Skip to content
This repository has been archived by the owner on Jul 9, 2021. It is now read-only.

ERC1155 Asset Proxy #1661

Merged
merged 29 commits into from
Mar 15, 2019
Merged

ERC1155 Asset Proxy #1661

merged 29 commits into from
Mar 15, 2019

Conversation

hysz
Copy link
Contributor

@hysz hysz commented Feb 28, 2019

Description

Asset Proxy for transferring ERC1155 assets. ERC1155 allows a set of fungible / non-fungible assets to exist under the same contract. The proxy uses ERC1155's safeBatchTransferFrom to transfer a set of ERC1155 assets between accounts. See #1657 for a minimal ERC1155 implementation.

Note - integration tests with the Exchange and MultiAsset Proxy in a separate PR.

Testing instructions

Types of changes

Checklist:

  • Prefix PR title with [WIP] if necessary.
  • Add tests to cover changes as needed.
  • Update documentation as needed.
  • Add new entries to the relevant CHANGELOG.jsons.

@coveralls
Copy link

coveralls commented Feb 28, 2019

Coverage Status

Coverage decreased (-0.02%) to 85.138% when pulling 22bc1fb on feature/contracts/erc1155Proxy-4 into d3f45d2 on development.

@hysz hysz force-pushed the feature/contracts/erc1155Proxy-4 branch from 24e2100 to 302ed95 Compare March 5, 2019 16:09
@hysz hysz requested a review from abandeali1 March 5, 2019 18:58
@hysz hysz force-pushed the feature/contracts/erc1155MinimalImplementation branch from 82cafd6 to 6fe5fed Compare March 5, 2019 19:37
@hysz hysz force-pushed the feature/contracts/erc1155Proxy-4 branch 2 times, most recently from 590dbf1 to c0eef21 Compare March 6, 2019 00:40
@hysz hysz force-pushed the feature/contracts/erc1155MinimalImplementation branch 2 times, most recently from 785f1c5 to 6fa806a Compare March 7, 2019 21:08
@hysz hysz force-pushed the feature/contracts/erc1155Proxy-4 branch from c0eef21 to 49ccb98 Compare March 7, 2019 22:40
@hysz hysz changed the title [WIP] ERC1155 Asset Proxy ERC1155 Asset Proxy Mar 11, 2019
@hysz hysz force-pushed the feature/contracts/erc1155Proxy-4 branch from 78ec115 to 12eeed4 Compare March 12, 2019 01:24
@hysz hysz force-pushed the feature/contracts/erc1155MinimalImplementation branch from 9b5199e to 9822792 Compare March 12, 2019 01:25
// 4 (function selector)
// + assetDataOffset
// + 32 (length of assetData)
calldatacopy(32, add(36, assetDataOffset), assetDataLength)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're probably right, but why not calldatacopy(68, add(36, assetDataOffset), sub(assetDataLength, 36))?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question - this line copies the entire assetData into memory at offset 32. Memory allocation looks like this:

32    :    assetProxyId 
36    :    address of ERC1155 contract
68    :    offset to tokenIds
...

This is later transformed into:

00    :    batchTransferFrom selector
04    :    from address
36    :    to address
68    :    offset to tokenIds
...

If we replaced this line with calldatacopy(68, add(36, assetDataOffset), sub(assetDataLength, 36)) then we would have the following allocation:

68    :    assetProxyId 
72    :    address of ERC1155 contract
104   :    offset to tokenIds
...

And it would truncate 36 bytes at the tail end of the asset data.

Note that assetData is a byte array so it is abi encoded as:

0   : length
32  : contents

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Super appreciate the walkthrough.

@hysz hysz changed the base branch from feature/contracts/erc1155MinimalImplementation to development March 12, 2019 20:08
@hysz hysz force-pushed the feature/contracts/erc1155Proxy-4 branch from 12eeed4 to 441b379 Compare March 12, 2019 21:38
// | Header | 0 | 4 | assetProxyId |
// | Params | | 4 * 32 | function parameters: |
// | | 4 | | 1. address of ERC1155 contract |
// | | 36 | | 2. offset to tokenIds (*) |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like these param names should be ids, values, and data to be consistent with the naming of the actual ERC1155 transfer params.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meh, actually we aren't really consistent in the other proxies either.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No I agree, we should be consistent with the naming of the ERC1155 transfer params.

// 4 (function selector)
// + assetDataOffset
// + 32 (length of assetData)
calldatacopy(32, add(36, assetDataOffset), assetDataLength)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this +1.

let scaledTokenValue := mul(tokenValue, scaleAmount)

// Check if scaled value is zero
if iszero(scaledTokenValue) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't actually check if the amount is 0 in any of the other proxies. What is the reason for doing so here, and can this ever be potentially limiting?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mm yeah, here's my reasoning - curious to get your thoughts - in the Exchange we check that the maker/taker amounts are non-zero. This amount is then directly used by the ERC20 and ERC721 proxies, so their check would be redundant. In the case of 1155, any one of the encoded values could also be zero, so I added this check for consistency.


// Check for multiplication overflow
let expectedTokenValue := div(scaledTokenValue, scaleAmount)
if iszero(eq(expectedTokenValue, tokenValue)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note that if we do remove the last check, we'll still need to check if scaleAmount is 0 before doing this division.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A check has been added above, right after we load amount.

"version": "2.2.3",
"changes": [
{
"note": "Added `ERC1155AssetData`, `ERC1155AssetDataNoProxyId`, and `ERC1155AssetDataAbi`",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change can be merged with the previous entry (not yet published).


*/

pragma solidity 0.4.24;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should test gas differences with a newer version of Solidity too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it's only ~100 gas cheaper if we use solidity 0.5.5.

Additionally, I believe all the proxies have to use the same version since they're in the same package, ya? If this is the case and the savings become more substantial it could be worthwhile to split proxies into standalone packages.

@@ -1,5 +1,8 @@
import {
AssetProxyId,
ERC1155AssetData,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll need to reexport these in the index.ts of this package and 0x.js (see doc-gen failing tests).

@hysz hysz force-pushed the feature/contracts/erc1155Proxy-4 branch from 56df883 to 334e935 Compare March 13, 2019 01:52
@hysz hysz force-pushed the feature/contracts/erc1155Proxy-4 branch 2 times, most recently from 9b2197f to 32b0b0b Compare March 14, 2019 21:21
hysz added 27 commits March 15, 2019 15:05
…to be consistent with the ERC1155 reference implementation.
@hysz hysz force-pushed the feature/contracts/erc1155Proxy-4 branch from a33da79 to 22bc1fb Compare March 15, 2019 22:06
@hysz hysz merged commit bab368b into development Mar 15, 2019
@hysz hysz deleted the feature/contracts/erc1155Proxy-4 branch March 16, 2019 04:35
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants