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

Child & Parent logic/review/testing #13

Merged
merged 59 commits into from
Nov 12, 2020
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
94ecf9d
Variable and method renames plus some initial docs
jamesmorgan Nov 9, 2020
ba67019
Fixing test
jamesmorgan Nov 9, 2020
eaab05b
Adding test for garment factory
jamesmorgan Nov 9, 2020
e5f3b9f
Adding more docs
jamesmorgan Nov 9, 2020
c5ab15e
Adding comments and logic review
jamesmorgan Nov 9, 2020
119c8be
Adding more TODOs
jamesmorgan Nov 9, 2020
0beeecc
New scenarios
jamesmorgan Nov 9, 2020
d3c78c8
Scenario 1
jamesmorgan Nov 10, 2020
1c1fd9b
Adding scenario 2
jamesmorgan Nov 10, 2020
6edfd52
Adding tests for sending tokens from different 1155 contracts
jamesmorgan Nov 10, 2020
2884162
Adding more tests
jamesmorgan Nov 10, 2020
53654f9
More testing
jamesmorgan Nov 10, 2020
1c84a1f
Adding more comments
jamesmorgan Nov 10, 2020
ef75fc6
moved garment contracts and fixed tests
del-blockchain-solutions Nov 10, 2020
2f728b4
Adding more tests
jamesmorgan Nov 10, 2020
58162c7
Merge branch 'child-parent-review-and-docs' of github.com:DIGITALAX/d…
jamesmorgan Nov 10, 2020
b5a22b6
tests
jamesmorgan Nov 10, 2020
1a9daec
added burnable to 1155
del-blockchain-solutions Nov 10, 2020
607d1b0
Merge branch 'child-parent-review-and-docs' of https://github.com/DIG…
del-blockchain-solutions Nov 10, 2020
6444c80
Merge remote-tracking branch 'origin/main' into child-parent-review-a…
del-blockchain-solutions Nov 10, 2020
9ab82c1
merge in master
del-blockchain-solutions Nov 10, 2020
bb47c6d
start of mock vault
del-blockchain-solutions Nov 10, 2020
cceb57b
Adding maxChildrenPerToken logic
jamesmorgan Nov 10, 2020
6c7fbe6
Merge branch 'child-parent-review-and-docs' of github.com:DIGITALAX/d…
jamesmorgan Nov 10, 2020
5551969
operator must be from when wrapping garment
del-blockchain-solutions Nov 10, 2020
f890d5a
Merge branch 'child-parent-review-and-docs' of https://github.com/DIG…
del-blockchain-solutions Nov 10, 2020
cdee4cc
Merge branch 'main' of github.com:DIGITALAX/digitalax-contracts into …
jamesmorgan Nov 11, 2020
f172181
Adding comments
jamesmorgan Nov 11, 2020
5f47783
Fixing imports
jamesmorgan Nov 11, 2020
5b67640
Fixing bad import
jamesmorgan Nov 11, 2020
85e8061
Another fix, woops
jamesmorgan Nov 11, 2020
8dd71ff
mock vault test providing you can deposit and burn 1155s
del-blockchain-solutions Nov 11, 2020
cfedb36
bug fix for total supply not decreasing on burn
del-blockchain-solutions Nov 11, 2020
e3d0238
Adding batch transfer scenario
jamesmorgan Nov 11, 2020
ad7aee1
Merge branch 'child-parent-review-and-docs' of github.com:DIGITALAX/d…
jamesmorgan Nov 11, 2020
a2d78a0
Adding primary sale price event and logic and tests
jamesmorgan Nov 11, 2020
9f24807
address some skipped tests
del-blockchain-solutions Nov 11, 2020
3388901
Merge branch 'child-parent-review-and-docs' of https://github.com/DIG…
del-blockchain-solutions Nov 11, 2020
fc62b81
addressed some further skipped tests
del-blockchain-solutions Nov 11, 2020
74b8800
fix regression
del-blockchain-solutions Nov 11, 2020
de1d587
Refactoring burn method
jamesmorgan Nov 11, 2020
1d9dce2
Merge branch 'child-parent-review-and-docs' of github.com:DIGITALAX/d…
jamesmorgan Nov 11, 2020
e604a95
tweaks to materials
del-blockchain-solutions Nov 11, 2020
3255161
gas report as of 11/11/20
del-blockchain-solutions Nov 11, 2020
5fa812c
delete mapping when burning nft
del-blockchain-solutions Nov 11, 2020
37b2879
updated parent child docs - wip
del-blockchain-solutions Nov 11, 2020
e40e912
Adding flat files
jamesmorgan Nov 11, 2020
a41ab4e
Merge branch 'child-parent-review-and-docs' of github.com:DIGITALAX/d…
jamesmorgan Nov 11, 2020
57f652d
transferring and wrapping a child
del-blockchain-solutions Nov 11, 2020
2ea8b5e
Merge branch 'child-parent-review-and-docs' of https://github.com/DIG…
del-blockchain-solutions Nov 11, 2020
89cdaf4
Minor comments
jamesmorgan Nov 12, 2020
0117006
latest rinkeby subgraph deploy
del-blockchain-solutions Nov 12, 2020
636012b
Merge branch 'child-parent-review-and-docs' of https://github.com/DIG…
del-blockchain-solutions Nov 12, 2020
935fee7
handle children created
del-blockchain-solutions Nov 12, 2020
edbaca0
Fixing comment
jamesmorgan Nov 12, 2020
d55c64f
tweaks to test scripts
del-blockchain-solutions Nov 12, 2020
2d6aff5
Merge branch 'child-parent-review-and-docs' of https://github.com/DIG…
del-blockchain-solutions Nov 12, 2020
7169965
test bid script
del-blockchain-solutions Nov 12, 2020
d6399c5
can mint direct to garment from mock vault
del-blockchain-solutions Nov 12, 2020
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,5 @@ build
.coverage_cache
.coverage_contracts
solc-sjw-macos-x64
slither-output.log
.solcx-lock-0.6.12
130 changes: 130 additions & 0 deletions smart-contracts/PARENT_CHILDREN_NFTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
## Primary and Children NFT Top Down Relationship

```
Garment (ERC-721) a.k.a parent
|
Strand / Swatches (ERC-1155) a.k.a. children
```

## DigitalaxGarmentFactory (Orchestrator for making child and parent tokens)

* Responsible for facilitating the minting of both children and parent tokens and linking those together if needed.
* The caller must have the `minter` role to do this
* Creating garments and then wrapping would otherwise be a two stage process and this is done in 1 TX through the factory
* However, in order to create and wrap a garment, the strands / children have to exist in the 1155 contract. Therefore, if the children that you want to wrap within a garment do not exist, creating a garment is a 2 step process as defined below.
* If children exist for a garment, you can skip step 1 below.

#### Step 1 - setting up the children

* The methods below define new ERC1155 semi-fungible tokens - these tokens can then have a supply
* There is no check to ensure the same token URI is not used across unique ERC-1155 tokens. Therefore, you could in theory make 2 1155s using the same `_uri` parameter.

```solidity
function createNewChild(string calldata _uri) external returns (uint256 childTokenId)
function createNewChildren(string[] calldata _uris) external returns (uint256[] memory childTokenIds)
```

#### Step 2 - minting garments

* `mintParentWithChildren` will increase the supply of the given children token IDs through minting
jamesmorgan marked this conversation as resolved.
Show resolved Hide resolved
* It is the responsibility of the caller to provide the correct amounts and IDs which are aligned via array index
* If 1155 tokenIds are provided which do not yet exist, the method will revert
* The above does not apply if minting a garment with no children

```solidity
function mintParentWithChildren(string calldata garmentTokenUri, address designer, uint256[] calldata childTokenIds, uint256[] calldata childTokenAmounts, address beneficiary)
function mintParentWithoutChildren(string calldata garmentTokenUri, address designer, address beneficiary)
```

## DigitalaxMaterials (Child tokens - ERC-1155)

#### Creating new children

* Can only be called by an account which has the `SMART_CONTRACT` role
* The methods will create a new token ID for the given URI(s)
* Tokens can have duplicate URIs
* When creating new tokens - they have a total supply of zero

```solidity
function createChild(string calldata _uri) external returns (uint256 id)
function batchCreateChildren(string[] calldata _uris) external returns (uint256[] memory tokenIds)
```

#### Minting tokens from existing children

* Increases the supply of the provided child token(s) for the given amount(s)
* Can only be called by an account which has the `SMART_CONTRACT` role

```solidity
function mintChild(uint256 _childTokenId, uint256 _amount, address _beneficiary, bytes calldata _data)
function batchMintChildren(uint256[] calldata _childTokenIds, uint256[] calldata _amounts, address _beneficiary, bytes calldata _data)
```

#### Burning children

* An owner of 1155 children or an approved operator of someone else's children has the ability to burn those children as they wish
* This would reduce the supply of any children burnt

```solidity
function burn(address account, uint256 id, uint256 amount)
function burnBatch(address account, uint256[] memory ids, uint256[] memory amounts)
```

### Wrapping children in parent (Garment) nfts

* There are currently 2 ways of wrapping 1155 children in parent NFTs. Either through:
* Minting
* Transferring

Whichever method is used, there are business rules that govern when this is allowed. A wrapping of children 1155 tokens in a parent 721 garment is allowed when:
* A 1155 birthing event has occured i.e. new 1155 children have been minted either directly or through the garment factory
* The owner of both children and a garment is either:
* Topping up the balance of a child or,
* Adding a new child to the garment

One final stipulation is that when an owner of a garment wants to add a new child (not top up a child's balance), they can do so provided they have (and will not) not exceeded the maximum amount of children that a garment can wrap. This is controlled by the `maxChildrenPerToken` variable and is needed to prevent certain loops running out of GAS.

#### Wrapping through minting

* It is possible to use either mint methods above to atomically wrap children in Garment ERC721 parent NFTs (which is what the Garment NFT factory does)
* The `_beneficiary` would need to be the address of the ERC721 parent contract
* The `_data` parameter would have to be `abi.encodePacked(${PARENT_TOKEN_ID})`

#### Wrapping through transferring

* If atomically wrapping children in a single garment as part of a transfer, the parameter requirements are:
* `to` is the address of the garment parent NFT contract
* `data` would have to be `abi.encodePacked(${PARENT_TOKEN_ID})`

```
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
)

function safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
)
```

But remember the business rules stipulated above; Only the owner of both 1155 children and the target parent token ID can perform this operation if they do not exceed the max children rule.

## DigitalaxGarmentNFT (Parent tokens - ERC-721)

#### Burning garments

* In order for a garment owner to get access to the embedded 1155 child tokens, a user must burn it🔥
* Burning a token is a one way process with the output being 1155 child tokens if and only if the token owned any children
* Only the token owner or an approved operator of someone else's token can burn their own token

```solidity
function burn(uint256 _tokenId)
```
2 changes: 1 addition & 1 deletion smart-contracts/PRIMARY_AUCTION_FLOW.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
### Primary Auction flow

The contract `DigitialAuction` is responsible for handling the primary sale of parent NFTs. The auction itself only deals
The contract `DigitalaxAuction` is responsible for handling the primary sale of parent NFTs. The auction itself only deals
with ERC-721 tokens, also known as `Parent` tokens.

Parent tokens can however hold other ERC-1155 tokens, also known as `Child` tokens.
Expand Down
3 changes: 2 additions & 1 deletion smart-contracts/buidler.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ usePlugin('@nomiclabs/buidler-truffle5');
usePlugin('buidler-gas-reporter');
usePlugin('solidity-coverage');
usePlugin('@nomiclabs/buidler-solhint');
usePlugin('buidler-contract-sizer');

const INFURA_PROJECT_ID = process.env.INFURA_PROJECT_ID;
const PRIVATE_KEY = process.env.PRIVATE_KEY;
Expand All @@ -18,7 +19,7 @@ module.exports = {
},
gasReporter: {
currency: 'USD',
enabled: (process.env.REPORT_GAS) ? true : false,
enabled: false,
gasPrice: 50
},
networks: {
Expand Down
136 changes: 0 additions & 136 deletions smart-contracts/contracts/DigitalaxMaterials.sol

This file was deleted.

63 changes: 62 additions & 1 deletion smart-contracts/contracts/ERC1155/ERC1155.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
// Token ID to its URI
mapping (uint256 => string) internal tokenUris;

// Token ID to its total supply
mapping(uint256 => uint256) public tokenTotalSupply;

/*
* bytes4(keccak256('balanceOf(address,uint256)')) == 0x00fdd58e
* bytes4(keccak256('balanceOfBatch(address[],uint256[])')) == 0x4e1273f4
Expand Down Expand Up @@ -224,6 +227,7 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
_beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);

_balances[id][account] = _balances[id][account].add(amount);
tokenTotalSupply[id] = tokenTotalSupply[id].add(amount);
emit TransferSingle(operator, address(0), account, id, amount);

_doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);
Expand All @@ -247,14 +251,71 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
_beforeTokenTransfer(operator, address(0), to, ids, amounts, data);

for (uint i = 0; i < ids.length; i++) {
_balances[ids[i]][to] = amounts[i].add(_balances[ids[i]][to]);
uint256 id = ids[i];
uint256 amount = amounts[i];
_balances[id][to] = amount.add(_balances[id][to]);
tokenTotalSupply[id] = tokenTotalSupply[id].add(amount);
}

emit TransferBatch(operator, address(0), to, ids, amounts);

_doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
}

/**
* @dev Destroys `amount` tokens of token type `id` from `account`
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens of token type `id`.
*/
function _burn(address account, uint256 id, uint256 amount) internal virtual {
require(account != address(0), "ERC1155: burn from the zero address");

address operator = _msgSender();

_beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), "");

_balances[id][account] = _balances[id][account].sub(
amount,
"ERC1155: burn amount exceeds balance"
);

tokenTotalSupply[id] = tokenTotalSupply[id].sub(amount);

emit TransferSingle(operator, account, address(0), id, amount);
}

/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
*/
function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) internal virtual {
require(account != address(0), "ERC1155: burn from the zero address");
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");

address operator = _msgSender();

_beforeTokenTransfer(operator, account, address(0), ids, amounts, "");

for (uint i = 0; i < ids.length; i++) {
uint256 id = ids[i];
uint256 amount = amounts[i];
_balances[id][account] = _balances[id][account].sub(
amount,
"ERC1155: burn amount exceeds balance"
);

tokenTotalSupply[id] = tokenTotalSupply[id].sub(amount);
}

emit TransferBatch(operator, account, address(0), ids, amounts);
}

/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning, as well as batched variants.
Expand Down
Loading