Basic ERC1155 Implementation. Derived from reference implementation, with bug fixes.
This commit is contained in:
parent
22af796302
commit
7c850cc082
2
.gitignore
vendored
2
.gitignore
vendored
@ -91,6 +91,7 @@ contracts/utils/generated-artifacts/
|
|||||||
contracts/exchange-libs/generated-artifacts/
|
contracts/exchange-libs/generated-artifacts/
|
||||||
contracts/erc20/generated-artifacts/
|
contracts/erc20/generated-artifacts/
|
||||||
contracts/erc721/generated-artifacts/
|
contracts/erc721/generated-artifacts/
|
||||||
|
contracts/erc1155/generated-artifacts/
|
||||||
contracts/extensions/generated-artifacts/
|
contracts/extensions/generated-artifacts/
|
||||||
contracts/exchange-forwarder/generated-artifacts/
|
contracts/exchange-forwarder/generated-artifacts/
|
||||||
packages/sol-tracing-utils/test/fixtures/artifacts/
|
packages/sol-tracing-utils/test/fixtures/artifacts/
|
||||||
@ -106,6 +107,7 @@ contracts/utils/generated-wrappers/
|
|||||||
contracts/exchange-libs/generated-wrappers/
|
contracts/exchange-libs/generated-wrappers/
|
||||||
contracts/erc20/generated-wrappers/
|
contracts/erc20/generated-wrappers/
|
||||||
contracts/erc721/generated-wrappers/
|
contracts/erc721/generated-wrappers/
|
||||||
|
contracts/erc1155/generated-wrappers/
|
||||||
contracts/extensions/generated-wrappers/
|
contracts/extensions/generated-wrappers/
|
||||||
contracts/exchange-forwarder/generated-wrappers/
|
contracts/exchange-forwarder/generated-wrappers/
|
||||||
packages/metacoin/src/contract_wrappers
|
packages/metacoin/src/contract_wrappers
|
||||||
|
3
contracts/erc1155/.solhintignore
Normal file
3
contracts/erc1155/.solhintignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
contracts/tokens/ZRXToken/ERC20Token_v1.sol
|
||||||
|
contracts/tokens/ZRXToken/Token_v1.sol
|
||||||
|
contracts/tokens/ZRXToken/UnlimitedAllowanceToken_v1.sol
|
11
contracts/erc1155/CHANGELOG.json
Normal file
11
contracts/erc1155/CHANGELOG.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"version": "1.0.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Created ERC1155 contracts package",
|
||||||
|
"pr": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
6
contracts/erc1155/CHANGELOG.md
Normal file
6
contracts/erc1155/CHANGELOG.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<!--
|
||||||
|
changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
|
||||||
|
Edit the package's CHANGELOG.json file only.
|
||||||
|
-->
|
||||||
|
|
||||||
|
CHANGELOG
|
1
contracts/erc1155/DEPLOYS.json
Normal file
1
contracts/erc1155/DEPLOYS.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
[]
|
73
contracts/erc1155/README.md
Normal file
73
contracts/erc1155/README.md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
## ERC1155 Tokens
|
||||||
|
|
||||||
|
This package contains implementations of various [ERC1155](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md) tokens. Addresses of the deployed contracts can be found in the 0x [wiki](https://0xproject.com/wiki#Deployed-Addresses) or the [DEPLOYS](./DEPLOYS.json) file within this package.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
**Install**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @0x/contracts-erc1155 --save
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bug bounty
|
||||||
|
|
||||||
|
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0xproject.com/wiki#Bug-Bounty).
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||||
|
|
||||||
|
For proposals regarding the 0x protocol's smart contract architecture, message format, or additional functionality, go to the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository and follow the contribution guidelines provided therein.
|
||||||
|
|
||||||
|
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||||
|
|
||||||
|
### Install Dependencies
|
||||||
|
|
||||||
|
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn config set workspaces-experimental true
|
||||||
|
```
|
||||||
|
|
||||||
|
Then install dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PKG=@0x/contracts-erc1155 yarn build
|
||||||
|
```
|
||||||
|
|
||||||
|
Or continuously rebuild on change:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PKG=@0x/contracts-erc1155 yarn watch
|
||||||
|
```
|
||||||
|
|
||||||
|
### Clean
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn clean
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lint
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn lint
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn test
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Testing options
|
||||||
|
|
||||||
|
Contracts testing options like coverage, profiling, revert traces or backing node choosing - are described [here](../TESTING.md).
|
28
contracts/erc1155/compiler.json
Normal file
28
contracts/erc1155/compiler.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"artifactsDir": "generated-artifacts",
|
||||||
|
"contractsDir": "contracts",
|
||||||
|
"useDockerisedSolc": true,
|
||||||
|
"compilerSettings": {
|
||||||
|
"optimizer": { "enabled": true, "runs": 1000000 },
|
||||||
|
"outputSelection": {
|
||||||
|
"*": {
|
||||||
|
"*": [
|
||||||
|
"abi",
|
||||||
|
"evm.bytecode.object",
|
||||||
|
"evm.bytecode.sourceMap",
|
||||||
|
"evm.deployedBytecode.object",
|
||||||
|
"evm.deployedBytecode.sourceMap"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contracts": [
|
||||||
|
"src/ERC1155.sol",
|
||||||
|
"src/ERC1155Mintable.sol",
|
||||||
|
"src/interfaces/IERC1155.sol",
|
||||||
|
"src/interfaces/IERC1155Receiver.sol",
|
||||||
|
"test/DummyERC1155Receiver.sol",
|
||||||
|
"test/DummyERC1155Token.sol",
|
||||||
|
"test/InvalidERC1155Receiver.sol"
|
||||||
|
]
|
||||||
|
}
|
161
contracts/erc1155/contracts/src/ERC1155.sol
Normal file
161
contracts/erc1155/contracts/src/ERC1155.sol
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
pragma solidity ^0.5.3;
|
||||||
|
|
||||||
|
import "./lib/SafeMath.sol";
|
||||||
|
import "./lib/Address.sol";
|
||||||
|
import "./interfaces/IERC1155.sol";
|
||||||
|
import "./interfaces/IERC1155Receiver.sol";
|
||||||
|
|
||||||
|
|
||||||
|
// A sample implementation of core ERC1155 function.
|
||||||
|
contract ERC1155 is
|
||||||
|
IERC1155,
|
||||||
|
SafeMath
|
||||||
|
{
|
||||||
|
using Address for address;
|
||||||
|
|
||||||
|
bytes4 constant public ERC1155_RECEIVED = 0xf23a6e61;
|
||||||
|
bytes4 constant public ERC1155_BATCH_RECEIVED = 0xbc197c81;
|
||||||
|
|
||||||
|
// id => (owner => balance)
|
||||||
|
mapping (uint256 => mapping(address => uint256)) internal balances;
|
||||||
|
|
||||||
|
// owner => (operator => approved)
|
||||||
|
mapping (address => mapping(address => bool)) internal operatorApproval;
|
||||||
|
|
||||||
|
// Use a split bit implementation.
|
||||||
|
// Store the type in the upper 128 bits..
|
||||||
|
uint256 constant TYPE_MASK = uint256(uint128(~0)) << 128;
|
||||||
|
|
||||||
|
// ..and the non-fungible index in the lower 128
|
||||||
|
uint256 constant NF_INDEX_MASK = uint128(~0);
|
||||||
|
|
||||||
|
// The top bit is a flag to tell if this is a NFI.
|
||||||
|
uint256 constant TYPE_NF_BIT = 1 << 255;
|
||||||
|
|
||||||
|
mapping (uint256 => address) nfOwners;
|
||||||
|
|
||||||
|
// Only to make code clearer. Should not be functions
|
||||||
|
function isNonFungible(uint256 _id) public pure returns(bool) {
|
||||||
|
return _id & TYPE_NF_BIT == TYPE_NF_BIT;
|
||||||
|
}
|
||||||
|
function isFungible(uint256 _id) public pure returns(bool) {
|
||||||
|
return _id & TYPE_NF_BIT == 0;
|
||||||
|
}
|
||||||
|
function getNonFungibleIndex(uint256 _id) public pure returns(uint256) {
|
||||||
|
return _id & NF_INDEX_MASK;
|
||||||
|
}
|
||||||
|
function getNonFungibleBaseType(uint256 _id) public pure returns(uint256) {
|
||||||
|
return _id & TYPE_MASK;
|
||||||
|
}
|
||||||
|
function isNonFungibleBaseType(uint256 _id) public pure returns(bool) {
|
||||||
|
// A base type has the NF bit but does not have an index.
|
||||||
|
return (_id & TYPE_NF_BIT == TYPE_NF_BIT) && (_id & NF_INDEX_MASK == 0);
|
||||||
|
}
|
||||||
|
function isNonFungibleItem(uint256 _id) public pure returns(bool) {
|
||||||
|
// A base type has the NF bit but does has an index.
|
||||||
|
return (_id & TYPE_NF_BIT == TYPE_NF_BIT) && (_id & NF_INDEX_MASK != 0);
|
||||||
|
}
|
||||||
|
function ownerOf(uint256 _id) public view returns (address) {
|
||||||
|
return nfOwners[_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
// overide
|
||||||
|
function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external {
|
||||||
|
|
||||||
|
require(_to != address(0x0), "cannot send to zero address");
|
||||||
|
require(_from == msg.sender || operatorApproval[_from][msg.sender] == true, "Need operator approval for 3rd party transfers.");
|
||||||
|
|
||||||
|
if (isNonFungible(_id)) {
|
||||||
|
require(nfOwners[_id] == _from);
|
||||||
|
nfOwners[_id] = _to;
|
||||||
|
// You could keep balance of NF type in base type id like so:
|
||||||
|
// uint256 baseType = getNonFungibleBaseType(_id);
|
||||||
|
// balances[baseType][_from] = balances[baseType][_from].safeSub(_value);
|
||||||
|
// balances[baseType][_to] = balances[baseType][_to].safeAdd(_value);
|
||||||
|
} else {
|
||||||
|
balances[_id][_from] = safeSub(balances[_id][_from], _value);
|
||||||
|
balances[_id][_to] = safeAdd(balances[_id][_to], _value);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit TransferSingle(msg.sender, _from, _to, _id, _value);
|
||||||
|
|
||||||
|
if (_to.isContract()) {
|
||||||
|
require(IERC1155Receiver(_to).onERC1155Received(msg.sender, _from, _id, _value, _data) == ERC1155_RECEIVED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// overide
|
||||||
|
function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external {
|
||||||
|
|
||||||
|
require(_to != address(0x0), "cannot send to zero address");
|
||||||
|
require(_ids.length == _values.length, "Array length must match");
|
||||||
|
|
||||||
|
// Only supporting a global operator approval allows us to do only 1 check and not to touch storage to handle allowances.
|
||||||
|
require(_from == msg.sender || operatorApproval[_from][msg.sender] == true, "Need operator approval for 3rd party transfers.");
|
||||||
|
|
||||||
|
for (uint256 i = 0; i < _ids.length; ++i) {
|
||||||
|
// Cache value to local variable to reduce read costs.
|
||||||
|
uint256 id = _ids[i];
|
||||||
|
uint256 value = _values[i];
|
||||||
|
|
||||||
|
if (isNonFungible(id)) {
|
||||||
|
require(nfOwners[id] == _from);
|
||||||
|
nfOwners[id] = _to;
|
||||||
|
} else {
|
||||||
|
balances[id][_from] = safeSub(balances[id][_from], value);
|
||||||
|
balances[id][_to] = safeAdd(value, balances[id][_to]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit TransferBatch(msg.sender, _from, _to, _ids, _values);
|
||||||
|
|
||||||
|
if (_to.isContract()) {
|
||||||
|
require(IERC1155Receiver(_to).onERC1155BatchReceived(msg.sender, _from, _ids, _values, _data) == ERC1155_BATCH_RECEIVED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function balanceOf(address _owner, uint256 _id) external view returns (uint256) {
|
||||||
|
if (isNonFungibleItem(_id))
|
||||||
|
return nfOwners[_id] == _owner ? 1 : 0;
|
||||||
|
return balances[_id][_owner];
|
||||||
|
}
|
||||||
|
|
||||||
|
function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory) {
|
||||||
|
|
||||||
|
require(_owners.length == _ids.length);
|
||||||
|
|
||||||
|
uint256[] memory balances_ = new uint256[](_owners.length);
|
||||||
|
|
||||||
|
for (uint256 i = 0; i < _owners.length; ++i) {
|
||||||
|
uint256 id = _ids[i];
|
||||||
|
if (isNonFungibleItem(id)) {
|
||||||
|
balances_[i] = nfOwners[id] == _owners[i] ? 1 : 0;
|
||||||
|
} else {
|
||||||
|
balances_[i] = balances[id][_owners[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return balances_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@notice Enable or disable approval for a third party ("operator") to manage all of the caller's tokens.
|
||||||
|
@dev MUST emit the ApprovalForAll event on success.
|
||||||
|
@param _operator address to safeAdd to the set of authorized operators
|
||||||
|
@param _approved True if the operator is approved, false to revoke approval
|
||||||
|
*/
|
||||||
|
function setApprovalForAll(address _operator, bool _approved) external {
|
||||||
|
operatorApproval[msg.sender][_operator] = _approved;
|
||||||
|
emit ApprovalForAll(msg.sender, _operator, _approved);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@notice Queries the approval status of an operator for a given owner.
|
||||||
|
@param _owner The owner of the Tokens
|
||||||
|
@param _operator address of authorized operator
|
||||||
|
@return True if the operator is approved, false if not
|
||||||
|
*/
|
||||||
|
function isApprovedForAll(address _owner, address _operator) external view returns (bool) {
|
||||||
|
return operatorApproval[_owner][_operator];
|
||||||
|
}
|
||||||
|
}
|
98
contracts/erc1155/contracts/src/ERC1155Mintable.sol
Normal file
98
contracts/erc1155/contracts/src/ERC1155Mintable.sol
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
pragma solidity ^0.5.3;
|
||||||
|
|
||||||
|
import "./lib/SafeMath.sol";
|
||||||
|
import "./ERC1155.sol";
|
||||||
|
|
||||||
|
/**
|
||||||
|
@dev Mintable form of ERC1155
|
||||||
|
Shows how easy it is to mint new items
|
||||||
|
*/
|
||||||
|
contract ERC1155Mintable is
|
||||||
|
ERC1155
|
||||||
|
{
|
||||||
|
|
||||||
|
uint256 nonce;
|
||||||
|
mapping (uint256 => address) public creators;
|
||||||
|
mapping (uint256 => uint256) public maxIndex;
|
||||||
|
|
||||||
|
modifier creatorOnly(uint256 _id) {
|
||||||
|
require(creators[_id] == msg.sender);
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function only creates the type.
|
||||||
|
function create(
|
||||||
|
string calldata _uri,
|
||||||
|
bool _isNF
|
||||||
|
)
|
||||||
|
external
|
||||||
|
returns (uint256 _type)
|
||||||
|
{
|
||||||
|
// Store the type in the upper 128 bits
|
||||||
|
_type = (++nonce << 128);
|
||||||
|
|
||||||
|
// Set a flag if this is an NFI.
|
||||||
|
if (_isNF)
|
||||||
|
_type = _type | TYPE_NF_BIT;
|
||||||
|
|
||||||
|
// This will allow restricted access to creators.
|
||||||
|
creators[_type] = msg.sender;
|
||||||
|
|
||||||
|
// emit a Transfer event with Create semantic to help with discovery.
|
||||||
|
emit TransferSingle(msg.sender, address(0x0), address(0x0), _type, 0);
|
||||||
|
|
||||||
|
if (bytes(_uri).length > 0)
|
||||||
|
emit URI(_uri, _type);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mintNonFungible(uint256 _type, address[] calldata _to) external creatorOnly(_type) {
|
||||||
|
|
||||||
|
// No need to check this is a nf type rather than an id since
|
||||||
|
// creatorOnly() will only let a type pass through.
|
||||||
|
require(isNonFungible(_type));
|
||||||
|
|
||||||
|
// Index are 1-based.
|
||||||
|
uint256 index = maxIndex[_type] + 1;
|
||||||
|
|
||||||
|
for (uint256 i = 0; i < _to.length; ++i) {
|
||||||
|
address dst = _to[i];
|
||||||
|
uint256 id = _type | index + i;
|
||||||
|
|
||||||
|
nfOwners[id] = dst;
|
||||||
|
|
||||||
|
// You could use base-type id to store NF type balances if you wish.
|
||||||
|
// balances[_type][dst] = quantity.safeAdd(balances[_type][dst]);
|
||||||
|
|
||||||
|
emit TransferSingle(msg.sender, address(0x0), dst, id, 1);
|
||||||
|
|
||||||
|
if (dst.isContract()) {
|
||||||
|
require(IERC1155Receiver(dst).onERC1155Received(msg.sender, msg.sender, id, 1, '') == ERC1155_RECEIVED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
maxIndex[_type] = safeAdd(_to.length, maxIndex[_type]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mintFungible(uint256 _id, address[] calldata _to, uint256[] calldata _quantities) external creatorOnly(_id) {
|
||||||
|
|
||||||
|
require(isFungible(_id));
|
||||||
|
|
||||||
|
for (uint256 i = 0; i < _to.length; ++i) {
|
||||||
|
|
||||||
|
address to = _to[i];
|
||||||
|
uint256 quantity = _quantities[i];
|
||||||
|
|
||||||
|
// Grant the items to the caller
|
||||||
|
balances[_id][to] = safeAdd(quantity, balances[_id][to]);
|
||||||
|
|
||||||
|
// Emit the Transfer/Mint event.
|
||||||
|
// the 0x0 source address implies a mint
|
||||||
|
// It will also provide the circulating supply info.
|
||||||
|
emit TransferSingle(msg.sender, address(0x0), to, _id, quantity);
|
||||||
|
|
||||||
|
if (to.isContract()) {
|
||||||
|
require(IERC1155Receiver(to).onERC1155Received(msg.sender, msg.sender, _id, quantity, '') == ERC1155_RECEIVED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
124
contracts/erc1155/contracts/src/interfaces/IERC1155.sol
Normal file
124
contracts/erc1155/contracts/src/interfaces/IERC1155.sol
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2018 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.3;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@title ERC-1155 Multi Token Standard
|
||||||
|
@dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md
|
||||||
|
Note: The ERC-165 identifier for this interface is 0xd9b67a26.
|
||||||
|
*/
|
||||||
|
interface IERC1155 {
|
||||||
|
/**
|
||||||
|
@dev Either TransferSingle or TransferBatch MUST emit when tokens are transferred, including zero value transfers as well as minting or burning.
|
||||||
|
Operator will always be msg.sender.
|
||||||
|
Either event from address `0x0` signifies a minting operation.
|
||||||
|
An event to address `0x0` signifies a burning or melting operation.
|
||||||
|
The total value transferred from address 0x0 minus the total value transferred to 0x0 may be used by clients and exchanges to be added to the "circulating supply" for a given token ID.
|
||||||
|
To define a token ID with no initial balance, the contract SHOULD emit the TransferSingle event from `0x0` to `0x0`, with the token creator as `_operator`.
|
||||||
|
*/
|
||||||
|
event TransferSingle(address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@dev Either TransferSingle or TransferBatch MUST emit when tokens are transferred, including zero value transfers as well as minting or burning.
|
||||||
|
Operator will always be msg.sender.
|
||||||
|
Either event from address `0x0` signifies a minting operation.
|
||||||
|
An event to address `0x0` signifies a burning or melting operation.
|
||||||
|
The total value transferred from address 0x0 minus the total value transferred to 0x0 may be used by clients and exchanges to be added to the "circulating supply" for a given token ID.
|
||||||
|
To define multiple token IDs with no initial balance, this SHOULD emit the TransferBatch event from `0x0` to `0x0`, with the token creator as `_operator`.
|
||||||
|
*/
|
||||||
|
event TransferBatch(address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@dev MUST emit when an approval is updated.
|
||||||
|
*/
|
||||||
|
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@dev MUST emit when the URI is updated for a token ID.
|
||||||
|
URIs are defined in RFC 3986.
|
||||||
|
The URI MUST point a JSON file that conforms to the "ERC-1155 Metadata JSON Schema".
|
||||||
|
*/
|
||||||
|
event URI(string _value, uint256 indexed _id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@notice Transfers value amount of an _id from the _from address to the _to address specified.
|
||||||
|
@dev MUST emit TransferSingle event on success.
|
||||||
|
Caller must be approved to manage the _from account's tokens (see isApprovedForAll).
|
||||||
|
MUST throw if `_to` is the zero address.
|
||||||
|
MUST throw if balance of sender for token `_id` is lower than the `_value` sent.
|
||||||
|
MUST throw on any other error.
|
||||||
|
When transfer is complete, this function MUST check if `_to` is a smart contract (code size > 0). If so, it MUST call `onERC1155Received` on `_to` and revert if the return value is not `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`.
|
||||||
|
@param _from Source address
|
||||||
|
@param _to Target address
|
||||||
|
@param _id ID of the token type
|
||||||
|
@param _value Transfer amount
|
||||||
|
@param _data Additional data with no specified format, sent in call to `_to`
|
||||||
|
*/
|
||||||
|
function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@notice Send multiple types of Tokens from a 3rd party in one transfer (with safety call).
|
||||||
|
@dev MUST emit TransferBatch event on success.
|
||||||
|
Caller must be approved to manage the _from account's tokens (see isApprovedForAll).
|
||||||
|
MUST throw if `_to` is the zero address.
|
||||||
|
MUST throw if length of `_ids` is not the same as length of `_values`.
|
||||||
|
MUST throw if any of the balance of sender for token `_ids` is lower than the respective `_values` sent.
|
||||||
|
MUST throw on any other error.
|
||||||
|
When transfer is complete, this function MUST check if `_to` is a smart contract (code size > 0). If so, it MUST call `onERC1155BatchReceived` on `_to` and revert if the return value is not `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`.
|
||||||
|
@param _from Source addresses
|
||||||
|
@param _to Target addresses
|
||||||
|
@param _ids IDs of each token type
|
||||||
|
@param _values Transfer amounts per token type
|
||||||
|
@param _data Additional data with no specified format, sent in call to `_to`
|
||||||
|
*/
|
||||||
|
function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@notice Get the balance of an account's Tokens.
|
||||||
|
@param _owner The address of the token holder
|
||||||
|
@param _id ID of the Token
|
||||||
|
@return The _owner's balance of the Token type requested
|
||||||
|
*/
|
||||||
|
function balanceOf(address _owner, uint256 _id) external view returns (uint256);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@notice Get the balance of multiple account/token pairs
|
||||||
|
@param _owners The addresses of the token holders
|
||||||
|
@param _ids ID of the Tokens
|
||||||
|
@return The _owner's balance of the Token types requested
|
||||||
|
*/
|
||||||
|
function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@notice Enable or disable approval for a third party ("operator") to manage all of the caller's tokens.
|
||||||
|
@dev MUST emit the ApprovalForAll event on success.
|
||||||
|
@param _operator Address to add to the set of authorized operators
|
||||||
|
@param _approved True if the operator is approved, false to revoke approval
|
||||||
|
*/
|
||||||
|
function setApprovalForAll(address _operator, bool _approved) external;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@notice Queries the approval status of an operator for a given owner.
|
||||||
|
@param _owner The owner of the Tokens
|
||||||
|
@param _operator Address of authorized operator
|
||||||
|
@return True if the operator is approved, false if not
|
||||||
|
*/
|
||||||
|
function isApprovedForAll(address _owner, address _operator) external view returns (bool);
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2018 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.3;
|
||||||
|
|
||||||
|
|
||||||
|
interface IERC1155Receiver {
|
||||||
|
|
||||||
|
/**
|
||||||
|
@notice Handle the receipt of a single ERC1155 token type
|
||||||
|
@dev The smart contract calls this function on the recipient
|
||||||
|
after a `safeTransferFrom`. This function MAY throw to revert and reject the
|
||||||
|
transfer. Return of other than the magic value MUST result in the
|
||||||
|
transaction being reverted
|
||||||
|
Note: the contract address is always the message sender
|
||||||
|
@param _operator The address which called `safeTransferFrom` function
|
||||||
|
@param _from The address which previously owned the token
|
||||||
|
@param _id An array containing the ids of the token being transferred
|
||||||
|
@param _value An array containing the amount of tokens being transferred
|
||||||
|
@param _data Additional data with no specified format
|
||||||
|
@return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
|
||||||
|
*/
|
||||||
|
function onERC1155Received(address _operator, address _from, uint256 _id, uint256 _value, bytes calldata _data) external returns(bytes4);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@notice Handle the receipt of multiple ERC1155 token types
|
||||||
|
@dev The smart contract calls this function on the recipient
|
||||||
|
after a `safeTransferFrom`. This function MAY throw to revert and reject the
|
||||||
|
transfer. Return of other than the magic value MUST result in the
|
||||||
|
transaction being reverted
|
||||||
|
Note: the contract address is always the message sender
|
||||||
|
@param _operator The address which called `safeTransferFrom` function
|
||||||
|
@param _from The address which previously owned the token
|
||||||
|
@param _ids An array containing ids of each token being transferred
|
||||||
|
@param _values An array containing amounts of each token being transferred
|
||||||
|
@param _data Additional data with no specified format
|
||||||
|
@return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
|
||||||
|
*/
|
||||||
|
function onERC1155BatchReceived(address _operator, address _from, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external returns(bytes4);
|
||||||
|
}
|
75
contracts/erc1155/contracts/test/DummyERC1155Receiver.sol
Normal file
75
contracts/erc1155/contracts/test/DummyERC1155Receiver.sol
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2018 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.3;
|
||||||
|
|
||||||
|
import "../src/interfaces/IERC1155Receiver.sol";
|
||||||
|
|
||||||
|
contract DummyERC1155Receiver is
|
||||||
|
IERC1155Receiver
|
||||||
|
{
|
||||||
|
|
||||||
|
bytes4 constant public ERC1155_RECEIVED = 0xf23a6e61;
|
||||||
|
bytes4 constant public ERC1155_BATCH_RECEIVED = 0xbc197c81;
|
||||||
|
|
||||||
|
constructor () public {}
|
||||||
|
|
||||||
|
event TokenReceived(
|
||||||
|
address operator,
|
||||||
|
address from,
|
||||||
|
uint256 tokenId,
|
||||||
|
uint256 tokenValue,
|
||||||
|
bytes data
|
||||||
|
);
|
||||||
|
|
||||||
|
event BatchTokenReceived(
|
||||||
|
address operator,
|
||||||
|
address from,
|
||||||
|
uint256[] tokenIds,
|
||||||
|
uint256[] tokenValues,
|
||||||
|
bytes data
|
||||||
|
);
|
||||||
|
|
||||||
|
function onERC1155Received(
|
||||||
|
address _operator,
|
||||||
|
address _from,
|
||||||
|
uint256 _id,
|
||||||
|
uint256 _value,
|
||||||
|
bytes calldata _data
|
||||||
|
)
|
||||||
|
external
|
||||||
|
returns (bytes4)
|
||||||
|
{
|
||||||
|
emit TokenReceived(_operator, _from, _id, _value, _data);
|
||||||
|
return ERC1155_RECEIVED;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onERC1155BatchReceived(
|
||||||
|
address _operator,
|
||||||
|
address _from,
|
||||||
|
uint256[] calldata _ids,
|
||||||
|
uint256[] calldata _values,
|
||||||
|
bytes calldata _data
|
||||||
|
)
|
||||||
|
external
|
||||||
|
returns (bytes4)
|
||||||
|
{
|
||||||
|
emit BatchTokenReceived(_operator, _from, _ids, _values, _data);
|
||||||
|
return ERC1155_BATCH_RECEIVED;
|
||||||
|
}
|
||||||
|
}
|
40
contracts/erc1155/contracts/test/DummyERC1155Token.sol
Normal file
40
contracts/erc1155/contracts/test/DummyERC1155Token.sol
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2018 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.3;
|
||||||
|
|
||||||
|
import "../src/ERC1155Mintable.sol";
|
||||||
|
|
||||||
|
// solhint-disable no-empty-blocks
|
||||||
|
contract DummyERC1155Token is
|
||||||
|
ERC1155Mintable
|
||||||
|
{
|
||||||
|
|
||||||
|
string public name;
|
||||||
|
string public symbol;
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
string memory _name,
|
||||||
|
string memory _symbol
|
||||||
|
)
|
||||||
|
public
|
||||||
|
{
|
||||||
|
name = _name;
|
||||||
|
symbol = _symbol;
|
||||||
|
}
|
||||||
|
}
|
68
contracts/erc1155/contracts/test/InvalidERC1155Receiver.sol
Normal file
68
contracts/erc1155/contracts/test/InvalidERC1155Receiver.sol
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2018 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.3;
|
||||||
|
|
||||||
|
|
||||||
|
contract InvalidERC1155Receiver //is
|
||||||
|
//IERC1155Receiver
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
// Actual function signature is `onERC1155Received(address,address,uint256,bytes)`
|
||||||
|
bytes4 constant internal INVALID_ERC1155_RECEIVED = bytes4(keccak256("onERC1155Received(address,uint256,bytes)"));
|
||||||
|
|
||||||
|
event TokenReceived(
|
||||||
|
address operator,
|
||||||
|
address from,
|
||||||
|
uint256 tokenId,
|
||||||
|
bytes data
|
||||||
|
);
|
||||||
|
|
||||||
|
/// @notice Handle the receipt of an NFT
|
||||||
|
/// @dev The ERC1155 smart contract calls this function on the recipient
|
||||||
|
/// after a `transfer`. This function MAY throw to revert and reject the
|
||||||
|
/// transfer. Return of other than the magic value MUST result in the
|
||||||
|
/// transaction being reverted.
|
||||||
|
/// Note: the contract address is always the message sender.
|
||||||
|
/// @param _operator The address which called `safeTransferFrom` function
|
||||||
|
/// @param _from The address which previously owned the token
|
||||||
|
/// @param _tokenId The NFT identifier which is being transferred
|
||||||
|
/// @param _data Additional data with no specified format
|
||||||
|
/// @return `bytes4(keccak256("onERC1155Received(address,address,uint256,bytes)"))`
|
||||||
|
/// unless throwing
|
||||||
|
function onERC1155Received(
|
||||||
|
address _operator,
|
||||||
|
address _from,
|
||||||
|
uint256 _tokenId,
|
||||||
|
bytes _data
|
||||||
|
)
|
||||||
|
external
|
||||||
|
returns (bytes4)
|
||||||
|
{
|
||||||
|
emit TokenReceived(
|
||||||
|
_operator,
|
||||||
|
_from,
|
||||||
|
_tokenId,
|
||||||
|
_data
|
||||||
|
);
|
||||||
|
return INVALID_ERC1155_RECEIVED;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
82
contracts/erc1155/package.json
Normal file
82
contracts/erc1155/package.json
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
{
|
||||||
|
"name": "@0x/contracts-erc1155",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.12"
|
||||||
|
},
|
||||||
|
"description": "Token contracts used by 0x protocol",
|
||||||
|
"main": "lib/src/index.js",
|
||||||
|
"directories": {
|
||||||
|
"test": "test"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "yarn pre_build && tsc -b",
|
||||||
|
"build:ci": "yarn build",
|
||||||
|
"pre_build": "run-s compile generate_contract_wrappers",
|
||||||
|
"test": "yarn run_mocha",
|
||||||
|
"rebuild_and_test": "run-s build test",
|
||||||
|
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
|
||||||
|
"test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html",
|
||||||
|
"test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha",
|
||||||
|
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
|
||||||
|
"compile": "sol-compiler",
|
||||||
|
"watch": "sol-compiler -w",
|
||||||
|
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
|
||||||
|
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
|
||||||
|
"lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts",
|
||||||
|
"coverage:report:text": "istanbul report text",
|
||||||
|
"coverage:report:html": "istanbul report html && open coverage/index.html",
|
||||||
|
"profiler:report:html": "istanbul report html && open coverage/index.html",
|
||||||
|
"coverage:report:lcov": "istanbul report lcov",
|
||||||
|
"test:circleci": "yarn test",
|
||||||
|
"contracts:gen": "contracts-gen",
|
||||||
|
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"abis": "generated-artifacts/@(DummyERC1155Receiver|DummyERC1155Token|ERC1155|ERC1155Mintable|IERC1155|IERC1155Receiver|InvalidERC1155Receiver).json",
|
||||||
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/0xProject/0x-monorepo.git"
|
||||||
|
},
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
|
||||||
|
"devDependencies": {
|
||||||
|
"@0x/abi-gen": "^2.0.4",
|
||||||
|
"@0x/contracts-gen": "^1.0.3",
|
||||||
|
"@0x/contracts-test-utils": "^3.0.5",
|
||||||
|
"@0x/dev-utils": "^2.1.1",
|
||||||
|
"@0x/sol-compiler": "^3.1.0",
|
||||||
|
"@0x/tslint-config": "^3.0.0",
|
||||||
|
"@types/lodash": "4.14.104",
|
||||||
|
"@types/node": "*",
|
||||||
|
"chai": "^4.0.1",
|
||||||
|
"chai-as-promised": "^7.1.0",
|
||||||
|
"chai-bignumber": "^3.0.0",
|
||||||
|
"dirty-chai": "^2.0.1",
|
||||||
|
"make-promises-safe": "^1.1.0",
|
||||||
|
"mocha": "^4.1.0",
|
||||||
|
"npm-run-all": "^4.1.2",
|
||||||
|
"shx": "^0.2.2",
|
||||||
|
"solhint": "^1.4.1",
|
||||||
|
"tslint": "5.11.0",
|
||||||
|
"typescript": "3.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@0x/base-contract": "^5.0.0",
|
||||||
|
"@0x/contracts-utils": "2.0.1",
|
||||||
|
"@0x/types": "^2.1.0",
|
||||||
|
"@0x/typescript-typings": "^4.1.0",
|
||||||
|
"@0x/utils": "^4.2.0",
|
||||||
|
"@0x/web3-wrapper": "^6.0.0",
|
||||||
|
"ethereum-types": "^2.1.0",
|
||||||
|
"lodash": "^4.17.11"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
}
|
||||||
|
}
|
23
contracts/erc1155/src/artifacts.ts
Normal file
23
contracts/erc1155/src/artifacts.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
import { ContractArtifact } from 'ethereum-types';
|
||||||
|
|
||||||
|
import * as DummyERC1155Receiver from '../generated-artifacts/DummyERC1155Receiver.json';
|
||||||
|
import * as DummyERC1155Token from '../generated-artifacts/DummyERC1155Token.json';
|
||||||
|
import * as ERC1155 from '../generated-artifacts/ERC1155.json';
|
||||||
|
import * as ERC1155Mintable from '../generated-artifacts/ERC1155Mintable.json';
|
||||||
|
import * as IERC1155 from '../generated-artifacts/IERC1155.json';
|
||||||
|
import * as IERC1155Receiver from '../generated-artifacts/IERC1155Receiver.json';
|
||||||
|
import * as InvalidERC1155Receiver from '../generated-artifacts/InvalidERC1155Receiver.json';
|
||||||
|
export const artifacts = {
|
||||||
|
ERC1155: ERC1155 as ContractArtifact,
|
||||||
|
ERC1155Mintable: ERC1155Mintable as ContractArtifact,
|
||||||
|
IERC1155: IERC1155 as ContractArtifact,
|
||||||
|
IERC1155Receiver: IERC1155Receiver as ContractArtifact,
|
||||||
|
DummyERC1155Receiver: DummyERC1155Receiver as ContractArtifact,
|
||||||
|
DummyERC1155Token: DummyERC1155Token as ContractArtifact,
|
||||||
|
InvalidERC1155Receiver: InvalidERC1155Receiver as ContractArtifact,
|
||||||
|
};
|
2
contracts/erc1155/src/index.ts
Normal file
2
contracts/erc1155/src/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './wrappers';
|
||||||
|
export * from './artifacts';
|
12
contracts/erc1155/src/wrappers.ts
Normal file
12
contracts/erc1155/src/wrappers.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
export * from '../generated-wrappers/dummy_erc1155_receiver';
|
||||||
|
export * from '../generated-wrappers/dummy_erc1155_token';
|
||||||
|
export * from '../generated-wrappers/erc1155';
|
||||||
|
export * from '../generated-wrappers/erc1155_mintable';
|
||||||
|
export * from '../generated-wrappers/i_erc1155_receiver';
|
||||||
|
export * from '../generated-wrappers/ierc1155';
|
||||||
|
export * from '../generated-wrappers/invalid_erc1155_receiver';
|
347
contracts/erc1155/test/erc1155_token.ts
Normal file
347
contracts/erc1155/test/erc1155_token.ts
Normal file
@ -0,0 +1,347 @@
|
|||||||
|
|
||||||
|
import {
|
||||||
|
chaiSetup,
|
||||||
|
constants,
|
||||||
|
expectTransactionFailedAsync,
|
||||||
|
expectTransactionFailedWithoutReasonAsync,
|
||||||
|
LogDecoder,
|
||||||
|
provider,
|
||||||
|
txDefaults,
|
||||||
|
web3Wrapper,
|
||||||
|
} from '@0x/contracts-test-utils';
|
||||||
|
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||||
|
import { RevertReason } from '@0x/types';
|
||||||
|
import { BigNumber } from '@0x/utils';
|
||||||
|
import * as chai from 'chai';
|
||||||
|
import { LogWithDecodedArgs } from 'ethereum-types';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import {
|
||||||
|
artifacts,
|
||||||
|
DummyERC1155ReceiverContract,
|
||||||
|
DummyERC1155ReceiverTokenReceivedEventArgs,
|
||||||
|
DummyERC1155TokenContract,
|
||||||
|
//DummyERC1155TokenTransferEventArgs,
|
||||||
|
InvalidERC1155ReceiverContract,
|
||||||
|
ERC1155TransferSingleEventArgs,
|
||||||
|
DummyERC1155ReceiverBatchTokenReceivedEventArgs
|
||||||
|
} from '../src';
|
||||||
|
|
||||||
|
chaiSetup.configure();
|
||||||
|
const expect = chai.expect;
|
||||||
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
|
// tslint:disable:no-unnecessary-type-assertion
|
||||||
|
describe('ERC1155Token', () => {
|
||||||
|
|
||||||
|
const DUMMY_FUNGIBLE_TOKEN_URI = 'FUN';
|
||||||
|
const DUMMY_FUNGIBLE_TOKEN_IS_FUNGIBLE = false;
|
||||||
|
const DUMMY_NONFUNGIBLE_TOKEN_URI = 'NOFUN';
|
||||||
|
const DUMMY_NONFUNGIBLE_TOKEN_IS_FUNGIBLE = true;
|
||||||
|
|
||||||
|
let owner: string;
|
||||||
|
let spender: string;
|
||||||
|
const spenderInitialBalance = new BigNumber(500);
|
||||||
|
const receiverInitialBalance = new BigNumber(0);
|
||||||
|
let token: DummyERC1155TokenContract;
|
||||||
|
let erc1155Receiver: DummyERC1155ReceiverContract;
|
||||||
|
let logDecoder: LogDecoder;
|
||||||
|
const tokenId = new BigNumber(1);
|
||||||
|
let dummyNft: BigNumber;
|
||||||
|
const nftOwnerBalance = new BigNumber(1);
|
||||||
|
const nftNotOwnerBalance = new BigNumber(0);
|
||||||
|
|
||||||
|
let dummyFungibleTokenType: BigNumber;
|
||||||
|
let dummyNonFungibleTokenType: BigNumber;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
await blockchainLifecycle.startAsync();
|
||||||
|
});
|
||||||
|
after(async () => {
|
||||||
|
await blockchainLifecycle.revertAsync();
|
||||||
|
});
|
||||||
|
before(async () => {
|
||||||
|
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||||
|
owner = accounts[0];
|
||||||
|
spender = accounts[1];
|
||||||
|
token = await DummyERC1155TokenContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.DummyERC1155Token,
|
||||||
|
provider,
|
||||||
|
txDefaults,
|
||||||
|
constants.DUMMY_TOKEN_NAME,
|
||||||
|
constants.DUMMY_TOKEN_SYMBOL,
|
||||||
|
);
|
||||||
|
erc1155Receiver = await DummyERC1155ReceiverContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.DummyERC1155Receiver,
|
||||||
|
provider,
|
||||||
|
txDefaults,
|
||||||
|
);
|
||||||
|
|
||||||
|
logDecoder = new LogDecoder(web3Wrapper, artifacts);
|
||||||
|
// Create & mint fungible token
|
||||||
|
let txReceipt = await logDecoder.getTxWithDecodedLogsAsync(
|
||||||
|
await token.create.sendTransactionAsync(
|
||||||
|
DUMMY_FUNGIBLE_TOKEN_URI,
|
||||||
|
DUMMY_FUNGIBLE_TOKEN_IS_FUNGIBLE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const createFungibleTokenLog = txReceipt.logs[0] as LogWithDecodedArgs<ERC1155TransferSingleEventArgs>;
|
||||||
|
dummyFungibleTokenType = createFungibleTokenLog.args._id;
|
||||||
|
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||||
|
await token.mintFungible.sendTransactionAsync(
|
||||||
|
dummyFungibleTokenType,
|
||||||
|
[spender],
|
||||||
|
[spenderInitialBalance],
|
||||||
|
{ from: owner }
|
||||||
|
),
|
||||||
|
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||||
|
);
|
||||||
|
// Create & mint non-fungible token
|
||||||
|
txReceipt = await logDecoder.getTxWithDecodedLogsAsync(
|
||||||
|
await token.create.sendTransactionAsync(
|
||||||
|
DUMMY_NONFUNGIBLE_TOKEN_URI,
|
||||||
|
DUMMY_NONFUNGIBLE_TOKEN_IS_FUNGIBLE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const createNonFungibleTokenLog = txReceipt.logs[0] as LogWithDecodedArgs<ERC1155TransferSingleEventArgs>;
|
||||||
|
dummyNonFungibleTokenType = createNonFungibleTokenLog.args._id;
|
||||||
|
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||||
|
await token.mintNonFungible.sendTransactionAsync(
|
||||||
|
dummyNonFungibleTokenType,
|
||||||
|
[spender],
|
||||||
|
{ from: owner }
|
||||||
|
),
|
||||||
|
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||||
|
);
|
||||||
|
dummyNft = dummyNonFungibleTokenType.plus(1);
|
||||||
|
});
|
||||||
|
beforeEach(async () => {
|
||||||
|
await blockchainLifecycle.startAsync();
|
||||||
|
});
|
||||||
|
afterEach(async () => {
|
||||||
|
await blockchainLifecycle.revertAsync();
|
||||||
|
});
|
||||||
|
describe('safeTransferFrom', () => {
|
||||||
|
it('should transfer fungible token if called by token owner', async () => {
|
||||||
|
// setup test parameters
|
||||||
|
const from = spender;
|
||||||
|
const to = erc1155Receiver.address;
|
||||||
|
const fromIdx = 0;
|
||||||
|
const toIdx = 1;
|
||||||
|
const participatingOwners = [from, to];
|
||||||
|
const participatingTokens = [dummyFungibleTokenType, dummyFungibleTokenType];
|
||||||
|
const tokenTypesToTransfer = [dummyFungibleTokenType];
|
||||||
|
const valueToTransfer = new BigNumber(200);
|
||||||
|
const valuesToTransfer = [valueToTransfer];
|
||||||
|
const callbackData = constants.NULL_BYTES;
|
||||||
|
// check balances before transfer
|
||||||
|
const balancesBeforeTransfer = await token.balanceOfBatch.callAsync(participatingOwners, participatingTokens);
|
||||||
|
expect(balancesBeforeTransfer[fromIdx]).to.be.bignumber.equal(spenderInitialBalance);
|
||||||
|
expect(balancesBeforeTransfer[toIdx]).to.be.bignumber.equal(receiverInitialBalance);
|
||||||
|
// execute transfer
|
||||||
|
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||||
|
await token.safeTransferFrom.sendTransactionAsync(from, to, tokenTypesToTransfer[0], valuesToTransfer[0], callbackData, {from}),
|
||||||
|
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||||
|
);
|
||||||
|
// check balances after transfer
|
||||||
|
const balancesAfterTransfer = await token.balanceOfBatch.callAsync(participatingOwners, participatingTokens);
|
||||||
|
expect(balancesAfterTransfer[fromIdx]).to.be.bignumber.equal(balancesBeforeTransfer[fromIdx].minus(valueToTransfer));
|
||||||
|
expect(balancesAfterTransfer[toIdx]).to.be.bignumber.equal(balancesBeforeTransfer[toIdx].plus(valueToTransfer));
|
||||||
|
});
|
||||||
|
it('should transfer non-fungible token if called by token owner', async () => {
|
||||||
|
// setup test parameters
|
||||||
|
const from = spender;
|
||||||
|
const to = erc1155Receiver.address;
|
||||||
|
const fromIdx = 0;
|
||||||
|
const toIdx = 1;
|
||||||
|
const participatingOwners = [from, to];
|
||||||
|
const participatingTokens = [dummyNft, dummyNft];
|
||||||
|
const tokenTypesToTransfer = [dummyNft];
|
||||||
|
const valueToTransfer = new BigNumber(1);
|
||||||
|
const valuesToTransfer = [valueToTransfer];
|
||||||
|
const callbackData = constants.NULL_BYTES;
|
||||||
|
// check balances before transfer
|
||||||
|
const balancesBeforeTransfer = await token.balanceOfBatch.callAsync(participatingOwners, participatingTokens);
|
||||||
|
expect(balancesBeforeTransfer[fromIdx]).to.be.bignumber.equal(nftOwnerBalance);
|
||||||
|
expect(balancesBeforeTransfer[toIdx]).to.be.bignumber.equal(nftNotOwnerBalance);
|
||||||
|
// execute transfer
|
||||||
|
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||||
|
await token.safeTransferFrom.sendTransactionAsync(from, to, tokenTypesToTransfer[0], valuesToTransfer[0], callbackData, {from}),
|
||||||
|
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||||
|
);
|
||||||
|
// check balances after transfer
|
||||||
|
const balancesAfterTransfer = await token.balanceOfBatch.callAsync(participatingOwners, participatingTokens);
|
||||||
|
expect(balancesAfterTransfer[fromIdx]).to.be.bignumber.equal(nftNotOwnerBalance);
|
||||||
|
expect(balancesAfterTransfer[toIdx]).to.be.bignumber.equal(nftOwnerBalance);
|
||||||
|
});
|
||||||
|
it('should trigger callback if transferring to a contract', async () => {
|
||||||
|
// setup test parameters
|
||||||
|
const from = spender;
|
||||||
|
const to = erc1155Receiver.address;
|
||||||
|
const fromIdxFungible = 0;
|
||||||
|
const toIdxFungible = 1;
|
||||||
|
const fromIdxNonFungible = 2;
|
||||||
|
const toIdxNonFungible = 3;
|
||||||
|
const participatingOwners = [from, to, from, to];
|
||||||
|
const participatingTokens = [dummyFungibleTokenType, dummyFungibleTokenType, dummyNft, dummyNft];
|
||||||
|
const tokenTypesToTransfer = [dummyFungibleTokenType, dummyNft];
|
||||||
|
const fungibleValueToTransfer = new BigNumber(200);
|
||||||
|
const nonFungibleValueToTransfer = new BigNumber(1);
|
||||||
|
const valuesToTransfer = [fungibleValueToTransfer, nonFungibleValueToTransfer];
|
||||||
|
const callbackData = '0x01020304';
|
||||||
|
// check balances before transfer
|
||||||
|
const balancesBeforeTransfer = await token.balanceOfBatch.callAsync(participatingOwners, participatingTokens);
|
||||||
|
expect(balancesBeforeTransfer[fromIdxFungible]).to.be.bignumber.equal(spenderInitialBalance);
|
||||||
|
expect(balancesBeforeTransfer[toIdxFungible]).to.be.bignumber.equal(receiverInitialBalance);
|
||||||
|
expect(balancesBeforeTransfer[fromIdxNonFungible]).to.be.bignumber.equal(nftOwnerBalance);
|
||||||
|
expect(balancesBeforeTransfer[toIdxNonFungible]).to.be.bignumber.equal(nftNotOwnerBalance);
|
||||||
|
// execute transfer
|
||||||
|
const txReceipt = await logDecoder.getTxWithDecodedLogsAsync(
|
||||||
|
await token.safeTransferFrom.sendTransactionAsync(from, to, tokenTypesToTransfer[0], valuesToTransfer[0], callbackData, {from})
|
||||||
|
);
|
||||||
|
expect(txReceipt.logs.length).to.be.equal(2);
|
||||||
|
const receiverLog = txReceipt.logs[1] as LogWithDecodedArgs<DummyERC1155ReceiverTokenReceivedEventArgs>;
|
||||||
|
// check callback logs
|
||||||
|
expect(receiverLog.args.operator).to.be.equal(from);
|
||||||
|
expect(receiverLog.args.from).to.be.equal(from);
|
||||||
|
expect(receiverLog.args.tokenId).to.be.bignumber.equal(tokenTypesToTransfer[0]);
|
||||||
|
expect(receiverLog.args.tokenValue).to.be.bignumber.equal(valuesToTransfer[0]);
|
||||||
|
expect(receiverLog.args.data).to.be.deep.equal(callbackData);
|
||||||
|
// check balances after transfer
|
||||||
|
const balancesAfterTransfer = await token.balanceOfBatch.callAsync(participatingOwners, participatingTokens);
|
||||||
|
expect(balancesAfterTransfer[fromIdxFungible]).to.be.bignumber.equal(balancesBeforeTransfer[fromIdxFungible].minus(fungibleValueToTransfer));
|
||||||
|
expect(balancesAfterTransfer[toIdxFungible]).to.be.bignumber.equal(balancesBeforeTransfer[toIdxFungible].plus(fungibleValueToTransfer));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('batchSafeTransferFrom', () => {
|
||||||
|
it('should transfer fungible tokens if called by token owner', async () => {
|
||||||
|
// setup test parameters
|
||||||
|
const from = spender;
|
||||||
|
const to = erc1155Receiver.address;
|
||||||
|
const fromIdx = 0;
|
||||||
|
const toIdx = 1;
|
||||||
|
const participatingOwners = [from, to];
|
||||||
|
const participatingTokens = [dummyFungibleTokenType, dummyFungibleTokenType];
|
||||||
|
const tokenTypesToTransfer = [dummyFungibleTokenType];
|
||||||
|
const valueToTransfer = new BigNumber(200);
|
||||||
|
const valuesToTransfer = [valueToTransfer];
|
||||||
|
const callbackData = constants.NULL_BYTES;
|
||||||
|
// check balances before transfer
|
||||||
|
const balancesBeforeTransfer = await token.balanceOfBatch.callAsync(participatingOwners, participatingTokens);
|
||||||
|
expect(balancesBeforeTransfer[fromIdx]).to.be.bignumber.equal(spenderInitialBalance);
|
||||||
|
expect(balancesBeforeTransfer[toIdx]).to.be.bignumber.equal(receiverInitialBalance);
|
||||||
|
// execute transfer
|
||||||
|
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||||
|
await token.safeBatchTransferFrom.sendTransactionAsync(from, to, tokenTypesToTransfer, valuesToTransfer, callbackData, {from}),
|
||||||
|
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||||
|
);
|
||||||
|
// check balances after transfer
|
||||||
|
const balancesAfterTransfer = await token.balanceOfBatch.callAsync(participatingOwners, participatingTokens);
|
||||||
|
expect(balancesAfterTransfer[fromIdx]).to.be.bignumber.equal(balancesBeforeTransfer[fromIdx].minus(valueToTransfer));
|
||||||
|
expect(balancesAfterTransfer[toIdx]).to.be.bignumber.equal(balancesBeforeTransfer[toIdx].plus(valueToTransfer));
|
||||||
|
});
|
||||||
|
it('should transfer non-fungible token if called by token owner', async () => {
|
||||||
|
// setup test parameters
|
||||||
|
const from = spender;
|
||||||
|
const to = erc1155Receiver.address;
|
||||||
|
const fromIdx = 0;
|
||||||
|
const toIdx = 1;
|
||||||
|
const participatingOwners = [from, to];
|
||||||
|
const participatingTokens = [dummyNft, dummyNft];
|
||||||
|
const tokenTypesToTransfer = [dummyNft];
|
||||||
|
const valueToTransfer = new BigNumber(1);
|
||||||
|
const valuesToTransfer = [valueToTransfer];
|
||||||
|
const callbackData = constants.NULL_BYTES;
|
||||||
|
// check balances before transfer
|
||||||
|
const balancesBeforeTransfer = await token.balanceOfBatch.callAsync(participatingOwners, participatingTokens);
|
||||||
|
expect(balancesBeforeTransfer[fromIdx]).to.be.bignumber.equal(nftOwnerBalance);
|
||||||
|
expect(balancesBeforeTransfer[toIdx]).to.be.bignumber.equal(nftNotOwnerBalance);
|
||||||
|
// execute transfer
|
||||||
|
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||||
|
await token.safeBatchTransferFrom.sendTransactionAsync(from, to, tokenTypesToTransfer, valuesToTransfer, callbackData, {from}),
|
||||||
|
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||||
|
);
|
||||||
|
// check balances after transfer
|
||||||
|
const balancesAfterTransfer = await token.balanceOfBatch.callAsync(participatingOwners, participatingTokens);
|
||||||
|
expect(balancesAfterTransfer[fromIdx]).to.be.bignumber.equal(nftNotOwnerBalance);
|
||||||
|
expect(balancesAfterTransfer[toIdx]).to.be.bignumber.equal(nftOwnerBalance);
|
||||||
|
});
|
||||||
|
it('should transfer mix of fungible / non-fungible tokens if called by token owner', async () => {
|
||||||
|
// setup test parameters
|
||||||
|
const from = spender;
|
||||||
|
const to = erc1155Receiver.address;
|
||||||
|
const fromIdxFungible = 0;
|
||||||
|
const toIdxFungible = 1;
|
||||||
|
const fromIdxNonFungible = 2;
|
||||||
|
const toIdxNonFungible = 3;
|
||||||
|
const participatingOwners = [from, to, from, to];
|
||||||
|
const participatingTokens = [dummyFungibleTokenType, dummyFungibleTokenType, dummyNft, dummyNft];
|
||||||
|
const tokenTypesToTransfer = [dummyFungibleTokenType, dummyNft];
|
||||||
|
const fungibleValueToTransfer = new BigNumber(200);
|
||||||
|
const nonFungibleValueToTransfer = new BigNumber(1);
|
||||||
|
const valuesToTransfer = [fungibleValueToTransfer, nonFungibleValueToTransfer];
|
||||||
|
const callbackData = constants.NULL_BYTES;
|
||||||
|
// check balances before transfer
|
||||||
|
const balancesBeforeTransfer = await token.balanceOfBatch.callAsync(participatingOwners, participatingTokens);
|
||||||
|
expect(balancesBeforeTransfer[fromIdxFungible]).to.be.bignumber.equal(spenderInitialBalance);
|
||||||
|
expect(balancesBeforeTransfer[toIdxFungible]).to.be.bignumber.equal(receiverInitialBalance);
|
||||||
|
expect(balancesBeforeTransfer[fromIdxNonFungible]).to.be.bignumber.equal(nftOwnerBalance);
|
||||||
|
expect(balancesBeforeTransfer[toIdxNonFungible]).to.be.bignumber.equal(nftNotOwnerBalance);
|
||||||
|
// execute transfer
|
||||||
|
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||||
|
await token.safeBatchTransferFrom.sendTransactionAsync(from, to, tokenTypesToTransfer, valuesToTransfer, callbackData, {from}),
|
||||||
|
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||||
|
);
|
||||||
|
// check balances after transfer
|
||||||
|
const balancesAfterTransfer = await token.balanceOfBatch.callAsync(participatingOwners, participatingTokens);
|
||||||
|
expect(balancesAfterTransfer[fromIdxFungible]).to.be.bignumber.equal(balancesBeforeTransfer[fromIdxFungible].minus(fungibleValueToTransfer));
|
||||||
|
expect(balancesAfterTransfer[toIdxFungible]).to.be.bignumber.equal(balancesBeforeTransfer[toIdxFungible].plus(fungibleValueToTransfer));
|
||||||
|
expect(balancesAfterTransfer[fromIdxNonFungible]).to.be.bignumber.equal(nftNotOwnerBalance);
|
||||||
|
expect(balancesAfterTransfer[toIdxNonFungible]).to.be.bignumber.equal(nftOwnerBalance);
|
||||||
|
});
|
||||||
|
it('should trigger callback if transferring to a contract', async () => {
|
||||||
|
// setup test parameters
|
||||||
|
const from = spender;
|
||||||
|
const to = erc1155Receiver.address;
|
||||||
|
const fromIdxFungible = 0;
|
||||||
|
const toIdxFungible = 1;
|
||||||
|
const fromIdxNonFungible = 2;
|
||||||
|
const toIdxNonFungible = 3;
|
||||||
|
const participatingOwners = [from, to, from, to];
|
||||||
|
const participatingTokens = [dummyFungibleTokenType, dummyFungibleTokenType, dummyNft, dummyNft];
|
||||||
|
const tokenTypesToTransfer = [dummyFungibleTokenType, dummyNft];
|
||||||
|
const fungibleValueToTransfer = new BigNumber(200);
|
||||||
|
const nonFungibleValueToTransfer = new BigNumber(1);
|
||||||
|
const valuesToTransfer = [fungibleValueToTransfer, nonFungibleValueToTransfer];
|
||||||
|
const callbackData = '0x01020304';
|
||||||
|
// check balances before transfer
|
||||||
|
const balancesBeforeTransfer = await token.balanceOfBatch.callAsync(participatingOwners, participatingTokens);
|
||||||
|
expect(balancesBeforeTransfer[fromIdxFungible]).to.be.bignumber.equal(spenderInitialBalance);
|
||||||
|
expect(balancesBeforeTransfer[toIdxFungible]).to.be.bignumber.equal(receiverInitialBalance);
|
||||||
|
expect(balancesBeforeTransfer[fromIdxNonFungible]).to.be.bignumber.equal(nftOwnerBalance);
|
||||||
|
expect(balancesBeforeTransfer[toIdxNonFungible]).to.be.bignumber.equal(nftNotOwnerBalance);
|
||||||
|
// execute transfer
|
||||||
|
const txReceipt = await logDecoder.getTxWithDecodedLogsAsync(
|
||||||
|
await token.safeBatchTransferFrom.sendTransactionAsync(from, to, tokenTypesToTransfer, valuesToTransfer, callbackData, {from})
|
||||||
|
);
|
||||||
|
expect(txReceipt.logs.length).to.be.equal(2);
|
||||||
|
const receiverLog = txReceipt.logs[1] as LogWithDecodedArgs<DummyERC1155ReceiverBatchTokenReceivedEventArgs>;
|
||||||
|
// check callback logs
|
||||||
|
expect(receiverLog.args.operator).to.be.equal(from);
|
||||||
|
expect(receiverLog.args.from).to.be.equal(from);
|
||||||
|
expect(receiverLog.args.tokenIds.length).to.be.equal(2);
|
||||||
|
expect(receiverLog.args.tokenIds[0]).to.be.bignumber.equal(tokenTypesToTransfer[0]);
|
||||||
|
expect(receiverLog.args.tokenIds[1]).to.be.bignumber.equal(tokenTypesToTransfer[1]);
|
||||||
|
expect(receiverLog.args.tokenValues.length).to.be.equal(2);
|
||||||
|
expect(receiverLog.args.tokenValues[0]).to.be.bignumber.equal(valuesToTransfer[0]);
|
||||||
|
expect(receiverLog.args.tokenValues[1]).to.be.bignumber.equal(valuesToTransfer[1]);
|
||||||
|
expect(receiverLog.args.data).to.be.deep.equal(callbackData);
|
||||||
|
// check balances after transfer
|
||||||
|
const balancesAfterTransfer = await token.balanceOfBatch.callAsync(participatingOwners, participatingTokens);
|
||||||
|
expect(balancesAfterTransfer[fromIdxFungible]).to.be.bignumber.equal(balancesBeforeTransfer[fromIdxFungible].minus(fungibleValueToTransfer));
|
||||||
|
expect(balancesAfterTransfer[toIdxFungible]).to.be.bignumber.equal(balancesBeforeTransfer[toIdxFungible].plus(fungibleValueToTransfer));
|
||||||
|
expect(balancesAfterTransfer[fromIdxNonFungible]).to.be.bignumber.equal(nftNotOwnerBalance);
|
||||||
|
expect(balancesAfterTransfer[toIdxNonFungible]).to.be.bignumber.equal(nftOwnerBalance);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// tslint:enable:no-unnecessary-type-assertion
|
17
contracts/erc1155/test/global_hooks.ts
Normal file
17
contracts/erc1155/test/global_hooks.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { env, EnvVars } from '@0x/dev-utils';
|
||||||
|
|
||||||
|
import { coverage, profiler, provider } from '@0x/contracts-test-utils';
|
||||||
|
before('start web3 provider', () => {
|
||||||
|
provider.start();
|
||||||
|
});
|
||||||
|
after('generate coverage report', async () => {
|
||||||
|
if (env.parseBoolean(EnvVars.SolidityCoverage)) {
|
||||||
|
const coverageSubprovider = coverage.getCoverageSubproviderSingleton();
|
||||||
|
await coverageSubprovider.writeCoverageAsync();
|
||||||
|
}
|
||||||
|
if (env.parseBoolean(EnvVars.SolidityProfiler)) {
|
||||||
|
const profilerSubprovider = profiler.getProfilerSubproviderSingleton();
|
||||||
|
await profilerSubprovider.writeProfilerOutputAsync();
|
||||||
|
}
|
||||||
|
provider.stop();
|
||||||
|
});
|
15
contracts/erc1155/tsconfig.json
Normal file
15
contracts/erc1155/tsconfig.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig",
|
||||||
|
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
|
||||||
|
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
||||||
|
"files": [
|
||||||
|
"generated-artifacts/DummyERC1155Receiver.json",
|
||||||
|
"generated-artifacts/DummyERC1155Token.json",
|
||||||
|
"generated-artifacts/ERC1155.json",
|
||||||
|
"generated-artifacts/ERC1155Mintable.json",
|
||||||
|
"generated-artifacts/IERC1155.json",
|
||||||
|
"generated-artifacts/IERC1155Receiver.json",
|
||||||
|
"generated-artifacts/InvalidERC1155Receiver.json"
|
||||||
|
],
|
||||||
|
"exclude": ["./deploy/solc/solc_bin"]
|
||||||
|
}
|
6
contracts/erc1155/tslint.json
Normal file
6
contracts/erc1155/tslint.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"extends": ["@0x/tslint-config"],
|
||||||
|
"rules": {
|
||||||
|
"custom-no-magic-numbers": false
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user