├── migrations └── .none ├── .soliumignore ├── .gitattributes ├── .gitignore ├── .solcover.js ├── typings ├── mocha.d.ts ├── truffle.d.ts ├── contracts │ ├── index.d.ts │ ├── LibEIP712.d.ts │ ├── IERC165.d.ts │ ├── IERC1271Wallet.d.ts │ ├── SignatureValidator.d.ts │ ├── ERC1155Metadata.d.ts │ ├── ERC1271WalletMock.d.ts │ ├── Ownable.d.ts │ ├── OwnableMock.d.ts │ ├── ERC1155MetadataMock.d.ts │ ├── IERC1155TokenReceiver.d.ts │ ├── IERC20.d.ts │ ├── IERC1155Meta.d.ts │ ├── ERC20.d.ts │ ├── ERC1155ReceiverMock.d.ts │ ├── IERC1155.d.ts │ ├── ERC1155.d.ts │ ├── ERC1155MintBurn.d.ts │ ├── ERC20Mock.d.ts │ ├── ERC1155PackedBalance.d.ts │ ├── ERC1155MintBurnPackedBalance.d.ts │ ├── ERC1155OperatorMock.d.ts │ ├── ERC1155Meta.d.ts │ ├── ERC1155MetaPackedBalance.d.ts │ └── ERC1155MetaMintBurnMock.d.ts └── txTypes.d.ts ├── contracts ├── mocks │ ├── OwnableMock.sol │ ├── ERC1155MetadataMock.sol │ ├── ERC1271WalletMock.sol │ ├── ERC1155MetaMintBurnMock.sol │ ├── ERC1155MetaMintBurnPackedBalanceMock.sol │ ├── ERC1155OperatorMock.sol │ ├── ERC1155ReceiverMock.sol │ └── ERC20Mock.sol ├── interfaces │ ├── IERC165.sol │ ├── IERC20.sol │ ├── IERC1271Wallet.sol │ ├── IERC1155TokenReceiver.sol │ ├── IERC1155Meta.sol │ └── IERC1155.sol ├── utils │ ├── Ownable.sol │ ├── Address.sol │ ├── SafeMath.sol │ ├── LibEIP712.sol │ ├── LibBytes.sol │ └── SignatureValidator.sol └── tokens │ ├── ERC1155 │ ├── ERC1155Metadata.sol │ ├── ERC1155MintBurn.sol │ └── ERC1155.sol │ └── ERC1155PackedBalance │ └── ERC1155MintBurnPackedBalance.sol ├── src └── tests │ ├── utils │ ├── index.ts │ └── contract.ts │ ├── Ownable.spec.ts │ ├── SignatureValidator.spec.ts │ └── ERC1155Metadata.spec.ts ├── .soliumrc.json ├── tsconfig.json ├── truffle.js ├── LICENSE ├── tslint.json └── package.json /migrations/.none: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.soliumignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | node_modules/ 4 | 5 | *.js.map 6 | build/ 7 | 8 | .DS_Store 9 | .vscode 10 | .idea/ 11 | *.iml 12 | 13 | npm-debug.log* 14 | yarn-debug.log* 15 | yarn-error.log* 16 | lerna-debug.log* 17 | -------------------------------------------------------------------------------- /.solcover.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | port: '8545', 3 | norpc: true, 4 | testCommand: 'truffle test --network coverage', 5 | skipFiles: [ 6 | 'ERC1155MockNoBalancePacking.sol', 7 | 'ERC1155Mock.sol', 8 | 'ERC1155MockX.sol', 9 | 'ERC1155OperatorMock.sol', 10 | 'ERC1155ReceiverMock.sol', 11 | 'ERC20Mock.sol', 12 | 'ERC721Mock.sol' 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /typings/mocha.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | 3 | // Adding if method for mocha's describe method 4 | /* https://github.com/mochajs/mocha/issues/591#issuecomment-443841252 */ 5 | /// 6 | declare module "mocha" { 7 | interface SuiteFunction { 8 | if: (condition: boolean, message: string, func: (this: Mocha.Suite) => void) => void; 9 | } 10 | } -------------------------------------------------------------------------------- /typings/truffle.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'truffle' { 2 | import * as truffle from 'truffle-contract' 3 | 4 | interface ArtifactsGlobal { 5 | require(name: string): truffle.TruffleContract 6 | } 7 | 8 | global { 9 | function contract( 10 | name: string, 11 | callback: (accounts: Array) => void 12 | ): void; 13 | const artifacts: ArtifactsGlobal 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /contracts/mocks/OwnableMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | 3 | import "../utils/Ownable.sol"; 4 | 5 | 6 | /** 7 | * @dev Contract that is ownable 8 | */ 9 | contract OwnableMock is Ownable { 10 | uint256 internal mockStateOwner = 0; 11 | uint256 internal mockStateNonOwner = 0; 12 | 13 | function ownerCall() external onlyOwner() { 14 | mockStateOwner += 1; 15 | } 16 | 17 | function nonOwnerCall() external { 18 | mockStateNonOwner += 1; 19 | } 20 | } -------------------------------------------------------------------------------- /contracts/interfaces/IERC165.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | 3 | 4 | /** 5 | * @title ERC165 6 | * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md 7 | */ 8 | interface IERC165 { 9 | 10 | /** 11 | * @notice Query if a contract implements an interface 12 | * @dev Interface identification is specified in ERC-165. This function 13 | * uses less than 30,000 gas 14 | * @param _interfaceId The interface identifier, as specified in ERC-165 15 | */ 16 | function supportsInterface(bytes4 _interfaceId) 17 | external 18 | view 19 | returns (bool); 20 | } -------------------------------------------------------------------------------- /src/tests/utils/index.ts: -------------------------------------------------------------------------------- 1 | import * as chai from 'chai' 2 | import chaiAsPromised from 'chai-as-promised' 3 | const ChaiBigNumber = require('chai-bignumber') 4 | import chaiString from 'chai-string' 5 | import * as ethers from 'ethers' 6 | 7 | export * from './contract' 8 | export * from './helpers' 9 | 10 | const BigNumber = ethers.utils.BigNumber 11 | export { BigNumber } 12 | 13 | export const { assert, expect } = chai 14 | .use(chaiString) 15 | .use(chaiAsPromised) 16 | .use(ChaiBigNumber()); 17 | 18 | describe.if = function (condition: boolean, message: string, func: (this: Mocha.Suite) => void): void { 19 | const run: Mocha.PendingSuiteFunction = condition ? this : this.skip; 20 | run(message, func); 21 | } -------------------------------------------------------------------------------- /.soliumrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solium:all", 3 | "plugins": ["security"], 4 | "rules": { 5 | "imports-on-top": 1, 6 | "variable-declarations": 1, 7 | "array-declarations": 1, 8 | "operator-whitespace": 1, 9 | "lbrace": 1, 10 | "mixedcase": 0, 11 | "camelcase": 1, 12 | "uppercase": 1, 13 | "no-empty-blocks": 1, 14 | "no-unused-vars": 1, 15 | "quotes": 1, 16 | "indentation": ["error", 2], 17 | "arg-overflow": ["error", 8], 18 | "whitespace": 1, 19 | "deprecated-suicide": 1, 20 | "pragma-on-top": 1, 21 | "no-experimental": 0, 22 | "security/enforce-explicit-visibility": ["error"], 23 | "security/no-block-members": ["warning"], 24 | "security/no-low-level-calls": 0, 25 | "security/no-inline-assembly": 0 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | 3 | /** 4 | * @title ERC20 interface 5 | * @dev see https://eips.ethereum.org/EIPS/eip-20 6 | */ 7 | interface IERC20 { 8 | function transfer(address to, uint256 value) external returns (bool); 9 | function approve(address spender, uint256 value) external returns (bool); 10 | function transferFrom(address from, address to, uint256 value) external returns (bool); 11 | function totalSupply() external view returns (uint256); 12 | function balanceOf(address who) external view returns (uint256); 13 | function allowance(address owner, address spender) external view returns (uint256); 14 | event Transfer(address indexed from, address indexed to, uint256 value); 15 | event Approval(address indexed owner, address indexed spender, uint256 value); 16 | } -------------------------------------------------------------------------------- /typings/contracts/index.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { 5 | BigNumberish, 6 | EventDescription, 7 | FunctionDescription 8 | } from "ethers/utils"; 9 | 10 | export class TransactionOverrides { 11 | nonce?: BigNumberish | Promise; 12 | gasLimit?: BigNumberish | Promise; 13 | gasPrice?: BigNumberish | Promise; 14 | value?: BigNumberish | Promise; 15 | chainId?: number | Promise; 16 | } 17 | 18 | export interface TypedEventDescription< 19 | T extends Pick 20 | > extends EventDescription { 21 | encodeTopics: T["encodeTopics"]; 22 | } 23 | 24 | export interface TypedFunctionDescription< 25 | T extends Pick 26 | > extends FunctionDescription { 27 | encode: T["encode"]; 28 | } 29 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "allowSyntheticDefaultImports": true, 8 | "resolveJsonModule": true, 9 | "downlevelIteration": true, 10 | "importHelpers": true, 11 | "removeComments": false, 12 | 13 | "strictNullChecks": true, 14 | "noImplicitUseStrict": true, 15 | "noImplicitAny": false, 16 | "noImplicitReturns": true, 17 | "noImplicitThis": true, 18 | "noUnusedParameters": false, 19 | "noErrorTruncation": true, 20 | "esModuleInterop": true, 21 | 22 | "experimentalDecorators": true, 23 | "forceConsistentCasingInFileNames": true, 24 | "allowJs": false, 25 | "checkJs": false, 26 | 27 | "baseUrl": ".", 28 | "outDir": "build", 29 | "lib": ["es2017", "dom"], 30 | 31 | "typeRoots": [ 32 | "./node_modules/@types" 33 | ] 34 | 35 | }, 36 | 37 | "include": [ 38 | "typings", "src" 39 | ], 40 | 41 | "exclude": [ 42 | "node_modules", 43 | "dist" 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // See 3 | // to customize your Truffle configuration! 4 | 5 | networks: { 6 | ganache: { 7 | network_id: 127001, 8 | host: "127.0.0.1", 9 | port: 8545 10 | }, 11 | coverage: { 12 | host: "localhost", 13 | network_id: "*", 14 | port: 8545, // <-- If you change this, also set the port option in .solcover.js. 15 | gas: 0xfffffffffff, // <-- Use this high gas value 16 | gasPrice: 0x0000000000000001 // <-- Use this low gas price 17 | }, 18 | }, 19 | 20 | compilers: { 21 | solc: { 22 | version: "./node_modules/solc" 23 | } 24 | }, 25 | solc: { 26 | optimizer: { 27 | enabled: true, // TO TURN ON for launch 28 | runs: 500, 29 | details: { 30 | yul: true 31 | } 32 | } 33 | }, 34 | 35 | mocha: { 36 | reporter: "eth-gas-reporter", 37 | reporterOptions: { 38 | currency: "USD", 39 | gasPrice: 10, 40 | showTimeSpent: true 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /typings/txTypes.d.ts: -------------------------------------------------------------------------------- 1 | import { Wallet } from 'ethers' 2 | import { BigNumber } from 'ethers/utils' 3 | 4 | export type GasReceipt = { 5 | gasLimit: number | string | BigNumber; 6 | baseGas: number | string | BigNumber; 7 | gasPrice: number | string | BigNumber; 8 | feeRecipient: string; 9 | feeTokenData: string | Uint8Array; 10 | }; 11 | 12 | export type TransferSignature = { 13 | contractAddress: string; 14 | signerWallet: Wallet; 15 | receiver: string; 16 | id: number | string | BigNumber; 17 | amount: number | string | BigNumber; 18 | transferData: Uint8Array | null; 19 | nonce: number | string | BigNumber; 20 | } 21 | 22 | export type BatchTransferSignature = { 23 | contractAddress: string; 24 | signerWallet: Wallet; 25 | receiver: string; 26 | ids: number[] | string[] | BigNumber[]; 27 | amounts: number[] | string[] | BigNumber[]; 28 | transferData: Uint8Array | null; 29 | nonce: number | string | BigNumber; 30 | } 31 | 32 | 33 | export type ApprovalSignature = { 34 | contractAddress: string; 35 | signerWallet: Wallet; 36 | operator: string; 37 | approved: boolean; 38 | nonce: number | string | BigNumber; 39 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-present https://github.com/horizon-games 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /typings/contracts/LibEIP712.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface LibEIP712Interface extends Interface { 14 | functions: {}; 15 | 16 | events: {}; 17 | } 18 | 19 | export class LibEIP712 extends Contract { 20 | connect(signerOrProvider: Signer | Provider | string): LibEIP712; 21 | attach(addressOrName: string): LibEIP712; 22 | deployed(): Promise; 23 | 24 | on(event: EventFilter | string, listener: Listener): LibEIP712; 25 | once(event: EventFilter | string, listener: Listener): LibEIP712; 26 | addListener(eventName: EventFilter | string, listener: Listener): LibEIP712; 27 | removeAllListeners(eventName: EventFilter | string): LibEIP712; 28 | removeListener(eventName: any, listener: Listener): LibEIP712; 29 | 30 | interface: LibEIP712Interface; 31 | 32 | functions: {}; 33 | 34 | filters: {}; 35 | 36 | estimate: {}; 37 | } 38 | -------------------------------------------------------------------------------- /typings/contracts/IERC165.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface IERC165Interface extends Interface { 14 | functions: {}; 15 | 16 | events: {}; 17 | } 18 | 19 | export class IERC165 extends Contract { 20 | connect(signerOrProvider: Signer | Provider | string): IERC165; 21 | attach(addressOrName: string): IERC165; 22 | deployed(): Promise; 23 | 24 | on(event: EventFilter | string, listener: Listener): IERC165; 25 | once(event: EventFilter | string, listener: Listener): IERC165; 26 | addListener(eventName: EventFilter | string, listener: Listener): IERC165; 27 | removeAllListeners(eventName: EventFilter | string): IERC165; 28 | removeListener(eventName: any, listener: Listener): IERC165; 29 | 30 | interface: IERC165Interface; 31 | 32 | functions: { 33 | supportsInterface(_interfaceId: Arrayish): Promise; 34 | }; 35 | 36 | filters: {}; 37 | 38 | estimate: {}; 39 | } 40 | -------------------------------------------------------------------------------- /typings/contracts/IERC1271Wallet.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface IERC1271WalletInterface extends Interface { 14 | functions: {}; 15 | 16 | events: {}; 17 | } 18 | 19 | export class IERC1271Wallet extends Contract { 20 | connect(signerOrProvider: Signer | Provider | string): IERC1271Wallet; 21 | attach(addressOrName: string): IERC1271Wallet; 22 | deployed(): Promise; 23 | 24 | on(event: EventFilter | string, listener: Listener): IERC1271Wallet; 25 | once(event: EventFilter | string, listener: Listener): IERC1271Wallet; 26 | addListener( 27 | eventName: EventFilter | string, 28 | listener: Listener 29 | ): IERC1271Wallet; 30 | removeAllListeners(eventName: EventFilter | string): IERC1271Wallet; 31 | removeListener(eventName: any, listener: Listener): IERC1271Wallet; 32 | 33 | interface: IERC1271WalletInterface; 34 | 35 | functions: { 36 | isValidSignature(_hash: Arrayish, _signature: Arrayish): Promise; 37 | }; 38 | 39 | filters: {}; 40 | 41 | estimate: {}; 42 | } 43 | -------------------------------------------------------------------------------- /contracts/utils/Ownable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | 3 | 4 | /** 5 | * @title Ownable 6 | * @dev The Ownable contract has an owner address, and provides basic authorization control 7 | * functions, this simplifies the implementation of "user permissions". 8 | */ 9 | contract Ownable { 10 | address private owner; 11 | 12 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 13 | 14 | /** 15 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender 16 | * account. 17 | */ 18 | constructor () internal { 19 | owner = msg.sender; 20 | emit OwnershipTransferred(address(0), owner); 21 | } 22 | 23 | /** 24 | * @dev Throws if called by any account other than the owner. 25 | */ 26 | modifier onlyOwner() { 27 | require(msg.sender == owner, "Ownable#onlyOwner: SENDER_IS_NOT_OWNER"); 28 | _; 29 | } 30 | 31 | /** 32 | * @notice Transfers the ownership of the contract to new address 33 | * @param _newOwner Address of the new owner 34 | */ 35 | function transferOwnership(address _newOwner) public onlyOwner { 36 | require(_newOwner != address(0), "Ownable#transferOwnership: INVALID_ADDRESS"); 37 | emit OwnershipTransferred(owner, _newOwner); 38 | owner = _newOwner; 39 | } 40 | 41 | /** 42 | * @notice Returns the address of the owner. 43 | */ 44 | function getOwner() public view returns (address) { 45 | return owner; 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /typings/contracts/SignatureValidator.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface SignatureValidatorInterface extends Interface { 14 | functions: {}; 15 | 16 | events: {}; 17 | } 18 | 19 | export class SignatureValidator extends Contract { 20 | connect(signerOrProvider: Signer | Provider | string): SignatureValidator; 21 | attach(addressOrName: string): SignatureValidator; 22 | deployed(): Promise; 23 | 24 | on(event: EventFilter | string, listener: Listener): SignatureValidator; 25 | once(event: EventFilter | string, listener: Listener): SignatureValidator; 26 | addListener( 27 | eventName: EventFilter | string, 28 | listener: Listener 29 | ): SignatureValidator; 30 | removeAllListeners(eventName: EventFilter | string): SignatureValidator; 31 | removeListener(eventName: any, listener: Listener): SignatureValidator; 32 | 33 | interface: SignatureValidatorInterface; 34 | 35 | functions: { 36 | isValidSignature( 37 | _signerAddress: string, 38 | _hash: Arrayish, 39 | _data: Arrayish, 40 | _sig: Arrayish 41 | ): Promise; 42 | }; 43 | 44 | filters: {}; 45 | 46 | estimate: {}; 47 | } 48 | -------------------------------------------------------------------------------- /typings/contracts/ERC1155Metadata.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface ERC1155MetadataInterface extends Interface { 14 | functions: {}; 15 | 16 | events: { 17 | URI: TypedEventDescription<{ 18 | encodeTopics([_uri, _id]: [null, BigNumberish | null]): string[]; 19 | }>; 20 | }; 21 | } 22 | 23 | export class ERC1155Metadata extends Contract { 24 | connect(signerOrProvider: Signer | Provider | string): ERC1155Metadata; 25 | attach(addressOrName: string): ERC1155Metadata; 26 | deployed(): Promise; 27 | 28 | on(event: EventFilter | string, listener: Listener): ERC1155Metadata; 29 | once(event: EventFilter | string, listener: Listener): ERC1155Metadata; 30 | addListener( 31 | eventName: EventFilter | string, 32 | listener: Listener 33 | ): ERC1155Metadata; 34 | removeAllListeners(eventName: EventFilter | string): ERC1155Metadata; 35 | removeListener(eventName: any, listener: Listener): ERC1155Metadata; 36 | 37 | interface: ERC1155MetadataInterface; 38 | 39 | functions: { 40 | uri(_id: BigNumberish): Promise; 41 | }; 42 | 43 | filters: { 44 | URI(_uri: null, _id: BigNumberish | null): EventFilter; 45 | }; 46 | 47 | estimate: {}; 48 | } 49 | -------------------------------------------------------------------------------- /contracts/mocks/ERC1155MetadataMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | pragma experimental ABIEncoderV2; 3 | 4 | import "../tokens/ERC1155/ERC1155Metadata.sol"; 5 | 6 | 7 | contract ERC1155MetadataMock is ERC1155Metadata { 8 | 9 | /***********************************| 10 | | Base URI Functions | 11 | |__________________________________*/ 12 | 13 | /** 14 | * @notice Will update the base URL of token's URI 15 | * @param _newBaseMetadataURI New base URL of token's URI 16 | */ 17 | function setBaseMetadataURI(string memory _newBaseMetadataURI) public { 18 | super._setBaseMetadataURI(_newBaseMetadataURI); 19 | } 20 | 21 | 22 | /***********************************| 23 | | Log URI Functions | 24 | |__________________________________*/ 25 | 26 | /** 27 | * @notice Will emit default URI log event for corresponding token _id 28 | * @param _tokenIDs Array of IDs of tokens to log default URI 29 | */ 30 | function logURIsMock(uint256[] memory _tokenIDs) public { 31 | super._logURIs(_tokenIDs); 32 | } 33 | 34 | /** 35 | * @notice Will emit a specific URI log event for corresponding token 36 | * @param _tokenIDs IDs of the token corresponding to the _uris logged 37 | * @param _URIs The URIs of the specified _tokenIDs 38 | */ 39 | function logURIsMock2(uint256[] memory _tokenIDs, string[] memory _URIs) public { 40 | super._logURIs(_tokenIDs, _URIs); 41 | } 42 | 43 | 44 | /***********************************| 45 | | Unsupported Functions | 46 | |__________________________________*/ 47 | 48 | function () external { 49 | revert('ERC1155MetadataMock: INVALID_METHOD'); 50 | } 51 | } -------------------------------------------------------------------------------- /contracts/interfaces/IERC1271Wallet.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | 3 | 4 | interface IERC1271Wallet { 5 | 6 | /** 7 | * @notice Verifies whether the provided signature is valid with respect to the provided data 8 | * @dev MUST return the correct magic value if the signature provided is valid for the provided data 9 | * > The bytes4 magic value to return when signature is valid is 0x20c13b0b : bytes4(keccak256("isValidSignature(bytes,bytes)") 10 | * > This function MAY modify Ethereum's state 11 | * @param _data Arbitrary length data signed on the behalf of address(this) 12 | * @param _signature Signature byte array associated with _data 13 | * @return Magic value 0x20c13b0b if the signature is valid and 0x0 otherwise 14 | * 15 | */ 16 | function isValidSignature( 17 | bytes calldata _data, 18 | bytes calldata _signature) 19 | external 20 | view 21 | returns (bytes4 magicValue); 22 | 23 | /** 24 | * @notice Verifies whether the provided signature is valid with respect to the provided hash 25 | * @dev MUST return the correct magic value if the signature provided is valid for the provided hash 26 | * > The bytes4 magic value to return when signature is valid is 0x20c13b0b : bytes4(keccak256("isValidSignature(bytes,bytes)") 27 | * > This function MAY modify Ethereum's state 28 | * @param _hash keccak256 hash that was signed 29 | * @param _signature Signature byte array associated with _data 30 | * @return Magic value 0x20c13b0b if the signature is valid and 0x0 otherwise 31 | */ 32 | function isValidSignature( 33 | bytes32 _hash, 34 | bytes calldata _signature) 35 | external 36 | view 37 | returns (bytes4 magicValue); 38 | } -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "warning", 3 | "rules": { 4 | "class-name": true, 5 | "comment-format": [ 6 | false, 7 | "check-space" 8 | ], 9 | "curly": false, 10 | "indent": [true, "spaces", 2], 11 | "interface-name": false, 12 | "jsdoc-format": true, 13 | "no-consecutive-blank-lines": false, 14 | "no-debugger": true, 15 | "no-duplicate-variable": true, 16 | "no-eval": true, 17 | "no-internal-module": true, 18 | "no-trailing-whitespace": false, 19 | "no-shadowed-variable": false, 20 | "no-switch-case-fall-through": true, 21 | "no-unused-expression": false, 22 | "no-use-before-declare": false, 23 | "no-var-keyword": true, 24 | "import-name": false, 25 | "jsx-no-multiline-js": false, 26 | "jsx-no-lambda": false, 27 | "one-line": [ 28 | true, 29 | "check-open-brace", 30 | "check-whitespace", 31 | "check-catch" 32 | ], 33 | "quotemark": [ 34 | true, 35 | "single", 36 | "jsx-double" 37 | ], 38 | "semicolon": [true, "never"], 39 | "trailing-comma": [ 40 | true, 41 | { 42 | "multiline": "never", 43 | "singleline": "never" 44 | } 45 | ], 46 | "triple-equals": [ 47 | true, 48 | "allow-null-check" 49 | ], 50 | "typedef-whitespace": [ 51 | true, 52 | { 53 | "call-signature": "nospace", 54 | "index-signature": "nospace", 55 | "parameter": "nospace", 56 | "property-declaration": "nospace", 57 | "variable-declaration": "nospace" 58 | } 59 | ], 60 | "variable-name": [ 61 | true, 62 | "ban-keywords" 63 | ], 64 | "whitespace": [ 65 | true, 66 | "check-branch", 67 | "check-decl", 68 | "check-separator", 69 | "check-type" 70 | ] 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /contracts/utils/Address.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 ZeroEx Intl. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | pragma solidity ^0.5.12; 15 | 16 | 17 | /** 18 | * Utility library of inline functions on addresses 19 | */ 20 | library Address { 21 | 22 | /** 23 | * Returns whether the target address is a contract 24 | * @dev This function will return false if invoked during the constructor of a contract, 25 | * as the code is not actually created until after the constructor finishes. 26 | * @param account address of the account to check 27 | * @return whether the target address is a contract 28 | */ 29 | function isContract(address account) internal view returns (bool) { 30 | bytes32 codehash; 31 | bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; 32 | 33 | // XXX Currently there is no better way to check if there is a contract in an address 34 | // than to check the size of the code at that address. 35 | // See https://ethereum.stackexchange.com/a/14016/36603 36 | // for more details about how this works. 37 | // TODO Check this again before the Serenity release, because all addresses will be 38 | // contracts then. 39 | assembly { codehash := extcodehash(account) } 40 | return (codehash != 0x0 && codehash != accountHash); 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /typings/contracts/ERC1271WalletMock.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface ERC1271WalletMockInterface extends Interface { 14 | functions: { 15 | setShouldReject: TypedFunctionDescription<{ 16 | encode([_value]: [boolean]): string; 17 | }>; 18 | }; 19 | 20 | events: {}; 21 | } 22 | 23 | export class ERC1271WalletMock extends Contract { 24 | connect(signerOrProvider: Signer | Provider | string): ERC1271WalletMock; 25 | attach(addressOrName: string): ERC1271WalletMock; 26 | deployed(): Promise; 27 | 28 | on(event: EventFilter | string, listener: Listener): ERC1271WalletMock; 29 | once(event: EventFilter | string, listener: Listener): ERC1271WalletMock; 30 | addListener( 31 | eventName: EventFilter | string, 32 | listener: Listener 33 | ): ERC1271WalletMock; 34 | removeAllListeners(eventName: EventFilter | string): ERC1271WalletMock; 35 | removeListener(eventName: any, listener: Listener): ERC1271WalletMock; 36 | 37 | interface: ERC1271WalletMockInterface; 38 | 39 | functions: { 40 | isValidSignature(_hash: Arrayish, _signature: Arrayish): Promise; 41 | 42 | setShouldReject( 43 | _value: boolean, 44 | overrides?: TransactionOverrides 45 | ): Promise; 46 | 47 | ERC1271_INVALID(): Promise; 48 | ERC1271_MAGIC_VAL(): Promise; 49 | shouldReject(): Promise; 50 | }; 51 | 52 | filters: {}; 53 | 54 | estimate: { 55 | setShouldReject(_value: boolean): Promise; 56 | }; 57 | } 58 | -------------------------------------------------------------------------------- /typings/contracts/Ownable.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface OwnableInterface extends Interface { 14 | functions: { 15 | transferOwnership: TypedFunctionDescription<{ 16 | encode([_newOwner]: [string]): string; 17 | }>; 18 | }; 19 | 20 | events: { 21 | OwnershipTransferred: TypedEventDescription<{ 22 | encodeTopics([previousOwner, newOwner]: [ 23 | string | null, 24 | string | null 25 | ]): string[]; 26 | }>; 27 | }; 28 | } 29 | 30 | export class Ownable extends Contract { 31 | connect(signerOrProvider: Signer | Provider | string): Ownable; 32 | attach(addressOrName: string): Ownable; 33 | deployed(): Promise; 34 | 35 | on(event: EventFilter | string, listener: Listener): Ownable; 36 | once(event: EventFilter | string, listener: Listener): Ownable; 37 | addListener(eventName: EventFilter | string, listener: Listener): Ownable; 38 | removeAllListeners(eventName: EventFilter | string): Ownable; 39 | removeListener(eventName: any, listener: Listener): Ownable; 40 | 41 | interface: OwnableInterface; 42 | 43 | functions: { 44 | transferOwnership( 45 | _newOwner: string, 46 | overrides?: TransactionOverrides 47 | ): Promise; 48 | 49 | getOwner(): Promise; 50 | }; 51 | 52 | filters: { 53 | OwnershipTransferred( 54 | previousOwner: string | null, 55 | newOwner: string | null 56 | ): EventFilter; 57 | }; 58 | 59 | estimate: { 60 | transferOwnership(_newOwner: string): Promise; 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /contracts/mocks/ERC1271WalletMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | 3 | import "../interfaces/IERC1271Wallet.sol"; 4 | 5 | 6 | // Contract to test safe transfer behavior. 7 | contract ERC1271WalletMock is IERC1271Wallet { 8 | bytes4 constant public ERC1271_MAGIC_VAL = 0x20c13b0b; 9 | bytes4 constant public ERC1271_INVALID = 0x0; 10 | 11 | // Keep values from last received contract. 12 | bool public shouldReject; 13 | 14 | // Set rejection to true by default 15 | constructor () public { 16 | shouldReject = true; 17 | } 18 | 19 | function setShouldReject(bool _value) public { 20 | shouldReject = _value; 21 | } 22 | 23 | /** 24 | * @dev Should return whether the signature provided is valid for the provided data 25 | * @param _data Arbitrary length data signed on the behalf of address(this) 26 | * @param _signature Signature byte array associated with _data 27 | * 28 | * MUST return the bytes4 magic value 0x20c13b0b when function passes. 29 | * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5) 30 | */ 31 | function isValidSignature( 32 | bytes calldata _data, 33 | bytes calldata _signature) 34 | external 35 | view 36 | returns (bytes4 magicValue) 37 | { 38 | magicValue = shouldReject ? ERC1271_INVALID : ERC1271_MAGIC_VAL; 39 | return magicValue; 40 | } 41 | 42 | 43 | /** 44 | * @dev Should return whether the signature provided is valid for the provided hash 45 | * @param _hash keccak256 hash that was signed 46 | * @param _signature Signature byte array associated with _data 47 | * 48 | * MUST return the bytes4 magic value 0x20c13b0b when function passes. 49 | * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5) 50 | */ 51 | function isValidSignature( 52 | bytes32 _hash, 53 | bytes calldata _signature) 54 | external 55 | view 56 | returns (bytes4 magicValue) 57 | { 58 | magicValue = shouldReject ? ERC1271_INVALID : ERC1271_MAGIC_VAL; 59 | return magicValue; 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /contracts/utils/SafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | 3 | 4 | /** 5 | * @title SafeMath 6 | * @dev Unsigned math operations with safety checks that revert on error 7 | */ 8 | library SafeMath { 9 | 10 | /** 11 | * @dev Multiplies two unsigned integers, reverts on overflow. 12 | */ 13 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 14 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 15 | // benefit is lost if 'b' is also tested. 16 | // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 17 | if (a == 0) { 18 | return 0; 19 | } 20 | 21 | uint256 c = a * b; 22 | require(c / a == b, "SafeMath#mul: OVERFLOW"); 23 | 24 | return c; 25 | } 26 | 27 | /** 28 | * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero. 29 | */ 30 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 31 | // Solidity only automatically asserts when dividing by 0 32 | require(b > 0, "SafeMath#div: DIVISION_BY_ZERO"); 33 | uint256 c = a / b; 34 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 35 | 36 | return c; 37 | } 38 | 39 | /** 40 | * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend). 41 | */ 42 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 43 | require(b <= a, "SafeMath#sub: UNDERFLOW"); 44 | uint256 c = a - b; 45 | 46 | return c; 47 | } 48 | 49 | /** 50 | * @dev Adds two unsigned integers, reverts on overflow. 51 | */ 52 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 53 | uint256 c = a + b; 54 | require(c >= a, "SafeMath#add: OVERFLOW"); 55 | 56 | return c; 57 | } 58 | 59 | /** 60 | * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo), 61 | * reverts when dividing by zero. 62 | */ 63 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 64 | require(b != 0, "SafeMath#mod: DIVISION_BY_ZERO"); 65 | return a % b; 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /contracts/mocks/ERC1155MetaMintBurnMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | pragma experimental ABIEncoderV2; 3 | 4 | import "../tokens/ERC1155/ERC1155Meta.sol"; 5 | import "../tokens/ERC1155/ERC1155MintBurn.sol"; 6 | import "../tokens/ERC1155/ERC1155Metadata.sol"; 7 | 8 | 9 | contract ERC1155MetaMintBurnMock is ERC1155Meta, ERC1155MintBurn, ERC1155Metadata { 10 | 11 | constructor() public { } 12 | 13 | // ---- Minting functions 14 | 15 | /** 16 | * @dev Mint _value of tokens of a given id 17 | * @param _to The address to mint tokens to. 18 | * @param _id token id to mint 19 | * @param _value The amount to be minted 20 | * @param _data Data to be passed if receiver is contract 21 | */ 22 | function mintMock(address _to, uint256 _id, uint256 _value, bytes memory _data) 23 | public 24 | { 25 | super._mint(_to, _id, _value, _data); 26 | } 27 | 28 | /** 29 | * @dev Mint tokens for each ids in _ids 30 | * @param _to The address to mint tokens to. 31 | * @param _ids Array of ids to mint 32 | * @param _values Array of amount of tokens to mint per id 33 | * @param _data Data to be passed if receiver is contract 34 | */ 35 | function batchMintMock(address _to, uint256[] memory _ids, uint256[] memory _values, bytes memory _data) 36 | public 37 | { 38 | super._batchMint(_to, _ids, _values, _data); 39 | } 40 | 41 | // ---- Burning functions 42 | 43 | /** 44 | * @dev burn _value of tokens of a given token id 45 | * @param _from The address to burn tokens from. 46 | * @param _id token id to burn 47 | * @param _value The amount to be burned 48 | */ 49 | function burnMock(address _from, uint256 _id, uint256 _value) 50 | public 51 | { 52 | super._burn(_from, _id, _value); 53 | } 54 | 55 | /** 56 | * @dev burn _value of tokens of a given token id 57 | * @param _from The address to burn tokens from. 58 | * @param _ids Array of token ids to burn 59 | * @param _values Array of the amount to be burned 60 | */ 61 | function batchBurnMock(address _from, uint256[] memory _ids, uint256[] memory _values) 62 | public 63 | { 64 | super._batchBurn(_from, _ids, _values); 65 | } 66 | 67 | /***********************************| 68 | | Unsupported Functions | 69 | |__________________________________*/ 70 | 71 | function () external { 72 | revert("ERC1155MetaMintBurnMock: INVALID_METHOD"); 73 | } 74 | } -------------------------------------------------------------------------------- /contracts/mocks/ERC1155MetaMintBurnPackedBalanceMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | pragma experimental ABIEncoderV2; 3 | 4 | import "../tokens/ERC1155PackedBalance/ERC1155MetaPackedBalance.sol"; 5 | import "../tokens/ERC1155PackedBalance/ERC1155MintBurnPackedBalance.sol"; 6 | 7 | 8 | contract ERC1155MetaMintBurnPackedBalanceMock is ERC1155MintBurnPackedBalance, ERC1155MetaPackedBalance { 9 | 10 | constructor() public {} 11 | 12 | // ---- Minting functions 13 | 14 | /** 15 | * @dev Mint _value of tokens of a given id 16 | * @param _to The address to mint tokens to. 17 | * @param _id token id to mint 18 | * @param _value The amount to be minted 19 | * @param _data Data to be passed if receiver is contract 20 | */ 21 | function mintMock(address _to, uint256 _id, uint256 _value, bytes memory _data) 22 | public 23 | { 24 | _mint(_to, _id, _value, _data); 25 | } 26 | 27 | /** 28 | * @dev Mint tokens for each ids in _ids 29 | * @param _to The address to mint tokens to. 30 | * @param _ids Array of ids to mint 31 | * @param _values Array of amount of tokens to mint per id 32 | * @param _data Data to be passed if receiver is contract 33 | */ 34 | function batchMintMock(address _to, uint256[] memory _ids, uint256[] memory _values, bytes memory _data) 35 | public 36 | { 37 | _batchMint(_to, _ids, _values, _data); 38 | } 39 | 40 | // ---- Burning functions 41 | 42 | /** 43 | * @dev burn _value of tokens of a given token id 44 | * @param _from The address to burn tokens from. 45 | * @param _id token id to burn 46 | * @param _value The amount to be burned 47 | */ 48 | function burnMock(address _from, uint256 _id, uint256 _value) 49 | public 50 | { 51 | _burn(_from, _id, _value); 52 | } 53 | 54 | /** 55 | * @dev burn _value of tokens of a given token id 56 | * @param _from The address to burn tokens from. 57 | * @param _ids Array of token ids to burn 58 | * @param _values Array of the amount to be burned 59 | */ 60 | function batchBurnMock(address _from, uint256[] memory _ids, uint256[] memory _values) 61 | public 62 | { 63 | _batchBurn(_from, _ids, _values); 64 | } 65 | 66 | /***********************************| 67 | | Unsupported Functions | 68 | |__________________________________*/ 69 | 70 | function () external { 71 | revert('ERC1155MetaMintBurnPackedBalanceMock: INVALID_METHOD'); 72 | } 73 | 74 | } -------------------------------------------------------------------------------- /typings/contracts/OwnableMock.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface OwnableMockInterface extends Interface { 14 | functions: { 15 | transferOwnership: TypedFunctionDescription<{ 16 | encode([_newOwner]: [string]): string; 17 | }>; 18 | 19 | ownerCall: TypedFunctionDescription<{ encode([]: []): string }>; 20 | 21 | nonOwnerCall: TypedFunctionDescription<{ encode([]: []): string }>; 22 | }; 23 | 24 | events: { 25 | OwnershipTransferred: TypedEventDescription<{ 26 | encodeTopics([previousOwner, newOwner]: [ 27 | string | null, 28 | string | null 29 | ]): string[]; 30 | }>; 31 | }; 32 | } 33 | 34 | export class OwnableMock extends Contract { 35 | connect(signerOrProvider: Signer | Provider | string): OwnableMock; 36 | attach(addressOrName: string): OwnableMock; 37 | deployed(): Promise; 38 | 39 | on(event: EventFilter | string, listener: Listener): OwnableMock; 40 | once(event: EventFilter | string, listener: Listener): OwnableMock; 41 | addListener(eventName: EventFilter | string, listener: Listener): OwnableMock; 42 | removeAllListeners(eventName: EventFilter | string): OwnableMock; 43 | removeListener(eventName: any, listener: Listener): OwnableMock; 44 | 45 | interface: OwnableMockInterface; 46 | 47 | functions: { 48 | transferOwnership( 49 | _newOwner: string, 50 | overrides?: TransactionOverrides 51 | ): Promise; 52 | 53 | ownerCall(overrides?: TransactionOverrides): Promise; 54 | 55 | nonOwnerCall( 56 | overrides?: TransactionOverrides 57 | ): Promise; 58 | 59 | getOwner(): Promise; 60 | }; 61 | 62 | filters: { 63 | OwnershipTransferred( 64 | previousOwner: string | null, 65 | newOwner: string | null 66 | ): EventFilter; 67 | }; 68 | 69 | estimate: { 70 | transferOwnership(_newOwner: string): Promise; 71 | 72 | ownerCall(): Promise; 73 | 74 | nonOwnerCall(): Promise; 75 | }; 76 | } 77 | -------------------------------------------------------------------------------- /contracts/utils/LibEIP712.sol: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 ZeroEx Intl. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | pragma solidity ^0.5.12; 14 | 15 | 16 | contract LibEIP712 { 17 | 18 | // keccak256( 19 | // "EIP712Domain(address verifyingContract)" 20 | // ); 21 | bytes32 internal constant DOMAIN_SEPARATOR_TYPEHASH = 0x035aff83d86937d35b32e04f0ddc6ff469290eef2f1b692d8a815c89404d4749; 22 | 23 | // Domain seperator created in constructor 24 | bytes32 internal EIP712_DOMAIN_HASH; 25 | 26 | // Instantiate EIP712_DOMAIN_HASH 27 | constructor () 28 | public 29 | { 30 | EIP712_DOMAIN_HASH = keccak256(abi.encodePacked(DOMAIN_SEPARATOR_TYPEHASH, address(this))); 31 | } 32 | 33 | /** 34 | * @dev Calculates EIP712 encoding for a hash struct in this EIP712 Domain. 35 | * @param hashStruct The EIP712 hash struct. 36 | * @return EIP712 hash applied to this EIP712 Domain. 37 | */ 38 | function hashEIP712Message(bytes32 hashStruct) 39 | internal 40 | view 41 | returns (bytes32 result) 42 | { 43 | 44 | return keccak256( 45 | abi.encodePacked( 46 | bytes32(0x1901000000000000000000000000000000000000000000000000000000000000), 47 | EIP712_DOMAIN_HASH, 48 | hashStruct 49 | )); 50 | 51 | //bytes32 eip712DomainHash = EIP712_DOMAIN_HASH; 52 | // Assembly for more efficient computing: 53 | // assembly { 54 | // // Load free memory pointer 55 | // let memPtr := mload(64) 56 | 57 | // mstore(memPtr, 0x1901000000000000000000000000000000000000000000000000000000000000) // EIP191 header 58 | // mstore(add(memPtr, 2), eip712DomainHash) // EIP712 domain hash 59 | // mstore(add(memPtr, 34), hashStruct) // Hash of struct 60 | 61 | // // Compute hash 62 | // result := keccak256(memPtr, 66) 63 | // } 64 | // return result; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /contracts/utils/LibBytes.sol: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 ZeroEx Intl. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | This is a truncated version of the original LibBytes.sol library from ZeroEx. 13 | */ 14 | 15 | pragma solidity ^0.5.12; 16 | 17 | 18 | library LibBytes { 19 | using LibBytes for bytes; 20 | 21 | 22 | /***********************************| 23 | | Pop Bytes Functions | 24 | |__________________________________*/ 25 | 26 | /** 27 | * @dev Pops the last byte off of a byte array by modifying its length. 28 | * @param b Byte array that will be modified. 29 | * @return The byte that was popped off. 30 | */ 31 | function popLastByte(bytes memory b) 32 | internal 33 | pure 34 | returns (bytes1 result) 35 | { 36 | require( 37 | b.length > 0, 38 | "LibBytes#popLastByte: GREATER_THAN_ZERO_LENGTH_REQUIRED" 39 | ); 40 | 41 | // Store last byte. 42 | result = b[b.length - 1]; 43 | 44 | assembly { 45 | // Decrement length of byte array. 46 | let newLen := sub(mload(b), 1) 47 | mstore(b, newLen) 48 | } 49 | return result; 50 | } 51 | 52 | 53 | /***********************************| 54 | | Read Bytes Functions | 55 | |__________________________________*/ 56 | 57 | /** 58 | * @dev Reads a bytes32 value from a position in a byte array. 59 | * @param b Byte array containing a bytes32 value. 60 | * @param index Index in byte array of bytes32 value. 61 | * @return bytes32 value from byte array. 62 | */ 63 | function readBytes32( 64 | bytes memory b, 65 | uint256 index 66 | ) 67 | internal 68 | pure 69 | returns (bytes32 result) 70 | { 71 | require( 72 | b.length >= index + 32, 73 | "LibBytes#readBytes32: GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED" 74 | ); 75 | 76 | // Arrays are prefixed by a 256 bit length parameter 77 | index += 32; 78 | 79 | // Read the bytes32 from array memory 80 | assembly { 81 | result := mload(add(b, index)) 82 | } 83 | return result; 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /typings/contracts/ERC1155MetadataMock.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface ERC1155MetadataMockInterface extends Interface { 14 | functions: { 15 | setBaseMetadataURI: TypedFunctionDescription<{ 16 | encode([_newBaseMetadataURI]: [string]): string; 17 | }>; 18 | 19 | logURIsMock: TypedFunctionDescription<{ 20 | encode([_tokenIDs]: [(BigNumberish)[]]): string; 21 | }>; 22 | 23 | logURIsMock2: TypedFunctionDescription<{ 24 | encode([_tokenIDs, _URIs]: [(BigNumberish)[], (string)[]]): string; 25 | }>; 26 | }; 27 | 28 | events: { 29 | URI: TypedEventDescription<{ 30 | encodeTopics([_uri, _id]: [null, BigNumberish | null]): string[]; 31 | }>; 32 | }; 33 | } 34 | 35 | export class ERC1155MetadataMock extends Contract { 36 | connect(signerOrProvider: Signer | Provider | string): ERC1155MetadataMock; 37 | attach(addressOrName: string): ERC1155MetadataMock; 38 | deployed(): Promise; 39 | 40 | on(event: EventFilter | string, listener: Listener): ERC1155MetadataMock; 41 | once(event: EventFilter | string, listener: Listener): ERC1155MetadataMock; 42 | addListener( 43 | eventName: EventFilter | string, 44 | listener: Listener 45 | ): ERC1155MetadataMock; 46 | removeAllListeners(eventName: EventFilter | string): ERC1155MetadataMock; 47 | removeListener(eventName: any, listener: Listener): ERC1155MetadataMock; 48 | 49 | interface: ERC1155MetadataMockInterface; 50 | 51 | functions: { 52 | uri(_id: BigNumberish): Promise; 53 | 54 | setBaseMetadataURI( 55 | _newBaseMetadataURI: string, 56 | overrides?: TransactionOverrides 57 | ): Promise; 58 | 59 | logURIsMock( 60 | _tokenIDs: (BigNumberish)[], 61 | overrides?: TransactionOverrides 62 | ): Promise; 63 | 64 | logURIsMock2( 65 | _tokenIDs: (BigNumberish)[], 66 | _URIs: (string)[], 67 | overrides?: TransactionOverrides 68 | ): Promise; 69 | }; 70 | 71 | filters: { 72 | URI(_uri: null, _id: BigNumberish | null): EventFilter; 73 | }; 74 | 75 | estimate: { 76 | setBaseMetadataURI(_newBaseMetadataURI: string): Promise; 77 | 78 | logURIsMock(_tokenIDs: (BigNumberish)[]): Promise; 79 | 80 | logURIsMock2( 81 | _tokenIDs: (BigNumberish)[], 82 | _URIs: (string)[] 83 | ): Promise; 84 | }; 85 | } 86 | -------------------------------------------------------------------------------- /typings/contracts/IERC1155TokenReceiver.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface IERC1155TokenReceiverInterface extends Interface { 14 | functions: { 15 | onERC1155Received: TypedFunctionDescription<{ 16 | encode([_operator, _from, _id, _amount, _data]: [ 17 | string, 18 | string, 19 | BigNumberish, 20 | BigNumberish, 21 | Arrayish 22 | ]): string; 23 | }>; 24 | 25 | onERC1155BatchReceived: TypedFunctionDescription<{ 26 | encode([_operator, _from, _ids, _amounts, _data]: [ 27 | string, 28 | string, 29 | (BigNumberish)[], 30 | (BigNumberish)[], 31 | Arrayish 32 | ]): string; 33 | }>; 34 | }; 35 | 36 | events: {}; 37 | } 38 | 39 | export class IERC1155TokenReceiver extends Contract { 40 | connect(signerOrProvider: Signer | Provider | string): IERC1155TokenReceiver; 41 | attach(addressOrName: string): IERC1155TokenReceiver; 42 | deployed(): Promise; 43 | 44 | on(event: EventFilter | string, listener: Listener): IERC1155TokenReceiver; 45 | once(event: EventFilter | string, listener: Listener): IERC1155TokenReceiver; 46 | addListener( 47 | eventName: EventFilter | string, 48 | listener: Listener 49 | ): IERC1155TokenReceiver; 50 | removeAllListeners(eventName: EventFilter | string): IERC1155TokenReceiver; 51 | removeListener(eventName: any, listener: Listener): IERC1155TokenReceiver; 52 | 53 | interface: IERC1155TokenReceiverInterface; 54 | 55 | functions: { 56 | supportsInterface(interfaceID: Arrayish): Promise; 57 | 58 | onERC1155Received( 59 | _operator: string, 60 | _from: string, 61 | _id: BigNumberish, 62 | _amount: BigNumberish, 63 | _data: Arrayish, 64 | overrides?: TransactionOverrides 65 | ): Promise; 66 | 67 | onERC1155BatchReceived( 68 | _operator: string, 69 | _from: string, 70 | _ids: (BigNumberish)[], 71 | _amounts: (BigNumberish)[], 72 | _data: Arrayish, 73 | overrides?: TransactionOverrides 74 | ): Promise; 75 | }; 76 | 77 | filters: {}; 78 | 79 | estimate: { 80 | onERC1155Received( 81 | _operator: string, 82 | _from: string, 83 | _id: BigNumberish, 84 | _amount: BigNumberish, 85 | _data: Arrayish 86 | ): Promise; 87 | 88 | onERC1155BatchReceived( 89 | _operator: string, 90 | _from: string, 91 | _ids: (BigNumberish)[], 92 | _amounts: (BigNumberish)[], 93 | _data: Arrayish 94 | ): Promise; 95 | }; 96 | } 97 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC1155TokenReceiver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | 3 | /** 4 | * @dev ERC-1155 interface for accepting safe transfers. 5 | */ 6 | interface IERC1155TokenReceiver { 7 | 8 | /** 9 | * @notice Handle the receipt of a single ERC1155 token type 10 | * @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeTransferFrom` after the balance has been updated 11 | * This function MAY throw to revert and reject the transfer 12 | * Return of other amount than the magic value MUST result in the transaction being reverted 13 | * Note: The token contract address is always the message sender 14 | * @param _operator The address which called the `safeTransferFrom` function 15 | * @param _from The address which previously owned the token 16 | * @param _id The id of the token being transferred 17 | * @param _amount The amount of tokens being transferred 18 | * @param _data Additional data with no specified format 19 | * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` 20 | */ 21 | function onERC1155Received(address _operator, address _from, uint256 _id, uint256 _amount, bytes calldata _data) external returns(bytes4); 22 | 23 | /** 24 | * @notice Handle the receipt of multiple ERC1155 token types 25 | * @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeBatchTransferFrom` after the balances have been updated 26 | * This function MAY throw to revert and reject the transfer 27 | * Return of other amount than the magic value WILL result in the transaction being reverted 28 | * Note: The token contract address is always the message sender 29 | * @param _operator The address which called the `safeBatchTransferFrom` function 30 | * @param _from The address which previously owned the token 31 | * @param _ids An array containing ids of each token being transferred 32 | * @param _amounts An array containing amounts of each token being transferred 33 | * @param _data Additional data with no specified format 34 | * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` 35 | */ 36 | function onERC1155BatchReceived(address _operator, address _from, uint256[] calldata _ids, uint256[] calldata _amounts, bytes calldata _data) external returns(bytes4); 37 | 38 | /** 39 | * @notice Indicates whether a contract implements the `ERC1155TokenReceiver` functions and so can accept ERC1155 token types. 40 | * @param interfaceID The ERC-165 interface ID that is queried for support.s 41 | * @dev This function MUST return true if it implements the ERC1155TokenReceiver interface and ERC-165 interface. 42 | * This function MUST NOT consume more than 5,000 gas. 43 | * @return Wheter ERC-165 or ERC1155TokenReceiver interfaces are supported. 44 | */ 45 | function supportsInterface(bytes4 interfaceID) external view returns (bool); 46 | 47 | } -------------------------------------------------------------------------------- /contracts/interfaces/IERC1155Meta.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | 3 | interface IERC1155Meta { 4 | 5 | /****************************************| 6 | | Public Meta Transfer Functions | 7 | |_______________________________________*/ 8 | 9 | /** 10 | * @notice Allows anyone with a valid signature to transfer _amount amount of a token _id on the bahalf of _from 11 | * @param _from Source address 12 | * @param _to Target address 13 | * @param _id ID of the token type 14 | * @param _amount Transfered amount 15 | * @param _isGasFee Whether gas is reimbursed to executor or not 16 | * @param _data Encodes a meta transfer indicator, signature, gas payment receipt and extra transfer data 17 | * _data should be encoded as ((bytes32 r, bytes32 s, uint8 v, SignatureType sigType), (GasReceipt g, bytes data)) 18 | * i.e. high level encoding should be (bytes, bytes), where the latter bytes array is a nested bytes array 19 | */ 20 | function metaSafeTransferFrom( 21 | address _from, 22 | address _to, 23 | uint256 _id, 24 | uint256 _amount, 25 | bool _isGasFee, 26 | bytes calldata _data) 27 | external; 28 | 29 | 30 | /** 31 | * @notice Allows anyone with a valid signature to transfer multiple types of tokens on the bahalf of _from 32 | * @param _from Source addresses 33 | * @param _to Target addresses 34 | * @param _ids IDs of each token type 35 | * @param _amounts Transfer amounts per token type 36 | * @param _data Encodes a meta transfer indicator, signature, gas payment receipt and extra transfer data 37 | * _data should be encoded as ((bytes32 r, bytes32 s, uint8 v, SignatureType sigType), (GasReceipt g, bytes data)) 38 | * i.e. high level encoding should be (bytes, bytes), where the latter bytes array is a nested bytes array 39 | */ 40 | function metaSafeBatchTransferFrom( 41 | address _from, 42 | address _to, 43 | uint256[] calldata _ids, 44 | uint256[] calldata _amounts, 45 | bool _isGasFee, 46 | bytes calldata _data) 47 | external; 48 | 49 | 50 | /***********************************| 51 | | Operator Functions | 52 | |__________________________________*/ 53 | 54 | /** 55 | * @notice Approve the passed address to spend on behalf of _from if valid signature is provided 56 | * @param _owner Address that wants to set operator status _spender 57 | * @param _operator Address to add to the set of authorized operators 58 | * @param _approved True if the operator is approved, false to revoke approval 59 | * @param _isGasFee Whether gas will be reimbursed or not, with vlid signature 60 | * @param _data Encodes signature and gas payment receipt 61 | * _data should be encoded as ((bytes32 r, bytes32 s, uint8 v, SignatureType sigType), (GasReceipt g)) 62 | * i.e. high level encoding should be (bytes, bytes), where the latter bytes array is a nested bytes array 63 | */ 64 | function metaSetApprovalForAll( 65 | address _owner, 66 | address _operator, 67 | bool _approved, 68 | bool _isGasFee, 69 | bytes calldata _data) 70 | external; 71 | 72 | } 73 | -------------------------------------------------------------------------------- /typings/contracts/IERC20.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface IERC20Interface extends Interface { 14 | functions: { 15 | transfer: TypedFunctionDescription<{ 16 | encode([to, value]: [string, BigNumberish]): string; 17 | }>; 18 | 19 | approve: TypedFunctionDescription<{ 20 | encode([spender, value]: [string, BigNumberish]): string; 21 | }>; 22 | 23 | transferFrom: TypedFunctionDescription<{ 24 | encode([from, to, value]: [string, string, BigNumberish]): string; 25 | }>; 26 | }; 27 | 28 | events: { 29 | Approval: TypedEventDescription<{ 30 | encodeTopics([owner, spender, value]: [ 31 | string | null, 32 | string | null, 33 | null 34 | ]): string[]; 35 | }>; 36 | 37 | Transfer: TypedEventDescription<{ 38 | encodeTopics([from, to, value]: [ 39 | string | null, 40 | string | null, 41 | null 42 | ]): string[]; 43 | }>; 44 | }; 45 | } 46 | 47 | export class IERC20 extends Contract { 48 | connect(signerOrProvider: Signer | Provider | string): IERC20; 49 | attach(addressOrName: string): IERC20; 50 | deployed(): Promise; 51 | 52 | on(event: EventFilter | string, listener: Listener): IERC20; 53 | once(event: EventFilter | string, listener: Listener): IERC20; 54 | addListener(eventName: EventFilter | string, listener: Listener): IERC20; 55 | removeAllListeners(eventName: EventFilter | string): IERC20; 56 | removeListener(eventName: any, listener: Listener): IERC20; 57 | 58 | interface: IERC20Interface; 59 | 60 | functions: { 61 | balanceOf(who: string): Promise; 62 | 63 | allowance(owner: string, spender: string): Promise; 64 | 65 | transfer( 66 | to: string, 67 | value: BigNumberish, 68 | overrides?: TransactionOverrides 69 | ): Promise; 70 | 71 | approve( 72 | spender: string, 73 | value: BigNumberish, 74 | overrides?: TransactionOverrides 75 | ): Promise; 76 | 77 | transferFrom( 78 | from: string, 79 | to: string, 80 | value: BigNumberish, 81 | overrides?: TransactionOverrides 82 | ): Promise; 83 | 84 | totalSupply(): Promise; 85 | }; 86 | 87 | filters: { 88 | Approval( 89 | owner: string | null, 90 | spender: string | null, 91 | value: null 92 | ): EventFilter; 93 | 94 | Transfer(from: string | null, to: string | null, value: null): EventFilter; 95 | }; 96 | 97 | estimate: { 98 | transfer(to: string, value: BigNumberish): Promise; 99 | 100 | approve(spender: string, value: BigNumberish): Promise; 101 | 102 | transferFrom( 103 | from: string, 104 | to: string, 105 | value: BigNumberish 106 | ): Promise; 107 | }; 108 | } 109 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "multi-token-standard", 3 | "version": "0.8.4", 4 | "description": "ERC1155 Multi-Token Standard implementation for Ethereum", 5 | "repository": "https://github.com/horizon-games/multi-token-standard", 6 | "license": "MIT", 7 | "keywords": [ 8 | "token", 9 | "ERC", 10 | "ERC1155", 11 | "ERC-1155", 12 | "Fungible", 13 | "Non-Fungible", 14 | "ethereum", 15 | "horizongames" 16 | ], 17 | "files": [ 18 | "LICENSE", 19 | "build", 20 | "contracts", 21 | "typings" 22 | ], 23 | "scripts": { 24 | "build": "truffle compile --all && yarn gen:contract-typings && tsc -b", 25 | "clean": "rm -rf build && rm -rf typings/contracts", 26 | "migrate": "truffle migrate --network ganache --reset", 27 | "migrate:rinkeby": "truffle migrate --network rinkeby", 28 | "test": "tsc -b && truffle test --network ganache build/*.spec.js", 29 | "test:benchmark": "tsc -b && truffle test --network ganache build/*.bench.js", 30 | "test:coverage": "solidity-coverage", 31 | "gen:contract-typings": "typechain --target ethers --outDir typings/contracts './build/contracts/*.json'", 32 | "lint": "yarn lint:ts && yarn lint:sol", 33 | "lint:fix": "yarn lint:ts:fix && yarn lint:sol:fix", 34 | "lint:sol": "solium -d .", 35 | "lint:sol:fix": "solium -d contracts/ --fix", 36 | "lint:ts": "tslint -c tslint.json -p .", 37 | "lint:ts:fix": "tslint -c tslint.json -p . --fix", 38 | "ganache": "ganache-cli --networkId ${npm_package_config_ganacheNetworkID} --port ${npm_package_config_ganachePort} --gasLimit ${npm_package_config_ganacheGasLimit} --gasPrice ${npm_package_config_ganacheGasPrice} --defaultBalanceEther ${npm_package_config_etherBalance} --deterministic --mnemonic \"${npm_package_config_mnemonic}\" ${npm_package_config_extra}", 39 | "ganache:verbose": "ganache-cli --networkId ${npm_package_config_ganacheNetworkID} --verbose --port ${npm_package_config_ganachePort} --gasLimit ${npm_package_config_ganacheGasLimit} --gasPrice ${npm_package_config_ganacheGasPrice} --defaultBalanceEther ${npm_package_config_etherBalance} --deterministic --mnemonic \"${npm_package_config_mnemonic}\" ${npm_package_config_extra}", 40 | "ganache:stop": "ps aux | grep ganache-cli | grep -v grep | awk '{print $2}' | xargs kill -9", 41 | "console": "truffle console" 42 | }, 43 | "config": { 44 | "mnemonic": "dose weasel clever culture letter volume endorse used harvest ripple circle install", 45 | "ganacheNetworkID": 127001, 46 | "ganachePort": 8545, 47 | "ganacheGasLimit": "0xfffffffffff", 48 | "ganacheGasPrice": "20000000000", 49 | "etherBalance": "100000", 50 | "extra": "" 51 | }, 52 | "devDependencies": { 53 | "@types/chai-as-promised": "^7.1.0", 54 | "@types/chai-string": "^1.4.1", 55 | "@types/mocha": "^5.2.7", 56 | "chai": "^4.2.0", 57 | "chai-as-promised": "^7.1.1", 58 | "chai-bignumber": "^3.0.0", 59 | "chai-string": "^1.5.0", 60 | "dotenv": "^8.0.0", 61 | "eth-gas-reporter": "^0.2.1", 62 | "ethers": "^4.0.31", 63 | "ganache-cli": "^6.4.4", 64 | "ganache-core": "^2.5.6", 65 | "solc": "0.5.12", 66 | "solidity-coverage": "^0.5.11", 67 | "solium": "^1.2.4", 68 | "truffle": "^5.0.25", 69 | "truffle-contract": "^4.0.22", 70 | "truffle-hdwallet-provider": "1.0.12", 71 | "tslint": "^5.18.0", 72 | "typechain": "^0.3.17", 73 | "typescript": "3.5.2", 74 | "zos-lib": "^2.4.0" 75 | }, 76 | "dependencies": {} 77 | } 78 | -------------------------------------------------------------------------------- /contracts/tokens/ERC1155/ERC1155Metadata.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.11; 2 | import "../../interfaces/IERC1155.sol"; 3 | 4 | 5 | /** 6 | * @notice Contract that handles metadata related methods. 7 | * @dev Methods assume a deterministic generation of URI based on token IDs. 8 | * Methods also assume that URI uses hex representation of token IDs. 9 | */ 10 | contract ERC1155Metadata { 11 | 12 | // URI's default URI prefix 13 | string internal baseMetadataURI; 14 | event URI(string _uri, uint256 indexed _id); 15 | 16 | 17 | /***********************************| 18 | | Metadata Public Function s | 19 | |__________________________________*/ 20 | 21 | /** 22 | * @notice A distinct Uniform Resource Identifier (URI) for a given token. 23 | * @dev URIs are defined in RFC 3986. 24 | * URIs are assumed to be deterministically generated based on token ID 25 | * Token IDs are assumed to be represented in their hex format in URIs 26 | * @return URI string 27 | */ 28 | function uri(uint256 _id) public view returns (string memory) { 29 | return string(abi.encodePacked(baseMetadataURI, _uint2str(_id), ".json")); 30 | } 31 | 32 | 33 | /***********************************| 34 | | Metadata Internal Functions | 35 | |__________________________________*/ 36 | 37 | /** 38 | * @notice Will emit default URI log event for corresponding token _id 39 | * @param _tokenIDs Array of IDs of tokens to log default URI 40 | */ 41 | function _logURIs(uint256[] memory _tokenIDs) internal { 42 | string memory baseURL = baseMetadataURI; 43 | string memory tokenURI; 44 | 45 | for (uint256 i = 0; i < _tokenIDs.length; i++) { 46 | tokenURI = string(abi.encodePacked(baseURL, _uint2str(_tokenIDs[i]), ".json")); 47 | emit URI(tokenURI, _tokenIDs[i]); 48 | } 49 | } 50 | 51 | /** 52 | * @notice Will emit a specific URI log event for corresponding token 53 | * @param _tokenIDs IDs of the token corresponding to the _uris logged 54 | * @param _URIs The URIs of the specified _tokenIDs 55 | */ 56 | function _logURIs(uint256[] memory _tokenIDs, string[] memory _URIs) internal { 57 | require(_tokenIDs.length == _URIs.length, "ERC1155Metadata#_logURIs: INVALID_ARRAYS_LENGTH"); 58 | for (uint256 i = 0; i < _tokenIDs.length; i++) { 59 | emit URI(_URIs[i], _tokenIDs[i]); 60 | } 61 | } 62 | 63 | /** 64 | * @notice Will update the base URL of token's URI 65 | * @param _newBaseMetadataURI New base URL of token's URI 66 | */ 67 | function _setBaseMetadataURI(string memory _newBaseMetadataURI) internal { 68 | baseMetadataURI = _newBaseMetadataURI; 69 | } 70 | 71 | 72 | /***********************************| 73 | | Utility Internal Functions | 74 | |__________________________________*/ 75 | 76 | /** 77 | * @notice Convert uint256 to string 78 | * @param _i Unsigned integer to convert to string 79 | */ 80 | function _uint2str(uint256 _i) internal pure returns (string memory _uintAsString) { 81 | if (_i == 0) { 82 | return "0"; 83 | } 84 | 85 | uint256 j = _i; 86 | uint256 ii = _i; 87 | uint256 len; 88 | 89 | // Get number of bytes 90 | while (j != 0) { 91 | len++; 92 | j /= 10; 93 | } 94 | 95 | bytes memory bstr = new bytes(len); 96 | uint256 k = len - 1; 97 | 98 | // Get each individual ASCII 99 | while (ii != 0) { 100 | bstr[k--] = byte(uint8(48 + ii % 10)); 101 | ii /= 10; 102 | } 103 | 104 | // Convert to string 105 | return string(bstr); 106 | } 107 | 108 | } -------------------------------------------------------------------------------- /typings/contracts/IERC1155Meta.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface IERC1155MetaInterface extends Interface { 14 | functions: { 15 | metaSafeTransferFrom: TypedFunctionDescription<{ 16 | encode([_from, _to, _id, _amount, _isGasFee, _data]: [ 17 | string, 18 | string, 19 | BigNumberish, 20 | BigNumberish, 21 | boolean, 22 | Arrayish 23 | ]): string; 24 | }>; 25 | 26 | metaSafeBatchTransferFrom: TypedFunctionDescription<{ 27 | encode([_from, _to, _ids, _amounts, _isGasFee, _data]: [ 28 | string, 29 | string, 30 | (BigNumberish)[], 31 | (BigNumberish)[], 32 | boolean, 33 | Arrayish 34 | ]): string; 35 | }>; 36 | 37 | metaSetApprovalForAll: TypedFunctionDescription<{ 38 | encode([_owner, _operator, _approved, _isGasFee, _data]: [ 39 | string, 40 | string, 41 | boolean, 42 | boolean, 43 | Arrayish 44 | ]): string; 45 | }>; 46 | }; 47 | 48 | events: {}; 49 | } 50 | 51 | export class IERC1155Meta extends Contract { 52 | connect(signerOrProvider: Signer | Provider | string): IERC1155Meta; 53 | attach(addressOrName: string): IERC1155Meta; 54 | deployed(): Promise; 55 | 56 | on(event: EventFilter | string, listener: Listener): IERC1155Meta; 57 | once(event: EventFilter | string, listener: Listener): IERC1155Meta; 58 | addListener( 59 | eventName: EventFilter | string, 60 | listener: Listener 61 | ): IERC1155Meta; 62 | removeAllListeners(eventName: EventFilter | string): IERC1155Meta; 63 | removeListener(eventName: any, listener: Listener): IERC1155Meta; 64 | 65 | interface: IERC1155MetaInterface; 66 | 67 | functions: { 68 | metaSafeTransferFrom( 69 | _from: string, 70 | _to: string, 71 | _id: BigNumberish, 72 | _amount: BigNumberish, 73 | _isGasFee: boolean, 74 | _data: Arrayish, 75 | overrides?: TransactionOverrides 76 | ): Promise; 77 | 78 | metaSafeBatchTransferFrom( 79 | _from: string, 80 | _to: string, 81 | _ids: (BigNumberish)[], 82 | _amounts: (BigNumberish)[], 83 | _isGasFee: boolean, 84 | _data: Arrayish, 85 | overrides?: TransactionOverrides 86 | ): Promise; 87 | 88 | metaSetApprovalForAll( 89 | _owner: string, 90 | _operator: string, 91 | _approved: boolean, 92 | _isGasFee: boolean, 93 | _data: Arrayish, 94 | overrides?: TransactionOverrides 95 | ): Promise; 96 | }; 97 | 98 | filters: {}; 99 | 100 | estimate: { 101 | metaSafeTransferFrom( 102 | _from: string, 103 | _to: string, 104 | _id: BigNumberish, 105 | _amount: BigNumberish, 106 | _isGasFee: boolean, 107 | _data: Arrayish 108 | ): Promise; 109 | 110 | metaSafeBatchTransferFrom( 111 | _from: string, 112 | _to: string, 113 | _ids: (BigNumberish)[], 114 | _amounts: (BigNumberish)[], 115 | _isGasFee: boolean, 116 | _data: Arrayish 117 | ): Promise; 118 | 119 | metaSetApprovalForAll( 120 | _owner: string, 121 | _operator: string, 122 | _approved: boolean, 123 | _isGasFee: boolean, 124 | _data: Arrayish 125 | ): Promise; 126 | }; 127 | } 128 | -------------------------------------------------------------------------------- /contracts/tokens/ERC1155/ERC1155MintBurn.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | 3 | import "./ERC1155.sol"; 4 | 5 | 6 | /** 7 | * @dev Multi-Fungible Tokens with minting and burning methods. These methods assume 8 | * a parent contract to be executed as they are `internal` functions 9 | */ 10 | contract ERC1155MintBurn is ERC1155 { 11 | 12 | 13 | /****************************************| 14 | | Minting Functions | 15 | |_______________________________________*/ 16 | 17 | /** 18 | * @notice Mint _amount of tokens of a given id 19 | * @param _to The address to mint tokens to 20 | * @param _id Token id to mint 21 | * @param _amount The amount to be minted 22 | * @param _data Data to pass if receiver is contract 23 | */ 24 | function _mint(address _to, uint256 _id, uint256 _amount, bytes memory _data) 25 | internal 26 | { 27 | // Add _amount 28 | balances[_to][_id] = balances[_to][_id].add(_amount); 29 | 30 | // Emit event 31 | emit TransferSingle(msg.sender, address(0x0), _to, _id, _amount); 32 | 33 | // Calling onReceive method if recipient is contract 34 | _callonERC1155Received(address(0x0), _to, _id, _amount, _data); 35 | } 36 | 37 | /** 38 | * @notice Mint tokens for each ids in _ids 39 | * @param _to The address to mint tokens to 40 | * @param _ids Array of ids to mint 41 | * @param _amounts Array of amount of tokens to mint per id 42 | * @param _data Data to pass if receiver is contract 43 | */ 44 | function _batchMint(address _to, uint256[] memory _ids, uint256[] memory _amounts, bytes memory _data) 45 | internal 46 | { 47 | require(_ids.length == _amounts.length, "ERC1155MintBurn#batchMint: INVALID_ARRAYS_LENGTH"); 48 | 49 | // Number of mints to execute 50 | uint256 nMint = _ids.length; 51 | 52 | // Executing all minting 53 | for (uint256 i = 0; i < nMint; i++) { 54 | // Update storage balance 55 | balances[_to][_ids[i]] = balances[_to][_ids[i]].add(_amounts[i]); 56 | } 57 | 58 | // Emit batch mint event 59 | emit TransferBatch(msg.sender, address(0x0), _to, _ids, _amounts); 60 | 61 | // Calling onReceive method if recipient is contract 62 | _callonERC1155BatchReceived(address(0x0), _to, _ids, _amounts, _data); 63 | } 64 | 65 | 66 | /****************************************| 67 | | Burning Functions | 68 | |_______________________________________*/ 69 | 70 | /** 71 | * @notice Burn _amount of tokens of a given token id 72 | * @param _from The address to burn tokens from 73 | * @param _id Token id to burn 74 | * @param _amount The amount to be burned 75 | */ 76 | function _burn(address _from, uint256 _id, uint256 _amount) 77 | internal 78 | { 79 | //Substract _amount 80 | balances[_from][_id] = balances[_from][_id].sub(_amount); 81 | 82 | // Emit event 83 | emit TransferSingle(msg.sender, _from, address(0x0), _id, _amount); 84 | } 85 | 86 | /** 87 | * @notice Burn tokens of given token id for each (_ids[i], _amounts[i]) pair 88 | * @param _from The address to burn tokens from 89 | * @param _ids Array of token ids to burn 90 | * @param _amounts Array of the amount to be burned 91 | */ 92 | function _batchBurn(address _from, uint256[] memory _ids, uint256[] memory _amounts) 93 | internal 94 | { 95 | require(_ids.length == _amounts.length, "ERC1155MintBurn#batchBurn: INVALID_ARRAYS_LENGTH"); 96 | 97 | // Number of mints to execute 98 | uint256 nBurn = _ids.length; 99 | 100 | // Executing all minting 101 | for (uint256 i = 0; i < nBurn; i++) { 102 | // Update storage balance 103 | balances[_from][_ids[i]] = balances[_from][_ids[i]].sub(_amounts[i]); 104 | } 105 | 106 | // Emit batch mint event 107 | emit TransferBatch(msg.sender, _from, address(0x0), _ids, _amounts); 108 | } 109 | 110 | } 111 | 112 | -------------------------------------------------------------------------------- /typings/contracts/ERC20.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface ERC20Interface extends Interface { 14 | functions: { 15 | transfer: TypedFunctionDescription<{ 16 | encode([to, value]: [string, BigNumberish]): string; 17 | }>; 18 | 19 | approve: TypedFunctionDescription<{ 20 | encode([spender, value]: [string, BigNumberish]): string; 21 | }>; 22 | 23 | transferFrom: TypedFunctionDescription<{ 24 | encode([from, to, value]: [string, string, BigNumberish]): string; 25 | }>; 26 | 27 | increaseAllowance: TypedFunctionDescription<{ 28 | encode([spender, addedValue]: [string, BigNumberish]): string; 29 | }>; 30 | 31 | decreaseAllowance: TypedFunctionDescription<{ 32 | encode([spender, subtractedValue]: [string, BigNumberish]): string; 33 | }>; 34 | }; 35 | 36 | events: { 37 | Approval: TypedEventDescription<{ 38 | encodeTopics([owner, spender, value]: [ 39 | string | null, 40 | string | null, 41 | null 42 | ]): string[]; 43 | }>; 44 | 45 | Transfer: TypedEventDescription<{ 46 | encodeTopics([from, to, value]: [ 47 | string | null, 48 | string | null, 49 | null 50 | ]): string[]; 51 | }>; 52 | }; 53 | } 54 | 55 | export class ERC20 extends Contract { 56 | connect(signerOrProvider: Signer | Provider | string): ERC20; 57 | attach(addressOrName: string): ERC20; 58 | deployed(): Promise; 59 | 60 | on(event: EventFilter | string, listener: Listener): ERC20; 61 | once(event: EventFilter | string, listener: Listener): ERC20; 62 | addListener(eventName: EventFilter | string, listener: Listener): ERC20; 63 | removeAllListeners(eventName: EventFilter | string): ERC20; 64 | removeListener(eventName: any, listener: Listener): ERC20; 65 | 66 | interface: ERC20Interface; 67 | 68 | functions: { 69 | balanceOf(owner: string): Promise; 70 | 71 | allowance(owner: string, spender: string): Promise; 72 | 73 | transfer( 74 | to: string, 75 | value: BigNumberish, 76 | overrides?: TransactionOverrides 77 | ): Promise; 78 | 79 | approve( 80 | spender: string, 81 | value: BigNumberish, 82 | overrides?: TransactionOverrides 83 | ): Promise; 84 | 85 | transferFrom( 86 | from: string, 87 | to: string, 88 | value: BigNumberish, 89 | overrides?: TransactionOverrides 90 | ): Promise; 91 | 92 | increaseAllowance( 93 | spender: string, 94 | addedValue: BigNumberish, 95 | overrides?: TransactionOverrides 96 | ): Promise; 97 | 98 | decreaseAllowance( 99 | spender: string, 100 | subtractedValue: BigNumberish, 101 | overrides?: TransactionOverrides 102 | ): Promise; 103 | 104 | totalSupply(): Promise; 105 | }; 106 | 107 | filters: { 108 | Approval( 109 | owner: string | null, 110 | spender: string | null, 111 | value: null 112 | ): EventFilter; 113 | 114 | Transfer(from: string | null, to: string | null, value: null): EventFilter; 115 | }; 116 | 117 | estimate: { 118 | transfer(to: string, value: BigNumberish): Promise; 119 | 120 | approve(spender: string, value: BigNumberish): Promise; 121 | 122 | transferFrom( 123 | from: string, 124 | to: string, 125 | value: BigNumberish 126 | ): Promise; 127 | 128 | increaseAllowance( 129 | spender: string, 130 | addedValue: BigNumberish 131 | ): Promise; 132 | 133 | decreaseAllowance( 134 | spender: string, 135 | subtractedValue: BigNumberish 136 | ): Promise; 137 | }; 138 | } 139 | -------------------------------------------------------------------------------- /typings/contracts/ERC1155ReceiverMock.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface ERC1155ReceiverMockInterface extends Interface { 14 | functions: { 15 | setShouldReject: TypedFunctionDescription<{ 16 | encode([_value]: [boolean]): string; 17 | }>; 18 | 19 | onERC1155Received: TypedFunctionDescription<{ 20 | encode([_operator, _from, _id, _value, _data]: [ 21 | string, 22 | string, 23 | BigNumberish, 24 | BigNumberish, 25 | Arrayish 26 | ]): string; 27 | }>; 28 | 29 | onERC1155BatchReceived: TypedFunctionDescription<{ 30 | encode([_operator, _from, _ids, _values, _data]: [ 31 | string, 32 | string, 33 | (BigNumberish)[], 34 | (BigNumberish)[], 35 | Arrayish 36 | ]): string; 37 | }>; 38 | }; 39 | 40 | events: { 41 | TransferBatchReceiver: TypedEventDescription<{ 42 | encodeTopics([_from, _to, _fromBalances, _toBalances]: [ 43 | null, 44 | null, 45 | null, 46 | null 47 | ]): string[]; 48 | }>; 49 | 50 | TransferSingleReceiver: TypedEventDescription<{ 51 | encodeTopics([_from, _to, _fromBalance, _toBalance]: [ 52 | null, 53 | null, 54 | null, 55 | null 56 | ]): string[]; 57 | }>; 58 | }; 59 | } 60 | 61 | export class ERC1155ReceiverMock extends Contract { 62 | connect(signerOrProvider: Signer | Provider | string): ERC1155ReceiverMock; 63 | attach(addressOrName: string): ERC1155ReceiverMock; 64 | deployed(): Promise; 65 | 66 | on(event: EventFilter | string, listener: Listener): ERC1155ReceiverMock; 67 | once(event: EventFilter | string, listener: Listener): ERC1155ReceiverMock; 68 | addListener( 69 | eventName: EventFilter | string, 70 | listener: Listener 71 | ): ERC1155ReceiverMock; 72 | removeAllListeners(eventName: EventFilter | string): ERC1155ReceiverMock; 73 | removeListener(eventName: any, listener: Listener): ERC1155ReceiverMock; 74 | 75 | interface: ERC1155ReceiverMockInterface; 76 | 77 | functions: { 78 | supportsInterface(interfaceID: Arrayish): Promise; 79 | 80 | setShouldReject( 81 | _value: boolean, 82 | overrides?: TransactionOverrides 83 | ): Promise; 84 | 85 | onERC1155Received( 86 | _operator: string, 87 | _from: string, 88 | _id: BigNumberish, 89 | _value: BigNumberish, 90 | _data: Arrayish, 91 | overrides?: TransactionOverrides 92 | ): Promise; 93 | 94 | onERC1155BatchReceived( 95 | _operator: string, 96 | _from: string, 97 | _ids: (BigNumberish)[], 98 | _values: (BigNumberish)[], 99 | _data: Arrayish, 100 | overrides?: TransactionOverrides 101 | ): Promise; 102 | 103 | lastData(): Promise; 104 | lastId(): Promise; 105 | lastOperator(): Promise; 106 | lastValue(): Promise; 107 | shouldReject(): Promise; 108 | }; 109 | 110 | filters: { 111 | TransferBatchReceiver( 112 | _from: null, 113 | _to: null, 114 | _fromBalances: null, 115 | _toBalances: null 116 | ): EventFilter; 117 | 118 | TransferSingleReceiver( 119 | _from: null, 120 | _to: null, 121 | _fromBalance: null, 122 | _toBalance: null 123 | ): EventFilter; 124 | }; 125 | 126 | estimate: { 127 | setShouldReject(_value: boolean): Promise; 128 | 129 | onERC1155Received( 130 | _operator: string, 131 | _from: string, 132 | _id: BigNumberish, 133 | _value: BigNumberish, 134 | _data: Arrayish 135 | ): Promise; 136 | 137 | onERC1155BatchReceived( 138 | _operator: string, 139 | _from: string, 140 | _ids: (BigNumberish)[], 141 | _values: (BigNumberish)[], 142 | _data: Arrayish 143 | ): Promise; 144 | }; 145 | } 146 | -------------------------------------------------------------------------------- /src/tests/Ownable.spec.ts: -------------------------------------------------------------------------------- 1 | import * as ethers from 'ethers' 2 | 3 | import { AbstractContract, expect, RevertError } from './utils' 4 | import * as utils from './utils' 5 | 6 | import { OwnableMock } from 'typings/contracts/OwnableMock' 7 | import { AddressZero } from 'ethers/constants'; 8 | 9 | // init test wallets from package.json mnemonic 10 | const web3 = (global as any).web3 11 | 12 | const { 13 | wallet: ownerWallet, 14 | } = utils.createTestWallet(web3, 0) 15 | 16 | const { 17 | wallet: userWallet, 18 | } = utils.createTestWallet(web3, 2) 19 | 20 | contract('Ownable Contract', (accounts: string[]) => { 21 | 22 | let ownableMockAbstract: AbstractContract 23 | let ownerOwnableMockContract: OwnableMock 24 | let userOwnableMockContract: OwnableMock 25 | 26 | // load contract abi and deploy to test server 27 | before(async () => { 28 | ownableMockAbstract = await AbstractContract.fromArtifactName('OwnableMock') 29 | }) 30 | 31 | // deploy before each test, to reset state of contract 32 | beforeEach(async () => { 33 | ownerOwnableMockContract = await ownableMockAbstract.deploy(ownerWallet) as OwnableMock 34 | userOwnableMockContract = await ownerOwnableMockContract.connect(userWallet) as OwnableMock 35 | }) 36 | 37 | describe('getOwner() Function', () => { 38 | 39 | it('should return current owner', async () => { 40 | const orginalOwner = await ownerOwnableMockContract.functions.getOwner() 41 | expect(orginalOwner).to.be.equal(ownerWallet.address) 42 | }) 43 | 44 | }) 45 | 46 | describe('ownerCall() Function', () => { 47 | 48 | it('should REVERT if called by a non-owner address', async () => { 49 | 50 | const tx = userOwnableMockContract.functions.ownerCall() 51 | await expect(tx).to.be.rejectedWith( RevertError("Ownable#onlyOwner: SENDER_IS_NOT_OWNER") ) 52 | }) 53 | 54 | it('should PASS if called by owner address', async () => { 55 | const tx = ownerOwnableMockContract.functions.ownerCall() 56 | await expect(tx).to.be.fulfilled 57 | }) 58 | 59 | }) 60 | 61 | describe('nonOwnerCall() Function', () => { 62 | 63 | it('should PASS if called by a non-owner address', async () => { 64 | const tx = userOwnableMockContract.functions.nonOwnerCall() 65 | await expect(tx).to.be.fulfilled 66 | }) 67 | 68 | it('should PASS if called by owner address', async () => { 69 | const tx = ownerOwnableMockContract.functions.nonOwnerCall() 70 | await expect(tx).to.be.fulfilled 71 | }) 72 | }) 73 | 74 | describe('transferOwnership() Function', () => { 75 | 76 | it('should REVERT if sender is not owner', async () => { 77 | const tx = userOwnableMockContract.functions.transferOwnership(userWallet.address) 78 | await expect(tx).to.be.rejectedWith( RevertError("Ownable#onlyOwner: SENDER_IS_NOT_OWNER") ) 79 | }) 80 | 81 | it('should REVERT if new owner is 0x0', async () => { 82 | const tx = ownerOwnableMockContract.functions.transferOwnership(AddressZero) 83 | await expect(tx).to.be.rejectedWith( RevertError("Ownable#transferOwnership: INVALID_ADDRESS") ) 84 | }) 85 | 86 | it('should update owner when it passes', async () => { 87 | const oldOwner = await ownerOwnableMockContract.functions.getOwner() 88 | await ownerOwnableMockContract.functions.transferOwnership(userWallet.address) 89 | const newOwner = await ownerOwnableMockContract.functions.getOwner() 90 | 91 | expect(oldOwner).to.be.equal(ownerWallet.address) 92 | expect(newOwner).to.be.equal(userWallet.address) 93 | }) 94 | 95 | context('When Ownership Transfer is Successful', () => { 96 | let tx: ethers.ContractTransaction 97 | 98 | beforeEach(async () => { 99 | tx = await ownerOwnableMockContract.functions.transferOwnership(userWallet.address) 100 | }) 101 | 102 | it('should emit OwnershipTransferred event when successful', async () => { 103 | const receipt = await tx.wait(1) 104 | const ev = receipt.events!.pop()! 105 | expect(ev.event).to.be.eql('OwnershipTransferred') 106 | }) 107 | 108 | it('should have old owner as `previousOwner` field', async () => { 109 | const receipt = await tx.wait(1) 110 | const ev = receipt.events!.pop()! 111 | 112 | const args = ev.args! as any 113 | expect(args.previousOwner).to.be.eql(ownerWallet.address) 114 | }) 115 | 116 | it('should have new owner as `newOwner` field', async () => { 117 | const receipt = await tx.wait(1) 118 | const ev = receipt.events!.pop()! 119 | 120 | const args = ev.args! as any 121 | expect(args.newOwner).to.be.eql(userWallet.address) 122 | }) 123 | 124 | }) 125 | 126 | }) 127 | }) -------------------------------------------------------------------------------- /contracts/tokens/ERC1155PackedBalance/ERC1155MintBurnPackedBalance.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | 3 | import "./ERC1155PackedBalance.sol"; 4 | 5 | 6 | /** 7 | * @dev Multi-Fungible Tokens with minting and burning methods. These methods assume 8 | * a parent contract to be executed as they are `internal` functions. 9 | */ 10 | contract ERC1155MintBurnPackedBalance is ERC1155PackedBalance { 11 | 12 | 13 | /****************************************| 14 | | Minting Functions | 15 | |_______________________________________*/ 16 | 17 | /** 18 | * @notice Mint _amount of tokens of a given id 19 | * @param _to The address to mint tokens to 20 | * @param _id Token id to mint 21 | * @param _amount The amount to be minted 22 | * @param _data Data to pass if receiver is contract 23 | */ 24 | function _mint(address _to, uint256 _id, uint256 _amount, bytes memory _data) 25 | internal 26 | { 27 | //Add _amount 28 | _updateIDBalance(_to, _id, _amount, Operations.Add); // Add amount to recipient 29 | 30 | // Emit event 31 | emit TransferSingle(msg.sender, address(0x0), _to, _id, _amount); 32 | 33 | // Calling onReceive method if recipient is contract 34 | _callonERC1155Received(address(0x0), _to, _id, _amount, _data); 35 | } 36 | 37 | /** 38 | * @notice Mint tokens for each (_ids[i], _amounts[i]) pair 39 | * @param _to The address to mint tokens to 40 | * @param _ids Array of ids to mint 41 | * @param _amounts Array of amount of tokens to mint per id 42 | * @param _data Data to pass if receiver is contract 43 | */ 44 | function _batchMint(address _to, uint256[] memory _ids, uint256[] memory _amounts, bytes memory _data) 45 | internal 46 | { 47 | require(_ids.length == _amounts.length, "ERC1155MintBurnPackedBalance#_batchMint: INVALID_ARRAYS_LENGTH"); 48 | 49 | // Load first bin and index where the token ID balance exists 50 | (uint256 bin, uint256 index) = getIDBinIndex(_ids[0]); 51 | 52 | // Balance for current bin in memory (initialized with first transfer) 53 | uint256 balTo = _viewUpdateIDBalance(balances[_to][bin], index, _amounts[0], Operations.Add); 54 | 55 | // Number of transfer to execute 56 | uint256 nTransfer = _ids.length; 57 | 58 | // Last bin updated 59 | uint256 lastBin = bin; 60 | 61 | for (uint256 i = 1; i < nTransfer; i++) { 62 | (bin, index) = getIDBinIndex(_ids[i]); 63 | 64 | // If new bin 65 | if (bin != lastBin) { 66 | // Update storage balance of previous bin 67 | balances[_to][lastBin] = balTo; 68 | balTo = balances[_to][bin]; 69 | // Bin will be the most recent bin 70 | lastBin = bin; 71 | } 72 | 73 | // // Update memory balance 74 | balTo = _viewUpdateIDBalance(balTo, index, _amounts[i], Operations.Add); 75 | } 76 | 77 | // Update storage of the last bin visited 78 | balances[_to][bin] = balTo; 79 | 80 | // //Emit event 81 | emit TransferBatch(msg.sender, address(0x0), _to, _ids, _amounts); 82 | 83 | // Calling onReceive method if recipient is contract 84 | _callonERC1155BatchReceived(address(0x0), _to, _ids, _amounts, _data); 85 | } 86 | 87 | 88 | /****************************************| 89 | | Burning Functions | 90 | |_______________________________________*/ 91 | 92 | /** 93 | * @notice Burn _amount of tokens of a given token id 94 | * @param _from The address to burn tokens from 95 | * @param _id Token id to burn 96 | * @param _amount The amount to be burned 97 | */ 98 | function _burn(address _from, uint256 _id, uint256 _amount) 99 | internal 100 | { 101 | //Substract _amount 102 | _updateIDBalance(_from, _id, _amount, Operations.Sub); 103 | 104 | // Emit event 105 | emit TransferSingle(msg.sender, _from, address(0x0), _id, _amount); 106 | } 107 | 108 | 109 | // USE EFFICIENT BURN IF POSSIBLE 110 | 111 | /** 112 | * @notice Burn tokens of given token id for each (_ids[i], _amounts[i]) pair 113 | * @param _from The address to burn tokens from 114 | * @param _ids Array of token ids to burn 115 | * @param _amounts Array of the amount to be burned 116 | */ 117 | function _batchBurn(address _from, uint256[] memory _ids, uint256[] memory _amounts) 118 | internal 119 | { 120 | require(_ids.length == _amounts.length, "ERC1155MintBurnPackedBalance#batchBurn: INVALID_ARRAYS_LENGTH"); 121 | 122 | // Number of mints to execute 123 | uint256 nBurn = _ids.length; 124 | 125 | // Executing all minting 126 | for (uint256 i = 0; i < nBurn; i++) { 127 | // Update storage balance 128 | _updateIDBalance(_from, _ids[i], _amounts[i], Operations.Sub); // Add amount to recipient 129 | } 130 | 131 | // Emit batch mint event 132 | emit TransferBatch(msg.sender, _from, address(0x0), _ids, _amounts); 133 | } 134 | 135 | } 136 | 137 | -------------------------------------------------------------------------------- /typings/contracts/IERC1155.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface IERC1155Interface extends Interface { 14 | functions: { 15 | safeTransferFrom: TypedFunctionDescription<{ 16 | encode([_from, _to, _id, _amount, _data]: [ 17 | string, 18 | string, 19 | BigNumberish, 20 | BigNumberish, 21 | Arrayish 22 | ]): string; 23 | }>; 24 | 25 | safeBatchTransferFrom: TypedFunctionDescription<{ 26 | encode([_from, _to, _ids, _amounts, _data]: [ 27 | string, 28 | string, 29 | (BigNumberish)[], 30 | (BigNumberish)[], 31 | Arrayish 32 | ]): string; 33 | }>; 34 | 35 | setApprovalForAll: TypedFunctionDescription<{ 36 | encode([_operator, _approved]: [string, boolean]): string; 37 | }>; 38 | }; 39 | 40 | events: { 41 | ApprovalForAll: TypedEventDescription<{ 42 | encodeTopics([_owner, _operator, _approved]: [ 43 | string | null, 44 | string | null, 45 | null 46 | ]): string[]; 47 | }>; 48 | 49 | TransferBatch: TypedEventDescription<{ 50 | encodeTopics([_operator, _from, _to, _ids, _amounts]: [ 51 | string | null, 52 | string | null, 53 | string | null, 54 | null, 55 | null 56 | ]): string[]; 57 | }>; 58 | 59 | TransferSingle: TypedEventDescription<{ 60 | encodeTopics([_operator, _from, _to, _id, _amount]: [ 61 | string | null, 62 | string | null, 63 | string | null, 64 | null, 65 | null 66 | ]): string[]; 67 | }>; 68 | 69 | URI: TypedEventDescription<{ 70 | encodeTopics([_amount, _id]: [null, BigNumberish | null]): string[]; 71 | }>; 72 | }; 73 | } 74 | 75 | export class IERC1155 extends Contract { 76 | connect(signerOrProvider: Signer | Provider | string): IERC1155; 77 | attach(addressOrName: string): IERC1155; 78 | deployed(): Promise; 79 | 80 | on(event: EventFilter | string, listener: Listener): IERC1155; 81 | once(event: EventFilter | string, listener: Listener): IERC1155; 82 | addListener(eventName: EventFilter | string, listener: Listener): IERC1155; 83 | removeAllListeners(eventName: EventFilter | string): IERC1155; 84 | removeListener(eventName: any, listener: Listener): IERC1155; 85 | 86 | interface: IERC1155Interface; 87 | 88 | functions: { 89 | balanceOf(_owner: string, _id: BigNumberish): Promise; 90 | 91 | balanceOfBatch( 92 | _owners: (string)[], 93 | _ids: (BigNumberish)[] 94 | ): Promise<(BigNumber)[]>; 95 | 96 | isApprovedForAll(_owner: string, _operator: string): Promise; 97 | 98 | safeTransferFrom( 99 | _from: string, 100 | _to: string, 101 | _id: BigNumberish, 102 | _amount: BigNumberish, 103 | _data: Arrayish, 104 | overrides?: TransactionOverrides 105 | ): Promise; 106 | 107 | safeBatchTransferFrom( 108 | _from: string, 109 | _to: string, 110 | _ids: (BigNumberish)[], 111 | _amounts: (BigNumberish)[], 112 | _data: Arrayish, 113 | overrides?: TransactionOverrides 114 | ): Promise; 115 | 116 | setApprovalForAll( 117 | _operator: string, 118 | _approved: boolean, 119 | overrides?: TransactionOverrides 120 | ): Promise; 121 | }; 122 | 123 | filters: { 124 | ApprovalForAll( 125 | _owner: string | null, 126 | _operator: string | null, 127 | _approved: null 128 | ): EventFilter; 129 | 130 | TransferBatch( 131 | _operator: string | null, 132 | _from: string | null, 133 | _to: string | null, 134 | _ids: null, 135 | _amounts: null 136 | ): EventFilter; 137 | 138 | TransferSingle( 139 | _operator: string | null, 140 | _from: string | null, 141 | _to: string | null, 142 | _id: null, 143 | _amount: null 144 | ): EventFilter; 145 | 146 | URI(_amount: null, _id: BigNumberish | null): EventFilter; 147 | }; 148 | 149 | estimate: { 150 | safeTransferFrom( 151 | _from: string, 152 | _to: string, 153 | _id: BigNumberish, 154 | _amount: BigNumberish, 155 | _data: Arrayish 156 | ): Promise; 157 | 158 | safeBatchTransferFrom( 159 | _from: string, 160 | _to: string, 161 | _ids: (BigNumberish)[], 162 | _amounts: (BigNumberish)[], 163 | _data: Arrayish 164 | ): Promise; 165 | 166 | setApprovalForAll( 167 | _operator: string, 168 | _approved: boolean 169 | ): Promise; 170 | }; 171 | } 172 | -------------------------------------------------------------------------------- /typings/contracts/ERC1155.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface ERC1155Interface extends Interface { 14 | functions: { 15 | safeTransferFrom: TypedFunctionDescription<{ 16 | encode([_from, _to, _id, _amount, _data]: [ 17 | string, 18 | string, 19 | BigNumberish, 20 | BigNumberish, 21 | Arrayish 22 | ]): string; 23 | }>; 24 | 25 | safeBatchTransferFrom: TypedFunctionDescription<{ 26 | encode([_from, _to, _ids, _amounts, _data]: [ 27 | string, 28 | string, 29 | (BigNumberish)[], 30 | (BigNumberish)[], 31 | Arrayish 32 | ]): string; 33 | }>; 34 | 35 | setApprovalForAll: TypedFunctionDescription<{ 36 | encode([_operator, _approved]: [string, boolean]): string; 37 | }>; 38 | }; 39 | 40 | events: { 41 | ApprovalForAll: TypedEventDescription<{ 42 | encodeTopics([_owner, _operator, _approved]: [ 43 | string | null, 44 | string | null, 45 | null 46 | ]): string[]; 47 | }>; 48 | 49 | TransferBatch: TypedEventDescription<{ 50 | encodeTopics([_operator, _from, _to, _ids, _amounts]: [ 51 | string | null, 52 | string | null, 53 | string | null, 54 | null, 55 | null 56 | ]): string[]; 57 | }>; 58 | 59 | TransferSingle: TypedEventDescription<{ 60 | encodeTopics([_operator, _from, _to, _id, _amount]: [ 61 | string | null, 62 | string | null, 63 | string | null, 64 | null, 65 | null 66 | ]): string[]; 67 | }>; 68 | 69 | URI: TypedEventDescription<{ 70 | encodeTopics([_uri, _id]: [null, BigNumberish | null]): string[]; 71 | }>; 72 | }; 73 | } 74 | 75 | export class ERC1155 extends Contract { 76 | connect(signerOrProvider: Signer | Provider | string): ERC1155; 77 | attach(addressOrName: string): ERC1155; 78 | deployed(): Promise; 79 | 80 | on(event: EventFilter | string, listener: Listener): ERC1155; 81 | once(event: EventFilter | string, listener: Listener): ERC1155; 82 | addListener(eventName: EventFilter | string, listener: Listener): ERC1155; 83 | removeAllListeners(eventName: EventFilter | string): ERC1155; 84 | removeListener(eventName: any, listener: Listener): ERC1155; 85 | 86 | interface: ERC1155Interface; 87 | 88 | functions: { 89 | isApprovedForAll(_owner: string, _operator: string): Promise; 90 | 91 | balanceOf(_owner: string, _id: BigNumberish): Promise; 92 | 93 | balanceOfBatch( 94 | _owners: (string)[], 95 | _ids: (BigNumberish)[] 96 | ): Promise<(BigNumber)[]>; 97 | 98 | supportsInterface(_interfaceID: Arrayish): Promise; 99 | 100 | safeTransferFrom( 101 | _from: string, 102 | _to: string, 103 | _id: BigNumberish, 104 | _amount: BigNumberish, 105 | _data: Arrayish, 106 | overrides?: TransactionOverrides 107 | ): Promise; 108 | 109 | safeBatchTransferFrom( 110 | _from: string, 111 | _to: string, 112 | _ids: (BigNumberish)[], 113 | _amounts: (BigNumberish)[], 114 | _data: Arrayish, 115 | overrides?: TransactionOverrides 116 | ): Promise; 117 | 118 | setApprovalForAll( 119 | _operator: string, 120 | _approved: boolean, 121 | overrides?: TransactionOverrides 122 | ): Promise; 123 | }; 124 | 125 | filters: { 126 | ApprovalForAll( 127 | _owner: string | null, 128 | _operator: string | null, 129 | _approved: null 130 | ): EventFilter; 131 | 132 | TransferBatch( 133 | _operator: string | null, 134 | _from: string | null, 135 | _to: string | null, 136 | _ids: null, 137 | _amounts: null 138 | ): EventFilter; 139 | 140 | TransferSingle( 141 | _operator: string | null, 142 | _from: string | null, 143 | _to: string | null, 144 | _id: null, 145 | _amount: null 146 | ): EventFilter; 147 | 148 | URI(_uri: null, _id: BigNumberish | null): EventFilter; 149 | }; 150 | 151 | estimate: { 152 | safeTransferFrom( 153 | _from: string, 154 | _to: string, 155 | _id: BigNumberish, 156 | _amount: BigNumberish, 157 | _data: Arrayish 158 | ): Promise; 159 | 160 | safeBatchTransferFrom( 161 | _from: string, 162 | _to: string, 163 | _ids: (BigNumberish)[], 164 | _amounts: (BigNumberish)[], 165 | _data: Arrayish 166 | ): Promise; 167 | 168 | setApprovalForAll( 169 | _operator: string, 170 | _approved: boolean 171 | ): Promise; 172 | }; 173 | } 174 | -------------------------------------------------------------------------------- /typings/contracts/ERC1155MintBurn.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface ERC1155MintBurnInterface extends Interface { 14 | functions: { 15 | safeBatchTransferFrom: TypedFunctionDescription<{ 16 | encode([_from, _to, _ids, _amounts, _data]: [ 17 | string, 18 | string, 19 | (BigNumberish)[], 20 | (BigNumberish)[], 21 | Arrayish 22 | ]): string; 23 | }>; 24 | 25 | safeTransferFrom: TypedFunctionDescription<{ 26 | encode([_from, _to, _id, _amount, _data]: [ 27 | string, 28 | string, 29 | BigNumberish, 30 | BigNumberish, 31 | Arrayish 32 | ]): string; 33 | }>; 34 | 35 | setApprovalForAll: TypedFunctionDescription<{ 36 | encode([_operator, _approved]: [string, boolean]): string; 37 | }>; 38 | }; 39 | 40 | events: { 41 | ApprovalForAll: TypedEventDescription<{ 42 | encodeTopics([_owner, _operator, _approved]: [ 43 | string | null, 44 | string | null, 45 | null 46 | ]): string[]; 47 | }>; 48 | 49 | TransferBatch: TypedEventDescription<{ 50 | encodeTopics([_operator, _from, _to, _ids, _amounts]: [ 51 | string | null, 52 | string | null, 53 | string | null, 54 | null, 55 | null 56 | ]): string[]; 57 | }>; 58 | 59 | TransferSingle: TypedEventDescription<{ 60 | encodeTopics([_operator, _from, _to, _id, _amount]: [ 61 | string | null, 62 | string | null, 63 | string | null, 64 | null, 65 | null 66 | ]): string[]; 67 | }>; 68 | 69 | URI: TypedEventDescription<{ 70 | encodeTopics([_uri, _id]: [null, BigNumberish | null]): string[]; 71 | }>; 72 | }; 73 | } 74 | 75 | export class ERC1155MintBurn extends Contract { 76 | connect(signerOrProvider: Signer | Provider | string): ERC1155MintBurn; 77 | attach(addressOrName: string): ERC1155MintBurn; 78 | deployed(): Promise; 79 | 80 | on(event: EventFilter | string, listener: Listener): ERC1155MintBurn; 81 | once(event: EventFilter | string, listener: Listener): ERC1155MintBurn; 82 | addListener( 83 | eventName: EventFilter | string, 84 | listener: Listener 85 | ): ERC1155MintBurn; 86 | removeAllListeners(eventName: EventFilter | string): ERC1155MintBurn; 87 | removeListener(eventName: any, listener: Listener): ERC1155MintBurn; 88 | 89 | interface: ERC1155MintBurnInterface; 90 | 91 | functions: { 92 | balanceOf(_owner: string, _id: BigNumberish): Promise; 93 | 94 | balanceOfBatch( 95 | _owners: (string)[], 96 | _ids: (BigNumberish)[] 97 | ): Promise<(BigNumber)[]>; 98 | 99 | isApprovedForAll(_owner: string, _operator: string): Promise; 100 | 101 | supportsInterface(_interfaceID: Arrayish): Promise; 102 | 103 | safeBatchTransferFrom( 104 | _from: string, 105 | _to: string, 106 | _ids: (BigNumberish)[], 107 | _amounts: (BigNumberish)[], 108 | _data: Arrayish, 109 | overrides?: TransactionOverrides 110 | ): Promise; 111 | 112 | safeTransferFrom( 113 | _from: string, 114 | _to: string, 115 | _id: BigNumberish, 116 | _amount: BigNumberish, 117 | _data: Arrayish, 118 | overrides?: TransactionOverrides 119 | ): Promise; 120 | 121 | setApprovalForAll( 122 | _operator: string, 123 | _approved: boolean, 124 | overrides?: TransactionOverrides 125 | ): Promise; 126 | }; 127 | 128 | filters: { 129 | ApprovalForAll( 130 | _owner: string | null, 131 | _operator: string | null, 132 | _approved: null 133 | ): EventFilter; 134 | 135 | TransferBatch( 136 | _operator: string | null, 137 | _from: string | null, 138 | _to: string | null, 139 | _ids: null, 140 | _amounts: null 141 | ): EventFilter; 142 | 143 | TransferSingle( 144 | _operator: string | null, 145 | _from: string | null, 146 | _to: string | null, 147 | _id: null, 148 | _amount: null 149 | ): EventFilter; 150 | 151 | URI(_uri: null, _id: BigNumberish | null): EventFilter; 152 | }; 153 | 154 | estimate: { 155 | safeBatchTransferFrom( 156 | _from: string, 157 | _to: string, 158 | _ids: (BigNumberish)[], 159 | _amounts: (BigNumberish)[], 160 | _data: Arrayish 161 | ): Promise; 162 | 163 | safeTransferFrom( 164 | _from: string, 165 | _to: string, 166 | _id: BigNumberish, 167 | _amount: BigNumberish, 168 | _data: Arrayish 169 | ): Promise; 170 | 171 | setApprovalForAll( 172 | _operator: string, 173 | _approved: boolean 174 | ): Promise; 175 | }; 176 | } 177 | -------------------------------------------------------------------------------- /typings/contracts/ERC20Mock.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface ERC20MockInterface extends Interface { 14 | functions: { 15 | approve: TypedFunctionDescription<{ 16 | encode([spender, value]: [string, BigNumberish]): string; 17 | }>; 18 | 19 | decreaseAllowance: TypedFunctionDescription<{ 20 | encode([spender, subtractedValue]: [string, BigNumberish]): string; 21 | }>; 22 | 23 | increaseAllowance: TypedFunctionDescription<{ 24 | encode([spender, addedValue]: [string, BigNumberish]): string; 25 | }>; 26 | 27 | transfer: TypedFunctionDescription<{ 28 | encode([to, value]: [string, BigNumberish]): string; 29 | }>; 30 | 31 | transferFrom: TypedFunctionDescription<{ 32 | encode([from, to, value]: [string, string, BigNumberish]): string; 33 | }>; 34 | 35 | mockMint: TypedFunctionDescription<{ 36 | encode([_address, _amount]: [string, BigNumberish]): string; 37 | }>; 38 | 39 | batchTransfer: TypedFunctionDescription<{ 40 | encode([_tokens, _to, _amounts]: [ 41 | (string)[], 42 | string, 43 | (BigNumberish)[] 44 | ]): string; 45 | }>; 46 | }; 47 | 48 | events: { 49 | Approval: TypedEventDescription<{ 50 | encodeTopics([owner, spender, value]: [ 51 | string | null, 52 | string | null, 53 | null 54 | ]): string[]; 55 | }>; 56 | 57 | Transfer: TypedEventDescription<{ 58 | encodeTopics([from, to, value]: [ 59 | string | null, 60 | string | null, 61 | null 62 | ]): string[]; 63 | }>; 64 | }; 65 | } 66 | 67 | export class ERC20Mock extends Contract { 68 | connect(signerOrProvider: Signer | Provider | string): ERC20Mock; 69 | attach(addressOrName: string): ERC20Mock; 70 | deployed(): Promise; 71 | 72 | on(event: EventFilter | string, listener: Listener): ERC20Mock; 73 | once(event: EventFilter | string, listener: Listener): ERC20Mock; 74 | addListener(eventName: EventFilter | string, listener: Listener): ERC20Mock; 75 | removeAllListeners(eventName: EventFilter | string): ERC20Mock; 76 | removeListener(eventName: any, listener: Listener): ERC20Mock; 77 | 78 | interface: ERC20MockInterface; 79 | 80 | functions: { 81 | allowance(owner: string, spender: string): Promise; 82 | 83 | balanceOf(owner: string): Promise; 84 | 85 | approve( 86 | spender: string, 87 | value: BigNumberish, 88 | overrides?: TransactionOverrides 89 | ): Promise; 90 | 91 | decreaseAllowance( 92 | spender: string, 93 | subtractedValue: BigNumberish, 94 | overrides?: TransactionOverrides 95 | ): Promise; 96 | 97 | increaseAllowance( 98 | spender: string, 99 | addedValue: BigNumberish, 100 | overrides?: TransactionOverrides 101 | ): Promise; 102 | 103 | transfer( 104 | to: string, 105 | value: BigNumberish, 106 | overrides?: TransactionOverrides 107 | ): Promise; 108 | 109 | transferFrom( 110 | from: string, 111 | to: string, 112 | value: BigNumberish, 113 | overrides?: TransactionOverrides 114 | ): Promise; 115 | 116 | mockMint( 117 | _address: string, 118 | _amount: BigNumberish, 119 | overrides?: TransactionOverrides 120 | ): Promise; 121 | 122 | batchTransfer( 123 | _tokens: (string)[], 124 | _to: string, 125 | _amounts: (BigNumberish)[], 126 | overrides?: TransactionOverrides 127 | ): Promise; 128 | 129 | totalSupply(): Promise; 130 | }; 131 | 132 | filters: { 133 | Approval( 134 | owner: string | null, 135 | spender: string | null, 136 | value: null 137 | ): EventFilter; 138 | 139 | Transfer(from: string | null, to: string | null, value: null): EventFilter; 140 | }; 141 | 142 | estimate: { 143 | approve(spender: string, value: BigNumberish): Promise; 144 | 145 | decreaseAllowance( 146 | spender: string, 147 | subtractedValue: BigNumberish 148 | ): Promise; 149 | 150 | increaseAllowance( 151 | spender: string, 152 | addedValue: BigNumberish 153 | ): Promise; 154 | 155 | transfer(to: string, value: BigNumberish): Promise; 156 | 157 | transferFrom( 158 | from: string, 159 | to: string, 160 | value: BigNumberish 161 | ): Promise; 162 | 163 | mockMint(_address: string, _amount: BigNumberish): Promise; 164 | 165 | batchTransfer( 166 | _tokens: (string)[], 167 | _to: string, 168 | _amounts: (BigNumberish)[] 169 | ): Promise; 170 | }; 171 | } 172 | -------------------------------------------------------------------------------- /contracts/utils/SignatureValidator.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | 3 | import "../interfaces/IERC1271Wallet.sol"; 4 | import "./LibBytes.sol"; 5 | import "./LibEIP712.sol"; 6 | 7 | /** 8 | * @dev Contains logic for signature validation. 9 | * Signatures from wallet contracts assume ERC-1271 support (https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1271.md) 10 | * Notes: Methods are strongly inspired by contracts in https://github.com/0xProject/0x-monorepo/blob/development/ 11 | */ 12 | contract SignatureValidator is LibEIP712 { 13 | using LibBytes for bytes; 14 | 15 | /***********************************| 16 | | Variables | 17 | |__________________________________*/ 18 | 19 | 20 | // bytes4(keccak256("isValidSignature(bytes,bytes)") 21 | bytes4 constant internal ERC1271_MAGICVALUE = 0x20c13b0b; 22 | 23 | // Allowed signature types. 24 | enum SignatureType { 25 | Illegal, // 0x00, default value 26 | EIP712, // 0x01 27 | EthSign, // 0x02 28 | WalletBytes, // 0x03 To call isValidSignature(bytes, bytes) on wallet contract 29 | WalletBytes32, // 0x04 To call isValidSignature(bytes32, bytes) on wallet contract 30 | NSignatureTypes // 0x05, number of signature types. Always leave at end. 31 | } 32 | 33 | 34 | /***********************************| 35 | | Signature Functions | 36 | |__________________________________*/ 37 | 38 | /** 39 | * @dev Verifies that a hash has been signed by the given signer. 40 | * @param _signerAddress Address that should have signed the given hash. 41 | * @param _hash Hash of the EIP-712 encoded data 42 | * @param _data Full EIP-712 data structure that was hashed and signed 43 | * @param _sig Proof that the hash has been signed by signer. 44 | * @return True if the address recovered from the provided signature matches the input signer address. 45 | */ 46 | function isValidSignature( 47 | address _signerAddress, 48 | bytes32 _hash, 49 | bytes memory _data, 50 | bytes memory _sig 51 | ) 52 | public 53 | view 54 | returns (bool isValid) 55 | { 56 | require( 57 | _sig.length > 0, 58 | "SignatureValidator#isValidSignature: LENGTH_GREATER_THAN_0_REQUIRED" 59 | ); 60 | 61 | require( 62 | _signerAddress != address(0x0), 63 | "SignatureValidator#isValidSignature: INVALID_SIGNER" 64 | ); 65 | 66 | // Pop last byte off of signature byte array. 67 | uint8 signatureTypeRaw = uint8(_sig.popLastByte()); 68 | 69 | // Ensure signature is supported 70 | require( 71 | signatureTypeRaw < uint8(SignatureType.NSignatureTypes), 72 | "SignatureValidator#isValidSignature: UNSUPPORTED_SIGNATURE" 73 | ); 74 | 75 | // Extract signature type 76 | SignatureType signatureType = SignatureType(signatureTypeRaw); 77 | 78 | // Variables are not scoped in Solidity. 79 | uint8 v; 80 | bytes32 r; 81 | bytes32 s; 82 | address recovered; 83 | 84 | // Always illegal signature. 85 | // This is always an implicit option since a signer can create a 86 | // signature array with invalid type or length. We may as well make 87 | // it an explicit option. This aids testing and analysis. It is 88 | // also the initialization value for the enum type. 89 | if (signatureType == SignatureType.Illegal) { 90 | revert("SignatureValidator#isValidSignature: ILLEGAL_SIGNATURE"); 91 | 92 | 93 | // Signature using EIP712 94 | } else if (signatureType == SignatureType.EIP712) { 95 | require( 96 | _sig.length == 65, 97 | "SignatureValidator#isValidSignature: LENGTH_65_REQUIRED" 98 | ); 99 | r = _sig.readBytes32(0); 100 | s = _sig.readBytes32(32); 101 | v = uint8(_sig[64]); 102 | recovered = ecrecover(_hash, v, r, s); 103 | isValid = _signerAddress == recovered; 104 | return isValid; 105 | 106 | 107 | // Signed using web3.eth_sign 108 | } else if (signatureType == SignatureType.EthSign) { 109 | require( 110 | _sig.length == 65, 111 | "SignatureValidator#isValidSignature: LENGTH_65_REQUIRED" 112 | ); 113 | r = _sig.readBytes32(0); 114 | s = _sig.readBytes32(32); 115 | v = uint8(_sig[64]); 116 | recovered = ecrecover( 117 | keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _hash)), 118 | v, 119 | r, 120 | s 121 | ); 122 | isValid = _signerAddress == recovered; 123 | return isValid; 124 | 125 | 126 | // Signature verified by wallet contract with data validation. 127 | } else if (signatureType == SignatureType.WalletBytes) { 128 | isValid = ERC1271_MAGICVALUE == IERC1271Wallet(_signerAddress).isValidSignature(_data, _sig); 129 | return isValid; 130 | 131 | 132 | // Signature verified by wallet contract without data validation. 133 | } else if (signatureType == SignatureType.WalletBytes32) { 134 | isValid = ERC1271_MAGICVALUE == IERC1271Wallet(_signerAddress).isValidSignature(_hash, _sig); 135 | return isValid; 136 | } 137 | 138 | // Anything else is illegal (We do not return false because 139 | // the signature may actually be valid, just not in a format 140 | // that we currently support. In this case returning false 141 | // may lead the caller to incorrectly believe that the 142 | // signature was invalid.) 143 | revert("SignatureValidator#isValidSignature: UNSUPPORTED_SIGNATURE"); 144 | } 145 | 146 | } -------------------------------------------------------------------------------- /typings/contracts/ERC1155PackedBalance.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface ERC1155PackedBalanceInterface extends Interface { 14 | functions: { 15 | safeTransferFrom: TypedFunctionDescription<{ 16 | encode([_from, _to, _id, _amount, _data]: [ 17 | string, 18 | string, 19 | BigNumberish, 20 | BigNumberish, 21 | Arrayish 22 | ]): string; 23 | }>; 24 | 25 | safeBatchTransferFrom: TypedFunctionDescription<{ 26 | encode([_from, _to, _ids, _amounts, _data]: [ 27 | string, 28 | string, 29 | (BigNumberish)[], 30 | (BigNumberish)[], 31 | Arrayish 32 | ]): string; 33 | }>; 34 | 35 | setApprovalForAll: TypedFunctionDescription<{ 36 | encode([_operator, _approved]: [string, boolean]): string; 37 | }>; 38 | }; 39 | 40 | events: { 41 | ApprovalForAll: TypedEventDescription<{ 42 | encodeTopics([_owner, _operator, _approved]: [ 43 | string | null, 44 | string | null, 45 | null 46 | ]): string[]; 47 | }>; 48 | 49 | TransferBatch: TypedEventDescription<{ 50 | encodeTopics([_operator, _from, _to, _ids, _amounts]: [ 51 | string | null, 52 | string | null, 53 | string | null, 54 | null, 55 | null 56 | ]): string[]; 57 | }>; 58 | 59 | TransferSingle: TypedEventDescription<{ 60 | encodeTopics([_operator, _from, _to, _id, _amount]: [ 61 | string | null, 62 | string | null, 63 | string | null, 64 | null, 65 | null 66 | ]): string[]; 67 | }>; 68 | 69 | URI: TypedEventDescription<{ 70 | encodeTopics([_uri, _id]: [null, BigNumberish | null]): string[]; 71 | }>; 72 | }; 73 | } 74 | 75 | export class ERC1155PackedBalance extends Contract { 76 | connect(signerOrProvider: Signer | Provider | string): ERC1155PackedBalance; 77 | attach(addressOrName: string): ERC1155PackedBalance; 78 | deployed(): Promise; 79 | 80 | on(event: EventFilter | string, listener: Listener): ERC1155PackedBalance; 81 | once(event: EventFilter | string, listener: Listener): ERC1155PackedBalance; 82 | addListener( 83 | eventName: EventFilter | string, 84 | listener: Listener 85 | ): ERC1155PackedBalance; 86 | removeAllListeners(eventName: EventFilter | string): ERC1155PackedBalance; 87 | removeListener(eventName: any, listener: Listener): ERC1155PackedBalance; 88 | 89 | interface: ERC1155PackedBalanceInterface; 90 | 91 | functions: { 92 | isApprovedForAll(_owner: string, _operator: string): Promise; 93 | 94 | balanceOf(_owner: string, _id: BigNumberish): Promise; 95 | 96 | balanceOfBatch( 97 | _owners: (string)[], 98 | _ids: (BigNumberish)[] 99 | ): Promise<(BigNumber)[]>; 100 | 101 | getIDBinIndex( 102 | _id: BigNumberish 103 | ): Promise<{ 104 | bin: BigNumber; 105 | index: BigNumber; 106 | 0: BigNumber; 107 | 1: BigNumber; 108 | }>; 109 | 110 | getValueInBin( 111 | _binAmount: BigNumberish, 112 | _index: BigNumberish 113 | ): Promise; 114 | 115 | supportsInterface(_interfaceID: Arrayish): Promise; 116 | 117 | safeTransferFrom( 118 | _from: string, 119 | _to: string, 120 | _id: BigNumberish, 121 | _amount: BigNumberish, 122 | _data: Arrayish, 123 | overrides?: TransactionOverrides 124 | ): Promise; 125 | 126 | safeBatchTransferFrom( 127 | _from: string, 128 | _to: string, 129 | _ids: (BigNumberish)[], 130 | _amounts: (BigNumberish)[], 131 | _data: Arrayish, 132 | overrides?: TransactionOverrides 133 | ): Promise; 134 | 135 | setApprovalForAll( 136 | _operator: string, 137 | _approved: boolean, 138 | overrides?: TransactionOverrides 139 | ): Promise; 140 | }; 141 | 142 | filters: { 143 | ApprovalForAll( 144 | _owner: string | null, 145 | _operator: string | null, 146 | _approved: null 147 | ): EventFilter; 148 | 149 | TransferBatch( 150 | _operator: string | null, 151 | _from: string | null, 152 | _to: string | null, 153 | _ids: null, 154 | _amounts: null 155 | ): EventFilter; 156 | 157 | TransferSingle( 158 | _operator: string | null, 159 | _from: string | null, 160 | _to: string | null, 161 | _id: null, 162 | _amount: null 163 | ): EventFilter; 164 | 165 | URI(_uri: null, _id: BigNumberish | null): EventFilter; 166 | }; 167 | 168 | estimate: { 169 | safeTransferFrom( 170 | _from: string, 171 | _to: string, 172 | _id: BigNumberish, 173 | _amount: BigNumberish, 174 | _data: Arrayish 175 | ): Promise; 176 | 177 | safeBatchTransferFrom( 178 | _from: string, 179 | _to: string, 180 | _ids: (BigNumberish)[], 181 | _amounts: (BigNumberish)[], 182 | _data: Arrayish 183 | ): Promise; 184 | 185 | setApprovalForAll( 186 | _operator: string, 187 | _approved: boolean 188 | ): Promise; 189 | }; 190 | } 191 | -------------------------------------------------------------------------------- /src/tests/utils/contract.ts: -------------------------------------------------------------------------------- 1 | // Build ethers.Contract instances from ABI JSON files generated by truffle. 2 | // 3 | // adapted this utility from the handy work by the counterfactual team at: 4 | // https://github.com/counterfactual/monorepo/blob/d9be8524a691c45b6aac1b5e1cf2ff81059203df/packages/contracts/utils/contract.ts 5 | 6 | import * as ethers from 'ethers' 7 | 8 | interface NetworkMapping { 9 | [networkId: number]: { address: string } 10 | } 11 | 12 | interface BuildArtifact { 13 | readonly contractName: string 14 | readonly abi: any[] 15 | readonly bytecode: string 16 | readonly networks: NetworkMapping 17 | } 18 | 19 | /** 20 | * Convenience class for an undeployed contract i.e. only the ABI and bytecode. 21 | */ 22 | export class AbstractContract { 23 | /** 24 | * Load build artifact by name into an abstract contract 25 | * @example 26 | * const CountingApp = AbstractContract.fromArtifactName("CountingApp", { StaticCall }) 27 | * @param artifactName The name of the artifact to load 28 | * @param links Optional AbstractContract libraries to link. 29 | * @returns Truffle artifact wrapped in an AbstractContract. 30 | */ 31 | public static async fromArtifactName( 32 | artifactName: string, 33 | links?: { [name: string]: Promise } 34 | ): Promise { 35 | // these ABI JSON files are generated by truffle 36 | const contract: BuildArtifact = await import(`../../build/contracts/${artifactName}.json`) 37 | return AbstractContract.fromBuildArtifact(contract, links, artifactName) 38 | } 39 | 40 | /** 41 | * Wrap build artifact in abstract contract 42 | * @param buildArtifact Truffle contract to wrap 43 | * @param links Optional AbstractContract libraries to link. 44 | * @returns Truffle artifact wrapped in an AbstractContract. 45 | */ 46 | public static async fromBuildArtifact( 47 | buildArtifact: BuildArtifact, 48 | links?: { [name: string]: Promise }, 49 | artifactName: string = 'UntitledContract' 50 | ): Promise { 51 | return new AbstractContract( 52 | buildArtifact.abi, 53 | buildArtifact.bytecode, 54 | buildArtifact.networks, 55 | links, 56 | artifactName 57 | ) 58 | } 59 | 60 | public static async getNetworkID(wallet: ethers.Wallet): Promise { 61 | return (await wallet.provider.getNetwork()).chainId 62 | } 63 | 64 | /** 65 | * @param abi ABI of the abstract contract 66 | * @param bytecode Binary of the abstract contract 67 | * @param networks Network mapping of deployed addresses 68 | * @param links 69 | * @param contractName 70 | */ 71 | constructor( 72 | readonly abi: string[] | string, 73 | readonly bytecode: string, 74 | readonly networks: NetworkMapping, 75 | readonly links?: { [contractName: string]: Promise }, 76 | readonly contractName?: string 77 | ) {} 78 | 79 | /** 80 | * Get the deployed singleton instance of this abstract contract, if it exists 81 | * @param Signer (with provider) to use for contract calls 82 | * @throws Error if AbstractContract has no deployed address 83 | */ 84 | public async getDeployed(wallet: ethers.Wallet): Promise { 85 | if (!wallet.provider) { 86 | throw new Error('Signer requires provider') 87 | } 88 | const networkId = (await wallet.provider.getNetwork()).chainId 89 | const address = this.getDeployedAddress(networkId) 90 | return new ethers.Contract(address, this.abi, wallet) 91 | } 92 | 93 | /** 94 | * Deploy new instance of contract 95 | * @param wallet Wallet (with provider) to use for contract calls 96 | * @param args Optional arguments to pass to contract constructor 97 | * @returns New contract instance 98 | */ 99 | public async deploy(wallet: ethers.Wallet, args?: any[]): Promise { 100 | if (!wallet.provider) { 101 | throw new Error('Signer requires provider') 102 | } 103 | 104 | const networkId = (await wallet.provider.getNetwork()).chainId 105 | const bytecode = (await this.links) 106 | ? await this.generateLinkedBytecode(networkId) 107 | : this.bytecode 108 | const contractFactory = new ethers.ContractFactory( 109 | this.abi, 110 | bytecode, 111 | wallet 112 | ) 113 | return contractFactory.deploy(...(args || [])) 114 | } 115 | 116 | /** 117 | * Connect to a deployed instance of this abstract contract 118 | * @param signer Signer (with provider) to use for contract calls 119 | * @param address Address of deployed instance to connect to 120 | * @returns Contract instance 121 | */ 122 | public async connect( 123 | signer: ethers.Signer, 124 | address: string 125 | ): Promise { 126 | return new ethers.Contract(address, this.abi, signer) 127 | } 128 | 129 | public getDeployedAddress(networkId: number): string { 130 | const info = this.networks[networkId] 131 | if (!info) { 132 | throw new Error( 133 | `Abstract contract ${ 134 | this.contractName 135 | } not deployed on network ${networkId}` 136 | ) 137 | } 138 | return info.address 139 | } 140 | 141 | public async generateLinkedBytecode(networkId: number): Promise { 142 | if (this.links === undefined) { 143 | throw new Error('Nothing to link') 144 | } 145 | let bytecode = this.bytecode 146 | for (const name of Object.keys(this.links)) { 147 | const library = this.links[name] 148 | const regex = new RegExp(`__${name}_+`, 'g') 149 | const address = (await library).getDeployedAddress(networkId) 150 | const addressHex = address.replace('0x', '') 151 | bytecode = bytecode.replace(regex, addressHex) 152 | } 153 | return bytecode 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /typings/contracts/ERC1155MintBurnPackedBalance.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface ERC1155MintBurnPackedBalanceInterface extends Interface { 14 | functions: { 15 | safeBatchTransferFrom: TypedFunctionDescription<{ 16 | encode([_from, _to, _ids, _amounts, _data]: [ 17 | string, 18 | string, 19 | (BigNumberish)[], 20 | (BigNumberish)[], 21 | Arrayish 22 | ]): string; 23 | }>; 24 | 25 | safeTransferFrom: TypedFunctionDescription<{ 26 | encode([_from, _to, _id, _amount, _data]: [ 27 | string, 28 | string, 29 | BigNumberish, 30 | BigNumberish, 31 | Arrayish 32 | ]): string; 33 | }>; 34 | 35 | setApprovalForAll: TypedFunctionDescription<{ 36 | encode([_operator, _approved]: [string, boolean]): string; 37 | }>; 38 | }; 39 | 40 | events: { 41 | ApprovalForAll: TypedEventDescription<{ 42 | encodeTopics([_owner, _operator, _approved]: [ 43 | string | null, 44 | string | null, 45 | null 46 | ]): string[]; 47 | }>; 48 | 49 | TransferBatch: TypedEventDescription<{ 50 | encodeTopics([_operator, _from, _to, _ids, _amounts]: [ 51 | string | null, 52 | string | null, 53 | string | null, 54 | null, 55 | null 56 | ]): string[]; 57 | }>; 58 | 59 | TransferSingle: TypedEventDescription<{ 60 | encodeTopics([_operator, _from, _to, _id, _amount]: [ 61 | string | null, 62 | string | null, 63 | string | null, 64 | null, 65 | null 66 | ]): string[]; 67 | }>; 68 | 69 | URI: TypedEventDescription<{ 70 | encodeTopics([_uri, _id]: [null, BigNumberish | null]): string[]; 71 | }>; 72 | }; 73 | } 74 | 75 | export class ERC1155MintBurnPackedBalance extends Contract { 76 | connect( 77 | signerOrProvider: Signer | Provider | string 78 | ): ERC1155MintBurnPackedBalance; 79 | attach(addressOrName: string): ERC1155MintBurnPackedBalance; 80 | deployed(): Promise; 81 | 82 | on( 83 | event: EventFilter | string, 84 | listener: Listener 85 | ): ERC1155MintBurnPackedBalance; 86 | once( 87 | event: EventFilter | string, 88 | listener: Listener 89 | ): ERC1155MintBurnPackedBalance; 90 | addListener( 91 | eventName: EventFilter | string, 92 | listener: Listener 93 | ): ERC1155MintBurnPackedBalance; 94 | removeAllListeners( 95 | eventName: EventFilter | string 96 | ): ERC1155MintBurnPackedBalance; 97 | removeListener( 98 | eventName: any, 99 | listener: Listener 100 | ): ERC1155MintBurnPackedBalance; 101 | 102 | interface: ERC1155MintBurnPackedBalanceInterface; 103 | 104 | functions: { 105 | balanceOf(_owner: string, _id: BigNumberish): Promise; 106 | 107 | balanceOfBatch( 108 | _owners: (string)[], 109 | _ids: (BigNumberish)[] 110 | ): Promise<(BigNumber)[]>; 111 | 112 | getIDBinIndex( 113 | _id: BigNumberish 114 | ): Promise<{ 115 | bin: BigNumber; 116 | index: BigNumber; 117 | 0: BigNumber; 118 | 1: BigNumber; 119 | }>; 120 | 121 | getValueInBin( 122 | _binAmount: BigNumberish, 123 | _index: BigNumberish 124 | ): Promise; 125 | 126 | isApprovedForAll(_owner: string, _operator: string): Promise; 127 | 128 | supportsInterface(_interfaceID: Arrayish): Promise; 129 | 130 | safeBatchTransferFrom( 131 | _from: string, 132 | _to: string, 133 | _ids: (BigNumberish)[], 134 | _amounts: (BigNumberish)[], 135 | _data: Arrayish, 136 | overrides?: TransactionOverrides 137 | ): Promise; 138 | 139 | safeTransferFrom( 140 | _from: string, 141 | _to: string, 142 | _id: BigNumberish, 143 | _amount: BigNumberish, 144 | _data: Arrayish, 145 | overrides?: TransactionOverrides 146 | ): Promise; 147 | 148 | setApprovalForAll( 149 | _operator: string, 150 | _approved: boolean, 151 | overrides?: TransactionOverrides 152 | ): Promise; 153 | }; 154 | 155 | filters: { 156 | ApprovalForAll( 157 | _owner: string | null, 158 | _operator: string | null, 159 | _approved: null 160 | ): EventFilter; 161 | 162 | TransferBatch( 163 | _operator: string | null, 164 | _from: string | null, 165 | _to: string | null, 166 | _ids: null, 167 | _amounts: null 168 | ): EventFilter; 169 | 170 | TransferSingle( 171 | _operator: string | null, 172 | _from: string | null, 173 | _to: string | null, 174 | _id: null, 175 | _amount: null 176 | ): EventFilter; 177 | 178 | URI(_uri: null, _id: BigNumberish | null): EventFilter; 179 | }; 180 | 181 | estimate: { 182 | safeBatchTransferFrom( 183 | _from: string, 184 | _to: string, 185 | _ids: (BigNumberish)[], 186 | _amounts: (BigNumberish)[], 187 | _data: Arrayish 188 | ): Promise; 189 | 190 | safeTransferFrom( 191 | _from: string, 192 | _to: string, 193 | _id: BigNumberish, 194 | _amount: BigNumberish, 195 | _data: Arrayish 196 | ): Promise; 197 | 198 | setApprovalForAll( 199 | _operator: string, 200 | _approved: boolean 201 | ): Promise; 202 | }; 203 | } 204 | -------------------------------------------------------------------------------- /typings/contracts/ERC1155OperatorMock.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface ERC1155OperatorMockInterface extends Interface { 14 | functions: { 15 | safeTransferFrom: TypedFunctionDescription<{ 16 | encode([_tokenAddress, _from, _to, _id, _amount, _data]: [ 17 | string, 18 | string, 19 | string, 20 | BigNumberish, 21 | BigNumberish, 22 | Arrayish 23 | ]): string; 24 | }>; 25 | 26 | safeBatchTransferFrom: TypedFunctionDescription<{ 27 | encode([_tokenAddress, _from, _to, _ids, _amounts, _data]: [ 28 | string, 29 | string, 30 | string, 31 | (BigNumberish)[], 32 | (BigNumberish)[], 33 | Arrayish 34 | ]): string; 35 | }>; 36 | 37 | metaSafeTransferFrom: TypedFunctionDescription<{ 38 | encode([_tokenAddress, _from, _to, _id, _amount, _isGasFee, _data]: [ 39 | string, 40 | string, 41 | string, 42 | BigNumberish, 43 | BigNumberish, 44 | boolean, 45 | Arrayish 46 | ]): string; 47 | }>; 48 | 49 | metaSafeBatchTransferFrom: TypedFunctionDescription<{ 50 | encode([_tokenAddress, _from, _to, _ids, _amounts, _isGasFee, _data]: [ 51 | string, 52 | string, 53 | string, 54 | (BigNumberish)[], 55 | (BigNumberish)[], 56 | boolean, 57 | Arrayish 58 | ]): string; 59 | }>; 60 | 61 | metaSetApprovalForAll: TypedFunctionDescription<{ 62 | encode([_tokenAddress, _owner, _operator, _approved, _isGasFee, _data]: [ 63 | string, 64 | string, 65 | string, 66 | boolean, 67 | boolean, 68 | Arrayish 69 | ]): string; 70 | }>; 71 | }; 72 | 73 | events: {}; 74 | } 75 | 76 | export class ERC1155OperatorMock extends Contract { 77 | connect(signerOrProvider: Signer | Provider | string): ERC1155OperatorMock; 78 | attach(addressOrName: string): ERC1155OperatorMock; 79 | deployed(): Promise; 80 | 81 | on(event: EventFilter | string, listener: Listener): ERC1155OperatorMock; 82 | once(event: EventFilter | string, listener: Listener): ERC1155OperatorMock; 83 | addListener( 84 | eventName: EventFilter | string, 85 | listener: Listener 86 | ): ERC1155OperatorMock; 87 | removeAllListeners(eventName: EventFilter | string): ERC1155OperatorMock; 88 | removeListener(eventName: any, listener: Listener): ERC1155OperatorMock; 89 | 90 | interface: ERC1155OperatorMockInterface; 91 | 92 | functions: { 93 | safeTransferFrom( 94 | _tokenAddress: string, 95 | _from: string, 96 | _to: string, 97 | _id: BigNumberish, 98 | _amount: BigNumberish, 99 | _data: Arrayish, 100 | overrides?: TransactionOverrides 101 | ): Promise; 102 | 103 | safeBatchTransferFrom( 104 | _tokenAddress: string, 105 | _from: string, 106 | _to: string, 107 | _ids: (BigNumberish)[], 108 | _amounts: (BigNumberish)[], 109 | _data: Arrayish, 110 | overrides?: TransactionOverrides 111 | ): Promise; 112 | 113 | metaSafeTransferFrom( 114 | _tokenAddress: string, 115 | _from: string, 116 | _to: string, 117 | _id: BigNumberish, 118 | _amount: BigNumberish, 119 | _isGasFee: boolean, 120 | _data: Arrayish, 121 | overrides?: TransactionOverrides 122 | ): Promise; 123 | 124 | metaSafeBatchTransferFrom( 125 | _tokenAddress: string, 126 | _from: string, 127 | _to: string, 128 | _ids: (BigNumberish)[], 129 | _amounts: (BigNumberish)[], 130 | _isGasFee: boolean, 131 | _data: Arrayish, 132 | overrides?: TransactionOverrides 133 | ): Promise; 134 | 135 | metaSetApprovalForAll( 136 | _tokenAddress: string, 137 | _owner: string, 138 | _operator: string, 139 | _approved: boolean, 140 | _isGasFee: boolean, 141 | _data: Arrayish, 142 | overrides?: TransactionOverrides 143 | ): Promise; 144 | }; 145 | 146 | filters: {}; 147 | 148 | estimate: { 149 | safeTransferFrom( 150 | _tokenAddress: string, 151 | _from: string, 152 | _to: string, 153 | _id: BigNumberish, 154 | _amount: BigNumberish, 155 | _data: Arrayish 156 | ): Promise; 157 | 158 | safeBatchTransferFrom( 159 | _tokenAddress: string, 160 | _from: string, 161 | _to: string, 162 | _ids: (BigNumberish)[], 163 | _amounts: (BigNumberish)[], 164 | _data: Arrayish 165 | ): Promise; 166 | 167 | metaSafeTransferFrom( 168 | _tokenAddress: string, 169 | _from: string, 170 | _to: string, 171 | _id: BigNumberish, 172 | _amount: BigNumberish, 173 | _isGasFee: boolean, 174 | _data: Arrayish 175 | ): Promise; 176 | 177 | metaSafeBatchTransferFrom( 178 | _tokenAddress: string, 179 | _from: string, 180 | _to: string, 181 | _ids: (BigNumberish)[], 182 | _amounts: (BigNumberish)[], 183 | _isGasFee: boolean, 184 | _data: Arrayish 185 | ): Promise; 186 | 187 | metaSetApprovalForAll( 188 | _tokenAddress: string, 189 | _owner: string, 190 | _operator: string, 191 | _approved: boolean, 192 | _isGasFee: boolean, 193 | _data: Arrayish 194 | ): Promise; 195 | }; 196 | } 197 | -------------------------------------------------------------------------------- /contracts/mocks/ERC1155OperatorMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | 3 | import "../interfaces/IERC1155.sol"; 4 | import "../interfaces/IERC1155Meta.sol"; 5 | 6 | 7 | /** 8 | * @dev Contract that acts as an operator contract. 9 | */ 10 | contract ERC1155OperatorMock { 11 | 12 | /****************************************| 13 | | Public Regular Transfer Functions | 14 | |_______________________________________*/ 15 | 16 | /** 17 | * @dev Allow _from or an operator to transfer tokens from one address to another 18 | * @param _tokenAddress The address of the token contract to call 19 | * @param _from The address which you want to send tokens from 20 | * @param _to The address which you want to transfer to 21 | * @param _id token id to update balance of 22 | * @param _amount The amount of tokens of provided token ID to be transferred 23 | * @param _data Data to pass to onERC1155Received() function if recipient is contract 24 | */ 25 | function safeTransferFrom( 26 | address _tokenAddress, 27 | address _from, 28 | address _to, 29 | uint256 _id, 30 | uint256 _amount, 31 | bytes memory _data) 32 | public 33 | { 34 | IERC1155(_tokenAddress).safeTransferFrom(_from, _to, _id, _amount, _data); 35 | } 36 | 37 | /** 38 | * @dev transfer objects from different ids to specified address 39 | * @param _tokenAddress The address of the token contract to call 40 | * @param _from The address to batchTransfer objects from. 41 | * @param _to The address to batchTransfer objects to. 42 | * @param _ids Array of ids to update balance of 43 | * @param _amounts Array of amount of object per id to be transferred. 44 | * @param _data Data to pass to onERC1155Received() function if recipient is contract 45 | * Note: Arrays should be sorted so that all ids in a same bin are adjacent (more efficient). 46 | */ 47 | function safeBatchTransferFrom( 48 | address _tokenAddress, 49 | address _from, 50 | address _to, 51 | uint256[] memory _ids, 52 | uint256[] memory _amounts, 53 | bytes memory _data) 54 | public 55 | { 56 | IERC1155(_tokenAddress).safeBatchTransferFrom(_from, _to, _ids, _amounts, _data); 57 | } 58 | 59 | /****************************************| 60 | | Public Meta Transfer Functions | 61 | |_______________________________________*/ 62 | 63 | /** 64 | * @notice Allows anyone with a valid signature to transfer _amount amount of a token _id on the bahalf of _from 65 | * @param _tokenAddress The address of the token contract to call 66 | * @param _from Source address 67 | * @param _to Target address 68 | * @param _id ID of the token type 69 | * @param _amount Transfered amount 70 | * @param _isGasFee Whether gas is reimbursed to executor or not 71 | * @param _data Encodes a meta transfer indicator, signature, gas payment receipt and extra transfer data 72 | * _data should be encoded as ((bytes32 r, bytes32 s, uint8 v, SignatureType sigType), (GasReceipt g, bytes data)) 73 | * i.e. high level encoding should be (bytes, bytes), where the latter bytes array is a nested bytes array 74 | */ 75 | function metaSafeTransferFrom( 76 | address _tokenAddress, 77 | address _from, 78 | address _to, 79 | uint256 _id, 80 | uint256 _amount, 81 | bool _isGasFee, 82 | bytes memory _data) 83 | public 84 | { 85 | IERC1155Meta(_tokenAddress).metaSafeTransferFrom(_from, _to, _id, _amount, _isGasFee, _data); 86 | } 87 | 88 | 89 | /** 90 | * @notice Allows anyone with a valid signature to transfer multiple types of tokens on the bahalf of _from 91 | * @param _tokenAddress The address of the token contract to call 92 | * @param _from Source addresses 93 | * @param _to Target addresses 94 | * @param _ids IDs of each token type 95 | * @param _amounts Transfer amounts per token type 96 | * @param _data Encodes a meta transfer indicator, signature, gas payment receipt and extra transfer data 97 | * _data should be encoded as ((bytes32 r, bytes32 s, uint8 v, SignatureType sigType), (GasReceipt g, bytes data)) 98 | * i.e. high level encoding should be (bytes, bytes), where the latter bytes array is a nested bytes array 99 | */ 100 | function metaSafeBatchTransferFrom( 101 | address _tokenAddress, 102 | address _from, 103 | address _to, 104 | uint256[] memory _ids, 105 | uint256[] memory _amounts, 106 | bool _isGasFee, 107 | bytes memory _data) 108 | public 109 | { 110 | IERC1155Meta(_tokenAddress).metaSafeBatchTransferFrom(_from, _to, _ids, _amounts, _isGasFee, _data); 111 | } 112 | 113 | 114 | /***********************************| 115 | | Operator Functions | 116 | |__________________________________*/ 117 | 118 | /** 119 | * @notice Approve the passed address to spend on behalf of _from if valid signature is provided 120 | * @param _tokenAddress The address of the token contract to call 121 | * @param _owner Address that wants to set operator status _spender 122 | * @param _operator Address to add to the set of authorized operators 123 | * @param _approved True if the operator is approved, false to revoke approval 124 | * @param _isGasFee Whether gas will be reimbursed or not, with vlid signature 125 | * @param _data Encodes signature and gas payment receipt 126 | * _data should be encoded as ((bytes32 r, bytes32 s, uint8 v, SignatureType sigType), (GasReceipt g)) 127 | * i.e. high level encoding should be (bytes, bytes), where the latter bytes array is a nested bytes array 128 | */ 129 | function metaSetApprovalForAll( 130 | address _tokenAddress, 131 | address _owner, 132 | address _operator, 133 | bool _approved, 134 | bool _isGasFee, 135 | bytes memory _data) 136 | public 137 | { 138 | IERC1155Meta(_tokenAddress).metaSetApprovalForAll(_owner, _operator, _approved, _isGasFee, _data); 139 | } 140 | 141 | } -------------------------------------------------------------------------------- /contracts/mocks/ERC1155ReceiverMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | 3 | import '../interfaces/IERC1155.sol'; 4 | 5 | 6 | // Contract to test safe transfer behavior. 7 | contract ERC1155ReceiverMock { 8 | bytes4 constant internal ERC1155_RECEIVED_SIG = 0xf23a6e61; 9 | bytes4 constant internal ERC1155_BATCH_RECEIVED_SIG = 0xbc197c81; 10 | bytes4 constant internal ERC1155_RECEIVED_INVALID = 0xdeadbeef; 11 | bytes4 constant internal IS_ERC1155_RECEIVER = 0x0d912442; //bytes4(keccak256("isERC1155TokenReceiver()")); 12 | 13 | // Keep values from last received contract. 14 | bool public shouldReject; 15 | 16 | bytes public lastData; 17 | address public lastOperator; 18 | uint256 public lastId; 19 | uint256 public lastValue; 20 | 21 | //Debug event 22 | event TransferSingleReceiver(address _from, address _to, uint256 _fromBalance, uint256 _toBalance); 23 | event TransferBatchReceiver(address _from, address _to, uint256[] _fromBalances, uint256[] _toBalances); 24 | 25 | function setShouldReject(bool _value) public { 26 | shouldReject = _value; 27 | } 28 | 29 | /** 30 | * @notice Handle the receipt of a single ERC1155 token type. 31 | * @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeTransferFrom` after the balance has been updated. 32 | * This function MAY throw to revert and reject the transfer. 33 | * Return of other than the magic value MUST result in the transaction being reverted. 34 | * Note: The contract address is always the message sender. 35 | * @param _operator The address which called the `safeTransferFrom` function 36 | * @param _from The address which previously owned the token 37 | * @param _id The id of the token being transferred 38 | * @param _value The amount of tokens being transferred 39 | * @param _data Additional data with no specified format 40 | * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` 41 | */ 42 | function onERC1155Received(address _operator, address _from, uint256 _id, uint256 _value, bytes memory _data) 43 | public returns(bytes4) 44 | { 45 | // To check the following conditions; 46 | // All the balances in the transfer MUST have been updated to match the senders intent before any hook is called on a recipient. 47 | // All the transfer events for the transfer MUST have been emitted to reflect the balance changes before any hook is called on a recipient. 48 | uint256 fromBalance = IERC1155(msg.sender).balanceOf(_from, _id); 49 | uint256 toBalance = IERC1155(msg.sender).balanceOf(address(this), _id); 50 | emit TransferSingleReceiver(_from, address(this), fromBalance, toBalance); 51 | 52 | if (shouldReject == true) { 53 | return ERC1155_RECEIVED_INVALID; // Some random value 54 | } else { 55 | return ERC1155_RECEIVED_SIG; 56 | } 57 | } 58 | 59 | /** 60 | * @notice Handle the receipt of multiple ERC1155 token types. 61 | * @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeBatchTransferFrom` after the balances have been updated. 62 | * This function MAY throw to revert and reject the transfer. 63 | * Return of other than the magic value WILL result in the transaction being reverted. 64 | * Note: The contract address is always the message sender. 65 | * @param _operator The address which called the `safeBatchTransferFrom` function 66 | * @param _from The address which previously owned the token 67 | * @param _ids An array containing ids of each token being transferred 68 | * @param _values An array containing amounts of each token being transferred 69 | * @param _data Additional data with no specified format 70 | * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` 71 | */ 72 | function onERC1155BatchReceived(address _operator, address _from, uint256[] memory _ids, uint256[] memory _values, bytes memory _data) 73 | public returns(bytes4) 74 | { 75 | // To check the following conditions; 76 | // All the balances in the transfer MUST have been updated to match the senders intent before any hook is called on a recipient. 77 | // All the transfer events for the transfer MUST have been emitted to reflect the balance changes before any hook is called on a recipient. 78 | address[] memory fromAddressArray = new address[](_ids.length); 79 | address[] memory toAddressArray = new address[](_ids.length); 80 | for (uint i = 0; i < _ids.length; i++ ) { 81 | fromAddressArray[i] = _from; 82 | toAddressArray[i] = (address(this)); 83 | } 84 | uint256[] memory fromBalances = IERC1155(msg.sender).balanceOfBatch(fromAddressArray, _ids); 85 | uint256[] memory toBalances = IERC1155(msg.sender).balanceOfBatch(toAddressArray, _ids); 86 | emit TransferBatchReceiver(_from, address(this), fromBalances, toBalances); 87 | 88 | if (shouldReject == true) { 89 | return ERC1155_RECEIVED_INVALID; // Some random value 90 | } else { 91 | return ERC1155_BATCH_RECEIVED_SIG; 92 | } 93 | } 94 | 95 | /** 96 | * @notice Indicates whether a contract implements the `ERC1155TokenReceiver` functions and so can accept ERC1155 token types. 97 | * @param interfaceID The ERC-165 interface ID that is queried for support.s 98 | * @dev This function MUST return true if it implements the ERC1155TokenReceiver interface and ERC-165 interface. 99 | * This function MUST NOT consume more than 5,000 gas. 100 | * @return Wheter ERC-165 or ERC1155TokenReceiver interfaces are supported. 101 | */ 102 | function supportsInterface(bytes4 interfaceID) external view returns (bool) { 103 | return interfaceID == 0x01ffc9a7 || // ERC-165 support (i.e. `bytes4(keccak256('supportsInterface(bytes4)'))`). 104 | interfaceID == 0x4e2312e0; // ERC-1155 `ERC1155TokenReceiver` support (i.e. `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)")) ^ bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`). 105 | } 106 | 107 | } -------------------------------------------------------------------------------- /contracts/interfaces/IERC1155.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | 3 | 4 | interface IERC1155 { 5 | // Events 6 | 7 | /** 8 | * @dev Either TransferSingle or TransferBatch MUST emit when tokens are transferred, including zero amount transfers as well as minting or burning 9 | * Operator MUST be msg.sender 10 | * When minting/creating tokens, the `_from` field MUST be set to `0x0` 11 | * When burning/destroying tokens, the `_to` field MUST be set to `0x0` 12 | * The total amount transferred from address 0x0 minus the total amount transferred to 0x0 may be used by clients and exchanges to be added to the "circulating supply" for a given token ID 13 | * To broadcast the existence of a token ID with no initial balance, the contract SHOULD emit the TransferSingle event from `0x0` to `0x0`, with the token creator as `_operator`, and a `_amount` of 0 14 | */ 15 | event TransferSingle(address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _amount); 16 | 17 | /** 18 | * @dev Either TransferSingle or TransferBatch MUST emit when tokens are transferred, including zero amount transfers as well as minting or burning 19 | * Operator MUST be msg.sender 20 | * When minting/creating tokens, the `_from` field MUST be set to `0x0` 21 | * When burning/destroying tokens, the `_to` field MUST be set to `0x0` 22 | * The total amount transferred from address 0x0 minus the total amount transferred to 0x0 may be used by clients and exchanges to be added to the "circulating supply" for a given token ID 23 | * To broadcast the existence of multiple token IDs with no initial balance, this SHOULD emit the TransferBatch event from `0x0` to `0x0`, with the token creator as `_operator`, and a `_amount` of 0 24 | */ 25 | event TransferBatch(address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _amounts); 26 | 27 | /** 28 | * @dev MUST emit when an approval is updated 29 | */ 30 | event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); 31 | 32 | /** 33 | * @dev MUST emit when the URI is updated for a token ID 34 | * URIs are defined in RFC 3986 35 | * The URI MUST point a JSON file that conforms to the "ERC-1155 Metadata JSON Schema" 36 | */ 37 | event URI(string _amount, uint256 indexed _id); 38 | 39 | /** 40 | * @notice Transfers amount of an _id from the _from address to the _to address specified 41 | * @dev MUST emit TransferSingle event on success 42 | * Caller must be approved to manage the _from account's tokens (see isApprovedForAll) 43 | * MUST throw if `_to` is the zero address 44 | * MUST throw if balance of sender for token `_id` is lower than the `_amount` sent 45 | * MUST throw on any other error 46 | * 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 amount is not `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` 47 | * @param _from Source address 48 | * @param _to Target address 49 | * @param _id ID of the token type 50 | * @param _amount Transfered amount 51 | * @param _data Additional data with no specified format, sent in call to `_to` 52 | */ 53 | function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _amount, bytes calldata _data) external; 54 | 55 | /** 56 | * @notice Send multiple types of Tokens from the _from address to the _to address (with safety call) 57 | * @dev MUST emit TransferBatch event on success 58 | * Caller must be approved to manage the _from account's tokens (see isApprovedForAll) 59 | * MUST throw if `_to` is the zero address 60 | * MUST throw if length of `_ids` is not the same as length of `_amounts` 61 | * MUST throw if any of the balance of sender for token `_ids` is lower than the respective `_amounts` sent 62 | * MUST throw on any other error 63 | * 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 amount is not `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` 64 | * Transfers and events MUST occur in the array order they were submitted (_ids[0] before _ids[1], etc) 65 | * @param _from Source addresses 66 | * @param _to Target addresses 67 | * @param _ids IDs of each token type 68 | * @param _amounts Transfer amounts per token type 69 | * @param _data Additional data with no specified format, sent in call to `_to` 70 | */ 71 | function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _amounts, bytes calldata _data) external; 72 | 73 | /** 74 | * @notice Get the balance of an account's Tokens 75 | * @param _owner The address of the token holder 76 | * @param _id ID of the Token 77 | * @return The _owner's balance of the Token type requested 78 | */ 79 | function balanceOf(address _owner, uint256 _id) external view returns (uint256); 80 | 81 | /** 82 | * @notice Get the balance of multiple account/token pairs 83 | * @param _owners The addresses of the token holders 84 | * @param _ids ID of the Tokens 85 | * @return The _owner's balance of the Token types requested (i.e. balance for each (owner, id) pair) 86 | */ 87 | function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory); 88 | 89 | /** 90 | * @notice Enable or disable approval for a third party ("operator") to manage all of caller's tokens 91 | * @dev MUST emit the ApprovalForAll event on success 92 | * @param _operator Address to add to the set of authorized operators 93 | * @param _approved True if the operator is approved, false to revoke approval 94 | */ 95 | function setApprovalForAll(address _operator, bool _approved) external; 96 | 97 | /** 98 | * @notice Queries the approval status of an operator for a given owner 99 | * @param _owner The owner of the Tokens 100 | * @param _operator Address of authorized operator 101 | * @return True if the operator is approved, false if not 102 | */ 103 | function isApprovedForAll(address _owner, address _operator) external view returns (bool isOperator); 104 | 105 | } 106 | -------------------------------------------------------------------------------- /src/tests/SignatureValidator.spec.ts: -------------------------------------------------------------------------------- 1 | import * as ethers from 'ethers' 2 | 3 | import { AbstractContract, expect, RevertError, ethSign, eip712Sign } from './utils' 4 | import * as utils from './utils' 5 | 6 | import { SignatureValidator } from 'typings/contracts/SignatureValidator' 7 | import { ERC1271WalletMock } from 'typings/contracts/ERC1271WalletMock' 8 | import { AddressZero } from 'ethers/constants'; 9 | 10 | // init test wallets from package.json mnemonic 11 | const web3 = (global as any).web3 12 | 13 | const { 14 | wallet: signerWallet, 15 | provider: signerProvider, 16 | signer: signerSigner 17 | } = utils.createTestWallet(web3, 0) 18 | 19 | contract('SignatureValidator Contract', (accounts: string[]) => { 20 | 21 | let signerAddress: string 22 | let signatureValidatorAbstract: AbstractContract 23 | let ERC1271WalletMockAbstract: AbstractContract 24 | let signatureValidatorContract: SignatureValidator 25 | let erc1271WalletMockContract: ERC1271WalletMock 26 | 27 | // load contract abi and deploy to test server 28 | before(async () => { 29 | signerAddress = await signerWallet.getAddress() 30 | signatureValidatorAbstract = await AbstractContract.fromArtifactName('SignatureValidator') 31 | }) 32 | 33 | // deploy before each test, to reset state of contract 34 | beforeEach(async () => { 35 | signatureValidatorContract = await signatureValidatorAbstract.deploy(signerWallet) as SignatureValidator 36 | }) 37 | 38 | describe('isValidSignature() Function', () => { 39 | 40 | let data = ethers.utils.toUtf8Bytes('Did the Ethereum blockchain reach 1TB yet? No.') 41 | let dataHash = ethers.utils.keccak256(data) 42 | let ethsig: string 43 | let eip712sig: string 44 | 45 | beforeEach(async () => { 46 | ethsig = await ethSign(signerWallet, data) 47 | }) 48 | 49 | it('should REVERT if signature is of length 0', async () => { 50 | // @ts-ignore 51 | const tx = signatureValidatorContract.functions.isValidSignature(signerAddress, dataHash, data, []) 52 | await expect(tx).to.be.rejectedWith( RevertError("SignatureValidator#isValidSignature: LENGTH_GREATER_THAN_0_REQUIRED") ) 53 | }) 54 | 55 | it('should REVERT if expected signer is 0x0', async () => { 56 | // @ts-ignore 57 | const tx = signatureValidatorContract.functions.isValidSignature(AddressZero, dataHash, data, ethsig) 58 | await expect(tx).to.be.rejectedWith( RevertError("SignatureValidator#isValidSignature: INVALID_SIGNER") ) 59 | }) 60 | 61 | it('should REVERT if signature is illigal (SignatureType: 0x0)', async () => { 62 | // @ts-ignore 63 | const tx = signatureValidatorContract.functions.isValidSignature(signerAddress, dataHash, data, ethsig.slice(0, -2) + '00') 64 | await expect(tx).to.be.rejectedWith( RevertError("SignatureValidator#isValidSignature: ILLEGAL_SIGNATURE") ) 65 | }) 66 | 67 | it('should REVERT if signatureType is above 05', async () => { 68 | // @ts-ignore 69 | const tx = signatureValidatorContract.functions.isValidSignature(signerAddress, dataHash, data, ethsig.slice(0, -2) + '06') 70 | await expect(tx).to.be.rejectedWith( RevertError("SignatureValidator#isValidSignature: UNSUPPORTED_SIGNATURE") ) 71 | }) 72 | 73 | describe(`EIP-712 signatures`, () => { 74 | 75 | beforeEach(async () => { 76 | eip712sig = await eip712Sign(signerWallet, data) 77 | }) 78 | 79 | it('should REVERT if signature length is not 65', async () => { 80 | // @ts-ignore 81 | const tx = signatureValidatorContract.functions.isValidSignature(signerAddress, dataHash, data, '0x1234' + eip712sig.slice(2) ) 82 | await expect(tx).to.be.rejectedWith( RevertError("SignatureValidator#isValidSignature: LENGTH_65_REQUIRED") ) 83 | }) 84 | 85 | it('should return TRUE if signature is valid', async () => { 86 | // @ts-ignore 87 | let isValid = await signatureValidatorContract.functions.isValidSignature(signerAddress, dataHash, data, eip712sig) 88 | await expect(isValid).to.be.equal(true); 89 | }) 90 | 91 | }) 92 | 93 | describe(`ETH_SIGN signatures`, () => { 94 | 95 | it('should REVERT if signature length is not 65', async () => { 96 | // @ts-ignore 97 | const tx = signatureValidatorContract.functions.isValidSignature(signerAddress, dataHash, data, '0x1234' + ethsig.slice(2)) 98 | await expect(tx).to.be.rejectedWith( RevertError("SignatureValidator#isValidSignature: LENGTH_65_REQUIRED") ) 99 | }) 100 | 101 | it('should return TRUE if signature is valid', async () => { 102 | // @ts-ignore 103 | let isValid = await signatureValidatorContract.functions.isValidSignature(signerAddress, dataHash, data, ethsig) 104 | expect(isValid).to.be.equal(true); 105 | }) 106 | 107 | }) 108 | 109 | describe(`EIP-1271 (bytes) signatures (03)`, () => { 110 | let erc1271WalletAddress; 111 | 112 | beforeEach( async () => { 113 | ERC1271WalletMockAbstract = await AbstractContract.fromArtifactName('ERC1271WalletMock') 114 | erc1271WalletMockContract = await ERC1271WalletMockAbstract.deploy(signerWallet) as ERC1271WalletMock 115 | erc1271WalletAddress = erc1271WalletMockContract.address; 116 | }) 117 | 118 | it('should return FALSE if contract returns incorrect magic value', async () => { 119 | // @ts-ignore 120 | let isValid = await signatureValidatorContract.functions.isValidSignature(erc1271WalletAddress, dataHash, data, ethsig + '03') 121 | expect(isValid).to.be.equal(false) 122 | }) 123 | 124 | it('should return TRUE if contract returns correct magic value', async () => { 125 | await erc1271WalletMockContract.functions.setShouldReject(false) 126 | 127 | // @ts-ignore 128 | let isValid = await signatureValidatorContract.functions.isValidSignature(erc1271WalletAddress, dataHash, data, ethsig + '03') 129 | await expect(isValid).to.be.equal(true); 130 | }) 131 | }) 132 | 133 | describe(`EIP-1271 (bytes32) signatures (04)`, () => { 134 | let erc1271WalletAddress; 135 | 136 | beforeEach( async () => { 137 | ERC1271WalletMockAbstract = await AbstractContract.fromArtifactName('ERC1271WalletMock') 138 | erc1271WalletMockContract = await ERC1271WalletMockAbstract.deploy(signerWallet) as ERC1271WalletMock 139 | erc1271WalletAddress = erc1271WalletMockContract.address; 140 | }) 141 | 142 | it('should return FALSE if contract returns incorrect magic value', async () => { 143 | // @ts-ignore 144 | let isValid = await signatureValidatorContract.functions.isValidSignature(erc1271WalletAddress, dataHash, data, ethsig + '04') 145 | expect(isValid).to.be.equal(false) 146 | }) 147 | 148 | it('should return TRUE if contract returns correct magic value', async () => { 149 | await erc1271WalletMockContract.functions.setShouldReject(false) 150 | 151 | // @ts-ignore 152 | let isValid = await signatureValidatorContract.functions.isValidSignature(erc1271WalletAddress, dataHash, data, ethsig + '04') 153 | await expect(isValid).to.be.equal(true); 154 | }) 155 | }) 156 | 157 | 158 | }) 159 | }) -------------------------------------------------------------------------------- /typings/contracts/ERC1155Meta.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface ERC1155MetaInterface extends Interface { 14 | functions: { 15 | safeBatchTransferFrom: TypedFunctionDescription<{ 16 | encode([_from, _to, _ids, _amounts, _data]: [ 17 | string, 18 | string, 19 | (BigNumberish)[], 20 | (BigNumberish)[], 21 | Arrayish 22 | ]): string; 23 | }>; 24 | 25 | safeTransferFrom: TypedFunctionDescription<{ 26 | encode([_from, _to, _id, _amount, _data]: [ 27 | string, 28 | string, 29 | BigNumberish, 30 | BigNumberish, 31 | Arrayish 32 | ]): string; 33 | }>; 34 | 35 | setApprovalForAll: TypedFunctionDescription<{ 36 | encode([_operator, _approved]: [string, boolean]): string; 37 | }>; 38 | 39 | metaSafeTransferFrom: TypedFunctionDescription<{ 40 | encode([_from, _to, _id, _amount, _isGasFee, _data]: [ 41 | string, 42 | string, 43 | BigNumberish, 44 | BigNumberish, 45 | boolean, 46 | Arrayish 47 | ]): string; 48 | }>; 49 | 50 | metaSafeBatchTransferFrom: TypedFunctionDescription<{ 51 | encode([_from, _to, _ids, _amounts, _isGasFee, _data]: [ 52 | string, 53 | string, 54 | (BigNumberish)[], 55 | (BigNumberish)[], 56 | boolean, 57 | Arrayish 58 | ]): string; 59 | }>; 60 | 61 | metaSetApprovalForAll: TypedFunctionDescription<{ 62 | encode([_owner, _operator, _approved, _isGasFee, _data]: [ 63 | string, 64 | string, 65 | boolean, 66 | boolean, 67 | Arrayish 68 | ]): string; 69 | }>; 70 | }; 71 | 72 | events: { 73 | ApprovalForAll: TypedEventDescription<{ 74 | encodeTopics([_owner, _operator, _approved]: [ 75 | string | null, 76 | string | null, 77 | null 78 | ]): string[]; 79 | }>; 80 | 81 | TransferBatch: TypedEventDescription<{ 82 | encodeTopics([_operator, _from, _to, _ids, _amounts]: [ 83 | string | null, 84 | string | null, 85 | string | null, 86 | null, 87 | null 88 | ]): string[]; 89 | }>; 90 | 91 | TransferSingle: TypedEventDescription<{ 92 | encodeTopics([_operator, _from, _to, _id, _amount]: [ 93 | string | null, 94 | string | null, 95 | string | null, 96 | null, 97 | null 98 | ]): string[]; 99 | }>; 100 | 101 | URI: TypedEventDescription<{ 102 | encodeTopics([_uri, _id]: [null, BigNumberish | null]): string[]; 103 | }>; 104 | }; 105 | } 106 | 107 | export class ERC1155Meta extends Contract { 108 | connect(signerOrProvider: Signer | Provider | string): ERC1155Meta; 109 | attach(addressOrName: string): ERC1155Meta; 110 | deployed(): Promise; 111 | 112 | on(event: EventFilter | string, listener: Listener): ERC1155Meta; 113 | once(event: EventFilter | string, listener: Listener): ERC1155Meta; 114 | addListener(eventName: EventFilter | string, listener: Listener): ERC1155Meta; 115 | removeAllListeners(eventName: EventFilter | string): ERC1155Meta; 116 | removeListener(eventName: any, listener: Listener): ERC1155Meta; 117 | 118 | interface: ERC1155MetaInterface; 119 | 120 | functions: { 121 | balanceOf(_owner: string, _id: BigNumberish): Promise; 122 | 123 | balanceOfBatch( 124 | _owners: (string)[], 125 | _ids: (BigNumberish)[] 126 | ): Promise<(BigNumber)[]>; 127 | 128 | isApprovedForAll(_owner: string, _operator: string): Promise; 129 | 130 | isValidSignature( 131 | _signerAddress: string, 132 | _hash: Arrayish, 133 | _data: Arrayish, 134 | _sig: Arrayish 135 | ): Promise; 136 | 137 | supportsInterface(_interfaceID: Arrayish): Promise; 138 | 139 | getNonce(_signer: string): Promise; 140 | 141 | safeBatchTransferFrom( 142 | _from: string, 143 | _to: string, 144 | _ids: (BigNumberish)[], 145 | _amounts: (BigNumberish)[], 146 | _data: Arrayish, 147 | overrides?: TransactionOverrides 148 | ): Promise; 149 | 150 | safeTransferFrom( 151 | _from: string, 152 | _to: string, 153 | _id: BigNumberish, 154 | _amount: BigNumberish, 155 | _data: Arrayish, 156 | overrides?: TransactionOverrides 157 | ): Promise; 158 | 159 | setApprovalForAll( 160 | _operator: string, 161 | _approved: boolean, 162 | overrides?: TransactionOverrides 163 | ): Promise; 164 | 165 | metaSafeTransferFrom( 166 | _from: string, 167 | _to: string, 168 | _id: BigNumberish, 169 | _amount: BigNumberish, 170 | _isGasFee: boolean, 171 | _data: Arrayish, 172 | overrides?: TransactionOverrides 173 | ): Promise; 174 | 175 | metaSafeBatchTransferFrom( 176 | _from: string, 177 | _to: string, 178 | _ids: (BigNumberish)[], 179 | _amounts: (BigNumberish)[], 180 | _isGasFee: boolean, 181 | _data: Arrayish, 182 | overrides?: TransactionOverrides 183 | ): Promise; 184 | 185 | metaSetApprovalForAll( 186 | _owner: string, 187 | _operator: string, 188 | _approved: boolean, 189 | _isGasFee: boolean, 190 | _data: Arrayish, 191 | overrides?: TransactionOverrides 192 | ): Promise; 193 | }; 194 | 195 | filters: { 196 | ApprovalForAll( 197 | _owner: string | null, 198 | _operator: string | null, 199 | _approved: null 200 | ): EventFilter; 201 | 202 | TransferBatch( 203 | _operator: string | null, 204 | _from: string | null, 205 | _to: string | null, 206 | _ids: null, 207 | _amounts: null 208 | ): EventFilter; 209 | 210 | TransferSingle( 211 | _operator: string | null, 212 | _from: string | null, 213 | _to: string | null, 214 | _id: null, 215 | _amount: null 216 | ): EventFilter; 217 | 218 | URI(_uri: null, _id: BigNumberish | null): EventFilter; 219 | }; 220 | 221 | estimate: { 222 | safeBatchTransferFrom( 223 | _from: string, 224 | _to: string, 225 | _ids: (BigNumberish)[], 226 | _amounts: (BigNumberish)[], 227 | _data: Arrayish 228 | ): Promise; 229 | 230 | safeTransferFrom( 231 | _from: string, 232 | _to: string, 233 | _id: BigNumberish, 234 | _amount: BigNumberish, 235 | _data: Arrayish 236 | ): Promise; 237 | 238 | setApprovalForAll( 239 | _operator: string, 240 | _approved: boolean 241 | ): Promise; 242 | 243 | metaSafeTransferFrom( 244 | _from: string, 245 | _to: string, 246 | _id: BigNumberish, 247 | _amount: BigNumberish, 248 | _isGasFee: boolean, 249 | _data: Arrayish 250 | ): Promise; 251 | 252 | metaSafeBatchTransferFrom( 253 | _from: string, 254 | _to: string, 255 | _ids: (BigNumberish)[], 256 | _amounts: (BigNumberish)[], 257 | _isGasFee: boolean, 258 | _data: Arrayish 259 | ): Promise; 260 | 261 | metaSetApprovalForAll( 262 | _owner: string, 263 | _operator: string, 264 | _approved: boolean, 265 | _isGasFee: boolean, 266 | _data: Arrayish 267 | ): Promise; 268 | }; 269 | } 270 | -------------------------------------------------------------------------------- /typings/contracts/ERC1155MetaPackedBalance.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface ERC1155MetaPackedBalanceInterface extends Interface { 14 | functions: { 15 | safeBatchTransferFrom: TypedFunctionDescription<{ 16 | encode([_from, _to, _ids, _amounts, _data]: [ 17 | string, 18 | string, 19 | (BigNumberish)[], 20 | (BigNumberish)[], 21 | Arrayish 22 | ]): string; 23 | }>; 24 | 25 | safeTransferFrom: TypedFunctionDescription<{ 26 | encode([_from, _to, _id, _amount, _data]: [ 27 | string, 28 | string, 29 | BigNumberish, 30 | BigNumberish, 31 | Arrayish 32 | ]): string; 33 | }>; 34 | 35 | setApprovalForAll: TypedFunctionDescription<{ 36 | encode([_operator, _approved]: [string, boolean]): string; 37 | }>; 38 | 39 | metaSafeTransferFrom: TypedFunctionDescription<{ 40 | encode([_from, _to, _id, _amount, _isGasFee, _data]: [ 41 | string, 42 | string, 43 | BigNumberish, 44 | BigNumberish, 45 | boolean, 46 | Arrayish 47 | ]): string; 48 | }>; 49 | 50 | metaSafeBatchTransferFrom: TypedFunctionDescription<{ 51 | encode([_from, _to, _ids, _amounts, _isGasFee, _data]: [ 52 | string, 53 | string, 54 | (BigNumberish)[], 55 | (BigNumberish)[], 56 | boolean, 57 | Arrayish 58 | ]): string; 59 | }>; 60 | 61 | metaSetApprovalForAll: TypedFunctionDescription<{ 62 | encode([_owner, _operator, _approved, _isGasFee, _data]: [ 63 | string, 64 | string, 65 | boolean, 66 | boolean, 67 | Arrayish 68 | ]): string; 69 | }>; 70 | }; 71 | 72 | events: { 73 | ApprovalForAll: TypedEventDescription<{ 74 | encodeTopics([_owner, _operator, _approved]: [ 75 | string | null, 76 | string | null, 77 | null 78 | ]): string[]; 79 | }>; 80 | 81 | TransferBatch: TypedEventDescription<{ 82 | encodeTopics([_operator, _from, _to, _ids, _amounts]: [ 83 | string | null, 84 | string | null, 85 | string | null, 86 | null, 87 | null 88 | ]): string[]; 89 | }>; 90 | 91 | TransferSingle: TypedEventDescription<{ 92 | encodeTopics([_operator, _from, _to, _id, _amount]: [ 93 | string | null, 94 | string | null, 95 | string | null, 96 | null, 97 | null 98 | ]): string[]; 99 | }>; 100 | 101 | URI: TypedEventDescription<{ 102 | encodeTopics([_uri, _id]: [null, BigNumberish | null]): string[]; 103 | }>; 104 | }; 105 | } 106 | 107 | export class ERC1155MetaPackedBalance extends Contract { 108 | connect( 109 | signerOrProvider: Signer | Provider | string 110 | ): ERC1155MetaPackedBalance; 111 | attach(addressOrName: string): ERC1155MetaPackedBalance; 112 | deployed(): Promise; 113 | 114 | on(event: EventFilter | string, listener: Listener): ERC1155MetaPackedBalance; 115 | once( 116 | event: EventFilter | string, 117 | listener: Listener 118 | ): ERC1155MetaPackedBalance; 119 | addListener( 120 | eventName: EventFilter | string, 121 | listener: Listener 122 | ): ERC1155MetaPackedBalance; 123 | removeAllListeners(eventName: EventFilter | string): ERC1155MetaPackedBalance; 124 | removeListener(eventName: any, listener: Listener): ERC1155MetaPackedBalance; 125 | 126 | interface: ERC1155MetaPackedBalanceInterface; 127 | 128 | functions: { 129 | balanceOf(_owner: string, _id: BigNumberish): Promise; 130 | 131 | balanceOfBatch( 132 | _owners: (string)[], 133 | _ids: (BigNumberish)[] 134 | ): Promise<(BigNumber)[]>; 135 | 136 | getIDBinIndex( 137 | _id: BigNumberish 138 | ): Promise<{ 139 | bin: BigNumber; 140 | index: BigNumber; 141 | 0: BigNumber; 142 | 1: BigNumber; 143 | }>; 144 | 145 | getValueInBin( 146 | _binAmount: BigNumberish, 147 | _index: BigNumberish 148 | ): Promise; 149 | 150 | isApprovedForAll(_owner: string, _operator: string): Promise; 151 | 152 | isValidSignature( 153 | _signerAddress: string, 154 | _hash: Arrayish, 155 | _data: Arrayish, 156 | _sig: Arrayish 157 | ): Promise; 158 | 159 | supportsInterface(_interfaceID: Arrayish): Promise; 160 | 161 | getNonce(_signer: string): Promise; 162 | 163 | safeBatchTransferFrom( 164 | _from: string, 165 | _to: string, 166 | _ids: (BigNumberish)[], 167 | _amounts: (BigNumberish)[], 168 | _data: Arrayish, 169 | overrides?: TransactionOverrides 170 | ): Promise; 171 | 172 | safeTransferFrom( 173 | _from: string, 174 | _to: string, 175 | _id: BigNumberish, 176 | _amount: BigNumberish, 177 | _data: Arrayish, 178 | overrides?: TransactionOverrides 179 | ): Promise; 180 | 181 | setApprovalForAll( 182 | _operator: string, 183 | _approved: boolean, 184 | overrides?: TransactionOverrides 185 | ): Promise; 186 | 187 | metaSafeTransferFrom( 188 | _from: string, 189 | _to: string, 190 | _id: BigNumberish, 191 | _amount: BigNumberish, 192 | _isGasFee: boolean, 193 | _data: Arrayish, 194 | overrides?: TransactionOverrides 195 | ): Promise; 196 | 197 | metaSafeBatchTransferFrom( 198 | _from: string, 199 | _to: string, 200 | _ids: (BigNumberish)[], 201 | _amounts: (BigNumberish)[], 202 | _isGasFee: boolean, 203 | _data: Arrayish, 204 | overrides?: TransactionOverrides 205 | ): Promise; 206 | 207 | metaSetApprovalForAll( 208 | _owner: string, 209 | _operator: string, 210 | _approved: boolean, 211 | _isGasFee: boolean, 212 | _data: Arrayish, 213 | overrides?: TransactionOverrides 214 | ): Promise; 215 | }; 216 | 217 | filters: { 218 | ApprovalForAll( 219 | _owner: string | null, 220 | _operator: string | null, 221 | _approved: null 222 | ): EventFilter; 223 | 224 | TransferBatch( 225 | _operator: string | null, 226 | _from: string | null, 227 | _to: string | null, 228 | _ids: null, 229 | _amounts: null 230 | ): EventFilter; 231 | 232 | TransferSingle( 233 | _operator: string | null, 234 | _from: string | null, 235 | _to: string | null, 236 | _id: null, 237 | _amount: null 238 | ): EventFilter; 239 | 240 | URI(_uri: null, _id: BigNumberish | null): EventFilter; 241 | }; 242 | 243 | estimate: { 244 | safeBatchTransferFrom( 245 | _from: string, 246 | _to: string, 247 | _ids: (BigNumberish)[], 248 | _amounts: (BigNumberish)[], 249 | _data: Arrayish 250 | ): Promise; 251 | 252 | safeTransferFrom( 253 | _from: string, 254 | _to: string, 255 | _id: BigNumberish, 256 | _amount: BigNumberish, 257 | _data: Arrayish 258 | ): Promise; 259 | 260 | setApprovalForAll( 261 | _operator: string, 262 | _approved: boolean 263 | ): Promise; 264 | 265 | metaSafeTransferFrom( 266 | _from: string, 267 | _to: string, 268 | _id: BigNumberish, 269 | _amount: BigNumberish, 270 | _isGasFee: boolean, 271 | _data: Arrayish 272 | ): Promise; 273 | 274 | metaSafeBatchTransferFrom( 275 | _from: string, 276 | _to: string, 277 | _ids: (BigNumberish)[], 278 | _amounts: (BigNumberish)[], 279 | _isGasFee: boolean, 280 | _data: Arrayish 281 | ): Promise; 282 | 283 | metaSetApprovalForAll( 284 | _owner: string, 285 | _operator: string, 286 | _approved: boolean, 287 | _isGasFee: boolean, 288 | _data: Arrayish 289 | ): Promise; 290 | }; 291 | } 292 | -------------------------------------------------------------------------------- /contracts/mocks/ERC20Mock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | 3 | import "../interfaces/IERC20.sol"; 4 | import "../utils/SafeMath.sol"; 5 | 6 | 7 | /** 8 | * @title Standard ERC20 token 9 | * 10 | * @dev Implementation of the basic standard token. 11 | * https://eips.ethereum.org/EIPS/eip-20 12 | * Originally based on code by FirstBlood: 13 | * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol 14 | * 15 | * This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for 16 | * all accounts just by listening to said events. Note that this isn't required by the specification, and other 17 | * compliant implementations may not do it. 18 | */ 19 | contract ERC20 is IERC20 { 20 | using SafeMath for uint256; 21 | 22 | mapping (address => uint256) private _balances; 23 | 24 | mapping (address => mapping (address => uint256)) private _allowed; 25 | 26 | uint256 private _totalSupply; 27 | 28 | /** 29 | * @dev Total number of tokens in existence 30 | */ 31 | function totalSupply() public view returns (uint256) { 32 | return _totalSupply; 33 | } 34 | 35 | /** 36 | * @dev Gets the balance of the specified address. 37 | * @param owner The address to query the balance of. 38 | * @return A uint256 representing the amount owned by the passed address. 39 | */ 40 | function balanceOf(address owner) public view returns (uint256) { 41 | return _balances[owner]; 42 | } 43 | 44 | /** 45 | * @dev Function to check the amount of tokens that an owner allowed to a spender. 46 | * @param owner address The address which owns the funds. 47 | * @param spender address The address which will spend the funds. 48 | * @return A uint256 specifying the amount of tokens still available for the spender. 49 | */ 50 | function allowance(address owner, address spender) public view returns (uint256) { 51 | return _allowed[owner][spender]; 52 | } 53 | 54 | /** 55 | * @dev Transfer token to a specified address 56 | * @param to The address to transfer to. 57 | * @param value The amount to be transferred. 58 | */ 59 | function transfer(address to, uint256 value) public returns (bool) { 60 | _transfer(msg.sender, to, value); 61 | return true; 62 | } 63 | 64 | /** 65 | * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. 66 | * Beware that changing an allowance with this method brings the risk that someone may use both the old 67 | * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this 68 | * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: 69 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 70 | * @param spender The address which will spend the funds. 71 | * @param value The amount of tokens to be spent. 72 | */ 73 | function approve(address spender, uint256 value) public returns (bool) { 74 | _approve(msg.sender, spender, value); 75 | return true; 76 | } 77 | 78 | /** 79 | * @dev Transfer tokens from one address to another. 80 | * Note that while this function emits an Approval event, this is not required as per the specification, 81 | * and other compliant implementations may not emit the event. 82 | * @param from address The address which you want to send tokens from 83 | * @param to address The address which you want to transfer to 84 | * @param value uint256 the amount of tokens to be transferred 85 | */ 86 | function transferFrom(address from, address to, uint256 value) public returns (bool) { 87 | _transfer(from, to, value); 88 | _approve(from, msg.sender, _allowed[from][msg.sender].sub(value)); 89 | return true; 90 | } 91 | 92 | /** 93 | * @dev Increase the amount of tokens that an owner allowed to a spender. 94 | * approve should be called when _allowed[msg.sender][spender] == 0. To increment 95 | * allowed value is better to use this function to avoid 2 calls (and wait until 96 | * the first transaction is mined) 97 | * From MonolithDAO Token.sol 98 | * Emits an Approval event. 99 | * @param spender The address which will spend the funds. 100 | * @param addedValue The amount of tokens to increase the allowance by. 101 | */ 102 | function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { 103 | _approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue)); 104 | return true; 105 | } 106 | 107 | /** 108 | * @dev Decrease the amount of tokens that an owner allowed to a spender. 109 | * approve should be called when _allowed[msg.sender][spender] == 0. To decrement 110 | * allowed value is better to use this function to avoid 2 calls (and wait until 111 | * the first transaction is mined) 112 | * From MonolithDAO Token.sol 113 | * Emits an Approval event. 114 | * @param spender The address which will spend the funds. 115 | * @param subtractedValue The amount of tokens to decrease the allowance by. 116 | */ 117 | function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { 118 | _approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue)); 119 | return true; 120 | } 121 | 122 | /** 123 | * @dev Transfer token for a specified addresses 124 | * @param from The address to transfer from. 125 | * @param to The address to transfer to. 126 | * @param value The amount to be transferred. 127 | */ 128 | function _transfer(address from, address to, uint256 value) internal { 129 | require(to != address(0)); 130 | 131 | _balances[from] = _balances[from].sub(value); 132 | _balances[to] = _balances[to].add(value); 133 | emit Transfer(from, to, value); 134 | } 135 | 136 | /** 137 | * @dev Internal function that mints an amount of the token and assigns it to 138 | * an account. This encapsulates the modification of balances such that the 139 | * proper events are emitted. 140 | * @param account The account that will receive the created tokens. 141 | * @param value The amount that will be created. 142 | */ 143 | function _mint(address account, uint256 value) internal { 144 | require(account != address(0)); 145 | 146 | _totalSupply = _totalSupply.add(value); 147 | _balances[account] = _balances[account].add(value); 148 | emit Transfer(address(0), account, value); 149 | } 150 | 151 | /** 152 | * @dev Internal function that burns an amount of the token of a given 153 | * account. 154 | * @param account The account whose tokens will be burnt. 155 | * @param value The amount that will be burnt. 156 | */ 157 | function _burn(address account, uint256 value) internal { 158 | require(account != address(0)); 159 | 160 | _totalSupply = _totalSupply.sub(value); 161 | _balances[account] = _balances[account].sub(value); 162 | emit Transfer(account, address(0), value); 163 | } 164 | 165 | /** 166 | * @dev Approve an address to spend another addresses' tokens. 167 | * @param owner The address that owns the tokens. 168 | * @param spender The address that will spend the tokens. 169 | * @param value The number of tokens that can be spent. 170 | */ 171 | function _approve(address owner, address spender, uint256 value) internal { 172 | require(spender != address(0)); 173 | require(owner != address(0)); 174 | 175 | _allowed[owner][spender] = value; 176 | emit Approval(owner, spender, value); 177 | } 178 | 179 | /** 180 | * @dev Internal function that burns an amount of the token of a given 181 | * account, deducting from the sender's allowance for said account. Uses the 182 | * internal burn function. 183 | * Emits an Approval event (reflecting the reduced allowance). 184 | * @param account The account whose tokens will be burnt. 185 | * @param value The amount that will be burnt. 186 | */ 187 | function _burnFrom(address account, uint256 value) internal { 188 | _burn(account, value); 189 | _approve(account, msg.sender, _allowed[account][msg.sender].sub(value)); 190 | } 191 | 192 | } 193 | 194 | contract ERC20Mock is ERC20 { 195 | 196 | constructor() public { } 197 | 198 | function mockMint(address _address, uint256 _amount) public { 199 | _mint(_address, _amount); 200 | } 201 | 202 | function batchTransfer(address[] calldata _tokens, address _to, uint256[] calldata _amounts) external { 203 | for (uint256 i = 0; i < _amounts.length; i++){ 204 | ERC20(_tokens[i]).transfer(_to, _amounts[i]); 205 | } 206 | } 207 | 208 | } 209 | 210 | 211 | -------------------------------------------------------------------------------- /src/tests/ERC1155Metadata.spec.ts: -------------------------------------------------------------------------------- 1 | import * as ethers from 'ethers' 2 | 3 | import { AbstractContract, assert, expect, RevertError, BigNumber } from './utils' 4 | import * as utils from './utils' 5 | 6 | import { ERC1155MetadataMock } from 'typings/contracts/ERC1155MetadataMock' 7 | 8 | // init test wallets from package.json mnemonic 9 | const web3 = (global as any).web3 10 | 11 | const { 12 | wallet: ownerWallet, 13 | provider: ownerProvider, 14 | signer: ownerSigner 15 | } = utils.createTestWallet(web3, 0) 16 | 17 | const { 18 | wallet: receiverWallet, 19 | provider: receiverProvider, 20 | signer: receiverSigner 21 | } = utils.createTestWallet(web3, 2) 22 | 23 | const { 24 | wallet: anyoneWallet, 25 | provider: anyoneProvider, 26 | signer: anyoneSigner 27 | } = utils.createTestWallet(web3, 3) 28 | 29 | const { 30 | wallet: operatorWallet, 31 | provider: operatorProvider, 32 | signer: operatorSigner 33 | } = utils.createTestWallet(web3, 4) 34 | 35 | 36 | contract('ERC1155Metadata', (accounts: string[]) => { 37 | 38 | const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' 39 | 40 | let ownerAddress: string 41 | let receiverAddress: string 42 | let anyoneAddress: string 43 | let operatorAddress: string 44 | 45 | let erc1155MetadataContract: ERC1155MetadataMock 46 | let anyoneERC1155MetadataContract; 47 | 48 | context('When ERC1155MetadataMock contract is deployed', () => { 49 | const BASE_URI = 'https://assets.skyweaver.net/c679a6577c12c47948084dd61a79b9598db17cc5/full-cards/' 50 | 51 | before(async () => { 52 | ownerAddress = await ownerWallet.getAddress() 53 | receiverAddress = await receiverWallet.getAddress() 54 | anyoneAddress = await anyoneWallet.getAddress() 55 | operatorAddress = await operatorWallet.getAddress() 56 | }) 57 | 58 | beforeEach(async () => { 59 | let abstract = await AbstractContract.fromArtifactName('ERC1155MetadataMock') 60 | erc1155MetadataContract = await abstract.deploy(ownerWallet) as ERC1155MetadataMock 61 | anyoneERC1155MetadataContract = await erc1155MetadataContract.connect(anyoneSigner) as ERC1155MetadataMock 62 | 63 | await erc1155MetadataContract.functions.setBaseMetadataURI(BASE_URI); 64 | }) 65 | 66 | describe('_updateBaseMetadataURL() function', () => { 67 | 68 | it('should ALLOW inheriting contract to call _updateBaseMetadataURL()', async () => { 69 | const tx = erc1155MetadataContract.functions.setBaseMetadataURI('HELLOTEST/'); 70 | await expect(tx).to.be.fulfilled 71 | }) 72 | 73 | it('should update baseMetadataURI when successful', async () => { 74 | const URI1 = await erc1155MetadataContract.functions.uri(1928374) 75 | await erc1155MetadataContract.functions.setBaseMetadataURI('HELLOTEST/'); 76 | const URI2 = await erc1155MetadataContract.functions.uri(1928374) 77 | expect(URI1).to.be.equal(BASE_URI + '1928374.json') 78 | expect(URI2).to.be.equal('HELLOTEST/1928374.json') 79 | }) 80 | 81 | it('Should revert if called directly by non-parent contract', async () => { 82 | const transaction = { 83 | to: erc1155MetadataContract.address, 84 | data: '0x122f94bf00000000000000000000000000000000000000000000000000000000000000' + 85 | '20000000000000000000000000000000000000000000000000000000000000000a48454c' + 86 | '4c4f544553542f00000000000000000000000000000000000000000000' 87 | } 88 | const tx = ownerWallet.sendTransaction(transaction) 89 | await expect(tx).to.be.rejectedWith(RevertError('ERC1155MetadataMock: INVALID_METHOD')) 90 | }) 91 | 92 | }) 93 | 94 | describe('_logURIs(uint256[]) function', () => { 95 | const ids = [1, 44, 19283091823] 96 | 97 | it('should ALLOW inheriting contract to call _logURIs()', async () => { 98 | const tx = erc1155MetadataContract.functions.logURIsMock(ids); 99 | await expect(tx).to.be.fulfilled 100 | }) 101 | 102 | it('Should revert if called directly by non-parent contract', async () => { 103 | const transaction = { 104 | to: erc1155MetadataContract.address, 105 | data: '0x78d76ac2000000000000000000000000000000000000000000000000000000000000002' + 106 | '0000000000000000000000000000000000000000000000000000000000000000300000000000000' + 107 | '0000000000000000000000000000000000000000000000000100000000000000000000000000000' + 108 | '0000000000000000000000000000000002c00000000000000000000000000000000000000000000' + 109 | '0000000000047d5ca16f' 110 | } 111 | const tx = ownerWallet.sendTransaction(transaction) 112 | await expect(tx).to.be.rejectedWith(RevertError('ERC1155MetadataMock: INVALID_METHOD')) 113 | }) 114 | 115 | it('should emit N URI events', async () => { 116 | const tx = await erc1155MetadataContract.functions.logURIsMock(ids) as ethers.ContractTransaction 117 | const receipt = await tx.wait(1) 118 | const URIevents = receipt.events!.filter(uri => uri.event === 'URI') 119 | expect(receipt.events!.length == ids.length) 120 | }) 121 | 122 | it('should emit URI events with correct information', async () => { 123 | const tx = await erc1155MetadataContract.functions.logURIsMock(ids) as ethers.ContractTransaction 124 | const receipt = await tx.wait(1) 125 | receipt.events! 126 | .filter(uri => uri.event === 'URI') 127 | .forEach(ev => { 128 | let args = erc1155MetadataContract.interface.events.URI.decode(ev.data, ev.topics) 129 | expect(args._uri).to.be.equal(BASE_URI + args._id + '.json') 130 | }) 131 | }) 132 | }) 133 | 134 | describe('_logURIs(uint256[],string[]) function', () => { 135 | const ids = [1, 44, 19283091823] 136 | const URIs = ids.map(id => BASE_URI + id + '.json') 137 | 138 | it('should ALLOW inheriting contract to call _logURIs()', async () => { 139 | const tx = erc1155MetadataContract.functions.logURIsMock2(ids, URIs); 140 | await expect(tx).to.be.fulfilled 141 | }) 142 | 143 | it('Should revert if called directly by non-parent contract', async () => { 144 | const transaction = { 145 | to: erc1155MetadataContract.address, 146 | data: '0xb7fc7804000000000000000000000000000000000000000000000000000000000000004' + 147 | '000000000000000000000000000000000000000000000000000000000000000c000000000000000' + 148 | '0000000000000000000000000000000000000000000000000300000000000000000000000000000' + 149 | '0000000000000000000000000000000000100000000000000000000000000000000000000000000' + 150 | '0000000000000000002c000000000000000000000000000000000000000000000000000000047d5' + 151 | 'ca16f00000000000000000000000000000000000000000000000000000000000000030000000000' + 152 | '0000000000000000000000000000000000000000000000000000600000000000000000000000000' + 153 | '0000000000000000000000000000000000000e00000000000000000000000000000000000000000' + 154 | '0000000000000000000001600000000000000000000000000000000000000000000000000000000' + 155 | '00000005768747470733a2f2f6173736574732e736b797765617665722e6e65742f633637396136' + 156 | '353737633132633437393438303834646436316137396239353938646231376363352f66756c6c2' + 157 | 'd63617264732f312e6a736f6e000000000000000000000000000000000000000000000000000000' + 158 | '000000000000000000000000005868747470733a2f2f6173736574732e736b797765617665722e6' + 159 | 'e65742f633637396136353737633132633437393438303834646436316137396239353938646231' + 160 | '376363352f66756c6c2d63617264732f34342e6a736f6e000000000000000000000000000000000' + 161 | '0000000000000000000000000000000000000000000006168747470733a2f2f6173736574732e73' + 162 | '6b797765617665722e6e65742f63363739613635373763313263343739343830383464643631613' + 163 | '7396239353938646231376363352f66756c6c2d63617264732f31393238333039313832332e6a73' + 164 | '6f6e00000000000000000000000000000000000000000000000000000000000000' 165 | } 166 | const tx = ownerWallet.sendTransaction(transaction) 167 | await expect(tx).to.be.rejectedWith(RevertError('ERC1155MetadataMock: INVALID_METHOD')) 168 | }) 169 | 170 | it('should emit N URI events', async () => { 171 | const tx = await erc1155MetadataContract.functions.logURIsMock2(ids, URIs) 172 | const receipt = await tx.wait(1) 173 | const URIevents = receipt.events!.filter(uri => uri.event === 'URI') 174 | expect(receipt.events!.length == ids.length) 175 | }) 176 | 177 | it('should emit URI events with correct information', async () => { 178 | const tx = await erc1155MetadataContract.functions.logURIsMock2(ids, URIs) 179 | const receipt = await tx.wait(1) 180 | receipt.events! 181 | .filter(uri => uri.event === 'URI') 182 | .forEach(ev => { 183 | let args = erc1155MetadataContract.interface.events.URI.decode(ev.data, ev.topics) 184 | expect(args._uri).to.be.equal(BASE_URI + args._id + '.json') 185 | }) 186 | }) 187 | }) 188 | 189 | }) 190 | }) 191 | -------------------------------------------------------------------------------- /typings/contracts/ERC1155MetaMintBurnMock.d.ts: -------------------------------------------------------------------------------- 1 | /* Generated by ts-generator ver. 0.0.8 */ 2 | /* tslint:disable */ 3 | 4 | import { Contract, ContractTransaction, EventFilter, Signer } from "ethers"; 5 | import { Listener, Provider } from "ethers/providers"; 6 | import { Arrayish, BigNumber, BigNumberish, Interface } from "ethers/utils"; 7 | import { 8 | TransactionOverrides, 9 | TypedEventDescription, 10 | TypedFunctionDescription 11 | } from "."; 12 | 13 | interface ERC1155MetaMintBurnMockInterface extends Interface { 14 | functions: { 15 | metaSafeBatchTransferFrom: TypedFunctionDescription<{ 16 | encode([_from, _to, _ids, _amounts, _isGasFee, _data]: [ 17 | string, 18 | string, 19 | (BigNumberish)[], 20 | (BigNumberish)[], 21 | boolean, 22 | Arrayish 23 | ]): string; 24 | }>; 25 | 26 | metaSafeTransferFrom: TypedFunctionDescription<{ 27 | encode([_from, _to, _id, _amount, _isGasFee, _data]: [ 28 | string, 29 | string, 30 | BigNumberish, 31 | BigNumberish, 32 | boolean, 33 | Arrayish 34 | ]): string; 35 | }>; 36 | 37 | metaSetApprovalForAll: TypedFunctionDescription<{ 38 | encode([_owner, _operator, _approved, _isGasFee, _data]: [ 39 | string, 40 | string, 41 | boolean, 42 | boolean, 43 | Arrayish 44 | ]): string; 45 | }>; 46 | 47 | safeBatchTransferFrom: TypedFunctionDescription<{ 48 | encode([_from, _to, _ids, _amounts, _data]: [ 49 | string, 50 | string, 51 | (BigNumberish)[], 52 | (BigNumberish)[], 53 | Arrayish 54 | ]): string; 55 | }>; 56 | 57 | safeTransferFrom: TypedFunctionDescription<{ 58 | encode([_from, _to, _id, _amount, _data]: [ 59 | string, 60 | string, 61 | BigNumberish, 62 | BigNumberish, 63 | Arrayish 64 | ]): string; 65 | }>; 66 | 67 | setApprovalForAll: TypedFunctionDescription<{ 68 | encode([_operator, _approved]: [string, boolean]): string; 69 | }>; 70 | 71 | mintMock: TypedFunctionDescription<{ 72 | encode([_to, _id, _value, _data]: [ 73 | string, 74 | BigNumberish, 75 | BigNumberish, 76 | Arrayish 77 | ]): string; 78 | }>; 79 | 80 | batchMintMock: TypedFunctionDescription<{ 81 | encode([_to, _ids, _values, _data]: [ 82 | string, 83 | (BigNumberish)[], 84 | (BigNumberish)[], 85 | Arrayish 86 | ]): string; 87 | }>; 88 | 89 | burnMock: TypedFunctionDescription<{ 90 | encode([_from, _id, _value]: [ 91 | string, 92 | BigNumberish, 93 | BigNumberish 94 | ]): string; 95 | }>; 96 | 97 | batchBurnMock: TypedFunctionDescription<{ 98 | encode([_from, _ids, _values]: [ 99 | string, 100 | (BigNumberish)[], 101 | (BigNumberish)[] 102 | ]): string; 103 | }>; 104 | }; 105 | 106 | events: { 107 | ApprovalForAll: TypedEventDescription<{ 108 | encodeTopics([_owner, _operator, _approved]: [ 109 | string | null, 110 | string | null, 111 | null 112 | ]): string[]; 113 | }>; 114 | 115 | TransferBatch: TypedEventDescription<{ 116 | encodeTopics([_operator, _from, _to, _ids, _amounts]: [ 117 | string | null, 118 | string | null, 119 | string | null, 120 | null, 121 | null 122 | ]): string[]; 123 | }>; 124 | 125 | TransferSingle: TypedEventDescription<{ 126 | encodeTopics([_operator, _from, _to, _id, _amount]: [ 127 | string | null, 128 | string | null, 129 | string | null, 130 | null, 131 | null 132 | ]): string[]; 133 | }>; 134 | 135 | URI: TypedEventDescription<{ 136 | encodeTopics([_uri, _id]: [null, BigNumberish | null]): string[]; 137 | }>; 138 | }; 139 | } 140 | 141 | export class ERC1155MetaMintBurnMock extends Contract { 142 | connect( 143 | signerOrProvider: Signer | Provider | string 144 | ): ERC1155MetaMintBurnMock; 145 | attach(addressOrName: string): ERC1155MetaMintBurnMock; 146 | deployed(): Promise; 147 | 148 | on(event: EventFilter | string, listener: Listener): ERC1155MetaMintBurnMock; 149 | once( 150 | event: EventFilter | string, 151 | listener: Listener 152 | ): ERC1155MetaMintBurnMock; 153 | addListener( 154 | eventName: EventFilter | string, 155 | listener: Listener 156 | ): ERC1155MetaMintBurnMock; 157 | removeAllListeners(eventName: EventFilter | string): ERC1155MetaMintBurnMock; 158 | removeListener(eventName: any, listener: Listener): ERC1155MetaMintBurnMock; 159 | 160 | interface: ERC1155MetaMintBurnMockInterface; 161 | 162 | functions: { 163 | balanceOf(_owner: string, _id: BigNumberish): Promise; 164 | 165 | balanceOfBatch( 166 | _owners: (string)[], 167 | _ids: (BigNumberish)[] 168 | ): Promise<(BigNumber)[]>; 169 | 170 | getNonce(_signer: string): Promise; 171 | 172 | isApprovedForAll(_owner: string, _operator: string): Promise; 173 | 174 | isValidSignature( 175 | _signerAddress: string, 176 | _hash: Arrayish, 177 | _data: Arrayish, 178 | _sig: Arrayish 179 | ): Promise; 180 | 181 | supportsInterface(_interfaceID: Arrayish): Promise; 182 | 183 | uri(_id: BigNumberish): Promise; 184 | 185 | metaSafeBatchTransferFrom( 186 | _from: string, 187 | _to: string, 188 | _ids: (BigNumberish)[], 189 | _amounts: (BigNumberish)[], 190 | _isGasFee: boolean, 191 | _data: Arrayish, 192 | overrides?: TransactionOverrides 193 | ): Promise; 194 | 195 | metaSafeTransferFrom( 196 | _from: string, 197 | _to: string, 198 | _id: BigNumberish, 199 | _amount: BigNumberish, 200 | _isGasFee: boolean, 201 | _data: Arrayish, 202 | overrides?: TransactionOverrides 203 | ): Promise; 204 | 205 | metaSetApprovalForAll( 206 | _owner: string, 207 | _operator: string, 208 | _approved: boolean, 209 | _isGasFee: boolean, 210 | _data: Arrayish, 211 | overrides?: TransactionOverrides 212 | ): Promise; 213 | 214 | safeBatchTransferFrom( 215 | _from: string, 216 | _to: string, 217 | _ids: (BigNumberish)[], 218 | _amounts: (BigNumberish)[], 219 | _data: Arrayish, 220 | overrides?: TransactionOverrides 221 | ): Promise; 222 | 223 | safeTransferFrom( 224 | _from: string, 225 | _to: string, 226 | _id: BigNumberish, 227 | _amount: BigNumberish, 228 | _data: Arrayish, 229 | overrides?: TransactionOverrides 230 | ): Promise; 231 | 232 | setApprovalForAll( 233 | _operator: string, 234 | _approved: boolean, 235 | overrides?: TransactionOverrides 236 | ): Promise; 237 | 238 | mintMock( 239 | _to: string, 240 | _id: BigNumberish, 241 | _value: BigNumberish, 242 | _data: Arrayish, 243 | overrides?: TransactionOverrides 244 | ): Promise; 245 | 246 | batchMintMock( 247 | _to: string, 248 | _ids: (BigNumberish)[], 249 | _values: (BigNumberish)[], 250 | _data: Arrayish, 251 | overrides?: TransactionOverrides 252 | ): Promise; 253 | 254 | burnMock( 255 | _from: string, 256 | _id: BigNumberish, 257 | _value: BigNumberish, 258 | overrides?: TransactionOverrides 259 | ): Promise; 260 | 261 | batchBurnMock( 262 | _from: string, 263 | _ids: (BigNumberish)[], 264 | _values: (BigNumberish)[], 265 | overrides?: TransactionOverrides 266 | ): Promise; 267 | }; 268 | 269 | filters: { 270 | ApprovalForAll( 271 | _owner: string | null, 272 | _operator: string | null, 273 | _approved: null 274 | ): EventFilter; 275 | 276 | TransferBatch( 277 | _operator: string | null, 278 | _from: string | null, 279 | _to: string | null, 280 | _ids: null, 281 | _amounts: null 282 | ): EventFilter; 283 | 284 | TransferSingle( 285 | _operator: string | null, 286 | _from: string | null, 287 | _to: string | null, 288 | _id: null, 289 | _amount: null 290 | ): EventFilter; 291 | 292 | URI(_uri: null, _id: BigNumberish | null): EventFilter; 293 | }; 294 | 295 | estimate: { 296 | metaSafeBatchTransferFrom( 297 | _from: string, 298 | _to: string, 299 | _ids: (BigNumberish)[], 300 | _amounts: (BigNumberish)[], 301 | _isGasFee: boolean, 302 | _data: Arrayish 303 | ): Promise; 304 | 305 | metaSafeTransferFrom( 306 | _from: string, 307 | _to: string, 308 | _id: BigNumberish, 309 | _amount: BigNumberish, 310 | _isGasFee: boolean, 311 | _data: Arrayish 312 | ): Promise; 313 | 314 | metaSetApprovalForAll( 315 | _owner: string, 316 | _operator: string, 317 | _approved: boolean, 318 | _isGasFee: boolean, 319 | _data: Arrayish 320 | ): Promise; 321 | 322 | safeBatchTransferFrom( 323 | _from: string, 324 | _to: string, 325 | _ids: (BigNumberish)[], 326 | _amounts: (BigNumberish)[], 327 | _data: Arrayish 328 | ): Promise; 329 | 330 | safeTransferFrom( 331 | _from: string, 332 | _to: string, 333 | _id: BigNumberish, 334 | _amount: BigNumberish, 335 | _data: Arrayish 336 | ): Promise; 337 | 338 | setApprovalForAll( 339 | _operator: string, 340 | _approved: boolean 341 | ): Promise; 342 | 343 | mintMock( 344 | _to: string, 345 | _id: BigNumberish, 346 | _value: BigNumberish, 347 | _data: Arrayish 348 | ): Promise; 349 | 350 | batchMintMock( 351 | _to: string, 352 | _ids: (BigNumberish)[], 353 | _values: (BigNumberish)[], 354 | _data: Arrayish 355 | ): Promise; 356 | 357 | burnMock( 358 | _from: string, 359 | _id: BigNumberish, 360 | _value: BigNumberish 361 | ): Promise; 362 | 363 | batchBurnMock( 364 | _from: string, 365 | _ids: (BigNumberish)[], 366 | _values: (BigNumberish)[] 367 | ): Promise; 368 | }; 369 | } 370 | -------------------------------------------------------------------------------- /contracts/tokens/ERC1155/ERC1155.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.12; 2 | 3 | import "../../interfaces/IERC165.sol"; 4 | import "../../utils/SafeMath.sol"; 5 | import "../../interfaces/IERC1155TokenReceiver.sol"; 6 | import "../../interfaces/IERC1155.sol"; 7 | import "../../utils/Address.sol"; 8 | 9 | 10 | /** 11 | * @dev Implementation of Multi-Token Standard contract 12 | */ 13 | contract ERC1155 is IERC165 { 14 | using SafeMath for uint256; 15 | using Address for address; 16 | 17 | 18 | /***********************************| 19 | | Variables and Events | 20 | |__________________________________*/ 21 | 22 | // onReceive function signatures 23 | bytes4 constant internal ERC1155_RECEIVED_VALUE = 0xf23a6e61; 24 | bytes4 constant internal ERC1155_BATCH_RECEIVED_VALUE = 0xbc197c81; 25 | 26 | // Objects balances 27 | mapping (address => mapping(uint256 => uint256)) internal balances; 28 | 29 | // Operator Functions 30 | mapping (address => mapping(address => bool)) internal operators; 31 | 32 | // Events 33 | event TransferSingle(address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _amount); 34 | event TransferBatch(address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _amounts); 35 | event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); 36 | event URI(string _uri, uint256 indexed _id); 37 | 38 | 39 | /***********************************| 40 | | Public Transfer Functions | 41 | |__________________________________*/ 42 | 43 | /** 44 | * @notice Transfers amount amount of an _id from the _from address to the _to address specified 45 | * @param _from Source address 46 | * @param _to Target address 47 | * @param _id ID of the token type 48 | * @param _amount Transfered amount 49 | * @param _data Additional data with no specified format, sent in call to `_to` 50 | */ 51 | function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _amount, bytes memory _data) 52 | public 53 | { 54 | require((msg.sender == _from) || isApprovedForAll(_from, msg.sender), "ERC1155#safeTransferFrom: INVALID_OPERATOR"); 55 | require(_to != address(0),"ERC1155#safeTransferFrom: INVALID_RECIPIENT"); 56 | // require(_amount >= balances[_from][_id]) is not necessary since checked with safemath operations 57 | 58 | _safeTransferFrom(_from, _to, _id, _amount); 59 | _callonERC1155Received(_from, _to, _id, _amount, _data); 60 | } 61 | 62 | /** 63 | * @notice Send multiple types of Tokens from the _from address to the _to address (with safety call) 64 | * @param _from Source addresses 65 | * @param _to Target addresses 66 | * @param _ids IDs of each token type 67 | * @param _amounts Transfer amounts per token type 68 | * @param _data Additional data with no specified format, sent in call to `_to` 69 | */ 70 | function safeBatchTransferFrom(address _from, address _to, uint256[] memory _ids, uint256[] memory _amounts, bytes memory _data) 71 | public 72 | { 73 | // Requirements 74 | require((msg.sender == _from) || isApprovedForAll(_from, msg.sender), "ERC1155#safeBatchTransferFrom: INVALID_OPERATOR"); 75 | require(_to != address(0), "ERC1155#safeBatchTransferFrom: INVALID_RECIPIENT"); 76 | 77 | _safeBatchTransferFrom(_from, _to, _ids, _amounts); 78 | _callonERC1155BatchReceived(_from, _to, _ids, _amounts, _data); 79 | } 80 | 81 | 82 | /***********************************| 83 | | Internal Transfer Functions | 84 | |__________________________________*/ 85 | 86 | /** 87 | * @notice Transfers amount amount of an _id from the _from address to the _to address specified 88 | * @param _from Source address 89 | * @param _to Target address 90 | * @param _id ID of the token type 91 | * @param _amount Transfered amount 92 | */ 93 | function _safeTransferFrom(address _from, address _to, uint256 _id, uint256 _amount) 94 | internal 95 | { 96 | // Update balances 97 | balances[_from][_id] = balances[_from][_id].sub(_amount); // Subtract amount 98 | balances[_to][_id] = balances[_to][_id].add(_amount); // Add amount 99 | 100 | // Emit event 101 | emit TransferSingle(msg.sender, _from, _to, _id, _amount); 102 | } 103 | 104 | /** 105 | * @notice Verifies if receiver is contract and if so, calls (_to).onERC1155Received(...) 106 | */ 107 | function _callonERC1155Received(address _from, address _to, uint256 _id, uint256 _amount, bytes memory _data) 108 | internal 109 | { 110 | // Check if recipient is contract 111 | if (_to.isContract()) { 112 | bytes4 retval = IERC1155TokenReceiver(_to).onERC1155Received(msg.sender, _from, _id, _amount, _data); 113 | require(retval == ERC1155_RECEIVED_VALUE, "ERC1155#_callonERC1155Received: INVALID_ON_RECEIVE_MESSAGE"); 114 | } 115 | } 116 | 117 | /** 118 | * @notice Send multiple types of Tokens from the _from address to the _to address (with safety call) 119 | * @param _from Source addresses 120 | * @param _to Target addresses 121 | * @param _ids IDs of each token type 122 | * @param _amounts Transfer amounts per token type 123 | */ 124 | function _safeBatchTransferFrom(address _from, address _to, uint256[] memory _ids, uint256[] memory _amounts) 125 | internal 126 | { 127 | require(_ids.length == _amounts.length, "ERC1155#_safeBatchTransferFrom: INVALID_ARRAYS_LENGTH"); 128 | 129 | // Number of transfer to execute 130 | uint256 nTransfer = _ids.length; 131 | 132 | // Executing all transfers 133 | for (uint256 i = 0; i < nTransfer; i++) { 134 | // Update storage balance of previous bin 135 | balances[_from][_ids[i]] = balances[_from][_ids[i]].sub(_amounts[i]); 136 | balances[_to][_ids[i]] = balances[_to][_ids[i]].add(_amounts[i]); 137 | } 138 | 139 | // Emit event 140 | emit TransferBatch(msg.sender, _from, _to, _ids, _amounts); 141 | } 142 | 143 | /** 144 | * @notice Verifies if receiver is contract and if so, calls (_to).onERC1155BatchReceived(...) 145 | */ 146 | function _callonERC1155BatchReceived(address _from, address _to, uint256[] memory _ids, uint256[] memory _amounts, bytes memory _data) 147 | internal 148 | { 149 | // Pass data if recipient is contract 150 | if (_to.isContract()) { 151 | bytes4 retval = IERC1155TokenReceiver(_to).onERC1155BatchReceived(msg.sender, _from, _ids, _amounts, _data); 152 | require(retval == ERC1155_BATCH_RECEIVED_VALUE, "ERC1155#_callonERC1155BatchReceived: INVALID_ON_RECEIVE_MESSAGE"); 153 | } 154 | } 155 | 156 | 157 | /***********************************| 158 | | Operator Functions | 159 | |__________________________________*/ 160 | 161 | /** 162 | * @notice Enable or disable approval for a third party ("operator") to manage all of caller's tokens 163 | * @param _operator Address to add to the set of authorized operators 164 | * @param _approved True if the operator is approved, false to revoke approval 165 | */ 166 | function setApprovalForAll(address _operator, bool _approved) 167 | external 168 | { 169 | // Update operator status 170 | operators[msg.sender][_operator] = _approved; 171 | emit ApprovalForAll(msg.sender, _operator, _approved); 172 | } 173 | 174 | /** 175 | * @notice Queries the approval status of an operator for a given owner 176 | * @param _owner The owner of the Tokens 177 | * @param _operator Address of authorized operator 178 | * @return True if the operator is approved, false if not 179 | */ 180 | function isApprovedForAll(address _owner, address _operator) 181 | public view returns (bool isOperator) 182 | { 183 | return operators[_owner][_operator]; 184 | } 185 | 186 | 187 | /***********************************| 188 | | Balance Functions | 189 | |__________________________________*/ 190 | 191 | /** 192 | * @notice Get the balance of an account's Tokens 193 | * @param _owner The address of the token holder 194 | * @param _id ID of the Token 195 | * @return The _owner's balance of the Token type requested 196 | */ 197 | function balanceOf(address _owner, uint256 _id) 198 | public view returns (uint256) 199 | { 200 | return balances[_owner][_id]; 201 | } 202 | 203 | /** 204 | * @notice Get the balance of multiple account/token pairs 205 | * @param _owners The addresses of the token holders 206 | * @param _ids ID of the Tokens 207 | * @return The _owner's balance of the Token types requested (i.e. balance for each (owner, id) pair) 208 | */ 209 | function balanceOfBatch(address[] memory _owners, uint256[] memory _ids) 210 | public view returns (uint256[] memory) 211 | { 212 | require(_owners.length == _ids.length, "ERC1155#balanceOfBatch: INVALID_ARRAY_LENGTH"); 213 | 214 | // Variables 215 | uint256[] memory batchBalances = new uint256[](_owners.length); 216 | 217 | // Iterate over each owner and token ID 218 | for (uint256 i = 0; i < _owners.length; i++) { 219 | batchBalances[i] = balances[_owners[i]][_ids[i]]; 220 | } 221 | 222 | return batchBalances; 223 | } 224 | 225 | 226 | /***********************************| 227 | | ERC165 Functions | 228 | |__________________________________*/ 229 | 230 | /** 231 | * INTERFACE_SIGNATURE_ERC165 = bytes4(keccak256("supportsInterface(bytes4)")); 232 | */ 233 | bytes4 constant private INTERFACE_SIGNATURE_ERC165 = 0x01ffc9a7; 234 | 235 | /** 236 | * INTERFACE_SIGNATURE_ERC1155 = 237 | * bytes4(keccak256("safeTransferFrom(address,address,uint256,uint256,bytes)")) ^ 238 | * bytes4(keccak256("safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)")) ^ 239 | * bytes4(keccak256("balanceOf(address,uint256)")) ^ 240 | * bytes4(keccak256("balanceOfBatch(address[],uint256[])")) ^ 241 | * bytes4(keccak256("setApprovalForAll(address,bool)")) ^ 242 | * bytes4(keccak256("isApprovedForAll(address,address)")); 243 | */ 244 | bytes4 constant private INTERFACE_SIGNATURE_ERC1155 = 0xd9b67a26; 245 | 246 | /** 247 | * @notice Query if a contract implements an interface 248 | * @param _interfaceID The interface identifier, as specified in ERC-165 249 | * @return `true` if the contract implements `_interfaceID` and 250 | */ 251 | function supportsInterface(bytes4 _interfaceID) external view returns (bool) { 252 | if (_interfaceID == INTERFACE_SIGNATURE_ERC165 || 253 | _interfaceID == INTERFACE_SIGNATURE_ERC1155) { 254 | return true; 255 | } 256 | return false; 257 | } 258 | 259 | } 260 | --------------------------------------------------------------------------------