Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement token interactions #16

Merged
merged 23 commits into from
Dec 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ node_modules
.idea/

#Test Coverage
coverage*
coverage*

#Personal Preferences
.vscode
5 changes: 1 addition & 4 deletions contracts/BosonToken.sol
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity >=0.6.6 <0.7.0;
import "./ERC20WithPermit.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract BosonToken is ERC20WithPermit, AccessControl, Ownable {
// SPDX-License-Identifier: MIT

bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

event LogRecoveredAddress (address recovered);

//TODO Write tests for transferring ownership
constructor(string memory name, string memory symbol)
ERC20WithPermit(name, symbol)
public
Expand Down
437 changes: 319 additions & 118 deletions contracts/Cashier.sol

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions contracts/ERC1155ERC721.sol
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ contract ERC1155ERC721 is IERC1155, IERC721 {
require(_to != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange)
require(_from == msg.sender || operatorApprovals[_from][msg.sender] == true, "UNAUTHORIZED_ST"); //hex"10"FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop)

// SafeMath throws with insuficient funds or if _id is not valid (balance will be 0)
// SafeMath throws with insufficient funds or if _id is not valid (balance will be 0)
balances[_tokenId][_from] = balances[_tokenId][_from].sub(_value);
balances[_tokenId][_to] = _value.add(balances[_tokenId][_to]);

Expand Down Expand Up @@ -249,14 +249,14 @@ contract ERC1155ERC721 is IERC1155, IERC721 {
override
{
require(_to != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange)
require(_tokenIds.length == _values.length, "MISMATCHED_ARRAY_LENGTS"); //hex"28" ISSION.code(FISSION.Category.Find, FISSION.Status.Duplicate_Conflict_Collision)
require(_tokenIds.length == _values.length, "MISMATCHED_ARRAY_LENGTHS"); //hex"28" FISSION.code(FISSION.Category.Find, FISSION.Status.Duplicate_Conflict_Collision)
require(_from == msg.sender || operatorApprovals[_from][msg.sender] == true, "UNAUTHORIZED_SB"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop)

for (uint256 i = 0; i < _tokenIds.length; ++i) {
uint256 tokenId = _tokenIds[i];
uint256 value = _values[i];

// SafeMath throws with insuficient funds or if _id is not valid (balance will be 0)
// SafeMath throws with insufficient funds or if _id is not valid (balance will be 0)
balances[tokenId][_from] = balances[tokenId][_from].sub(value);
balances[tokenId][_to] = value.add(balances[tokenId][_to]);
}
Expand Down Expand Up @@ -391,7 +391,7 @@ contract ERC1155ERC721 is IERC1155, IERC721 {
override
returns (uint256[] memory)
{
require(_accounts.length == _tokenIds.length, "MISMATCHED_ARRAY_LENGTS"); //hex"28" FISSION.code(FISSION.Category.Find, FISSION.Status.Duplicate_Conflict_Collision)
require(_accounts.length == _tokenIds.length, "MISMATCHED_ARRAY_LENGTHS"); //hex"28" FISSION.code(FISSION.Category.Find, FISSION.Status.Duplicate_Conflict_Collision)
uint256[] memory batchBalances = new uint256[](_accounts.length);

for (uint256 i = 0; i < _accounts.length; ++i) {
Expand Down Expand Up @@ -459,7 +459,7 @@ contract ERC1155ERC721 is IERC1155, IERC721 {
// // // // // // // //
/**
* @notice Mint an amount of a desired token
* Currently no restrictions as to who is allowd to mint - so, it is public.
* Currently no restrictions as to who is allowed to mint - so, it is public.
* @dev ERC-1155
* @param _to owner of the minted token
* @param _tokenId ID of the token to be minted
Expand Down Expand Up @@ -532,7 +532,7 @@ contract ERC1155ERC721 is IERC1155, IERC721 {

/**
* @notice Batch minting of tokens
* Currently no restrictions as to who is allowd to mint - so, it is public.
* Currently no restrictions as to who is allowed to mint - so, it is public.
* @dev ERC-1155
* @param _to The address that will own the minted token
* @param _tokenIds IDs of the tokens to be minted
Expand Down Expand Up @@ -560,7 +560,7 @@ contract ERC1155ERC721 is IERC1155, IERC721 {
internal
{
require(_to != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange)
require(_tokenIds.length == _values.length, "MISMATCHED_ARRAY_LENGTS"); //hex"28" FISSION.code(FISSION.Category.Find, FISSION.Status.Duplicate_Conflict_Collision)
require(_tokenIds.length == _values.length, "MISMATCHED_ARRAY_LENGTHS"); //hex"28" FISSION.code(FISSION.Category.Find, FISSION.Status.Duplicate_Conflict_Collision)

for(uint i = 0; i < _tokenIds.length; i++) {
balances[_tokenIds[i]][_to] = _values[i].add(balances[_tokenIds[i]][_to]);
Expand Down Expand Up @@ -629,7 +629,7 @@ contract ERC1155ERC721 is IERC1155, IERC721 {
internal
{
require(_account != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange)
require(_tokenIds.length == _values.length, "MISMATCHED_ARRAY_LENGTS"); //hex"28" FISSION.code(FISSION.Category.Find, FISSION.Status.Duplicate_Conflict_Collision)
require(_tokenIds.length == _values.length, "MISMATCHED_ARRAY_LENGTHS"); //hex"28" FISSION.code(FISSION.Category.Find, FISSION.Status.Duplicate_Conflict_Collision)

for(uint i = 0; i < _tokenIds.length; i++) {
balances[_tokenIds[i]][_account] = balances[_tokenIds[i]][_account].sub(_values[i]);
Expand Down
9 changes: 3 additions & 6 deletions contracts/ERC20WithPermit.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity >=0.6.6;

import "./IERC20WithPermit.sol";
Expand All @@ -15,11 +15,8 @@ contract ERC20WithPermit is IERC20WithPermit {
mapping(address => uint256) public override balanceOf;
mapping(address => mapping(address => uint256)) public override allowance;

// TODO - This TODO stems from the ERC20WithPermit Standard
bytes32 public override DOMAIN_SEPARATOR;
// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); // The commented line stems from the ERC20WithPermit Standard
bytes32
public override constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
bytes32 public override DOMAIN_SEPARATOR; //prevents collision of identical structures. Formed in the initialization of the contract
bytes32 public override constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; //representation of keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
mapping(address => uint256) public override nonces;

event Approval(
Expand Down
3 changes: 1 addition & 2 deletions contracts/IERC20WithPermit.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity >=0.6.0 <0.7.0;

interface IERC20WithPermit {
Expand Down Expand Up @@ -34,7 +34,6 @@ interface IERC20WithPermit {
uint256 value
) external returns (bool);

// TODO
function DOMAIN_SEPARATOR() external view returns (bytes32);

function PERMIT_TYPEHASH() external pure returns (bytes32);
Expand Down
125 changes: 102 additions & 23 deletions contracts/VoucherKernel.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ contract VoucherKernel is Ownable, usingHelpers {
//promise for an asset could be reusable, but simplified here for brevitbytes32
struct Promise {
bytes32 promiseId;
string assetTitle; //the asset that is offered
uint256 nonce; //the asset that is offered
thecryptofruit marked this conversation as resolved.
Show resolved Hide resolved
address seller; //the seller who created the promise

//we simplify the value for the demoapp, otherwise voucher details would be packed in one bytes32 field value
Expand All @@ -40,10 +40,19 @@ contract VoucherKernel is Ownable, usingHelpers {

uint idx;
}

struct VoucherPaymentMethod {
uint8 paymentMethod;
address addressTokenPrice;
address addressTokenDeposits;
}

address public cashierAddress; //address of the Cashier contract

mapping(bytes32 => Promise) public promises; //promises to deliver goods or services
mapping(address => uint256) public tokenNonces; //mapping between seller address and its own nonces. Every time seller creates supply ID it gets incremented. Used to avoid duplicate ID's
mapping (uint256 => VoucherPaymentMethod) public paymentDetails; // tokenSupplyId to VoucherPaymentMethod

bytes32[] public promiseKeys;

mapping(address => uint256) public accountSupply;
Expand Down Expand Up @@ -85,12 +94,20 @@ contract VoucherKernel is Ownable, usingHelpers {

event LogPromiseCreated(
bytes32 indexed _promiseId,
string indexed _assetTitle,
uint256 indexed _nonce,
address indexed _seller,
uint256 _validFrom,
uint256 _validTo,
uint256 _idx
);

event LogVoucherDelivered(
uint256 indexed _tokenIdSupply,
uint256 _tokenIdVoucher,
address _issuer,
address _holder,
bytes32 _promiseId
);

event LogVoucherRedeemed(
uint256 _tokenIdVoucher,
Expand Down Expand Up @@ -169,40 +186,39 @@ contract VoucherKernel is Ownable, usingHelpers {
* @notice Creating a new promise for goods or services.
* Can be reused, e.g. for making different batches of these (but not in prototype).
* @param _seller seller of the promise
* @param _assetTitle Name of the asset
* @param _validFrom Start of valid period
* @param _validTo End of valid period
* @param _price Price (payment amount)
* @param _depositSe Seller's deposit
* @param _depositBu Buyer's deposit
*/
function createAssetPromise(
function createTokenSupplyID(
address _seller,
string calldata _assetTitle,
uint256 _validFrom,
uint256 _validTo,
uint256 _price,
uint256 _depositSe,
uint256 _depositBu
uint256 _depositBu,
uint256 _quantity
)
external
onlyFromCashier
returns (bytes32)
returns (uint256)
{

require(_validFrom <= _validTo, "INVALID_VALIDITY_FROM"); //hex"26" FISSION.code(FISSION.Category.Find, FISSION.Status.Above_Range_Overflow)
require(_validTo >= block.timestamp, "INVALID_VALIDITY_TO"); //hex"24" FISSION.code(FISSION.Category.Find, FISSION.Status.BelowRange_Underflow)

bytes32 key;
key = keccak256(abi.encodePacked(_assetTitle, _validFrom, _validTo));
key = keccak256(abi.encodePacked(tokenNonces[_seller]++, _validFrom, _validTo));

if (promiseKeys.length > 0) {
require(promiseKeys[promises[key].idx] != key, "PROMISE_ALREADY_EXISTS");
}

promises[key] = Promise({
promiseId: key,
assetTitle: _assetTitle,
nonce: tokenNonces[_seller],
seller: _seller,
validFrom: _validFrom,
validTo: _validTo,
Expand All @@ -214,13 +230,30 @@ contract VoucherKernel is Ownable, usingHelpers {

promiseKeys.push(key);

emit LogPromiseCreated(key, _assetTitle, msg.sender, _validFrom, _validTo, //_price, _depositSe, _depositBu, _complainPeriod, _cancelFaultPeriod,
emit LogPromiseCreated(key, tokenNonces[_seller], _seller, _validFrom, _validTo, //_price, _depositSe, _depositBu, _complainPeriod, _cancelFaultPeriod,
promiseKeys.length - 1);

return key;
}



return createOrder(_seller, key, _quantity);
}

function createPaymentMethod(
uint256 _tokenIdSupply,
uint8 _paymentMethod,
address _tokenPrice,
address _tokenDeposits
)
external
onlyFromCashier
{

paymentDetails[_tokenIdSupply] = VoucherPaymentMethod({
paymentMethod: _paymentMethod,
addressTokenPrice: _tokenPrice,
addressTokenDeposits: _tokenDeposits

});
}

/**
* @notice Create an order for offering a certain quantity of an asset
* This creates a listing in a marketplace, technically as an ERC-1155 non-fungible token with supply.
Expand All @@ -229,8 +262,7 @@ contract VoucherKernel is Ownable, usingHelpers {
* @param _quantity Quantity of assets on offer
*/
function createOrder(address _seller, bytes32 _promiseId, uint256 _quantity)
external
onlyFromCashier
private
returns (uint256)
{
require(_promiseId != bytes32(0), "UNSPECIFIED_PROMISE"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange)
Expand All @@ -256,13 +288,15 @@ contract VoucherKernel is Ownable, usingHelpers {
function fillOrder(uint256 _tokenIdSupply, address _issuer, address _holder)
external
onlyFromCashier
returns (uint256)

{
//checks
checkOrderFillable(_tokenIdSupply, _issuer, _holder);

//close order
return extract721(_issuer, _holder, _tokenIdSupply);
uint256 voucherTokenId = extract721(_issuer, _holder, _tokenIdSupply);

emit LogVoucherDelivered(_tokenIdSupply, voucherTokenId, _issuer, _holder, getPromiseIdFromVoucherId(voucherTokenId));
}


Expand Down Expand Up @@ -413,7 +447,7 @@ contract VoucherKernel is Ownable, usingHelpers {
//check if still in the complain period
Promise memory tPromise = promises[getPromiseIdFromVoucherId(_tokenIdVoucher)];

//if redeeemed or refunded
//if redeemed or refunded
if (isStateRedemptionSigned(vouchersStatus[_tokenIdVoucher].status) ||
isStateRefunded(vouchersStatus[_tokenIdVoucher].status)) {
if (!isStatus(vouchersStatus[_tokenIdVoucher].status, idxCancelFault)) {
Expand Down Expand Up @@ -472,7 +506,7 @@ contract VoucherKernel is Ownable, usingHelpers {
Promise memory tPromise = promises[getPromiseIdFromVoucherId(_tokenIdVoucher)];

if (isStatus(tStatus, idxRedeem) || isStatus(tStatus, idxRefund)) {
//if redeeemed or refunded
//if redeemed or refunded
if (!isStatus(tStatus, idxComplain)) {
require(block.timestamp <= vouchersStatus[_tokenIdVoucher].complainPeriodStart + complainPeriod + cancelFaultPeriod, "COFPERIOD_EXPIRED"); //hex"46" FISSION.code(FISSION.Category.Availability, FISSION.Status.Expired)
vouchersStatus[_tokenIdVoucher].complainPeriodStart = block.timestamp; //resetting the complain period
Expand Down Expand Up @@ -741,7 +775,7 @@ contract VoucherKernel is Ownable, usingHelpers {
/**
* @notice Get all necessary funds for a supply token
* @param _tokenIdSupply ID of the supply token
* @return returns a tupple (Payment amount, Seller's deposit, Buyer's deposit)
* @return returns a tuple (Payment amount, Seller's deposit, Buyer's deposit)
*/
function getOrderCosts(uint256 _tokenIdSupply)
public view
Expand All @@ -750,6 +784,20 @@ contract VoucherKernel is Ownable, usingHelpers {
bytes32 promiseKey = ordersPromise[_tokenIdSupply];
return (promises[promiseKey].price, promises[promiseKey].depositSe, promises[promiseKey].depositBu);
}


/**
* @notice Get Buyer costs required to make an order for a supply token
* @param _tokenIdSupply ID of the supply token
* @return returns a tuple (Payment amount, Buyer's deposit)
*/
function getBuyerOrderCosts(uint256 _tokenIdSupply)
public view
returns (uint256, uint256)
{
bytes32 promiseKey = ordersPromise[_tokenIdSupply];
return (promises[promiseKey].price, promises[promiseKey].depositBu);
}


/**
Expand Down Expand Up @@ -789,7 +837,38 @@ contract VoucherKernel is Ownable, usingHelpers {
{
return tokensContract.ownerOf(_tokenIdVoucher);
}



/**
* @notice Get the address of the token where the price for the supply is held
* @param _tokenIdSupply ID of the voucher token
* @return Address of the token
*/
function getVoucherPriceToken(uint256 _tokenIdSupply)
public view
returns (address)
{
return paymentDetails[_tokenIdSupply].addressTokenPrice;
}

/**
* @notice Get the address of the token where the deposits for the supply are held
* @param _tokenIdSupply ID of the voucher token
* @return Address of the token
*/
function getVoucherDepositToken(uint256 _tokenIdSupply)
public view
returns (address)
{
return paymentDetails[_tokenIdSupply].addressTokenDeposits;
}

function getVoucherPaymentMethod(uint256 _tokenIdSupply)
public view
returns (uint8)
{
return paymentDetails[_tokenIdSupply].paymentMethod;
}

/**
*
Expand Down
Loading