From 3948f8b66bc396309be8729ca37fb4350eef2302 Mon Sep 17 00:00:00 2001 From: Michael Zhu Date: Tue, 1 Oct 2019 15:33:37 -0700 Subject: [PATCH 01/87] Replace nonReentrant + refundFinalBalance with refundFinalBalanceNoReentry --- .../exchange/contracts/src/MixinExchangeCore.sol | 9 +++------ .../exchange/contracts/src/MixinMatchOrders.sol | 12 ++++-------- .../contracts/src/MixinSignatureValidator.sol | 12 ++++-------- .../contracts/src/MixinWrapperFunctions.sol | 12 ++++-------- contracts/utils/contracts/src/Refundable.sol | 13 ++++++++++++- 5 files changed, 27 insertions(+), 31 deletions(-) diff --git a/contracts/exchange/contracts/src/MixinExchangeCore.sol b/contracts/exchange/contracts/src/MixinExchangeCore.sol index 202538cbdf..ee32be26b8 100644 --- a/contracts/exchange/contracts/src/MixinExchangeCore.sol +++ b/contracts/exchange/contracts/src/MixinExchangeCore.sol @@ -61,8 +61,7 @@ contract MixinExchangeCore is function cancelOrdersUpTo(uint256 targetOrderEpoch) external payable - nonReentrant - refundFinalBalance + refundFinalBalanceNoReentry { address makerAddress = _getCurrentContextAddress(); // If this function is called via `executeTransaction`, we only update the orderEpoch for the makerAddress/msg.sender combination. @@ -103,8 +102,7 @@ contract MixinExchangeCore is ) public payable - nonReentrant - refundFinalBalance + refundFinalBalanceNoReentry returns (LibFillResults.FillResults memory fillResults) { fillResults = _fillOrder( @@ -120,8 +118,7 @@ contract MixinExchangeCore is function cancelOrder(LibOrder.Order memory order) public payable - nonReentrant - refundFinalBalance + refundFinalBalanceNoReentry { _cancelOrder(order); } diff --git a/contracts/exchange/contracts/src/MixinMatchOrders.sol b/contracts/exchange/contracts/src/MixinMatchOrders.sol index 69c914298d..3b5b251b04 100644 --- a/contracts/exchange/contracts/src/MixinMatchOrders.sol +++ b/contracts/exchange/contracts/src/MixinMatchOrders.sol @@ -51,8 +51,7 @@ contract MixinMatchOrders is ) public payable - nonReentrant - refundFinalBalance + refundFinalBalanceNoReentry returns (LibFillResults.BatchMatchedFillResults memory batchMatchedFillResults) { return _batchMatchOrders( @@ -81,8 +80,7 @@ contract MixinMatchOrders is ) public payable - nonReentrant - refundFinalBalance + refundFinalBalanceNoReentry returns (LibFillResults.BatchMatchedFillResults memory batchMatchedFillResults) { return _batchMatchOrders( @@ -111,8 +109,7 @@ contract MixinMatchOrders is ) public payable - nonReentrant - refundFinalBalance + refundFinalBalanceNoReentry returns (LibFillResults.MatchedFillResults memory matchedFillResults) { return _matchOrders( @@ -141,8 +138,7 @@ contract MixinMatchOrders is ) public payable - nonReentrant - refundFinalBalance + refundFinalBalanceNoReentry returns (LibFillResults.MatchedFillResults memory matchedFillResults) { return _matchOrders( diff --git a/contracts/exchange/contracts/src/MixinSignatureValidator.sol b/contracts/exchange/contracts/src/MixinSignatureValidator.sol index f961f1aedf..f0387fded0 100644 --- a/contracts/exchange/contracts/src/MixinSignatureValidator.sol +++ b/contracts/exchange/contracts/src/MixinSignatureValidator.sol @@ -22,7 +22,6 @@ pragma experimental ABIEncoderV2; import "@0x/contracts-utils/contracts/src/LibBytes.sol"; import "@0x/contracts-utils/contracts/src/LibEIP1271.sol"; import "@0x/contracts-utils/contracts/src/LibRichErrors.sol"; -import "@0x/contracts-utils/contracts/src/ReentrancyGuard.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomain.sol"; @@ -35,7 +34,6 @@ import "./MixinTransactions.sol"; contract MixinSignatureValidator is - ReentrancyGuard, LibEIP712ExchangeDomain, LibEIP1271, ISignatureValidator, @@ -61,8 +59,7 @@ contract MixinSignatureValidator is function preSign(bytes32 hash) external payable - nonReentrant - refundFinalBalance + refundFinalBalanceNoReentry { address signerAddress = _getCurrentContextAddress(); preSigned[hash][signerAddress] = true; @@ -78,8 +75,7 @@ contract MixinSignatureValidator is ) external payable - nonReentrant - refundFinalBalance + refundFinalBalanceNoReentry { address signerAddress = _getCurrentContextAddress(); allowedValidators[signerAddress][validatorAddress] = approval; @@ -465,7 +461,7 @@ contract MixinSignatureValidator is return signatureType; } - /// @dev ABI encodes an order and hash with a selector to be passed into + /// @dev ABI encodes an order and hash with a selector to be passed into /// an EIP1271 compliant `isValidSignature` function. function _encodeEIP1271OrderWithHash( LibOrder.Order memory order, @@ -482,7 +478,7 @@ contract MixinSignatureValidator is ); } - /// @dev ABI encodes a transaction and hash with a selector to be passed into + /// @dev ABI encodes a transaction and hash with a selector to be passed into /// an EIP1271 compliant `isValidSignature` function. function _encodeEIP1271TransactionWithHash( LibZeroExTransaction.ZeroExTransaction memory transaction, diff --git a/contracts/exchange/contracts/src/MixinWrapperFunctions.sol b/contracts/exchange/contracts/src/MixinWrapperFunctions.sol index 2bd0792138..f01e9c084f 100644 --- a/contracts/exchange/contracts/src/MixinWrapperFunctions.sol +++ b/contracts/exchange/contracts/src/MixinWrapperFunctions.sol @@ -47,8 +47,7 @@ contract MixinWrapperFunctions is ) public payable - nonReentrant - refundFinalBalance + refundFinalBalanceNoReentry returns (LibFillResults.FillResults memory fillResults) { fillResults = _fillOrKillOrder( @@ -71,8 +70,7 @@ contract MixinWrapperFunctions is ) public payable - nonReentrant - refundFinalBalance + refundFinalBalanceNoReentry returns (LibFillResults.FillResults[] memory fillResults) { uint256 ordersLength = orders.length; @@ -99,8 +97,7 @@ contract MixinWrapperFunctions is ) public payable - nonReentrant - refundFinalBalance + refundFinalBalanceNoReentry returns (LibFillResults.FillResults[] memory fillResults) { uint256 ordersLength = orders.length; @@ -287,8 +284,7 @@ contract MixinWrapperFunctions is function batchCancelOrders(LibOrder.Order[] memory orders) public payable - nonReentrant - refundFinalBalance + refundFinalBalanceNoReentry { uint256 ordersLength = orders.length; for (uint256 i = 0; i != ordersLength; i++) { diff --git a/contracts/utils/contracts/src/Refundable.sol b/contracts/utils/contracts/src/Refundable.sol index 42293d9bac..55d32b492b 100644 --- a/contracts/utils/contracts/src/Refundable.sol +++ b/contracts/utils/contracts/src/Refundable.sol @@ -18,8 +18,12 @@ pragma solidity ^0.5.9; +import "./ReentrancyGuard.sol"; -contract Refundable { + +contract Refundable is + ReentrancyGuard +{ // This bool is used by the refund modifier to allow for lazily evaluated refunds. bool internal _shouldNotRefund; @@ -29,6 +33,13 @@ contract Refundable { _refundNonZeroBalanceIfEnabled(); } + modifier refundFinalBalanceNoReentry { + _lockMutexOrThrowIfAlreadyLocked(); + _; + _refundNonZeroBalanceIfEnabled(); + _unlockMutex(); + } + modifier disableRefundUntilEnd { if (_areRefundsDisabled()) { _; From 24e4567b253c58bb2c8fb09d6336718b2ae563f9 Mon Sep 17 00:00:00 2001 From: Alex Towle Date: Thu, 3 Oct 2019 16:06:29 -0700 Subject: [PATCH 02/87] `@0x:contracts-integration-tests` Added an integration-tests package and a deployment manager class --- .gitignore | 2 + .prettierignore | 2 + contracts/exchange/src/wrapper_interfaces.ts | 3 + contracts/integration-tests/CHANGELOG.json | 15 + contracts/integration-tests/README.md | 65 +++ contracts/integration-tests/compiler.json | 26 + .../integration-tests/contracts/Empty.sol | 7 + .../contracts/test/StakingWithTokens.sol | 53 ++ contracts/integration-tests/package.json | 99 ++++ contracts/integration-tests/src/artifacts.ts | 9 + .../src/deployment_mananger.ts | 453 ++++++++++++++++++ contracts/integration-tests/src/index.ts | 3 + contracts/integration-tests/src/wrappers.ts | 6 + .../test/deployment_manager_test.ts | 176 +++++++ .../test/deployment_test.ts} | 23 +- contracts/integration-tests/tsconfig.json | 6 + .../contracts/src/AssetProxyOwner.sol | 4 +- 17 files changed, 938 insertions(+), 14 deletions(-) create mode 100644 contracts/integration-tests/CHANGELOG.json create mode 100644 contracts/integration-tests/README.md create mode 100644 contracts/integration-tests/compiler.json create mode 100644 contracts/integration-tests/contracts/Empty.sol create mode 100644 contracts/integration-tests/contracts/test/StakingWithTokens.sol create mode 100644 contracts/integration-tests/package.json create mode 100644 contracts/integration-tests/src/artifacts.ts create mode 100644 contracts/integration-tests/src/deployment_mananger.ts create mode 100644 contracts/integration-tests/src/index.ts create mode 100644 contracts/integration-tests/src/wrappers.ts create mode 100644 contracts/integration-tests/test/deployment_manager_test.ts rename contracts/{exchange/test/end-to-end/deployment.ts => integration-tests/test/deployment_test.ts} (99%) create mode 100644 contracts/integration-tests/tsconfig.json diff --git a/.gitignore b/.gitignore index 0c111bd88f..b415882dee 100644 --- a/.gitignore +++ b/.gitignore @@ -82,6 +82,7 @@ TODO.md packages/testnet-faucets/server/ # generated contract artifacts/ +contracts/integration-tests/generated-artifacts/ contracts/staking/generated-artifacts/ contracts/coordinator/generated-artifacts/ contracts/exchange/generated-artifacts/ @@ -115,6 +116,7 @@ contracts/dev-utils/build/ # generated contract wrappers packages/python-contract-wrappers/generated/ +contracts/integration-tests/generated-wrappers/ contracts/staking/generated-wrappers/ contracts/coordinator/generated-wrappers/ contracts/exchange/generated-wrappers/ diff --git a/.prettierignore b/.prettierignore index a308083081..e074386c49 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,7 @@ lib .nyc_output +/contracts/integration-tests/generated-wrappers +/contracts/integration-tests/generated-artifacts /contracts/staking/generated-wrappers /contracts/staking/generated-artifacts /contracts/coordinator/generated-wrappers diff --git a/contracts/exchange/src/wrapper_interfaces.ts b/contracts/exchange/src/wrapper_interfaces.ts index 11acfb6624..88ed09502b 100644 --- a/contracts/exchange/src/wrapper_interfaces.ts +++ b/contracts/exchange/src/wrapper_interfaces.ts @@ -36,6 +36,9 @@ export interface Authorizable extends Ownable { authorized: { callAsync(authority: string, callData?: Partial, defaultBlock?: BlockParam): Promise; }; + getAuthorizedAddresses: { + callAsync(callData?: Partial, defaultBlock?: BlockParam): Promise; + }; } export interface Ownable { diff --git a/contracts/integration-tests/CHANGELOG.json b/contracts/integration-tests/CHANGELOG.json new file mode 100644 index 0000000000..3bc7806044 --- /dev/null +++ b/contracts/integration-tests/CHANGELOG.json @@ -0,0 +1,15 @@ +[ + { + "version": "1.0.0", + "changes": [ + { + "note": "Created package", + "pr": "2240" + }, + { + "note": "Added the deployment manager class", + "pr": "2240" + } + ] + } +] diff --git a/contracts/integration-tests/README.md b/contracts/integration-tests/README.md new file mode 100644 index 0000000000..ab729e9c1c --- /dev/null +++ b/contracts/integration-tests/README.md @@ -0,0 +1,65 @@ +## Integration Tests + +This package implements integration tests against 0x's smart contracts and will provide a location for external contracts to be tested alongside the 0x smart contracts. + +## Installation + +**Install** + +```bash +npm install @0x/contracts-staking --save +``` + +## Contributing + +We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository. + +For proposals regarding the 0x protocol's smart contract architecture, message format, or additional functionality, go to the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository and follow the contribution guidelines provided therein. + +Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started. + +### Install Dependencies + +If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them: + +```bash +yarn config set workspaces-experimental true +``` + +Then install dependencies + +```bash +yarn install +``` + +### Build + +To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory: + +```bash +PKG=@0x/contracts-integration-tests yarn build +``` + +Or continuously rebuild on change: + +```bash +PKG=@0x/contracts-integration-tests yarn watch +``` + +### Clean + +```bash +yarn clean +``` + +### Lint + +```bash +yarn lint +``` + +### Run Tests + +```bash +yarn test +``` diff --git a/contracts/integration-tests/compiler.json b/contracts/integration-tests/compiler.json new file mode 100644 index 0000000000..6b74c612c2 --- /dev/null +++ b/contracts/integration-tests/compiler.json @@ -0,0 +1,26 @@ +{ + "artifactsDir": "./generated-artifacts", + "contractsDir": "./contracts", + "useDockerisedSolc": false, + "isOfflineMode": false, + "compilerSettings": { + "evmVersion": "constantinople", + "optimizer": { + "enabled": true, + "runs": 1000000, + "details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true } + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "devdoc", + "evm.bytecode.object", + "evm.bytecode.sourceMap", + "evm.deployedBytecode.object", + "evm.deployedBytecode.sourceMap" + ] + } + } + } +} diff --git a/contracts/integration-tests/contracts/Empty.sol b/contracts/integration-tests/contracts/Empty.sol new file mode 100644 index 0000000000..ccae8c5f09 --- /dev/null +++ b/contracts/integration-tests/contracts/Empty.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.5.0; + + +// TODO(jalextowle): This contract must be included to ensure that `abi-gen` +// doesn't fail to run. Remove this contract or remove the contracts directory +// depending on whether or not this package should contain packages. +contract Empty { } // solhint-disable-line no-empty-blocks diff --git a/contracts/integration-tests/contracts/test/StakingWithTokens.sol b/contracts/integration-tests/contracts/test/StakingWithTokens.sol new file mode 100644 index 0000000000..c8fbb69343 --- /dev/null +++ b/contracts/integration-tests/contracts/test/StakingWithTokens.sol @@ -0,0 +1,53 @@ +pragma solidity ^0.5.9; +pragma experimental ABIEncoderV2; + +import "@0x/contracts-staking/contracts/src/Staking.sol"; + + +contract StakingWithTokens is + Staking +{ + address public wethAddress; + address public zrxVault; + + bytes4 internal constant WETH_PROXY_ID = 0xf47261b0; + + function setWethAddress(address weth) + public + { + wethAddress = weth; + } + + function setZrxVault(address vault) + public + { + zrxVault = vault; + } + + function getWethAssetData() + public + view + returns (bytes memory) + { + return abi.encodeWithSelector( + WETH_PROXY_ID, + wethAddress + ); + } + + function getWethContract() + public + view + returns (IEtherToken) + { + return IEtherToken(wethAddress); + } + + function getZrxVault() + public + view + returns (IZrxVault) + { + return IZrxVault(zrxVault); + } +} diff --git a/contracts/integration-tests/package.json b/contracts/integration-tests/package.json new file mode 100644 index 0000000000..170a724107 --- /dev/null +++ b/contracts/integration-tests/package.json @@ -0,0 +1,99 @@ +{ + "name": "@0x/contracts-integration-tests", + "version": "1.0.0", + "engines": { + "node": ">=6.12" + }, + "description": "Integration tests for the 0x protocol", + "main": "lib/src/index.js", + "directories": { + "test": "test" + }, + "scripts": { + "build": "yarn pre_build && tsc -b", + "build:ci": "yarn build", + "pre_build": "run-s compile contracts:gen generate_contract_wrappers", + "test": "yarn run_mocha", + "rebuild_and_test": "run-s build test", + "test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov", + "test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html", + "test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha", + "run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit", + "compile": "sol-compiler", + "watch": "sol-compiler -w", + "clean": "shx rm -rf lib generated-artifacts generated-wrappers", + "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", + "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", + "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", + "coverage:report:text": "istanbul report text", + "coverage:report:html": "istanbul report html && open coverage/index.html", + "profiler:report:html": "istanbul report html && open coverage/index.html", + "coverage:report:lcov": "istanbul report lcov", + "test:circleci": "yarn test", + "contracts:gen": "contracts-gen", + "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol", + "compile:truffle": "truffle compile" + }, + "config": { + "abis": "./generated-artifacts/@(StakingWithTokens).json", + "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually." + }, + "repository": { + "type": "git", + "url": "https://github.com/0xProject/0x-monorepo.git" + }, + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/0xProject/0x-monorepo/issues" + }, + "homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md", + "devDependencies": { + "@0x/abi-gen": "^4.3.0-beta.0", + "@0x/contracts-gen": "^1.1.0-beta.0", + "@0x/dev-utils": "^2.4.0-beta.0", + "@0x/sol-compiler": "^3.2.0-beta.0", + "@0x/tslint-config": "^3.0.1", + "@types/lodash": "4.14.104", + "@types/mocha": "^5.2.7", + "@types/node": "*", + "chai": "^4.0.1", + "chai-as-promised": "^7.1.0", + "chai-bignumber": "^3.0.0", + "dirty-chai": "^2.0.1", + "make-promises-safe": "^1.1.0", + "mocha": "^6.2.0", + "npm-run-all": "^4.1.2", + "shx": "^0.2.2", + "solhint": "^1.4.1", + "truffle": "^5.0.32", + "tslint": "5.11.0", + "typescript": "3.0.1" + }, + "dependencies": { + "@0x/base-contract": "^5.5.0-beta.0", + "@0x/contracts-asset-proxy": "^2.3.0-beta.0", + "@0x/contracts-coordinator": "^2.1.0-beta.0", + "@0x/contracts-dev-utils": "^0.1.0-beta.0", + "@0x/contracts-erc1155": "^1.2.0-beta.0", + "@0x/contracts-erc20": "^2.3.0-beta.0", + "@0x/contracts-erc721": "^2.2.0-beta.0", + "@0x/contracts-exchange": "^2.2.0-beta.0", + "@0x/contracts-exchange-forwarder": "^3.1.0-beta.0", + "@0x/contracts-exchange-libs": "^3.1.0-beta.0", + "@0x/contracts-extensions": "^4.1.0-beta.0", + "@0x/contracts-multisig": "^3.2.0-beta.0", + "@0x/contracts-staking": "^1.1.0-beta.0", + "@0x/contracts-test-utils": "^3.2.0-beta.0", + "@0x/contracts-utils": "^3.3.0-beta.0", + "@0x/order-utils": "^8.5.0-beta.0", + "@0x/types": "^2.5.0-beta.0", + "@0x/typescript-typings": "^4.4.0-beta.0", + "@0x/utils": "^4.6.0-beta.0", + "@0x/web3-wrapper": "^6.1.0-beta.0", + "ethereum-types": "^2.2.0-beta.0", + "lodash": "^4.17.11" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/contracts/integration-tests/src/artifacts.ts b/contracts/integration-tests/src/artifacts.ts new file mode 100644 index 0000000000..bc8f8d3013 --- /dev/null +++ b/contracts/integration-tests/src/artifacts.ts @@ -0,0 +1,9 @@ +/* + * ----------------------------------------------------------------------------- + * Warning: This file is auto-generated by contracts-gen. Don't edit manually. + * ----------------------------------------------------------------------------- + */ +import { ContractArtifact } from 'ethereum-types'; + +import * as StakingWithTokens from '../generated-artifacts/StakingWithTokens.json'; +export const artifacts = { StakingWithTokens: StakingWithTokens as ContractArtifact }; diff --git a/contracts/integration-tests/src/deployment_mananger.ts b/contracts/integration-tests/src/deployment_mananger.ts new file mode 100644 index 0000000000..2fb9dd5220 --- /dev/null +++ b/contracts/integration-tests/src/deployment_mananger.ts @@ -0,0 +1,453 @@ +import { + artifacts as assetProxyArtifacts, + ERC1155ProxyContract, + ERC20ProxyContract, + ERC721ProxyContract, + MultiAssetProxyContract, + StaticCallProxyContract, +} from '@0x/contracts-asset-proxy'; +import { artifacts as ERC1155Artifacts, ERC1155Contract } from '@0x/contracts-erc1155'; +import { artifacts as ERC20Artifacts, ERC20TokenContract, ZRXTokenContract, WETH9Contract } from '@0x/contracts-erc20'; +import { artifacts as ERC721Artifacts, ERC721TokenContract } from '@0x/contracts-erc721'; +import { + artifacts as exchangeArtifacts, + AssetProxyDispatcher, + Authorizable, + ExchangeContract, + Ownable, +} from '@0x/contracts-exchange'; +import { artifacts as multisigArtifacts, AssetProxyOwnerContract } from '@0x/contracts-multisig'; +import { + artifacts as stakingArtifacts, + ReadOnlyProxyContract, + StakingContract, + StakingProxyContract, + ZrxVaultContract, +} from '@0x/contracts-staking'; +import { BlockchainTestsEnvironment, constants } from '@0x/contracts-test-utils'; +import { Web3ProviderEngine } from '@0x/subproviders'; +import { BigNumber } from '@0x/utils'; +import { TxData } from 'ethereum-types'; +import * as _ from 'lodash'; + +import { artifacts, StakingWithTokensContract } from './'; + +/** + * Adds a batch of authorities to a list of authorizable contracts. + * @param owner The owner of the authorizable contracts. + * @param authorizers The authorizable contracts. + * @param authorities A list of addresses to authorize in each authorizer contract. + */ +async function batchAddAuthorizedAddressAsync( + owner: string, + authorizers: Authorizable[], + authorities: string[], +): Promise { + for (const authorizer of authorizers) { + for (const authority of authorities) { + await authorizer.addAuthorizedAddress.awaitTransactionSuccessAsync(authority, { from: owner }); + } + } +} + +/** + * Batch registers asset proxies in a list of registry contracts. + * @param owner The owner of the registry accounts. + * @param registries The registries that the asset proxies should be registered in. + * @param proxies A list of proxy contracts to register. + */ +async function batchRegisterAssetProxyAsync( + owner: string, + registries: AssetProxyDispatcher[], + proxies: string[], +): Promise { + for (const registry of registries) { + for (const proxy of proxies) { + await registry.registerAssetProxy.awaitTransactionSuccessAsync(proxy, { from: owner }); + } + } +} + +/** + * Transfers ownership of several contracts from one address to another. + * @param owner The address that currently owns the contract instances. + * @param newOwner The address that will be given ownership of the contract instances. + * @param ownedContracts The contracts whose ownership will be transferred. + */ +async function batchTransferOwnershipAsync( + owner: string, + newOwner: AssetProxyOwnerContract, + ownedContracts: Ownable[], +): Promise { + for (const ownedContract of ownedContracts) { + await ownedContract.transferOwnership.awaitTransactionSuccessAsync(newOwner.address, { from: owner }); + } +} + +// Contract wrappers for all of the asset proxies +interface AssetProxyContracts { + erc20Proxy: ERC20ProxyContract; + erc721Proxy: ERC721ProxyContract; + erc1155Proxy: ERC1155ProxyContract; + multiAssetProxy: MultiAssetProxyContract; + staticCallProxy: StaticCallProxyContract; +} + +// Contract wrappers for all of the staking contracts +interface StakingContracts { + readOnlyProxy: ReadOnlyProxyContract; + stakingLogic: StakingWithTokensContract; + stakingProxy: StakingProxyContract; + stakingWrapper: StakingWithTokensContract; + zrxVault: ZrxVaultContract; +} + +// Contract wrappers for tokens. +interface TokenContracts { + erc1155: ERC1155Contract; + erc20: ERC20TokenContract; + erc721: ERC721TokenContract; + weth: WETH9Contract; + zrx: ZRXTokenContract; +} + +export class DeploymentManager { + public static protocolFeeMultiplier = new BigNumber(150000); + + public assetProxies: AssetProxyContracts; + public assetProxyOwner: AssetProxyOwnerContract; + public exchange: ExchangeContract; + public staking: StakingContracts; + public tokens: TokenContracts; + + /** + * Fully deploy the 0x exchange and staking contracts and configure the system with the + * asset proxy owner multisig. + * @param environment A blockchain test environment to use for contracts deployment. + */ + public static async deployAsync(environment: BlockchainTestsEnvironment): Promise { + const chainId = await environment.getChainIdAsync(); + const [owner] = await environment.getAccountAddressesAsync(); + const txDefaults = { + ...environment.txDefaults, + from: owner, + }; + + // Deploy the contracts using the same owner and environment. + const assetProxies = await DeploymentManager._deployAssetProxyContractsAsync(environment, owner, txDefaults); + const exchange = await ExchangeContract.deployFrom0xArtifactAsync( + exchangeArtifacts.Exchange, + environment.provider, + environment.txDefaults, + exchangeArtifacts, + new BigNumber(chainId), + ); + const assetProxyOwner = await AssetProxyOwnerContract.deployFrom0xArtifactAsync( + multisigArtifacts.AssetProxyOwner, + environment.provider, + txDefaults, + multisigArtifacts, + [], + [], + [], + [owner], + new BigNumber(1), + constants.ZERO_AMOUNT, + ); + const tokens = await DeploymentManager._deployTokenContractsAsync(environment, txDefaults); + const staking = await DeploymentManager._deployStakingContractsAsync( + environment, + owner, + txDefaults, + tokens, + assetProxies, + ); + + // Configure the asset proxies with the exchange and the exchange with the staking contracts. + await DeploymentManager._configureAssetProxiesWithExchangeAsync(assetProxies, exchange, owner); + await DeploymentManager._configureExchangeWithStakingAsync(exchange, staking, owner); + + // Authorize the asset-proxy owner in the staking proxy and in the zrx vault. + await staking.stakingProxy.addAuthorizedAddress.awaitTransactionSuccessAsync(assetProxyOwner.address, { + from: owner, + }); + await staking.zrxVault.addAuthorizedAddress.awaitTransactionSuccessAsync(assetProxyOwner.address, { + from: owner, + }); + + // Remove authorization for the original owner address. + await staking.stakingProxy.removeAuthorizedAddress.awaitTransactionSuccessAsync(owner, { from: owner }); + await staking.zrxVault.removeAuthorizedAddress.awaitTransactionSuccessAsync(owner, { from: owner }); + + // Transfer complete ownership of the system to the asset proxy owner. + await batchTransferOwnershipAsync(owner, assetProxyOwner, [ + assetProxies.erc20Proxy, + assetProxies.erc721Proxy, + assetProxies.erc1155Proxy, + assetProxies.multiAssetProxy, + exchange, + staking.readOnlyProxy, + staking.stakingProxy, + ]); + + return new DeploymentManager(assetProxies, assetProxyOwner, exchange, staking, tokens); + } + + /** + * Configures a set of asset proxies with an exchange contract. + * @param assetProxies A set of asset proxies to be configured. + * @param exchange An exchange contract to configure with the asset proxies. + * @param owner An owner address to use when configuring the asset proxies. + */ + protected static async _configureAssetProxiesWithExchangeAsync( + assetProxies: AssetProxyContracts, + exchange: ExchangeContract, + owner: string, + ): Promise { + // Register the asset proxies in the exchange contract. + await batchRegisterAssetProxyAsync( + owner, + [exchange], + [ + assetProxies.erc20Proxy.address, + assetProxies.erc721Proxy.address, + assetProxies.erc1155Proxy.address, + assetProxies.multiAssetProxy.address, + assetProxies.staticCallProxy.address, + ], + ); + + // Register the asset proxies in the multi-asset proxy. + await batchRegisterAssetProxyAsync( + owner, + [assetProxies.multiAssetProxy], + [ + assetProxies.erc20Proxy.address, + assetProxies.erc721Proxy.address, + assetProxies.erc1155Proxy.address, + assetProxies.staticCallProxy.address, + ], + ); + + // Add the multi-asset proxy as an authorized address of the token proxies. + await batchAddAuthorizedAddressAsync( + owner, + [assetProxies.erc20Proxy, assetProxies.erc721Proxy, assetProxies.erc1155Proxy], + [assetProxies.multiAssetProxy.address], + ); + + // Add the exchange as an authorized address in all of the proxies. + await batchAddAuthorizedAddressAsync( + owner, + [ + assetProxies.erc20Proxy, + assetProxies.erc721Proxy, + assetProxies.erc1155Proxy, + assetProxies.multiAssetProxy, + ], + [exchange.address], + ); + } + + /** + * Configures an exchange contract with staking contracts + * @param exchange + * @param staking + * @param owner An owner address to use when configuring the asset proxies. + */ + protected static async _configureExchangeWithStakingAsync( + exchange: ExchangeContract, + staking: StakingContracts, + owner: string, + ): Promise { + // Configure the exchange for staking. + await exchange.setProtocolFeeCollectorAddress.awaitTransactionSuccessAsync(staking.stakingProxy.address, { + from: owner, + }); + await exchange.setProtocolFeeMultiplier.awaitTransactionSuccessAsync(DeploymentManager.protocolFeeMultiplier); + + // Register the exchange contract in staking. + await staking.stakingWrapper.addExchangeAddress.awaitTransactionSuccessAsync(exchange.address, { from: owner }); + } + + /** + * Deploy a set of asset proxy contracts. + * @param environment The blockchain environment to use. + * @param owner An owner address to use when configuring the asset proxies. + * @param txDefaults Defaults to use when deploying the asset proxies. + */ + protected static async _deployAssetProxyContractsAsync( + environment: BlockchainTestsEnvironment, + owner: string, + txDefaults: Partial, + ): Promise { + const erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync( + assetProxyArtifacts.ERC20Proxy, + environment.provider, + txDefaults, + assetProxyArtifacts, + ); + const erc721Proxy = await ERC721ProxyContract.deployFrom0xArtifactAsync( + assetProxyArtifacts.ERC721Proxy, + environment.provider, + txDefaults, + assetProxyArtifacts, + ); + const erc1155Proxy = await ERC1155ProxyContract.deployFrom0xArtifactAsync( + assetProxyArtifacts.ERC1155Proxy, + environment.provider, + txDefaults, + assetProxyArtifacts, + ); + const multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync( + assetProxyArtifacts.MultiAssetProxy, + environment.provider, + txDefaults, + assetProxyArtifacts, + ); + const staticCallProxy = await StaticCallProxyContract.deployFrom0xArtifactAsync( + assetProxyArtifacts.StaticCallProxy, + environment.provider, + txDefaults, + assetProxyArtifacts, + ); + return { + erc20Proxy, + erc721Proxy, + erc1155Proxy, + multiAssetProxy, + staticCallProxy, + }; + } + + /** + * Deploy a set of staking contracts. + * @param environment The blockchain environment to use. + * @param owner An owner address to use when configuring the asset proxies. + * @param txDefaults Defaults to use when deploying the asset proxies. + * @param tokens A set of token contracts to use during deployment of the staking contracts. + * @param assetProxies A set of asset proxies to use with the staking contracts. + */ + protected static async _deployStakingContractsAsync( + environment: BlockchainTestsEnvironment, + owner: string, + txDefaults: Partial, + tokens: TokenContracts, + assetProxies: AssetProxyContracts, + ): Promise { + const zrxVault = await ZrxVaultContract.deployFrom0xArtifactAsync( + stakingArtifacts.ZrxVault, + environment.provider, + txDefaults, + stakingArtifacts, + assetProxies.erc20Proxy.address, + tokens.zrx.address, + ); + const readOnlyProxy = await ReadOnlyProxyContract.deployFrom0xArtifactAsync( + stakingArtifacts.ReadOnlyProxy, + environment.provider, + txDefaults, + stakingArtifacts, + ); + const stakingLogic = await StakingWithTokensContract.deployFrom0xArtifactAsync( + artifacts.StakingWithTokens, + environment.provider, + txDefaults, + stakingArtifacts, + ); + const stakingProxy = await StakingProxyContract.deployFrom0xArtifactAsync( + stakingArtifacts.StakingProxy, + environment.provider, + txDefaults, + stakingArtifacts, + stakingLogic.address, + readOnlyProxy.address, + ); + const stakingWrapper = new StakingWithTokensContract(stakingProxy.address, environment.provider); + + // Authorize the owner address in the staking proxy and the zrx vault. + await stakingProxy.addAuthorizedAddress.awaitTransactionSuccessAsync(owner, { from: owner }); + await zrxVault.addAuthorizedAddress.awaitTransactionSuccessAsync(owner, { from: owner }); + + // Configure the zrx vault and the staking contract. + await zrxVault.setStakingProxy.awaitTransactionSuccessAsync(stakingProxy.address, { from: owner }); + await zrxVault.setStakingProxy.awaitTransactionSuccessAsync(stakingProxy.address, { from: owner }); + await stakingWrapper.setZrxVault.awaitTransactionSuccessAsync(zrxVault.address, { from: owner }); + await stakingWrapper.setWethAddress.awaitTransactionSuccessAsync(tokens.weth.address, { from: owner }); + + return { + readOnlyProxy, + stakingLogic, + stakingProxy, + stakingWrapper, + zrxVault, + }; + } + + /** + * Deploy a set of token contracts. + * @param environment The blockchain environment to use. + * @param txDefaults Defaults to use when deploying the asset proxies. + */ + protected static async _deployTokenContractsAsync( + environment: BlockchainTestsEnvironment, + txDefaults: Partial, + ): Promise { + const erc20 = await ERC20TokenContract.deployFrom0xArtifactAsync( + ERC20Artifacts.ERC20Token, + environment.provider, + txDefaults, + ERC20Artifacts, + ); + + const erc721 = await ERC721TokenContract.deployFrom0xArtifactAsync( + ERC721Artifacts.ERC721Token, + environment.provider, + txDefaults, + ERC721Artifacts, + ); + + const erc1155 = await ERC1155Contract.deployFrom0xArtifactAsync( + ERC1155Artifacts.ERC1155, + environment.provider, + txDefaults, + ERC1155Artifacts, + ); + + const weth = await WETH9Contract.deployFrom0xArtifactAsync( + ERC20Artifacts.WETH9, + environment.provider, + txDefaults, + ERC20Artifacts, + ); + + const zrx = await ZRXTokenContract.deployFrom0xArtifactAsync( + ERC20Artifacts.ZRXToken, + environment.provider, + txDefaults, + ERC20Artifacts, + ); + + return { + erc1155, + erc20, + erc721, + weth, + zrx, + }; + } + + private constructor( + assetProxies: AssetProxyContracts, + assetProxyOwner: AssetProxyOwnerContract, + exchange: ExchangeContract, + staking: StakingContracts, + tokens: TokenContracts, + ) { + this.assetProxies = assetProxies; + this.assetProxyOwner = assetProxyOwner; + this.exchange = exchange; + this.staking = staking; + this.tokens = tokens; + } +} diff --git a/contracts/integration-tests/src/index.ts b/contracts/integration-tests/src/index.ts new file mode 100644 index 0000000000..a51a51959b --- /dev/null +++ b/contracts/integration-tests/src/index.ts @@ -0,0 +1,3 @@ +export * from './artifacts'; +export * from './wrappers'; +export * from './deployment_mananger'; diff --git a/contracts/integration-tests/src/wrappers.ts b/contracts/integration-tests/src/wrappers.ts new file mode 100644 index 0000000000..289a4cf2d1 --- /dev/null +++ b/contracts/integration-tests/src/wrappers.ts @@ -0,0 +1,6 @@ +/* + * ----------------------------------------------------------------------------- + * Warning: This file is auto-generated by contracts-gen. Don't edit manually. + * ----------------------------------------------------------------------------- + */ +export * from '../generated-wrappers/staking_with_tokens'; diff --git a/contracts/integration-tests/test/deployment_manager_test.ts b/contracts/integration-tests/test/deployment_manager_test.ts new file mode 100644 index 0000000000..70b3538987 --- /dev/null +++ b/contracts/integration-tests/test/deployment_manager_test.ts @@ -0,0 +1,176 @@ +import { Authorizable, Ownable } from '@0x/contracts-exchange'; +import { blockchainTests, constants, expect } from '@0x/contracts-test-utils'; +import { BigNumber } from '@0x/utils'; + +import { DeploymentManager } from '../src'; + +blockchainTests('Deployment Manager', env => { + let owner: string; + let deploymentManager: DeploymentManager; + + before(async () => { + [owner] = await env.getAccountAddressesAsync(); + + deploymentManager = await DeploymentManager.deployAsync(env); + }); + + async function batchAssertAuthoritiesAsync( + authorities: string[], + authorizedContracts: Authorizable[], + ): Promise { + for (const authorized of authorizedContracts) { + expect(await authorized.getAuthorizedAddresses.callAsync()).to.be.deep.eq(authorities); + } + } + + async function batchAssertAuthorizedAsync( + authorizedAddress: string, + authorizedContracts: Authorizable[], + ): Promise { + for (const authorized of authorizedContracts) { + expect(await authorized.authorized.callAsync(authorizedAddress)).to.be.true(); + } + } + + async function batchAssertOwnerAsync(ownerAddress: string, owners: Ownable[]): Promise { + for (const ownerContract of owners) { + expect(await ownerContract.owner.callAsync()).to.be.eq(ownerAddress); + } + } + + describe('asset proxy owner', () => { + it('should be owned by `owner`', async () => { + // Ensure that the owners of the asset proxy only contain the owner. + const owners = await deploymentManager.assetProxyOwner.getOwners.callAsync(); + expect(owners).to.be.deep.eq([owner]); + }); + }); + + describe('asset proxies', () => { + it('should be owned be the asset proxy owner', async () => { + await batchAssertOwnerAsync(deploymentManager.assetProxyOwner.address, [ + deploymentManager.assetProxies.erc1155Proxy, + deploymentManager.assetProxies.erc20Proxy, + deploymentManager.assetProxies.erc721Proxy, + deploymentManager.assetProxies.multiAssetProxy, + ]); + }); + + it('should have authorized the multi-asset proxy', async () => { + await batchAssertAuthorizedAsync(deploymentManager.assetProxies.multiAssetProxy.address, [ + deploymentManager.assetProxies.erc1155Proxy, + deploymentManager.assetProxies.erc20Proxy, + deploymentManager.assetProxies.erc721Proxy, + ]); + }); + + it('should have authorized the exchange', async () => { + await batchAssertAuthorizedAsync(deploymentManager.exchange.address, [ + deploymentManager.assetProxies.erc1155Proxy, + deploymentManager.assetProxies.erc20Proxy, + deploymentManager.assetProxies.erc721Proxy, + deploymentManager.assetProxies.multiAssetProxy, + ]); + }); + + it('should have the correct authorities list', async () => { + // The multi-asset proxy should only have the exchange in the authorities list. + const authorities = await deploymentManager.assetProxies.multiAssetProxy.getAuthorizedAddresses.callAsync(); + expect(authorities).to.be.deep.eq([deploymentManager.exchange.address]); + + // The other asset proxies should have the exchange and the multi-asset proxy in their + // authorities list. + await batchAssertAuthoritiesAsync( + [deploymentManager.assetProxies.multiAssetProxy.address, deploymentManager.exchange.address], + [ + deploymentManager.assetProxies.erc1155Proxy, + deploymentManager.assetProxies.erc20Proxy, + deploymentManager.assetProxies.erc721Proxy, + ], + ); + }); + }); + + describe('exchange', () => { + it('should be owned by the asset proxy owner', async () => { + const exchangeOwner = await deploymentManager.exchange.owner.callAsync(); + expect(exchangeOwner).to.be.eq(deploymentManager.assetProxyOwner.address); + }); + + /* + TODO(jalextowle): This test should be enabled once the Exchange is + made an Authorizable contract. + it('should have authorized the asset proxy owner', async () => { + const isAuthorized = await deploymentManager.exchange.owner.callAsync( + deploymentManager.assetProxyOwner.address, + ); + expect(isAuthorized).to.be.true(); + }); + */ + + it('should have registered the staking proxy', async () => { + const feeCollector = await deploymentManager.exchange.protocolFeeCollector.callAsync(); + expect(feeCollector).to.be.eq(deploymentManager.staking.stakingProxy.address); + }); + + it('should have set the protocol fee multiplier', async () => { + const feeMultiplier = await deploymentManager.exchange.protocolFeeMultiplier.callAsync(); + expect(feeMultiplier).bignumber.to.be.eq(DeploymentManager.protocolFeeMultiplier); + }); + }); + + describe('staking', () => { + it('should be owned by the asset proxy owner', async () => { + const stakingOwner = await deploymentManager.staking.stakingProxy.owner.callAsync(); + expect(stakingOwner).to.be.eq(deploymentManager.assetProxyOwner.address); + }); + + it('should have authorized the asset proxy owner in the staking proxy', async () => { + const isAuthorized = await deploymentManager.staking.stakingProxy.authorized.callAsync( + deploymentManager.assetProxyOwner.address, + ); + expect(isAuthorized).to.be.true(); + }); + + it('should have registered the exchange in the staking proxy', async () => { + const isValid = await deploymentManager.staking.stakingProxy.validExchanges.callAsync( + deploymentManager.exchange.address, + ); + expect(isValid).to.be.true(); + }); + + it('should have registered the read-only proxy in the staking proxy', async () => { + const readOnlyProxy = await deploymentManager.staking.stakingProxy.readOnlyProxy.callAsync(); + expect(readOnlyProxy).to.be.eq(deploymentManager.staking.readOnlyProxy.address); + }); + + it('should have registered the staking contract in the staking proxy', async () => { + const stakingContract = await deploymentManager.staking.stakingProxy.stakingContract.callAsync(); + expect(stakingContract).to.be.eq(deploymentManager.staking.stakingLogic.address); + }); + + it('should have registered the weth contract in the staking contract', async () => { + const weth = await deploymentManager.staking.stakingWrapper.wethAddress.callAsync(); + expect(weth).to.be.eq(deploymentManager.tokens.weth.address); + }); + + it('should have registered the zrx vault in the staking contract', async () => { + const zrxVault = await deploymentManager.staking.stakingWrapper.zrxVault.callAsync(); + expect(zrxVault).to.be.eq(deploymentManager.staking.zrxVault.address); + }); + + it('should have registered the staking proxy in the zrx vault', async () => { + const stakingProxy = await deploymentManager.staking.zrxVault.stakingProxyAddress.callAsync(); + expect(stakingProxy).to.be.eq(deploymentManager.staking.stakingProxy.address); + }); + + it('should have correctly set the params', async () => { + const params = await deploymentManager.staking.stakingWrapper.getParams.callAsync(); + expect(params).to.be.deep.eq( + [10 * 60 * 60 * 24, (90 * constants.PPM_DENOMINATOR) / 100, 100 * 1e18, 10, 1, 2].map( + value => new BigNumber(value), + ), + ); + }); + }); +}); diff --git a/contracts/exchange/test/end-to-end/deployment.ts b/contracts/integration-tests/test/deployment_test.ts similarity index 99% rename from contracts/exchange/test/end-to-end/deployment.ts rename to contracts/integration-tests/test/deployment_test.ts index a2ca5d856c..b45b3f5477 100644 --- a/contracts/exchange/test/end-to-end/deployment.ts +++ b/contracts/integration-tests/test/deployment_test.ts @@ -6,6 +6,17 @@ import { MultiAssetProxyContract, StaticCallProxyContract, } from '@0x/contracts-asset-proxy'; +import { + artifacts as exchangeArtifacts, + AssetProxyDispatcher, + Authorizable, + ExchangeAssetProxyRegisteredEventArgs, + ExchangeContract, + ExchangeEvents, + ExchangeProtocolFeeCollectorAddressEventArgs, + ExchangeProtocolFeeMultiplierEventArgs, + Ownable, +} from '@0x/contracts-exchange'; import { artifacts as multisigArtifacts, AssetProxyOwnerContract } from '@0x/contracts-multisig'; import { artifacts as stakingArtifacts, @@ -25,18 +36,6 @@ import { AssetProxyId } from '@0x/types'; import { BigNumber } from '@0x/utils'; import { TxData } from 'ethereum-types'; -import { - artifacts as exchangeArtifacts, - AssetProxyDispatcher, - Authorizable, - ExchangeAssetProxyRegisteredEventArgs, - ExchangeContract, - ExchangeEvents, - ExchangeProtocolFeeCollectorAddressEventArgs, - ExchangeProtocolFeeMultiplierEventArgs, - Ownable, -} from '../../src'; - // tslint:disable:no-unnecessary-type-assertion blockchainTests('Deployment and Configuration End to End Tests', env => { // Available Addresses diff --git a/contracts/integration-tests/tsconfig.json b/contracts/integration-tests/tsconfig.json new file mode 100644 index 0000000000..b7fbedee7f --- /dev/null +++ b/contracts/integration-tests/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../tsconfig", + "compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true }, + "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"], + "files": ["generated-artifacts/StakingWithTokens.json"] +} diff --git a/contracts/multisig/contracts/src/AssetProxyOwner.sol b/contracts/multisig/contracts/src/AssetProxyOwner.sol index 204ae6d3e1..9e424e9c7d 100644 --- a/contracts/multisig/contracts/src/AssetProxyOwner.sol +++ b/contracts/multisig/contracts/src/AssetProxyOwner.sol @@ -46,7 +46,7 @@ contract AssetProxyOwner is mapping (bytes4 => mapping (address => TimeLock)) public functionCallTimeLocks; /// @dev Contract constructor sets initial owners, required number of confirmations, and default time lock - /// It will also register unique timelocks for each passed in function selector / destination combo. + /// It will also register unique timelocks for each passed in function selector / destination combo. /// @param _functionSelectors Array of function selectors for registered functions. /// @param _destinations Array of destinations for registered function calls. /// @param _functionCallTimeLockSeconds Array of seconds that each registered function call will be timelocked. @@ -170,7 +170,7 @@ contract AssetProxyOwner is bool hasCustomTimeLock, bytes4 functionSelector, address destination, - uint128 newSecondsTimeLocked + uint128 newSecondsTimeLocked ) internal { From b8e01d7be535196a3145a431291183ecfbb333c6 Mon Sep 17 00:00:00 2001 From: fabioberger Date: Fri, 4 Oct 2019 13:28:25 +0800 Subject: [PATCH 03/87] Add beta version to next tslint-config release --- packages/tslint-config/CHANGELOG.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/tslint-config/CHANGELOG.json b/packages/tslint-config/CHANGELOG.json index ca8e72f988..34ba702768 100644 --- a/packages/tslint-config/CHANGELOG.json +++ b/packages/tslint-config/CHANGELOG.json @@ -1,4 +1,12 @@ [ + { + "version": "3.1.0-beta.0", + "changes": [ + { + "note": "Dependencies updated" + } + ] + }, { "version": "3.0.1", "changes": [ From 2020d87824e197a85ed71b2f2e91f319c3d3f7b7 Mon Sep 17 00:00:00 2001 From: fabioberger Date: Fri, 4 Oct 2019 20:44:18 +0800 Subject: [PATCH 04/87] Fix dist tag issue in publish script --- packages/monorepo-scripts/src/publish.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/monorepo-scripts/src/publish.ts b/packages/monorepo-scripts/src/publish.ts index 397336c8d0..697b599831 100644 --- a/packages/monorepo-scripts/src/publish.ts +++ b/packages/monorepo-scripts/src/publish.ts @@ -252,7 +252,7 @@ async function lernaPublishAsync(packageToNextVersion: { [name: string]: string lernaPublishArgs.push('--no-push'); } if (configs.DIST_TAG !== '') { - lernaPublishArgs.push(`--dist-tag ${configs.DIST_TAG}`); + lernaPublishArgs.push(`--dist-tag=${configs.DIST_TAG}`); } utils.log('Lerna is publishing...'); try { From 3c6957095d4c9808aa2eec3d45012a3e707ac1f6 Mon Sep 17 00:00:00 2001 From: Alex Towle Date: Fri, 4 Oct 2019 15:42:36 -0700 Subject: [PATCH 05/87] `@0x:contracts-integrations` Addressed review feedback --- .gitignore | 4 +- .prettierignore | 4 +- .../integration-tests/contracts/Empty.sol | 7 --- .../contracts/test/StakingWithTokens.sol | 53 ------------------- .../CHANGELOG.json | 0 .../README.md | 6 +-- .../compiler.json | 0 .../contracts/test/TestStakingPlaceholder.sol | 15 ++++++ .../package.json | 6 +-- .../src/artifacts.ts | 4 +- .../src/deployment_mananger.ts | 20 ++++--- .../src/index.ts | 0 .../src/wrappers.ts | 2 +- .../test/deployment_manager_test.ts | 18 ++++--- .../test/deployment_test.ts | 19 ++++--- .../tsconfig.json | 2 +- .../staking/contracts/test/TestStaking.sol | 16 ++++++ contracts/staking/src/index.ts | 1 + 18 files changed, 78 insertions(+), 99 deletions(-) delete mode 100644 contracts/integration-tests/contracts/Empty.sol delete mode 100644 contracts/integration-tests/contracts/test/StakingWithTokens.sol rename contracts/{integration-tests => integrations}/CHANGELOG.json (100%) rename contracts/{integration-tests => integrations}/README.md (90%) rename contracts/{integration-tests => integrations}/compiler.json (100%) create mode 100644 contracts/integrations/contracts/test/TestStakingPlaceholder.sol rename contracts/{integration-tests => integrations}/package.json (96%) rename contracts/{integration-tests => integrations}/src/artifacts.ts (61%) rename contracts/{integration-tests => integrations}/src/deployment_mananger.ts (96%) rename contracts/{integration-tests => integrations}/src/index.ts (100%) rename contracts/{integration-tests => integrations}/src/wrappers.ts (79%) rename contracts/{integration-tests => integrations}/test/deployment_manager_test.ts (92%) rename contracts/{integration-tests => integrations}/test/deployment_test.ts (97%) rename contracts/{integration-tests => integrations}/tsconfig.json (75%) diff --git a/.gitignore b/.gitignore index b415882dee..934fdf50d0 100644 --- a/.gitignore +++ b/.gitignore @@ -82,7 +82,7 @@ TODO.md packages/testnet-faucets/server/ # generated contract artifacts/ -contracts/integration-tests/generated-artifacts/ +contracts/integrations/generated-artifacts/ contracts/staking/generated-artifacts/ contracts/coordinator/generated-artifacts/ contracts/exchange/generated-artifacts/ @@ -116,7 +116,7 @@ contracts/dev-utils/build/ # generated contract wrappers packages/python-contract-wrappers/generated/ -contracts/integration-tests/generated-wrappers/ +contracts/integrations/generated-wrappers/ contracts/staking/generated-wrappers/ contracts/coordinator/generated-wrappers/ contracts/exchange/generated-wrappers/ diff --git a/.prettierignore b/.prettierignore index e074386c49..ff3bf6e8c7 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,7 +1,7 @@ lib .nyc_output -/contracts/integration-tests/generated-wrappers -/contracts/integration-tests/generated-artifacts +/contracts/integrations/generated-wrappers +/contracts/integrations/generated-artifacts /contracts/staking/generated-wrappers /contracts/staking/generated-artifacts /contracts/coordinator/generated-wrappers diff --git a/contracts/integration-tests/contracts/Empty.sol b/contracts/integration-tests/contracts/Empty.sol deleted file mode 100644 index ccae8c5f09..0000000000 --- a/contracts/integration-tests/contracts/Empty.sol +++ /dev/null @@ -1,7 +0,0 @@ -pragma solidity ^0.5.0; - - -// TODO(jalextowle): This contract must be included to ensure that `abi-gen` -// doesn't fail to run. Remove this contract or remove the contracts directory -// depending on whether or not this package should contain packages. -contract Empty { } // solhint-disable-line no-empty-blocks diff --git a/contracts/integration-tests/contracts/test/StakingWithTokens.sol b/contracts/integration-tests/contracts/test/StakingWithTokens.sol deleted file mode 100644 index c8fbb69343..0000000000 --- a/contracts/integration-tests/contracts/test/StakingWithTokens.sol +++ /dev/null @@ -1,53 +0,0 @@ -pragma solidity ^0.5.9; -pragma experimental ABIEncoderV2; - -import "@0x/contracts-staking/contracts/src/Staking.sol"; - - -contract StakingWithTokens is - Staking -{ - address public wethAddress; - address public zrxVault; - - bytes4 internal constant WETH_PROXY_ID = 0xf47261b0; - - function setWethAddress(address weth) - public - { - wethAddress = weth; - } - - function setZrxVault(address vault) - public - { - zrxVault = vault; - } - - function getWethAssetData() - public - view - returns (bytes memory) - { - return abi.encodeWithSelector( - WETH_PROXY_ID, - wethAddress - ); - } - - function getWethContract() - public - view - returns (IEtherToken) - { - return IEtherToken(wethAddress); - } - - function getZrxVault() - public - view - returns (IZrxVault) - { - return IZrxVault(zrxVault); - } -} diff --git a/contracts/integration-tests/CHANGELOG.json b/contracts/integrations/CHANGELOG.json similarity index 100% rename from contracts/integration-tests/CHANGELOG.json rename to contracts/integrations/CHANGELOG.json diff --git a/contracts/integration-tests/README.md b/contracts/integrations/README.md similarity index 90% rename from contracts/integration-tests/README.md rename to contracts/integrations/README.md index ab729e9c1c..5a1d2be163 100644 --- a/contracts/integration-tests/README.md +++ b/contracts/integrations/README.md @@ -7,7 +7,7 @@ This package implements integration tests against 0x's smart contracts and will **Install** ```bash -npm install @0x/contracts-staking --save +npm install @0x/contracts-integrations --save ``` ## Contributing @@ -37,13 +37,13 @@ yarn install To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory: ```bash -PKG=@0x/contracts-integration-tests yarn build +PKG=@0x/contracts-integrations yarn build ``` Or continuously rebuild on change: ```bash -PKG=@0x/contracts-integration-tests yarn watch +PKG=@0x/contracts-integrations yarn watch ``` ### Clean diff --git a/contracts/integration-tests/compiler.json b/contracts/integrations/compiler.json similarity index 100% rename from contracts/integration-tests/compiler.json rename to contracts/integrations/compiler.json diff --git a/contracts/integrations/contracts/test/TestStakingPlaceholder.sol b/contracts/integrations/contracts/test/TestStakingPlaceholder.sol new file mode 100644 index 0000000000..7d53089303 --- /dev/null +++ b/contracts/integrations/contracts/test/TestStakingPlaceholder.sol @@ -0,0 +1,15 @@ +pragma solidity ^0.5.9; +pragma experimental ABIEncoderV2; + +import "@0x/contracts-staking/contracts/test/TestStaking.sol"; + + +// TODO(jalextowle): This contract can be removed when the added to this package. +contract TestStakingPlaceholder is + TestStaking +{ + constructor(address wethAddress, address zrxVaultAddress) + public + TestStaking(wethAddress, zrxVaultAddress) + {} // solhint-disable-line no-empty-blocks +} diff --git a/contracts/integration-tests/package.json b/contracts/integrations/package.json similarity index 96% rename from contracts/integration-tests/package.json rename to contracts/integrations/package.json index 170a724107..ec3050c0e7 100644 --- a/contracts/integration-tests/package.json +++ b/contracts/integrations/package.json @@ -1,10 +1,10 @@ { - "name": "@0x/contracts-integration-tests", + "name": "@0x/contracts-integrations", "version": "1.0.0", "engines": { "node": ">=6.12" }, - "description": "Integration tests for the 0x protocol", + "description": "Integrations with the 0x protocol", "main": "lib/src/index.js", "directories": { "test": "test" @@ -35,7 +35,7 @@ "compile:truffle": "truffle compile" }, "config": { - "abis": "./generated-artifacts/@(StakingWithTokens).json", + "abis": "./generated-artifacts/@(TestStakingPlaceholder).json", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually." }, "repository": { diff --git a/contracts/integration-tests/src/artifacts.ts b/contracts/integrations/src/artifacts.ts similarity index 61% rename from contracts/integration-tests/src/artifacts.ts rename to contracts/integrations/src/artifacts.ts index bc8f8d3013..2c10ff1fe1 100644 --- a/contracts/integration-tests/src/artifacts.ts +++ b/contracts/integrations/src/artifacts.ts @@ -5,5 +5,5 @@ */ import { ContractArtifact } from 'ethereum-types'; -import * as StakingWithTokens from '../generated-artifacts/StakingWithTokens.json'; -export const artifacts = { StakingWithTokens: StakingWithTokens as ContractArtifact }; +import * as TestStakingPlaceholder from '../generated-artifacts/TestStakingPlaceholder.json'; +export const artifacts = { TestStakingPlaceholder: TestStakingPlaceholder as ContractArtifact }; diff --git a/contracts/integration-tests/src/deployment_mananger.ts b/contracts/integrations/src/deployment_mananger.ts similarity index 96% rename from contracts/integration-tests/src/deployment_mananger.ts rename to contracts/integrations/src/deployment_mananger.ts index 2fb9dd5220..f763c3f609 100644 --- a/contracts/integration-tests/src/deployment_mananger.ts +++ b/contracts/integrations/src/deployment_mananger.ts @@ -30,7 +30,7 @@ import { BigNumber } from '@0x/utils'; import { TxData } from 'ethereum-types'; import * as _ from 'lodash'; -import { artifacts, StakingWithTokensContract } from './'; +import { artifacts, TestStakingPlaceholderContract } from './'; /** * Adds a batch of authorities to a list of authorizable contracts. @@ -96,9 +96,9 @@ interface AssetProxyContracts { // Contract wrappers for all of the staking contracts interface StakingContracts { readOnlyProxy: ReadOnlyProxyContract; - stakingLogic: StakingWithTokensContract; + stakingLogic: TestStakingPlaceholderContract; stakingProxy: StakingProxyContract; - stakingWrapper: StakingWithTokensContract; + stakingWrapper: TestStakingPlaceholderContract; zrxVault: ZrxVaultContract; } @@ -349,11 +349,13 @@ export class DeploymentManager { txDefaults, stakingArtifacts, ); - const stakingLogic = await StakingWithTokensContract.deployFrom0xArtifactAsync( - artifacts.StakingWithTokens, + const stakingLogic = await TestStakingPlaceholderContract.deployFrom0xArtifactAsync( + artifacts.TestStakingPlaceholder, environment.provider, txDefaults, stakingArtifacts, + tokens.weth.address, + tokens.zrx.address, ); const stakingProxy = await StakingProxyContract.deployFrom0xArtifactAsync( stakingArtifacts.StakingProxy, @@ -363,7 +365,11 @@ export class DeploymentManager { stakingLogic.address, readOnlyProxy.address, ); - const stakingWrapper = new StakingWithTokensContract(stakingProxy.address, environment.provider); + const stakingWrapper = new TestStakingPlaceholderContract(stakingProxy.address, environment.provider); + + // Add the zrx vault and the weth contract to the staking proxy. + await stakingWrapper.setWethContract.awaitTransactionSuccessAsync(tokens.weth.address, { from: owner }); + await stakingWrapper.setZrxVault.awaitTransactionSuccessAsync(zrxVault.address, { from: owner }); // Authorize the owner address in the staking proxy and the zrx vault. await stakingProxy.addAuthorizedAddress.awaitTransactionSuccessAsync(owner, { from: owner }); @@ -372,8 +378,6 @@ export class DeploymentManager { // Configure the zrx vault and the staking contract. await zrxVault.setStakingProxy.awaitTransactionSuccessAsync(stakingProxy.address, { from: owner }); await zrxVault.setStakingProxy.awaitTransactionSuccessAsync(stakingProxy.address, { from: owner }); - await stakingWrapper.setZrxVault.awaitTransactionSuccessAsync(zrxVault.address, { from: owner }); - await stakingWrapper.setWethAddress.awaitTransactionSuccessAsync(tokens.weth.address, { from: owner }); return { readOnlyProxy, diff --git a/contracts/integration-tests/src/index.ts b/contracts/integrations/src/index.ts similarity index 100% rename from contracts/integration-tests/src/index.ts rename to contracts/integrations/src/index.ts diff --git a/contracts/integration-tests/src/wrappers.ts b/contracts/integrations/src/wrappers.ts similarity index 79% rename from contracts/integration-tests/src/wrappers.ts rename to contracts/integrations/src/wrappers.ts index 289a4cf2d1..4568c84786 100644 --- a/contracts/integration-tests/src/wrappers.ts +++ b/contracts/integrations/src/wrappers.ts @@ -3,4 +3,4 @@ * Warning: This file is auto-generated by contracts-gen. Don't edit manually. * ----------------------------------------------------------------------------- */ -export * from '../generated-wrappers/staking_with_tokens'; +export * from '../generated-wrappers/test_staking_placeholder'; diff --git a/contracts/integration-tests/test/deployment_manager_test.ts b/contracts/integrations/test/deployment_manager_test.ts similarity index 92% rename from contracts/integration-tests/test/deployment_manager_test.ts rename to contracts/integrations/test/deployment_manager_test.ts index 70b3538987..d3cc022c84 100644 --- a/contracts/integration-tests/test/deployment_manager_test.ts +++ b/contracts/integrations/test/deployment_manager_test.ts @@ -1,4 +1,5 @@ import { Authorizable, Ownable } from '@0x/contracts-exchange'; +import { constants as stakingConstants } from '@0x/contracts-staking'; import { blockchainTests, constants, expect } from '@0x/contracts-test-utils'; import { BigNumber } from '@0x/utils'; @@ -150,12 +151,12 @@ blockchainTests('Deployment Manager', env => { }); it('should have registered the weth contract in the staking contract', async () => { - const weth = await deploymentManager.staking.stakingWrapper.wethAddress.callAsync(); + const weth = await deploymentManager.staking.stakingWrapper.testWethAddress.callAsync(); expect(weth).to.be.eq(deploymentManager.tokens.weth.address); }); it('should have registered the zrx vault in the staking contract', async () => { - const zrxVault = await deploymentManager.staking.stakingWrapper.zrxVault.callAsync(); + const zrxVault = await deploymentManager.staking.stakingWrapper.testZrxVaultAddress.callAsync(); expect(zrxVault).to.be.eq(deploymentManager.staking.zrxVault.address); }); @@ -166,11 +167,14 @@ blockchainTests('Deployment Manager', env => { it('should have correctly set the params', async () => { const params = await deploymentManager.staking.stakingWrapper.getParams.callAsync(); - expect(params).to.be.deep.eq( - [10 * 60 * 60 * 24, (90 * constants.PPM_DENOMINATOR) / 100, 100 * 1e18, 10, 1, 2].map( - value => new BigNumber(value), - ), - ); + expect(params).to.be.deep.eq([ + stakingConstants.DEFAULT_PARAMS.epochDurationInSeconds, + stakingConstants.DEFAULT_PARAMS.rewardDelegatedStakeWeight, + stakingConstants.DEFAULT_PARAMS.minimumPoolStake, + stakingConstants.DEFAULT_PARAMS.maximumMakersInPool, + stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaNumerator, + stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaDenominator, + ]); }); }); }); diff --git a/contracts/integration-tests/test/deployment_test.ts b/contracts/integrations/test/deployment_test.ts similarity index 97% rename from contracts/integration-tests/test/deployment_test.ts rename to contracts/integrations/test/deployment_test.ts index b45b3f5477..895a09e6f9 100644 --- a/contracts/integration-tests/test/deployment_test.ts +++ b/contracts/integrations/test/deployment_test.ts @@ -20,6 +20,7 @@ import { import { artifacts as multisigArtifacts, AssetProxyOwnerContract } from '@0x/contracts-multisig'; import { artifacts as stakingArtifacts, + constants as stakingConstants, ReadOnlyProxyContract, StakingContract, StakingEvents, @@ -287,16 +288,14 @@ blockchainTests('Deployment and Configuration End to End Tests', env => { it('should have initialized the correct parameters in the staking proxy', async () => { // Ensure that the correct parameters were set. const params = await stakingWrapper.getParams.callAsync(); - expect(params).to.be.deep.eq( - [ - 864000, // epochDurationInSeconds - 900000, // rewardDelegatedStakeWeight - 100000000000000000000, // minimumPoolStake - 10, // maximumMakerInPool - 1, // cobbDouglasAlphaNumerator - 2, // cobbDouglasAlphaDenominator - ].map(value => new BigNumber(value)), - ); + expect(params).to.be.deep.eq([ + stakingConstants.DEFAULT_PARAMS.epochDurationInSeconds, + stakingConstants.DEFAULT_PARAMS.rewardDelegatedStakeWeight, + stakingConstants.DEFAULT_PARAMS.minimumPoolStake, + stakingConstants.DEFAULT_PARAMS.maximumMakersInPool, + stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaNumerator, + stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaDenominator, + ]); }); }); diff --git a/contracts/integration-tests/tsconfig.json b/contracts/integrations/tsconfig.json similarity index 75% rename from contracts/integration-tests/tsconfig.json rename to contracts/integrations/tsconfig.json index b7fbedee7f..541c4adba9 100644 --- a/contracts/integration-tests/tsconfig.json +++ b/contracts/integrations/tsconfig.json @@ -2,5 +2,5 @@ "extends": "../../tsconfig", "compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true }, "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"], - "files": ["generated-artifacts/StakingWithTokens.json"] + "files": ["generated-artifacts/TestStakingPlaceholder.json"] } diff --git a/contracts/staking/contracts/test/TestStaking.sol b/contracts/staking/contracts/test/TestStaking.sol index 1d57d1e8f0..2284388340 100644 --- a/contracts/staking/contracts/test/TestStaking.sol +++ b/contracts/staking/contracts/test/TestStaking.sol @@ -40,6 +40,22 @@ contract TestStaking is testZrxVaultAddress = zrxVaultAddress; } + /// @dev Sets the weth contract address. + /// @param wethAddress The address of the weth contract. + function setWethContract(address wethAddress) + external + { + testWethAddress = wethAddress; + } + + /// @dev Sets the zrx vault address. + /// @param zrxVaultAddress The address of a zrx vault. + function setZrxVault(address zrxVaultAddress) + external + { + testZrxVaultAddress = zrxVaultAddress; + } + /// @dev Overridden to use testWethAddress; function getWethContract() public diff --git a/contracts/staking/src/index.ts b/contracts/staking/src/index.ts index 91dd7e0e3e..4cb7af88e1 100644 --- a/contracts/staking/src/index.ts +++ b/contracts/staking/src/index.ts @@ -1,2 +1,3 @@ export * from './wrappers'; export * from './artifacts'; +export { constants } from '../test/utils/constants'; From b4ae42cc9a84658fb6ddc8f129b9509a82eb3f80 Mon Sep 17 00:00:00 2001 From: Alex Towle Date: Fri, 4 Oct 2019 16:32:39 -0700 Subject: [PATCH 06/87] `@0x/contracts-integrations` Added the integrations package to the top-level configuration --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cba7f7b99a..4f77217ad6 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "lint:contracts": "wsrun lint -p ${npm_package_config_contractsPackages} -c --fast-exit --stages --exclude-missing" }, "config": { - "contractsPackages": "@0x/contracts-asset-proxy @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-exchange-libs @0x/contracts-multisig @0x/contracts-test-utils @0x/contracts-utils @0x/contracts-dev-utils @0x/contracts-staking", + "contractsPackages": "@0x/contracts-asset-proxy @0x/contracts-dev-utils @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-exchange-libs @0x/contracts-integrations @0x/contracts-multisig @0x/contracts-staking @0x/contracts-test-utils @0x/contracts-utils", "mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic", "packagesWithDocPages": "contract-wrappers 0x.js connect json-schemas subproviders web3-wrapper order-utils sol-compiler sol-coverage sol-profiler sol-trace ethereum-types asset-buyer asset-swapper migrations", "ignoreDependencyVersions": "@types/styled-components @types/node", From c0c27ed637d43c79dbdb6bac00df80bc9b4e9a10 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Fri, 4 Oct 2019 18:04:44 -0700 Subject: [PATCH 07/87] Enforce that assetData is padded to 32 bytes, excluding the id, before dispatching transfer --- .../exchange/contracts/src/MixinAssetProxyDispatcher.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contracts/exchange/contracts/src/MixinAssetProxyDispatcher.sol b/contracts/exchange/contracts/src/MixinAssetProxyDispatcher.sol index e0cc5aa15e..84c9fe5ff5 100644 --- a/contracts/exchange/contracts/src/MixinAssetProxyDispatcher.sol +++ b/contracts/exchange/contracts/src/MixinAssetProxyDispatcher.sol @@ -88,8 +88,9 @@ contract MixinAssetProxyDispatcher is { // Do nothing if no amount should be transferred. if (amount > 0) { - // Ensure assetData length is valid - if (assetData.length <= 3) { + + // Ensure assetData is padded to 32 bytes (excluding the id) and is at least 4 bytes long + if (assetData.length % 32 != 4) { LibRichErrors.rrevert(LibExchangeRichErrors.AssetProxyDispatchError( LibExchangeRichErrors.AssetProxyDispatchErrorCodes.INVALID_ASSET_DATA_LENGTH, orderHash, From 87906a3af1f92876bec4ae876e460dea42b28c47 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Fri, 4 Oct 2019 18:05:20 -0700 Subject: [PATCH 08/87] Add test for improperly padded assetData --- contracts/exchange/test/dispatcher.ts | 39 +++++++++++++-------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/contracts/exchange/test/dispatcher.ts b/contracts/exchange/test/dispatcher.ts index e087f008f8..e82a738efa 100644 --- a/contracts/exchange/test/dispatcher.ts +++ b/contracts/exchange/test/dispatcher.ts @@ -238,37 +238,35 @@ describe('AssetProxyDispatcher', () => { expect(newBalances).to.deep.equal(erc20Balances); }); - it('should perform a noop transfer if from == to', async () => { - // Register ERC20 proxy - await assetProxyDispatcher.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, { - from: owner, - }); + it('should revert if dispatching to unregistered proxy', async () => { // Construct metadata for ERC20 proxy const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); - // Perform a transfer from makerAddress to takerAddress - const erc20Balances = await erc20Wrapper.getBalancesAsync(); const amount = new BigNumber(10); - const txReceipt = await assetProxyDispatcher.dispatchTransferFrom.awaitTransactionSuccessAsync( + const expectedError = new ExchangeRevertErrors.AssetProxyDispatchError( + ExchangeRevertErrors.AssetProxyDispatchErrorCode.UnknownAssetProxy, + orderHash, + encodedAssetData, + ); + const tx = assetProxyDispatcher.dispatchTransferFrom.sendTransactionAsync( orderHash, encodedAssetData, makerAddress, - makerAddress, + takerAddress, amount, { from: owner }, ); - expect(txReceipt.logs.length).to.be.equal(1); - const newBalances = await erc20Wrapper.getBalancesAsync(); - expect(newBalances).to.deep.equal(erc20Balances); + return expect(tx).to.revertWith(expectedError); }); - it('should revert if dispatching to unregistered proxy', async () => { - // Construct metadata for ERC20 proxy - const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); - // Perform a transfer from makerAddress to takerAddress - const amount = new BigNumber(10); + it('should revert with the correct error when assetData length < 4 bytes', async () => { + await assetProxyDispatcher.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, { + from: owner, + }); + const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address).slice(0, 8); + const amount = new BigNumber(1); const expectedError = new ExchangeRevertErrors.AssetProxyDispatchError( - ExchangeRevertErrors.AssetProxyDispatchErrorCode.UnknownAssetProxy, + ExchangeRevertErrors.AssetProxyDispatchErrorCode.InvalidAssetDataLength, orderHash, encodedAssetData, ); @@ -283,11 +281,12 @@ describe('AssetProxyDispatcher', () => { return expect(tx).to.revertWith(expectedError); }); - it('should revert with the correct error when assetData length < 4 bytes', async () => { + it('should revert if assetData is not padded to 32 bytes (excluding the id)', async () => { await assetProxyDispatcher.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, { from: owner, }); - const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address).slice(0, 8); + // Shave off the last byte + const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address).slice(0, 72); const amount = new BigNumber(1); const expectedError = new ExchangeRevertErrors.AssetProxyDispatchError( ExchangeRevertErrors.AssetProxyDispatchErrorCode.InvalidAssetDataLength, From 17362bcf4453350ffef15335261246c14765d2dd Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Sun, 29 Sep 2019 18:31:00 -0400 Subject: [PATCH 09/87] `@0x/contracts-asset-proxy`: Create `UniswapBridge`. --- .../contracts/src/bridges/UniswapBridge.sol | 193 ++++++++++++++++++ .../contracts/src/interfaces/IUniswap.sol | 83 ++++++++ contracts/asset-proxy/test/uniswap_bridge.ts | 180 ++++++++++++++++ 3 files changed, 456 insertions(+) create mode 100644 contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol create mode 100644 contracts/asset-proxy/contracts/src/interfaces/IUniswap.sol create mode 100644 contracts/asset-proxy/test/uniswap_bridge.ts diff --git a/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol new file mode 100644 index 0000000000..af1bfdb34a --- /dev/null +++ b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol @@ -0,0 +1,193 @@ +/* + + Copyright 2019 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.5.9; +pragma experimental ABIEncoderV2; + +import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; +import "@0x/contracts-exchange/contracts/src/interfaces/IWallet.sol"; +import "../interfaces/IUniswap.sol"; +import "./ERC20Bridge.sol"; + + +// solhint-disable space-after-comma +contract UniswaBridge is + ERC20Bridge, + IWallet +{ + bytes4 private constant LEGACY_WALLET_MAGIC_VALUE = 0xb0671381; + /* Mainnet addresses */ + address constant public UNISWAP_EXCHANGE_FACTORY_ADDRESS = address(0); + address constant public WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + + /// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of + /// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress` + /// token encoded in the bridge data. + /// @param toTokenAddress The token to buy and transfer to `to`. + /// @param to The recipient of the bought tokens. + /// @param amount Minimum amount of `toTokenAddress` tokens to buy. + /// @param bridgeData The abi-encoded "from" token address. + /// @return success The magic bytes if successful. + function withdrawTo( + address toTokenAddress, + address /* from */, + address to, + uint256 amount, + bytes calldata bridgeData, + ) + external + returns (bytes4 success) + { + // Decode the bridge data to get the `fromTokenAddress`. + (address fromTokenAddress) = abi.decode(bridgeData, (address)); + + // Just transfer the tokens if they're the same. + if (fromTokenAddress == toTokenAddress) { + IERC20Token(fromToken).transfer(to, amount); + return BRIDGE_SUCCESS; + } + + uint256 fromTokenBalance = IERC20Token(fromToken).balanceOf(address(this)); + uint256 toTokenBalance = IERC20Token(toToken).balanceOf(address(this)); + + // Get the exchange for the token pair. + IUniswapExchange exchange = _getUniswapExchangeForTokenPair( + fromTokenAddress, + toTokenAddress + ); + + // Convert from WETH to a token. + if (fromTokenAddress == address(weth)) { + // Unwrap the WETH. + IEtherToken weth = _getWethContract(); + weth.withdraw(weth.balanceOf(this)); + // Buy as much of `toTokenAddress` token with ETH as possible and + // transfer it to `to`. + exchange.ethToTokenTransferInput.value(fromTokenBalance)( + // No minimum buy amount. + 0, + // Expires after this block. + block.timestamp, + // Recipient is `to`. + to + ); + + // Convert from a token to WETH. + } else if (toTokenAddress == address(weth)) { + // Buy as much ETH with `toTokenAddress` token as possible. + uint256 ethBought = exchange.tokenToEthSwapInput( + // Sell all tokens we hold. + fromTokenBalance, + // Expires after this block. + block.timestamp, + // Recipient is `to`. + to + ); + // Wrap the ETH. + IEtherToken weth = _getWethContract(); + weth.deposit.value(ethBought)(); + // Transfer the WETH to `to`. + weth.transfer(to, ethBought); + + // Convert from one token to another. + } else { + // Buy as much `toTokenAddress` token with `fromTokenAddress` token + // and transfer it to `to`. + exchange.tokenToTokenTransferInput( + // Sell all tokens we hold. + fromTokenBalance, + // No minimum buy amount. + 0, + // No minimum intermediate ETH buy amount. + 0, + // Expires after this block. + block.timestamp, + // Recipient is `to`. + to, + // Convert to `toTokenAddress`. + toTokenAddress + ); + } + return BRIDGE_SUCCESS; + } + + /// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker + /// and sign for itself in orders. Always succeeds. + /// @return magicValue Success bytes, always. + function isValidSignature( + bytes32, + bytes calldata + ) + external + view + returns (bytes4 magicValue) + { + return LEGACY_WALLET_MAGIC_VALUE; + } + + /// @dev Overridable way to get the weth contract. + /// @return token The WETH contract. + function _getWethContract() + internal + view + returns (IERC20Token token) + { + return IERC20Token(WETH_ADDRESS); + } + + /// @dev Overridable way to get the uniswap exchange factory contract. + /// @return factory The exchange factory contract. + function _getUniswapExchangeFactoryContract() + internal + view + returns (IUniswapExchangeFactory factory) + { + return IUniswapExchangeFactory(ETH2DAI_ADDRESS); + } + + /// @dev Retrieves the uniswap exchange contract for a given token pair. + /// @return exchange The exchange contract for the token pair. + function _getUniswapExchangeForTokenPair( + address fromTokenAddress, + address toTokenAddress + ) + private + view + returns (IUniswapExchange exchange) + { + // Whichever isn't WETH is the exchange token. + address wethAddress = address(_getWethContract()); + if (fromTokenAddress != wethAddress) { + return _getUniswapExchangeForToken(fromTokenAddress); + } + return _getUniswapExchangeForToken(toTokenAddress); + } + + /// @dev Retrieves the uniswap exchange contract for a given token. + /// @return exchange The exchange contract for the token. + function _getUniswapExchangeForToken(address tokenAddress) + private + view + returns (IUniswapExchange exchange) + { + address exchangeAddress = _getUniswapExchangeFactoryContract() + .getExchange(tokenAddress); + require(exchangeAddress != address(0), "NO_UNISWAP_EXCHANGE_FOR_TOKEN"); + return IUniswapExchange(exchangeAddress); + } +} diff --git a/contracts/asset-proxy/contracts/src/interfaces/IUniswap.sol b/contracts/asset-proxy/contracts/src/interfaces/IUniswap.sol new file mode 100644 index 0000000000..c4035f93f6 --- /dev/null +++ b/contracts/asset-proxy/contracts/src/interfaces/IUniswap.sol @@ -0,0 +1,83 @@ +/* + + Copyright 2019 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.5.9; + + +// solhint-disable func-param-name-mixedcase +interface IUniswapExchange { + + /// @dev Buys at least `minTokensBought` tokens with ETH and transfer them + /// to `recipient`. + /// @param minTokensBought The minimum number of tokens to buy. + /// @param deadline Time when this order expires. + /// @param recipient Who to transfer the tokens to. + /// @return tokensBought Amount of tokens bought. + function ethToTokenTransferInput( + uint256 minTokensBought, + uint64 deadline, + address recipient + ) + external + payable + returns (uint256 tokensBought); + + /// @dev Buys at least `minEthBought` ETH with tokens. + /// @param tokensSold Amount of tokens to sell. + /// @param minEthBought The minimum amount of ETH to buy. + /// @param deadline Time when this order expires. + /// @return ethBought Amount of tokens bought. + function tokenToEthSwapInput( + uint256 tokensSold, + uint256 minEthBought, + uint64 deadline + ) + external + payable + returns (uint256 ethBought); + + /// @dev Buys at least `minTokensBought` tokens with the exchange token + /// and transfer them to `recipient`. + /// @param minTokensBought The minimum number of tokens to buy. + /// @param minEthBought The minimum amount of intermediate ETH to buy. + /// @param deadline Time when this order expires. + /// @param recipient Who to transfer the tokens to. + /// @param toTokenAddress The token being bought. + /// @return tokensBought Amount of tokens bought. + function tokenToTokenTransferInput( + uint256 tokensSold, + uint256 minTokensBought, + uint256 minEthBought, + uint64 deadline, + address recipient, + address toTokenAddress + ) + external + returns (uint256 tokensBought); +} + + +interface IUniswapExchangeFactory { + + /// @dev Get the exchange for a token. + /// @param tokenAddress The address of the token contract. + function getExchange(address tokenAddress) + external + view + returns (IUniswapExchange); +} diff --git a/contracts/asset-proxy/test/uniswap_bridge.ts b/contracts/asset-proxy/test/uniswap_bridge.ts new file mode 100644 index 0000000000..2d236cd1c0 --- /dev/null +++ b/contracts/asset-proxy/test/uniswap_bridge.ts @@ -0,0 +1,180 @@ +import { + blockchainTests, + constants, + expect, + filterLogsToArguments, + getRandomInteger, + hexRandom, + Numberish, + randomAddress, + TransactionHelper, +} from '@0x/contracts-test-utils'; +import { BigNumber } from '@0x/utils'; +import { DecodedLogs } from 'ethereum-types'; +import * as _ from 'lodash'; + +import { + artifacts, + TestUniswapBridgeContract, + TestUniswapBridgeEvents, + TestUniswapBridgeSellAllAmountEventArgs, + TestUniswapBridgeTokenTransferEventArgs, +} from '../src'; + +blockchainTests.resets('UniswapBridge unit tests', env => { + const txHelper = new TransactionHelper(env.web3Wrapper, artifacts); + let testContract: TestUniswapBridgeContract; + let daiTokenAddress: string; + let wethTokenAddress: string; + + before(async () => { + testContract = await TestUniswapBridgeContract.deployFrom0xArtifactAsync( + artifacts.TestUniswapBridge, + env.provider, + env.txDefaults, + artifacts, + ); + [daiTokenAddress, wethTokenAddress] = await Promise.all([ + testContract.daiToken.callAsync(), + testContract.wethToken.callAsync(), + ]); + }); + + describe('deployment', () => { + it('sets Uniswap allowances to maximum', async () => { + const [wethAllowance, daiAllowance] = await testContract.getUniswapTokenAllowances.callAsync(); + expect(wethAllowance).to.bignumber.eq(constants.MAX_UINT256); + expect(daiAllowance).to.bignumber.eq(constants.MAX_UINT256); + }); + }); + + describe('isValidSignature()', () => { + it('returns success bytes', async () => { + const LEGACY_WALLET_MAGIC_VALUE = '0xb0671381'; + const result = await testContract.isValidSignature.callAsync(hexRandom(), hexRandom(_.random(0, 32))); + expect(result).to.eq(LEGACY_WALLET_MAGIC_VALUE); + }); + }); + + describe('transfer()', () => { + interface TransferOpts { + toTokenAddress: string; + toAddress: string; + amount: Numberish; + fromTokenBalance: Numberish; + revertReason: string; + fillAmount: Numberish; + } + + function createTransferOpts(opts?: Partial): TransferOpts { + return { + toTokenAddress: _.sampleSize([wethTokenAddress, daiTokenAddress], 1)[0], + toAddress: randomAddress(), + amount: getRandomInteger(1, 100e18), + revertReason: '', + fillAmount: getRandomInteger(1, 100e18), + fromTokenBalance: getRandomInteger(1, 100e18), + ...opts, + }; + } + + async function transferAsync(opts?: Partial): Promise<[string, DecodedLogs]> { + const _opts = createTransferOpts(opts); + // Set the fill behavior. + await testContract.setFillBehavior.awaitTransactionSuccessAsync( + _opts.revertReason, + new BigNumber(_opts.fillAmount), + ); + // Set the token balance for the token we're converting from. + await testContract.setTokenBalances.awaitTransactionSuccessAsync( + _opts.toTokenAddress === daiTokenAddress + ? new BigNumber(_opts.fromTokenBalance) + : constants.ZERO_AMOUNT, + _opts.toTokenAddress === wethTokenAddress + ? new BigNumber(_opts.fromTokenBalance) + : constants.ZERO_AMOUNT, + ); + // Call transfer(). + const [result, { logs }] = await txHelper.getResultAndReceiptAsync( + testContract.transfer, + '0x', + _opts.toTokenAddress, + randomAddress(), + _opts.toAddress, + new BigNumber(_opts.amount), + ); + return [result, (logs as any) as DecodedLogs]; + } + + function getOppositeToken(tokenAddress: string): string { + if (tokenAddress === daiTokenAddress) { + return wethTokenAddress; + } + return daiTokenAddress; + } + + it('returns magic bytes on success', async () => { + const BRIDGE_SUCCESS_RETURN_DATA = '0xb5d40d78'; + const [result] = await transferAsync(); + expect(result).to.eq(BRIDGE_SUCCESS_RETURN_DATA); + }); + + it('calls `Uniswap.sellAllAmount()`', async () => { + const opts = createTransferOpts(); + const [, logs] = await transferAsync(opts); + const transfers = filterLogsToArguments( + logs, + TestUniswapBridgeEvents.SellAllAmount, + ); + expect(transfers.length).to.eq(1); + expect(transfers[0].sellToken).to.eq(getOppositeToken(opts.toTokenAddress)); + expect(transfers[0].buyToken).to.eq(opts.toTokenAddress); + expect(transfers[0].sellTokenAmount).to.bignumber.eq(opts.fromTokenBalance); + expect(transfers[0].minimumFillAmount).to.bignumber.eq(opts.amount); + }); + + it('can swap DAI for WETH', async () => { + const opts = createTransferOpts({ toTokenAddress: wethTokenAddress }); + const [, logs] = await transferAsync(opts); + const transfers = filterLogsToArguments( + logs, + TestUniswapBridgeEvents.SellAllAmount, + ); + expect(transfers.length).to.eq(1); + expect(transfers[0].sellToken).to.eq(daiTokenAddress); + expect(transfers[0].buyToken).to.eq(wethTokenAddress); + }); + + it('can swap WETH for DAI', async () => { + const opts = createTransferOpts({ toTokenAddress: daiTokenAddress }); + const [, logs] = await transferAsync(opts); + const transfers = filterLogsToArguments( + logs, + TestUniswapBridgeEvents.SellAllAmount, + ); + expect(transfers.length).to.eq(1); + expect(transfers[0].sellToken).to.eq(wethTokenAddress); + expect(transfers[0].buyToken).to.eq(daiTokenAddress); + }); + + it('transfers filled amount to `to`', async () => { + const opts = createTransferOpts(); + const [, logs] = await transferAsync(opts); + const transfers = filterLogsToArguments( + logs, + TestUniswapBridgeEvents.TokenTransfer, + ); + expect(transfers.length).to.eq(1); + expect(transfers[0].token).to.eq(opts.toTokenAddress); + expect(transfers[0].from).to.eq(testContract.address); + expect(transfers[0].to).to.eq(opts.toAddress); + expect(transfers[0].amount).to.bignumber.eq(opts.fillAmount); + }); + + it('fails if `Uniswap.sellAllAmount()` reverts', async () => { + const opts = createTransferOpts({ revertReason: 'FOOBAR' }); + const tx = transferAsync(opts); + return expect(tx).to.revertWith(opts.revertReason); + }); + }); +}); From 6a2911d10f1649d352212292bcd50ae03d2b92b8 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Sun, 29 Sep 2019 18:50:49 -0400 Subject: [PATCH 10/87] `@0x/contracts-asset-proxy`: Start work on `UniswapBridge` tests. --- .../contracts/src/bridges/UniswapBridge.sol | 13 +- .../contracts/test/TestUniswapBridge.sol | 204 ++++++++++++++++++ 2 files changed, 209 insertions(+), 8 deletions(-) create mode 100644 contracts/asset-proxy/contracts/test/TestUniswapBridge.sol diff --git a/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol index af1bfdb34a..db55aa58e3 100644 --- a/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol +++ b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol @@ -62,20 +62,18 @@ contract UniswaBridge is return BRIDGE_SUCCESS; } - uint256 fromTokenBalance = IERC20Token(fromToken).balanceOf(address(this)); - uint256 toTokenBalance = IERC20Token(toToken).balanceOf(address(this)); - // Get the exchange for the token pair. IUniswapExchange exchange = _getUniswapExchangeForTokenPair( fromTokenAddress, toTokenAddress ); + // Get our balance of `fromTokenAddress` token. + uint256 fromTokenBalance = IERC20Token(fromToken).balanceOf(address(this)); // Convert from WETH to a token. if (fromTokenAddress == address(weth)) { // Unwrap the WETH. - IEtherToken weth = _getWethContract(); - weth.withdraw(weth.balanceOf(this)); + _getWethContract().withdraw(fromTokenBalance); // Buy as much of `toTokenAddress` token with ETH as possible and // transfer it to `to`. exchange.ethToTokenTransferInput.value(fromTokenBalance)( @@ -99,10 +97,9 @@ contract UniswaBridge is to ); // Wrap the ETH. - IEtherToken weth = _getWethContract(); - weth.deposit.value(ethBought)(); + _getWethContract().deposit.value(ethBought)(); // Transfer the WETH to `to`. - weth.transfer(to, ethBought); + IERC20Token(toTokenAddress).transfer(to, ethBought); // Convert from one token to another. } else { diff --git a/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol b/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol new file mode 100644 index 0000000000..d254c000e4 --- /dev/null +++ b/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol @@ -0,0 +1,204 @@ +/* + + Copyright 2019 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.5.9; +pragma experimental ABIEncoderV2; + +import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; +import "../src/bridges/Eth2DaiBridge.sol"; +import "../src/interfaces/IEth2Dai.sol"; + + +// solhint-disable no-simple-event-func-name +/// @dev Interface that allows `TestToken` to call `raiseTransferEvent` on +/// the `TestEth2DaiBridge` contract. +interface ITestTokenCaller { + + function raiseTransferEvent( + address from, + address to, + uint256 amount + ) + external; + + function raiseTransferEvent( + address from, + address to, + uint256 amount + ) + external; +} + + +/// @dev A minimalist ERC20/WETH token. +contract TestToken { + + mapping (address => uint256) public balances; + + /// @dev Just calls `raiseTransferEvent()` on the caller. + function transfer(address to, uint256 amount) + external + returns (bool) + { + IRaiseTransferEvent(msg.sender).raiseTransferEvent(msg.sender, to, amount); + return true; + } + + /// @dev Set the balance for `owner`. + function setBalance(address owner, uint256 balance) + external + { + balances[owner] = balance; + } + + /// @dev Just calls `raiseApproveEvent()` on the caller. + function approve(address spender, uint256 allowance) + external + returns (bool) + { + allowances[msg.sender][spender] = allowance; + return true; + } + + /// @dev Retrieve the balance for `owner`. + function balanceOf(address owner) + external + view + returns (uint256) + { + return balances[owner]; + } +} + + +/// @dev Eth2DaiBridge overridden to mock tokens and +/// implement IEth2Dai. +contract TestEth2DaiBridge is + IEth2Dai, + Eth2DaiBridge +{ + event SellAllAmount( + address sellToken, + uint256 sellTokenAmount, + address buyToken, + uint256 minimumFillAmount + ); + + event TokenTransfer( + address token, + address from, + address to, + uint256 amount + ); + + TestToken public wethToken = new TestToken(); + TestToken public daiToken = new TestToken(); + string private _nextRevertReason; + uint256 private _nextFillAmount; + + /// @dev Set token balances for this contract. + function setTokenBalances(uint256 wethBalance, uint256 daiBalance) + external + { + wethToken.setBalance(address(this), wethBalance); + daiToken.setBalance(address(this), daiBalance); + } + + /// @dev Set the behavior for `IEth2Dai.sellAllAmount()`. + function setFillBehavior(string calldata revertReason, uint256 fillAmount) + external + { + _nextRevertReason = revertReason; + _nextFillAmount = fillAmount; + } + + /// @dev Implementation of `IEth2Dai.sellAllAmount()` + function sellAllAmount( + address sellTokenAddress, + uint256 sellTokenAmount, + address buyTokenAddress, + uint256 minimumFillAmount + ) + external + returns (uint256 fillAmount) + { + emit SellAllAmount( + sellTokenAddress, + sellTokenAmount, + buyTokenAddress, + minimumFillAmount + ); + if (bytes(_nextRevertReason).length != 0) { + revert(_nextRevertReason); + } + return _nextFillAmount; + } + + function raiseTransferEvent( + address from, + address to, + uint256 amount + ) + external + { + emit TokenTransfer( + msg.sender, + from, + to, + amount + ); + } + + /// @dev Retrieves the allowances of the test tokens. + function getEth2DaiTokenAllowances() + external + view + returns (uint256 wethAllowance, uint256 daiAllowance) + { + wethAllowance = wethToken.allowances(address(this), address(this)); + daiAllowance = daiToken.allowances(address(this), address(this)); + return (wethAllowance, daiAllowance); + } + + // @dev Use `wethToken`. + function _getWethContract() + internal + view + returns (IERC20Token) + { + return IERC20Token(address(wethToken)); + } + + // @dev Use `daiToken`. + function _getDaiContract() + internal + view + returns (IERC20Token) + { + return IERC20Token(address(daiToken)); + } + + // @dev This contract will double as the Eth2Dai contract. + function _getEth2DaiContract() + internal + view + returns (IEth2Dai) + { + return IEth2Dai(address(this)); + } +} From 7d121bafd0d83ddcec63b74ad1acecfba93ef0ea Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Sun, 29 Sep 2019 19:21:42 -0400 Subject: [PATCH 11/87] `@0x/contracts-asset-proxy`: More work on `UniswapBridge` tests. --- .../contracts/src/bridges/UniswapBridge.sol | 32 +++++- .../contracts/test/TestUniswapBridge.sol | 106 +++++++++++++----- 2 files changed, 107 insertions(+), 31 deletions(-) diff --git a/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol index db55aa58e3..bcb0a6ce09 100644 --- a/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol +++ b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol @@ -35,6 +35,9 @@ contract UniswaBridge is address constant public UNISWAP_EXCHANGE_FACTORY_ADDRESS = address(0); address constant public WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + /// @dev Whether we've granted an allowance to a spender for a token. + mapping (address => mapping (address => bool)) private _hasAllowance; + /// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of /// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress` /// token encoded in the bridge data. @@ -67,6 +70,8 @@ contract UniswaBridge is fromTokenAddress, toTokenAddress ); + // Grant an allowance to the exchange. + _grantAllowanceForTokens(address(exchange), [fromTokenAddress, toTokenAddress]); // Get our balance of `fromTokenAddress` token. uint256 fromTokenBalance = IERC20Token(fromToken).balanceOf(address(this)); @@ -157,6 +162,30 @@ contract UniswaBridge is return IUniswapExchangeFactory(ETH2DAI_ADDRESS); } + /// @dev Grants an unlimited allowance to `spender` for `fromTokenAddress` + /// and `toTokenAddress` tokens, if they're not WETH and we haven't + /// already granted `spender` an allowance. + /// @param spender The spender being granted an aloowance. + /// @param tokenAddresses Array of token addresses. + function _grantAllowanceForTokens( + address spender, + address[2] memory tokenAddresses, + ) + private + { + address wethAddress = address(_getWethContract()); + mapping (address => bool) storage doesSpenderHaveAllowance = _hasAllowance[spender]; + for (uint256 i = 0; i < tokenAddresses.length; ++i) { + address tokenAddress = tokenAddresses[i]; + if (tokenAddress != wethAddress) { + if (!doesSpenderHaveAllowance[tokenAddress]) { + IERC20Token(tokenAddress).approve(spender, uint256(-1)); + doesSpenderHaveAllowance[tokenAddress] = true; + } + } + } + } + /// @dev Retrieves the uniswap exchange contract for a given token pair. /// @return exchange The exchange contract for the token pair. function _getUniswapExchangeForTokenPair( @@ -168,8 +197,7 @@ contract UniswaBridge is returns (IUniswapExchange exchange) { // Whichever isn't WETH is the exchange token. - address wethAddress = address(_getWethContract()); - if (fromTokenAddress != wethAddress) { + if (fromTokenAddress != address(_getWethContract())) { return _getUniswapExchangeForToken(fromTokenAddress); } return _getUniswapExchangeForToken(toTokenAddress); diff --git a/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol b/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol index d254c000e4..943cda072b 100644 --- a/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol +++ b/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol @@ -20,25 +20,34 @@ pragma solidity ^0.5.9; pragma experimental ABIEncoderV2; import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; -import "../src/bridges/Eth2DaiBridge.sol"; -import "../src/interfaces/IEth2Dai.sol"; +import "../src/bridges/UniswapBridge.sol"; +import "../src/interfaces/IUniswap.sol"; // solhint-disable no-simple-event-func-name -/// @dev Interface that allows `TestToken` to call `raiseTransferEvent` on -/// the `TestEth2DaiBridge` contract. -interface ITestTokenCaller { +/// @dev Interface that allows `TestToken` to call functions on the +/// `TestUniswapBridge` contract. +interface ITestEventRaiser { - function raiseTransferEvent( + function raiseTokenTransferEvent( address from, address to, uint256 amount ) external; - function raiseTransferEvent( - address from, - address to, + function raiseTokenApproveEvent( + address spender, + uint256 allowance + ) + external; + + function raiseWethDeposit( + uint256 amount + ) + external; + + function raiseWethWithdraw( uint256 amount ) external; @@ -50,12 +59,21 @@ contract TestToken { mapping (address => uint256) public balances; - /// @dev Just calls `raiseTransferEvent()` on the caller. + /// @dev Just calls `raiseTokenTransferEvent()` on the caller. function transfer(address to, uint256 amount) external returns (bool) { - IRaiseTransferEvent(msg.sender).raiseTransferEvent(msg.sender, to, amount); + ITestEventRaiser(msg.sender).raiseTokenTransferEvent(msg.sender, to, amount); + return true; + } + + /// @dev Just calls `raiseTokenApproveEvent()` on the caller. + function approve(address spender, uint256 allowance) + external + returns (bool) + { + ITestEventRaiser(msg.sender).raiseTokenApproveEvent(spender, allowance); return true; } @@ -66,13 +84,19 @@ contract TestToken { balances[owner] = balance; } - /// @dev Just calls `raiseApproveEvent()` on the caller. - function approve(address spender, uint256 allowance) + // @dev `IWETH.deposit()` that just calls `raiseWethDeposit()` on the caller. + function deposit() external - returns (bool) + payable { - allowances[msg.sender][spender] = allowance; - return true; + ITestEventRaiser(msg.sender).raiseWethDeposit(msg.value); + } + + // @dev `IWETH.withdraw()` that just calls `raiseWethWithdraw()` on the caller. + function withdraw(uint256 amount) + external + { + ITestEventRaiser(msg.sender).raiseWethWithdraw(amount); } /// @dev Retrieve the balance for `owner`. @@ -86,11 +110,10 @@ contract TestToken { } -/// @dev Eth2DaiBridge overridden to mock tokens and -/// implement IEth2Dai. -contract TestEth2DaiBridge is - IEth2Dai, - Eth2DaiBridge +/// @dev UniswapBridge overridden to mock tokens and implement IUniswap. +contract TestUniswapBridge is + IUniswap, + UniswapBridge { event SellAllAmount( address sellToken, @@ -106,6 +129,19 @@ contract TestEth2DaiBridge is uint256 amount ); + event TokenApprove( + address spender, + uint256 allowance + ); + + event WethDeposit( + uint256 amount + ); + + event WethWithdraw( + uint256 amount + ); + TestToken public wethToken = new TestToken(); TestToken public daiToken = new TestToken(); string private _nextRevertReason; @@ -119,7 +155,7 @@ contract TestEth2DaiBridge is daiToken.setBalance(address(this), daiBalance); } - /// @dev Set the behavior for `IEth2Dai.sellAllAmount()`. + /// @dev Set the behavior for `IUniswap.sellAllAmount()`. function setFillBehavior(string calldata revertReason, uint256 fillAmount) external { @@ -127,7 +163,7 @@ contract TestEth2DaiBridge is _nextFillAmount = fillAmount; } - /// @dev Implementation of `IEth2Dai.sellAllAmount()` + /// @dev Implementation of `IUniswap.sellAllAmount()` function sellAllAmount( address sellTokenAddress, uint256 sellTokenAmount, @@ -149,7 +185,7 @@ contract TestEth2DaiBridge is return _nextFillAmount; } - function raiseTransferEvent( + function raiseTokenTransferEvent( address from, address to, uint256 amount @@ -164,8 +200,20 @@ contract TestEth2DaiBridge is ); } + function raiseTokenApproveEvent( + address spender, + uint256 allowance + ) + external + { + emit TokenApprove( + spender, + allowance + ); + } + /// @dev Retrieves the allowances of the test tokens. - function getEth2DaiTokenAllowances() + function getUniswapTokenAllowances() external view returns (uint256 wethAllowance, uint256 daiAllowance) @@ -193,12 +241,12 @@ contract TestEth2DaiBridge is return IERC20Token(address(daiToken)); } - // @dev This contract will double as the Eth2Dai contract. - function _getEth2DaiContract() + // @dev This contract will double as the Uniswap contract. + function _getUniswapContract() internal view - returns (IEth2Dai) + returns (IUniswap) { - return IEth2Dai(address(this)); + return IUniswap(address(this)); } } From b38378187082483ba867ad0d4af3c5cc769035e7 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Mon, 30 Sep 2019 14:02:10 -0700 Subject: [PATCH 12/87] `@0x/contracts-asset-proxy`: Getting around stack issues. --- .../contracts/src/bridges/UniswapBridge.sol | 75 ++-- .../{IUniswap.sol => IUniswapExchange.sol} | 18 +- .../interfaces/IUniswapExchangeFactory.sol | 32 ++ .../contracts/test/TestUniswapBridge.sol | 372 ++++++++++++------ 4 files changed, 337 insertions(+), 160 deletions(-) rename contracts/asset-proxy/contracts/src/interfaces/{IUniswap.sol => IUniswapExchange.sol} (86%) create mode 100644 contracts/asset-proxy/contracts/src/interfaces/IUniswapExchangeFactory.sol diff --git a/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol index bcb0a6ce09..68e140894e 100644 --- a/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol +++ b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol @@ -20,21 +20,31 @@ pragma solidity ^0.5.9; pragma experimental ABIEncoderV2; import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; +import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol"; import "@0x/contracts-exchange/contracts/src/interfaces/IWallet.sol"; -import "../interfaces/IUniswap.sol"; +import "../interfaces/IUniswapExchangeFactory.sol"; +import "../interfaces/IUniswapExchange.sol"; import "./ERC20Bridge.sol"; // solhint-disable space-after-comma -contract UniswaBridge is +contract UniswapBridge is ERC20Bridge, IWallet { bytes4 private constant LEGACY_WALLET_MAGIC_VALUE = 0xb0671381; /* Mainnet addresses */ - address constant public UNISWAP_EXCHANGE_FACTORY_ADDRESS = address(0); + address constant public UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95; address constant public WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + // Struct to hold `withdrawTo()` local variables in memory and to avoid + // stack overflows. + struct WithdrawToState { + IUniswapExchange exchange; + uint256 fromTokenBalance; + IEtherToken weth; + } + /// @dev Whether we've granted an allowance to a spender for a token. mapping (address => mapping (address => bool)) private _hasAllowance; @@ -51,37 +61,41 @@ contract UniswaBridge is address /* from */, address to, uint256 amount, - bytes calldata bridgeData, + bytes calldata bridgeData ) external returns (bytes4 success) { + // State memory object to avoid stack overflows. + WithdrawToState memory state; // Decode the bridge data to get the `fromTokenAddress`. (address fromTokenAddress) = abi.decode(bridgeData, (address)); // Just transfer the tokens if they're the same. if (fromTokenAddress == toTokenAddress) { - IERC20Token(fromToken).transfer(to, amount); + IERC20Token(fromTokenAddress).transfer(to, amount); return BRIDGE_SUCCESS; } // Get the exchange for the token pair. - IUniswapExchange exchange = _getUniswapExchangeForTokenPair( + state.exchange = _getUniswapExchangeForTokenPair( fromTokenAddress, toTokenAddress ); // Grant an allowance to the exchange. - _grantAllowanceForTokens(address(exchange), [fromTokenAddress, toTokenAddress]); + _grantAllowanceForTokens(address(state.exchange), [fromTokenAddress, toTokenAddress]); // Get our balance of `fromTokenAddress` token. - uint256 fromTokenBalance = IERC20Token(fromToken).balanceOf(address(this)); + state.fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this)); + // Get the weth contract. + state.weth = _getWethContract(); // Convert from WETH to a token. - if (fromTokenAddress == address(weth)) { + if (fromTokenAddress == address(state.weth)) { // Unwrap the WETH. - _getWethContract().withdraw(fromTokenBalance); + state.weth.withdraw(state.fromTokenBalance); // Buy as much of `toTokenAddress` token with ETH as possible and // transfer it to `to`. - exchange.ethToTokenTransferInput.value(fromTokenBalance)( + state.exchange.ethToTokenTransferInput.value(state.fromTokenBalance)( // No minimum buy amount. 0, // Expires after this block. @@ -91,18 +105,18 @@ contract UniswaBridge is ); // Convert from a token to WETH. - } else if (toTokenAddress == address(weth)) { + } else if (toTokenAddress == address(state.weth)) { // Buy as much ETH with `toTokenAddress` token as possible. - uint256 ethBought = exchange.tokenToEthSwapInput( + uint256 ethBought = state.exchange.tokenToEthSwapInput( // Sell all tokens we hold. - fromTokenBalance, + state.fromTokenBalance, + // No minimum buy amount. + 0, // Expires after this block. - block.timestamp, - // Recipient is `to`. - to + block.timestamp ); // Wrap the ETH. - _getWethContract().deposit.value(ethBought)(); + state.weth.deposit.value(ethBought)(); // Transfer the WETH to `to`. IERC20Token(toTokenAddress).transfer(to, ethBought); @@ -110,9 +124,9 @@ contract UniswaBridge is } else { // Buy as much `toTokenAddress` token with `fromTokenAddress` token // and transfer it to `to`. - exchange.tokenToTokenTransferInput( + state.exchange.tokenToTokenTransferInput( // Sell all tokens we hold. - fromTokenBalance, + state.fromTokenBalance, // No minimum buy amount. 0, // No minimum intermediate ETH buy amount. @@ -147,9 +161,9 @@ contract UniswaBridge is function _getWethContract() internal view - returns (IERC20Token token) + returns (IEtherToken token) { - return IERC20Token(WETH_ADDRESS); + return IEtherToken(WETH_ADDRESS); } /// @dev Overridable way to get the uniswap exchange factory contract. @@ -159,17 +173,17 @@ contract UniswaBridge is view returns (IUniswapExchangeFactory factory) { - return IUniswapExchangeFactory(ETH2DAI_ADDRESS); + return IUniswapExchangeFactory(UNISWAP_EXCHANGE_FACTORY_ADDRESS); } - /// @dev Grants an unlimited allowance to `spender` for `fromTokenAddress` - /// and `toTokenAddress` tokens, if they're not WETH and we haven't - /// already granted `spender` an allowance. + /// @dev Grants an unlimited allowance to `spender` for the tokens passed, + /// if they're not WETH and we haven't already granted `spender` an + /// allowance. /// @param spender The spender being granted an aloowance. /// @param tokenAddresses Array of token addresses. function _grantAllowanceForTokens( address spender, - address[2] memory tokenAddresses, + address[2] memory tokenAddresses ) private { @@ -210,9 +224,8 @@ contract UniswaBridge is view returns (IUniswapExchange exchange) { - address exchangeAddress = _getUniswapExchangeFactoryContract() - .getExchange(tokenAddress); - require(exchangeAddress != address(0), "NO_UNISWAP_EXCHANGE_FOR_TOKEN"); - return IUniswapExchange(exchangeAddress); + exchange = _getUniswapExchangeFactoryContract().getExchange(tokenAddress); + require(address(exchange) != address(0), "NO_UNISWAP_EXCHANGE_FOR_TOKEN"); + return exchange; } } diff --git a/contracts/asset-proxy/contracts/src/interfaces/IUniswap.sol b/contracts/asset-proxy/contracts/src/interfaces/IUniswapExchange.sol similarity index 86% rename from contracts/asset-proxy/contracts/src/interfaces/IUniswap.sol rename to contracts/asset-proxy/contracts/src/interfaces/IUniswapExchange.sol index c4035f93f6..f11b2304de 100644 --- a/contracts/asset-proxy/contracts/src/interfaces/IUniswap.sol +++ b/contracts/asset-proxy/contracts/src/interfaces/IUniswapExchange.sol @@ -19,7 +19,6 @@ pragma solidity ^0.5.9; -// solhint-disable func-param-name-mixedcase interface IUniswapExchange { /// @dev Buys at least `minTokensBought` tokens with ETH and transfer them @@ -30,7 +29,7 @@ interface IUniswapExchange { /// @return tokensBought Amount of tokens bought. function ethToTokenTransferInput( uint256 minTokensBought, - uint64 deadline, + uint256 deadline, address recipient ) external @@ -45,7 +44,7 @@ interface IUniswapExchange { function tokenToEthSwapInput( uint256 tokensSold, uint256 minEthBought, - uint64 deadline + uint256 deadline ) external payable @@ -63,21 +62,10 @@ interface IUniswapExchange { uint256 tokensSold, uint256 minTokensBought, uint256 minEthBought, - uint64 deadline, + uint256 deadline, address recipient, address toTokenAddress ) external returns (uint256 tokensBought); } - - -interface IUniswapExchangeFactory { - - /// @dev Get the exchange for a token. - /// @param tokenAddress The address of the token contract. - function getExchange(address tokenAddress) - external - view - returns (IUniswapExchange); -} diff --git a/contracts/asset-proxy/contracts/src/interfaces/IUniswapExchangeFactory.sol b/contracts/asset-proxy/contracts/src/interfaces/IUniswapExchangeFactory.sol new file mode 100644 index 0000000000..c175f55326 --- /dev/null +++ b/contracts/asset-proxy/contracts/src/interfaces/IUniswapExchangeFactory.sol @@ -0,0 +1,32 @@ +/* + + Copyright 2019 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.5.9; + +import "./IUniswapExchange.sol"; + + +interface IUniswapExchangeFactory { + + /// @dev Get the exchange for a token. + /// @param tokenAddress The address of the token contract. + function getExchange(address tokenAddress) + external + view + returns (IUniswapExchange); +} diff --git a/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol b/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol index 943cda072b..a6ab535f82 100644 --- a/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol +++ b/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol @@ -20,83 +20,197 @@ pragma solidity ^0.5.9; pragma experimental ABIEncoderV2; import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; +import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; import "../src/bridges/UniswapBridge.sol"; -import "../src/interfaces/IUniswap.sol"; +import "../src/interfaces/IUniswapExchangeFactory.sol"; +import "../src/interfaces/IUniswapExchange.sol"; -// solhint-disable no-simple-event-func-name -/// @dev Interface that allows `TestToken` to call functions on the -/// `TestUniswapBridge` contract. -interface ITestEventRaiser { +contract TestEventsRaiser { - function raiseTokenTransferEvent( + event SellAllAmount( + address sellToken, + uint256 sellTokenAmount, + address buyToken, + uint256 minimumFillAmount + ); + + event TokenTransfer( + address token, address from, address to, uint256 amount - ) - external; + ); - function raiseTokenApproveEvent( + event TokenApprove( address spender, uint256 allowance - ) - external; + ); + + event WethDeposit( + uint256 amount + ); - function raiseWethDeposit( + event WethWithdraw( uint256 amount + ); + + event EthToTokenTransferInput( + uint256 minTokensBought, + uint256 deadline, + address recipient + ); + + event TokenToEthSwapInput( + uint256 tokensSold, + uint256 minEthBought, + uint256 deadline + ); + + event TokenToTokenTransferInput( + uint256 tokensSold, + uint256 minTokensBought, + uint256 minEthBought, + uint256 deadline, + address recipient, + address toTokenAddress + ); + + function raiseEthToTokenTransferInput( + uint256 minTokensBought, + uint256 deadline, + address recipient + ) + external + { + emit EthToTokenTransferInput( + minTokensBought, + deadline, + recipient + ); + } + + function raiseTokenToEthSwapInput( + uint256 tokensSold, + uint256 minEthBought, + uint256 deadline ) - external; + external + { + emit TokenToEthSwapInput( + tokensSold, + minEthBought, + deadline + ); + } - function raiseWethWithdraw( + function raiseTokenToTokenTransferInput( + uint256 tokensSold, + uint256 minTokensBought, + uint256 minEthBought, + uint256 deadline, + address recipient, + address toTokenAddress + ) + external + { + emit TokenToTokenTransferInput( + tokensSold, + minTokensBought, + minEthBought, + deadline, + recipient, + toTokenAddress + ); + } + + function raiseTokenTransfer( + address from, + address to, uint256 amount ) - external; -} + external + { + emit TokenTransfer( + msg.sender, + from, + to, + amount + ); + } + function raiseTokenApprove(address spender, uint256 allowance) + external + { + emit TokenApprove(spender, allowance); + } + + function raiseWethDeposit(uint256 amount) + external + { + emit WethDeposit(amount); + } + + function raiseWethWithdraw(uint256 amount) + external + { + emit WethWithdraw(amount); + } +} /// @dev A minimalist ERC20/WETH token. contract TestToken { + using LibSafeMath for uint256; + mapping (address => uint256) public balances; - /// @dev Just calls `raiseTokenTransferEvent()` on the caller. + /// @dev Calls `raiseTokenTransfer()` on the caller. function transfer(address to, uint256 amount) external returns (bool) { - ITestEventRaiser(msg.sender).raiseTokenTransferEvent(msg.sender, to, amount); + TestEventsRaiser(msg.sender).raiseTokenTransfer(msg.sender, to, amount); + balances[msg.sender] = balances[msg.sender].safeSub(amount); + balances[to] = balances[to].safeAdd(amount); return true; } - /// @dev Just calls `raiseTokenApproveEvent()` on the caller. + /// @dev Just calls `raiseTokenApprove()` on the caller. function approve(address spender, uint256 allowance) external returns (bool) { - ITestEventRaiser(msg.sender).raiseTokenApproveEvent(spender, allowance); + TestEventsRaiser(msg.sender).raiseTokenApprove(spender, allowance); return true; } /// @dev Set the balance for `owner`. function setBalance(address owner, uint256 balance) external + payable { balances[owner] = balance; } - // @dev `IWETH.deposit()` that just calls `raiseWethDeposit()` on the caller. + /// @dev `IWETH.deposit()` that increases balances and calls + /// `raiseWethDeposit()` on the caller. function deposit() external payable { - ITestEventRaiser(msg.sender).raiseWethDeposit(msg.value); + balances[msg.sender] += balances[msg.sender].safeAdd(msg.value); + TestEventsRaiser(msg.sender).raiseWethDeposit(msg.value); } - // @dev `IWETH.withdraw()` that just calls `raiseWethWithdraw()` on the caller. + /// @dev `IWETH.withdraw()` that just reduces balances and calls + /// `raiseWethWithdraw()` on the caller. function withdraw(uint256 amount) external { - ITestEventRaiser(msg.sender).raiseWethWithdraw(amount); + balances[msg.sender] = balances[msg.sender].safeSub(amount); + msg.sender.transfer(amount); + TestEventsRaiser(msg.sender).raiseWethWithdraw(amount); } /// @dev Retrieve the balance for `owner`. @@ -110,143 +224,173 @@ contract TestToken { } -/// @dev UniswapBridge overridden to mock tokens and implement IUniswap. -contract TestUniswapBridge is - IUniswap, - UniswapBridge +contract TestExchange is + IUniswapExchange { - event SellAllAmount( - address sellToken, - uint256 sellTokenAmount, - address buyToken, - uint256 minimumFillAmount - ); - - event TokenTransfer( - address token, - address from, - address to, - uint256 amount - ); - - event TokenApprove( - address spender, - uint256 allowance - ); - - event WethDeposit( - uint256 amount - ); - - event WethWithdraw( - uint256 amount - ); - - TestToken public wethToken = new TestToken(); - TestToken public daiToken = new TestToken(); + address public tokenAddress; string private _nextRevertReason; uint256 private _nextFillAmount; - /// @dev Set token balances for this contract. - function setTokenBalances(uint256 wethBalance, uint256 daiBalance) - external - { - wethToken.setBalance(address(this), wethBalance); - daiToken.setBalance(address(this), daiBalance); + constructor(address _tokenAddress) public { + tokenAddress = _tokenAddress; } - /// @dev Set the behavior for `IUniswap.sellAllAmount()`. - function setFillBehavior(string calldata revertReason, uint256 fillAmount) + function setFillBehavior( + string calldata revertReason, + uint256 fillAmount + ) external + payable { _nextRevertReason = revertReason; _nextFillAmount = fillAmount; } - /// @dev Implementation of `IUniswap.sellAllAmount()` - function sellAllAmount( - address sellTokenAddress, - uint256 sellTokenAmount, - address buyTokenAddress, - uint256 minimumFillAmount + function ethToTokenTransferInput( + uint256 minTokensBought, + uint256 deadline, + address recipient ) external - returns (uint256 fillAmount) + payable + returns (uint256 tokensBought) { - emit SellAllAmount( - sellTokenAddress, - sellTokenAmount, - buyTokenAddress, - minimumFillAmount + TestEventsRaiser(msg.sender).raiseEthToTokenTransferInput( + minTokensBought, + deadline, + recipient ); - if (bytes(_nextRevertReason).length != 0) { - revert(_nextRevertReason); - } + _revertIfReasonExists(); return _nextFillAmount; } - function raiseTokenTransferEvent( - address from, - address to, - uint256 amount + function tokenToEthSwapInput( + uint256 tokensSold, + uint256 minEthBought, + uint256 deadline ) external + payable + returns (uint256 ethBought) { - emit TokenTransfer( - msg.sender, - from, - to, - amount + TestEventsRaiser(msg.sender).raiseTokenToEthSwapInput( + tokensSold, + minEthBought, + deadline ); + _revertIfReasonExists(); + return _nextFillAmount; } - function raiseTokenApproveEvent( - address spender, - uint256 allowance + function tokenToTokenTransferInput( + uint256 tokensSold, + uint256 minTokensBought, + uint256 minEthBought, + uint256 deadline, + address recipient, + address toTokenAddress ) external + returns (uint256 tokensBought) { - emit TokenApprove( - spender, - allowance + TestEventsRaiser(msg.sender).raiseTokenToTokenTransferInput( + tokensSold, + minTokensBought, + minEthBought, + deadline, + recipient, + toTokenAddress ); + _revertIfReasonExists(); + return _nextFillAmount; + } + + function _revertIfReasonExists() + private + { + if (bytes(_nextRevertReason).length != 0) { + revert(_nextRevertReason); + } } +} + + +/// @dev UniswapBridge overridden to mock tokens and implement IUniswapExchangeFactory. +contract TestUniswapBridge is + IUniswapExchangeFactory, + TestEventsRaiser, + UniswapBridge +{ - /// @dev Retrieves the allowances of the test tokens. - function getUniswapTokenAllowances() + TestToken public wethToken = new TestToken(); + // Token address to TestToken instance. + mapping (address => TestToken) private _testTokens; + // Token address to TestExchange instance. + mapping (address => TestExchange) private _testExchanges; + + /// @dev Set token balances for this contract. + function setTokenBalances(address tokenAddress, uint256 balance) external - view - returns (uint256 wethAllowance, uint256 daiAllowance) { - wethAllowance = wethToken.allowances(address(this), address(this)); - daiAllowance = daiToken.allowances(address(this), address(this)); - return (wethAllowance, daiAllowance); + TestToken token = _testTokens[tokenAddress]; + // Create the token if it doesn't exist. + if (address(token) == address(0)) { + _testTokens[tokenAddress] = token = new TestToken(); + } + token.setBalance(address(this), balance); } - // @dev Use `wethToken`. - function _getWethContract() - internal + /// @dev Set the behavior for a fill on a uniswap exchange. + function setExchangeFillBehavior( + address exchangeAddress, + string calldata revertReason, + uint256 fillAmount + ) + external + payable + { + createExchange(exchangeAddress).setFillBehavior.value(msg.value)( + revertReason, + fillAmount + ); + } + + /// @dev Create an exchange for a token. + function createExchange(address tokenAddress) + public + returns (TestExchange exchangeAddress) + { + TestExchange exchange = _testExchanges[tokenAddress]; + if (address(exchange) == address(0)) { + _testExchanges[tokenAddress] = exchange = new TestExchange(tokenAddress); + } + return exchange; + } + + /// @dev `IUniswapExchangeFactory.getExchange` + function getExchange(address tokenAddress) + external view - returns (IERC20Token) + returns (IUniswapExchange) { - return IERC20Token(address(wethToken)); + return IUniswapExchange(_testExchanges[tokenAddress]); } - // @dev Use `daiToken`. - function _getDaiContract() + // @dev Use `wethToken`. + function _getWethContract() internal view - returns (IERC20Token) + returns (IEtherToken) { - return IERC20Token(address(daiToken)); + return IEtherToken(address(wethToken)); } // @dev This contract will double as the Uniswap contract. - function _getUniswapContract() + function _getUniswapExchangeFactoryContract() internal view - returns (IUniswap) + returns (IUniswapExchangeFactory) { - return IUniswap(address(this)); + return IUniswapExchangeFactory(address(this)); } } From c2261a6bbe39c6b37b8acf756ce99427880b0b57 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Tue, 1 Oct 2019 18:15:33 -0700 Subject: [PATCH 13/87] `@0x/contracts-asset-proxy`: Finish off `UniswapBridge` tests. --- .../contracts/src/bridges/UniswapBridge.sol | 48 +-- .../src/interfaces/IUniswapExchange.sol | 8 +- .../contracts/test/TestUniswapBridge.sol | 142 +++--- contracts/asset-proxy/test/uniswap_bridge.ts | 408 +++++++++++++----- 4 files changed, 424 insertions(+), 182 deletions(-) diff --git a/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol index 68e140894e..f1a55d9faf 100644 --- a/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol +++ b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol @@ -21,18 +21,18 @@ pragma experimental ABIEncoderV2; import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol"; -import "@0x/contracts-exchange/contracts/src/interfaces/IWallet.sol"; import "../interfaces/IUniswapExchangeFactory.sol"; import "../interfaces/IUniswapExchange.sol"; -import "./ERC20Bridge.sol"; +import "../interfaces/IWallet.sol"; +import "../interfaces/IERC20Bridge.sol"; // solhint-disable space-after-comma +// solhint-disable not-rely-on-time contract UniswapBridge is - ERC20Bridge, + IERC20Bridge, IWallet { - bytes4 private constant LEGACY_WALLET_MAGIC_VALUE = 0xb0671381; /* Mainnet addresses */ address constant public UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95; address constant public WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; @@ -45,8 +45,15 @@ contract UniswapBridge is IEtherToken weth; } - /// @dev Whether we've granted an allowance to a spender for a token. - mapping (address => mapping (address => bool)) private _hasAllowance; + // solhint-disable no-empty-blocks + /// @dev Payable fallback to receive ETH from uniswap. + function () + external + payable + {} + + /// @dev Whether we've granted an allowance to the exchange for a token. + mapping (address => bool) private _hasAllowance; /// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of /// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress` @@ -83,7 +90,7 @@ contract UniswapBridge is toTokenAddress ); // Grant an allowance to the exchange. - _grantAllowanceForTokens(address(state.exchange), [fromTokenAddress, toTokenAddress]); + _grantExchangeAllowance(state.exchange); // Get our balance of `fromTokenAddress` token. state.fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this)); // Get the weth contract. @@ -176,27 +183,16 @@ contract UniswapBridge is return IUniswapExchangeFactory(UNISWAP_EXCHANGE_FACTORY_ADDRESS); } - /// @dev Grants an unlimited allowance to `spender` for the tokens passed, - /// if they're not WETH and we haven't already granted `spender` an - /// allowance. - /// @param spender The spender being granted an aloowance. - /// @param tokenAddresses Array of token addresses. - function _grantAllowanceForTokens( - address spender, - address[2] memory tokenAddresses - ) + /// @dev Grants an unlimited allowance to the exchange for its token + /// on behalf of this contract, if we haven't already done so. + /// @param exchange The Uniswap token exchange. + function _grantExchangeAllowance(IUniswapExchange exchange) private { - address wethAddress = address(_getWethContract()); - mapping (address => bool) storage doesSpenderHaveAllowance = _hasAllowance[spender]; - for (uint256 i = 0; i < tokenAddresses.length; ++i) { - address tokenAddress = tokenAddresses[i]; - if (tokenAddress != wethAddress) { - if (!doesSpenderHaveAllowance[tokenAddress]) { - IERC20Token(tokenAddress).approve(spender, uint256(-1)); - doesSpenderHaveAllowance[tokenAddress] = true; - } - } + address tokenAddress = exchange.toTokenAddress(); + if (!_hasAllowance[tokenAddress]) { + IERC20Token(tokenAddress).approve(address(exchange), uint256(-1)); + _hasAllowance[tokenAddress] = true; } } diff --git a/contracts/asset-proxy/contracts/src/interfaces/IUniswapExchange.sol b/contracts/asset-proxy/contracts/src/interfaces/IUniswapExchange.sol index f11b2304de..20fa61ab58 100644 --- a/contracts/asset-proxy/contracts/src/interfaces/IUniswapExchange.sol +++ b/contracts/asset-proxy/contracts/src/interfaces/IUniswapExchange.sol @@ -47,7 +47,6 @@ interface IUniswapExchange { uint256 deadline ) external - payable returns (uint256 ethBought); /// @dev Buys at least `minTokensBought` tokens with the exchange token @@ -68,4 +67,11 @@ interface IUniswapExchange { ) external returns (uint256 tokensBought); + + /// @dev Retrieves the token that is associated with this exchange. + /// @return tokenAddress The token address. + function toTokenAddress() + external + view + returns (address tokenAddress); } diff --git a/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol b/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol index a6ab535f82..19c4e86042 100644 --- a/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol +++ b/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol @@ -26,15 +26,9 @@ import "../src/interfaces/IUniswapExchangeFactory.sol"; import "../src/interfaces/IUniswapExchange.sol"; +// solhint-disable no-simple-event-func-name contract TestEventsRaiser { - event SellAllAmount( - address sellToken, - uint256 sellTokenAmount, - address buyToken, - uint256 minimumFillAmount - ); - event TokenTransfer( address token, address from, @@ -56,18 +50,21 @@ contract TestEventsRaiser { ); event EthToTokenTransferInput( + address exchange, uint256 minTokensBought, uint256 deadline, address recipient ); event TokenToEthSwapInput( + address exchange, uint256 tokensSold, uint256 minEthBought, uint256 deadline ); event TokenToTokenTransferInput( + address exchange, uint256 tokensSold, uint256 minTokensBought, uint256 minEthBought, @@ -84,6 +81,7 @@ contract TestEventsRaiser { external { emit EthToTokenTransferInput( + msg.sender, minTokensBought, deadline, recipient @@ -98,6 +96,7 @@ contract TestEventsRaiser { external { emit TokenToEthSwapInput( + msg.sender, tokensSold, minEthBought, deadline @@ -115,6 +114,7 @@ contract TestEventsRaiser { external { emit TokenToTokenTransferInput( + msg.sender, tokensSold, minTokensBought, minEthBought, @@ -158,21 +158,38 @@ contract TestEventsRaiser { } } + /// @dev A minimalist ERC20/WETH token. contract TestToken { using LibSafeMath for uint256; mapping (address => uint256) public balances; + string private _nextRevertReason; + + /// @dev Set the balance for `owner`. + function setBalance(address owner) + external + payable + { + balances[owner] = msg.value; + } + + /// @dev Set the revert reason for `transfer()`, + /// `deposit()`, and `withdraw()`. + function setRevertReason(string calldata reason) + external + { + _nextRevertReason = reason; + } - /// @dev Calls `raiseTokenTransfer()` on the caller. + /// @dev Just calls `raiseTokenTransfer()` on the caller. function transfer(address to, uint256 amount) external returns (bool) { + _revertIfReasonExists(); TestEventsRaiser(msg.sender).raiseTokenTransfer(msg.sender, to, amount); - balances[msg.sender] = balances[msg.sender].safeSub(amount); - balances[to] = balances[to].safeAdd(amount); return true; } @@ -185,20 +202,13 @@ contract TestToken { return true; } - /// @dev Set the balance for `owner`. - function setBalance(address owner, uint256 balance) - external - payable - { - balances[owner] = balance; - } - /// @dev `IWETH.deposit()` that increases balances and calls /// `raiseWethDeposit()` on the caller. function deposit() external payable { + _revertIfReasonExists(); balances[msg.sender] += balances[msg.sender].safeAdd(msg.value); TestEventsRaiser(msg.sender).raiseWethDeposit(msg.value); } @@ -208,6 +218,7 @@ contract TestToken { function withdraw(uint256 amount) external { + _revertIfReasonExists(); balances[msg.sender] = balances[msg.sender].safeSub(amount); msg.sender.transfer(amount); TestEventsRaiser(msg.sender).raiseWethWithdraw(amount); @@ -221,6 +232,15 @@ contract TestToken { { return balances[owner]; } + + function _revertIfReasonExists() + private + view + { + if (bytes(_nextRevertReason).length != 0) { + revert(_nextRevertReason); + } + } } @@ -229,21 +249,18 @@ contract TestExchange is { address public tokenAddress; string private _nextRevertReason; - uint256 private _nextFillAmount; constructor(address _tokenAddress) public { tokenAddress = _tokenAddress; } function setFillBehavior( - string calldata revertReason, - uint256 fillAmount + string calldata revertReason ) external payable { _nextRevertReason = revertReason; - _nextFillAmount = fillAmount; } function ethToTokenTransferInput( @@ -261,7 +278,7 @@ contract TestExchange is recipient ); _revertIfReasonExists(); - return _nextFillAmount; + return address(this).balance; } function tokenToEthSwapInput( @@ -270,7 +287,6 @@ contract TestExchange is uint256 deadline ) external - payable returns (uint256 ethBought) { TestEventsRaiser(msg.sender).raiseTokenToEthSwapInput( @@ -279,7 +295,9 @@ contract TestExchange is deadline ); _revertIfReasonExists(); - return _nextFillAmount; + uint256 fillAmount = address(this).balance; + msg.sender.transfer(fillAmount); + return fillAmount; } function tokenToTokenTransferInput( @@ -302,11 +320,20 @@ contract TestExchange is toTokenAddress ); _revertIfReasonExists(); - return _nextFillAmount; + return address(this).balance; + } + + function toTokenAddress() + external + view + returns (address _tokenAddress) + { + return tokenAddress; } function _revertIfReasonExists() private + view { if (bytes(_nextRevertReason).length != 0) { revert(_nextRevertReason); @@ -321,50 +348,59 @@ contract TestUniswapBridge is TestEventsRaiser, UniswapBridge { - - TestToken public wethToken = new TestToken(); + TestToken public wethToken; // Token address to TestToken instance. mapping (address => TestToken) private _testTokens; // Token address to TestExchange instance. mapping (address => TestExchange) private _testExchanges; - /// @dev Set token balances for this contract. - function setTokenBalances(address tokenAddress, uint256 balance) + constructor() public { + wethToken = new TestToken(); + _testTokens[address(wethToken)] = wethToken; + } + + /// @dev Sets the balance of this contract for an existing token. + /// The wei attached will be the balance. + function setTokenBalance(address tokenAddress) external + payable { TestToken token = _testTokens[tokenAddress]; - // Create the token if it doesn't exist. - if (address(token) == address(0)) { - _testTokens[tokenAddress] = token = new TestToken(); - } - token.setBalance(address(this), balance); + token.deposit.value(msg.value)(); } - /// @dev Set the behavior for a fill on a uniswap exchange. - function setExchangeFillBehavior( - address exchangeAddress, - string calldata revertReason, - uint256 fillAmount - ) + /// @dev Sets the revert reason for an existing token. + function setTokenRevertReason(address tokenAddress, string calldata revertReason) external - payable { - createExchange(exchangeAddress).setFillBehavior.value(msg.value)( - revertReason, - fillAmount - ); + TestToken token = _testTokens[tokenAddress]; + token.setRevertReason(revertReason); } - /// @dev Create an exchange for a token. - function createExchange(address tokenAddress) - public - returns (TestExchange exchangeAddress) + /// @dev Create a token and exchange (if they don't exist) for a new token + /// and sets the exchange revert and fill behavior. The wei attached + /// will be the fill amount for the exchange. + /// @param tokenAddress The token address. If zero, one will be created. + /// @param revertReason The revert reason for exchange operations. + function createTokenAndExchange( + address tokenAddress, + string calldata revertReason + ) + external + payable + returns (TestToken token, TestExchange exchange) { - TestExchange exchange = _testExchanges[tokenAddress]; + token = TestToken(tokenAddress); + if (tokenAddress == address(0)) { + token = new TestToken(); + } + _testTokens[address(token)] = token; + exchange = _testExchanges[address(token)]; if (address(exchange) == address(0)) { - _testExchanges[tokenAddress] = exchange = new TestExchange(tokenAddress); + _testExchanges[address(token)] = exchange = new TestExchange(address(token)); } - return exchange; + exchange.setFillBehavior.value(msg.value)(revertReason); + return (token, exchange); } /// @dev `IUniswapExchangeFactory.getExchange` diff --git a/contracts/asset-proxy/test/uniswap_bridge.ts b/contracts/asset-proxy/test/uniswap_bridge.ts index 2d236cd1c0..d2dd2de3d6 100644 --- a/contracts/asset-proxy/test/uniswap_bridge.ts +++ b/contracts/asset-proxy/test/uniswap_bridge.ts @@ -2,13 +2,16 @@ import { blockchainTests, constants, expect, + filterLogs, filterLogsToArguments, getRandomInteger, + hexLeftPad, hexRandom, Numberish, randomAddress, TransactionHelper, } from '@0x/contracts-test-utils'; +import { AssetProxyId } from '@0x/types'; import { BigNumber } from '@0x/utils'; import { DecodedLogs } from 'ethereum-types'; import * as _ from 'lodash'; @@ -16,15 +19,19 @@ import * as _ from 'lodash'; import { artifacts, TestUniswapBridgeContract, - TestUniswapBridgeEvents, - TestUniswapBridgeSellAllAmountEventArgs, - TestUniswapBridgeTokenTransferEventArgs, + TestUniswapBridgeEthToTokenTransferInputEventArgs as EthToTokenTransferInputArgs, + TestUniswapBridgeEvents as ContractEvents, + TestUniswapBridgeTokenApproveEventArgs as TokenApproveArgs, + TestUniswapBridgeTokenToEthSwapInputEventArgs as TokenToEthSwapInputArgs, + TestUniswapBridgeTokenToTokenTransferInputEventArgs as TokenToTokenTransferInputArgs, + TestUniswapBridgeTokenTransferEventArgs as TokenTransferArgs, + TestUniswapBridgeWethDepositEventArgs as WethDepositArgs, + TestUniswapBridgeWethWithdrawEventArgs as WethWithdrawArgs, } from '../src'; -blockchainTests.resets('UniswapBridge unit tests', env => { +blockchainTests.resets.only('UniswapBridge unit tests', env => { const txHelper = new TransactionHelper(env.web3Wrapper, artifacts); let testContract: TestUniswapBridgeContract; - let daiTokenAddress: string; let wethTokenAddress: string; before(async () => { @@ -34,18 +41,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { env.txDefaults, artifacts, ); - [daiTokenAddress, wethTokenAddress] = await Promise.all([ - testContract.daiToken.callAsync(), - testContract.wethToken.callAsync(), - ]); - }); - - describe('deployment', () => { - it('sets Uniswap allowances to maximum', async () => { - const [wethAllowance, daiAllowance] = await testContract.getUniswapTokenAllowances.callAsync(); - expect(wethAllowance).to.bignumber.eq(constants.MAX_UINT256); - expect(daiAllowance).to.bignumber.eq(constants.MAX_UINT256); - }); + wethTokenAddress = await testContract.wethToken.callAsync(); }); describe('isValidSignature()', () => { @@ -56,125 +52,333 @@ blockchainTests.resets('UniswapBridge unit tests', env => { }); }); - describe('transfer()', () => { - interface TransferOpts { + describe('withdrawTo()', () => { + interface WithdrawToOpts { + fromTokenAddress: string; toTokenAddress: string; + fromTokenBalance: Numberish; toAddress: string; amount: Numberish; - fromTokenBalance: Numberish; - revertReason: string; - fillAmount: Numberish; + exchangeRevertReason: string; + exchangeFillAmount: Numberish; + toTokenRevertReason: string; + fromTokenRevertReason: string; } - function createTransferOpts(opts?: Partial): TransferOpts { + function createWithdrawToOpts(opts?: Partial): WithdrawToOpts { return { - toTokenAddress: _.sampleSize([wethTokenAddress, daiTokenAddress], 1)[0], + fromTokenAddress: constants.NULL_ADDRESS, + toTokenAddress: constants.NULL_ADDRESS, + fromTokenBalance: getRandomInteger(1, 1e18), toAddress: randomAddress(), - amount: getRandomInteger(1, 100e18), - revertReason: '', - fillAmount: getRandomInteger(1, 100e18), - fromTokenBalance: getRandomInteger(1, 100e18), + amount: getRandomInteger(1, 1e18), + exchangeRevertReason: '', + exchangeFillAmount: getRandomInteger(1, 1e18), + toTokenRevertReason: '', + fromTokenRevertReason: '', ...opts, }; } - async function transferAsync(opts?: Partial): Promise<[string, DecodedLogs]> { - const _opts = createTransferOpts(opts); - // Set the fill behavior. - await testContract.setFillBehavior.awaitTransactionSuccessAsync( - _opts.revertReason, - new BigNumber(_opts.fillAmount), + interface WithdrawToResult { + opts: WithdrawToOpts; + result: string; + logs: DecodedLogs; + blockTime: number; + } + + async function withdrawToAsync(opts?: Partial): Promise { + const _opts = createWithdrawToOpts(opts); + // Create the "from" token and exchange. + [[_opts.fromTokenAddress]] = await txHelper.getResultAndReceiptAsync( + testContract.createTokenAndExchange, + _opts.fromTokenAddress, + _opts.exchangeRevertReason, + { value: new BigNumber(_opts.exchangeFillAmount) }, ); - // Set the token balance for the token we're converting from. - await testContract.setTokenBalances.awaitTransactionSuccessAsync( - _opts.toTokenAddress === daiTokenAddress - ? new BigNumber(_opts.fromTokenBalance) - : constants.ZERO_AMOUNT, - _opts.toTokenAddress === wethTokenAddress - ? new BigNumber(_opts.fromTokenBalance) - : constants.ZERO_AMOUNT, + // Create the "to" token and exchange. + [[_opts.toTokenAddress]] = await txHelper.getResultAndReceiptAsync( + testContract.createTokenAndExchange, + _opts.toTokenAddress, + _opts.exchangeRevertReason, + { value: new BigNumber(_opts.exchangeFillAmount) }, + ); + await testContract.setTokenRevertReason.awaitTransactionSuccessAsync( + _opts.toTokenAddress, + _opts.toTokenRevertReason, + ); + await testContract.setTokenRevertReason.awaitTransactionSuccessAsync( + _opts.fromTokenAddress, + _opts.fromTokenRevertReason, ); - // Call transfer(). - const [result, { logs }] = await txHelper.getResultAndReceiptAsync( - testContract.transfer, - '0x', + // Set the token balance for the token we're converting from. + await testContract.setTokenBalance.awaitTransactionSuccessAsync(_opts.fromTokenAddress, { + value: new BigNumber(_opts.fromTokenBalance), + }); + // Call withdrawTo(). + const [result, receipt] = await txHelper.getResultAndReceiptAsync( + testContract.withdrawTo, + // The "to" token address. _opts.toTokenAddress, + // The "from" address. randomAddress(), + // The "to" address. _opts.toAddress, + // The amount to transfer to "to" new BigNumber(_opts.amount), + // ABI-encoded "from" token address. + hexLeftPad(_opts.fromTokenAddress), ); - return [result, (logs as any) as DecodedLogs]; + return { + opts: _opts, + result, + logs: receipt.logs, + blockTime: await env.web3Wrapper.getBlockTimestampAsync(receipt.blockNumber), + }; } - function getOppositeToken(tokenAddress: string): string { - if (tokenAddress === daiTokenAddress) { - return wethTokenAddress; - } - return daiTokenAddress; + async function getExchangeForTokenAsync(tokenAddress: string): Promise { + return testContract.getExchange.callAsync(tokenAddress); } it('returns magic bytes on success', async () => { - const BRIDGE_SUCCESS_RETURN_DATA = '0xb5d40d78'; - const [result] = await transferAsync(); - expect(result).to.eq(BRIDGE_SUCCESS_RETURN_DATA); + const { result } = await withdrawToAsync(); + expect(result).to.eq(AssetProxyId.ERC20Bridge); }); - it('calls `Uniswap.sellAllAmount()`', async () => { - const opts = createTransferOpts(); - const [, logs] = await transferAsync(opts); - const transfers = filterLogsToArguments( - logs, - TestUniswapBridgeEvents.SellAllAmount, + it('just transfers tokens to `to` if the same tokens are in play', async () => { + const [[tokenAddress]] = await txHelper.getResultAndReceiptAsync( + testContract.createTokenAndExchange, + constants.NULL_ADDRESS, + '', ); + const { opts, result, logs } = await withdrawToAsync({ + fromTokenAddress: tokenAddress, + toTokenAddress: tokenAddress, + }); + expect(result).to.eq(AssetProxyId.ERC20Bridge); + const transfers = filterLogsToArguments(logs, ContractEvents.TokenTransfer); expect(transfers.length).to.eq(1); - expect(transfers[0].sellToken).to.eq(getOppositeToken(opts.toTokenAddress)); - expect(transfers[0].buyToken).to.eq(opts.toTokenAddress); - expect(transfers[0].sellTokenAmount).to.bignumber.eq(opts.fromTokenBalance); - expect(transfers[0].minimumFillAmount).to.bignumber.eq(opts.amount); + expect(transfers[0].token).to.eq(tokenAddress); + expect(transfers[0].from).to.eq(testContract.address); + expect(transfers[0].to).to.eq(opts.toAddress); + expect(transfers[0].amount).to.bignumber.eq(opts.amount); }); - it('can swap DAI for WETH', async () => { - const opts = createTransferOpts({ toTokenAddress: wethTokenAddress }); - const [, logs] = await transferAsync(opts); - const transfers = filterLogsToArguments( - logs, - TestUniswapBridgeEvents.SellAllAmount, - ); - expect(transfers.length).to.eq(1); - expect(transfers[0].sellToken).to.eq(daiTokenAddress); - expect(transfers[0].buyToken).to.eq(wethTokenAddress); - }); + describe('token -> token', () => { + it('calls `IUniswapExchange.tokenToTokenTransferInput()', async () => { + const { opts, logs, blockTime } = await withdrawToAsync(); + const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); + const calls = filterLogsToArguments( + logs, + ContractEvents.TokenToTokenTransferInput, + ); + expect(calls.length).to.eq(1); + expect(calls[0].exchange).to.eq(exchangeAddress); + expect(calls[0].tokensSold).to.bignumber.eq(opts.fromTokenBalance); + expect(calls[0].minTokensBought).to.bignumber.eq(0); + expect(calls[0].minEthBought).to.bignumber.eq(0); + expect(calls[0].deadline).to.bignumber.eq(blockTime); + expect(calls[0].recipient).to.eq(opts.toAddress); + expect(calls[0].toTokenAddress).to.eq(opts.toTokenAddress); + }); - it('can swap WETH for DAI', async () => { - const opts = createTransferOpts({ toTokenAddress: daiTokenAddress }); - const [, logs] = await transferAsync(opts); - const transfers = filterLogsToArguments( - logs, - TestUniswapBridgeEvents.SellAllAmount, - ); - expect(transfers.length).to.eq(1); - expect(transfers[0].sellToken).to.eq(wethTokenAddress); - expect(transfers[0].buyToken).to.eq(daiTokenAddress); + it('sets allowance for "from" token', async () => { + const { opts, logs } = await withdrawToAsync(); + const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); + const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); + expect(transfers.length).to.eq(1); + expect(transfers[0].spender).to.eq(exchangeAddress); + expect(transfers[0].allowance).to.bignumber.eq(constants.MAX_UINT256); + }); + + it('sets allowance for "from" token only once', async () => { + const { opts } = await withdrawToAsync(); + const { logs } = await withdrawToAsync(opts); + const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); + expect(transfers.length).to.eq(0); + }); + + it('fails if "from" token does not exist', async () => { + const tx = testContract.withdrawTo.awaitTransactionSuccessAsync( + randomAddress(), + randomAddress(), + randomAddress(), + getRandomInteger(1, 1e18), + hexLeftPad(randomAddress()), + ); + return expect(tx).to.revertWith('NO_UNISWAP_EXCHANGE_FOR_TOKEN'); + }); + + it('fails if the exchange fails', async () => { + const revertReason = 'FOOBAR'; + const tx = withdrawToAsync({ + exchangeRevertReason: revertReason, + }); + return expect(tx).to.revertWith(revertReason); + }); }); - it('transfers filled amount to `to`', async () => { - const opts = createTransferOpts(); - const [, logs] = await transferAsync(opts); - const transfers = filterLogsToArguments( - logs, - TestUniswapBridgeEvents.TokenTransfer, - ); - expect(transfers.length).to.eq(1); - expect(transfers[0].token).to.eq(opts.toTokenAddress); - expect(transfers[0].from).to.eq(testContract.address); - expect(transfers[0].to).to.eq(opts.toAddress); - expect(transfers[0].amount).to.bignumber.eq(opts.fillAmount); + describe('token -> ETH', () => { + it('calls `IUniswapExchange.tokenToEthSwapInput()`, `WETH.deposit()`, then `transfer()`', async () => { + const { opts, logs, blockTime } = await withdrawToAsync({ + toTokenAddress: wethTokenAddress, + }); + const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); + let calls: any = filterLogs(logs, ContractEvents.TokenToEthSwapInput); + expect(calls.length).to.eq(1); + expect(calls[0].args.exchange).to.eq(exchangeAddress); + expect(calls[0].args.tokensSold).to.bignumber.eq(opts.fromTokenBalance); + expect(calls[0].args.minEthBought).to.bignumber.eq(0); + expect(calls[0].args.deadline).to.bignumber.eq(blockTime); + calls = filterLogs( + logs.slice(calls[0].logIndex as number), + ContractEvents.WethDeposit, + ); + expect(calls.length).to.eq(1); + expect(calls[0].args.amount).to.bignumber.eq(opts.exchangeFillAmount); + calls = filterLogs( + logs.slice(calls[0].logIndex as number), + ContractEvents.TokenTransfer, + ); + expect(calls.length).to.eq(1); + expect(calls[0].args.token).to.eq(opts.toTokenAddress); + expect(calls[0].args.from).to.eq(testContract.address); + expect(calls[0].args.to).to.eq(opts.toAddress); + expect(calls[0].args.amount).to.bignumber.eq(opts.exchangeFillAmount); + }); + + it('calls `IUniswapExchange.tokenToEthSwapInput()`', async () => { + const { opts, logs, blockTime } = await withdrawToAsync({ + toTokenAddress: wethTokenAddress, + }); + const calls = filterLogsToArguments(logs, ContractEvents.TokenToEthSwapInput); + const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); + expect(calls.length).to.eq(1); + expect(calls[0].exchange).to.eq(exchangeAddress); + expect(calls[0].tokensSold).to.bignumber.eq(opts.fromTokenBalance); + expect(calls[0].minEthBought).to.bignumber.eq(0); + expect(calls[0].deadline).to.bignumber.eq(blockTime); + }); + + it('sets allowance for "from" token', async () => { + const { opts, logs } = await withdrawToAsync({ + toTokenAddress: wethTokenAddress, + }); + const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); + const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); + expect(transfers.length).to.eq(1); + expect(transfers[0].spender).to.eq(exchangeAddress); + expect(transfers[0].allowance).to.bignumber.eq(constants.MAX_UINT256); + }); + + it('sets allowance for "from" token only once', async () => { + const { opts } = await withdrawToAsync({ + toTokenAddress: wethTokenAddress, + }); + const { logs } = await withdrawToAsync(opts); + const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); + expect(transfers.length).to.eq(0); + }); + + it('fails if "from" token does not exist', async () => { + const tx = testContract.withdrawTo.awaitTransactionSuccessAsync( + randomAddress(), + randomAddress(), + randomAddress(), + getRandomInteger(1, 1e18), + hexLeftPad(wethTokenAddress), + ); + return expect(tx).to.revertWith('NO_UNISWAP_EXCHANGE_FOR_TOKEN'); + }); + + it('fails if `WETH.deposit()` fails', async () => { + const revertReason = 'FOOBAR'; + const tx = withdrawToAsync({ + toTokenAddress: wethTokenAddress, + toTokenRevertReason: revertReason, + }); + return expect(tx).to.revertWith(revertReason); + }); + + it('fails if the exchange fails', async () => { + const revertReason = 'FOOBAR'; + const tx = withdrawToAsync({ + toTokenAddress: wethTokenAddress, + exchangeRevertReason: revertReason, + }); + return expect(tx).to.revertWith(revertReason); + }); }); - it('fails if `Uniswap.sellAllAmount()` reverts', async () => { - const opts = createTransferOpts({ revertReason: 'FOOBAR' }); - const tx = transferAsync(opts); - return expect(tx).to.revertWith(opts.revertReason); + describe('ETH -> token', () => { + it('calls `WETH.withdraw()`, then `IUniswapExchange.ethToTokenTransferInput()`', async () => { + const { opts, logs, blockTime } = await withdrawToAsync({ + fromTokenAddress: wethTokenAddress, + }); + const exchangeAddress = await getExchangeForTokenAsync(opts.toTokenAddress); + let calls: any = filterLogs(logs, ContractEvents.WethWithdraw); + expect(calls.length).to.eq(1); + expect(calls[0].args.amount).to.bignumber.eq(opts.fromTokenBalance); + calls = filterLogs( + logs.slice(calls[0].logIndex as number), + ContractEvents.EthToTokenTransferInput, + ); + expect(calls.length).to.eq(1); + expect(calls[0].args.exchange).to.eq(exchangeAddress); + expect(calls[0].args.minTokensBought).to.bignumber.eq(0); + expect(calls[0].args.deadline).to.bignumber.eq(blockTime); + expect(calls[0].args.recipient).to.eq(opts.toAddress); + }); + + it('sets allowance for "to" token', async () => { + const { opts, logs } = await withdrawToAsync({ + fromTokenAddress: wethTokenAddress, + }); + const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); + const exchangeAddress = await getExchangeForTokenAsync(opts.toTokenAddress); + expect(transfers.length).to.eq(1); + expect(transfers[0].spender).to.eq(exchangeAddress); + expect(transfers[0].allowance).to.bignumber.eq(constants.MAX_UINT256); + }); + + it('sets allowance for "from" token only', async () => { + const { opts } = await withdrawToAsync({ + fromTokenAddress: wethTokenAddress, + }); + const { logs } = await withdrawToAsync(opts); + const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); + expect(transfers.length).to.eq(0); + }); + + it('fails if "to" token does not exist', async () => { + const tx = testContract.withdrawTo.awaitTransactionSuccessAsync( + wethTokenAddress, + randomAddress(), + randomAddress(), + getRandomInteger(1, 1e18), + hexLeftPad(randomAddress()), + ); + return expect(tx).to.revertWith('NO_UNISWAP_EXCHANGE_FOR_TOKEN'); + }); + + it('fails if the `WETH.withdraw()` fails', async () => { + const revertReason = 'FOOBAR'; + const tx = withdrawToAsync({ + fromTokenAddress: wethTokenAddress, + fromTokenRevertReason: revertReason, + }); + return expect(tx).to.revertWith(revertReason); + }); + + it('fails if the exchange fails', async () => { + const revertReason = 'FOOBAR'; + const tx = withdrawToAsync({ + fromTokenAddress: wethTokenAddress, + exchangeRevertReason: revertReason, + }); + return expect(tx).to.revertWith(revertReason); + }); }); }); }); From 2593f1ff30c5b6e2e8a060e57b9edb662de907b4 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Tue, 1 Oct 2019 18:22:57 -0700 Subject: [PATCH 14/87] `@0x/contracts-asset-proxy`: Update CHANGELOG. --- contracts/asset-proxy/CHANGELOG.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contracts/asset-proxy/CHANGELOG.json b/contracts/asset-proxy/CHANGELOG.json index d9d6329dc4..e51f943a2b 100644 --- a/contracts/asset-proxy/CHANGELOG.json +++ b/contracts/asset-proxy/CHANGELOG.json @@ -25,6 +25,10 @@ { "note": "Add `Eth2DaiBridge`", "pr": 2221 + }, + { + "note": "Add `UniswapBridge`", + "pr": 2233 } ], "timestamp": 1570135330 From 95e461072f2b2b9b05eb60a6a9d5c8976dc32131 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Tue, 1 Oct 2019 18:32:41 -0700 Subject: [PATCH 15/87] `@0x/contracts-asset-proxy`: Always set allowance. --- .../contracts/src/bridges/UniswapBridge.sol | 10 +-- contracts/asset-proxy/test/uniswap_bridge.ts | 74 +++++++++---------- 2 files changed, 39 insertions(+), 45 deletions(-) diff --git a/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol index f1a55d9faf..8d01628d04 100644 --- a/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol +++ b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol @@ -52,9 +52,6 @@ contract UniswapBridge is payable {} - /// @dev Whether we've granted an allowance to the exchange for a token. - mapping (address => bool) private _hasAllowance; - /// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of /// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress` /// token encoded in the bridge data. @@ -184,16 +181,13 @@ contract UniswapBridge is } /// @dev Grants an unlimited allowance to the exchange for its token - /// on behalf of this contract, if we haven't already done so. + /// on behalf of this contract. /// @param exchange The Uniswap token exchange. function _grantExchangeAllowance(IUniswapExchange exchange) private { address tokenAddress = exchange.toTokenAddress(); - if (!_hasAllowance[tokenAddress]) { - IERC20Token(tokenAddress).approve(address(exchange), uint256(-1)); - _hasAllowance[tokenAddress] = true; - } + IERC20Token(tokenAddress).approve(address(exchange), uint256(-1)); } /// @dev Retrieves the uniswap exchange contract for a given token pair. diff --git a/contracts/asset-proxy/test/uniswap_bridge.ts b/contracts/asset-proxy/test/uniswap_bridge.ts index d2dd2de3d6..558d8ed10a 100644 --- a/contracts/asset-proxy/test/uniswap_bridge.ts +++ b/contracts/asset-proxy/test/uniswap_bridge.ts @@ -47,7 +47,10 @@ blockchainTests.resets.only('UniswapBridge unit tests', env => { describe('isValidSignature()', () => { it('returns success bytes', async () => { const LEGACY_WALLET_MAGIC_VALUE = '0xb0671381'; - const result = await testContract.isValidSignature.callAsync(hexRandom(), hexRandom(_.random(0, 32))); + const result = await testContract.isValidSignature.callAsync( + hexRandom(), + hexRandom(_.random(0, 32)), + ); expect(result).to.eq(LEGACY_WALLET_MAGIC_VALUE); }); }); @@ -112,9 +115,10 @@ blockchainTests.resets.only('UniswapBridge unit tests', env => { _opts.fromTokenRevertReason, ); // Set the token balance for the token we're converting from. - await testContract.setTokenBalance.awaitTransactionSuccessAsync(_opts.fromTokenAddress, { - value: new BigNumber(_opts.fromTokenBalance), - }); + await testContract.setTokenBalance.awaitTransactionSuccessAsync( + _opts.fromTokenAddress, + { value: new BigNumber(_opts.fromTokenBalance) }, + ); // Call withdrawTo(). const [result, receipt] = await txHelper.getResultAndReceiptAsync( testContract.withdrawTo, @@ -132,7 +136,7 @@ blockchainTests.resets.only('UniswapBridge unit tests', env => { return { opts: _opts, result, - logs: receipt.logs, + logs: receipt.logs as any as DecodedLogs, blockTime: await env.web3Wrapper.getBlockTimestampAsync(receipt.blockNumber), }; } @@ -157,7 +161,10 @@ blockchainTests.resets.only('UniswapBridge unit tests', env => { toTokenAddress: tokenAddress, }); expect(result).to.eq(AssetProxyId.ERC20Bridge); - const transfers = filterLogsToArguments(logs, ContractEvents.TokenTransfer); + const transfers = filterLogsToArguments( + logs, + ContractEvents.TokenTransfer, + ); expect(transfers.length).to.eq(1); expect(transfers[0].token).to.eq(tokenAddress); expect(transfers[0].from).to.eq(testContract.address); @@ -185,20 +192,16 @@ blockchainTests.resets.only('UniswapBridge unit tests', env => { it('sets allowance for "from" token', async () => { const { opts, logs } = await withdrawToAsync(); - const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); + const transfers = filterLogsToArguments( + logs, + ContractEvents.TokenApprove, + ); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); expect(transfers.length).to.eq(1); expect(transfers[0].spender).to.eq(exchangeAddress); expect(transfers[0].allowance).to.bignumber.eq(constants.MAX_UINT256); }); - it('sets allowance for "from" token only once', async () => { - const { opts } = await withdrawToAsync(); - const { logs } = await withdrawToAsync(opts); - const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); - expect(transfers.length).to.eq(0); - }); - it('fails if "from" token does not exist', async () => { const tx = testContract.withdrawTo.awaitTransactionSuccessAsync( randomAddress(), @@ -225,7 +228,10 @@ blockchainTests.resets.only('UniswapBridge unit tests', env => { toTokenAddress: wethTokenAddress, }); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); - let calls: any = filterLogs(logs, ContractEvents.TokenToEthSwapInput); + let calls: any = filterLogs( + logs, + ContractEvents.TokenToEthSwapInput, + ); expect(calls.length).to.eq(1); expect(calls[0].args.exchange).to.eq(exchangeAddress); expect(calls[0].args.tokensSold).to.bignumber.eq(opts.fromTokenBalance); @@ -252,7 +258,10 @@ blockchainTests.resets.only('UniswapBridge unit tests', env => { const { opts, logs, blockTime } = await withdrawToAsync({ toTokenAddress: wethTokenAddress, }); - const calls = filterLogsToArguments(logs, ContractEvents.TokenToEthSwapInput); + const calls = filterLogsToArguments( + logs, + ContractEvents.TokenToEthSwapInput, + ); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); expect(calls.length).to.eq(1); expect(calls[0].exchange).to.eq(exchangeAddress); @@ -265,22 +274,16 @@ blockchainTests.resets.only('UniswapBridge unit tests', env => { const { opts, logs } = await withdrawToAsync({ toTokenAddress: wethTokenAddress, }); - const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); + const transfers = filterLogsToArguments( + logs, + ContractEvents.TokenApprove, + ); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); expect(transfers.length).to.eq(1); expect(transfers[0].spender).to.eq(exchangeAddress); expect(transfers[0].allowance).to.bignumber.eq(constants.MAX_UINT256); }); - it('sets allowance for "from" token only once', async () => { - const { opts } = await withdrawToAsync({ - toTokenAddress: wethTokenAddress, - }); - const { logs } = await withdrawToAsync(opts); - const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); - expect(transfers.length).to.eq(0); - }); - it('fails if "from" token does not exist', async () => { const tx = testContract.withdrawTo.awaitTransactionSuccessAsync( randomAddress(), @@ -317,7 +320,10 @@ blockchainTests.resets.only('UniswapBridge unit tests', env => { fromTokenAddress: wethTokenAddress, }); const exchangeAddress = await getExchangeForTokenAsync(opts.toTokenAddress); - let calls: any = filterLogs(logs, ContractEvents.WethWithdraw); + let calls: any = filterLogs( + logs, + ContractEvents.WethWithdraw, + ); expect(calls.length).to.eq(1); expect(calls[0].args.amount).to.bignumber.eq(opts.fromTokenBalance); calls = filterLogs( @@ -335,22 +341,16 @@ blockchainTests.resets.only('UniswapBridge unit tests', env => { const { opts, logs } = await withdrawToAsync({ fromTokenAddress: wethTokenAddress, }); - const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); + const transfers = filterLogsToArguments( + logs, + ContractEvents.TokenApprove, + ); const exchangeAddress = await getExchangeForTokenAsync(opts.toTokenAddress); expect(transfers.length).to.eq(1); expect(transfers[0].spender).to.eq(exchangeAddress); expect(transfers[0].allowance).to.bignumber.eq(constants.MAX_UINT256); }); - it('sets allowance for "from" token only', async () => { - const { opts } = await withdrawToAsync({ - fromTokenAddress: wethTokenAddress, - }); - const { logs } = await withdrawToAsync(opts); - const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); - expect(transfers.length).to.eq(0); - }); - it('fails if "to" token does not exist', async () => { const tx = testContract.withdrawTo.awaitTransactionSuccessAsync( wethTokenAddress, From ab70c4df743e9c0ec66c45b36f49d412cfe336bf Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Tue, 1 Oct 2019 18:36:13 -0700 Subject: [PATCH 16/87] `@0x/contracts-asset-proxy`: Remove `only` modifier on tests. --- contracts/asset-proxy/test/uniswap_bridge.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/asset-proxy/test/uniswap_bridge.ts b/contracts/asset-proxy/test/uniswap_bridge.ts index 558d8ed10a..7e73f2f6f1 100644 --- a/contracts/asset-proxy/test/uniswap_bridge.ts +++ b/contracts/asset-proxy/test/uniswap_bridge.ts @@ -29,7 +29,7 @@ import { TestUniswapBridgeWethWithdrawEventArgs as WethWithdrawArgs, } from '../src'; -blockchainTests.resets.only('UniswapBridge unit tests', env => { +blockchainTests.resets('UniswapBridge unit tests', env => { const txHelper = new TransactionHelper(env.web3Wrapper, artifacts); let testContract: TestUniswapBridgeContract; let wethTokenAddress: string; From 80cb6b654bef71e580721679432f70460cb457c6 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Tue, 1 Oct 2019 19:10:26 -0700 Subject: [PATCH 17/87] `@0x/contracts-asset-proxy`: Fix linter errors. --- contracts/asset-proxy/test/uniswap_bridge.ts | 49 +++++--------------- 1 file changed, 12 insertions(+), 37 deletions(-) diff --git a/contracts/asset-proxy/test/uniswap_bridge.ts b/contracts/asset-proxy/test/uniswap_bridge.ts index 7e73f2f6f1..246f5bd8f0 100644 --- a/contracts/asset-proxy/test/uniswap_bridge.ts +++ b/contracts/asset-proxy/test/uniswap_bridge.ts @@ -47,10 +47,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { describe('isValidSignature()', () => { it('returns success bytes', async () => { const LEGACY_WALLET_MAGIC_VALUE = '0xb0671381'; - const result = await testContract.isValidSignature.callAsync( - hexRandom(), - hexRandom(_.random(0, 32)), - ); + const result = await testContract.isValidSignature.callAsync(hexRandom(), hexRandom(_.random(0, 32))); expect(result).to.eq(LEGACY_WALLET_MAGIC_VALUE); }); }); @@ -115,10 +112,9 @@ blockchainTests.resets('UniswapBridge unit tests', env => { _opts.fromTokenRevertReason, ); // Set the token balance for the token we're converting from. - await testContract.setTokenBalance.awaitTransactionSuccessAsync( - _opts.fromTokenAddress, - { value: new BigNumber(_opts.fromTokenBalance) }, - ); + await testContract.setTokenBalance.awaitTransactionSuccessAsync(_opts.fromTokenAddress, { + value: new BigNumber(_opts.fromTokenBalance), + }); // Call withdrawTo(). const [result, receipt] = await txHelper.getResultAndReceiptAsync( testContract.withdrawTo, @@ -136,7 +132,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { return { opts: _opts, result, - logs: receipt.logs as any as DecodedLogs, + logs: (receipt.logs as any) as DecodedLogs, blockTime: await env.web3Wrapper.getBlockTimestampAsync(receipt.blockNumber), }; } @@ -161,10 +157,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { toTokenAddress: tokenAddress, }); expect(result).to.eq(AssetProxyId.ERC20Bridge); - const transfers = filterLogsToArguments( - logs, - ContractEvents.TokenTransfer, - ); + const transfers = filterLogsToArguments(logs, ContractEvents.TokenTransfer); expect(transfers.length).to.eq(1); expect(transfers[0].token).to.eq(tokenAddress); expect(transfers[0].from).to.eq(testContract.address); @@ -192,10 +185,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { it('sets allowance for "from" token', async () => { const { opts, logs } = await withdrawToAsync(); - const transfers = filterLogsToArguments( - logs, - ContractEvents.TokenApprove, - ); + const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); expect(transfers.length).to.eq(1); expect(transfers[0].spender).to.eq(exchangeAddress); @@ -228,10 +218,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { toTokenAddress: wethTokenAddress, }); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); - let calls: any = filterLogs( - logs, - ContractEvents.TokenToEthSwapInput, - ); + let calls: any = filterLogs(logs, ContractEvents.TokenToEthSwapInput); expect(calls.length).to.eq(1); expect(calls[0].args.exchange).to.eq(exchangeAddress); expect(calls[0].args.tokensSold).to.bignumber.eq(opts.fromTokenBalance); @@ -258,10 +245,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { const { opts, logs, blockTime } = await withdrawToAsync({ toTokenAddress: wethTokenAddress, }); - const calls = filterLogsToArguments( - logs, - ContractEvents.TokenToEthSwapInput, - ); + const calls = filterLogsToArguments(logs, ContractEvents.TokenToEthSwapInput); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); expect(calls.length).to.eq(1); expect(calls[0].exchange).to.eq(exchangeAddress); @@ -274,10 +258,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { const { opts, logs } = await withdrawToAsync({ toTokenAddress: wethTokenAddress, }); - const transfers = filterLogsToArguments( - logs, - ContractEvents.TokenApprove, - ); + const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); expect(transfers.length).to.eq(1); expect(transfers[0].spender).to.eq(exchangeAddress); @@ -320,10 +301,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { fromTokenAddress: wethTokenAddress, }); const exchangeAddress = await getExchangeForTokenAsync(opts.toTokenAddress); - let calls: any = filterLogs( - logs, - ContractEvents.WethWithdraw, - ); + let calls: any = filterLogs(logs, ContractEvents.WethWithdraw); expect(calls.length).to.eq(1); expect(calls[0].args.amount).to.bignumber.eq(opts.fromTokenBalance); calls = filterLogs( @@ -341,10 +319,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { const { opts, logs } = await withdrawToAsync({ fromTokenAddress: wethTokenAddress, }); - const transfers = filterLogsToArguments( - logs, - ContractEvents.TokenApprove, - ); + const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); const exchangeAddress = await getExchangeForTokenAsync(opts.toTokenAddress); expect(transfers.length).to.eq(1); expect(transfers[0].spender).to.eq(exchangeAddress); From 3840ebf538681d0e9810c493d5e9b1082e9d784e Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Thu, 3 Oct 2019 10:06:34 -0700 Subject: [PATCH 18/87] `@0x/contracts-exchange`: Move `IWallet.sol` to `exchange-libs`. --- contracts/exchange/CHANGELOG.json | 4 ++ .../contracts/src/MixinSignatureValidator.sol | 6 +-- .../src/interfaces/IProtocolFees.sol | 1 + .../contracts/src/interfaces/IWallet.sol | 38 ------------------- contracts/exchange/package.json | 2 +- contracts/exchange/src/artifacts.ts | 2 - contracts/exchange/src/wrappers.ts | 1 - contracts/exchange/tsconfig.json | 1 - 8 files changed, 9 insertions(+), 46 deletions(-) delete mode 100644 contracts/exchange/contracts/src/interfaces/IWallet.sol diff --git a/contracts/exchange/CHANGELOG.json b/contracts/exchange/CHANGELOG.json index 741ff3f973..676f003e6b 100644 --- a/contracts/exchange/CHANGELOG.json +++ b/contracts/exchange/CHANGELOG.json @@ -189,6 +189,10 @@ { "note": "Overridden functions in `ReentrancyTester` now return sane values.", "pr": 2075 + }, + { + "note": "Move `IWallet.sol` to `exchange-libs`.", + "pr": 2233 } ], "timestamp": 1570135330 diff --git a/contracts/exchange/contracts/src/MixinSignatureValidator.sol b/contracts/exchange/contracts/src/MixinSignatureValidator.sol index f961f1aedf..d84d7b8ab5 100644 --- a/contracts/exchange/contracts/src/MixinSignatureValidator.sol +++ b/contracts/exchange/contracts/src/MixinSignatureValidator.sol @@ -27,7 +27,7 @@ import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomain.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibExchangeRichErrors.sol"; -import "./interfaces/IWallet.sol"; +import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol"; import "./interfaces/IEIP1271Wallet.sol"; import "./interfaces/ISignatureValidator.sol"; import "./interfaces/IEIP1271Data.sol"; @@ -465,7 +465,7 @@ contract MixinSignatureValidator is return signatureType; } - /// @dev ABI encodes an order and hash with a selector to be passed into + /// @dev ABI encodes an order and hash with a selector to be passed into /// an EIP1271 compliant `isValidSignature` function. function _encodeEIP1271OrderWithHash( LibOrder.Order memory order, @@ -482,7 +482,7 @@ contract MixinSignatureValidator is ); } - /// @dev ABI encodes a transaction and hash with a selector to be passed into + /// @dev ABI encodes a transaction and hash with a selector to be passed into /// an EIP1271 compliant `isValidSignature` function. function _encodeEIP1271TransactionWithHash( LibZeroExTransaction.ZeroExTransaction memory transaction, diff --git a/contracts/exchange/contracts/src/interfaces/IProtocolFees.sol b/contracts/exchange/contracts/src/interfaces/IProtocolFees.sol index cd0e570c2f..8e60a9b5f5 100644 --- a/contracts/exchange/contracts/src/interfaces/IProtocolFees.sol +++ b/contracts/exchange/contracts/src/interfaces/IProtocolFees.sol @@ -19,6 +19,7 @@ pragma solidity ^0.5.9; +// solhint-disable no-simple-event-func-name contract IProtocolFees { // Logs updates to the protocol fee multiplier. diff --git a/contracts/exchange/contracts/src/interfaces/IWallet.sol b/contracts/exchange/contracts/src/interfaces/IWallet.sol deleted file mode 100644 index 50a58d0e5e..0000000000 --- a/contracts/exchange/contracts/src/interfaces/IWallet.sol +++ /dev/null @@ -1,38 +0,0 @@ -/* - - Copyright 2019 ZeroEx Intl. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pragma solidity ^0.5.9; -pragma experimental ABIEncoderV2; - -import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; - - -contract IWallet { - - /// @dev Validates a hash with the `Wallet` signature type. - /// @param hash Message hash that is signed. - /// @param signature Proof of signing. - /// @return magicValue `bytes4(0xb0671381)` if the signature check succeeds. - function isValidSignature( - bytes32 hash, - bytes calldata signature - ) - external - view - returns (bytes4 magicValue); -} diff --git a/contracts/exchange/package.json b/contracts/exchange/package.json index c8199af93e..8f2ca64a0f 100644 --- a/contracts/exchange/package.json +++ b/contracts/exchange/package.json @@ -35,7 +35,7 @@ "compile:truffle": "truffle compile" }, "config": { - "abis": "./generated-artifacts/@(Exchange|IAssetProxy|IAssetProxyDispatcher|IEIP1271Data|IEIP1271Wallet|IExchange|IExchangeCore|IMatchOrders|IProtocolFees|ISignatureValidator|ITransactions|ITransferSimulator|IWallet|IWrapperFunctions|IsolatedExchange|LibExchangeRichErrorDecoder|MixinAssetProxyDispatcher|MixinExchangeCore|MixinMatchOrders|MixinProtocolFees|MixinSignatureValidator|MixinTransactions|MixinTransferSimulator|MixinWrapperFunctions|ReentrancyTester|TestAssetProxyDispatcher|TestExchangeInternals|TestLibExchangeRichErrorDecoder|TestProtocolFees|TestProtocolFeesReceiver|TestSignatureValidator|TestTransactions|TestValidatorWallet|TestWrapperFunctions).json", + "abis": "./generated-artifacts/@(Exchange|IAssetProxy|IAssetProxyDispatcher|IEIP1271Data|IEIP1271Wallet|IExchange|IExchangeCore|IMatchOrders|IProtocolFees|ISignatureValidator|ITransactions|ITransferSimulator|IWrapperFunctions|IsolatedExchange|LibExchangeRichErrorDecoder|MixinAssetProxyDispatcher|MixinExchangeCore|MixinMatchOrders|MixinProtocolFees|MixinSignatureValidator|MixinTransactions|MixinTransferSimulator|MixinWrapperFunctions|ReentrancyTester|TestAssetProxyDispatcher|TestExchangeInternals|TestLibExchangeRichErrorDecoder|TestProtocolFees|TestProtocolFeesReceiver|TestSignatureValidator|TestTransactions|TestValidatorWallet|TestWrapperFunctions).json", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually." }, "repository": { diff --git a/contracts/exchange/src/artifacts.ts b/contracts/exchange/src/artifacts.ts index 15a1d88233..afe062ebda 100644 --- a/contracts/exchange/src/artifacts.ts +++ b/contracts/exchange/src/artifacts.ts @@ -18,7 +18,6 @@ import * as ISignatureValidator from '../generated-artifacts/ISignatureValidator import * as IsolatedExchange from '../generated-artifacts/IsolatedExchange.json'; import * as ITransactions from '../generated-artifacts/ITransactions.json'; import * as ITransferSimulator from '../generated-artifacts/ITransferSimulator.json'; -import * as IWallet from '../generated-artifacts/IWallet.json'; import * as IWrapperFunctions from '../generated-artifacts/IWrapperFunctions.json'; import * as LibExchangeRichErrorDecoder from '../generated-artifacts/LibExchangeRichErrorDecoder.json'; import * as MixinAssetProxyDispatcher from '../generated-artifacts/MixinAssetProxyDispatcher.json'; @@ -60,7 +59,6 @@ export const artifacts = { ISignatureValidator: ISignatureValidator as ContractArtifact, ITransactions: ITransactions as ContractArtifact, ITransferSimulator: ITransferSimulator as ContractArtifact, - IWallet: IWallet as ContractArtifact, IWrapperFunctions: IWrapperFunctions as ContractArtifact, LibExchangeRichErrorDecoder: LibExchangeRichErrorDecoder as ContractArtifact, IsolatedExchange: IsolatedExchange as ContractArtifact, diff --git a/contracts/exchange/src/wrappers.ts b/contracts/exchange/src/wrappers.ts index f5d76edb4d..fe85e934e7 100644 --- a/contracts/exchange/src/wrappers.ts +++ b/contracts/exchange/src/wrappers.ts @@ -15,7 +15,6 @@ export * from '../generated-wrappers/i_protocol_fees'; export * from '../generated-wrappers/i_signature_validator'; export * from '../generated-wrappers/i_transactions'; export * from '../generated-wrappers/i_transfer_simulator'; -export * from '../generated-wrappers/i_wallet'; export * from '../generated-wrappers/i_wrapper_functions'; export * from '../generated-wrappers/isolated_exchange'; export * from '../generated-wrappers/lib_exchange_rich_error_decoder'; diff --git a/contracts/exchange/tsconfig.json b/contracts/exchange/tsconfig.json index 6783d6851e..797be7016d 100644 --- a/contracts/exchange/tsconfig.json +++ b/contracts/exchange/tsconfig.json @@ -15,7 +15,6 @@ "generated-artifacts/ISignatureValidator.json", "generated-artifacts/ITransactions.json", "generated-artifacts/ITransferSimulator.json", - "generated-artifacts/IWallet.json", "generated-artifacts/IWrapperFunctions.json", "generated-artifacts/IsolatedExchange.json", "generated-artifacts/LibExchangeRichErrorDecoder.json", From cf2053ec771da987f11a5bda19f4aa0490eedf31 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Thu, 3 Oct 2019 10:08:03 -0700 Subject: [PATCH 19/87] `@0x/contracts-exchange-libs`: Move `IWallet` from `asset-proxy` and `exchange` packages into this package. --- contracts/exchange-libs/CHANGELOG.json | 4 ++ .../exchange-libs/contracts/src/IWallet.sol | 38 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 contracts/exchange-libs/contracts/src/IWallet.sol diff --git a/contracts/exchange-libs/CHANGELOG.json b/contracts/exchange-libs/CHANGELOG.json index 9fd46bc262..4059813c1e 100644 --- a/contracts/exchange-libs/CHANGELOG.json +++ b/contracts/exchange-libs/CHANGELOG.json @@ -105,6 +105,10 @@ { "note": "Update `IncompleteFillError` to take an `errorCode`, `expectedAssetFillAmount`, and `actualAssetFillAmount` fields.", "pr": 2075 + }, + { + "note": "Move `IWallet.sol` from `asset-proxy` and `exchange` packages to here.", + "pr": 2233 } ], "timestamp": 1570135330 diff --git a/contracts/exchange-libs/contracts/src/IWallet.sol b/contracts/exchange-libs/contracts/src/IWallet.sol new file mode 100644 index 0000000000..2bb323e578 --- /dev/null +++ b/contracts/exchange-libs/contracts/src/IWallet.sol @@ -0,0 +1,38 @@ +/* + + Copyright 2019 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.5.9; +pragma experimental ABIEncoderV2; + + +contract IWallet { + + bytes4 internal constant LEGACY_WALLET_MAGIC_VALUE = 0xb0671381; + + /// @dev Validates a hash with the `Wallet` signature type. + /// @param hash Message hash that is signed. + /// @param signature Proof of signing. + /// @return magicValue `bytes4(0xb0671381)` if the signature check succeeds. + function isValidSignature( + bytes32 hash, + bytes calldata signature + ) + external + view + returns (bytes4 magicValue); +} From 035dc607db51eb7131358822aca6f62e8ee3457e Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Thu, 3 Oct 2019 10:16:49 -0700 Subject: [PATCH 20/87] `@0x/contracts-asset-proxy`: Use `IWallet` from `exchange-libs`. `@0x/contracts-asset-proxy`: Fix some comment typos in `UniswapBridge`. `@0x/contracts-asset-proxy`: Add more allowance tests to the `UniswapBridge` tests. --- .../contracts/src/bridges/UniswapBridge.sol | 4 +- .../contracts/src/interfaces/IWallet.sol | 38 ------- contracts/asset-proxy/test/uniswap_bridge.ts | 104 +++++++++++++++--- 3 files changed, 88 insertions(+), 58 deletions(-) delete mode 100644 contracts/asset-proxy/contracts/src/interfaces/IWallet.sol diff --git a/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol index 8d01628d04..ef975a7699 100644 --- a/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol +++ b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol @@ -21,9 +21,9 @@ pragma experimental ABIEncoderV2; import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol"; +import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol"; import "../interfaces/IUniswapExchangeFactory.sol"; import "../interfaces/IUniswapExchange.sol"; -import "../interfaces/IWallet.sol"; import "../interfaces/IERC20Bridge.sol"; @@ -110,7 +110,7 @@ contract UniswapBridge is // Convert from a token to WETH. } else if (toTokenAddress == address(state.weth)) { - // Buy as much ETH with `toTokenAddress` token as possible. + // Buy as much ETH with `fromTokenAddress` token as possible. uint256 ethBought = state.exchange.tokenToEthSwapInput( // Sell all tokens we hold. state.fromTokenBalance, diff --git a/contracts/asset-proxy/contracts/src/interfaces/IWallet.sol b/contracts/asset-proxy/contracts/src/interfaces/IWallet.sol deleted file mode 100644 index 2bb323e578..0000000000 --- a/contracts/asset-proxy/contracts/src/interfaces/IWallet.sol +++ /dev/null @@ -1,38 +0,0 @@ -/* - - Copyright 2019 ZeroEx Intl. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pragma solidity ^0.5.9; -pragma experimental ABIEncoderV2; - - -contract IWallet { - - bytes4 internal constant LEGACY_WALLET_MAGIC_VALUE = 0xb0671381; - - /// @dev Validates a hash with the `Wallet` signature type. - /// @param hash Message hash that is signed. - /// @param signature Proof of signing. - /// @return magicValue `bytes4(0xb0671381)` if the signature check succeeds. - function isValidSignature( - bytes32 hash, - bytes calldata signature - ) - external - view - returns (bytes4 magicValue); -} diff --git a/contracts/asset-proxy/test/uniswap_bridge.ts b/contracts/asset-proxy/test/uniswap_bridge.ts index 246f5bd8f0..b14ab427a8 100644 --- a/contracts/asset-proxy/test/uniswap_bridge.ts +++ b/contracts/asset-proxy/test/uniswap_bridge.ts @@ -47,7 +47,10 @@ blockchainTests.resets('UniswapBridge unit tests', env => { describe('isValidSignature()', () => { it('returns success bytes', async () => { const LEGACY_WALLET_MAGIC_VALUE = '0xb0671381'; - const result = await testContract.isValidSignature.callAsync(hexRandom(), hexRandom(_.random(0, 32))); + const result = await testContract.isValidSignature.callAsync( + hexRandom(), + hexRandom(_.random(0, 32)), + ); expect(result).to.eq(LEGACY_WALLET_MAGIC_VALUE); }); }); @@ -112,9 +115,10 @@ blockchainTests.resets('UniswapBridge unit tests', env => { _opts.fromTokenRevertReason, ); // Set the token balance for the token we're converting from. - await testContract.setTokenBalance.awaitTransactionSuccessAsync(_opts.fromTokenAddress, { - value: new BigNumber(_opts.fromTokenBalance), - }); + await testContract.setTokenBalance.awaitTransactionSuccessAsync( + _opts.fromTokenAddress, + { value: new BigNumber(_opts.fromTokenBalance) }, + ); // Call withdrawTo(). const [result, receipt] = await txHelper.getResultAndReceiptAsync( testContract.withdrawTo, @@ -132,7 +136,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { return { opts: _opts, result, - logs: (receipt.logs as any) as DecodedLogs, + logs: receipt.logs as any as DecodedLogs, blockTime: await env.web3Wrapper.getBlockTimestampAsync(receipt.blockNumber), }; } @@ -157,7 +161,10 @@ blockchainTests.resets('UniswapBridge unit tests', env => { toTokenAddress: tokenAddress, }); expect(result).to.eq(AssetProxyId.ERC20Bridge); - const transfers = filterLogsToArguments(logs, ContractEvents.TokenTransfer); + const transfers = filterLogsToArguments( + logs, + ContractEvents.TokenTransfer, + ); expect(transfers.length).to.eq(1); expect(transfers[0].token).to.eq(tokenAddress); expect(transfers[0].from).to.eq(testContract.address); @@ -185,11 +192,27 @@ blockchainTests.resets('UniswapBridge unit tests', env => { it('sets allowance for "from" token', async () => { const { opts, logs } = await withdrawToAsync(); - const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); + const approvals = filterLogsToArguments( + logs, + ContractEvents.TokenApprove, + ); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); - expect(transfers.length).to.eq(1); - expect(transfers[0].spender).to.eq(exchangeAddress); - expect(transfers[0].allowance).to.bignumber.eq(constants.MAX_UINT256); + expect(approvals.length).to.eq(1); + expect(approvals[0].spender).to.eq(exchangeAddress); + expect(approvals[0].allowance).to.bignumber.eq(constants.MAX_UINT256); + }); + + it('sets allowance for "from" token on subsequent calls', async () => { + const { opts } = await withdrawToAsync(); + const { logs } = await withdrawToAsync(opts); + const approvals = filterLogsToArguments( + logs, + ContractEvents.TokenApprove, + ); + const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); + expect(approvals.length).to.eq(1); + expect(approvals[0].spender).to.eq(exchangeAddress); + expect(approvals[0].allowance).to.bignumber.eq(constants.MAX_UINT256); }); it('fails if "from" token does not exist', async () => { @@ -218,7 +241,10 @@ blockchainTests.resets('UniswapBridge unit tests', env => { toTokenAddress: wethTokenAddress, }); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); - let calls: any = filterLogs(logs, ContractEvents.TokenToEthSwapInput); + let calls: any = filterLogs( + logs, + ContractEvents.TokenToEthSwapInput, + ); expect(calls.length).to.eq(1); expect(calls[0].args.exchange).to.eq(exchangeAddress); expect(calls[0].args.tokensSold).to.bignumber.eq(opts.fromTokenBalance); @@ -245,7 +271,10 @@ blockchainTests.resets('UniswapBridge unit tests', env => { const { opts, logs, blockTime } = await withdrawToAsync({ toTokenAddress: wethTokenAddress, }); - const calls = filterLogsToArguments(logs, ContractEvents.TokenToEthSwapInput); + const calls = filterLogsToArguments( + logs, + ContractEvents.TokenToEthSwapInput, + ); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); expect(calls.length).to.eq(1); expect(calls[0].exchange).to.eq(exchangeAddress); @@ -258,13 +287,31 @@ blockchainTests.resets('UniswapBridge unit tests', env => { const { opts, logs } = await withdrawToAsync({ toTokenAddress: wethTokenAddress, }); - const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); + const transfers = filterLogsToArguments( + logs, + ContractEvents.TokenApprove, + ); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); expect(transfers.length).to.eq(1); expect(transfers[0].spender).to.eq(exchangeAddress); expect(transfers[0].allowance).to.bignumber.eq(constants.MAX_UINT256); }); + it('sets allowance for "from" token on subsequent calls', async () => { + const { opts } = await withdrawToAsync({ + toTokenAddress: wethTokenAddress, + }); + const { logs } = await withdrawToAsync(opts); + const approvals = filterLogsToArguments( + logs, + ContractEvents.TokenApprove, + ); + const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); + expect(approvals.length).to.eq(1); + expect(approvals[0].spender).to.eq(exchangeAddress); + expect(approvals[0].allowance).to.bignumber.eq(constants.MAX_UINT256); + }); + it('fails if "from" token does not exist', async () => { const tx = testContract.withdrawTo.awaitTransactionSuccessAsync( randomAddress(), @@ -301,7 +348,10 @@ blockchainTests.resets('UniswapBridge unit tests', env => { fromTokenAddress: wethTokenAddress, }); const exchangeAddress = await getExchangeForTokenAsync(opts.toTokenAddress); - let calls: any = filterLogs(logs, ContractEvents.WethWithdraw); + let calls: any = filterLogs( + logs, + ContractEvents.WethWithdraw, + ); expect(calls.length).to.eq(1); expect(calls[0].args.amount).to.bignumber.eq(opts.fromTokenBalance); calls = filterLogs( @@ -319,11 +369,29 @@ blockchainTests.resets('UniswapBridge unit tests', env => { const { opts, logs } = await withdrawToAsync({ fromTokenAddress: wethTokenAddress, }); - const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); + const approvals = filterLogsToArguments( + logs, + ContractEvents.TokenApprove, + ); const exchangeAddress = await getExchangeForTokenAsync(opts.toTokenAddress); - expect(transfers.length).to.eq(1); - expect(transfers[0].spender).to.eq(exchangeAddress); - expect(transfers[0].allowance).to.bignumber.eq(constants.MAX_UINT256); + expect(approvals.length).to.eq(1); + expect(approvals[0].spender).to.eq(exchangeAddress); + expect(approvals[0].allowance).to.bignumber.eq(constants.MAX_UINT256); + }); + + it('sets allowance for "to" token on subsequent calls', async () => { + const { opts } = await withdrawToAsync({ + fromTokenAddress: wethTokenAddress, + }); + const { logs } = await withdrawToAsync(opts); + const approvals = filterLogsToArguments( + logs, + ContractEvents.TokenApprove, + ); + const exchangeAddress = await getExchangeForTokenAsync(opts.toTokenAddress); + expect(approvals.length).to.eq(1); + expect(approvals[0].spender).to.eq(exchangeAddress); + expect(approvals[0].allowance).to.bignumber.eq(constants.MAX_UINT256); }); it('fails if "to" token does not exist', async () => { From f993b6d1edfcfb6352c2edc2569c7c5892afb0e5 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Thu, 3 Oct 2019 10:21:24 -0700 Subject: [PATCH 21/87] `@0x/contracts-exchange`: Revert changes to `IWallet`. --- contracts/exchange/CHANGELOG.json | 4 -- .../contracts/src/MixinSignatureValidator.sol | 6 +-- .../src/interfaces/IProtocolFees.sol | 1 - .../contracts/src/interfaces/IWallet.sol | 38 +++++++++++++++++++ contracts/exchange/package.json | 2 +- contracts/exchange/src/artifacts.ts | 2 + contracts/exchange/src/wrappers.ts | 1 + contracts/exchange/tsconfig.json | 1 + 8 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 contracts/exchange/contracts/src/interfaces/IWallet.sol diff --git a/contracts/exchange/CHANGELOG.json b/contracts/exchange/CHANGELOG.json index 676f003e6b..741ff3f973 100644 --- a/contracts/exchange/CHANGELOG.json +++ b/contracts/exchange/CHANGELOG.json @@ -189,10 +189,6 @@ { "note": "Overridden functions in `ReentrancyTester` now return sane values.", "pr": 2075 - }, - { - "note": "Move `IWallet.sol` to `exchange-libs`.", - "pr": 2233 } ], "timestamp": 1570135330 diff --git a/contracts/exchange/contracts/src/MixinSignatureValidator.sol b/contracts/exchange/contracts/src/MixinSignatureValidator.sol index d84d7b8ab5..f961f1aedf 100644 --- a/contracts/exchange/contracts/src/MixinSignatureValidator.sol +++ b/contracts/exchange/contracts/src/MixinSignatureValidator.sol @@ -27,7 +27,7 @@ import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomain.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibExchangeRichErrors.sol"; -import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol"; +import "./interfaces/IWallet.sol"; import "./interfaces/IEIP1271Wallet.sol"; import "./interfaces/ISignatureValidator.sol"; import "./interfaces/IEIP1271Data.sol"; @@ -465,7 +465,7 @@ contract MixinSignatureValidator is return signatureType; } - /// @dev ABI encodes an order and hash with a selector to be passed into + /// @dev ABI encodes an order and hash with a selector to be passed into /// an EIP1271 compliant `isValidSignature` function. function _encodeEIP1271OrderWithHash( LibOrder.Order memory order, @@ -482,7 +482,7 @@ contract MixinSignatureValidator is ); } - /// @dev ABI encodes a transaction and hash with a selector to be passed into + /// @dev ABI encodes a transaction and hash with a selector to be passed into /// an EIP1271 compliant `isValidSignature` function. function _encodeEIP1271TransactionWithHash( LibZeroExTransaction.ZeroExTransaction memory transaction, diff --git a/contracts/exchange/contracts/src/interfaces/IProtocolFees.sol b/contracts/exchange/contracts/src/interfaces/IProtocolFees.sol index 8e60a9b5f5..cd0e570c2f 100644 --- a/contracts/exchange/contracts/src/interfaces/IProtocolFees.sol +++ b/contracts/exchange/contracts/src/interfaces/IProtocolFees.sol @@ -19,7 +19,6 @@ pragma solidity ^0.5.9; -// solhint-disable no-simple-event-func-name contract IProtocolFees { // Logs updates to the protocol fee multiplier. diff --git a/contracts/exchange/contracts/src/interfaces/IWallet.sol b/contracts/exchange/contracts/src/interfaces/IWallet.sol new file mode 100644 index 0000000000..50a58d0e5e --- /dev/null +++ b/contracts/exchange/contracts/src/interfaces/IWallet.sol @@ -0,0 +1,38 @@ +/* + + Copyright 2019 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.5.9; +pragma experimental ABIEncoderV2; + +import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; + + +contract IWallet { + + /// @dev Validates a hash with the `Wallet` signature type. + /// @param hash Message hash that is signed. + /// @param signature Proof of signing. + /// @return magicValue `bytes4(0xb0671381)` if the signature check succeeds. + function isValidSignature( + bytes32 hash, + bytes calldata signature + ) + external + view + returns (bytes4 magicValue); +} diff --git a/contracts/exchange/package.json b/contracts/exchange/package.json index 8f2ca64a0f..c8199af93e 100644 --- a/contracts/exchange/package.json +++ b/contracts/exchange/package.json @@ -35,7 +35,7 @@ "compile:truffle": "truffle compile" }, "config": { - "abis": "./generated-artifacts/@(Exchange|IAssetProxy|IAssetProxyDispatcher|IEIP1271Data|IEIP1271Wallet|IExchange|IExchangeCore|IMatchOrders|IProtocolFees|ISignatureValidator|ITransactions|ITransferSimulator|IWrapperFunctions|IsolatedExchange|LibExchangeRichErrorDecoder|MixinAssetProxyDispatcher|MixinExchangeCore|MixinMatchOrders|MixinProtocolFees|MixinSignatureValidator|MixinTransactions|MixinTransferSimulator|MixinWrapperFunctions|ReentrancyTester|TestAssetProxyDispatcher|TestExchangeInternals|TestLibExchangeRichErrorDecoder|TestProtocolFees|TestProtocolFeesReceiver|TestSignatureValidator|TestTransactions|TestValidatorWallet|TestWrapperFunctions).json", + "abis": "./generated-artifacts/@(Exchange|IAssetProxy|IAssetProxyDispatcher|IEIP1271Data|IEIP1271Wallet|IExchange|IExchangeCore|IMatchOrders|IProtocolFees|ISignatureValidator|ITransactions|ITransferSimulator|IWallet|IWrapperFunctions|IsolatedExchange|LibExchangeRichErrorDecoder|MixinAssetProxyDispatcher|MixinExchangeCore|MixinMatchOrders|MixinProtocolFees|MixinSignatureValidator|MixinTransactions|MixinTransferSimulator|MixinWrapperFunctions|ReentrancyTester|TestAssetProxyDispatcher|TestExchangeInternals|TestLibExchangeRichErrorDecoder|TestProtocolFees|TestProtocolFeesReceiver|TestSignatureValidator|TestTransactions|TestValidatorWallet|TestWrapperFunctions).json", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually." }, "repository": { diff --git a/contracts/exchange/src/artifacts.ts b/contracts/exchange/src/artifacts.ts index afe062ebda..15a1d88233 100644 --- a/contracts/exchange/src/artifacts.ts +++ b/contracts/exchange/src/artifacts.ts @@ -18,6 +18,7 @@ import * as ISignatureValidator from '../generated-artifacts/ISignatureValidator import * as IsolatedExchange from '../generated-artifacts/IsolatedExchange.json'; import * as ITransactions from '../generated-artifacts/ITransactions.json'; import * as ITransferSimulator from '../generated-artifacts/ITransferSimulator.json'; +import * as IWallet from '../generated-artifacts/IWallet.json'; import * as IWrapperFunctions from '../generated-artifacts/IWrapperFunctions.json'; import * as LibExchangeRichErrorDecoder from '../generated-artifacts/LibExchangeRichErrorDecoder.json'; import * as MixinAssetProxyDispatcher from '../generated-artifacts/MixinAssetProxyDispatcher.json'; @@ -59,6 +60,7 @@ export const artifacts = { ISignatureValidator: ISignatureValidator as ContractArtifact, ITransactions: ITransactions as ContractArtifact, ITransferSimulator: ITransferSimulator as ContractArtifact, + IWallet: IWallet as ContractArtifact, IWrapperFunctions: IWrapperFunctions as ContractArtifact, LibExchangeRichErrorDecoder: LibExchangeRichErrorDecoder as ContractArtifact, IsolatedExchange: IsolatedExchange as ContractArtifact, diff --git a/contracts/exchange/src/wrappers.ts b/contracts/exchange/src/wrappers.ts index fe85e934e7..f5d76edb4d 100644 --- a/contracts/exchange/src/wrappers.ts +++ b/contracts/exchange/src/wrappers.ts @@ -15,6 +15,7 @@ export * from '../generated-wrappers/i_protocol_fees'; export * from '../generated-wrappers/i_signature_validator'; export * from '../generated-wrappers/i_transactions'; export * from '../generated-wrappers/i_transfer_simulator'; +export * from '../generated-wrappers/i_wallet'; export * from '../generated-wrappers/i_wrapper_functions'; export * from '../generated-wrappers/isolated_exchange'; export * from '../generated-wrappers/lib_exchange_rich_error_decoder'; diff --git a/contracts/exchange/tsconfig.json b/contracts/exchange/tsconfig.json index 797be7016d..6783d6851e 100644 --- a/contracts/exchange/tsconfig.json +++ b/contracts/exchange/tsconfig.json @@ -15,6 +15,7 @@ "generated-artifacts/ISignatureValidator.json", "generated-artifacts/ITransactions.json", "generated-artifacts/ITransferSimulator.json", + "generated-artifacts/IWallet.json", "generated-artifacts/IWrapperFunctions.json", "generated-artifacts/IsolatedExchange.json", "generated-artifacts/LibExchangeRichErrorDecoder.json", From 584f8b13fec1bd9d1f2cc8185af7e555813b8d4a Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Thu, 3 Oct 2019 10:31:32 -0700 Subject: [PATCH 22/87] `@0x/contracts-asset-proxy`: Rebase and update `Eth2DaiBridge` to use `IWallet` from `exchange-libs`. --- .../contracts/src/bridges/Eth2DaiBridge.sol | 2 +- contracts/asset-proxy/package.json | 2 +- contracts/asset-proxy/src/artifacts.ts | 10 ++- contracts/asset-proxy/src/wrappers.ts | 5 +- contracts/asset-proxy/test/uniswap_bridge.ts | 64 +++++-------------- contracts/asset-proxy/tsconfig.json | 7 +- 6 files changed, 34 insertions(+), 56 deletions(-) diff --git a/contracts/asset-proxy/contracts/src/bridges/Eth2DaiBridge.sol b/contracts/asset-proxy/contracts/src/bridges/Eth2DaiBridge.sol index d724dc5c51..8cba2ca305 100644 --- a/contracts/asset-proxy/contracts/src/bridges/Eth2DaiBridge.sol +++ b/contracts/asset-proxy/contracts/src/bridges/Eth2DaiBridge.sol @@ -20,9 +20,9 @@ pragma solidity ^0.5.9; pragma experimental ABIEncoderV2; import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; +import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol"; import "../interfaces/IERC20Bridge.sol"; import "../interfaces/IEth2Dai.sol"; -import "../interfaces/IWallet.sol"; // solhint-disable space-after-comma diff --git a/contracts/asset-proxy/package.json b/contracts/asset-proxy/package.json index bbd5b8a108..a39c3c18b5 100644 --- a/contracts/asset-proxy/package.json +++ b/contracts/asset-proxy/package.json @@ -35,7 +35,7 @@ "compile:truffle": "truffle compile" }, "config": { - "abis": "./generated-artifacts/@(ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IERC20Bridge|IEth2Dai|IWallet|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestERC20Bridge|TestEth2DaiBridge|TestStaticCallTarget).json", + "abis": "./generated-artifacts/@(ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IERC20Bridge|IEth2Dai|IUniswapExchange|IUniswapExchangeFactory|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestERC20Bridge|TestEth2DaiBridge|TestStaticCallTarget|TestUniswapBridge|UniswapBridge).json", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually." }, "repository": { diff --git a/contracts/asset-proxy/src/artifacts.ts b/contracts/asset-proxy/src/artifacts.ts index a7145fd6c5..ebe46f9d40 100644 --- a/contracts/asset-proxy/src/artifacts.ts +++ b/contracts/asset-proxy/src/artifacts.ts @@ -16,7 +16,8 @@ import * as IAssetProxyDispatcher from '../generated-artifacts/IAssetProxyDispat import * as IAuthorizable from '../generated-artifacts/IAuthorizable.json'; import * as IERC20Bridge from '../generated-artifacts/IERC20Bridge.json'; import * as IEth2Dai from '../generated-artifacts/IEth2Dai.json'; -import * as IWallet from '../generated-artifacts/IWallet.json'; +import * as IUniswapExchange from '../generated-artifacts/IUniswapExchange.json'; +import * as IUniswapExchangeFactory from '../generated-artifacts/IUniswapExchangeFactory.json'; import * as MixinAssetProxyDispatcher from '../generated-artifacts/MixinAssetProxyDispatcher.json'; import * as MixinAuthorizable from '../generated-artifacts/MixinAuthorizable.json'; import * as MultiAssetProxy from '../generated-artifacts/MultiAssetProxy.json'; @@ -25,6 +26,8 @@ import * as StaticCallProxy from '../generated-artifacts/StaticCallProxy.json'; import * as TestERC20Bridge from '../generated-artifacts/TestERC20Bridge.json'; import * as TestEth2DaiBridge from '../generated-artifacts/TestEth2DaiBridge.json'; import * as TestStaticCallTarget from '../generated-artifacts/TestStaticCallTarget.json'; +import * as TestUniswapBridge from '../generated-artifacts/TestUniswapBridge.json'; +import * as UniswapBridge from '../generated-artifacts/UniswapBridge.json'; export const artifacts = { MixinAssetProxyDispatcher: MixinAssetProxyDispatcher as ContractArtifact, MixinAuthorizable: MixinAuthorizable as ContractArtifact, @@ -36,14 +39,17 @@ export const artifacts = { MultiAssetProxy: MultiAssetProxy as ContractArtifact, StaticCallProxy: StaticCallProxy as ContractArtifact, Eth2DaiBridge: Eth2DaiBridge as ContractArtifact, + UniswapBridge: UniswapBridge as ContractArtifact, IAssetData: IAssetData as ContractArtifact, IAssetProxy: IAssetProxy as ContractArtifact, IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact, IAuthorizable: IAuthorizable as ContractArtifact, IERC20Bridge: IERC20Bridge as ContractArtifact, IEth2Dai: IEth2Dai as ContractArtifact, - IWallet: IWallet as ContractArtifact, + IUniswapExchange: IUniswapExchange as ContractArtifact, + IUniswapExchangeFactory: IUniswapExchangeFactory as ContractArtifact, TestERC20Bridge: TestERC20Bridge as ContractArtifact, TestEth2DaiBridge: TestEth2DaiBridge as ContractArtifact, TestStaticCallTarget: TestStaticCallTarget as ContractArtifact, + TestUniswapBridge: TestUniswapBridge as ContractArtifact, }; diff --git a/contracts/asset-proxy/src/wrappers.ts b/contracts/asset-proxy/src/wrappers.ts index a87eda1f77..a39cbd282b 100644 --- a/contracts/asset-proxy/src/wrappers.ts +++ b/contracts/asset-proxy/src/wrappers.ts @@ -14,7 +14,8 @@ export * from '../generated-wrappers/i_asset_proxy_dispatcher'; export * from '../generated-wrappers/i_authorizable'; export * from '../generated-wrappers/i_erc20_bridge'; export * from '../generated-wrappers/i_eth2_dai'; -export * from '../generated-wrappers/i_wallet'; +export * from '../generated-wrappers/i_uniswap_exchange'; +export * from '../generated-wrappers/i_uniswap_exchange_factory'; export * from '../generated-wrappers/mixin_asset_proxy_dispatcher'; export * from '../generated-wrappers/mixin_authorizable'; export * from '../generated-wrappers/multi_asset_proxy'; @@ -23,3 +24,5 @@ export * from '../generated-wrappers/static_call_proxy'; export * from '../generated-wrappers/test_erc20_bridge'; export * from '../generated-wrappers/test_eth2_dai_bridge'; export * from '../generated-wrappers/test_static_call_target'; +export * from '../generated-wrappers/test_uniswap_bridge'; +export * from '../generated-wrappers/uniswap_bridge'; diff --git a/contracts/asset-proxy/test/uniswap_bridge.ts b/contracts/asset-proxy/test/uniswap_bridge.ts index b14ab427a8..f284aa122c 100644 --- a/contracts/asset-proxy/test/uniswap_bridge.ts +++ b/contracts/asset-proxy/test/uniswap_bridge.ts @@ -47,10 +47,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { describe('isValidSignature()', () => { it('returns success bytes', async () => { const LEGACY_WALLET_MAGIC_VALUE = '0xb0671381'; - const result = await testContract.isValidSignature.callAsync( - hexRandom(), - hexRandom(_.random(0, 32)), - ); + const result = await testContract.isValidSignature.callAsync(hexRandom(), hexRandom(_.random(0, 32))); expect(result).to.eq(LEGACY_WALLET_MAGIC_VALUE); }); }); @@ -115,10 +112,9 @@ blockchainTests.resets('UniswapBridge unit tests', env => { _opts.fromTokenRevertReason, ); // Set the token balance for the token we're converting from. - await testContract.setTokenBalance.awaitTransactionSuccessAsync( - _opts.fromTokenAddress, - { value: new BigNumber(_opts.fromTokenBalance) }, - ); + await testContract.setTokenBalance.awaitTransactionSuccessAsync(_opts.fromTokenAddress, { + value: new BigNumber(_opts.fromTokenBalance), + }); // Call withdrawTo(). const [result, receipt] = await txHelper.getResultAndReceiptAsync( testContract.withdrawTo, @@ -136,7 +132,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { return { opts: _opts, result, - logs: receipt.logs as any as DecodedLogs, + logs: (receipt.logs as any) as DecodedLogs, blockTime: await env.web3Wrapper.getBlockTimestampAsync(receipt.blockNumber), }; } @@ -161,10 +157,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { toTokenAddress: tokenAddress, }); expect(result).to.eq(AssetProxyId.ERC20Bridge); - const transfers = filterLogsToArguments( - logs, - ContractEvents.TokenTransfer, - ); + const transfers = filterLogsToArguments(logs, ContractEvents.TokenTransfer); expect(transfers.length).to.eq(1); expect(transfers[0].token).to.eq(tokenAddress); expect(transfers[0].from).to.eq(testContract.address); @@ -192,10 +185,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { it('sets allowance for "from" token', async () => { const { opts, logs } = await withdrawToAsync(); - const approvals = filterLogsToArguments( - logs, - ContractEvents.TokenApprove, - ); + const approvals = filterLogsToArguments(logs, ContractEvents.TokenApprove); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); expect(approvals.length).to.eq(1); expect(approvals[0].spender).to.eq(exchangeAddress); @@ -205,10 +195,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { it('sets allowance for "from" token on subsequent calls', async () => { const { opts } = await withdrawToAsync(); const { logs } = await withdrawToAsync(opts); - const approvals = filterLogsToArguments( - logs, - ContractEvents.TokenApprove, - ); + const approvals = filterLogsToArguments(logs, ContractEvents.TokenApprove); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); expect(approvals.length).to.eq(1); expect(approvals[0].spender).to.eq(exchangeAddress); @@ -241,10 +228,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { toTokenAddress: wethTokenAddress, }); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); - let calls: any = filterLogs( - logs, - ContractEvents.TokenToEthSwapInput, - ); + let calls: any = filterLogs(logs, ContractEvents.TokenToEthSwapInput); expect(calls.length).to.eq(1); expect(calls[0].args.exchange).to.eq(exchangeAddress); expect(calls[0].args.tokensSold).to.bignumber.eq(opts.fromTokenBalance); @@ -271,10 +255,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { const { opts, logs, blockTime } = await withdrawToAsync({ toTokenAddress: wethTokenAddress, }); - const calls = filterLogsToArguments( - logs, - ContractEvents.TokenToEthSwapInput, - ); + const calls = filterLogsToArguments(logs, ContractEvents.TokenToEthSwapInput); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); expect(calls.length).to.eq(1); expect(calls[0].exchange).to.eq(exchangeAddress); @@ -287,10 +268,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { const { opts, logs } = await withdrawToAsync({ toTokenAddress: wethTokenAddress, }); - const transfers = filterLogsToArguments( - logs, - ContractEvents.TokenApprove, - ); + const transfers = filterLogsToArguments(logs, ContractEvents.TokenApprove); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); expect(transfers.length).to.eq(1); expect(transfers[0].spender).to.eq(exchangeAddress); @@ -302,10 +280,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { toTokenAddress: wethTokenAddress, }); const { logs } = await withdrawToAsync(opts); - const approvals = filterLogsToArguments( - logs, - ContractEvents.TokenApprove, - ); + const approvals = filterLogsToArguments(logs, ContractEvents.TokenApprove); const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); expect(approvals.length).to.eq(1); expect(approvals[0].spender).to.eq(exchangeAddress); @@ -348,10 +323,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { fromTokenAddress: wethTokenAddress, }); const exchangeAddress = await getExchangeForTokenAsync(opts.toTokenAddress); - let calls: any = filterLogs( - logs, - ContractEvents.WethWithdraw, - ); + let calls: any = filterLogs(logs, ContractEvents.WethWithdraw); expect(calls.length).to.eq(1); expect(calls[0].args.amount).to.bignumber.eq(opts.fromTokenBalance); calls = filterLogs( @@ -369,10 +341,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { const { opts, logs } = await withdrawToAsync({ fromTokenAddress: wethTokenAddress, }); - const approvals = filterLogsToArguments( - logs, - ContractEvents.TokenApprove, - ); + const approvals = filterLogsToArguments(logs, ContractEvents.TokenApprove); const exchangeAddress = await getExchangeForTokenAsync(opts.toTokenAddress); expect(approvals.length).to.eq(1); expect(approvals[0].spender).to.eq(exchangeAddress); @@ -384,10 +353,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { fromTokenAddress: wethTokenAddress, }); const { logs } = await withdrawToAsync(opts); - const approvals = filterLogsToArguments( - logs, - ContractEvents.TokenApprove, - ); + const approvals = filterLogsToArguments(logs, ContractEvents.TokenApprove); const exchangeAddress = await getExchangeForTokenAsync(opts.toTokenAddress); expect(approvals.length).to.eq(1); expect(approvals[0].spender).to.eq(exchangeAddress); diff --git a/contracts/asset-proxy/tsconfig.json b/contracts/asset-proxy/tsconfig.json index b3faf3e356..8ca5339b81 100644 --- a/contracts/asset-proxy/tsconfig.json +++ b/contracts/asset-proxy/tsconfig.json @@ -14,7 +14,8 @@ "generated-artifacts/IAuthorizable.json", "generated-artifacts/IERC20Bridge.json", "generated-artifacts/IEth2Dai.json", - "generated-artifacts/IWallet.json", + "generated-artifacts/IUniswapExchange.json", + "generated-artifacts/IUniswapExchangeFactory.json", "generated-artifacts/MixinAssetProxyDispatcher.json", "generated-artifacts/MixinAuthorizable.json", "generated-artifacts/MultiAssetProxy.json", @@ -22,7 +23,9 @@ "generated-artifacts/StaticCallProxy.json", "generated-artifacts/TestERC20Bridge.json", "generated-artifacts/TestEth2DaiBridge.json", - "generated-artifacts/TestStaticCallTarget.json" + "generated-artifacts/TestStaticCallTarget.json", + "generated-artifacts/TestUniswapBridge.json", + "generated-artifacts/UniswapBridge.json" ], "exclude": ["./deploy/solc/solc_bin"] } From e67888d65f48214c04b43d9a822c881350b4d840 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Sat, 5 Oct 2019 16:27:24 -0500 Subject: [PATCH 23/87] `@0x/contracs-asset-proxy`: Pass in minimum buy amounts in the `UniswapBridge`. `@0x/contracs-asset-proxy`: Slight refactors in `UniswapBridge`. --- .../contracts/src/bridges/UniswapBridge.sol | 62 +++++++++++-------- .../contracts/test/TestUniswapBridge.sol | 8 +-- contracts/asset-proxy/test/uniswap_bridge.ts | 19 +----- 3 files changed, 42 insertions(+), 47 deletions(-) diff --git a/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol index ef975a7699..1da6a3ea25 100644 --- a/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol +++ b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol @@ -34,12 +34,13 @@ contract UniswapBridge is IWallet { /* Mainnet addresses */ - address constant public UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95; - address constant public WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95; + address constant private WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // Struct to hold `withdrawTo()` local variables in memory and to avoid // stack overflows. struct WithdrawToState { + address exchangeTokenAddress; IUniswapExchange exchange; uint256 fromTokenBalance; IEtherToken weth; @@ -81,17 +82,19 @@ contract UniswapBridge is return BRIDGE_SUCCESS; } - // Get the exchange for the token pair. - state.exchange = _getUniswapExchangeForTokenPair( + // Get the exchange token for the token pair. + state.exchangeTokenAddress = _getUniswapExchangeTokenAddressForTokenPair( fromTokenAddress, toTokenAddress ); + // Get the exchange. + state.exchange = _getUniswapExchangeForToken(state.exchangeTokenAddress); // Grant an allowance to the exchange. - _grantExchangeAllowance(state.exchange); + _grantExchangeAllowance(state.exchange, state.exchangeTokenAddress); // Get our balance of `fromTokenAddress` token. state.fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this)); // Get the weth contract. - state.weth = _getWethContract(); + state.weth = getWethContract(); // Convert from WETH to a token. if (fromTokenAddress == address(state.weth)) { @@ -100,8 +103,8 @@ contract UniswapBridge is // Buy as much of `toTokenAddress` token with ETH as possible and // transfer it to `to`. state.exchange.ethToTokenTransferInput.value(state.fromTokenBalance)( - // No minimum buy amount. - 0, + // Minimum buy amount. + amount, // Expires after this block. block.timestamp, // Recipient is `to`. @@ -114,15 +117,15 @@ contract UniswapBridge is uint256 ethBought = state.exchange.tokenToEthSwapInput( // Sell all tokens we hold. state.fromTokenBalance, - // No minimum buy amount. - 0, + // Minimum buy amount. + amount, // Expires after this block. block.timestamp ); // Wrap the ETH. state.weth.deposit.value(ethBought)(); // Transfer the WETH to `to`. - IERC20Token(toTokenAddress).transfer(to, ethBought); + IEtherToken(toTokenAddress).transfer(to, ethBought); // Convert from one token to another. } else { @@ -131,8 +134,8 @@ contract UniswapBridge is state.exchange.tokenToTokenTransferInput( // Sell all tokens we hold. state.fromTokenBalance, - // No minimum buy amount. - 0, + // Minimum buy amount. + amount, // No minimum intermediate ETH buy amount. 0, // Expires after this block. @@ -162,8 +165,8 @@ contract UniswapBridge is /// @dev Overridable way to get the weth contract. /// @return token The WETH contract. - function _getWethContract() - internal + function getWethContract() + public view returns (IEtherToken token) { @@ -172,8 +175,8 @@ contract UniswapBridge is /// @dev Overridable way to get the uniswap exchange factory contract. /// @return factory The exchange factory contract. - function _getUniswapExchangeFactoryContract() - internal + function getUniswapExchangeFactoryContract() + public view returns (IUniswapExchangeFactory factory) { @@ -183,28 +186,33 @@ contract UniswapBridge is /// @dev Grants an unlimited allowance to the exchange for its token /// on behalf of this contract. /// @param exchange The Uniswap token exchange. - function _grantExchangeAllowance(IUniswapExchange exchange) + /// @param tokenAddress The token address for the exchange. + function _grantExchangeAllowance(IUniswapExchange exchange, address tokenAddress) private { - address tokenAddress = exchange.toTokenAddress(); IERC20Token(tokenAddress).approve(address(exchange), uint256(-1)); } - /// @dev Retrieves the uniswap exchange contract for a given token pair. - /// @return exchange The exchange contract for the token pair. - function _getUniswapExchangeForTokenPair( + /// @dev Retrieves the uniswap exchange token address for a given token pair. + /// In the case of a WETH-token exchange, this will be the non-WETH token. + /// In th ecase of a token-token exchange, this will be the first token. + /// @param fromTokenAddress The address of the token we are converting from. + /// @param toTokenAddress The address of the token we are converting to. + /// @return exchangeTokenAddress The address of the token for the uniswap + /// exchange. + function _getUniswapExchangeTokenAddressForTokenPair( address fromTokenAddress, address toTokenAddress ) private view - returns (IUniswapExchange exchange) + returns (address exchangeTokenAddress) { // Whichever isn't WETH is the exchange token. - if (fromTokenAddress != address(_getWethContract())) { - return _getUniswapExchangeForToken(fromTokenAddress); + if (fromTokenAddress != address(getWethContract())) { + return fromTokenAddress; } - return _getUniswapExchangeForToken(toTokenAddress); + return toTokenAddress; } /// @dev Retrieves the uniswap exchange contract for a given token. @@ -214,7 +222,7 @@ contract UniswapBridge is view returns (IUniswapExchange exchange) { - exchange = _getUniswapExchangeFactoryContract().getExchange(tokenAddress); + exchange = getUniswapExchangeFactoryContract().getExchange(tokenAddress); require(address(exchange) != address(0), "NO_UNISWAP_EXCHANGE_FOR_TOKEN"); return exchange; } diff --git a/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol b/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol index 19c4e86042..9f67714a1b 100644 --- a/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol +++ b/contracts/asset-proxy/contracts/test/TestUniswapBridge.sol @@ -413,8 +413,8 @@ contract TestUniswapBridge is } // @dev Use `wethToken`. - function _getWethContract() - internal + function getWethContract() + public view returns (IEtherToken) { @@ -422,8 +422,8 @@ contract TestUniswapBridge is } // @dev This contract will double as the Uniswap contract. - function _getUniswapExchangeFactoryContract() - internal + function getUniswapExchangeFactoryContract() + public view returns (IUniswapExchangeFactory) { diff --git a/contracts/asset-proxy/test/uniswap_bridge.ts b/contracts/asset-proxy/test/uniswap_bridge.ts index f284aa122c..a284ff7fc7 100644 --- a/contracts/asset-proxy/test/uniswap_bridge.ts +++ b/contracts/asset-proxy/test/uniswap_bridge.ts @@ -176,7 +176,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { expect(calls.length).to.eq(1); expect(calls[0].exchange).to.eq(exchangeAddress); expect(calls[0].tokensSold).to.bignumber.eq(opts.fromTokenBalance); - expect(calls[0].minTokensBought).to.bignumber.eq(0); + expect(calls[0].minTokensBought).to.bignumber.eq(opts.amount); expect(calls[0].minEthBought).to.bignumber.eq(0); expect(calls[0].deadline).to.bignumber.eq(blockTime); expect(calls[0].recipient).to.eq(opts.toAddress); @@ -232,7 +232,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { expect(calls.length).to.eq(1); expect(calls[0].args.exchange).to.eq(exchangeAddress); expect(calls[0].args.tokensSold).to.bignumber.eq(opts.fromTokenBalance); - expect(calls[0].args.minEthBought).to.bignumber.eq(0); + expect(calls[0].args.minEthBought).to.bignumber.eq(opts.amount); expect(calls[0].args.deadline).to.bignumber.eq(blockTime); calls = filterLogs( logs.slice(calls[0].logIndex as number), @@ -251,19 +251,6 @@ blockchainTests.resets('UniswapBridge unit tests', env => { expect(calls[0].args.amount).to.bignumber.eq(opts.exchangeFillAmount); }); - it('calls `IUniswapExchange.tokenToEthSwapInput()`', async () => { - const { opts, logs, blockTime } = await withdrawToAsync({ - toTokenAddress: wethTokenAddress, - }); - const calls = filterLogsToArguments(logs, ContractEvents.TokenToEthSwapInput); - const exchangeAddress = await getExchangeForTokenAsync(opts.fromTokenAddress); - expect(calls.length).to.eq(1); - expect(calls[0].exchange).to.eq(exchangeAddress); - expect(calls[0].tokensSold).to.bignumber.eq(opts.fromTokenBalance); - expect(calls[0].minEthBought).to.bignumber.eq(0); - expect(calls[0].deadline).to.bignumber.eq(blockTime); - }); - it('sets allowance for "from" token', async () => { const { opts, logs } = await withdrawToAsync({ toTokenAddress: wethTokenAddress, @@ -332,7 +319,7 @@ blockchainTests.resets('UniswapBridge unit tests', env => { ); expect(calls.length).to.eq(1); expect(calls[0].args.exchange).to.eq(exchangeAddress); - expect(calls[0].args.minTokensBought).to.bignumber.eq(0); + expect(calls[0].args.minTokensBought).to.bignumber.eq(opts.amount); expect(calls[0].args.deadline).to.bignumber.eq(blockTime); expect(calls[0].args.recipient).to.eq(opts.toAddress); }); From ef6e69164600b665eecb43776a3960dd8ec3f75f Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Sat, 5 Oct 2019 16:29:06 -0500 Subject: [PATCH 24/87] `@0x/contracts-exchange-libs`: Update generated source files after revase. --- contracts/exchange-libs/package.json | 2 +- contracts/exchange-libs/src/artifacts.ts | 2 ++ contracts/exchange-libs/src/wrappers.ts | 1 + contracts/exchange-libs/tsconfig.json | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/contracts/exchange-libs/package.json b/contracts/exchange-libs/package.json index b22d8ec706..e21a07ead7 100644 --- a/contracts/exchange-libs/package.json +++ b/contracts/exchange-libs/package.json @@ -35,7 +35,7 @@ "compile:truffle": "truffle compile" }, "config": { - "abis": "./generated-artifacts/@(LibEIP712ExchangeDomain|LibExchangeRichErrors|LibFillResults|LibMath|LibMathRichErrors|LibOrder|LibZeroExTransaction|TestLibEIP712ExchangeDomain|TestLibFillResults|TestLibMath|TestLibOrder|TestLibZeroExTransaction).json", + "abis": "./generated-artifacts/@(IWallet|LibEIP712ExchangeDomain|LibExchangeRichErrors|LibFillResults|LibMath|LibMathRichErrors|LibOrder|LibZeroExTransaction|TestLibEIP712ExchangeDomain|TestLibFillResults|TestLibMath|TestLibOrder|TestLibZeroExTransaction).json", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually." }, "repository": { diff --git a/contracts/exchange-libs/src/artifacts.ts b/contracts/exchange-libs/src/artifacts.ts index 7bfb67a9d3..1769fc432a 100644 --- a/contracts/exchange-libs/src/artifacts.ts +++ b/contracts/exchange-libs/src/artifacts.ts @@ -5,6 +5,7 @@ */ import { ContractArtifact } from 'ethereum-types'; +import * as IWallet from '../generated-artifacts/IWallet.json'; import * as LibEIP712ExchangeDomain from '../generated-artifacts/LibEIP712ExchangeDomain.json'; import * as LibExchangeRichErrors from '../generated-artifacts/LibExchangeRichErrors.json'; import * as LibFillResults from '../generated-artifacts/LibFillResults.json'; @@ -18,6 +19,7 @@ import * as TestLibMath from '../generated-artifacts/TestLibMath.json'; import * as TestLibOrder from '../generated-artifacts/TestLibOrder.json'; import * as TestLibZeroExTransaction from '../generated-artifacts/TestLibZeroExTransaction.json'; export const artifacts = { + IWallet: IWallet as ContractArtifact, LibEIP712ExchangeDomain: LibEIP712ExchangeDomain as ContractArtifact, LibExchangeRichErrors: LibExchangeRichErrors as ContractArtifact, LibFillResults: LibFillResults as ContractArtifact, diff --git a/contracts/exchange-libs/src/wrappers.ts b/contracts/exchange-libs/src/wrappers.ts index 89a7ffc03b..695fe2da79 100644 --- a/contracts/exchange-libs/src/wrappers.ts +++ b/contracts/exchange-libs/src/wrappers.ts @@ -3,6 +3,7 @@ * Warning: This file is auto-generated by contracts-gen. Don't edit manually. * ----------------------------------------------------------------------------- */ +export * from '../generated-wrappers/i_wallet'; export * from '../generated-wrappers/lib_e_i_p712_exchange_domain'; export * from '../generated-wrappers/lib_exchange_rich_errors'; export * from '../generated-wrappers/lib_fill_results'; diff --git a/contracts/exchange-libs/tsconfig.json b/contracts/exchange-libs/tsconfig.json index 7e46a4852c..b75670d9f7 100644 --- a/contracts/exchange-libs/tsconfig.json +++ b/contracts/exchange-libs/tsconfig.json @@ -3,6 +3,7 @@ "compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true }, "include": ["./src/**/*", "./test/**/*", "./scripts/**/*", "./generated-wrappers/**/*"], "files": [ + "generated-artifacts/IWallet.json", "generated-artifacts/LibEIP712ExchangeDomain.json", "generated-artifacts/LibExchangeRichErrors.json", "generated-artifacts/LibFillResults.json", From 6825eb442b7e0acb7188d622d40bce95d23d0a44 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Sat, 5 Oct 2019 17:22:46 -0500 Subject: [PATCH 25/87] `@0x/contracts-staking`: Fix shadowed variable in `MixinStakingPoolRewards._computeUnfinalizedDelegatorReward()` and make the function `pure`. --- .../src/staking_pools/MixinStakingPoolRewards.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol b/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol index 153481bfa0..282010d6a7 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol @@ -314,18 +314,18 @@ contract MixinStakingPoolRewards is /// @dev Computes the unfinalized rewards earned by a delegator in the last epoch. /// @param unsyncedStake Unsynced delegated stake to pool by staker - /// @param currentEpoch The epoch in which this call is executing + /// @param currentEpoch_ The epoch in which this call is executing /// @param unfinalizedMembersReward Unfinalized total members reward (if any). /// @param unfinalizedMembersStake Unfinalized total members stake (if any). /// @return reward Balance in WETH. function _computeUnfinalizedDelegatorReward( IStructs.StoredBalance memory unsyncedStake, - uint256 currentEpoch, + uint256 currentEpoch_, uint256 unfinalizedMembersReward, uint256 unfinalizedMembersStake ) private - view + pure returns (uint256) { // If there are unfinalized rewards this epoch, compute the member's @@ -335,8 +335,8 @@ contract MixinStakingPoolRewards is } // Unfinalized rewards are always earned from stake in - // the prior epoch so we want the stake at `currentEpoch-1`. - uint256 unfinalizedStakeBalance = unsyncedStake.currentEpoch >= currentEpoch.safeSub(1) ? + // the prior epoch so we want the stake at `currentEpoch_-1`. + uint256 unfinalizedStakeBalance = unsyncedStake.currentEpoch >= currentEpoch_.safeSub(1) ? unsyncedStake.currentEpochBalance : unsyncedStake.nextEpochBalance; From dbf22583b5e771f5394000cbfa289df345e53fc9 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Sat, 5 Oct 2019 22:37:51 -0500 Subject: [PATCH 26/87] `@0x/contracts-asset-proxy`: Remove unecessary token allowance when coming from WETH. --- .../contracts/src/bridges/UniswapBridge.sol | 39 +++++++------------ contracts/asset-proxy/test/uniswap_bridge.ts | 23 ++--------- 2 files changed, 18 insertions(+), 44 deletions(-) diff --git a/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol index 1da6a3ea25..c5210d7e96 100644 --- a/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol +++ b/contracts/asset-proxy/contracts/src/bridges/UniswapBridge.sol @@ -40,7 +40,6 @@ contract UniswapBridge is // Struct to hold `withdrawTo()` local variables in memory and to avoid // stack overflows. struct WithdrawToState { - address exchangeTokenAddress; IUniswapExchange exchange; uint256 fromTokenBalance; IEtherToken weth; @@ -82,15 +81,11 @@ contract UniswapBridge is return BRIDGE_SUCCESS; } - // Get the exchange token for the token pair. - state.exchangeTokenAddress = _getUniswapExchangeTokenAddressForTokenPair( + // Get the exchange for the token pair. + state.exchange = _getUniswapExchangeForTokenPair( fromTokenAddress, toTokenAddress ); - // Get the exchange. - state.exchange = _getUniswapExchangeForToken(state.exchangeTokenAddress); - // Grant an allowance to the exchange. - _grantExchangeAllowance(state.exchange, state.exchangeTokenAddress); // Get our balance of `fromTokenAddress` token. state.fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this)); // Get the weth contract. @@ -113,6 +108,8 @@ contract UniswapBridge is // Convert from a token to WETH. } else if (toTokenAddress == address(state.weth)) { + // Grant the exchange an allowance. + _grantExchangeAllowance(state.exchange, fromTokenAddress); // Buy as much ETH with `fromTokenAddress` token as possible. uint256 ethBought = state.exchange.tokenToEthSwapInput( // Sell all tokens we hold. @@ -129,6 +126,8 @@ contract UniswapBridge is // Convert from one token to another. } else { + // Grant the exchange an allowance. + _grantExchangeAllowance(state.exchange, fromTokenAddress); // Buy as much `toTokenAddress` token with `fromTokenAddress` token // and transfer it to `to`. state.exchange.tokenToTokenTransferInput( @@ -193,36 +192,26 @@ contract UniswapBridge is IERC20Token(tokenAddress).approve(address(exchange), uint256(-1)); } - /// @dev Retrieves the uniswap exchange token address for a given token pair. + /// @dev Retrieves the uniswap exchange for a given token pair. /// In the case of a WETH-token exchange, this will be the non-WETH token. /// In th ecase of a token-token exchange, this will be the first token. /// @param fromTokenAddress The address of the token we are converting from. /// @param toTokenAddress The address of the token we are converting to. - /// @return exchangeTokenAddress The address of the token for the uniswap - /// exchange. - function _getUniswapExchangeTokenAddressForTokenPair( + /// @return exchange The uniswap exchange. + function _getUniswapExchangeForTokenPair( address fromTokenAddress, address toTokenAddress ) private view - returns (address exchangeTokenAddress) + returns (IUniswapExchange exchange) { + address exchangeTokenAddress = fromTokenAddress; // Whichever isn't WETH is the exchange token. - if (fromTokenAddress != address(getWethContract())) { - return fromTokenAddress; + if (fromTokenAddress == address(getWethContract())) { + exchangeTokenAddress = toTokenAddress; } - return toTokenAddress; - } - - /// @dev Retrieves the uniswap exchange contract for a given token. - /// @return exchange The exchange contract for the token. - function _getUniswapExchangeForToken(address tokenAddress) - private - view - returns (IUniswapExchange exchange) - { - exchange = getUniswapExchangeFactoryContract().getExchange(tokenAddress); + exchange = getUniswapExchangeFactoryContract().getExchange(exchangeTokenAddress); require(address(exchange) != address(0), "NO_UNISWAP_EXCHANGE_FOR_TOKEN"); return exchange; } diff --git a/contracts/asset-proxy/test/uniswap_bridge.ts b/contracts/asset-proxy/test/uniswap_bridge.ts index a284ff7fc7..92e70d5ca1 100644 --- a/contracts/asset-proxy/test/uniswap_bridge.ts +++ b/contracts/asset-proxy/test/uniswap_bridge.ts @@ -29,7 +29,7 @@ import { TestUniswapBridgeWethWithdrawEventArgs as WethWithdrawArgs, } from '../src'; -blockchainTests.resets('UniswapBridge unit tests', env => { +blockchainTests.resets.only('UniswapBridge unit tests', env => { const txHelper = new TransactionHelper(env.web3Wrapper, artifacts); let testContract: TestUniswapBridgeContract; let wethTokenAddress: string; @@ -324,27 +324,12 @@ blockchainTests.resets('UniswapBridge unit tests', env => { expect(calls[0].args.recipient).to.eq(opts.toAddress); }); - it('sets allowance for "to" token', async () => { - const { opts, logs } = await withdrawToAsync({ - fromTokenAddress: wethTokenAddress, - }); - const approvals = filterLogsToArguments(logs, ContractEvents.TokenApprove); - const exchangeAddress = await getExchangeForTokenAsync(opts.toTokenAddress); - expect(approvals.length).to.eq(1); - expect(approvals[0].spender).to.eq(exchangeAddress); - expect(approvals[0].allowance).to.bignumber.eq(constants.MAX_UINT256); - }); - - it('sets allowance for "to" token on subsequent calls', async () => { - const { opts } = await withdrawToAsync({ + it('does not set any allowance', async () => { + const { logs } = await withdrawToAsync({ fromTokenAddress: wethTokenAddress, }); - const { logs } = await withdrawToAsync(opts); const approvals = filterLogsToArguments(logs, ContractEvents.TokenApprove); - const exchangeAddress = await getExchangeForTokenAsync(opts.toTokenAddress); - expect(approvals.length).to.eq(1); - expect(approvals[0].spender).to.eq(exchangeAddress); - expect(approvals[0].allowance).to.bignumber.eq(constants.MAX_UINT256); + expect(approvals).to.be.empty(''); }); it('fails if "to" token does not exist', async () => { From 0e7387550cce05fb62b3e1acd2fe72b3e3eef776 Mon Sep 17 00:00:00 2001 From: Michael Zhu Date: Fri, 27 Sep 2019 15:07:06 -0700 Subject: [PATCH 27/87] Update contracts --- .../src/MixinCoordinatorApprovalVerifier.sol | 72 +++++++----- .../contracts/src/MixinCoordinatorCore.sol | 15 ++- .../contracts/src/MixinSignatureValidator.sol | 70 ++++++++---- .../ICoordinatorApprovalVerifier.sol | 8 +- .../src/interfaces/ICoordinatorCore.sol | 12 +- .../ICoordinatorSignatureValidator.sol | 6 +- .../src/libs/LibCoordinatorApproval.sol | 19 ++-- .../src/libs/LibCoordinatorRichErrors.sol | 106 ++++++++++++++++++ .../src/libs/LibEIP712CoordinatorDomain.sol | 12 +- .../registry/MixinCoordinatorRegistryCore.sol | 5 +- .../interfaces/ICoordinatorRegistryCore.sol | 5 +- contracts/utils/contracts/src/LibEIP712.sol | 10 +- .../src/coordinator_revert_errors.ts | 52 +++++++++ 13 files changed, 308 insertions(+), 84 deletions(-) create mode 100644 contracts/coordinator/contracts/src/libs/LibCoordinatorRichErrors.sol create mode 100644 packages/order-utils/src/coordinator_revert_errors.ts diff --git a/contracts/coordinator/contracts/src/MixinCoordinatorApprovalVerifier.sol b/contracts/coordinator/contracts/src/MixinCoordinatorApprovalVerifier.sol index 0b9e986db6..f848a5870b 100644 --- a/contracts/coordinator/contracts/src/MixinCoordinatorApprovalVerifier.sol +++ b/contracts/coordinator/contracts/src/MixinCoordinatorApprovalVerifier.sol @@ -19,12 +19,15 @@ pragma solidity ^0.5.9; pragma experimental ABIEncoderV2; +import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomain.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol"; -import "@0x/contracts-utils/contracts/src/LibBytes.sol"; import "@0x/contracts-utils/contracts/src/LibAddressArray.sol"; +import "@0x/contracts-utils/contracts/src/LibBytes.sol"; +import "@0x/contracts-utils/contracts/src/LibRichErrors.sol"; import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol"; import "./libs/LibCoordinatorApproval.sol"; +import "./libs/LibCoordinatorRichErrors.sol"; import "./interfaces/ICoordinatorSignatureValidator.sol"; import "./interfaces/ICoordinatorApprovalVerifier.sol"; @@ -32,7 +35,7 @@ import "./interfaces/ICoordinatorApprovalVerifier.sol"; // solhint-disable avoid-tx-origin contract MixinCoordinatorApprovalVerifier is LibCoordinatorApproval, - LibZeroExTransaction, + LibEIP712ExchangeDomain, ICoordinatorSignatureValidator, ICoordinatorApprovalVerifier { @@ -44,8 +47,10 @@ contract MixinCoordinatorApprovalVerifier is /// @param transaction 0x transaction containing salt, signerAddress, and data. /// @param txOrigin Required signer of Ethereum transaction calling this function. /// @param transactionSignature Proof that the transaction has been signed by the signer. - /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires. - /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order in the transaction's Exchange calldata. + /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each + /// corresponding approval signature expires. + /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each + /// order in the transaction's Exchange calldata. function assertValidCoordinatorApprovals( LibZeroExTransaction.ZeroExTransaction memory transaction, address txOrigin, @@ -75,7 +80,7 @@ contract MixinCoordinatorApprovalVerifier is /// @dev Decodes the orders from Exchange calldata representing any fill method. /// @param data Exchange calldata representing a fill method. - /// @return The orders from the Exchange calldata. + /// @return orders The orders from the Exchange calldata. function decodeOrdersFromFillData(bytes memory data) public pure @@ -84,7 +89,6 @@ contract MixinCoordinatorApprovalVerifier is bytes4 selector = data.readBytes4(0); if ( selector == IExchange(address(0)).fillOrder.selector || - selector == IExchange(address(0)).fillOrderNoThrow.selector || selector == IExchange(address(0)).fillOrKillOrder.selector ) { // Decode single order @@ -98,8 +102,10 @@ contract MixinCoordinatorApprovalVerifier is selector == IExchange(address(0)).batchFillOrders.selector || selector == IExchange(address(0)).batchFillOrdersNoThrow.selector || selector == IExchange(address(0)).batchFillOrKillOrders.selector || - selector == IExchange(address(0)).marketBuyOrders.selector || - selector == IExchange(address(0)).marketSellOrders.selector + selector == IExchange(address(0)).marketBuyOrdersNoThrow.selector || + selector == IExchange(address(0)).marketBuyOrdersFillOrKill.selector || + selector == IExchange(address(0)).marketSellOrdersNoThrow.selector || + selector == IExchange(address(0)).marketSellOrdersFillOrKill.selector ) { // Decode all orders // solhint-disable indent @@ -107,7 +113,10 @@ contract MixinCoordinatorApprovalVerifier is data.slice(4, data.length), (LibOrder.Order[]) ); - } else if (selector == IExchange(address(0)).matchOrders.selector) { + } else if ( + selector == IExchange(address(0)).matchOrders.selector || + selector == IExchange(address(0)).matchOrdersWithMaximalFill.selector + ) { // Decode left and right orders (LibOrder.Order memory leftOrder, LibOrder.Order memory rightOrder) = abi.decode( data.slice(4, data.length), @@ -118,7 +127,16 @@ contract MixinCoordinatorApprovalVerifier is orders = new LibOrder.Order[](2); orders[0] = leftOrder; orders[1] = rightOrder; - } + } /* else if ( + selector == IExchange(address(0)).batchMatchOrders.selector || + selector == IExchange(address(0)).batchMatchOrdersWithMaximalFill.selector + ) { + // Decode left and right orders + (LibOrder.Order[] memory leftOrders, LibOrder.Order[] memory rightOrders) = abi.decode( + data.slice(4, data.length), + (LibOrder.Order[], LibOrder.Order[]) + ); + } */ return orders; } @@ -127,7 +145,8 @@ contract MixinCoordinatorApprovalVerifier is /// @param orders Array of order structs containing order specifications. /// @param txOrigin Required signer of Ethereum transaction calling this function. /// @param transactionSignature Proof that the transaction has been signed by the signer. - /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires. + /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each + /// corresponding approval signature expires. /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order. function _assertValidTransactionOrdersApproval( LibZeroExTransaction.ZeroExTransaction memory transaction, @@ -141,13 +160,12 @@ contract MixinCoordinatorApprovalVerifier is view { // Verify that Ethereum tx signer is the same as the approved txOrigin - require( - tx.origin == txOrigin, - "INVALID_ORIGIN" - ); + if (tx.origin != txOrigin) { + LibRichErrors.rrevert(LibCoordinatorRichErrors.InvalidOriginError(txOrigin)); + } // Hash 0x transaction - bytes32 transactionHash = getTransactionHash(transaction); + bytes32 transactionHash = LibZeroExTransaction.getTypedDataHash(transaction, EIP712_EXCHANGE_DOMAIN_HASH); // Create empty list of approval signers address[] memory approvalSignerAddresses = new address[](0); @@ -164,11 +182,13 @@ contract MixinCoordinatorApprovalVerifier is }); // Ensure approval has not expired - require( - // solhint-disable-next-line not-rely-on-time - currentApprovalExpirationTimeSeconds > block.timestamp, - "APPROVAL_EXPIRED" - ); + // solhint-disable-next-line not-rely-on-time + if (currentApprovalExpirationTimeSeconds <= block.timestamp) { + LibRichErrors.rrevert(LibCoordinatorRichErrors.ApprovalExpiredError( + transactionHash, + currentApprovalExpirationTimeSeconds + )); + } // Hash approval message and recover signer address bytes32 approvalHash = getCoordinatorApprovalHash(approval); @@ -191,10 +211,12 @@ contract MixinCoordinatorApprovalVerifier is // Ensure feeRecipient of order has approved this 0x transaction address approverAddress = orders[i].feeRecipientAddress; bool isOrderApproved = approvalSignerAddresses.contains(approverAddress); - require( - isOrderApproved, - "INVALID_APPROVAL_SIGNATURE" - ); + if (!isOrderApproved) { + LibRichErrors.rrevert(LibCoordinatorRichErrors.InvalidApprovalSignatureError( + transactionHash, + approverAddress + )); + } } } } diff --git a/contracts/coordinator/contracts/src/MixinCoordinatorCore.sol b/contracts/coordinator/contracts/src/MixinCoordinatorCore.sol index 67122c2923..85dcc092c1 100644 --- a/contracts/coordinator/contracts/src/MixinCoordinatorCore.sol +++ b/contracts/coordinator/contracts/src/MixinCoordinatorCore.sol @@ -20,22 +20,27 @@ pragma solidity ^0.5.9; pragma experimental ABIEncoderV2; import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol"; +import "@0x/contracts-utils/contracts/src/Refundable.sol"; import "./libs/LibConstants.sol"; import "./interfaces/ICoordinatorCore.sol"; import "./interfaces/ICoordinatorApprovalVerifier.sol"; contract MixinCoordinatorCore is + Refundable, LibConstants, ICoordinatorApprovalVerifier, ICoordinatorCore { - /// @dev Executes a 0x transaction that has been signed by the feeRecipients that correspond to each order in the transaction's Exchange calldata. + /// @dev Executes a 0x transaction that has been signed by the feeRecipients that correspond to + /// each order in the transaction's Exchange calldata. /// @param transaction 0x transaction containing salt, signerAddress, and data. /// @param txOrigin Required signer of Ethereum transaction calling this function. /// @param transactionSignature Proof that the transaction has been signed by the signer. - /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires. - /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order in the transaction's Exchange calldata. + /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each + /// corresponding approval signature expires. + /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each + /// order in the transaction's Exchange calldata. function executeTransaction( LibZeroExTransaction.ZeroExTransaction memory transaction, address txOrigin, @@ -44,6 +49,8 @@ contract MixinCoordinatorCore is bytes[] memory approvalSignatures ) public + payable + refundFinalBalance { // Validate that the 0x transaction has been approves by each feeRecipient assertValidCoordinatorApprovals( @@ -55,6 +62,6 @@ contract MixinCoordinatorCore is ); // Execute the transaction - EXCHANGE.executeTransaction(transaction, transactionSignature); + EXCHANGE.executeTransaction.value(msg.value)(transaction, transactionSignature); } } diff --git a/contracts/coordinator/contracts/src/MixinSignatureValidator.sol b/contracts/coordinator/contracts/src/MixinSignatureValidator.sol index a060ea4af1..0f940d135e 100644 --- a/contracts/coordinator/contracts/src/MixinSignatureValidator.sol +++ b/contracts/coordinator/contracts/src/MixinSignatureValidator.sol @@ -19,7 +19,9 @@ pragma solidity ^0.5.9; import "@0x/contracts-utils/contracts/src/LibBytes.sol"; +import "@0x/contracts-utils/contracts/src/LibRichErrors.sol"; import "./interfaces/ICoordinatorSignatureValidator.sol"; +import "./libs/LibCoordinatorRichErrors.sol"; contract MixinSignatureValidator is @@ -30,24 +32,32 @@ contract MixinSignatureValidator is /// @dev Recovers the address of a signer given a hash and signature. /// @param hash Any 32 byte hash. /// @param signature Proof that the hash has been signed by signer. + /// @return signerAddress Address of the signer. function getSignerAddress(bytes32 hash, bytes memory signature) public pure returns (address signerAddress) { - require( - signature.length > 0, - "LENGTH_GREATER_THAN_0_REQUIRED" - ); + uint256 signatureLength = signature.length; + if (signatureLength == 0) { + LibRichErrors.rrevert(LibCoordinatorRichErrors.SignatureError( + LibCoordinatorRichErrors.SignatureErrorCodes.INVALID_LENGTH, + hash, + signature + )); + } // Pop last byte off of signature byte array. uint8 signatureTypeRaw = uint8(signature.popLastByte()); // Ensure signature is supported - require( - signatureTypeRaw < uint8(SignatureType.NSignatureTypes), - "SIGNATURE_UNSUPPORTED" - ); + if (signatureTypeRaw >= uint8(SignatureType.NSignatureTypes)) { + LibRichErrors.rrevert(LibCoordinatorRichErrors.SignatureError( + LibCoordinatorRichErrors.SignatureErrorCodes.UNSUPPORTED, + hash, + signature + )); + } SignatureType signatureType = SignatureType(signatureTypeRaw); @@ -57,25 +67,32 @@ contract MixinSignatureValidator is // it an explicit option. This aids testing and analysis. It is // also the initialization value for the enum type. if (signatureType == SignatureType.Illegal) { - revert("SIGNATURE_ILLEGAL"); + LibRichErrors.rrevert(LibCoordinatorRichErrors.SignatureError( + LibCoordinatorRichErrors.SignatureErrorCodes.ILLEGAL, + hash, + signature + )); // Always invalid signature. // Like Illegal, this is always implicitly available and therefore // offered explicitly. It can be implicitly created by providing // a correctly formatted but incorrect signature. } else if (signatureType == SignatureType.Invalid) { - require( - signature.length == 0, - "LENGTH_0_REQUIRED" - ); - revert("SIGNATURE_INVALID"); + LibRichErrors.rrevert(LibCoordinatorRichErrors.SignatureError( + LibCoordinatorRichErrors.SignatureErrorCodes.INVALID, + hash, + signature + )); // Signature using EIP712 } else if (signatureType == SignatureType.EIP712) { - require( - signature.length == 65, - "LENGTH_65_REQUIRED" - ); + if (signatureLength != 66) { + LibRichErrors.rrevert(LibCoordinatorRichErrors.SignatureError( + LibCoordinatorRichErrors.SignatureErrorCodes.INVALID_LENGTH, + hash, + signature + )); + } uint8 v = uint8(signature[0]); bytes32 r = signature.readBytes32(1); bytes32 s = signature.readBytes32(33); @@ -89,10 +106,13 @@ contract MixinSignatureValidator is // Signed using web3.eth_sign } else if (signatureType == SignatureType.EthSign) { - require( - signature.length == 65, - "LENGTH_65_REQUIRED" - ); + if (signatureLength != 66) { + LibRichErrors.rrevert(LibCoordinatorRichErrors.SignatureError( + LibCoordinatorRichErrors.SignatureErrorCodes.INVALID_LENGTH, + hash, + signature + )); + } uint8 v = uint8(signature[0]); bytes32 r = signature.readBytes32(1); bytes32 s = signature.readBytes32(33); @@ -113,6 +133,10 @@ contract MixinSignatureValidator is // that we currently support. In this case returning false // may lead the caller to incorrectly believe that the // signature was invalid.) - revert("SIGNATURE_UNSUPPORTED"); + LibRichErrors.rrevert(LibCoordinatorRichErrors.SignatureError( + LibCoordinatorRichErrors.SignatureErrorCodes.UNSUPPORTED, + hash, + signature + )); } } diff --git a/contracts/coordinator/contracts/src/interfaces/ICoordinatorApprovalVerifier.sol b/contracts/coordinator/contracts/src/interfaces/ICoordinatorApprovalVerifier.sol index b5b39dac65..5d5ecebe7b 100644 --- a/contracts/coordinator/contracts/src/interfaces/ICoordinatorApprovalVerifier.sol +++ b/contracts/coordinator/contracts/src/interfaces/ICoordinatorApprovalVerifier.sol @@ -30,8 +30,10 @@ contract ICoordinatorApprovalVerifier { /// @param transaction 0x transaction containing salt, signerAddress, and data. /// @param txOrigin Required signer of Ethereum transaction calling this function. /// @param transactionSignature Proof that the transaction has been signed by the signer. - /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires. - /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order in the transaction's Exchange calldata. + /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each + /// corresponding approval signature expires. + /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each + /// order in the transaction's Exchange calldata. function assertValidCoordinatorApprovals( LibZeroExTransaction.ZeroExTransaction memory transaction, address txOrigin, @@ -44,7 +46,7 @@ contract ICoordinatorApprovalVerifier { /// @dev Decodes the orders from Exchange calldata representing any fill method. /// @param data Exchange calldata representing a fill method. - /// @return The orders from the Exchange calldata. + /// @return orders The orders from the Exchange calldata. function decodeOrdersFromFillData(bytes memory data) public pure diff --git a/contracts/coordinator/contracts/src/interfaces/ICoordinatorCore.sol b/contracts/coordinator/contracts/src/interfaces/ICoordinatorCore.sol index f758e00f06..5081869bbd 100644 --- a/contracts/coordinator/contracts/src/interfaces/ICoordinatorCore.sol +++ b/contracts/coordinator/contracts/src/interfaces/ICoordinatorCore.sol @@ -24,12 +24,15 @@ import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol"; contract ICoordinatorCore { - /// @dev Executes a 0x transaction that has been signed by the feeRecipients that correspond to each order in the transaction's Exchange calldata. + /// @dev Executes a 0x transaction that has been signed by the feeRecipients that correspond to + /// each order in the transaction's Exchange calldata. /// @param transaction 0x transaction containing salt, signerAddress, and data. /// @param txOrigin Required signer of Ethereum transaction calling this function. /// @param transactionSignature Proof that the transaction has been signed by the signer. - /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires. - /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order in the transaction's Exchange calldata. + /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each + /// corresponding approval signature expires. + /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each + /// order in the transaction's Exchange calldata. function executeTransaction( LibZeroExTransaction.ZeroExTransaction memory transaction, address txOrigin, @@ -37,5 +40,6 @@ contract ICoordinatorCore { uint256[] memory approvalExpirationTimeSeconds, bytes[] memory approvalSignatures ) - public; + public + payable; } diff --git a/contracts/coordinator/contracts/src/interfaces/ICoordinatorSignatureValidator.sol b/contracts/coordinator/contracts/src/interfaces/ICoordinatorSignatureValidator.sol index 74288ab9d5..8152a4d5ec 100644 --- a/contracts/coordinator/contracts/src/interfaces/ICoordinatorSignatureValidator.sol +++ b/contracts/coordinator/contracts/src/interfaces/ICoordinatorSignatureValidator.sol @@ -30,14 +30,14 @@ contract ICoordinatorSignatureValidator { Wallet, // 0x04 Validator, // 0x05 PreSigned, // 0x06 - OrderValidator, // 0x07 - WalletOrderValidator, // 0x08 - NSignatureTypes // 0x09, number of signature types. Always leave at end. + EIP1271Wallet, // 0x07 + NSignatureTypes // 0x08, number of signature types. Always leave at end. } /// @dev Recovers the address of a signer given a hash and signature. /// @param hash Any 32 byte hash. /// @param signature Proof that the hash has been signed by signer. + /// @return signerAddress Address of the signer. function getSignerAddress(bytes32 hash, bytes memory signature) public pure diff --git a/contracts/coordinator/contracts/src/libs/LibCoordinatorApproval.sol b/contracts/coordinator/contracts/src/libs/LibCoordinatorApproval.sol index 693f52ffb7..de647c5308 100644 --- a/contracts/coordinator/contracts/src/libs/LibCoordinatorApproval.sol +++ b/contracts/coordinator/contracts/src/libs/LibCoordinatorApproval.sol @@ -34,7 +34,8 @@ contract LibCoordinatorApproval is // "uint256 approvalExpirationTimeSeconds", // ")" // )); - bytes32 constant public EIP712_COORDINATOR_APPROVAL_SCHEMA_HASH = 0x2fbcdbaa76bc7589916958ae919dfbef04d23f6bbf26de6ff317b32c6cc01e05; + bytes32 constant public EIP712_COORDINATOR_APPROVAL_SCHEMA_HASH = + 0x2fbcdbaa76bc7589916958ae919dfbef04d23f6bbf26de6ff317b32c6cc01e05; struct CoordinatorApproval { address txOrigin; // Required signer of Ethereum transaction that is submitting approval. @@ -43,9 +44,12 @@ contract LibCoordinatorApproval is uint256 approvalExpirationTimeSeconds; // Timestamp in seconds for which the approval expires. } - /// @dev Calculated the EIP712 hash of the Coordinator approval mesasage using the domain separator of this contract. - /// @param approval Coordinator approval message containing the transaction hash, transaction signature, and expiration of the approval. - /// @return EIP712 hash of the Coordinator approval message with the domain separator of this contract. + /// @dev Calculates the EIP712 hash of the Coordinator approval mesasage using the domain + /// separator of this contract. + /// @param approval Coordinator approval message containing the transaction hash, transaction + /// signature, and expiration of the approval. + /// @return approvalHash EIP712 hash of the Coordinator approval message with the domain + /// separator of this contract. function getCoordinatorApprovalHash(CoordinatorApproval memory approval) public view @@ -55,9 +59,10 @@ contract LibCoordinatorApproval is return approvalHash; } - /// @dev Calculated the EIP712 hash of the Coordinator approval mesasage with no domain separator. - /// @param approval Coordinator approval message containing the transaction hash, transaction signature, and expiration of the approval. - /// @return EIP712 hash of the Coordinator approval message with no domain separator. + /// @dev Calculates the EIP712 hash of the Coordinator approval mesasage with no domain separator. + /// @param approval Coordinator approval message containing the transaction hash, transaction + // signature, and expiration of the approval. + /// @return result EIP712 hash of the Coordinator approval message with no domain separator. function _hashCoordinatorApproval(CoordinatorApproval memory approval) internal pure diff --git a/contracts/coordinator/contracts/src/libs/LibCoordinatorRichErrors.sol b/contracts/coordinator/contracts/src/libs/LibCoordinatorRichErrors.sol new file mode 100644 index 0000000000..14f93ed359 --- /dev/null +++ b/contracts/coordinator/contracts/src/libs/LibCoordinatorRichErrors.sol @@ -0,0 +1,106 @@ +/* + + Copyright 2019 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.5.9; + + +library LibCoordinatorRichErrors { + enum SignatureErrorCodes { + INVALID_LENGTH, + UNSUPPORTED, + ILLEGAL, + INVALID + } + + // bytes4(keccak256("SignatureError(uint8,bytes32,bytes)")) + bytes4 internal constant SIGNATURE_ERROR_SELECTOR = + 0x779c5223; + + // bytes4(keccak256("InvalidOriginError(address)")) + bytes4 internal constant INVALID_ORIGIN_ERROR_SELECTOR = + 0xa458d7ff; + + // bytes4(keccak256("ApprovalExpiredError(bytes32,uint256)")) + bytes4 internal constant APPROVAL_EXPIRED_ERROR_SELECTOR = + 0x677b712d; + + // bytes4(keccak256("InvalidApprovalSignatureError(bytes32,address)")) + bytes4 internal constant INVALID_APPROVAL_SIGNATURE_ERROR_SELECTOR = + 0xd789b640; + + // solhint-disable func-name-mixedcase + function SignatureError( + SignatureErrorCodes errorCode, + bytes32 hash, + bytes memory signature + ) + internal + pure + returns (bytes memory) + { + return abi.encodeWithSelector( + SIGNATURE_ERROR_SELECTOR, + errorCode, + hash, + signature + ); + } + + function InvalidOriginError( + address expectedOrigin + ) + internal + pure + returns (bytes memory) + { + return abi.encodeWithSelector( + INVALID_ORIGIN_ERROR_SELECTOR, + expectedOrigin + ); + } + + function ApprovalExpiredError( + bytes32 transactionHash, + uint256 approvalExpirationTime + ) + internal + pure + returns (bytes memory) + { + return abi.encodeWithSelector( + APPROVAL_EXPIRED_ERROR_SELECTOR, + transactionHash, + approvalExpirationTime + ); + } + + function InvalidApprovalSignatureError( + bytes32 transactionHash, + address approverAddress + ) + internal + pure + returns (bytes memory) + { + return abi.encodeWithSelector( + INVALID_APPROVAL_SIGNATURE_ERROR_SELECTOR, + transactionHash, + approverAddress + ); + } +} diff --git a/contracts/coordinator/contracts/src/libs/LibEIP712CoordinatorDomain.sol b/contracts/coordinator/contracts/src/libs/LibEIP712CoordinatorDomain.sol index 13abe0611f..0025205c61 100644 --- a/contracts/coordinator/contracts/src/libs/LibEIP712CoordinatorDomain.sol +++ b/contracts/coordinator/contracts/src/libs/LibEIP712CoordinatorDomain.sol @@ -21,15 +21,13 @@ pragma solidity ^0.5.9; import "@0x/contracts-utils/contracts/src/LibEIP712.sol"; -contract LibEIP712CoordinatorDomain is - LibEIP712 -{ +contract LibEIP712CoordinatorDomain { // EIP712 Domain Name value for the Coordinator string constant public EIP712_COORDINATOR_DOMAIN_NAME = "0x Protocol Coordinator"; // EIP712 Domain Version value for the Coordinator - string constant public EIP712_COORDINATOR_DOMAIN_VERSION = "2.0.0"; + string constant public EIP712_COORDINATOR_DOMAIN_VERSION = "3.0.0"; // Hash of the EIP712 Domain Separator data for the Coordinator // solhint-disable-next-line var-name-mixedcase @@ -43,7 +41,9 @@ contract LibEIP712CoordinatorDomain is ) public { - address verifyingContractAddress = verifyingContractAddressIfExists == address(0) ? address(this) : verifyingContractAddressIfExists; + address verifyingContractAddress = verifyingContractAddressIfExists == address(0) + ? address(this) + : verifyingContractAddressIfExists; EIP712_COORDINATOR_DOMAIN_HASH = LibEIP712.hashEIP712Domain( EIP712_COORDINATOR_DOMAIN_NAME, EIP712_COORDINATOR_DOMAIN_VERSION, @@ -55,7 +55,7 @@ contract LibEIP712CoordinatorDomain is /// @dev Calculates EIP712 encoding for a hash struct in the EIP712 domain /// of this contract. /// @param hashStruct The EIP712 hash struct. - /// @return EIP712 hash applied to this EIP712 Domain. + /// @return result EIP712 hash applied to this EIP712 Domain. function _hashEIP712CoordinatorMessage(bytes32 hashStruct) internal view diff --git a/contracts/coordinator/contracts/src/registry/MixinCoordinatorRegistryCore.sol b/contracts/coordinator/contracts/src/registry/MixinCoordinatorRegistryCore.sol index 6c96e5b902..799c668e04 100644 --- a/contracts/coordinator/contracts/src/registry/MixinCoordinatorRegistryCore.sol +++ b/contracts/coordinator/contracts/src/registry/MixinCoordinatorRegistryCore.sol @@ -29,7 +29,7 @@ contract MixinCoordinatorRegistryCore is mapping (address => string) internal coordinatorEndpoints; /// @dev Called by a Coordinator operator to set the endpoint of their Coordinator. - /// @param coordinatorEndpoint endpoint of the Coordinator. + /// @param coordinatorEndpoint Endpoint of the Coordinator as a string. function setCoordinatorEndpoint(string calldata coordinatorEndpoint) external { address coordinatorOperator = msg.sender; coordinatorEndpoints[coordinatorOperator] = coordinatorEndpoint; @@ -37,7 +37,8 @@ contract MixinCoordinatorRegistryCore is } /// @dev Gets the endpoint for a Coordinator. - /// @param coordinatorOperator operator of the Coordinator endpoint. + /// @param coordinatorOperator Operator of the Coordinator endpoint. + /// @return coordinatorEndpoint Endpoint of the Coordinator as a string. function getCoordinatorEndpoint(address coordinatorOperator) external view diff --git a/contracts/coordinator/contracts/src/registry/interfaces/ICoordinatorRegistryCore.sol b/contracts/coordinator/contracts/src/registry/interfaces/ICoordinatorRegistryCore.sol index f9c3068d05..c562c4f159 100644 --- a/contracts/coordinator/contracts/src/registry/interfaces/ICoordinatorRegistryCore.sol +++ b/contracts/coordinator/contracts/src/registry/interfaces/ICoordinatorRegistryCore.sol @@ -29,11 +29,12 @@ contract ICoordinatorRegistryCore ); /// @dev Called by a Coordinator operator to set the endpoint of their Coordinator. - /// @param coordinatorEndpoint endpoint of the Coordinator. + /// @param coordinatorEndpoint Endpoint of the Coordinator as a string. function setCoordinatorEndpoint(string calldata coordinatorEndpoint) external; /// @dev Gets the endpoint for a Coordinator. - /// @param coordinatorOperator operator of the Coordinator endpoint. + /// @param coordinatorOperator Operator of the Coordinator endpoint. + /// @return coordinatorEndpoint Endpoint of the Coordinator as a string. function getCoordinatorEndpoint(address coordinatorOperator) external view diff --git a/contracts/utils/contracts/src/LibEIP712.sol b/contracts/utils/contracts/src/LibEIP712.sol index 3cad675629..38d08fbf12 100644 --- a/contracts/utils/contracts/src/LibEIP712.sol +++ b/contracts/utils/contracts/src/LibEIP712.sol @@ -31,17 +31,17 @@ library LibEIP712 { // ")" // )) bytes32 constant internal _EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f; - + /// @dev Calculates a EIP712 domain separator. /// @param name The EIP712 domain name. /// @param version The EIP712 domain version. - /// @param verifyingContractAddress The EIP712 verifying contract. + /// @param verifyingContract The EIP712 verifying contract. /// @return EIP712 domain separator. function hashEIP712Domain( string memory name, string memory version, uint256 chainId, - address verifyingContractAddress + address verifyingContract ) internal pure @@ -55,7 +55,7 @@ library LibEIP712 { // keccak256(bytes(name)), // keccak256(bytes(version)), // chainId, - // uint256(verifyingContractAddress) + // uint256(verifyingContract) // )) assembly { @@ -71,7 +71,7 @@ library LibEIP712 { mstore(add(memPtr, 32), nameHash) mstore(add(memPtr, 64), versionHash) mstore(add(memPtr, 96), chainId) - mstore(add(memPtr, 128), verifyingContractAddress) + mstore(add(memPtr, 128), verifyingContract) // Compute hash result := keccak256(memPtr, 160) diff --git a/packages/order-utils/src/coordinator_revert_errors.ts b/packages/order-utils/src/coordinator_revert_errors.ts new file mode 100644 index 0000000000..e97831c555 --- /dev/null +++ b/packages/order-utils/src/coordinator_revert_errors.ts @@ -0,0 +1,52 @@ +import { BigNumber, RevertError } from '@0x/utils'; + +// tslint:disable:max-classes-per-file + +export enum SignatureErrorCodes { + InvalidLength, + Unsupported, + Illegal, + Invalid, +} + +export class SignatureError extends RevertError { + constructor(errorCode?: SignatureErrorCodes, hash?: string, signature?: string) { + super('SignatureError', 'SignatureError(uint8 errorCode, bytes32 hash, bytes signature)', { + errorCode, + hash, + signature, + }); + } +} + +export class InvalidOriginError extends RevertError { + constructor(expectedOrigin?: string) { + super('InvalidOriginError', 'InvalidOriginError(address expectedOrigin)', { expectedOrigin }); + } +} + +export class ApprovalExpiredError extends RevertError { + constructor(transactionHash?: string, approvalExpirationTime?: BigNumber | number | string) { + super('ApprovalExpiredError', 'ApprovalExpiredError(bytes32 transactionHash, uint256 approvalExpirationTime)', { + transactionHash, + approvalExpirationTime, + }); + } +} + +export class InvalidApprovalSignature extends RevertError { + constructor(transactionHash?: string, approverAddress?: string) { + super( + 'InvalidApprovalSignature', + 'InvalidApprovalSignature(bytes32 transactionHash, address approverAddress)', + { transactionHash, approverAddress }, + ); + } +} + +const types = [SignatureError, InvalidOriginError, ApprovalExpiredError, InvalidApprovalSignature]; + +// Register the types we've defined. +for (const type of types) { + RevertError.registerType(type); +} From 9b922f746bfc1db9ca90f3222b29243ef077481a Mon Sep 17 00:00:00 2001 From: Michael Zhu Date: Mon, 30 Sep 2019 19:22:18 -0700 Subject: [PATCH 28/87] Update coordinator tests --- .../contracts/src/MixinSignatureValidator.sol | 2 +- contracts/coordinator/package.json | 2 +- contracts/coordinator/src/artifacts.ts | 24 + contracts/coordinator/src/wrappers.ts | 12 + contracts/coordinator/test/coordinator.ts | 512 ++++++++---------- .../coordinator/test/coordinator_registry.ts | 27 +- contracts/coordinator/test/libs.ts | 49 +- contracts/coordinator/test/mixins.ts | 300 +++++----- .../utils/coordinator_registry_wrapper.ts | 3 +- contracts/coordinator/tsconfig.json | 17 +- packages/order-utils/src/constants.ts | 2 +- .../src/coordinator_revert_errors.ts | 8 +- packages/order-utils/src/eip712_utils.ts | 2 +- packages/order-utils/src/index.ts | 1 + 14 files changed, 454 insertions(+), 507 deletions(-) diff --git a/contracts/coordinator/contracts/src/MixinSignatureValidator.sol b/contracts/coordinator/contracts/src/MixinSignatureValidator.sol index 0f940d135e..8a3e79dac2 100644 --- a/contracts/coordinator/contracts/src/MixinSignatureValidator.sol +++ b/contracts/coordinator/contracts/src/MixinSignatureValidator.sol @@ -48,7 +48,7 @@ contract MixinSignatureValidator is } // Pop last byte off of signature byte array. - uint8 signatureTypeRaw = uint8(signature.popLastByte()); + uint8 signatureTypeRaw = uint8(signature[signature.length - 1]); // Ensure signature is supported if (signatureTypeRaw >= uint8(SignatureType.NSignatureTypes)) { diff --git a/contracts/coordinator/package.json b/contracts/coordinator/package.json index 17b480ea21..16de8c364c 100644 --- a/contracts/coordinator/package.json +++ b/contracts/coordinator/package.json @@ -35,7 +35,7 @@ "compile:truffle": "truffle compile" }, "config": { - "abis": "./generated-artifacts/@(Coordinator|CoordinatorRegistry).json", + "abis": "./generated-artifacts/@(Coordinator|CoordinatorRegistry|ICoordinatorApprovalVerifier|ICoordinatorCore|ICoordinatorRegistryCore|ICoordinatorSignatureValidator|LibConstants|LibCoordinatorApproval|LibCoordinatorRichErrors|LibEIP712CoordinatorDomain|MixinCoordinatorApprovalVerifier|MixinCoordinatorCore|MixinCoordinatorRegistryCore|MixinSignatureValidator).json", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually." }, "repository": { diff --git a/contracts/coordinator/src/artifacts.ts b/contracts/coordinator/src/artifacts.ts index 8276964486..9722198ad8 100644 --- a/contracts/coordinator/src/artifacts.ts +++ b/contracts/coordinator/src/artifacts.ts @@ -7,7 +7,31 @@ import { ContractArtifact } from 'ethereum-types'; import * as Coordinator from '../generated-artifacts/Coordinator.json'; import * as CoordinatorRegistry from '../generated-artifacts/CoordinatorRegistry.json'; +import * as ICoordinatorApprovalVerifier from '../generated-artifacts/ICoordinatorApprovalVerifier.json'; +import * as ICoordinatorCore from '../generated-artifacts/ICoordinatorCore.json'; +import * as ICoordinatorRegistryCore from '../generated-artifacts/ICoordinatorRegistryCore.json'; +import * as ICoordinatorSignatureValidator from '../generated-artifacts/ICoordinatorSignatureValidator.json'; +import * as LibConstants from '../generated-artifacts/LibConstants.json'; +import * as LibCoordinatorApproval from '../generated-artifacts/LibCoordinatorApproval.json'; +import * as LibCoordinatorRichErrors from '../generated-artifacts/LibCoordinatorRichErrors.json'; +import * as LibEIP712CoordinatorDomain from '../generated-artifacts/LibEIP712CoordinatorDomain.json'; +import * as MixinCoordinatorApprovalVerifier from '../generated-artifacts/MixinCoordinatorApprovalVerifier.json'; +import * as MixinCoordinatorCore from '../generated-artifacts/MixinCoordinatorCore.json'; +import * as MixinCoordinatorRegistryCore from '../generated-artifacts/MixinCoordinatorRegistryCore.json'; +import * as MixinSignatureValidator from '../generated-artifacts/MixinSignatureValidator.json'; export const artifacts = { Coordinator: Coordinator as ContractArtifact, + MixinCoordinatorApprovalVerifier: MixinCoordinatorApprovalVerifier as ContractArtifact, + MixinCoordinatorCore: MixinCoordinatorCore as ContractArtifact, + MixinSignatureValidator: MixinSignatureValidator as ContractArtifact, + ICoordinatorApprovalVerifier: ICoordinatorApprovalVerifier as ContractArtifact, + ICoordinatorCore: ICoordinatorCore as ContractArtifact, + ICoordinatorSignatureValidator: ICoordinatorSignatureValidator as ContractArtifact, + LibConstants: LibConstants as ContractArtifact, + LibCoordinatorApproval: LibCoordinatorApproval as ContractArtifact, + LibCoordinatorRichErrors: LibCoordinatorRichErrors as ContractArtifact, + LibEIP712CoordinatorDomain: LibEIP712CoordinatorDomain as ContractArtifact, CoordinatorRegistry: CoordinatorRegistry as ContractArtifact, + MixinCoordinatorRegistryCore: MixinCoordinatorRegistryCore as ContractArtifact, + ICoordinatorRegistryCore: ICoordinatorRegistryCore as ContractArtifact, }; diff --git a/contracts/coordinator/src/wrappers.ts b/contracts/coordinator/src/wrappers.ts index a88791dffa..1307b59821 100644 --- a/contracts/coordinator/src/wrappers.ts +++ b/contracts/coordinator/src/wrappers.ts @@ -5,3 +5,15 @@ */ export * from '../generated-wrappers/coordinator'; export * from '../generated-wrappers/coordinator_registry'; +export * from '../generated-wrappers/i_coordinator_approval_verifier'; +export * from '../generated-wrappers/i_coordinator_core'; +export * from '../generated-wrappers/i_coordinator_registry_core'; +export * from '../generated-wrappers/i_coordinator_signature_validator'; +export * from '../generated-wrappers/lib_constants'; +export * from '../generated-wrappers/lib_coordinator_approval'; +export * from '../generated-wrappers/lib_coordinator_rich_errors'; +export * from '../generated-wrappers/lib_e_i_p712_coordinator_domain'; +export * from '../generated-wrappers/mixin_coordinator_approval_verifier'; +export * from '../generated-wrappers/mixin_coordinator_core'; +export * from '../generated-wrappers/mixin_coordinator_registry_core'; +export * from '../generated-wrappers/mixin_signature_validator'; diff --git a/contracts/coordinator/test/coordinator.ts b/contracts/coordinator/test/coordinator.ts index ac3d2cd108..27e90c49f6 100644 --- a/contracts/coordinator/test/coordinator.ts +++ b/contracts/coordinator/test/coordinator.ts @@ -7,35 +7,28 @@ import { ExchangeCancelUpToEventArgs, ExchangeContract, exchangeDataEncoder, + ExchangeEvents, ExchangeFillEventArgs, ExchangeFunctionName, } from '@0x/contracts-exchange'; import { - chaiSetup, + blockchainTests, constants, - expectTransactionFailedAsync, + expect, + filterLogsToArguments, getLatestBlockTimestampAsync, OrderFactory, - provider, TransactionFactory, - txDefaults, - web3Wrapper, } from '@0x/contracts-test-utils'; -import { BlockchainLifecycle } from '@0x/dev-utils'; -import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; -import { RevertReason } from '@0x/types'; -import { BigNumber, providerUtils } from '@0x/utils'; -import * as chai from 'chai'; -import { LogWithDecodedArgs } from 'ethereum-types'; +import { assetDataUtils, CoordinatorRevertErrors, orderHashUtils, transactionHashUtils } from '@0x/order-utils'; +import { SignedOrder } from '@0x/types'; +import { BigNumber } from '@0x/utils'; +import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import { ApprovalFactory, artifacts, CoordinatorContract } from '../src'; -chaiSetup.configure(); -const expect = chai.expect; -const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); -web3Wrapper.abiDecoder.addABI(exchangeArtifacts.Exchange.compilerOutput.abi); // tslint:disable:no-unnecessary-type-assertion -describe('Coordinator tests', () => { +blockchainTests.resets('Coordinator tests', env => { let chainId: number; let makerAddress: string; let owner: string; @@ -55,18 +48,17 @@ describe('Coordinator tests', () => { let makerTransactionFactory: TransactionFactory; let approvalFactory: ApprovalFactory; + // const GAS_PRICE = new BigNumber(env.txDefaults.gasPrice || constants.DEFAULT_GAS_PRICE); + // const PROTOCOL_FEE_MULTIPLIER = new BigNumber(150); + // const PROTOCOL_FEE = GAS_PRICE.times(PROTOCOL_FEE_MULTIPLIER); + const PROTOCOL_FEE = new BigNumber(0); + before(async () => { - await blockchainLifecycle.startAsync(); - }); - after(async () => { - await blockchainLifecycle.revertAsync(); - }); - before(async () => { - chainId = await providerUtils.getChainIdAsync(provider); - const accounts = await web3Wrapper.getAvailableAddressesAsync(); - const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = accounts.slice(0, 4)); + chainId = await env.getChainIdAsync(); + const accounts = await env.getAccountAddressesAsync(); + const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = accounts); - erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner); + erc20Wrapper = new ERC20Wrapper(env.provider, usedAddresses, owner); erc20Proxy = await erc20Wrapper.deployProxyAsync(); const numDummyErc20ToDeploy = 3; [erc20TokenA, erc20TokenB, makerFeeToken] = await erc20Wrapper.deployDummyTokensAsync( @@ -77,26 +69,28 @@ describe('Coordinator tests', () => { exchange = await ExchangeContract.deployFrom0xArtifactAsync( exchangeArtifacts.Exchange, - provider, - txDefaults, + env.provider, + env.txDefaults, + {}, new BigNumber(chainId), ); - await web3Wrapper.awaitTransactionSuccessAsync( - await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: owner }), + await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( + exchange.address, + { from: owner }, constants.AWAIT_TRANSACTION_MINED_MS, ); - - await web3Wrapper.awaitTransactionSuccessAsync( - await exchange.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, { from: owner }), + await exchange.registerAssetProxy.awaitTransactionSuccessAsync( + erc20Proxy.address, + { from: owner }, constants.AWAIT_TRANSACTION_MINED_MS, ); coordinatorContract = await CoordinatorContract.deployFrom0xArtifactAsync( artifacts.Coordinator, - provider, - txDefaults, - artifacts, + env.provider, + env.txDefaults, + { ...exchangeArtifacts, ...artifacts }, exchange.address, new BigNumber(chainId), ); @@ -106,6 +100,7 @@ describe('Coordinator tests', () => { ...constants.STATIC_ORDER_PARAMS, senderAddress: coordinatorContract.address, makerAddress, + takerAddress, feeRecipientAddress, makerAssetData: assetDataUtils.encodeERC20AssetData(erc20TokenA.address), takerAssetData: assetDataUtils.encodeERC20AssetData(erc20TokenB.address), @@ -122,12 +117,48 @@ describe('Coordinator tests', () => { takerTransactionFactory = new TransactionFactory(takerPrivateKey, exchange.address, chainId); approvalFactory = new ApprovalFactory(feeRecipientPrivateKey, coordinatorContract.address); }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); + + function verifyEvents( + txReceipt: TransactionReceiptWithDecodedLogs, + expectedEvents: TEventArgs[], + eventName: string, + ): void { + const logs = filterLogsToArguments(txReceipt.logs, eventName); + expect(logs.length).to.eq(expectedEvents.length); + logs.forEach((log, index) => { + expect(log).to.deep.equal(expectedEvents[index]); + }); + } + + function expectedFillEvent(order: SignedOrder): ExchangeFillEventArgs { + return { + makerAddress: order.makerAddress, + feeRecipientAddress: order.feeRecipientAddress, + makerAssetData: order.makerAssetData, + takerAssetData: order.takerAssetData, + makerFeeAssetData: order.makerFeeAssetData, + takerFeeAssetData: order.takerFeeAssetData, + takerAddress: order.takerAddress, + senderAddress: order.senderAddress, + makerAssetFilledAmount: order.makerAssetAmount, + takerAssetFilledAmount: order.takerAssetAmount, + makerFeePaid: order.makerFee, + takerFeePaid: order.takerFee, + protocolFeePaid: PROTOCOL_FEE, + orderHash: orderHashUtils.getOrderHashHex(order), + }; + } + + function expectedCancelEvent(order: SignedOrder): ExchangeCancelEventArgs { + return { + makerAddress: order.makerAddress, + feeRecipientAddress: order.feeRecipientAddress, + makerAssetData: order.makerAssetData, + takerAssetData: order.takerAssetData, + senderAddress: order.senderAddress, + orderHash: orderHashUtils.getOrderHashHex(order), + }; + } describe('single order fills', () => { for (const fnName of exchangeConstants.SINGLE_FILL_FN_NAMES) { @@ -142,83 +173,52 @@ describe('Coordinator tests', () => { takerAddress, approvalExpirationTimeSeconds, ); - const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync( - await coordinatorContract.executeTransaction.sendTransactionAsync( - transaction, - takerAddress, - transaction.signature, - [approvalExpirationTimeSeconds], - [approval.signature], - { from: takerAddress }, - ), + const transactionReceipt = await coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + transaction, + takerAddress, + transaction.signature, + [approvalExpirationTimeSeconds], + [approval.signature], + { from: takerAddress }, constants.AWAIT_TRANSACTION_MINED_MS, ); - const fillLogs = transactionReceipt.logs.filter( - log => (log as LogWithDecodedArgs).event === 'Fill', - ); - expect(fillLogs.length).to.eq(1); - const fillLogArgs = (fillLogs[0] as LogWithDecodedArgs).args; - expect(fillLogArgs.makerAddress).to.eq(makerAddress); - expect(fillLogArgs.takerAddress).to.eq(takerAddress); - expect(fillLogArgs.senderAddress).to.eq(coordinatorContract.address); - expect(fillLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress); - expect(fillLogArgs.makerAssetData).to.eq(orders[0].makerAssetData); - expect(fillLogArgs.takerAssetData).to.eq(orders[0].takerAssetData); - expect(fillLogArgs.makerAssetFilledAmount).to.bignumber.eq(orders[0].makerAssetAmount); - expect(fillLogArgs.takerAssetFilledAmount).to.bignumber.eq(orders[0].takerAssetAmount); - expect(fillLogArgs.makerFeePaid).to.bignumber.eq(orders[0].makerFee); - expect(fillLogArgs.takerFeePaid).to.bignumber.eq(orders[0].takerFee); - expect(fillLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(orders[0])); + + verifyEvents(transactionReceipt, [expectedFillEvent(orders[0])], ExchangeEvents.Fill); }); it(`${fnName} should fill the order if called by approver`, async () => { const orders = [await orderFactory.newSignedOrderAsync()]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); - const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync( - await coordinatorContract.executeTransaction.sendTransactionAsync( - transaction, - feeRecipientAddress, - transaction.signature, - [], - [], - { from: feeRecipientAddress }, - ), + const transactionReceipt = await coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + transaction, + feeRecipientAddress, + transaction.signature, + [], + [], + { from: feeRecipientAddress }, constants.AWAIT_TRANSACTION_MINED_MS, ); - const fillLogs = transactionReceipt.logs.filter( - log => (log as LogWithDecodedArgs).event === 'Fill', - ); - expect(fillLogs.length).to.eq(1); - const fillLogArgs = (fillLogs[0] as LogWithDecodedArgs).args; - expect(fillLogArgs.makerAddress).to.eq(makerAddress); - expect(fillLogArgs.takerAddress).to.eq(takerAddress); - expect(fillLogArgs.senderAddress).to.eq(coordinatorContract.address); - expect(fillLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress); - expect(fillLogArgs.makerAssetData).to.eq(orders[0].makerAssetData); - expect(fillLogArgs.takerAssetData).to.eq(orders[0].takerAssetData); - expect(fillLogArgs.makerAssetFilledAmount).to.bignumber.eq(orders[0].makerAssetAmount); - expect(fillLogArgs.takerAssetFilledAmount).to.bignumber.eq(orders[0].takerAssetAmount); - expect(fillLogArgs.makerFeePaid).to.bignumber.eq(orders[0].makerFee); - expect(fillLogArgs.takerFeePaid).to.bignumber.eq(orders[0].takerFee); - expect(fillLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(orders[0])); + verifyEvents(transactionReceipt, [expectedFillEvent(orders[0])], ExchangeEvents.Fill); }); it(`${fnName} should revert with no approval signature`, async () => { const orders = [await orderFactory.newSignedOrderAsync()]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); - await expectTransactionFailedAsync( - coordinatorContract.executeTransaction.sendTransactionAsync( - transaction, - takerAddress, - transaction.signature, - [], - [], - { - from: takerAddress, - gas: constants.MAX_EXECUTE_TRANSACTION_GAS, - }, - ), - RevertReason.InvalidApprovalSignature, + const tx = coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + transaction, + takerAddress, + transaction.signature, + [], + [], + { + from: takerAddress, + gas: constants.MAX_EXECUTE_TRANSACTION_GAS, + }, + ); + + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + expect(tx).to.revertWith( + new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, feeRecipientAddress), ); }); it(`${fnName} should revert with an invalid approval signature`, async () => { @@ -233,16 +233,18 @@ describe('Coordinator tests', () => { approvalExpirationTimeSeconds, ); const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`; - await expectTransactionFailedAsync( - coordinatorContract.executeTransaction.sendTransactionAsync( - transaction, - takerAddress, - transaction.signature, - [approvalExpirationTimeSeconds], - [signature], - { from: takerAddress }, - ), - RevertReason.InvalidApprovalSignature, + const tx = coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + transaction, + takerAddress, + transaction.signature, + [approvalExpirationTimeSeconds], + [signature], + { from: takerAddress }, + ); + + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + expect(tx).to.revertWith( + new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, feeRecipientAddress), ); }); it(`${fnName} should revert with an expired approval`, async () => { @@ -256,16 +258,19 @@ describe('Coordinator tests', () => { takerAddress, approvalExpirationTimeSeconds, ); - await expectTransactionFailedAsync( - coordinatorContract.executeTransaction.sendTransactionAsync( - transaction, - takerAddress, - transaction.signature, - [approvalExpirationTimeSeconds], - [approval.signature], - { from: takerAddress }, - ), - RevertReason.ApprovalExpired, + + const tx = coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + transaction, + takerAddress, + transaction.signature, + [approvalExpirationTimeSeconds], + [approval.signature], + { from: takerAddress }, + ); + + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + expect(tx).to.revertWith( + new CoordinatorRevertErrors.ApprovalExpiredError(transactionHash, approvalExpirationTimeSeconds), ); }); it(`${fnName} should revert if not called by tx signer or approver`, async () => { @@ -279,17 +284,16 @@ describe('Coordinator tests', () => { takerAddress, approvalExpirationTimeSeconds, ); - await expectTransactionFailedAsync( - coordinatorContract.executeTransaction.sendTransactionAsync( - transaction, - takerAddress, - transaction.signature, - [approvalExpirationTimeSeconds], - [approval.signature], - { from: owner }, - ), - RevertReason.InvalidOrigin, + + const tx = coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + transaction, + takerAddress, + transaction.signature, + [approvalExpirationTimeSeconds], + [approval.signature], + { from: owner }, ); + expect(tx).to.revertWith(new CoordinatorRevertErrors.InvalidOriginError(takerAddress)); }); } }); @@ -306,69 +310,35 @@ describe('Coordinator tests', () => { takerAddress, approvalExpirationTimeSeconds, ); - const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync( - await coordinatorContract.executeTransaction.sendTransactionAsync( - transaction, - takerAddress, - transaction.signature, - [approvalExpirationTimeSeconds], - [approval.signature], - { from: takerAddress, gas: constants.MAX_EXECUTE_TRANSACTION_GAS }, - ), + const transactionReceipt = await coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + transaction, + takerAddress, + transaction.signature, + [approvalExpirationTimeSeconds], + [approval.signature], + { from: takerAddress, gas: constants.MAX_EXECUTE_TRANSACTION_GAS }, constants.AWAIT_TRANSACTION_MINED_MS, ); - const fillLogs = transactionReceipt.logs.filter( - log => (log as LogWithDecodedArgs).event === 'Fill', - ); - expect(fillLogs.length).to.eq(orders.length); - orders.forEach((order, index) => { - const fillLogArgs = (fillLogs[index] as LogWithDecodedArgs).args; - expect(fillLogArgs.makerAddress).to.eq(makerAddress); - expect(fillLogArgs.takerAddress).to.eq(takerAddress); - expect(fillLogArgs.senderAddress).to.eq(coordinatorContract.address); - expect(fillLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress); - expect(fillLogArgs.makerAssetData).to.eq(order.makerAssetData); - expect(fillLogArgs.takerAssetData).to.eq(order.takerAssetData); - expect(fillLogArgs.makerAssetFilledAmount).to.bignumber.eq(order.makerAssetAmount); - expect(fillLogArgs.takerAssetFilledAmount).to.bignumber.eq(order.takerAssetAmount); - expect(fillLogArgs.makerFeePaid).to.bignumber.eq(order.makerFee); - expect(fillLogArgs.takerFeePaid).to.bignumber.eq(order.takerFee); - expect(fillLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(order)); - }); + + const expectedEvents = orders.map(order => expectedFillEvent(order)); + verifyEvents(transactionReceipt, expectedEvents, ExchangeEvents.Fill); }); it(`${fnName} should fill the orders if called by approver`, async () => { const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); - const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync( - await coordinatorContract.executeTransaction.sendTransactionAsync( - transaction, - feeRecipientAddress, - transaction.signature, - [], - [], - { from: feeRecipientAddress, gas: constants.MAX_EXECUTE_TRANSACTION_GAS }, - ), + const transactionReceipt = await coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + transaction, + feeRecipientAddress, + transaction.signature, + [], + [], + { from: feeRecipientAddress, gas: constants.MAX_EXECUTE_TRANSACTION_GAS }, constants.AWAIT_TRANSACTION_MINED_MS, ); - const fillLogs = transactionReceipt.logs.filter( - log => (log as LogWithDecodedArgs).event === 'Fill', - ); - expect(fillLogs.length).to.eq(orders.length); - orders.forEach((order, index) => { - const fillLogArgs = (fillLogs[index] as LogWithDecodedArgs).args; - expect(fillLogArgs.makerAddress).to.eq(makerAddress); - expect(fillLogArgs.takerAddress).to.eq(takerAddress); - expect(fillLogArgs.senderAddress).to.eq(coordinatorContract.address); - expect(fillLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress); - expect(fillLogArgs.makerAssetData).to.eq(order.makerAssetData); - expect(fillLogArgs.takerAssetData).to.eq(order.takerAssetData); - expect(fillLogArgs.makerAssetFilledAmount).to.bignumber.eq(order.makerAssetAmount); - expect(fillLogArgs.takerAssetFilledAmount).to.bignumber.eq(order.takerAssetAmount); - expect(fillLogArgs.makerFeePaid).to.bignumber.eq(order.makerFee); - expect(fillLogArgs.takerFeePaid).to.bignumber.eq(order.takerFee); - expect(fillLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(order)); - }); + + const expectedEvents = orders.map(order => expectedFillEvent(order)); + verifyEvents(transactionReceipt, expectedEvents, ExchangeEvents.Fill); }); it(`${fnName} should revert with an invalid approval signature`, async () => { const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()]; @@ -382,16 +352,18 @@ describe('Coordinator tests', () => { approvalExpirationTimeSeconds, ); const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`; - await expectTransactionFailedAsync( - coordinatorContract.executeTransaction.sendTransactionAsync( - transaction, - takerAddress, - transaction.signature, - [approvalExpirationTimeSeconds], - [signature], - { from: takerAddress }, - ), - RevertReason.InvalidApprovalSignature, + const tx = coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + transaction, + takerAddress, + transaction.signature, + [approvalExpirationTimeSeconds], + [signature], + { from: takerAddress }, + ); + + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + expect(tx).to.revertWith( + new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, feeRecipientAddress), ); }); it(`${fnName} should revert with an expired approval`, async () => { @@ -405,16 +377,18 @@ describe('Coordinator tests', () => { takerAddress, approvalExpirationTimeSeconds, ); - await expectTransactionFailedAsync( - coordinatorContract.executeTransaction.sendTransactionAsync( - transaction, - takerAddress, - transaction.signature, - [approvalExpirationTimeSeconds], - [approval.signature], - { from: takerAddress }, - ), - RevertReason.ApprovalExpired, + const tx = coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + transaction, + takerAddress, + transaction.signature, + [approvalExpirationTimeSeconds], + [approval.signature], + { from: takerAddress }, + ); + + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + expect(tx).to.revertWith( + new CoordinatorRevertErrors.ApprovalExpiredError(transactionHash, approvalExpirationTimeSeconds), ); }); it(`${fnName} should revert if not called by tx signer or approver`, async () => { @@ -428,17 +402,16 @@ describe('Coordinator tests', () => { takerAddress, approvalExpirationTimeSeconds, ); - await expectTransactionFailedAsync( - coordinatorContract.executeTransaction.sendTransactionAsync( - transaction, - takerAddress, - transaction.signature, - [approvalExpirationTimeSeconds], - [approval.signature], - { from: owner }, - ), - RevertReason.InvalidOrigin, + + const tx = coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + transaction, + takerAddress, + transaction.signature, + [approvalExpirationTimeSeconds], + [approval.signature], + { from: owner }, ); + expect(tx).to.revertWith(new CoordinatorRevertErrors.InvalidOriginError(takerAddress)); }); } }); @@ -447,84 +420,55 @@ describe('Coordinator tests', () => { const orders = [await orderFactory.newSignedOrderAsync()]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(ExchangeFunctionName.CancelOrder, orders); const transaction = await makerTransactionFactory.newSignedTransactionAsync({ data }); - const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync( - await coordinatorContract.executeTransaction.sendTransactionAsync( - transaction, - makerAddress, - transaction.signature, - [], - [], - { - from: makerAddress, - }, - ), - ); - const cancelLogs = transactionReceipt.logs.filter( - log => (log as LogWithDecodedArgs).event === 'Cancel', + const transactionReceipt = await coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + transaction, + makerAddress, + transaction.signature, + [], + [], + { + from: makerAddress, + }, ); - expect(cancelLogs.length).to.eq(1); - const cancelLogArgs = (cancelLogs[0] as LogWithDecodedArgs).args; - expect(cancelLogArgs.makerAddress).to.eq(makerAddress); - expect(cancelLogArgs.senderAddress).to.eq(coordinatorContract.address); - expect(cancelLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress); - expect(cancelLogArgs.makerAssetData).to.eq(orders[0].makerAssetData); - expect(cancelLogArgs.takerAssetData).to.eq(orders[0].takerAssetData); - expect(cancelLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(orders[0])); + verifyEvents(transactionReceipt, [expectedCancelEvent(orders[0])], ExchangeEvents.Cancel); }); it('batchCancelOrders call should be successful without an approval', async () => { const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(ExchangeFunctionName.BatchCancelOrders, orders); const transaction = await makerTransactionFactory.newSignedTransactionAsync({ data }); - const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync( - await coordinatorContract.executeTransaction.sendTransactionAsync( - transaction, - makerAddress, - transaction.signature, - [], - [], - { - from: makerAddress, - }, - ), - ); - const cancelLogs = transactionReceipt.logs.filter( - log => (log as LogWithDecodedArgs).event === 'Cancel', + const transactionReceipt = await coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + transaction, + makerAddress, + transaction.signature, + [], + [], + { + from: makerAddress, + }, ); - expect(cancelLogs.length).to.eq(orders.length); - orders.forEach((order, index) => { - const cancelLogArgs = (cancelLogs[index] as LogWithDecodedArgs).args; - expect(cancelLogArgs.makerAddress).to.eq(makerAddress); - expect(cancelLogArgs.senderAddress).to.eq(coordinatorContract.address); - expect(cancelLogArgs.feeRecipientAddress).to.eq(feeRecipientAddress); - expect(cancelLogArgs.makerAssetData).to.eq(order.makerAssetData); - expect(cancelLogArgs.takerAssetData).to.eq(order.takerAssetData); - expect(cancelLogArgs.orderHash).to.eq(orderHashUtils.getOrderHashHex(order)); - }); + const expectedEvents = orders.map(order => expectedCancelEvent(order)); + verifyEvents(transactionReceipt, expectedEvents, ExchangeEvents.Cancel); }); it('cancelOrdersUpTo call should be successful without an approval', async () => { const targetEpoch = constants.ZERO_AMOUNT; const data = exchange.cancelOrdersUpTo.getABIEncodedTransactionData(targetEpoch); const transaction = await makerTransactionFactory.newSignedTransactionAsync({ data }); - const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync( - await coordinatorContract.executeTransaction.sendTransactionAsync( - transaction, - makerAddress, - transaction.signature, - [], - [], - { - from: makerAddress, - }, - ), - ); - const cancelLogs = transactionReceipt.logs.filter( - log => (log as LogWithDecodedArgs).event === 'CancelUpTo', + const transactionReceipt = await coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + transaction, + makerAddress, + transaction.signature, + [], + [], + { + from: makerAddress, + }, ); - expect(cancelLogs.length).to.eq(1); - const cancelLogArgs = (cancelLogs[0] as LogWithDecodedArgs).args; - expect(cancelLogArgs.makerAddress).to.eq(makerAddress); - expect(cancelLogArgs.orderSenderAddress).to.eq(coordinatorContract.address); - expect(cancelLogArgs.orderEpoch).to.bignumber.eq(targetEpoch.plus(1)); + const expectedEvent: ExchangeCancelUpToEventArgs = { + makerAddress, + orderSenderAddress: coordinatorContract.address, + orderEpoch: targetEpoch.plus(1), + }; + verifyEvents(transactionReceipt, [expectedEvent], ExchangeEvents.CancelUpTo); }); }); }); diff --git a/contracts/coordinator/test/coordinator_registry.ts b/contracts/coordinator/test/coordinator_registry.ts index c9404cc939..f3830f4d86 100644 --- a/contracts/coordinator/test/coordinator_registry.ts +++ b/contracts/coordinator/test/coordinator_registry.ts @@ -1,44 +1,25 @@ -import { artifacts as exchangeArtifacts } from '@0x/contracts-exchange'; -import { chaiSetup, provider, web3Wrapper } from '@0x/contracts-test-utils'; -import { BlockchainLifecycle } from '@0x/dev-utils'; -import * as chai from 'chai'; +import { blockchainTests, expect } from '@0x/contracts-test-utils'; import { LogWithDecodedArgs } from 'ethereum-types'; import { CoordinatorRegistryCoordinatorEndpointSetEventArgs } from '../src'; import { CoordinatorRegistryWrapper } from './utils/coordinator_registry_wrapper'; -chaiSetup.configure(); -const expect = chai.expect; -const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); -web3Wrapper.abiDecoder.addABI(exchangeArtifacts.Exchange.compilerOutput.abi); // tslint:disable:no-unnecessary-type-assertion -describe('Coordinator Registry tests', () => { +blockchainTests.resets('Coordinator Registry tests', env => { let coordinatorOperator: string; const coordinatorEndpoint = 'http://sometec.0x.org'; const nilCoordinatorEndpoint = ''; let coordinatorRegistryWrapper: CoordinatorRegistryWrapper; // tests - before(async () => { - await blockchainLifecycle.startAsync(); - }); - after(async () => { - await blockchainLifecycle.revertAsync(); - }); before(async () => { // setup accounts (skip owner) - const accounts = await web3Wrapper.getAvailableAddressesAsync(); + const accounts = await env.getAccountAddressesAsync(); [, coordinatorOperator] = accounts; // deploy coordinator registry - coordinatorRegistryWrapper = new CoordinatorRegistryWrapper(provider); + coordinatorRegistryWrapper = new CoordinatorRegistryWrapper(env.provider); await coordinatorRegistryWrapper.deployCoordinatorRegistryAsync(); }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); describe('core', () => { it('Should successfully set a Coordinator endpoint', async () => { await coordinatorRegistryWrapper.setCoordinatorEndpointAsync(coordinatorOperator, coordinatorEndpoint); diff --git a/contracts/coordinator/test/libs.ts b/contracts/coordinator/test/libs.ts index 3d9715dcee..5e32e55486 100644 --- a/contracts/coordinator/test/libs.ts +++ b/contracts/coordinator/test/libs.ts @@ -1,66 +1,31 @@ -import { chaiSetup, constants, provider, randomAddress, txDefaults, web3Wrapper } from '@0x/contracts-test-utils'; -import { BlockchainLifecycle } from '@0x/dev-utils'; +import { blockchainTests, constants, expect, randomAddress } from '@0x/contracts-test-utils'; import { transactionHashUtils } from '@0x/order-utils'; -import { BigNumber, providerUtils } from '@0x/utils'; -import * as chai from 'chai'; +import { BigNumber } from '@0x/utils'; import { artifacts, CoordinatorContract, hashUtils } from '../src'; -chaiSetup.configure(); -const expect = chai.expect; -const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); - -describe('Libs tests', () => { +blockchainTests.resets('Libs tests', env => { let coordinatorContract: CoordinatorContract; let chainId: number; const exchangeAddress = randomAddress(); before(async () => { - await blockchainLifecycle.startAsync(); - }); - after(async () => { - await blockchainLifecycle.revertAsync(); - }); - before(async () => { - chainId = await providerUtils.getChainIdAsync(provider); + chainId = await env.getChainIdAsync(); coordinatorContract = await CoordinatorContract.deployFrom0xArtifactAsync( artifacts.Coordinator, - provider, - txDefaults, + env.provider, + env.txDefaults, artifacts, exchangeAddress, new BigNumber(chainId), ); }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); - - describe('getTransactionHash', () => { - it('should return the correct transaction hash', async () => { - const tx = { - salt: new BigNumber(0), - expirationTimeSeconds: new BigNumber(0), - signerAddress: constants.NULL_ADDRESS, - data: '0x1234', - domain: { - verifyingContract: exchangeAddress, - chainId, - }, - }; - const expectedTxHash = transactionHashUtils.getTransactionHashHex(tx); - const txHash = await coordinatorContract.getTransactionHash.callAsync(tx); - expect(expectedTxHash).to.eq(txHash); - }); - }); describe('getApprovalHash', () => { it('should return the correct approval hash', async () => { const signedTx = { salt: new BigNumber(0), + gasPrice: new BigNumber(0), expirationTimeSeconds: new BigNumber(0), signerAddress: constants.NULL_ADDRESS, data: '0x1234', diff --git a/contracts/coordinator/test/mixins.ts b/contracts/coordinator/test/mixins.ts index 6394b4e12b..50b1d63c44 100644 --- a/contracts/coordinator/test/mixins.ts +++ b/contracts/coordinator/test/mixins.ts @@ -1,29 +1,20 @@ import { constants as exchangeConstants, exchangeDataEncoder, ExchangeFunctionName } from '@0x/contracts-exchange'; import { - chaiSetup, + blockchainTests, constants, - expectContractCallFailedAsync, + expect, getLatestBlockTimestampAsync, - provider, randomAddress, TransactionFactory, - txDefaults, - web3Wrapper, } from '@0x/contracts-test-utils'; -import { BlockchainLifecycle } from '@0x/dev-utils'; -import { transactionHashUtils } from '@0x/order-utils'; -import { RevertReason, SignatureType, SignedOrder } from '@0x/types'; -import { BigNumber, LibBytesRevertErrors, providerUtils } from '@0x/utils'; -import * as chai from 'chai'; +import { CoordinatorRevertErrors, transactionHashUtils } from '@0x/order-utils'; +import { SignatureType, SignedOrder } from '@0x/types'; +import { BigNumber, LibBytesRevertErrors } from '@0x/utils'; import * as ethUtil from 'ethereumjs-util'; import { ApprovalFactory, artifacts, CoordinatorContract } from '../src'; -chaiSetup.configure(); -const expect = chai.expect; -const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); - -describe('Mixins tests', () => { +blockchainTests.resets('Mixins tests', env => { let chainId: number; let transactionSignerAddress: string; let approvalSignerAddress1: string; @@ -36,23 +27,17 @@ describe('Mixins tests', () => { const exchangeAddress = randomAddress(); before(async () => { - await blockchainLifecycle.startAsync(); - }); - after(async () => { - await blockchainLifecycle.revertAsync(); - }); - before(async () => { - chainId = await providerUtils.getChainIdAsync(provider); + chainId = await env.getChainIdAsync(); mixins = await CoordinatorContract.deployFrom0xArtifactAsync( artifacts.Coordinator, - provider, - txDefaults, + env.provider, + env.txDefaults, artifacts, exchangeAddress, new BigNumber(chainId), ); - const accounts = await web3Wrapper.getAvailableAddressesAsync(); - [transactionSignerAddress, approvalSignerAddress1, approvalSignerAddress2] = accounts.slice(0, 3); + const accounts = await env.getAccountAddressesAsync(); + [transactionSignerAddress, approvalSignerAddress1, approvalSignerAddress2] = accounts; defaultOrder = { makerAddress: constants.NULL_ADDRESS, takerAddress: constants.NULL_ADDRESS, @@ -79,12 +64,6 @@ describe('Mixins tests', () => { approvalFactory1 = new ApprovalFactory(approvalSignerPrivateKey1, mixins.address); approvalFactory2 = new ApprovalFactory(approvalSignerPrivateKey2, mixins.address); }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); describe('getSignerAddress', () => { it('should return the correct address using the EthSign signature type', async () => { @@ -110,8 +89,12 @@ describe('Mixins tests', () => { transaction.signature.length - 2, )}${illegalSignatureByte}`; const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); - expect(mixins.getSignerAddress.callAsync(transactionHash, transaction.signature)).to.be.rejectedWith( - RevertReason.SignatureIllegal, + expect(mixins.getSignerAddress.callAsync(transactionHash, transaction.signature)).to.revertWith( + new CoordinatorRevertErrors.SignatureError( + CoordinatorRevertErrors.SignatureErrorCodes.Illegal, + transactionHash, + transaction.signature, + ), ); }); it('should revert with with the Invalid signature type', async () => { @@ -120,8 +103,12 @@ describe('Mixins tests', () => { const invalidSignatureByte = ethUtil.toBuffer(SignatureType.Invalid).toString('hex'); transaction.signature = `0x${invalidSignatureByte}`; const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); - expect(mixins.getSignerAddress.callAsync(transactionHash, transaction.signature)).to.be.rejectedWith( - RevertReason.SignatureInvalid, + expect(mixins.getSignerAddress.callAsync(transactionHash, transaction.signature)).to.revertWith( + new CoordinatorRevertErrors.SignatureError( + CoordinatorRevertErrors.SignatureErrorCodes.Invalid, + transactionHash, + transaction.signature, + ), ); }); it("should revert with with a signature type that doesn't exist", async () => { @@ -133,8 +120,12 @@ describe('Mixins tests', () => { transaction.signature.length - 2, )}${invalidSignatureByte}`; const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); - expect(mixins.getSignerAddress.callAsync(transactionHash, transaction.signature)).to.be.rejectedWith( - RevertReason.SignatureUnsupported, + expect(mixins.getSignerAddress.callAsync(transactionHash, transaction.signature)).to.revertWith( + new CoordinatorRevertErrors.SignatureError( + CoordinatorRevertErrors.SignatureErrorCodes.Unsupported, + transactionHash, + transaction.signature, + ), ); }); }); @@ -320,16 +311,18 @@ describe('Mixins tests', () => { approvalExpirationTimeSeconds, ); const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`; - expectContractCallFailedAsync( - mixins.assertValidCoordinatorApprovals.callAsync( - transaction, - transactionSignerAddress, - transaction.signature, - [approvalExpirationTimeSeconds], - [signature], - { from: transactionSignerAddress }, - ), - RevertReason.InvalidApprovalSignature, + const tx = mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + transactionSignerAddress, + transaction.signature, + [approvalExpirationTimeSeconds], + [signature], + { from: transactionSignerAddress }, + ); + + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + expect(tx).to.revertWith( + new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress1), ); }); it(`Should revert: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[approver1], expiration=[invalid]`, async () => { @@ -343,16 +336,18 @@ describe('Mixins tests', () => { transactionSignerAddress, approvalExpirationTimeSeconds, ); - expectContractCallFailedAsync( - mixins.assertValidCoordinatorApprovals.callAsync( - transaction, - transactionSignerAddress, - transaction.signature, - [approvalExpirationTimeSeconds], - [approval.signature], - { from: transactionSignerAddress }, - ), - RevertReason.ApprovalExpired, + const tx = mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + transactionSignerAddress, + transaction.signature, + [approvalExpirationTimeSeconds], + [approval.signature], + { from: transactionSignerAddress }, + ); + + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + expect(tx).to.revertWith( + new CoordinatorRevertErrors.ApprovalExpiredError(transactionHash, approvalExpirationTimeSeconds), ); }); it(`Should revert: function=${fnName}, caller=approver2, senderAddress=[verifier], approval_sig=[approver1], expiration=[valid]`, async () => { @@ -366,17 +361,16 @@ describe('Mixins tests', () => { transactionSignerAddress, approvalExpirationTimeSeconds, ); - expectContractCallFailedAsync( - mixins.assertValidCoordinatorApprovals.callAsync( - transaction, - transactionSignerAddress, - transaction.signature, - [approvalExpirationTimeSeconds], - [approval.signature], - { from: approvalSignerAddress2 }, - ), - RevertReason.InvalidOrigin, + + const tx = mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + transactionSignerAddress, + transaction.signature, + [approvalExpirationTimeSeconds], + [approval.signature], + { from: approvalSignerAddress2 }, ); + expect(tx).to.revertWith(new CoordinatorRevertErrors.InvalidOriginError(transactionSignerAddress)); }); } }); @@ -514,32 +508,33 @@ describe('Mixins tests', () => { transactionSignerAddress, approvalExpirationTimeSeconds, ); - expectContractCallFailedAsync( - mixins.assertValidCoordinatorApprovals.callAsync( - transaction, - transactionSignerAddress, - transaction.signature, - [approvalExpirationTimeSeconds], - [approval2.signature], - { from: approvalSignerAddress1 }, - ), - RevertReason.InvalidOrigin, + + const tx = mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + transactionSignerAddress, + transaction.signature, + [approvalExpirationTimeSeconds], + [approval2.signature], + { from: approvalSignerAddress1 }, ); + expect(tx).to.revertWith(new CoordinatorRevertErrors.InvalidOriginError(transactionSignerAddress)); }); it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[], expiration=[]`, async () => { const orders = [defaultOrder, defaultOrder]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - expectContractCallFailedAsync( - mixins.assertValidCoordinatorApprovals.callAsync( - transaction, - transactionSignerAddress, - transaction.signature, - [], - [], - { from: transactionSignerAddress }, - ), - RevertReason.InvalidApprovalSignature, + const tx = mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + transactionSignerAddress, + transaction.signature, + [], + [], + { from: transactionSignerAddress }, + ); + + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + expect(tx).to.revertWith( + new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress1), ); }); it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[invalid], expiration=[valid]`, async () => { @@ -554,16 +549,18 @@ describe('Mixins tests', () => { approvalExpirationTimeSeconds, ); const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`; - expectContractCallFailedAsync( - mixins.assertValidCoordinatorApprovals.callAsync( - transaction, - transactionSignerAddress, - transaction.signature, - [approvalExpirationTimeSeconds], - [signature], - { from: transactionSignerAddress }, - ), - RevertReason.InvalidApprovalSignature, + const tx = mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + transactionSignerAddress, + transaction.signature, + [approvalExpirationTimeSeconds], + [signature], + { from: transactionSignerAddress }, + ); + + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + expect(tx).to.revertWith( + new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress1), ); }); it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid,invalid], expiration=[valid,valid]`, async () => { @@ -583,16 +580,18 @@ describe('Mixins tests', () => { approvalExpirationTimeSeconds, ); const approvalSignature2 = `${approval2.signature.slice(0, 4)}FFFFFFFF${approval2.signature.slice(12)}`; - expectContractCallFailedAsync( - mixins.assertValidCoordinatorApprovals.callAsync( - transaction, - transactionSignerAddress, - transaction.signature, - [approvalExpirationTimeSeconds, approvalExpirationTimeSeconds], - [approval1.signature, approvalSignature2], - { from: transactionSignerAddress }, - ), - RevertReason.InvalidApprovalSignature, + const tx = mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + transactionSignerAddress, + transaction.signature, + [approvalExpirationTimeSeconds, approvalExpirationTimeSeconds], + [approval1.signature, approvalSignature2], + { from: transactionSignerAddress }, + ); + + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + expect(tx).to.revertWith( + new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress2), ); }); it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[invalid], expiration=[valid]`, async () => { @@ -607,16 +606,18 @@ describe('Mixins tests', () => { approvalExpirationTimeSeconds, ); const approvalSignature2 = `${approval2.signature.slice(0, 4)}FFFFFFFF${approval2.signature.slice(12)}`; - expectContractCallFailedAsync( - mixins.assertValidCoordinatorApprovals.callAsync( - transaction, - approvalSignerAddress1, - transaction.signature, - [approvalExpirationTimeSeconds], - [approvalSignature2], - { from: approvalSignerAddress1 }, - ), - RevertReason.InvalidApprovalSignature, + const tx = mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + approvalSignerAddress1, + transaction.signature, + [approvalExpirationTimeSeconds], + [approvalSignature2], + { from: approvalSignerAddress1 }, + ); + + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + expect(tx).to.revertWith( + new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress2), ); }); it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid,valid], expiration=[valid,invalid]`, async () => { @@ -636,16 +637,18 @@ describe('Mixins tests', () => { transactionSignerAddress, approvalExpirationTimeSeconds2, ); - expectContractCallFailedAsync( - mixins.assertValidCoordinatorApprovals.callAsync( - transaction, - transactionSignerAddress, - transaction.signature, - [approvalExpirationTimeSeconds1, approvalExpirationTimeSeconds2], - [approval1.signature, approval2.signature], - { from: transactionSignerAddress }, - ), - RevertReason.ApprovalExpired, + + const tx = mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + transactionSignerAddress, + transaction.signature, + [approvalExpirationTimeSeconds1, approvalExpirationTimeSeconds2], + [approval1.signature, approval2.signature], + { from: transactionSignerAddress }, + ); + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + expect(tx).to.revertWith( + new CoordinatorRevertErrors.ApprovalExpiredError(transactionHash, approvalExpirationTimeSeconds2), ); }); it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid], expiration=[invalid]`, async () => { @@ -659,16 +662,18 @@ describe('Mixins tests', () => { transactionSignerAddress, approvalExpirationTimeSeconds, ); - expectContractCallFailedAsync( - mixins.assertValidCoordinatorApprovals.callAsync( - transaction, - approvalSignerAddress1, - transaction.signature, - [approvalExpirationTimeSeconds], - [approval2.signature], - { from: approvalSignerAddress1 }, - ), - RevertReason.ApprovalExpired, + + const tx = mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + approvalSignerAddress1, + transaction.signature, + [approvalExpirationTimeSeconds], + [approval2.signature], + { from: approvalSignerAddress1 }, + ); + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + expect(tx).to.revertWith( + new CoordinatorRevertErrors.ApprovalExpiredError(transactionHash, approvalExpirationTimeSeconds), ); }); it(`Should revert: function=${fnName} caller=approver2, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[valid], expiration=[valid]`, async () => { @@ -682,17 +687,16 @@ describe('Mixins tests', () => { transactionSignerAddress, approvalExpirationTimeSeconds, ); - expectContractCallFailedAsync( - mixins.assertValidCoordinatorApprovals.callAsync( - transaction, - transactionSignerAddress, - transaction.signature, - [approvalExpirationTimeSeconds], - [approval1.signature], - { from: approvalSignerAddress2 }, - ), - RevertReason.InvalidOrigin, + + const tx = mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + transactionSignerAddress, + transaction.signature, + [approvalExpirationTimeSeconds], + [approval1.signature], + { from: approvalSignerAddress2 }, ); + expect(tx).to.revertWith(new CoordinatorRevertErrors.InvalidOriginError(transactionSignerAddress)); }); } }); diff --git a/contracts/coordinator/test/utils/coordinator_registry_wrapper.ts b/contracts/coordinator/test/utils/coordinator_registry_wrapper.ts index 3d7a2999ef..a31d90b03b 100644 --- a/contracts/coordinator/test/utils/coordinator_registry_wrapper.ts +++ b/contracts/coordinator/test/utils/coordinator_registry_wrapper.ts @@ -1,3 +1,4 @@ +import { artifacts as exchangeArtifacts } from '@0x/contracts-exchange'; import { LogDecoder, txDefaults } from '@0x/contracts-test-utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { TransactionReceiptWithDecodedLogs, ZeroExProvider } from 'ethereum-types'; @@ -17,7 +18,7 @@ export class CoordinatorRegistryWrapper { constructor(provider: ZeroExProvider) { this._web3Wrapper = new Web3Wrapper(provider); this._provider = provider; - this._logDecoder = new LogDecoder(this._web3Wrapper, artifacts); + this._logDecoder = new LogDecoder(this._web3Wrapper, { ...exchangeArtifacts, ...artifacts }); } public async deployCoordinatorRegistryAsync(): Promise { this._coordinatorRegistryContract = await CoordinatorRegistryContract.deployFrom0xArtifactAsync( diff --git a/contracts/coordinator/tsconfig.json b/contracts/coordinator/tsconfig.json index ba2c48b6cd..8db06e4dd6 100644 --- a/contracts/coordinator/tsconfig.json +++ b/contracts/coordinator/tsconfig.json @@ -2,6 +2,21 @@ "extends": "../../tsconfig", "compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true }, "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"], - "files": ["generated-artifacts/Coordinator.json", "generated-artifacts/CoordinatorRegistry.json"], + "files": [ + "generated-artifacts/Coordinator.json", + "generated-artifacts/CoordinatorRegistry.json", + "generated-artifacts/ICoordinatorApprovalVerifier.json", + "generated-artifacts/ICoordinatorCore.json", + "generated-artifacts/ICoordinatorRegistryCore.json", + "generated-artifacts/ICoordinatorSignatureValidator.json", + "generated-artifacts/LibConstants.json", + "generated-artifacts/LibCoordinatorApproval.json", + "generated-artifacts/LibCoordinatorRichErrors.json", + "generated-artifacts/LibEIP712CoordinatorDomain.json", + "generated-artifacts/MixinCoordinatorApprovalVerifier.json", + "generated-artifacts/MixinCoordinatorCore.json", + "generated-artifacts/MixinCoordinatorRegistryCore.json", + "generated-artifacts/MixinSignatureValidator.json" + ], "exclude": ["./deploy/solc/solc_bin"] } diff --git a/packages/order-utils/src/constants.ts b/packages/order-utils/src/constants.ts index 8ab303343d..8c6fd8d9a1 100644 --- a/packages/order-utils/src/constants.ts +++ b/packages/order-utils/src/constants.ts @@ -140,7 +140,7 @@ export const constants = { ], }, COORDINATOR_DOMAIN_NAME: '0x Protocol Coordinator', - COORDINATOR_DOMAIN_VERSION: '2.0.0', + COORDINATOR_DOMAIN_VERSION: '3.0.0', COORDINATOR_APPROVAL_SCHEMA: { name: 'CoordinatorApproval', parameters: [ diff --git a/packages/order-utils/src/coordinator_revert_errors.ts b/packages/order-utils/src/coordinator_revert_errors.ts index e97831c555..4433790a8e 100644 --- a/packages/order-utils/src/coordinator_revert_errors.ts +++ b/packages/order-utils/src/coordinator_revert_errors.ts @@ -34,17 +34,17 @@ export class ApprovalExpiredError extends RevertError { } } -export class InvalidApprovalSignature extends RevertError { +export class InvalidApprovalSignatureError extends RevertError { constructor(transactionHash?: string, approverAddress?: string) { super( - 'InvalidApprovalSignature', - 'InvalidApprovalSignature(bytes32 transactionHash, address approverAddress)', + 'InvalidApprovalSignatureError', + 'InvalidApprovalSignatureError(bytes32 transactionHash, address approverAddress)', { transactionHash, approverAddress }, ); } } -const types = [SignatureError, InvalidOriginError, ApprovalExpiredError, InvalidApprovalSignature]; +const types = [SignatureError, InvalidOriginError, ApprovalExpiredError, InvalidApprovalSignatureError]; // Register the types we've defined. for (const type of types) { diff --git a/packages/order-utils/src/eip712_utils.ts b/packages/order-utils/src/eip712_utils.ts index d6972557c8..2b9404cc65 100644 --- a/packages/order-utils/src/eip712_utils.ts +++ b/packages/order-utils/src/eip712_utils.ts @@ -95,7 +95,7 @@ export const eip712Utils = { return typedData; }, /** - * Creates an Coordiantor typedData EIP712TypedData object for use with the Coordinator extension contract + * Creates an Coordinator typedData EIP712TypedData object for use with the Coordinator extension contract * @param transaction A 0x transaction * @param verifyingContract The coordinator extension contract address that will be verifying the typedData * @param txOrigin The desired `tx.origin` that should be able to submit an Ethereum txn involving this 0x transaction diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts index 1898f219c0..3b20d0ea14 100644 --- a/packages/order-utils/src/index.ts +++ b/packages/order-utils/src/index.ts @@ -1,3 +1,4 @@ +export import CoordinatorRevertErrors = require('./coordinator_revert_errors'); export import ExchangeRevertErrors = require('./exchange_revert_errors'); export import ForwarderRevertErrors = require('./forwarder_revert_errors'); export import LibMathRevertErrors = require('./lib_math_revert_errors'); From 589d2212eef89bf1fe059813a666b1ec6d7271b7 Mon Sep 17 00:00:00 2001 From: Michael Zhu Date: Thu, 3 Oct 2019 12:32:40 -0700 Subject: [PATCH 29/87] Test coordinator protocol fees --- .../contracts/src/MixinCoordinatorCore.sol | 9 ++ contracts/coordinator/test/coordinator.ts | 105 ++++++++++++------ contracts/exchange-forwarder/package.json | 2 +- contracts/exchange-forwarder/src/artifacts.ts | 2 - contracts/exchange-forwarder/src/wrappers.ts | 1 - .../exchange-forwarder/test/forwarder.ts | 17 ++- contracts/exchange-forwarder/tsconfig.json | 3 +- .../test/TestProtocolFeeCollector.sol | 25 +++-- contracts/exchange/package.json | 2 +- contracts/exchange/src/artifacts.ts | 2 + contracts/exchange/src/wrappers.ts | 1 + contracts/exchange/tsconfig.json | 1 + 12 files changed, 108 insertions(+), 62 deletions(-) rename contracts/{exchange-forwarder/contracts/src => exchange/contracts}/test/TestProtocolFeeCollector.sol (76%) diff --git a/contracts/coordinator/contracts/src/MixinCoordinatorCore.sol b/contracts/coordinator/contracts/src/MixinCoordinatorCore.sol index 85dcc092c1..69c3ed9fae 100644 --- a/contracts/coordinator/contracts/src/MixinCoordinatorCore.sol +++ b/contracts/coordinator/contracts/src/MixinCoordinatorCore.sol @@ -26,12 +26,21 @@ import "./interfaces/ICoordinatorCore.sol"; import "./interfaces/ICoordinatorApprovalVerifier.sol"; +// solhint-disable no-empty-blocks contract MixinCoordinatorCore is Refundable, LibConstants, ICoordinatorApprovalVerifier, ICoordinatorCore { + + /// @dev A payable fallback function that makes this contract "payable". This is necessary to allow + /// this contract to gracefully handle refunds from the Exchange. + function () + external + payable + {} + /// @dev Executes a 0x transaction that has been signed by the feeRecipients that correspond to /// each order in the transaction's Exchange calldata. /// @param transaction 0x transaction containing salt, signerAddress, and data. diff --git a/contracts/coordinator/test/coordinator.ts b/contracts/coordinator/test/coordinator.ts index 27e90c49f6..d7dd2e7469 100644 --- a/contracts/coordinator/test/coordinator.ts +++ b/contracts/coordinator/test/coordinator.ts @@ -1,5 +1,5 @@ import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy'; -import { DummyERC20TokenContract } from '@0x/contracts-erc20'; +import { artifacts as erc20Artifacts, DummyERC20TokenContract, WETH9Contract } from '@0x/contracts-erc20'; import { artifacts as exchangeArtifacts, constants as exchangeConstants, @@ -10,6 +10,7 @@ import { ExchangeEvents, ExchangeFillEventArgs, ExchangeFunctionName, + TestProtocolFeeCollectorContract, } from '@0x/contracts-exchange'; import { blockchainTests, @@ -48,16 +49,25 @@ blockchainTests.resets('Coordinator tests', env => { let makerTransactionFactory: TransactionFactory; let approvalFactory: ApprovalFactory; - // const GAS_PRICE = new BigNumber(env.txDefaults.gasPrice || constants.DEFAULT_GAS_PRICE); - // const PROTOCOL_FEE_MULTIPLIER = new BigNumber(150); - // const PROTOCOL_FEE = GAS_PRICE.times(PROTOCOL_FEE_MULTIPLIER); - const PROTOCOL_FEE = new BigNumber(0); + const GAS_PRICE = new BigNumber(env.txDefaults.gasPrice || constants.DEFAULT_GAS_PRICE); + const PROTOCOL_FEE_MULTIPLIER = new BigNumber(150); + const PROTOCOL_FEE = GAS_PRICE.times(PROTOCOL_FEE_MULTIPLIER); before(async () => { chainId = await env.getChainIdAsync(); const accounts = await env.getAccountAddressesAsync(); const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = accounts); + // Deploy Exchange + exchange = await ExchangeContract.deployFrom0xArtifactAsync( + exchangeArtifacts.Exchange, + env.provider, + env.txDefaults, + {}, + new BigNumber(chainId), + ); + + // Set up ERC20 erc20Wrapper = new ERC20Wrapper(env.provider, usedAddresses, owner); erc20Proxy = await erc20Wrapper.deployProxyAsync(); const numDummyErc20ToDeploy = 3; @@ -65,27 +75,45 @@ blockchainTests.resets('Coordinator tests', env => { numDummyErc20ToDeploy, constants.DUMMY_TOKEN_DECIMALS, ); - await erc20Wrapper.setBalancesAndAllowancesAsync(); + await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchange.address, { from: owner }); + await exchange.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, { from: owner }); - exchange = await ExchangeContract.deployFrom0xArtifactAsync( - exchangeArtifacts.Exchange, + // Set up WETH + const wethContract = await WETH9Contract.deployFrom0xArtifactAsync( + erc20Artifacts.WETH9, env.provider, env.txDefaults, {}, - new BigNumber(chainId), ); + const weth = new DummyERC20TokenContract(wethContract.address, env.provider); + erc20Wrapper.addDummyTokenContract(weth); + await erc20Wrapper.setBalancesAndAllowancesAsync(); - await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - exchange.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await exchange.registerAssetProxy.awaitTransactionSuccessAsync( - erc20Proxy.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, + // Set up Protocol Fee Collector + const protocolFeeCollector = await TestProtocolFeeCollectorContract.deployFrom0xArtifactAsync( + exchangeArtifacts.TestProtocolFeeCollector, + env.provider, + env.txDefaults, + {}, + weth.address, ); + await exchange.setProtocolFeeMultiplier.awaitTransactionSuccessAsync(PROTOCOL_FEE_MULTIPLIER); + await exchange.setProtocolFeeCollectorAddress.awaitTransactionSuccessAsync(protocolFeeCollector.address); + for (const account of usedAddresses) { + await wethContract.deposit.awaitTransactionSuccessAsync({ + from: account, + value: constants.ONE_ETHER, + }); + await wethContract.approve.awaitTransactionSuccessAsync( + protocolFeeCollector.address, + constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS, + { + from: account, + }, + ); + } + // Deploy Coordinator coordinatorContract = await CoordinatorContract.deployFrom0xArtifactAsync( artifacts.Coordinator, env.provider, @@ -100,7 +128,6 @@ blockchainTests.resets('Coordinator tests', env => { ...constants.STATIC_ORDER_PARAMS, senderAddress: coordinatorContract.address, makerAddress, - takerAddress, feeRecipientAddress, makerAssetData: assetDataUtils.encodeERC20AssetData(erc20TokenA.address), takerAssetData: assetDataUtils.encodeERC20AssetData(erc20TokenB.address), @@ -133,13 +160,13 @@ blockchainTests.resets('Coordinator tests', env => { function expectedFillEvent(order: SignedOrder): ExchangeFillEventArgs { return { makerAddress: order.makerAddress, + takerAddress, + senderAddress: order.senderAddress, feeRecipientAddress: order.feeRecipientAddress, makerAssetData: order.makerAssetData, takerAssetData: order.takerAssetData, makerFeeAssetData: order.makerFeeAssetData, takerFeeAssetData: order.takerFeeAssetData, - takerAddress: order.takerAddress, - senderAddress: order.senderAddress, makerAssetFilledAmount: order.makerAssetAmount, takerAssetFilledAmount: order.takerAssetAmount, makerFeePaid: order.makerFee, @@ -152,10 +179,10 @@ blockchainTests.resets('Coordinator tests', env => { function expectedCancelEvent(order: SignedOrder): ExchangeCancelEventArgs { return { makerAddress: order.makerAddress, + senderAddress: order.senderAddress, feeRecipientAddress: order.feeRecipientAddress, makerAssetData: order.makerAssetData, takerAssetData: order.takerAssetData, - senderAddress: order.senderAddress, orderHash: orderHashUtils.getOrderHashHex(order), }; } @@ -179,10 +206,8 @@ blockchainTests.resets('Coordinator tests', env => { transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], - { from: takerAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, + { from: takerAddress, value: PROTOCOL_FEE }, ); - verifyEvents(transactionReceipt, [expectedFillEvent(orders[0])], ExchangeEvents.Fill); }); it(`${fnName} should fill the order if called by approver`, async () => { @@ -195,8 +220,7 @@ blockchainTests.resets('Coordinator tests', env => { transaction.signature, [], [], - { from: feeRecipientAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, + { from: feeRecipientAddress, value: PROTOCOL_FEE }, ); verifyEvents(transactionReceipt, [expectedFillEvent(orders[0])], ExchangeEvents.Fill); }); @@ -213,6 +237,7 @@ blockchainTests.resets('Coordinator tests', env => { { from: takerAddress, gas: constants.MAX_EXECUTE_TRANSACTION_GAS, + value: PROTOCOL_FEE, }, ); @@ -239,7 +264,7 @@ blockchainTests.resets('Coordinator tests', env => { transaction.signature, [approvalExpirationTimeSeconds], [signature], - { from: takerAddress }, + { from: takerAddress, value: PROTOCOL_FEE }, ); const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); @@ -265,7 +290,7 @@ blockchainTests.resets('Coordinator tests', env => { transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], - { from: takerAddress }, + { from: takerAddress, value: PROTOCOL_FEE }, ); const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); @@ -291,7 +316,7 @@ blockchainTests.resets('Coordinator tests', env => { transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], - { from: owner }, + { from: owner, value: PROTOCOL_FEE }, ); expect(tx).to.revertWith(new CoordinatorRevertErrors.InvalidOriginError(takerAddress)); }); @@ -316,8 +341,11 @@ blockchainTests.resets('Coordinator tests', env => { transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], - { from: takerAddress, gas: constants.MAX_EXECUTE_TRANSACTION_GAS }, - constants.AWAIT_TRANSACTION_MINED_MS, + { + from: takerAddress, + gas: constants.MAX_EXECUTE_TRANSACTION_GAS, + value: PROTOCOL_FEE.times(orders.length), + }, ); const expectedEvents = orders.map(order => expectedFillEvent(order)); @@ -333,8 +361,11 @@ blockchainTests.resets('Coordinator tests', env => { transaction.signature, [], [], - { from: feeRecipientAddress, gas: constants.MAX_EXECUTE_TRANSACTION_GAS }, - constants.AWAIT_TRANSACTION_MINED_MS, + { + from: feeRecipientAddress, + gas: constants.MAX_EXECUTE_TRANSACTION_GAS, + value: PROTOCOL_FEE.times(orders.length), + }, ); const expectedEvents = orders.map(order => expectedFillEvent(order)); @@ -358,7 +389,7 @@ blockchainTests.resets('Coordinator tests', env => { transaction.signature, [approvalExpirationTimeSeconds], [signature], - { from: takerAddress }, + { from: takerAddress, value: PROTOCOL_FEE.times(orders.length) }, ); const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); @@ -383,7 +414,7 @@ blockchainTests.resets('Coordinator tests', env => { transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], - { from: takerAddress }, + { from: takerAddress, value: PROTOCOL_FEE.times(orders.length) }, ); const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); @@ -409,7 +440,7 @@ blockchainTests.resets('Coordinator tests', env => { transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], - { from: owner }, + { from: owner, value: PROTOCOL_FEE.times(orders.length) }, ); expect(tx).to.revertWith(new CoordinatorRevertErrors.InvalidOriginError(takerAddress)); }); diff --git a/contracts/exchange-forwarder/package.json b/contracts/exchange-forwarder/package.json index 3880356015..a14a5a8cd1 100644 --- a/contracts/exchange-forwarder/package.json +++ b/contracts/exchange-forwarder/package.json @@ -35,7 +35,7 @@ "compile:truffle": "truffle compile" }, "config": { - "abis": "./generated-artifacts/@(Forwarder|IAssets|IForwarder|IForwarderCore|LibConstants|LibForwarderRichErrors|MixinAssets|MixinExchangeWrapper|MixinForwarderCore|MixinWeth|TestProtocolFeeCollector).json", + "abis": "./generated-artifacts/@(Forwarder|IAssets|IForwarder|IForwarderCore|LibConstants|LibForwarderRichErrors|MixinAssets|MixinExchangeWrapper|MixinForwarderCore|MixinWeth).json", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually." }, "repository": { diff --git a/contracts/exchange-forwarder/src/artifacts.ts b/contracts/exchange-forwarder/src/artifacts.ts index de0fa3fe35..9643be939a 100644 --- a/contracts/exchange-forwarder/src/artifacts.ts +++ b/contracts/exchange-forwarder/src/artifacts.ts @@ -15,7 +15,6 @@ import * as MixinAssets from '../generated-artifacts/MixinAssets.json'; import * as MixinExchangeWrapper from '../generated-artifacts/MixinExchangeWrapper.json'; import * as MixinForwarderCore from '../generated-artifacts/MixinForwarderCore.json'; import * as MixinWeth from '../generated-artifacts/MixinWeth.json'; -import * as TestProtocolFeeCollector from '../generated-artifacts/TestProtocolFeeCollector.json'; export const artifacts = { Forwarder: Forwarder as ContractArtifact, MixinAssets: MixinAssets as ContractArtifact, @@ -27,5 +26,4 @@ export const artifacts = { IForwarderCore: IForwarderCore as ContractArtifact, LibConstants: LibConstants as ContractArtifact, LibForwarderRichErrors: LibForwarderRichErrors as ContractArtifact, - TestProtocolFeeCollector: TestProtocolFeeCollector as ContractArtifact, }; diff --git a/contracts/exchange-forwarder/src/wrappers.ts b/contracts/exchange-forwarder/src/wrappers.ts index 1d9bd5b205..23213da16e 100644 --- a/contracts/exchange-forwarder/src/wrappers.ts +++ b/contracts/exchange-forwarder/src/wrappers.ts @@ -13,4 +13,3 @@ export * from '../generated-wrappers/mixin_assets'; export * from '../generated-wrappers/mixin_exchange_wrapper'; export * from '../generated-wrappers/mixin_forwarder_core'; export * from '../generated-wrappers/mixin_weth'; -export * from '../generated-wrappers/test_protocol_fee_collector'; diff --git a/contracts/exchange-forwarder/test/forwarder.ts b/contracts/exchange-forwarder/test/forwarder.ts index 1bff25011a..1e791ba39d 100644 --- a/contracts/exchange-forwarder/test/forwarder.ts +++ b/contracts/exchange-forwarder/test/forwarder.ts @@ -1,7 +1,12 @@ import { ERC20Wrapper, ERC721Wrapper } from '@0x/contracts-asset-proxy'; import { artifacts as erc20Artifacts, DummyERC20TokenContract, WETH9Contract } from '@0x/contracts-erc20'; import { DummyERC721TokenContract } from '@0x/contracts-erc721'; -import { artifacts as exchangeArtifacts, ExchangeContract, ExchangeWrapper } from '@0x/contracts-exchange'; +import { + artifacts as exchangeArtifacts, + ExchangeContract, + ExchangeWrapper, + TestProtocolFeeCollectorContract, +} from '@0x/contracts-exchange'; import { blockchainTests, constants, @@ -15,13 +20,7 @@ import { assetDataUtils, ForwarderRevertErrors } from '@0x/order-utils'; import { BigNumber } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; -import { - artifacts, - ForwarderContract, - ForwarderTestFactory, - ForwarderWrapper, - TestProtocolFeeCollectorContract, -} from '../src'; +import { artifacts, ForwarderContract, ForwarderTestFactory, ForwarderWrapper } from '../src'; const DECIMALS_DEFAULT = 18; @@ -114,7 +113,7 @@ blockchainTests(ContractName.Forwarder, env => { // Set up Protocol Fee Collector protocolFeeCollector = await TestProtocolFeeCollectorContract.deployFrom0xArtifactAsync( - artifacts.TestProtocolFeeCollector, + exchangeArtifacts.TestProtocolFeeCollector, env.provider, env.txDefaults, {}, diff --git a/contracts/exchange-forwarder/tsconfig.json b/contracts/exchange-forwarder/tsconfig.json index 1fc2108a56..e5d468a5ce 100644 --- a/contracts/exchange-forwarder/tsconfig.json +++ b/contracts/exchange-forwarder/tsconfig.json @@ -12,8 +12,7 @@ "generated-artifacts/MixinAssets.json", "generated-artifacts/MixinExchangeWrapper.json", "generated-artifacts/MixinForwarderCore.json", - "generated-artifacts/MixinWeth.json", - "generated-artifacts/TestProtocolFeeCollector.json" + "generated-artifacts/MixinWeth.json" ], "exclude": ["./deploy/solc/solc_bin"] } diff --git a/contracts/exchange-forwarder/contracts/src/test/TestProtocolFeeCollector.sol b/contracts/exchange/contracts/test/TestProtocolFeeCollector.sol similarity index 76% rename from contracts/exchange-forwarder/contracts/src/test/TestProtocolFeeCollector.sol rename to contracts/exchange/contracts/test/TestProtocolFeeCollector.sol index 84ac37d878..6830586061 100644 --- a/contracts/exchange-forwarder/contracts/src/test/TestProtocolFeeCollector.sol +++ b/contracts/exchange/contracts/test/TestProtocolFeeCollector.sol @@ -22,7 +22,7 @@ pragma experimental ABIEncoderV2; import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol"; - // solhint-disable no-unused-vars + // solhint-disable no-unused-vars, no-empty-blocks contract TestProtocolFeeCollector { address private _wethAddress; @@ -35,6 +35,11 @@ contract TestProtocolFeeCollector { _wethAddress = wethAddress; } + function () + external + payable + {} + /// @dev Pays a protocol fee in WETH (Forwarder orders will always pay protocol fees in WETH). /// @param makerAddress The address of the order's maker. /// @param payerAddress The address of the protocol fee payer. @@ -47,13 +52,15 @@ contract TestProtocolFeeCollector { external payable { - assert(msg.value == 0); - - // Transfer the protocol fee to this address in WETH. - IEtherToken(_wethAddress).transferFrom( - payerAddress, - address(this), - protocolFeePaid - ); + if (msg.value != protocolFeePaid) { + assert(msg.value == 0); + + // Transfer the protocol fee to this address in WETH. + IEtherToken(_wethAddress).transferFrom( + payerAddress, + address(this), + protocolFeePaid + ); + } } } diff --git a/contracts/exchange/package.json b/contracts/exchange/package.json index c8199af93e..6f09054ea8 100644 --- a/contracts/exchange/package.json +++ b/contracts/exchange/package.json @@ -35,7 +35,7 @@ "compile:truffle": "truffle compile" }, "config": { - "abis": "./generated-artifacts/@(Exchange|IAssetProxy|IAssetProxyDispatcher|IEIP1271Data|IEIP1271Wallet|IExchange|IExchangeCore|IMatchOrders|IProtocolFees|ISignatureValidator|ITransactions|ITransferSimulator|IWallet|IWrapperFunctions|IsolatedExchange|LibExchangeRichErrorDecoder|MixinAssetProxyDispatcher|MixinExchangeCore|MixinMatchOrders|MixinProtocolFees|MixinSignatureValidator|MixinTransactions|MixinTransferSimulator|MixinWrapperFunctions|ReentrancyTester|TestAssetProxyDispatcher|TestExchangeInternals|TestLibExchangeRichErrorDecoder|TestProtocolFees|TestProtocolFeesReceiver|TestSignatureValidator|TestTransactions|TestValidatorWallet|TestWrapperFunctions).json", + "abis": "./generated-artifacts/@(Exchange|IAssetProxy|IAssetProxyDispatcher|IEIP1271Data|IEIP1271Wallet|IExchange|IExchangeCore|IMatchOrders|IProtocolFees|ISignatureValidator|ITransactions|ITransferSimulator|IWallet|IWrapperFunctions|IsolatedExchange|LibExchangeRichErrorDecoder|MixinAssetProxyDispatcher|MixinExchangeCore|MixinMatchOrders|MixinProtocolFees|MixinSignatureValidator|MixinTransactions|MixinTransferSimulator|MixinWrapperFunctions|ReentrancyTester|TestAssetProxyDispatcher|TestExchangeInternals|TestLibExchangeRichErrorDecoder|TestProtocolFeeCollector|TestProtocolFees|TestProtocolFeesReceiver|TestSignatureValidator|TestTransactions|TestValidatorWallet|TestWrapperFunctions).json", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually." }, "repository": { diff --git a/contracts/exchange/src/artifacts.ts b/contracts/exchange/src/artifacts.ts index 15a1d88233..34354204c4 100644 --- a/contracts/exchange/src/artifacts.ts +++ b/contracts/exchange/src/artifacts.ts @@ -33,6 +33,7 @@ import * as ReentrancyTester from '../generated-artifacts/ReentrancyTester.json' import * as TestAssetProxyDispatcher from '../generated-artifacts/TestAssetProxyDispatcher.json'; import * as TestExchangeInternals from '../generated-artifacts/TestExchangeInternals.json'; import * as TestLibExchangeRichErrorDecoder from '../generated-artifacts/TestLibExchangeRichErrorDecoder.json'; +import * as TestProtocolFeeCollector from '../generated-artifacts/TestProtocolFeeCollector.json'; import * as TestProtocolFees from '../generated-artifacts/TestProtocolFees.json'; import * as TestProtocolFeesReceiver from '../generated-artifacts/TestProtocolFeesReceiver.json'; import * as TestSignatureValidator from '../generated-artifacts/TestSignatureValidator.json'; @@ -68,6 +69,7 @@ export const artifacts = { TestAssetProxyDispatcher: TestAssetProxyDispatcher as ContractArtifact, TestExchangeInternals: TestExchangeInternals as ContractArtifact, TestLibExchangeRichErrorDecoder: TestLibExchangeRichErrorDecoder as ContractArtifact, + TestProtocolFeeCollector: TestProtocolFeeCollector as ContractArtifact, TestProtocolFees: TestProtocolFees as ContractArtifact, TestProtocolFeesReceiver: TestProtocolFeesReceiver as ContractArtifact, TestSignatureValidator: TestSignatureValidator as ContractArtifact, diff --git a/contracts/exchange/src/wrappers.ts b/contracts/exchange/src/wrappers.ts index f5d76edb4d..28922d2dfc 100644 --- a/contracts/exchange/src/wrappers.ts +++ b/contracts/exchange/src/wrappers.ts @@ -31,6 +31,7 @@ export * from '../generated-wrappers/reentrancy_tester'; export * from '../generated-wrappers/test_asset_proxy_dispatcher'; export * from '../generated-wrappers/test_exchange_internals'; export * from '../generated-wrappers/test_lib_exchange_rich_error_decoder'; +export * from '../generated-wrappers/test_protocol_fee_collector'; export * from '../generated-wrappers/test_protocol_fees'; export * from '../generated-wrappers/test_protocol_fees_receiver'; export * from '../generated-wrappers/test_signature_validator'; diff --git a/contracts/exchange/tsconfig.json b/contracts/exchange/tsconfig.json index 6783d6851e..c38484f4d5 100644 --- a/contracts/exchange/tsconfig.json +++ b/contracts/exchange/tsconfig.json @@ -31,6 +31,7 @@ "generated-artifacts/TestAssetProxyDispatcher.json", "generated-artifacts/TestExchangeInternals.json", "generated-artifacts/TestLibExchangeRichErrorDecoder.json", + "generated-artifacts/TestProtocolFeeCollector.json", "generated-artifacts/TestProtocolFees.json", "generated-artifacts/TestProtocolFeesReceiver.json", "generated-artifacts/TestSignatureValidator.json", From c17984b74fbb39664056630022ddec13033f0d20 Mon Sep 17 00:00:00 2001 From: Michael Zhu Date: Fri, 4 Oct 2019 09:34:57 -0700 Subject: [PATCH 30/87] Refactor integration tests (CoordinatorTestFactory) --- .../src/MixinCoordinatorApprovalVerifier.sol | 11 +- contracts/coordinator/test/coordinator.ts | 291 +++++++++--------- contracts/coordinator/test/mixins.ts | 22 +- .../test/utils/coordinator_test_factory.ts | 268 ++++++++++++++++ contracts/coordinator/test/utils/index.ts | 1 + contracts/exchange/test/utils/constants.ts | 13 + .../test/utils/exchange_data_encoder.ts | 2 +- contracts/exchange/test/utils/types.ts | 2 +- 8 files changed, 446 insertions(+), 164 deletions(-) create mode 100644 contracts/coordinator/test/utils/coordinator_test_factory.ts diff --git a/contracts/coordinator/contracts/src/MixinCoordinatorApprovalVerifier.sol b/contracts/coordinator/contracts/src/MixinCoordinatorApprovalVerifier.sol index f848a5870b..fdcb8bf267 100644 --- a/contracts/coordinator/contracts/src/MixinCoordinatorApprovalVerifier.sol +++ b/contracts/coordinator/contracts/src/MixinCoordinatorApprovalVerifier.sol @@ -127,16 +127,7 @@ contract MixinCoordinatorApprovalVerifier is orders = new LibOrder.Order[](2); orders[0] = leftOrder; orders[1] = rightOrder; - } /* else if ( - selector == IExchange(address(0)).batchMatchOrders.selector || - selector == IExchange(address(0)).batchMatchOrdersWithMaximalFill.selector - ) { - // Decode left and right orders - (LibOrder.Order[] memory leftOrders, LibOrder.Order[] memory rightOrders) = abi.decode( - data.slice(4, data.length), - (LibOrder.Order[], LibOrder.Order[]) - ); - } */ + } return orders; } diff --git a/contracts/coordinator/test/coordinator.ts b/contracts/coordinator/test/coordinator.ts index d7dd2e7469..e08187414d 100644 --- a/contracts/coordinator/test/coordinator.ts +++ b/contracts/coordinator/test/coordinator.ts @@ -3,30 +3,22 @@ import { artifacts as erc20Artifacts, DummyERC20TokenContract, WETH9Contract } f import { artifacts as exchangeArtifacts, constants as exchangeConstants, - ExchangeCancelEventArgs, - ExchangeCancelUpToEventArgs, ExchangeContract, exchangeDataEncoder, - ExchangeEvents, - ExchangeFillEventArgs, ExchangeFunctionName, TestProtocolFeeCollectorContract, } from '@0x/contracts-exchange'; import { blockchainTests, constants, - expect, - filterLogsToArguments, getLatestBlockTimestampAsync, OrderFactory, TransactionFactory, } from '@0x/contracts-test-utils'; -import { assetDataUtils, CoordinatorRevertErrors, orderHashUtils, transactionHashUtils } from '@0x/order-utils'; -import { SignedOrder } from '@0x/types'; +import { assetDataUtils, CoordinatorRevertErrors, transactionHashUtils } from '@0x/order-utils'; import { BigNumber } from '@0x/utils'; -import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; -import { ApprovalFactory, artifacts, CoordinatorContract } from '../src'; +import { ApprovalFactory, artifacts, CoordinatorTestFactory, CoordinatorContract } from '../src'; // tslint:disable:no-unnecessary-type-assertion blockchainTests.resets('Coordinator tests', env => { @@ -40,14 +32,18 @@ blockchainTests.resets('Coordinator tests', env => { let erc20TokenA: DummyERC20TokenContract; let erc20TokenB: DummyERC20TokenContract; let makerFeeToken: DummyERC20TokenContract; + let takerFeeToken: DummyERC20TokenContract; let coordinatorContract: CoordinatorContract; let exchange: ExchangeContract; + let protocolFeeCollector: TestProtocolFeeCollectorContract; + let wethContract: WETH9Contract; let erc20Wrapper: ERC20Wrapper; let orderFactory: OrderFactory; let takerTransactionFactory: TransactionFactory; let makerTransactionFactory: TransactionFactory; let approvalFactory: ApprovalFactory; + let testFactory: CoordinatorTestFactory; const GAS_PRICE = new BigNumber(env.txDefaults.gasPrice || constants.DEFAULT_GAS_PRICE); const PROTOCOL_FEE_MULTIPLIER = new BigNumber(150); @@ -70,8 +66,8 @@ blockchainTests.resets('Coordinator tests', env => { // Set up ERC20 erc20Wrapper = new ERC20Wrapper(env.provider, usedAddresses, owner); erc20Proxy = await erc20Wrapper.deployProxyAsync(); - const numDummyErc20ToDeploy = 3; - [erc20TokenA, erc20TokenB, makerFeeToken] = await erc20Wrapper.deployDummyTokensAsync( + const numDummyErc20ToDeploy = 4; + [erc20TokenA, erc20TokenB, makerFeeToken, takerFeeToken] = await erc20Wrapper.deployDummyTokensAsync( numDummyErc20ToDeploy, constants.DUMMY_TOKEN_DECIMALS, ); @@ -79,7 +75,7 @@ blockchainTests.resets('Coordinator tests', env => { await exchange.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, { from: owner }); // Set up WETH - const wethContract = await WETH9Contract.deployFrom0xArtifactAsync( + wethContract = await WETH9Contract.deployFrom0xArtifactAsync( erc20Artifacts.WETH9, env.provider, env.txDefaults, @@ -90,7 +86,7 @@ blockchainTests.resets('Coordinator tests', env => { await erc20Wrapper.setBalancesAndAllowancesAsync(); // Set up Protocol Fee Collector - const protocolFeeCollector = await TestProtocolFeeCollectorContract.deployFrom0xArtifactAsync( + protocolFeeCollector = await TestProtocolFeeCollectorContract.deployFrom0xArtifactAsync( exchangeArtifacts.TestProtocolFeeCollector, env.provider, env.txDefaults, @@ -112,6 +108,7 @@ blockchainTests.resets('Coordinator tests', env => { }, ); } + erc20Wrapper.addTokenOwnerAddress(protocolFeeCollector.address); // Deploy Coordinator coordinatorContract = await CoordinatorContract.deployFrom0xArtifactAsync( @@ -122,6 +119,7 @@ blockchainTests.resets('Coordinator tests', env => { exchange.address, new BigNumber(chainId), ); + erc20Wrapper.addTokenOwnerAddress(coordinatorContract.address); // Configure order defaults const defaultOrderParams = { @@ -132,7 +130,7 @@ blockchainTests.resets('Coordinator tests', env => { makerAssetData: assetDataUtils.encodeERC20AssetData(erc20TokenA.address), takerAssetData: assetDataUtils.encodeERC20AssetData(erc20TokenB.address), makerFeeAssetData: assetDataUtils.encodeERC20AssetData(makerFeeToken.address), - takerFeeAssetData: assetDataUtils.encodeERC20AssetData(makerFeeToken.address), + takerFeeAssetData: assetDataUtils.encodeERC20AssetData(takerFeeToken.address), exchangeAddress: exchange.address, chainId, }; @@ -143,55 +141,28 @@ blockchainTests.resets('Coordinator tests', env => { makerTransactionFactory = new TransactionFactory(makerPrivateKey, exchange.address, chainId); takerTransactionFactory = new TransactionFactory(takerPrivateKey, exchange.address, chainId); approvalFactory = new ApprovalFactory(feeRecipientPrivateKey, coordinatorContract.address); - }); - - function verifyEvents( - txReceipt: TransactionReceiptWithDecodedLogs, - expectedEvents: TEventArgs[], - eventName: string, - ): void { - const logs = filterLogsToArguments(txReceipt.logs, eventName); - expect(logs.length).to.eq(expectedEvents.length); - logs.forEach((log, index) => { - expect(log).to.deep.equal(expectedEvents[index]); - }); - } - - function expectedFillEvent(order: SignedOrder): ExchangeFillEventArgs { - return { - makerAddress: order.makerAddress, + testFactory = new CoordinatorTestFactory( + coordinatorContract, + erc20Wrapper, + makerAddress, takerAddress, - senderAddress: order.senderAddress, - feeRecipientAddress: order.feeRecipientAddress, - makerAssetData: order.makerAssetData, - takerAssetData: order.takerAssetData, - makerFeeAssetData: order.makerFeeAssetData, - takerFeeAssetData: order.takerFeeAssetData, - makerAssetFilledAmount: order.makerAssetAmount, - takerAssetFilledAmount: order.takerAssetAmount, - makerFeePaid: order.makerFee, - takerFeePaid: order.takerFee, - protocolFeePaid: PROTOCOL_FEE, - orderHash: orderHashUtils.getOrderHashHex(order), - }; - } - - function expectedCancelEvent(order: SignedOrder): ExchangeCancelEventArgs { - return { - makerAddress: order.makerAddress, - senderAddress: order.senderAddress, - feeRecipientAddress: order.feeRecipientAddress, - makerAssetData: order.makerAssetData, - takerAssetData: order.takerAssetData, - orderHash: orderHashUtils.getOrderHashHex(order), - }; - } + feeRecipientAddress, + protocolFeeCollector.address, + erc20TokenA.address, + erc20TokenB.address, + makerFeeToken.address, + takerFeeToken.address, + weth.address, + GAS_PRICE, + PROTOCOL_FEE_MULTIPLIER, + ); + }); describe('single order fills', () => { for (const fnName of exchangeConstants.SINGLE_FILL_FN_NAMES) { it(`${fnName} should fill the order with a signed approval`, async () => { - const orders = [await orderFactory.newSignedOrderAsync()]; - const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); + const order = await orderFactory.newSignedOrderAsync(); + const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, [order]); const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); @@ -200,38 +171,95 @@ blockchainTests.resets('Coordinator tests', env => { takerAddress, approvalExpirationTimeSeconds, ); - const transactionReceipt = await coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + const txData = { from: takerAddress, value: PROTOCOL_FEE }; + await testFactory.executeFillTransactionTestAsync( + [order], transaction, takerAddress, - transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], - { from: takerAddress, value: PROTOCOL_FEE }, + txData, + ); + }); + it(`${fnName} should fill the order if called by approver (eth protocol fee, no refund)`, async () => { + const order = await orderFactory.newSignedOrderAsync(); + const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, [order]); + const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); + const txData = { from: feeRecipientAddress, value: PROTOCOL_FEE }; + await testFactory.executeFillTransactionTestAsync( + [order], + transaction, + feeRecipientAddress, + [], + [], + txData, + ); + }); + it(`${fnName} should fill the order if called by approver (eth protocol fee, refund)`, async () => { + const order = await orderFactory.newSignedOrderAsync(); + const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, [order]); + const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); + const txData = { from: feeRecipientAddress, value: PROTOCOL_FEE.plus(1) }; + await testFactory.executeFillTransactionTestAsync( + [order], + transaction, + feeRecipientAddress, + [], + [], + txData, + ); + }); + it(`${fnName} should fill the order if called by approver (weth protocol fee, no refund)`, async () => { + const order = await orderFactory.newSignedOrderAsync(); + const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, [order]); + const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); + const txData = { from: feeRecipientAddress }; + await testFactory.executeFillTransactionTestAsync( + [order], + transaction, + feeRecipientAddress, + [], + [], + txData, + ); + }); + it(`${fnName} should fill the order if called by approver (weth protocol fee, refund)`, async () => { + const order = await orderFactory.newSignedOrderAsync(); + const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, [order]); + const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); + const txData = { from: feeRecipientAddress, value: new BigNumber(1) }; + await testFactory.executeFillTransactionTestAsync( + [order], + transaction, + feeRecipientAddress, + [], + [], + txData, ); - verifyEvents(transactionReceipt, [expectedFillEvent(orders[0])], ExchangeEvents.Fill); }); it(`${fnName} should fill the order if called by approver`, async () => { - const orders = [await orderFactory.newSignedOrderAsync()]; - const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); + const order = await orderFactory.newSignedOrderAsync(); + const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, [order]); const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); - const transactionReceipt = await coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + const txData = { from: feeRecipientAddress, value: PROTOCOL_FEE }; + await testFactory.executeFillTransactionTestAsync( + [order], transaction, feeRecipientAddress, - transaction.signature, [], [], - { from: feeRecipientAddress, value: PROTOCOL_FEE }, + txData, ); - verifyEvents(transactionReceipt, [expectedFillEvent(orders[0])], ExchangeEvents.Fill); }); it(`${fnName} should revert with no approval signature`, async () => { const orders = [await orderFactory.newSignedOrderAsync()]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); - const tx = coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + await testFactory.executeFillTransactionTestAsync( + orders, transaction, takerAddress, - transaction.signature, [], [], { @@ -239,10 +267,6 @@ blockchainTests.resets('Coordinator tests', env => { gas: constants.MAX_EXECUTE_TRANSACTION_GAS, value: PROTOCOL_FEE, }, - ); - - const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); - expect(tx).to.revertWith( new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, feeRecipientAddress), ); }); @@ -258,17 +282,14 @@ blockchainTests.resets('Coordinator tests', env => { approvalExpirationTimeSeconds, ); const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`; - const tx = coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + await testFactory.executeFillTransactionTestAsync( + orders, transaction, takerAddress, - transaction.signature, [approvalExpirationTimeSeconds], [signature], { from: takerAddress, value: PROTOCOL_FEE }, - ); - - const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); - expect(tx).to.revertWith( new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, feeRecipientAddress), ); }); @@ -283,18 +304,14 @@ blockchainTests.resets('Coordinator tests', env => { takerAddress, approvalExpirationTimeSeconds, ); - - const tx = coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + await testFactory.executeFillTransactionTestAsync( + orders, transaction, takerAddress, - transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], { from: takerAddress, value: PROTOCOL_FEE }, - ); - - const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); - expect(tx).to.revertWith( new CoordinatorRevertErrors.ApprovalExpiredError(transactionHash, approvalExpirationTimeSeconds), ); }); @@ -309,16 +326,15 @@ blockchainTests.resets('Coordinator tests', env => { takerAddress, approvalExpirationTimeSeconds, ); - - const tx = coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + await testFactory.executeFillTransactionTestAsync( + orders, transaction, takerAddress, - transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], { from: owner, value: PROTOCOL_FEE }, + new CoordinatorRevertErrors.InvalidOriginError(takerAddress), ); - expect(tx).to.revertWith(new CoordinatorRevertErrors.InvalidOriginError(takerAddress)); }); } }); @@ -335,10 +351,10 @@ blockchainTests.resets('Coordinator tests', env => { takerAddress, approvalExpirationTimeSeconds, ); - const transactionReceipt = await coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + await testFactory.executeFillTransactionTestAsync( + orders, transaction, takerAddress, - transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], { @@ -347,29 +363,26 @@ blockchainTests.resets('Coordinator tests', env => { value: PROTOCOL_FEE.times(orders.length), }, ); - - const expectedEvents = orders.map(order => expectedFillEvent(order)); - verifyEvents(transactionReceipt, expectedEvents, ExchangeEvents.Fill); }); - it(`${fnName} should fill the orders if called by approver`, async () => { + it(`${fnName} should fill the orders if called by approver (eth fee, no refund)`, async () => { const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); - const transactionReceipt = await coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( - transaction, - feeRecipientAddress, - transaction.signature, - [], - [], - { - from: feeRecipientAddress, - gas: constants.MAX_EXECUTE_TRANSACTION_GAS, - value: PROTOCOL_FEE.times(orders.length), - }, - ); - - const expectedEvents = orders.map(order => expectedFillEvent(order)); - verifyEvents(transactionReceipt, expectedEvents, ExchangeEvents.Fill); + await testFactory.executeFillTransactionTestAsync(orders, transaction, feeRecipientAddress, [], [], { + from: feeRecipientAddress, + gas: constants.MAX_EXECUTE_TRANSACTION_GAS, + value: PROTOCOL_FEE.times(orders.length), + }); + }); + it(`${fnName} should fill the orders if called by approver (mixed fees, refund)`, async () => { + const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()]; + const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); + const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); + await testFactory.executeFillTransactionTestAsync(orders, transaction, feeRecipientAddress, [], [], { + from: feeRecipientAddress, + gas: constants.MAX_EXECUTE_TRANSACTION_GAS, + value: PROTOCOL_FEE.times(orders.length).plus(1), + }); }); it(`${fnName} should revert with an invalid approval signature`, async () => { const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()]; @@ -383,17 +396,14 @@ blockchainTests.resets('Coordinator tests', env => { approvalExpirationTimeSeconds, ); const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`; - const tx = coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + await testFactory.executeFillTransactionTestAsync( + orders, transaction, takerAddress, - transaction.signature, [approvalExpirationTimeSeconds], [signature], { from: takerAddress, value: PROTOCOL_FEE.times(orders.length) }, - ); - - const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); - expect(tx).to.revertWith( new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, feeRecipientAddress), ); }); @@ -408,17 +418,14 @@ blockchainTests.resets('Coordinator tests', env => { takerAddress, approvalExpirationTimeSeconds, ); - const tx = coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + await testFactory.executeFillTransactionTestAsync( + orders, transaction, takerAddress, - transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], { from: takerAddress, value: PROTOCOL_FEE.times(orders.length) }, - ); - - const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); - expect(tx).to.revertWith( new CoordinatorRevertErrors.ApprovalExpiredError(transactionHash, approvalExpirationTimeSeconds), ); }); @@ -433,16 +440,15 @@ blockchainTests.resets('Coordinator tests', env => { takerAddress, approvalExpirationTimeSeconds, ); - - const tx = coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + await testFactory.executeFillTransactionTestAsync( + orders, transaction, takerAddress, - transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], { from: owner, value: PROTOCOL_FEE.times(orders.length) }, + new CoordinatorRevertErrors.InvalidOriginError(takerAddress), ); - expect(tx).to.revertWith(new CoordinatorRevertErrors.InvalidOriginError(takerAddress)); }); } }); @@ -451,55 +457,48 @@ blockchainTests.resets('Coordinator tests', env => { const orders = [await orderFactory.newSignedOrderAsync()]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(ExchangeFunctionName.CancelOrder, orders); const transaction = await makerTransactionFactory.newSignedTransactionAsync({ data }); - const transactionReceipt = await coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + await testFactory.executeCancelTransactionTestAsync( + ExchangeFunctionName.CancelOrder, + orders, transaction, makerAddress, - transaction.signature, [], [], { from: makerAddress, }, ); - verifyEvents(transactionReceipt, [expectedCancelEvent(orders[0])], ExchangeEvents.Cancel); }); it('batchCancelOrders call should be successful without an approval', async () => { const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(ExchangeFunctionName.BatchCancelOrders, orders); const transaction = await makerTransactionFactory.newSignedTransactionAsync({ data }); - const transactionReceipt = await coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + await testFactory.executeCancelTransactionTestAsync( + ExchangeFunctionName.BatchCancelOrders, + orders, transaction, makerAddress, - transaction.signature, [], [], { from: makerAddress, }, ); - const expectedEvents = orders.map(order => expectedCancelEvent(order)); - verifyEvents(transactionReceipt, expectedEvents, ExchangeEvents.Cancel); }); it('cancelOrdersUpTo call should be successful without an approval', async () => { - const targetEpoch = constants.ZERO_AMOUNT; - const data = exchange.cancelOrdersUpTo.getABIEncodedTransactionData(targetEpoch); + const data = exchangeDataEncoder.encodeOrdersToExchangeData(ExchangeFunctionName.CancelOrdersUpTo, []); const transaction = await makerTransactionFactory.newSignedTransactionAsync({ data }); - const transactionReceipt = await coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + await testFactory.executeCancelTransactionTestAsync( + ExchangeFunctionName.CancelOrdersUpTo, + [], transaction, makerAddress, - transaction.signature, [], [], { from: makerAddress, }, ); - const expectedEvent: ExchangeCancelUpToEventArgs = { - makerAddress, - orderSenderAddress: coordinatorContract.address, - orderEpoch: targetEpoch.plus(1), - }; - verifyEvents(transactionReceipt, [expectedEvent], ExchangeEvents.CancelUpTo); }); }); }); diff --git a/contracts/coordinator/test/mixins.ts b/contracts/coordinator/test/mixins.ts index 50b1d63c44..82b1c04391 100644 --- a/contracts/coordinator/test/mixins.ts +++ b/contracts/coordinator/test/mixins.ts @@ -173,11 +173,21 @@ blockchainTests.resets('Mixins tests', env => { expect(orders).to.deep.eq(decodedSignedOrders); }); } - for (const fnName of [ - ExchangeFunctionName.CancelOrder, - ExchangeFunctionName.BatchCancelOrders, - ExchangeFunctionName.CancelOrdersUpTo, - ]) { + for (const fnName of exchangeConstants.MATCH_ORDER_FN_NAMES) { + it(`should correctly decode the orders for ${fnName} data`, async () => { + const orders = [defaultOrder, defaultOrder]; + const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); + const decodedOrders = await mixins.decodeOrdersFromFillData.callAsync(data); + const decodedSignedOrders = decodedOrders.map(order => ({ + ...order, + signature: constants.NULL_BYTES, + exchangeAddress: constants.NULL_ADDRESS, + chainId, + })); + expect(orders).to.deep.eq(decodedSignedOrders); + }); + } + for (const fnName of exchangeConstants.CANCEL_ORDER_FN_NAMES) { it(`should correctly decode the orders for ${fnName} data`, async () => { const orders = [defaultOrder, defaultOrder]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); @@ -378,7 +388,7 @@ blockchainTests.resets('Mixins tests', env => { for (const fnName of [ ...exchangeConstants.BATCH_FILL_FN_NAMES, ...exchangeConstants.MARKET_FILL_FN_NAMES, - ExchangeFunctionName.MatchOrders, + ...exchangeConstants.MATCH_ORDER_FN_NAMES, ]) { it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver1], approval_sig=[approver1], expiration=[valid]`, async () => { const orders = [defaultOrder, defaultOrder]; diff --git a/contracts/coordinator/test/utils/coordinator_test_factory.ts b/contracts/coordinator/test/utils/coordinator_test_factory.ts new file mode 100644 index 0000000000..cdcc26155a --- /dev/null +++ b/contracts/coordinator/test/utils/coordinator_test_factory.ts @@ -0,0 +1,268 @@ +import { ERC20Wrapper } from '@0x/contracts-asset-proxy'; +import { + ExchangeCancelEventArgs, + ExchangeCancelUpToEventArgs, + ExchangeEvents, + ExchangeFillEventArgs, + ExchangeFunctionName, +} from '@0x/contracts-exchange'; +import { expect, filterLogsToArguments, Numberish, TokenBalances, web3Wrapper } from '@0x/contracts-test-utils'; +import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; +import { SignedOrder, SignedZeroExTransaction } from '@0x/types'; +import { BigNumber, RevertError } from '@0x/utils'; +import { TransactionReceiptWithDecodedLogs, TxData } from 'ethereum-types'; +import * as _ from 'lodash'; + +import { CoordinatorContract } from '../../src'; + +export class CoordinatorTestFactory { + private readonly _addresses: string[]; + private readonly _protocolFee: BigNumber; + + public static verifyEvents( + txReceipt: TransactionReceiptWithDecodedLogs, + expectedEvents: TEventArgs[], + eventName: string, + ): void { + const logs = filterLogsToArguments(txReceipt.logs, eventName); + expect(logs.length).to.eq(expectedEvents.length); + logs.forEach((log, index) => { + expect(log).to.deep.equal(expectedEvents[index]); + }); + } + + constructor( + private readonly _coordinatorContract: CoordinatorContract, + private readonly _erc20Wrapper: ERC20Wrapper, + private readonly _makerAddress: string, + private readonly _takerAddress: string, + private readonly _feeRecipientAddress: string, + private readonly _protocolFeeCollectorAddress: string, + private readonly _makerAssetAddress: string, + private readonly _takerAssetAddress: string, + private readonly _makerFeeAssetAddress: string, + private readonly _takerFeeAssetAddress: string, + private readonly _wethAddress: string, + private readonly _gasPrice: BigNumber, + _protocolFeeMultiplier: BigNumber, + ) { + this._addresses = [ + _makerAddress, + _takerAddress, + _coordinatorContract.address, + _feeRecipientAddress, + _protocolFeeCollectorAddress, + ]; + this._protocolFee = _gasPrice.times(_protocolFeeMultiplier); + } + + public async executeFillTransactionTestAsync( + orders: SignedOrder[], + transaction: SignedZeroExTransaction, + txOrigin: string, + approvalExpirationTimeSeconds: BigNumber[], + approvalSignatures: string[], + txData: Partial, + revertError?: RevertError, + ): Promise { + const initBalances = await this._getTokenBalances(); + const tx = this._coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + transaction, + txOrigin, + transaction.signature, + approvalExpirationTimeSeconds, + approvalSignatures, + txData, + ); + + if (revertError !== undefined) { + return expect(tx).to.revertWith(revertError); + } + + const transactionReceipt = await tx; + CoordinatorTestFactory.verifyEvents( + transactionReceipt, + orders.map(order => this._expectedFillEvent(order)), + ExchangeEvents.Fill, + ); + + const expectedBalances = this._getExpectedBalances(initBalances, orders, transactionReceipt, txData.value); + await this._verifyBalancesAsync(expectedBalances); + } + + public async executeCancelTransactionTestAsync( + fnName: ExchangeFunctionName, + orders: SignedOrder[], + transaction: SignedZeroExTransaction, + txOrigin: string, + approvalExpirationTimeSeconds: BigNumber[], + approvalSignatures: string[], + txData: Partial, + ): Promise { + const transactionReceipt = await this._coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( + transaction, + txOrigin, + transaction.signature, + approvalExpirationTimeSeconds, + approvalSignatures, + txData, + ); + + if (fnName === ExchangeFunctionName.CancelOrdersUpTo) { + const expectedEvent: ExchangeCancelUpToEventArgs = { + makerAddress: this._makerAddress, + orderSenderAddress: this._coordinatorContract.address, + orderEpoch: new BigNumber(1), + }; + CoordinatorTestFactory.verifyEvents(transactionReceipt, [expectedEvent], ExchangeEvents.CancelUpTo); + } else { + CoordinatorTestFactory.verifyEvents( + transactionReceipt, + orders.map(order => CoordinatorTestFactory._expectedCancelEvent(order)), + ExchangeEvents.Cancel, + ); + } + } + + private async _getTokenBalances(): Promise { + let erc20Balances = await this._erc20Wrapper.getBalancesAsync(); + const ethBalances = _.zipObject( + this._addresses, + await Promise.all(this._addresses.map(address => web3Wrapper.getBalanceInWeiAsync(address))), + ); + + return { + erc20: erc20Balances, + erc721: {}, + erc1155: {}, + eth: ethBalances, + }; + } + + private _getExpectedBalances( + initBalances: TokenBalances, + orders: SignedOrder[], + txReceipt: TransactionReceiptWithDecodedLogs, + txValue?: Numberish, + ): TokenBalances { + const { erc20: erc20Balances, eth: ethBalances } = initBalances; + let remainingValue = new BigNumber(txValue || 0); + ethBalances[txReceipt.from] = ethBalances[txReceipt.from].minus(this._gasPrice.times(txReceipt.gasUsed)); + + for (const order of orders) { + const [makerAssetAddress, takerAssetAddress, makerFeeAssetAddress, takerFeeAssetAddress] = [ + order.makerAssetData, + order.takerAssetData, + order.makerFeeAssetData, + order.takerFeeAssetData, + ].map(assetData => assetDataUtils.decodeERC20AssetData(assetData).tokenAddress); + + erc20Balances[order.makerAddress][makerAssetAddress] = erc20Balances[order.makerAddress][ + makerAssetAddress + ].minus(order.makerAssetAmount); + erc20Balances[this._takerAddress][makerAssetAddress] = erc20Balances[this._takerAddress][ + makerAssetAddress + ].plus(order.makerAssetAmount); + erc20Balances[order.makerAddress][takerAssetAddress] = erc20Balances[order.makerAddress][ + takerAssetAddress + ].plus(order.takerAssetAmount); + erc20Balances[this._takerAddress][takerAssetAddress] = erc20Balances[this._takerAddress][ + takerAssetAddress + ].minus(order.takerAssetAmount); + erc20Balances[order.makerAddress][makerFeeAssetAddress] = erc20Balances[order.makerAddress][ + makerFeeAssetAddress + ].minus(order.makerFee); + erc20Balances[this._takerAddress][takerFeeAssetAddress] = erc20Balances[this._takerAddress][ + takerFeeAssetAddress + ].minus(order.takerFee); + erc20Balances[order.feeRecipientAddress][makerFeeAssetAddress] = erc20Balances[order.feeRecipientAddress][ + makerFeeAssetAddress + ].plus(order.makerFee); + erc20Balances[order.feeRecipientAddress][takerFeeAssetAddress] = erc20Balances[order.feeRecipientAddress][ + takerFeeAssetAddress + ].plus(order.takerFee); + + if (remainingValue.isGreaterThanOrEqualTo(this._protocolFee)) { + ethBalances[txReceipt.from] = ethBalances[txReceipt.from].minus(this._protocolFee); + ethBalances[this._protocolFeeCollectorAddress] = ethBalances[this._protocolFeeCollectorAddress].plus( + this._protocolFee, + ); + remainingValue = remainingValue.minus(this._protocolFee); + } else { + erc20Balances[this._takerAddress][this._wethAddress] = erc20Balances[this._takerAddress][ + this._wethAddress + ].minus(this._protocolFee); + erc20Balances[this._protocolFeeCollectorAddress][this._wethAddress] = erc20Balances[ + this._protocolFeeCollectorAddress + ][this._wethAddress].plus(this._protocolFee); + } + } + + return { + erc20: erc20Balances, + erc721: {}, + erc1155: {}, + eth: ethBalances, + }; + } + + private async _verifyBalancesAsync(expectedBalances: TokenBalances): Promise { + const { erc20: expectedErc20Balances, eth: expectedEthBalances } = expectedBalances; + const { erc20: actualErc20Balances, eth: actualEthBalances } = await this._getTokenBalances(); + const ownersByName = { + maker: this._makerAddress, + taker: this._takerAddress, + feeRecipient: this._feeRecipientAddress, + coordinator: this._coordinatorContract.address, + protocolFeeCollector: this._protocolFeeCollectorAddress, + }; + const tokensByName = { + makerAsset: this._makerAssetAddress, + takerAsset: this._takerAssetAddress, + makerFeeAsset: this._makerFeeAssetAddress, + takerFeeAsset: this._takerFeeAssetAddress, + weth: this._wethAddress, + }; + _.forIn(ownersByName, (ownerAddress, ownerName) => { + expect(actualEthBalances[ownerAddress], `${ownerName} eth balance`).to.bignumber.equal( + expectedEthBalances[ownerAddress], + ); + _.forIn(tokensByName, (tokenAddress, tokenName) => { + expect( + actualErc20Balances[ownerAddress][tokenAddress], + `${ownerName} ${tokenName} balance`, + ).to.bignumber.equal(expectedErc20Balances[ownerAddress][tokenAddress]); + }); + }); + } + + private _expectedFillEvent(order: SignedOrder): ExchangeFillEventArgs { + return { + makerAddress: order.makerAddress, + takerAddress: this._takerAddress, + senderAddress: order.senderAddress, + feeRecipientAddress: order.feeRecipientAddress, + makerAssetData: order.makerAssetData, + takerAssetData: order.takerAssetData, + makerFeeAssetData: order.makerFeeAssetData, + takerFeeAssetData: order.takerFeeAssetData, + makerAssetFilledAmount: order.makerAssetAmount, + takerAssetFilledAmount: order.takerAssetAmount, + makerFeePaid: order.makerFee, + takerFeePaid: order.takerFee, + protocolFeePaid: this._protocolFee, + orderHash: orderHashUtils.getOrderHashHex(order), + }; + } + + private static _expectedCancelEvent(order: SignedOrder): ExchangeCancelEventArgs { + return { + makerAddress: order.makerAddress, + senderAddress: order.senderAddress, + feeRecipientAddress: order.feeRecipientAddress, + makerAssetData: order.makerAssetData, + takerAssetData: order.takerAssetData, + orderHash: orderHashUtils.getOrderHashHex(order), + }; + } +} diff --git a/contracts/coordinator/test/utils/index.ts b/contracts/coordinator/test/utils/index.ts index bd5bd79dae..a724673f47 100644 --- a/contracts/coordinator/test/utils/index.ts +++ b/contracts/coordinator/test/utils/index.ts @@ -1,3 +1,4 @@ export { hashUtils } from './hash_utils'; export { ApprovalFactory } from './approval_factory'; +export { CoordinatorTestFactory } from './coordinator_test_factory'; export * from './types'; diff --git a/contracts/exchange/test/utils/constants.ts b/contracts/exchange/test/utils/constants.ts index b060b83d18..9456b91a3f 100644 --- a/contracts/exchange/test/utils/constants.ts +++ b/contracts/exchange/test/utils/constants.ts @@ -24,6 +24,19 @@ export const constants = { ExchangeFunctionName.MarketBuyOrdersNoThrow, ExchangeFunctionName.MarketSellOrdersNoThrow, ], + MATCH_ORDER_FN_NAMES: [ + ExchangeFunctionName.MatchOrders, + ExchangeFunctionName.MatchOrdersWithMaximalFill, + ], + BATCH_MATCH_ORDER_FN_NAMES: [ + ExchangeFunctionName.BatchMatchOrders, + ExchangeFunctionName.BatchMatchOrdersWithMaximalFill, + ], + CANCEL_ORDER_FN_NAMES: [ + ExchangeFunctionName.CancelOrder, + ExchangeFunctionName.BatchCancelOrders, + ExchangeFunctionName.CancelOrdersUpTo, + ], }; export enum ValidatorWalletAction { diff --git a/contracts/exchange/test/utils/exchange_data_encoder.ts b/contracts/exchange/test/utils/exchange_data_encoder.ts index d5253c0e66..5b7e383d08 100644 --- a/contracts/exchange/test/utils/exchange_data_encoder.ts +++ b/contracts/exchange/test/utils/exchange_data_encoder.ts @@ -27,7 +27,7 @@ export const exchangeDataEncoder = { orders.map(order => order[fillAsset]).reduce((prev, curr) => prev.plus(curr)), orders.map(order => order.signature), ); - } else if (fnName === ExchangeFunctionName.MatchOrders) { + } else if (exchangeConstants.MATCH_ORDER_FN_NAMES.indexOf(fnName) !== -1) { data = exchangeInstance.matchOrders.getABIEncodedTransactionData( orders[0], orders[1], diff --git a/contracts/exchange/test/utils/types.ts b/contracts/exchange/test/utils/types.ts index b8a4827109..02d8188191 100644 --- a/contracts/exchange/test/utils/types.ts +++ b/contracts/exchange/test/utils/types.ts @@ -14,7 +14,7 @@ export enum ExchangeFunctionName { BatchFillOrders = 'batchFillOrders', BatchFillOrdersNoThrow = 'batchFillOrdersNoThrow', BatchMatchOrders = 'batchMatchOrders', - BatchMatchordersWithMaximalFill = 'batchMatchOrdersWithMaximalFill', + BatchMatchOrdersWithMaximalFill = 'batchMatchOrdersWithMaximalFill', CancelOrder = 'cancelOrder', CancelOrdersUpTo = 'cancelOrdersUpTo', ExecuteTransaction = 'executeTransaction', From cf517b1459d1f8a8e4e28c925bbf8825cb6c1a8c Mon Sep 17 00:00:00 2001 From: Michael Zhu Date: Fri, 4 Oct 2019 10:02:50 -0700 Subject: [PATCH 31/87] appease static tests --- contracts/coordinator/test/coordinator.ts | 2 +- .../test/utils/coordinator_test_factory.ts | 30 +++++++++---------- contracts/exchange/test/utils/constants.ts | 5 +--- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/contracts/coordinator/test/coordinator.ts b/contracts/coordinator/test/coordinator.ts index e08187414d..f14b51ca45 100644 --- a/contracts/coordinator/test/coordinator.ts +++ b/contracts/coordinator/test/coordinator.ts @@ -18,7 +18,7 @@ import { import { assetDataUtils, CoordinatorRevertErrors, transactionHashUtils } from '@0x/order-utils'; import { BigNumber } from '@0x/utils'; -import { ApprovalFactory, artifacts, CoordinatorTestFactory, CoordinatorContract } from '../src'; +import { ApprovalFactory, artifacts, CoordinatorContract, CoordinatorTestFactory } from '../src'; // tslint:disable:no-unnecessary-type-assertion blockchainTests.resets('Coordinator tests', env => { diff --git a/contracts/coordinator/test/utils/coordinator_test_factory.ts b/contracts/coordinator/test/utils/coordinator_test_factory.ts index cdcc26155a..c8a88c0760 100644 --- a/contracts/coordinator/test/utils/coordinator_test_factory.ts +++ b/contracts/coordinator/test/utils/coordinator_test_factory.ts @@ -31,6 +31,17 @@ export class CoordinatorTestFactory { }); } + private static _expectedCancelEvent(order: SignedOrder): ExchangeCancelEventArgs { + return { + makerAddress: order.makerAddress, + senderAddress: order.senderAddress, + feeRecipientAddress: order.feeRecipientAddress, + makerAssetData: order.makerAssetData, + takerAssetData: order.takerAssetData, + orderHash: orderHashUtils.getOrderHashHex(order), + }; + } + constructor( private readonly _coordinatorContract: CoordinatorContract, private readonly _erc20Wrapper: ERC20Wrapper, @@ -65,7 +76,7 @@ export class CoordinatorTestFactory { txData: Partial, revertError?: RevertError, ): Promise { - const initBalances = await this._getTokenBalances(); + const initBalances = await this._getTokenBalancesAsync(); const tx = this._coordinatorContract.executeTransaction.awaitTransactionSuccessAsync( transaction, txOrigin, @@ -124,8 +135,8 @@ export class CoordinatorTestFactory { } } - private async _getTokenBalances(): Promise { - let erc20Balances = await this._erc20Wrapper.getBalancesAsync(); + private async _getTokenBalancesAsync(): Promise { + const erc20Balances = await this._erc20Wrapper.getBalancesAsync(); const ethBalances = _.zipObject( this._addresses, await Promise.all(this._addresses.map(address => web3Wrapper.getBalanceInWeiAsync(address))), @@ -208,7 +219,7 @@ export class CoordinatorTestFactory { private async _verifyBalancesAsync(expectedBalances: TokenBalances): Promise { const { erc20: expectedErc20Balances, eth: expectedEthBalances } = expectedBalances; - const { erc20: actualErc20Balances, eth: actualEthBalances } = await this._getTokenBalances(); + const { erc20: actualErc20Balances, eth: actualEthBalances } = await this._getTokenBalancesAsync(); const ownersByName = { maker: this._makerAddress, taker: this._takerAddress, @@ -254,15 +265,4 @@ export class CoordinatorTestFactory { orderHash: orderHashUtils.getOrderHashHex(order), }; } - - private static _expectedCancelEvent(order: SignedOrder): ExchangeCancelEventArgs { - return { - makerAddress: order.makerAddress, - senderAddress: order.senderAddress, - feeRecipientAddress: order.feeRecipientAddress, - makerAssetData: order.makerAssetData, - takerAssetData: order.takerAssetData, - orderHash: orderHashUtils.getOrderHashHex(order), - }; - } } diff --git a/contracts/exchange/test/utils/constants.ts b/contracts/exchange/test/utils/constants.ts index 9456b91a3f..27e22e917e 100644 --- a/contracts/exchange/test/utils/constants.ts +++ b/contracts/exchange/test/utils/constants.ts @@ -24,10 +24,7 @@ export const constants = { ExchangeFunctionName.MarketBuyOrdersNoThrow, ExchangeFunctionName.MarketSellOrdersNoThrow, ], - MATCH_ORDER_FN_NAMES: [ - ExchangeFunctionName.MatchOrders, - ExchangeFunctionName.MatchOrdersWithMaximalFill, - ], + MATCH_ORDER_FN_NAMES: [ExchangeFunctionName.MatchOrders, ExchangeFunctionName.MatchOrdersWithMaximalFill], BATCH_MATCH_ORDER_FN_NAMES: [ ExchangeFunctionName.BatchMatchOrders, ExchangeFunctionName.BatchMatchOrdersWithMaximalFill, From 52fc7517f940bcc1f28cdc4d1543f77f64c714c5 Mon Sep 17 00:00:00 2001 From: Michael Zhu Date: Fri, 4 Oct 2019 17:58:37 -0700 Subject: [PATCH 32/87] Remove approval expirations, address other comments --- .circleci/config.yml | 6 +- .../src/MixinCoordinatorApprovalVerifier.sol | 22 +- .../contracts/src/MixinCoordinatorCore.sol | 4 - .../ICoordinatorApprovalVerifier.sol | 3 - .../src/interfaces/ICoordinatorCore.sol | 3 - .../src/libs/LibCoordinatorApproval.sol | 19 +- .../src/libs/LibCoordinatorRichErrors.sol | 19 - contracts/coordinator/test/coordinator.ts | 124 +------ .../coordinator/test/coordinator_registry.ts | 55 +-- contracts/coordinator/test/libs.ts | 15 +- contracts/coordinator/test/mixins.ts | 324 +++++------------- .../test/utils/approval_factory.ts | 15 +- .../utils/coordinator_registry_wrapper.ts | 66 ---- .../test/utils/coordinator_test_factory.ts | 4 - .../coordinator/test/utils/hash_utils.ts | 29 +- contracts/coordinator/test/utils/types.ts | 2 - .../test/TestProtocolFeeCollector.sol | 5 +- package.json | 6 +- packages/order-utils/src/constants.ts | 1 - packages/order-utils/src/eip712_utils.ts | 4 - 20 files changed, 164 insertions(+), 562 deletions(-) delete mode 100644 contracts/coordinator/test/utils/coordinator_registry_wrapper.ts diff --git a/.circleci/config.yml b/.circleci/config.yml index 44f93b5dc1..43e2947822 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -67,11 +67,9 @@ jobs: - restore_cache: keys: - repo-{{ .Environment.CIRCLE_SHA1 }} - - run: yarn wsrun test:circleci @0x/contracts-multisig @0x/contracts-utils @0x/contracts-exchange-libs @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-asset-proxy @0x/contracts-exchange-forwarder @0x/contracts-dev-utils @0x/contracts-staking + - run: yarn wsrun test:circleci @0x/contracts-multisig @0x/contracts-utils @0x/contracts-exchange-libs @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-asset-proxy @0x/contracts-exchange-forwarder @0x/contracts-dev-utils @0x/contracts-staking @0x/contracts-coordinator # TODO(dorothy-zbornak): Re-enable after updating this package for 3.0. # - run: yarn wsrun test:circleci @0x/contracts-extensions - # TODO(abandeali): Re-enable after this package is complete. - # - run: yarn wsrun test:circleci @0x/contracts-coordinator test-publish: resource_class: medium+ docker: @@ -82,7 +80,7 @@ jobs: - restore_cache: keys: - repo-{{ .Environment.CIRCLE_SHA1 }} - - run: + - run: command: yarn test:publish:circleci no_output_timeout: 1800 test-doc-generation: diff --git a/contracts/coordinator/contracts/src/MixinCoordinatorApprovalVerifier.sol b/contracts/coordinator/contracts/src/MixinCoordinatorApprovalVerifier.sol index fdcb8bf267..9b542fc603 100644 --- a/contracts/coordinator/contracts/src/MixinCoordinatorApprovalVerifier.sol +++ b/contracts/coordinator/contracts/src/MixinCoordinatorApprovalVerifier.sol @@ -47,15 +47,12 @@ contract MixinCoordinatorApprovalVerifier is /// @param transaction 0x transaction containing salt, signerAddress, and data. /// @param txOrigin Required signer of Ethereum transaction calling this function. /// @param transactionSignature Proof that the transaction has been signed by the signer. - /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each - /// corresponding approval signature expires. /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each /// order in the transaction's Exchange calldata. function assertValidCoordinatorApprovals( LibZeroExTransaction.ZeroExTransaction memory transaction, address txOrigin, bytes memory transactionSignature, - uint256[] memory approvalExpirationTimeSeconds, bytes[] memory approvalSignatures ) public @@ -72,7 +69,6 @@ contract MixinCoordinatorApprovalVerifier is orders, txOrigin, transactionSignature, - approvalExpirationTimeSeconds, approvalSignatures ); } @@ -127,7 +123,7 @@ contract MixinCoordinatorApprovalVerifier is orders = new LibOrder.Order[](2); orders[0] = leftOrder; orders[1] = rightOrder; - } + } return orders; } @@ -136,15 +132,12 @@ contract MixinCoordinatorApprovalVerifier is /// @param orders Array of order structs containing order specifications. /// @param txOrigin Required signer of Ethereum transaction calling this function. /// @param transactionSignature Proof that the transaction has been signed by the signer. - /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each - /// corresponding approval signature expires. /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order. function _assertValidTransactionOrdersApproval( LibZeroExTransaction.ZeroExTransaction memory transaction, LibOrder.Order[] memory orders, address txOrigin, bytes memory transactionSignature, - uint256[] memory approvalExpirationTimeSeconds, bytes[] memory approvalSignatures ) internal @@ -164,23 +157,12 @@ contract MixinCoordinatorApprovalVerifier is uint256 signaturesLength = approvalSignatures.length; for (uint256 i = 0; i != signaturesLength; i++) { // Create approval message - uint256 currentApprovalExpirationTimeSeconds = approvalExpirationTimeSeconds[i]; CoordinatorApproval memory approval = CoordinatorApproval({ txOrigin: txOrigin, transactionHash: transactionHash, - transactionSignature: transactionSignature, - approvalExpirationTimeSeconds: currentApprovalExpirationTimeSeconds + transactionSignature: transactionSignature }); - // Ensure approval has not expired - // solhint-disable-next-line not-rely-on-time - if (currentApprovalExpirationTimeSeconds <= block.timestamp) { - LibRichErrors.rrevert(LibCoordinatorRichErrors.ApprovalExpiredError( - transactionHash, - currentApprovalExpirationTimeSeconds - )); - } - // Hash approval message and recover signer address bytes32 approvalHash = getCoordinatorApprovalHash(approval); address approvalSignerAddress = getSignerAddress(approvalHash, approvalSignatures[i]); diff --git a/contracts/coordinator/contracts/src/MixinCoordinatorCore.sol b/contracts/coordinator/contracts/src/MixinCoordinatorCore.sol index 69c3ed9fae..6a128c7c4f 100644 --- a/contracts/coordinator/contracts/src/MixinCoordinatorCore.sol +++ b/contracts/coordinator/contracts/src/MixinCoordinatorCore.sol @@ -46,15 +46,12 @@ contract MixinCoordinatorCore is /// @param transaction 0x transaction containing salt, signerAddress, and data. /// @param txOrigin Required signer of Ethereum transaction calling this function. /// @param transactionSignature Proof that the transaction has been signed by the signer. - /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each - /// corresponding approval signature expires. /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each /// order in the transaction's Exchange calldata. function executeTransaction( LibZeroExTransaction.ZeroExTransaction memory transaction, address txOrigin, bytes memory transactionSignature, - uint256[] memory approvalExpirationTimeSeconds, bytes[] memory approvalSignatures ) public @@ -66,7 +63,6 @@ contract MixinCoordinatorCore is transaction, txOrigin, transactionSignature, - approvalExpirationTimeSeconds, approvalSignatures ); diff --git a/contracts/coordinator/contracts/src/interfaces/ICoordinatorApprovalVerifier.sol b/contracts/coordinator/contracts/src/interfaces/ICoordinatorApprovalVerifier.sol index 5d5ecebe7b..994ec04623 100644 --- a/contracts/coordinator/contracts/src/interfaces/ICoordinatorApprovalVerifier.sol +++ b/contracts/coordinator/contracts/src/interfaces/ICoordinatorApprovalVerifier.sol @@ -30,15 +30,12 @@ contract ICoordinatorApprovalVerifier { /// @param transaction 0x transaction containing salt, signerAddress, and data. /// @param txOrigin Required signer of Ethereum transaction calling this function. /// @param transactionSignature Proof that the transaction has been signed by the signer. - /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each - /// corresponding approval signature expires. /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each /// order in the transaction's Exchange calldata. function assertValidCoordinatorApprovals( LibZeroExTransaction.ZeroExTransaction memory transaction, address txOrigin, bytes memory transactionSignature, - uint256[] memory approvalExpirationTimeSeconds, bytes[] memory approvalSignatures ) public diff --git a/contracts/coordinator/contracts/src/interfaces/ICoordinatorCore.sol b/contracts/coordinator/contracts/src/interfaces/ICoordinatorCore.sol index 5081869bbd..03d4ade319 100644 --- a/contracts/coordinator/contracts/src/interfaces/ICoordinatorCore.sol +++ b/contracts/coordinator/contracts/src/interfaces/ICoordinatorCore.sol @@ -29,15 +29,12 @@ contract ICoordinatorCore { /// @param transaction 0x transaction containing salt, signerAddress, and data. /// @param txOrigin Required signer of Ethereum transaction calling this function. /// @param transactionSignature Proof that the transaction has been signed by the signer. - /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each - /// corresponding approval signature expires. /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each /// order in the transaction's Exchange calldata. function executeTransaction( LibZeroExTransaction.ZeroExTransaction memory transaction, address txOrigin, bytes memory transactionSignature, - uint256[] memory approvalExpirationTimeSeconds, bytes[] memory approvalSignatures ) public diff --git a/contracts/coordinator/contracts/src/libs/LibCoordinatorApproval.sol b/contracts/coordinator/contracts/src/libs/LibCoordinatorApproval.sol index de647c5308..3fdbb04afd 100644 --- a/contracts/coordinator/contracts/src/libs/LibCoordinatorApproval.sol +++ b/contracts/coordinator/contracts/src/libs/LibCoordinatorApproval.sol @@ -30,24 +30,22 @@ contract LibCoordinatorApproval is // "CoordinatorApproval(", // "address txOrigin,", // "bytes32 transactionHash,", - // "bytes transactionSignature,", - // "uint256 approvalExpirationTimeSeconds", + // "bytes transactionSignature", // ")" // )); bytes32 constant public EIP712_COORDINATOR_APPROVAL_SCHEMA_HASH = - 0x2fbcdbaa76bc7589916958ae919dfbef04d23f6bbf26de6ff317b32c6cc01e05; + 0xa6511c04ca44625d50986f8c36bedc09366207a17b96e347094053a9f8507168; struct CoordinatorApproval { address txOrigin; // Required signer of Ethereum transaction that is submitting approval. bytes32 transactionHash; // EIP712 hash of the transaction. bytes transactionSignature; // Signature of the 0x transaction. - uint256 approvalExpirationTimeSeconds; // Timestamp in seconds for which the approval expires. } /// @dev Calculates the EIP712 hash of the Coordinator approval mesasage using the domain /// separator of this contract. - /// @param approval Coordinator approval message containing the transaction hash, transaction - /// signature, and expiration of the approval. + /// @param approval Coordinator approval message containing the transaction hash, and transaction + /// signature. /// @return approvalHash EIP712 hash of the Coordinator approval message with the domain /// separator of this contract. function getCoordinatorApprovalHash(CoordinatorApproval memory approval) @@ -60,8 +58,8 @@ contract LibCoordinatorApproval is } /// @dev Calculates the EIP712 hash of the Coordinator approval mesasage with no domain separator. - /// @param approval Coordinator approval message containing the transaction hash, transaction - // signature, and expiration of the approval. + /// @param approval Coordinator approval message containing the transaction hash, and transaction + // signature. /// @return result EIP712 hash of the Coordinator approval message with no domain separator. function _hashCoordinatorApproval(CoordinatorApproval memory approval) internal @@ -72,7 +70,6 @@ contract LibCoordinatorApproval is bytes memory transactionSignature = approval.transactionSignature; address txOrigin = approval.txOrigin; bytes32 transactionHash = approval.transactionHash; - uint256 approvalExpirationTimeSeconds = approval.approvalExpirationTimeSeconds; // Assembly for more efficiently computing: // keccak256(abi.encodePacked( @@ -80,7 +77,6 @@ contract LibCoordinatorApproval is // approval.txOrigin, // approval.transactionHash, // keccak256(approval.transactionSignature) - // approval.approvalExpirationTimeSeconds, // )); assembly { @@ -94,9 +90,8 @@ contract LibCoordinatorApproval is mstore(add(memPtr, 32), txOrigin) // txOrigin mstore(add(memPtr, 64), transactionHash) // transactionHash mstore(add(memPtr, 96), transactionSignatureHash) // transactionSignatureHash - mstore(add(memPtr, 128), approvalExpirationTimeSeconds) // approvalExpirationTimeSeconds // Compute hash - result := keccak256(memPtr, 160) + result := keccak256(memPtr, 128) } return result; } diff --git a/contracts/coordinator/contracts/src/libs/LibCoordinatorRichErrors.sol b/contracts/coordinator/contracts/src/libs/LibCoordinatorRichErrors.sol index 14f93ed359..ad7dbcc430 100644 --- a/contracts/coordinator/contracts/src/libs/LibCoordinatorRichErrors.sol +++ b/contracts/coordinator/contracts/src/libs/LibCoordinatorRichErrors.sol @@ -35,10 +35,6 @@ library LibCoordinatorRichErrors { bytes4 internal constant INVALID_ORIGIN_ERROR_SELECTOR = 0xa458d7ff; - // bytes4(keccak256("ApprovalExpiredError(bytes32,uint256)")) - bytes4 internal constant APPROVAL_EXPIRED_ERROR_SELECTOR = - 0x677b712d; - // bytes4(keccak256("InvalidApprovalSignatureError(bytes32,address)")) bytes4 internal constant INVALID_APPROVAL_SIGNATURE_ERROR_SELECTOR = 0xd789b640; @@ -74,21 +70,6 @@ library LibCoordinatorRichErrors { ); } - function ApprovalExpiredError( - bytes32 transactionHash, - uint256 approvalExpirationTime - ) - internal - pure - returns (bytes memory) - { - return abi.encodeWithSelector( - APPROVAL_EXPIRED_ERROR_SELECTOR, - transactionHash, - approvalExpirationTime - ); - } - function InvalidApprovalSignatureError( bytes32 transactionHash, address approverAddress diff --git a/contracts/coordinator/test/coordinator.ts b/contracts/coordinator/test/coordinator.ts index f14b51ca45..02db8841e3 100644 --- a/contracts/coordinator/test/coordinator.ts +++ b/contracts/coordinator/test/coordinator.ts @@ -11,7 +11,8 @@ import { import { blockchainTests, constants, - getLatestBlockTimestampAsync, + hexConcat, + hexSlice, OrderFactory, TransactionFactory, } from '@0x/contracts-test-utils'; @@ -46,7 +47,7 @@ blockchainTests.resets('Coordinator tests', env => { let testFactory: CoordinatorTestFactory; const GAS_PRICE = new BigNumber(env.txDefaults.gasPrice || constants.DEFAULT_GAS_PRICE); - const PROTOCOL_FEE_MULTIPLIER = new BigNumber(150); + const PROTOCOL_FEE_MULTIPLIER = new BigNumber(150000); const PROTOCOL_FEE = GAS_PRICE.times(PROTOCOL_FEE_MULTIPLIER); before(async () => { @@ -164,19 +165,12 @@ blockchainTests.resets('Coordinator tests', env => { const order = await orderFactory.newSignedOrderAsync(); const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, [order]); const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory.newSignedApproval( - transaction, - takerAddress, - approvalExpirationTimeSeconds, - ); + const approval = approvalFactory.newSignedApproval(transaction, takerAddress); const txData = { from: takerAddress, value: PROTOCOL_FEE }; await testFactory.executeFillTransactionTestAsync( [order], transaction, takerAddress, - [approvalExpirationTimeSeconds], [approval.signature], txData, ); @@ -191,7 +185,6 @@ blockchainTests.resets('Coordinator tests', env => { transaction, feeRecipientAddress, [], - [], txData, ); }); @@ -205,7 +198,6 @@ blockchainTests.resets('Coordinator tests', env => { transaction, feeRecipientAddress, [], - [], txData, ); }); @@ -219,7 +211,6 @@ blockchainTests.resets('Coordinator tests', env => { transaction, feeRecipientAddress, [], - [], txData, ); }); @@ -233,7 +224,6 @@ blockchainTests.resets('Coordinator tests', env => { transaction, feeRecipientAddress, [], - [], txData, ); }); @@ -247,7 +237,6 @@ blockchainTests.resets('Coordinator tests', env => { transaction, feeRecipientAddress, [], - [], txData, ); }); @@ -261,7 +250,6 @@ blockchainTests.resets('Coordinator tests', env => { transaction, takerAddress, [], - [], { from: takerAddress, gas: constants.MAX_EXECUTE_TRANSACTION_GAS, @@ -274,63 +262,31 @@ blockchainTests.resets('Coordinator tests', env => { const orders = [await orderFactory.newSignedOrderAsync()]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory.newSignedApproval( - transaction, - takerAddress, - approvalExpirationTimeSeconds, + const approval = approvalFactory.newSignedApproval(transaction, takerAddress); + const signature = hexConcat( + hexSlice(approval.signature, 0, 2), + '0xFFFFFFFF', + hexSlice(approval.signature, 6), ); - const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`; const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); await testFactory.executeFillTransactionTestAsync( orders, transaction, takerAddress, - [approvalExpirationTimeSeconds], [signature], { from: takerAddress, value: PROTOCOL_FEE }, new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, feeRecipientAddress), ); }); - it(`${fnName} should revert with an expired approval`, async () => { - const orders = [await orderFactory.newSignedOrderAsync()]; - const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); - const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER); - const approval = approvalFactory.newSignedApproval( - transaction, - takerAddress, - approvalExpirationTimeSeconds, - ); - const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); - await testFactory.executeFillTransactionTestAsync( - orders, - transaction, - takerAddress, - [approvalExpirationTimeSeconds], - [approval.signature], - { from: takerAddress, value: PROTOCOL_FEE }, - new CoordinatorRevertErrors.ApprovalExpiredError(transactionHash, approvalExpirationTimeSeconds), - ); - }); it(`${fnName} should revert if not called by tx signer or approver`, async () => { const orders = [await orderFactory.newSignedOrderAsync()]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory.newSignedApproval( - transaction, - takerAddress, - approvalExpirationTimeSeconds, - ); + const approval = approvalFactory.newSignedApproval(transaction, takerAddress); await testFactory.executeFillTransactionTestAsync( orders, transaction, takerAddress, - [approvalExpirationTimeSeconds], [approval.signature], { from: owner, value: PROTOCOL_FEE }, new CoordinatorRevertErrors.InvalidOriginError(takerAddress), @@ -344,18 +300,11 @@ blockchainTests.resets('Coordinator tests', env => { const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory.newSignedApproval( - transaction, - takerAddress, - approvalExpirationTimeSeconds, - ); + const approval = approvalFactory.newSignedApproval(transaction, takerAddress); await testFactory.executeFillTransactionTestAsync( orders, transaction, takerAddress, - [approvalExpirationTimeSeconds], [approval.signature], { from: takerAddress, @@ -368,7 +317,7 @@ blockchainTests.resets('Coordinator tests', env => { const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); - await testFactory.executeFillTransactionTestAsync(orders, transaction, feeRecipientAddress, [], [], { + await testFactory.executeFillTransactionTestAsync(orders, transaction, feeRecipientAddress, [], { from: feeRecipientAddress, gas: constants.MAX_EXECUTE_TRANSACTION_GAS, value: PROTOCOL_FEE.times(orders.length), @@ -378,7 +327,7 @@ blockchainTests.resets('Coordinator tests', env => { const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); - await testFactory.executeFillTransactionTestAsync(orders, transaction, feeRecipientAddress, [], [], { + await testFactory.executeFillTransactionTestAsync(orders, transaction, feeRecipientAddress, [], { from: feeRecipientAddress, gas: constants.MAX_EXECUTE_TRANSACTION_GAS, value: PROTOCOL_FEE.times(orders.length).plus(1), @@ -388,63 +337,31 @@ blockchainTests.resets('Coordinator tests', env => { const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory.newSignedApproval( - transaction, - takerAddress, - approvalExpirationTimeSeconds, + const approval = approvalFactory.newSignedApproval(transaction, takerAddress); + const signature = hexConcat( + hexSlice(approval.signature, 0, 2), + '0xFFFFFFFF', + hexSlice(approval.signature, 6), ); - const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`; const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); await testFactory.executeFillTransactionTestAsync( orders, transaction, takerAddress, - [approvalExpirationTimeSeconds], [signature], { from: takerAddress, value: PROTOCOL_FEE.times(orders.length) }, new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, feeRecipientAddress), ); }); - it(`${fnName} should revert with an expired approval`, async () => { - const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()]; - const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); - const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER); - const approval = approvalFactory.newSignedApproval( - transaction, - takerAddress, - approvalExpirationTimeSeconds, - ); - const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); - await testFactory.executeFillTransactionTestAsync( - orders, - transaction, - takerAddress, - [approvalExpirationTimeSeconds], - [approval.signature], - { from: takerAddress, value: PROTOCOL_FEE.times(orders.length) }, - new CoordinatorRevertErrors.ApprovalExpiredError(transactionHash, approvalExpirationTimeSeconds), - ); - }); it(`${fnName} should revert if not called by tx signer or approver`, async () => { const orders = [await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync()]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await takerTransactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory.newSignedApproval( - transaction, - takerAddress, - approvalExpirationTimeSeconds, - ); + const approval = approvalFactory.newSignedApproval(transaction, takerAddress); await testFactory.executeFillTransactionTestAsync( orders, transaction, takerAddress, - [approvalExpirationTimeSeconds], [approval.signature], { from: owner, value: PROTOCOL_FEE.times(orders.length) }, new CoordinatorRevertErrors.InvalidOriginError(takerAddress), @@ -463,7 +380,6 @@ blockchainTests.resets('Coordinator tests', env => { transaction, makerAddress, [], - [], { from: makerAddress, }, @@ -479,7 +395,6 @@ blockchainTests.resets('Coordinator tests', env => { transaction, makerAddress, [], - [], { from: makerAddress, }, @@ -494,7 +409,6 @@ blockchainTests.resets('Coordinator tests', env => { transaction, makerAddress, [], - [], { from: makerAddress, }, diff --git a/contracts/coordinator/test/coordinator_registry.ts b/contracts/coordinator/test/coordinator_registry.ts index f3830f4d86..ef20a0eaf8 100644 --- a/contracts/coordinator/test/coordinator_registry.ts +++ b/contracts/coordinator/test/coordinator_registry.ts @@ -1,62 +1,77 @@ import { blockchainTests, expect } from '@0x/contracts-test-utils'; -import { LogWithDecodedArgs } from 'ethereum-types'; -import { CoordinatorRegistryCoordinatorEndpointSetEventArgs } from '../src'; - -import { CoordinatorRegistryWrapper } from './utils/coordinator_registry_wrapper'; +import { + artifacts, + CoordinatorRegistryContract, + CoordinatorRegistryCoordinatorEndpointSetEventArgs, + CoordinatorTestFactory, +} from '../src'; // tslint:disable:no-unnecessary-type-assertion blockchainTests.resets('Coordinator Registry tests', env => { + let coordinatorRegistry: CoordinatorRegistryContract; let coordinatorOperator: string; const coordinatorEndpoint = 'http://sometec.0x.org'; const nilCoordinatorEndpoint = ''; - let coordinatorRegistryWrapper: CoordinatorRegistryWrapper; // tests before(async () => { // setup accounts (skip owner) const accounts = await env.getAccountAddressesAsync(); [, coordinatorOperator] = accounts; // deploy coordinator registry - coordinatorRegistryWrapper = new CoordinatorRegistryWrapper(env.provider); - await coordinatorRegistryWrapper.deployCoordinatorRegistryAsync(); + coordinatorRegistry = await CoordinatorRegistryContract.deployFrom0xArtifactAsync( + artifacts.CoordinatorRegistry, + env.provider, + env.txDefaults, + artifacts, + ); }); describe('core', () => { it('Should successfully set a Coordinator endpoint', async () => { - await coordinatorRegistryWrapper.setCoordinatorEndpointAsync(coordinatorOperator, coordinatorEndpoint); - const recordedCoordinatorEndpoint = await coordinatorRegistryWrapper.getCoordinatorEndpointAsync( + await coordinatorRegistry.setCoordinatorEndpoint.awaitTransactionSuccessAsync(coordinatorEndpoint, { + from: coordinatorOperator, + }); + const recordedCoordinatorEndpoint = await coordinatorRegistry.getCoordinatorEndpoint.callAsync( coordinatorOperator, ); expect(recordedCoordinatorEndpoint).to.be.equal(coordinatorEndpoint); }); it('Should successfully unset a Coordinator endpoint', async () => { // set Coordinator endpoint - await coordinatorRegistryWrapper.setCoordinatorEndpointAsync(coordinatorOperator, coordinatorEndpoint); - let recordedCoordinatorEndpoint = await coordinatorRegistryWrapper.getCoordinatorEndpointAsync( + await coordinatorRegistry.setCoordinatorEndpoint.awaitTransactionSuccessAsync(coordinatorEndpoint, { + from: coordinatorOperator, + }); + let recordedCoordinatorEndpoint = await coordinatorRegistry.getCoordinatorEndpoint.callAsync( coordinatorOperator, ); expect(recordedCoordinatorEndpoint).to.be.equal(coordinatorEndpoint); // unset Coordinator endpoint - await coordinatorRegistryWrapper.setCoordinatorEndpointAsync(coordinatorOperator, nilCoordinatorEndpoint); - recordedCoordinatorEndpoint = await coordinatorRegistryWrapper.getCoordinatorEndpointAsync( + await coordinatorRegistry.setCoordinatorEndpoint.awaitTransactionSuccessAsync(nilCoordinatorEndpoint, { + from: coordinatorOperator, + }); + recordedCoordinatorEndpoint = await coordinatorRegistry.getCoordinatorEndpoint.callAsync( coordinatorOperator, ); expect(recordedCoordinatorEndpoint).to.be.equal(nilCoordinatorEndpoint); }); it('Should emit an event when setting Coordinator endpoint', async () => { // set Coordinator endpoint - const txReceipt = await coordinatorRegistryWrapper.setCoordinatorEndpointAsync( - coordinatorOperator, + const txReceipt = await coordinatorRegistry.setCoordinatorEndpoint.awaitTransactionSuccessAsync( coordinatorEndpoint, + { + from: coordinatorOperator, + }, ); - const recordedCoordinatorEndpoint = await coordinatorRegistryWrapper.getCoordinatorEndpointAsync( + const recordedCoordinatorEndpoint = await coordinatorRegistry.getCoordinatorEndpoint.callAsync( coordinatorOperator, ); expect(recordedCoordinatorEndpoint).to.be.equal(coordinatorEndpoint); // validate event - expect(txReceipt.logs.length).to.be.equal(1); - const log = txReceipt.logs[0] as LogWithDecodedArgs; - expect(log.args.coordinatorOperator).to.be.equal(coordinatorOperator); - expect(log.args.coordinatorEndpoint).to.be.equal(coordinatorEndpoint); + const expectedEvent: CoordinatorRegistryCoordinatorEndpointSetEventArgs = { + coordinatorOperator, + coordinatorEndpoint, + }; + CoordinatorTestFactory.verifyEvents(txReceipt, [expectedEvent], 'CoordinatorEndpointSet'); }); }); }); diff --git a/contracts/coordinator/test/libs.ts b/contracts/coordinator/test/libs.ts index 5e32e55486..ef6eb0b2a7 100644 --- a/contracts/coordinator/test/libs.ts +++ b/contracts/coordinator/test/libs.ts @@ -24,9 +24,9 @@ blockchainTests.resets('Libs tests', env => { describe('getApprovalHash', () => { it('should return the correct approval hash', async () => { const signedTx = { - salt: new BigNumber(0), - gasPrice: new BigNumber(0), - expirationTimeSeconds: new BigNumber(0), + salt: constants.ZERO_AMOUNT, + gasPrice: constants.ZERO_AMOUNT, + expirationTimeSeconds: constants.ZERO_AMOUNT, signerAddress: constants.NULL_ADDRESS, data: '0x1234', signature: '0x5678', @@ -35,20 +35,13 @@ blockchainTests.resets('Libs tests', env => { chainId, }, }; - const approvalExpirationTimeSeconds = new BigNumber(0); const txOrigin = constants.NULL_ADDRESS; const approval = { txOrigin, transactionHash: transactionHashUtils.getTransactionHashHex(signedTx), transactionSignature: signedTx.signature, - approvalExpirationTimeSeconds, }; - const expectedApprovalHash = hashUtils.getApprovalHashHex( - signedTx, - coordinatorContract.address, - txOrigin, - approvalExpirationTimeSeconds, - ); + const expectedApprovalHash = hashUtils.getApprovalHashHex(signedTx, coordinatorContract.address, txOrigin); const approvalHash = await coordinatorContract.getCoordinatorApprovalHash.callAsync(approval); expect(expectedApprovalHash).to.eq(approvalHash); }); diff --git a/contracts/coordinator/test/mixins.ts b/contracts/coordinator/test/mixins.ts index 82b1c04391..4ee471b797 100644 --- a/contracts/coordinator/test/mixins.ts +++ b/contracts/coordinator/test/mixins.ts @@ -3,14 +3,14 @@ import { blockchainTests, constants, expect, - getLatestBlockTimestampAsync, + hexConcat, + hexSlice, randomAddress, TransactionFactory, } from '@0x/contracts-test-utils'; import { CoordinatorRevertErrors, transactionHashUtils } from '@0x/order-utils'; import { SignatureType, SignedOrder } from '@0x/types'; import { BigNumber, LibBytesRevertErrors } from '@0x/utils'; -import * as ethUtil from 'ethereumjs-util'; import { ApprovalFactory, artifacts, CoordinatorContract } from '../src'; @@ -83,11 +83,10 @@ blockchainTests.resets('Mixins tests', env => { it('should revert with with the Illegal signature type', async () => { const data = constants.NULL_BYTES; const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const illegalSignatureByte = ethUtil.toBuffer(SignatureType.Illegal).toString('hex'); - transaction.signature = `${transaction.signature.slice( - 0, - transaction.signature.length - 2, - )}${illegalSignatureByte}`; + transaction.signature = hexConcat( + hexSlice(transaction.signature, 0, transaction.signature.length - 1), + SignatureType.Illegal, + ); const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); expect(mixins.getSignerAddress.callAsync(transactionHash, transaction.signature)).to.revertWith( new CoordinatorRevertErrors.SignatureError( @@ -100,8 +99,7 @@ blockchainTests.resets('Mixins tests', env => { it('should revert with with the Invalid signature type', async () => { const data = constants.NULL_BYTES; const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const invalidSignatureByte = ethUtil.toBuffer(SignatureType.Invalid).toString('hex'); - transaction.signature = `0x${invalidSignatureByte}`; + transaction.signature = hexConcat(SignatureType.Invalid); const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); expect(mixins.getSignerAddress.callAsync(transactionHash, transaction.signature)).to.revertWith( new CoordinatorRevertErrors.SignatureError( @@ -111,14 +109,29 @@ blockchainTests.resets('Mixins tests', env => { ), ); }); - it("should revert with with a signature type that doesn't exist", async () => { + it('should revert with with a signature type that equals `NSignatureTypes`', async () => { + const data = constants.NULL_BYTES; + const transaction = await transactionFactory.newSignedTransactionAsync({ data }); + transaction.signature = hexConcat( + hexSlice(transaction.signature, 0, transaction.signature.length - 1), + SignatureType.NSignatureTypes, + ); + const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); + expect(mixins.getSignerAddress.callAsync(transactionHash, transaction.signature)).to.revertWith( + new CoordinatorRevertErrors.SignatureError( + CoordinatorRevertErrors.SignatureErrorCodes.Unsupported, + transactionHash, + transaction.signature, + ), + ); + }); + it("should revert with with a signature type that isn't supported", async () => { const data = constants.NULL_BYTES; const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const invalidSignatureByte = '04'; - transaction.signature = `${transaction.signature.slice( - 0, - transaction.signature.length - 2, - )}${invalidSignatureByte}`; + transaction.signature = hexConcat( + hexSlice(transaction.signature, 0, transaction.signature.length - 1), + SignatureType.Wallet, + ); const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); expect(mixins.getSignerAddress.callAsync(transactionHash, transaction.signature)).to.revertWith( new CoordinatorRevertErrors.SignatureError( @@ -215,27 +228,20 @@ blockchainTests.resets('Mixins tests', env => { describe('Single order approvals', () => { for (const fnName of exchangeConstants.SINGLE_FILL_FN_NAMES) { - it(`Should be successful: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[approver1], expiration=[valid]`, async () => { + it(`Should be successful: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[approver1]`, async () => { const orders = [defaultOrder]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, - ); + const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress); await mixins.assertValidCoordinatorApprovals.callAsync( transaction, transactionSignerAddress, transaction.signature, - [approvalExpirationTimeSeconds], [approval.signature], { from: transactionSignerAddress }, ); }); - it(`Should be successful: function=${fnName}, caller=tx_signer, senderAddress=[null], approval_sig=[approver1], expiration=[valid]`, async () => { + it(`Should be successful: function=${fnName}, caller=tx_signer, senderAddress=[null], approval_sig=[approver1]`, async () => { const order = { ...defaultOrder, senderAddress: constants.NULL_ADDRESS, @@ -243,23 +249,16 @@ blockchainTests.resets('Mixins tests', env => { const orders = [order]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, - ); + const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress); await mixins.assertValidCoordinatorApprovals.callAsync( transaction, transactionSignerAddress, transaction.signature, - [approvalExpirationTimeSeconds], [approval.signature], { from: transactionSignerAddress }, ); }); - it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[], expiration=[]`, async () => { + it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[]`, async () => { const orders = [defaultOrder]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); @@ -268,33 +267,25 @@ blockchainTests.resets('Mixins tests', env => { approvalSignerAddress1, transaction.signature, [], - [], { from: approvalSignerAddress1, }, ); }); - it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[approver1], expiration=[invalid]`, async () => { + it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[approver1]`, async () => { const orders = [defaultOrder]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, - ); + const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress); await mixins.assertValidCoordinatorApprovals.callAsync( transaction, approvalSignerAddress1, transaction.signature, - [approvalExpirationTimeSeconds], [approval.signature], { from: approvalSignerAddress1 }, ); }); - it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[], expiration=[]`, async () => { + it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[]`, async () => { const orders = [defaultOrder]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); @@ -303,29 +294,25 @@ blockchainTests.resets('Mixins tests', env => { approvalSignerAddress1, transaction.signature, [], - [], { from: approvalSignerAddress1, }, ); }); - it(`Should revert: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[invalid], expiration=[valid]`, async () => { + it(`Should revert: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[invalid]`, async () => { const orders = [defaultOrder]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, + const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress); + const signature = hexConcat( + hexSlice(approval.signature, 0, 2), + '0xFFFFFFFF', + hexSlice(approval.signature, 6), ); - const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`; const tx = mixins.assertValidCoordinatorApprovals.callAsync( transaction, transactionSignerAddress, transaction.signature, - [approvalExpirationTimeSeconds], [signature], { from: transactionSignerAddress }, ); @@ -335,48 +322,16 @@ blockchainTests.resets('Mixins tests', env => { new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress1), ); }); - it(`Should revert: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[approver1], expiration=[invalid]`, async () => { - const orders = [defaultOrder]; - const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); - const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, - ); - const tx = mixins.assertValidCoordinatorApprovals.callAsync( - transaction, - transactionSignerAddress, - transaction.signature, - [approvalExpirationTimeSeconds], - [approval.signature], - { from: transactionSignerAddress }, - ); - - const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); - expect(tx).to.revertWith( - new CoordinatorRevertErrors.ApprovalExpiredError(transactionHash, approvalExpirationTimeSeconds), - ); - }); - it(`Should revert: function=${fnName}, caller=approver2, senderAddress=[verifier], approval_sig=[approver1], expiration=[valid]`, async () => { + it(`Should revert: function=${fnName}, caller=approver2, senderAddress=[verifier], approval_sig=[approver1]`, async () => { const orders = [defaultOrder]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, - ); + const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress); const tx = mixins.assertValidCoordinatorApprovals.callAsync( transaction, transactionSignerAddress, transaction.signature, - [approvalExpirationTimeSeconds], [approval.signature], { from: approvalSignerAddress2 }, ); @@ -390,50 +345,36 @@ blockchainTests.resets('Mixins tests', env => { ...exchangeConstants.MARKET_FILL_FN_NAMES, ...exchangeConstants.MATCH_ORDER_FN_NAMES, ]) { - it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver1], approval_sig=[approver1], expiration=[valid]`, async () => { + it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver1], approval_sig=[approver1]`, async () => { const orders = [defaultOrder, defaultOrder]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, - ); + const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress); await mixins.assertValidCoordinatorApprovals.callAsync( transaction, transactionSignerAddress, transaction.signature, - [approvalExpirationTimeSeconds], [approval.signature], { from: transactionSignerAddress }, ); }); - it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[null,null], feeRecipient=[approver1,approver1], approval_sig=[approver1], expiration=[valid]`, async () => { + it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[null,null], feeRecipient=[approver1,approver1], approval_sig=[approver1]`, async () => { const orders = [defaultOrder, defaultOrder].map(order => ({ ...order, senderAddress: constants.NULL_ADDRESS, })); const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, - ); + const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress); await mixins.assertValidCoordinatorApprovals.callAsync( transaction, transactionSignerAddress, transaction.signature, - [approvalExpirationTimeSeconds], [approval.signature], { from: transactionSignerAddress }, ); }); - it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[null,null], feeRecipient=[approver1,approver1], approval_sig=[], expiration=[]`, async () => { + it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[null,null], feeRecipient=[approver1,approver1], approval_sig=[]`, async () => { const orders = [defaultOrder, defaultOrder].map(order => ({ ...order, senderAddress: constants.NULL_ADDRESS, @@ -445,56 +386,37 @@ blockchainTests.resets('Mixins tests', env => { transactionSignerAddress, transaction.signature, [], - [], { from: transactionSignerAddress }, ); }); - it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,null], feeRecipient=[approver1,approver1], approval_sig=[approver1], expiration=[valid]`, async () => { + it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,null], feeRecipient=[approver1,approver1], approval_sig=[approver1]`, async () => { const orders = [defaultOrder, { ...defaultOrder, senderAddress: constants.NULL_ADDRESS }]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, - ); + const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress); await mixins.assertValidCoordinatorApprovals.callAsync( transaction, transactionSignerAddress, transaction.signature, - [approvalExpirationTimeSeconds], [approval.signature], { from: transactionSignerAddress }, ); }); - it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver1,approver2], expiration=[valid,valid]`, async () => { + it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver1,approver2]`, async () => { const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval1 = approvalFactory1.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, - ); - const approval2 = approvalFactory2.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, - ); + const approval1 = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress); + const approval2 = approvalFactory2.newSignedApproval(transaction, transactionSignerAddress); await mixins.assertValidCoordinatorApprovals.callAsync( transaction, transactionSignerAddress, transaction.signature, - [approvalExpirationTimeSeconds, approvalExpirationTimeSeconds], [approval1.signature, approval2.signature], { from: transactionSignerAddress }, ); }); - it(`Should be successful: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver1], approval_sig=[], expiration=[]`, async () => { + it(`Should be successful: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver1], approval_sig=[]`, async () => { const orders = [defaultOrder, defaultOrder]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); @@ -503,33 +425,25 @@ blockchainTests.resets('Mixins tests', env => { approvalSignerAddress1, transaction.signature, [], - [], { from: approvalSignerAddress1 }, ); }); - it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver2], expiration=[valid]`, async () => { + it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver2]`, async () => { const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval2 = approvalFactory2.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, - ); + const approval2 = approvalFactory2.newSignedApproval(transaction, transactionSignerAddress); const tx = mixins.assertValidCoordinatorApprovals.callAsync( transaction, transactionSignerAddress, transaction.signature, - [approvalExpirationTimeSeconds], [approval2.signature], { from: approvalSignerAddress1 }, ); expect(tx).to.revertWith(new CoordinatorRevertErrors.InvalidOriginError(transactionSignerAddress)); }); - it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[], expiration=[]`, async () => { + it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[]`, async () => { const orders = [defaultOrder, defaultOrder]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); @@ -538,7 +452,6 @@ blockchainTests.resets('Mixins tests', env => { transactionSignerAddress, transaction.signature, [], - [], { from: transactionSignerAddress }, ); @@ -547,23 +460,20 @@ blockchainTests.resets('Mixins tests', env => { new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress1), ); }); - it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[invalid], expiration=[valid]`, async () => { + it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[invalid]`, async () => { const orders = [defaultOrder, defaultOrder]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, + const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress); + const signature = hexConcat( + hexSlice(approval.signature, 0, 2), + '0xFFFFFFFF', + hexSlice(approval.signature, 6), ); - const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`; const tx = mixins.assertValidCoordinatorApprovals.callAsync( transaction, transactionSignerAddress, transaction.signature, - [approvalExpirationTimeSeconds], [signature], { from: transactionSignerAddress }, ); @@ -573,28 +483,21 @@ blockchainTests.resets('Mixins tests', env => { new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress1), ); }); - it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid,invalid], expiration=[valid,valid]`, async () => { + it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid,invalid]`, async () => { const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval1 = approvalFactory1.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, - ); - const approval2 = approvalFactory2.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, + const approval1 = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress); + const approval2 = approvalFactory2.newSignedApproval(transaction, transactionSignerAddress); + const approvalSignature2 = hexConcat( + hexSlice(approval2.signature, 0, 2), + '0xFFFFFFFF', + hexSlice(approval2.signature, 6), ); - const approvalSignature2 = `${approval2.signature.slice(0, 4)}FFFFFFFF${approval2.signature.slice(12)}`; const tx = mixins.assertValidCoordinatorApprovals.callAsync( transaction, transactionSignerAddress, transaction.signature, - [approvalExpirationTimeSeconds, approvalExpirationTimeSeconds], [approval1.signature, approvalSignature2], { from: transactionSignerAddress }, ); @@ -604,23 +507,20 @@ blockchainTests.resets('Mixins tests', env => { new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress2), ); }); - it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[invalid], expiration=[valid]`, async () => { + it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[invalid]`, async () => { const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval2 = approvalFactory2.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, + const approval2 = approvalFactory2.newSignedApproval(transaction, transactionSignerAddress); + const approvalSignature2 = hexConcat( + hexSlice(approval2.signature, 0, 2), + '0xFFFFFFFF', + hexSlice(approval2.signature, 6), ); - const approvalSignature2 = `${approval2.signature.slice(0, 4)}FFFFFFFF${approval2.signature.slice(12)}`; const tx = mixins.assertValidCoordinatorApprovals.callAsync( transaction, approvalSignerAddress1, transaction.signature, - [approvalExpirationTimeSeconds], [approvalSignature2], { from: approvalSignerAddress1 }, ); @@ -630,79 +530,16 @@ blockchainTests.resets('Mixins tests', env => { new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress2), ); }); - it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid,valid], expiration=[valid,invalid]`, async () => { - const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }]; - const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); - const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds1 = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approvalExpirationTimeSeconds2 = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER); - const approval1 = approvalFactory1.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds1, - ); - const approval2 = approvalFactory2.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds2, - ); - - const tx = mixins.assertValidCoordinatorApprovals.callAsync( - transaction, - transactionSignerAddress, - transaction.signature, - [approvalExpirationTimeSeconds1, approvalExpirationTimeSeconds2], - [approval1.signature, approval2.signature], - { from: transactionSignerAddress }, - ); - const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); - expect(tx).to.revertWith( - new CoordinatorRevertErrors.ApprovalExpiredError(transactionHash, approvalExpirationTimeSeconds2), - ); - }); - it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid], expiration=[invalid]`, async () => { - const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }]; - const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); - const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER); - const approval2 = approvalFactory2.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, - ); - - const tx = mixins.assertValidCoordinatorApprovals.callAsync( - transaction, - approvalSignerAddress1, - transaction.signature, - [approvalExpirationTimeSeconds], - [approval2.signature], - { from: approvalSignerAddress1 }, - ); - const transactionHash = transactionHashUtils.getTransactionHashHex(transaction); - expect(tx).to.revertWith( - new CoordinatorRevertErrors.ApprovalExpiredError(transactionHash, approvalExpirationTimeSeconds), - ); - }); - it(`Should revert: function=${fnName} caller=approver2, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[valid], expiration=[valid]`, async () => { + it(`Should revert: function=${fnName} caller=approver2, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[valid]`, async () => { const orders = [defaultOrder, defaultOrder]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = await transactionFactory.newSignedTransactionAsync({ data }); - const currentTimestamp = await getLatestBlockTimestampAsync(); - const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval1 = approvalFactory1.newSignedApproval( - transaction, - transactionSignerAddress, - approvalExpirationTimeSeconds, - ); + const approval1 = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress); const tx = mixins.assertValidCoordinatorApprovals.callAsync( transaction, transactionSignerAddress, transaction.signature, - [approvalExpirationTimeSeconds], [approval1.signature], { from: approvalSignerAddress2 }, ); @@ -720,7 +557,6 @@ blockchainTests.resets('Mixins tests', env => { transactionSignerAddress, transaction.signature, [], - [], { from: transactionSignerAddress }, ); }); @@ -733,7 +569,6 @@ blockchainTests.resets('Mixins tests', env => { transactionSignerAddress, transaction.signature, [], - [], { from: transactionSignerAddress }, ); }); @@ -745,7 +580,6 @@ blockchainTests.resets('Mixins tests', env => { transactionSignerAddress, transaction.signature, [], - [], { from: transactionSignerAddress }, ); }); diff --git a/contracts/coordinator/test/utils/approval_factory.ts b/contracts/coordinator/test/utils/approval_factory.ts index 8496d868f4..2ee069de03 100644 --- a/contracts/coordinator/test/utils/approval_factory.ts +++ b/contracts/coordinator/test/utils/approval_factory.ts @@ -1,7 +1,5 @@ -import { signingUtils } from '@0x/contracts-test-utils'; +import { hexConcat, signingUtils } from '@0x/contracts-test-utils'; import { SignatureType, SignedZeroExTransaction } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as ethUtil from 'ethereumjs-util'; import { hashUtils, SignedCoordinatorApproval } from './index'; @@ -17,21 +15,14 @@ export class ApprovalFactory { public newSignedApproval( transaction: SignedZeroExTransaction, txOrigin: string, - approvalExpirationTimeSeconds: BigNumber, signatureType: SignatureType = SignatureType.EthSign, ): SignedCoordinatorApproval { - const approvalHashBuff = hashUtils.getApprovalHashBuffer( - transaction, - this._verifyingContractAddress, - txOrigin, - approvalExpirationTimeSeconds, - ); + const approvalHashBuff = hashUtils.getApprovalHashBuffer(transaction, this._verifyingContractAddress, txOrigin); const signatureBuff = signingUtils.signMessage(approvalHashBuff, this._privateKey, signatureType); const signedApproval = { txOrigin, transaction, - approvalExpirationTimeSeconds, - signature: ethUtil.addHexPrefix(signatureBuff.toString('hex')), + signature: hexConcat(signatureBuff), }; return signedApproval; } diff --git a/contracts/coordinator/test/utils/coordinator_registry_wrapper.ts b/contracts/coordinator/test/utils/coordinator_registry_wrapper.ts deleted file mode 100644 index a31d90b03b..0000000000 --- a/contracts/coordinator/test/utils/coordinator_registry_wrapper.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { artifacts as exchangeArtifacts } from '@0x/contracts-exchange'; -import { LogDecoder, txDefaults } from '@0x/contracts-test-utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { TransactionReceiptWithDecodedLogs, ZeroExProvider } from 'ethereum-types'; - -import { artifacts, CoordinatorRegistryContract } from '../../src'; - -export class CoordinatorRegistryWrapper { - private readonly _web3Wrapper: Web3Wrapper; - private readonly _provider: ZeroExProvider; - private readonly _logDecoder: LogDecoder; - private _coordinatorRegistryContract?: CoordinatorRegistryContract; - /** - * Instanitates an CoordinatorRegistryWrapper - * @param provider Web3 provider to use for all JSON RPC requests - * Instance of CoordinatorRegistryWrapper - */ - constructor(provider: ZeroExProvider) { - this._web3Wrapper = new Web3Wrapper(provider); - this._provider = provider; - this._logDecoder = new LogDecoder(this._web3Wrapper, { ...exchangeArtifacts, ...artifacts }); - } - public async deployCoordinatorRegistryAsync(): Promise { - this._coordinatorRegistryContract = await CoordinatorRegistryContract.deployFrom0xArtifactAsync( - artifacts.CoordinatorRegistry, - this._provider, - txDefaults, - artifacts, - ); - if (this._coordinatorRegistryContract === undefined) { - throw new Error(`Failed to deploy Coordinator Registry contract.`); - } - return this._coordinatorRegistryContract; - } - public async setCoordinatorEndpointAsync( - coordinatorOperator: string, - coordinatorEndpoint: string, - ): Promise { - this._assertCoordinatorRegistryDeployed(); - const txReceipt = await this._logDecoder.getTxWithDecodedLogsAsync( - await (this - ._coordinatorRegistryContract as CoordinatorRegistryContract).setCoordinatorEndpoint.sendTransactionAsync( - coordinatorEndpoint, - { - from: coordinatorOperator, - }, - ), - ); - return txReceipt; - } - public async getCoordinatorEndpointAsync(coordinatorOperator: string): Promise { - this._assertCoordinatorRegistryDeployed(); - const coordinatorEndpoint = await (this - ._coordinatorRegistryContract as CoordinatorRegistryContract).getCoordinatorEndpoint.callAsync( - coordinatorOperator, - ); - return coordinatorEndpoint; - } - private _assertCoordinatorRegistryDeployed(): void { - if (this._coordinatorRegistryContract === undefined) { - throw new Error( - 'The Coordinator Registry contract was not deployed through the CoordinatorRegistryWrapper. Call `deployCoordinatorRegistryAsync` to deploy.', - ); - } - } -} diff --git a/contracts/coordinator/test/utils/coordinator_test_factory.ts b/contracts/coordinator/test/utils/coordinator_test_factory.ts index c8a88c0760..caca5877da 100644 --- a/contracts/coordinator/test/utils/coordinator_test_factory.ts +++ b/contracts/coordinator/test/utils/coordinator_test_factory.ts @@ -71,7 +71,6 @@ export class CoordinatorTestFactory { orders: SignedOrder[], transaction: SignedZeroExTransaction, txOrigin: string, - approvalExpirationTimeSeconds: BigNumber[], approvalSignatures: string[], txData: Partial, revertError?: RevertError, @@ -81,7 +80,6 @@ export class CoordinatorTestFactory { transaction, txOrigin, transaction.signature, - approvalExpirationTimeSeconds, approvalSignatures, txData, ); @@ -106,7 +104,6 @@ export class CoordinatorTestFactory { orders: SignedOrder[], transaction: SignedZeroExTransaction, txOrigin: string, - approvalExpirationTimeSeconds: BigNumber[], approvalSignatures: string[], txData: Partial, ): Promise { @@ -114,7 +111,6 @@ export class CoordinatorTestFactory { transaction, txOrigin, transaction.signature, - approvalExpirationTimeSeconds, approvalSignatures, txData, ); diff --git a/contracts/coordinator/test/utils/hash_utils.ts b/contracts/coordinator/test/utils/hash_utils.ts index 54214cf3bd..1781608e49 100644 --- a/contracts/coordinator/test/utils/hash_utils.ts +++ b/contracts/coordinator/test/utils/hash_utils.ts @@ -1,33 +1,16 @@ +import { hexConcat } from '@0x/contracts-test-utils'; import { eip712Utils } from '@0x/order-utils'; import { SignedZeroExTransaction } from '@0x/types'; -import { BigNumber, signTypedDataUtils } from '@0x/utils'; -import * as _ from 'lodash'; +import { signTypedDataUtils } from '@0x/utils'; export const hashUtils = { - getApprovalHashBuffer( - transaction: SignedZeroExTransaction, - verifyingContract: string, - txOrigin: string, - approvalExpirationTimeSeconds: BigNumber, - ): Buffer { - const typedData = eip712Utils.createCoordinatorApprovalTypedData( - transaction, - verifyingContract, - txOrigin, - approvalExpirationTimeSeconds, - ); + getApprovalHashBuffer(transaction: SignedZeroExTransaction, verifyingContract: string, txOrigin: string): Buffer { + const typedData = eip712Utils.createCoordinatorApprovalTypedData(transaction, verifyingContract, txOrigin); const hashBuffer = signTypedDataUtils.generateTypedDataHash(typedData); return hashBuffer; }, - getApprovalHashHex( - transaction: SignedZeroExTransaction, - verifyingContract: string, - txOrigin: string, - approvalExpirationTimeSeconds: BigNumber, - ): string { - const hashHex = `0x${hashUtils - .getApprovalHashBuffer(transaction, verifyingContract, txOrigin, approvalExpirationTimeSeconds) - .toString('hex')}`; + getApprovalHashHex(transaction: SignedZeroExTransaction, verifyingContract: string, txOrigin: string): string { + const hashHex = hexConcat(hashUtils.getApprovalHashBuffer(transaction, verifyingContract, txOrigin)); return hashHex; }, }; diff --git a/contracts/coordinator/test/utils/types.ts b/contracts/coordinator/test/utils/types.ts index e0a3eafea4..4efc9b184d 100644 --- a/contracts/coordinator/test/utils/types.ts +++ b/contracts/coordinator/test/utils/types.ts @@ -1,10 +1,8 @@ import { SignedZeroExTransaction } from '@0x/types'; -import { BigNumber } from '@0x/utils'; export interface CoordinatorApproval { transaction: SignedZeroExTransaction; txOrigin: string; - approvalExpirationTimeSeconds: BigNumber; } export interface SignedCoordinatorApproval extends CoordinatorApproval { diff --git a/contracts/exchange/contracts/test/TestProtocolFeeCollector.sol b/contracts/exchange/contracts/test/TestProtocolFeeCollector.sol index 6830586061..2f1b33959b 100644 --- a/contracts/exchange/contracts/test/TestProtocolFeeCollector.sol +++ b/contracts/exchange/contracts/test/TestProtocolFeeCollector.sol @@ -53,7 +53,10 @@ contract TestProtocolFeeCollector { payable { if (msg.value != protocolFeePaid) { - assert(msg.value == 0); + require( + msg.value == 0, + "No value should be forwarded to collector when paying fee in WETH" + ); // Transfer the protocol fee to this address in WETH. IEtherToken(_wethAddress).transferFrom( diff --git a/package.json b/package.json index 4f77217ad6..7eeed92f4f 100644 --- a/package.json +++ b/package.json @@ -25,8 +25,8 @@ "install:all": "yarn install", "wsrun": "wsrun", "lerna": "lerna", - "build": "lerna link && wsrun build $PKG -r --stages --fast-exit --exclude-missing --exclude @0x/contracts-extensions --exclude @0x/contracts-coordinator", - "build:ci": "lerna link && wsrun build:ci $PKG --fast-exit -r --stages --exclude-missing --exclude @0x/contracts-extensions --exclude @0x/contracts-coordinator", + "build": "lerna link && wsrun build $PKG -r --stages --fast-exit --exclude-missing --exclude @0x/contracts-extensions", + "build:ci": "lerna link && wsrun build:ci $PKG --fast-exit -r --stages --exclude-missing --exclude @0x/contracts-extensions", "build:contracts": "lerna link && wsrun build -p ${npm_package_config_contractsPackages} -c --fast-exit -r --stages --exclude-missing", "build:monorepo_scripts": "PKG=@0x/monorepo-scripts yarn build", "build:ts": "tsc -b", @@ -51,7 +51,7 @@ "lint:contracts": "wsrun lint -p ${npm_package_config_contractsPackages} -c --fast-exit --stages --exclude-missing" }, "config": { - "contractsPackages": "@0x/contracts-asset-proxy @0x/contracts-dev-utils @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-exchange-libs @0x/contracts-integrations @0x/contracts-multisig @0x/contracts-staking @0x/contracts-test-utils @0x/contracts-utils", + "contractsPackages": "@0x/contracts-asset-proxy @0x/contracts-dev-utils @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-exchange-libs @0x/contracts-integrations @0x/contracts-multisig @0x/contracts-staking @0x/contracts-test-utils @0x/contracts-utils @0x/contracts-coordinator", "mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic", "packagesWithDocPages": "contract-wrappers 0x.js connect json-schemas subproviders web3-wrapper order-utils sol-compiler sol-coverage sol-profiler sol-trace ethereum-types asset-buyer asset-swapper migrations", "ignoreDependencyVersions": "@types/styled-components @types/node", diff --git a/packages/order-utils/src/constants.ts b/packages/order-utils/src/constants.ts index 8c6fd8d9a1..b2768f4918 100644 --- a/packages/order-utils/src/constants.ts +++ b/packages/order-utils/src/constants.ts @@ -147,7 +147,6 @@ export const constants = { { name: 'txOrigin', type: 'address' }, { name: 'transactionHash', type: 'bytes32' }, { name: 'transactionSignature', type: 'bytes' }, - { name: 'approvalExpirationTimeSeconds', type: 'uint256' }, ], }, ERC20_METHOD_ABI, diff --git a/packages/order-utils/src/eip712_utils.ts b/packages/order-utils/src/eip712_utils.ts index 2b9404cc65..0370db9d97 100644 --- a/packages/order-utils/src/eip712_utils.ts +++ b/packages/order-utils/src/eip712_utils.ts @@ -9,7 +9,6 @@ import { SignedZeroExTransaction, ZeroExTransaction, } from '@0x/types'; -import { BigNumber } from '@0x/utils'; import * as _ from 'lodash'; import { constants } from './constants'; @@ -99,14 +98,12 @@ export const eip712Utils = { * @param transaction A 0x transaction * @param verifyingContract The coordinator extension contract address that will be verifying the typedData * @param txOrigin The desired `tx.origin` that should be able to submit an Ethereum txn involving this 0x transaction - * @param approvalExpirationTimeSeconds The approvals expiration time * @return A typed data object */ createCoordinatorApprovalTypedData: ( transaction: SignedZeroExTransaction, verifyingContract: string, txOrigin: string, - approvalExpirationTimeSeconds: BigNumber, ): EIP712TypedData => { const domain = { ...transaction.domain, @@ -119,7 +116,6 @@ export const eip712Utils = { txOrigin, transactionHash, transactionSignature: transaction.signature, - approvalExpirationTimeSeconds: approvalExpirationTimeSeconds.toString(), }; const typedData = eip712Utils.createTypedData( constants.COORDINATOR_APPROVAL_SCHEMA.name, From a0f5a8b64bd0be95068932fcb6cfe6a2e9df8644 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Mon, 7 Oct 2019 13:50:23 +0900 Subject: [PATCH 33/87] Simplify Makers Interactions with Staking Pools. - No longer an upper limit on how many makers can be in a pool. - No longer a handshake for a maker to join a pool. - No longer any special powers given to makers. - Pool Id starts at 1 and increments by 1. --- .../test/deployment_manager_test.ts | 1 - .../integrations/test/deployment_test.ts | 1 - contracts/staking/CHANGELOG.json | 21 + .../staking/contracts/src/StakingProxy.sol | 8 - .../contracts/src/fees/MixinExchangeFees.sol | 3 +- .../contracts/src/immutable/MixinStorage.sol | 13 +- .../src/interfaces/IStakingEvents.sol | 26 +- .../contracts/src/interfaces/IStorage.sol | 5 - .../contracts/src/interfaces/IStructs.sol | 11 - .../src/libs/LibStakingRichErrors.sol | 38 +- .../src/staking_pools/MixinStakingPool.sol | 176 +------- .../staking/contracts/src/sys/MixinParams.sol | 12 - .../test/TestAssertStorageParams.sol | 2 - .../contracts/test/TestProtocolFees.sol | 8 +- .../test/TestStorageLayoutAndConstants.sol | 12 +- contracts/staking/test/actors/maker_actor.ts | 20 +- .../test/actors/pool_operator_actor.ts | 53 +-- contracts/staking/test/migration_test.ts | 15 +- contracts/staking/test/pools_test.ts | 392 +----------------- .../staking/test/unit_tests/params_test.ts | 7 +- .../test/unit_tests/protocol_fees_test.ts | 1 + contracts/staking/test/utils/api_wrapper.ts | 2 - contracts/staking/test/utils/constants.ts | 5 +- contracts/staking/test/utils/types.ts | 1 - packages/order-utils/CHANGELOG.json | 4 + .../order-utils/src/staking_revert_errors.ts | 8 +- 26 files changed, 90 insertions(+), 755 deletions(-) diff --git a/contracts/integrations/test/deployment_manager_test.ts b/contracts/integrations/test/deployment_manager_test.ts index d3cc022c84..26591a3b5c 100644 --- a/contracts/integrations/test/deployment_manager_test.ts +++ b/contracts/integrations/test/deployment_manager_test.ts @@ -171,7 +171,6 @@ blockchainTests('Deployment Manager', env => { stakingConstants.DEFAULT_PARAMS.epochDurationInSeconds, stakingConstants.DEFAULT_PARAMS.rewardDelegatedStakeWeight, stakingConstants.DEFAULT_PARAMS.minimumPoolStake, - stakingConstants.DEFAULT_PARAMS.maximumMakersInPool, stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaNumerator, stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaDenominator, ]); diff --git a/contracts/integrations/test/deployment_test.ts b/contracts/integrations/test/deployment_test.ts index 895a09e6f9..fd88c20cc5 100644 --- a/contracts/integrations/test/deployment_test.ts +++ b/contracts/integrations/test/deployment_test.ts @@ -292,7 +292,6 @@ blockchainTests('Deployment and Configuration End to End Tests', env => { stakingConstants.DEFAULT_PARAMS.epochDurationInSeconds, stakingConstants.DEFAULT_PARAMS.rewardDelegatedStakeWeight, stakingConstants.DEFAULT_PARAMS.minimumPoolStake, - stakingConstants.DEFAULT_PARAMS.maximumMakersInPool, stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaNumerator, stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaDenominator, ]); diff --git a/contracts/staking/CHANGELOG.json b/contracts/staking/CHANGELOG.json index 8c747dbbee..6ffc8f5be0 100644 --- a/contracts/staking/CHANGELOG.json +++ b/contracts/staking/CHANGELOG.json @@ -72,5 +72,26 @@ } ], "timestamp": 1570135330 + }, + { + "version": "1.1.0-beta.1", + "changes": [ + { + "note": "Removed handshake when adding maker to pool.", + "pr": 2250 + }, + { + "note": "Removed upper limit on number of makers in a pool.", + "pr": 2250 + }, + { + "note": "Removed operator permissions from makers.", + "pr": 2250 + }, + { + "note": "Pool Id starts at 1 and increases by 1.", + "pr": 2250 + } + ] } ] diff --git a/contracts/staking/contracts/src/StakingProxy.sol b/contracts/staking/contracts/src/StakingProxy.sol index 194dc70ef9..e2135f7b87 100644 --- a/contracts/staking/contracts/src/StakingProxy.sol +++ b/contracts/staking/contracts/src/StakingProxy.sol @@ -173,14 +173,6 @@ contract StakingProxy is )); } - // Pools must allow at least one maker - if (maximumMakersInPool == 0) { - LibRichErrors.rrevert( - LibStakingRichErrors.InvalidParamValueError( - LibStakingRichErrors.InvalidParamValueErrorCodes.InvalidMaximumMakersInPool - )); - } - // Minimum stake must be > 1 if (minimumPoolStake < 2) { LibRichErrors.rrevert( diff --git a/contracts/staking/contracts/src/fees/MixinExchangeFees.sol b/contracts/staking/contracts/src/fees/MixinExchangeFees.sol index 37dc7159f6..239145da75 100644 --- a/contracts/staking/contracts/src/fees/MixinExchangeFees.sol +++ b/contracts/staking/contracts/src/fees/MixinExchangeFees.sol @@ -67,7 +67,8 @@ contract MixinExchangeFees is } // Get the pool id of the maker address. - bytes32 poolId = getStakingPoolIdOfMaker(makerAddress); + bytes32 poolId = poolIdByMaker[makerAddress]; + // Only attribute the protocol fee payment to a pool if the maker is // registered to a pool. if (poolId == NIL_POOL_ID) { diff --git a/contracts/staking/contracts/src/immutable/MixinStorage.sol b/contracts/staking/contracts/src/immutable/MixinStorage.sol index 147831b8c8..f109726529 100644 --- a/contracts/staking/contracts/src/immutable/MixinStorage.sol +++ b/contracts/staking/contracts/src/immutable/MixinStorage.sol @@ -69,12 +69,10 @@ contract MixinStorage is mapping (address => uint256) internal _withdrawableStakeByOwner; // tracking Pool Id - bytes32 public nextPoolId = INITIAL_POOL_ID; + bytes32 public nextPoolId = bytes32(uint256(1)); - // mapping from Maker Address to a struct representing the pool the maker has joined and - // whether the operator of that pool has subsequently added the maker. - // (access externally using `getStakingPoolIdOfMaker`) - mapping (address => IStructs.MakerPoolJoinStatus) internal _poolJoinedByMakerAddress; + // mapping from Maker Address to Pool Id of maker + mapping (address => bytes32) public poolIdByMaker; // mapping from Pool Id to Pool mapping (bytes32 => IStructs.Pool) internal _poolById; @@ -83,7 +81,7 @@ contract MixinStorage is mapping (bytes32 => uint256) public rewardsByPoolId; // current epoch - uint256 public currentEpoch = INITIAL_EPOCH; + uint256 public currentEpoch; // current epoch start time uint256 public currentEpochStartTimeInSeconds; @@ -108,9 +106,6 @@ contract MixinStorage is // Minimum amount of stake required in a pool to collect rewards. uint256 public minimumPoolStake; - // Maximum number of maker addresses allowed to be registered to a pool. - uint256 public maximumMakersInPool; - // Numerator for cobb douglas alpha factor. uint32 public cobbDouglasAlphaNumerator; diff --git a/contracts/staking/contracts/src/interfaces/IStakingEvents.sol b/contracts/staking/contracts/src/interfaces/IStakingEvents.sol index 530e37d46b..353f5dda4d 100644 --- a/contracts/staking/contracts/src/interfaces/IStakingEvents.sol +++ b/contracts/staking/contracts/src/interfaces/IStakingEvents.sol @@ -92,14 +92,12 @@ interface IStakingEvents { /// @param epochDurationInSeconds Minimum seconds between epochs. /// @param rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm. /// @param minimumPoolStake Minimum amount of stake required in a pool to collect rewards. - /// @param maximumMakersInPool Maximum number of maker addresses allowed to be registered to a pool. /// @param cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor. /// @param cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor. event ParamsSet( uint256 epochDurationInSeconds, uint32 rewardDelegatedStakeWeight, uint256 minimumPoolStake, - uint256 maximumMakersInPool, uint256 cobbDouglasAlphaNumerator, uint256 cobbDouglasAlphaDenominator ); @@ -114,28 +112,12 @@ interface IStakingEvents { uint32 operatorShare ); - /// @dev Emitted by MixinStakingPool when a new maker requests to join a pool. - /// @param poolId Unique id of pool. - /// @param makerAddress Adress of maker joining the pool. - event PendingAddMakerToPool( - bytes32 indexed poolId, - address makerAddress - ); - - /// @dev Emitted by MixinStakingPool when a new maker is added to a pool. - /// @param poolId Unique id of pool. + /// @dev Emitted by MixinStakingPool when a maker sets their pool. /// @param makerAddress Adress of maker added to pool. - event MakerAddedToStakingPool( - bytes32 indexed poolId, - address makerAddress - ); - - /// @dev Emitted by MixinStakingPool when a maker is removed from a pool. /// @param poolId Unique id of pool. - /// @param makerAddress Adress of maker added to pool. - event MakerRemovedFromStakingPool( - bytes32 indexed poolId, - address makerAddress + event MakerStakingPoolSet( + address indexed makerAddress, + bytes32 indexed poolId ); /// @dev Emitted when a staking pool's operator share is decreased. diff --git a/contracts/staking/contracts/src/interfaces/IStorage.sol b/contracts/staking/contracts/src/interfaces/IStorage.sol index 300a8bfb18..1a9a6fd478 100644 --- a/contracts/staking/contracts/src/interfaces/IStorage.sol +++ b/contracts/staking/contracts/src/interfaces/IStorage.sol @@ -90,11 +90,6 @@ interface IStorage { view returns (uint256); - function maximumMakersInPool() - external - view - returns(uint256); - function cobbDouglasAlphaNumerator() external view diff --git a/contracts/staking/contracts/src/interfaces/IStructs.sol b/contracts/staking/contracts/src/interfaces/IStructs.sol index e91c68d4d3..61ebae8ada 100644 --- a/contracts/staking/contracts/src/interfaces/IStructs.sol +++ b/contracts/staking/contracts/src/interfaces/IStructs.sol @@ -95,24 +95,13 @@ interface IStructs { uint256 denominator; } - /// @dev State for keeping track of which pool a maker has joined, and if the operator has - /// added them (see MixinStakingPool). - /// @param poolId Unique Id of staking pool. - /// @param confirmed Whether the operator has added the maker to the pool. - struct MakerPoolJoinStatus { - bytes32 poolId; - bool confirmed; - } - /// @dev Holds the metadata for a staking pool. /// @param initialized True iff the balance struct is initialized. /// @param operator of the pool. /// @param operatorShare Fraction of the total balance owned by the operator, in ppm. - /// @param numberOfMakers Number of makers in the pool. struct Pool { bool initialized; address payable operator; uint32 operatorShare; - uint32 numberOfMakers; } } diff --git a/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol b/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol index 6f9cea14d6..4051b44bda 100644 --- a/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol +++ b/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol @@ -47,13 +47,6 @@ library LibStakingRichErrors { InvalidEpochDuration } - enum MakerPoolAssignmentErrorCodes { - MakerAddressAlreadyRegistered, - MakerAddressNotRegistered, - MakerAddressNotPendingAdd, - PoolIsFull - } - enum ExchangeManagerErrorCodes { ExchangeAlreadyRegistered, ExchangeNotRegistered @@ -71,13 +64,9 @@ library LibStakingRichErrors { bytes4 internal constant INSUFFICIENT_BALANCE_ERROR_SELECTOR = 0x84c8b7c9; - // bytes4(keccak256("OnlyCallableByPoolOperatorOrMakerError(address,bytes32)")) - bytes4 internal constant ONLY_CALLABLE_BY_POOL_OPERATOR_OR_MAKER_ERROR_SELECTOR = - 0x7677eb13; - - // bytes4(keccak256("MakerPoolAssignmentError(uint8,address,bytes32)")) - bytes4 internal constant MAKER_POOL_ASSIGNMENT_ERROR_SELECTOR = - 0x69945e3f; + // bytes4(keccak256("OnlyCallableByPoolOperatorError(address,bytes32)")) + bytes4 internal constant ONLY_CALLABLE_BY_POOL_OPERATOR_ERROR_SELECTOR = + 0x82ded785; // bytes4(keccak256("BlockTimestampTooLowError(uint256,uint256)")) bytes4 internal constant BLOCK_TIMESTAMP_TOO_LOW_ERROR_SELECTOR = @@ -171,7 +160,7 @@ library LibStakingRichErrors { ); } - function OnlyCallableByPoolOperatorOrMakerError( + function OnlyCallableByPoolOperatorError( address senderAddress, bytes32 poolId ) @@ -180,29 +169,12 @@ library LibStakingRichErrors { returns (bytes memory) { return abi.encodeWithSelector( - ONLY_CALLABLE_BY_POOL_OPERATOR_OR_MAKER_ERROR_SELECTOR, + ONLY_CALLABLE_BY_POOL_OPERATOR_ERROR_SELECTOR, senderAddress, poolId ); } - function MakerPoolAssignmentError( - MakerPoolAssignmentErrorCodes errorCodes, - address makerAddress, - bytes32 poolId - ) - internal - pure - returns (bytes memory) - { - return abi.encodeWithSelector( - MAKER_POOL_ASSIGNMENT_ERROR_SELECTOR, - errorCodes, - makerAddress, - poolId - ); - } - function BlockTimestampTooLowError( uint256 epochEndTime, uint256 currentBlockTimestamp diff --git a/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol b/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol index e9b76656d2..f787dc09a9 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol @@ -34,10 +34,10 @@ contract MixinStakingPool is using LibSafeMath for uint256; using LibSafeDowncast for uint256; - /// @dev Asserts that the sender is the operator of the input pool or the input maker. + /// @dev Asserts that the sender is the operator of the input pool. /// @param poolId Pool sender must be operator of. - modifier onlyStakingPoolOperatorOrMaker(bytes32 poolId) { - _assertSenderIsPoolOperatorOrMaker(poolId); + modifier onlyStakingPoolOperator(bytes32 poolId) { + _assertSenderIsPoolOperator(poolId); _; } @@ -68,8 +68,7 @@ contract MixinStakingPool is IStructs.Pool memory pool = IStructs.Pool({ initialized: true, operator: operator, - operatorShare: operatorShare, - numberOfMakers: 0 + operatorShare: operatorShare }); _poolById[poolId] = pool; @@ -81,7 +80,7 @@ contract MixinStakingPool is emit StakingPoolCreated(poolId, operator, operatorShare); if (addOperatorAsMaker) { - _addMakerToStakingPool(poolId, operator); + setMakerStakingPool(poolId); } return poolId; @@ -92,7 +91,7 @@ contract MixinStakingPool is /// @param newOperatorShare The newly decreased percentage of any rewards owned by the operator. function decreaseStakingPoolOperatorShare(bytes32 poolId, uint32 newOperatorShare) external - onlyStakingPoolOperatorOrMaker(poolId) + onlyStakingPoolOperator(poolId) { // load pool and assert that we can decrease uint32 currentOperatorShare = _poolById[poolId].operatorShare; @@ -111,92 +110,17 @@ contract MixinStakingPool is ); } - /// @dev Allows caller to join a staking pool if already assigned. + /// @dev Allows caller to join a staking pool as a maker. /// @param poolId Unique id of pool. - function joinStakingPoolAsMaker(bytes32 poolId) - external - { - // Is the maker already in a pool? - address makerAddress = msg.sender; - IStructs.MakerPoolJoinStatus memory poolJoinStatus = _poolJoinedByMakerAddress[makerAddress]; - if (poolJoinStatus.confirmed) { - LibRichErrors.rrevert(LibStakingRichErrors.MakerPoolAssignmentError( - LibStakingRichErrors.MakerPoolAssignmentErrorCodes.MakerAddressAlreadyRegistered, - makerAddress, - poolJoinStatus.poolId - )); - } - - poolJoinStatus.poolId = poolId; - _poolJoinedByMakerAddress[makerAddress] = poolJoinStatus; - - // Maker has joined to the pool, awaiting operator confirmation - emit PendingAddMakerToPool( - poolId, - makerAddress - ); - } - - /// @dev Adds a maker to a staking pool. Note that this is only callable by the pool operator. - /// Note also that the maker must have previously called joinStakingPoolAsMaker. - /// @param poolId Unique id of pool. - /// @param makerAddress Address of maker. - function addMakerToStakingPool( - bytes32 poolId, - address makerAddress - ) - external - onlyStakingPoolOperatorOrMaker(poolId) - { - _addMakerToStakingPool(poolId, makerAddress); - } - - /// @dev Removes a maker from a staking pool. Note that this is only callable by the pool operator or maker. - /// Note also that the maker does not have to *agree* to leave the pool; this action is - /// at the sole discretion of the pool operator. - /// @param poolId Unique id of pool. - /// @param makerAddress Address of maker. - function removeMakerFromStakingPool( - bytes32 poolId, - address makerAddress - ) - external - onlyStakingPoolOperatorOrMaker(poolId) - { - bytes32 makerPoolId = getStakingPoolIdOfMaker(makerAddress); - if (makerPoolId != poolId) { - LibRichErrors.rrevert(LibStakingRichErrors.MakerPoolAssignmentError( - LibStakingRichErrors.MakerPoolAssignmentErrorCodes.MakerAddressNotRegistered, - makerAddress, - makerPoolId - )); - } - - // remove the pool and confirmation from the maker status - delete _poolJoinedByMakerAddress[makerAddress]; - _poolById[poolId].numberOfMakers = uint256(_poolById[poolId].numberOfMakers).safeSub(1).downcastToUint32(); - - // Maker has been removed from the pool` - emit MakerRemovedFromStakingPool( - poolId, - makerAddress - ); - } - - /// @dev Returns the pool id of the input maker. - /// @param makerAddress Address of maker - /// @return Pool id, nil if maker is not yet assigned to a pool. - function getStakingPoolIdOfMaker(address makerAddress) + function setMakerStakingPool(bytes32 poolId) public - view - returns (bytes32) { - IStructs.MakerPoolJoinStatus memory poolJoinStatus = _poolJoinedByMakerAddress[makerAddress]; - if (poolJoinStatus.confirmed) { - return poolJoinStatus.poolId; - } else { - return NIL_POOL_ID; - } + address maker = msg.sender; + poolIdByMaker[maker] = poolId; + emit MakerStakingPoolSet( + maker, + poolId + ); } /// @dev Returns a staking pool @@ -209,65 +133,6 @@ contract MixinStakingPool is return _poolById[poolId]; } - /// @dev Adds a maker to a staking pool. Note that this is only callable by the pool operator. - /// Note also that the maker must have previously called joinStakingPoolAsMaker. - /// @param poolId Unique id of pool. - /// @param makerAddress Address of maker. - function _addMakerToStakingPool( - bytes32 poolId, - address makerAddress - ) - internal - { - // cache pool and join status for use throughout this function - IStructs.Pool memory pool = _poolById[poolId]; - IStructs.MakerPoolJoinStatus memory poolJoinStatus = _poolJoinedByMakerAddress[makerAddress]; - - // Is the maker already in a pool? - if (poolJoinStatus.confirmed) { - LibRichErrors.rrevert(LibStakingRichErrors.MakerPoolAssignmentError( - LibStakingRichErrors.MakerPoolAssignmentErrorCodes.MakerAddressAlreadyRegistered, - makerAddress, - poolJoinStatus.poolId - )); - } - - // Is the maker trying to join this pool; or are they the operator? - bytes32 makerPendingPoolId = poolJoinStatus.poolId; - if (makerPendingPoolId != poolId && makerAddress != pool.operator) { - LibRichErrors.rrevert(LibStakingRichErrors.MakerPoolAssignmentError( - LibStakingRichErrors.MakerPoolAssignmentErrorCodes.MakerAddressNotPendingAdd, - makerAddress, - makerPendingPoolId - )); - } - - // Is the pool already full? - // NOTE: If maximumMakersInPool is decreased below the number of makers currently in a pool, - // the pool will no longer be able to add more makers. - if (pool.numberOfMakers >= maximumMakersInPool) { - LibRichErrors.rrevert(LibStakingRichErrors.MakerPoolAssignmentError( - LibStakingRichErrors.MakerPoolAssignmentErrorCodes.PoolIsFull, - makerAddress, - poolId - )); - } - - // Add maker to pool - poolJoinStatus = IStructs.MakerPoolJoinStatus({ - poolId: poolId, - confirmed: true - }); - _poolJoinedByMakerAddress[makerAddress] = poolJoinStatus; - _poolById[poolId].numberOfMakers = uint256(pool.numberOfMakers).safeAdd(1).downcastToUint32(); - - // Maker has been added to the pool - emit MakerAddedToStakingPool( - poolId, - makerAddress - ); - } - /// @dev Computes the unique id that comes after the input pool id. /// @param poolId Unique id of pool. /// @return Next pool id after input pool. @@ -276,7 +141,7 @@ contract MixinStakingPool is pure returns (bytes32) { - return bytes32(uint256(poolId).safeAdd(POOL_ID_INCREMENT_AMOUNT)); + return bytes32(uint256(poolId).safeAdd(1)); } /// @dev Reverts iff a staking pool does not exist. @@ -327,19 +192,16 @@ contract MixinStakingPool is } } - /// @dev Asserts that the sender is the operator of the input pool or the input maker. + /// @dev Asserts that the sender is the operator of the input pool. /// @param poolId Pool sender must be operator of. - function _assertSenderIsPoolOperatorOrMaker(bytes32 poolId) + function _assertSenderIsPoolOperator(bytes32 poolId) private view { address operator = _poolById[poolId].operator; - if ( - msg.sender != operator && - getStakingPoolIdOfMaker(msg.sender) != poolId - ) { + if (msg.sender != operator) { LibRichErrors.rrevert( - LibStakingRichErrors.OnlyCallableByPoolOperatorOrMakerError( + LibStakingRichErrors.OnlyCallableByPoolOperatorError( msg.sender, poolId ) diff --git a/contracts/staking/contracts/src/sys/MixinParams.sol b/contracts/staking/contracts/src/sys/MixinParams.sol index b4384feeb7..a242e8b35d 100644 --- a/contracts/staking/contracts/src/sys/MixinParams.sol +++ b/contracts/staking/contracts/src/sys/MixinParams.sol @@ -32,14 +32,12 @@ contract MixinParams is /// @param _epochDurationInSeconds Minimum seconds between epochs. /// @param _rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm. /// @param _minimumPoolStake Minimum amount of stake required in a pool to collect rewards. - /// @param _maximumMakersInPool Maximum number of maker addresses allowed to be registered to a pool. /// @param _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor. /// @param _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor. function setParams( uint256 _epochDurationInSeconds, uint32 _rewardDelegatedStakeWeight, uint256 _minimumPoolStake, - uint256 _maximumMakersInPool, uint32 _cobbDouglasAlphaNumerator, uint32 _cobbDouglasAlphaDenominator ) @@ -50,7 +48,6 @@ contract MixinParams is _epochDurationInSeconds, _rewardDelegatedStakeWeight, _minimumPoolStake, - _maximumMakersInPool, _cobbDouglasAlphaNumerator, _cobbDouglasAlphaDenominator ); @@ -60,7 +57,6 @@ contract MixinParams is /// @return _epochDurationInSeconds Minimum seconds between epochs. /// @return _rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm. /// @return _minimumPoolStake Minimum amount of stake required in a pool to collect rewards. - /// @return _maximumMakersInPool Maximum number of maker addresses allowed to be registered to a pool. /// @return _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor. /// @return _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor. function getParams() @@ -70,7 +66,6 @@ contract MixinParams is uint256 _epochDurationInSeconds, uint32 _rewardDelegatedStakeWeight, uint256 _minimumPoolStake, - uint256 _maximumMakersInPool, uint32 _cobbDouglasAlphaNumerator, uint32 _cobbDouglasAlphaDenominator ) @@ -78,7 +73,6 @@ contract MixinParams is _epochDurationInSeconds = epochDurationInSeconds; _rewardDelegatedStakeWeight = rewardDelegatedStakeWeight; _minimumPoolStake = minimumPoolStake; - _maximumMakersInPool = maximumMakersInPool; _cobbDouglasAlphaNumerator = cobbDouglasAlphaNumerator; _cobbDouglasAlphaDenominator = cobbDouglasAlphaDenominator; } @@ -96,7 +90,6 @@ contract MixinParams is 10 days, // epochDurationInSeconds (90 * PPM_DENOMINATOR) / 100, // rewardDelegatedStakeWeight 100 * MIN_TOKEN_VALUE, // minimumPoolStake - 10, // maximumMakersInPool 1, // cobbDouglasAlphaNumerator 2 // cobbDouglasAlphaDenominator ); @@ -110,7 +103,6 @@ contract MixinParams is if (epochDurationInSeconds != 0 && rewardDelegatedStakeWeight != 0 && minimumPoolStake != 0 && - maximumMakersInPool != 0 && cobbDouglasAlphaNumerator != 0 && cobbDouglasAlphaDenominator != 0 ) { @@ -126,14 +118,12 @@ contract MixinParams is /// @param _epochDurationInSeconds Minimum seconds between epochs. /// @param _rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm. /// @param _minimumPoolStake Minimum amount of stake required in a pool to collect rewards. - /// @param _maximumMakersInPool Maximum number of maker addresses allowed to be registered to a pool. /// @param _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor. /// @param _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor. function _setParams( uint256 _epochDurationInSeconds, uint32 _rewardDelegatedStakeWeight, uint256 _minimumPoolStake, - uint256 _maximumMakersInPool, uint32 _cobbDouglasAlphaNumerator, uint32 _cobbDouglasAlphaDenominator ) @@ -142,7 +132,6 @@ contract MixinParams is epochDurationInSeconds = _epochDurationInSeconds; rewardDelegatedStakeWeight = _rewardDelegatedStakeWeight; minimumPoolStake = _minimumPoolStake; - maximumMakersInPool = _maximumMakersInPool; cobbDouglasAlphaNumerator = _cobbDouglasAlphaNumerator; cobbDouglasAlphaDenominator = _cobbDouglasAlphaDenominator; @@ -150,7 +139,6 @@ contract MixinParams is _epochDurationInSeconds, _rewardDelegatedStakeWeight, _minimumPoolStake, - _maximumMakersInPool, _cobbDouglasAlphaNumerator, _cobbDouglasAlphaDenominator ); diff --git a/contracts/staking/contracts/test/TestAssertStorageParams.sol b/contracts/staking/contracts/test/TestAssertStorageParams.sol index 5fb94f0763..aa5c5c62b0 100644 --- a/contracts/staking/contracts/test/TestAssertStorageParams.sol +++ b/contracts/staking/contracts/test/TestAssertStorageParams.sol @@ -29,7 +29,6 @@ contract TestAssertStorageParams is uint256 epochDurationInSeconds; uint32 rewardDelegatedStakeWeight; uint256 minimumPoolStake; - uint256 maximumMakersInPool; uint32 cobbDouglasAlphaNumerator; uint32 cobbDouglasAlphaDenominator; } @@ -48,7 +47,6 @@ contract TestAssertStorageParams is epochDurationInSeconds = params.epochDurationInSeconds; rewardDelegatedStakeWeight = params.rewardDelegatedStakeWeight; minimumPoolStake = params.minimumPoolStake; - maximumMakersInPool = params.maximumMakersInPool; cobbDouglasAlphaNumerator = params.cobbDouglasAlphaNumerator; cobbDouglasAlphaDenominator = params.cobbDouglasAlphaDenominator; _assertValidStorageParams(); diff --git a/contracts/staking/contracts/test/TestProtocolFees.sol b/contracts/staking/contracts/test/TestProtocolFees.sol index 8194e4f3eb..383eeef0cc 100644 --- a/contracts/staking/contracts/test/TestProtocolFees.sol +++ b/contracts/staking/contracts/test/TestProtocolFees.sol @@ -48,13 +48,6 @@ contract TestProtocolFees is _removeAuthorizedAddressAtIndex(msg.sender, 0); } - function addMakerToPool(bytes32 poolId, address makerAddress) - external - { - _poolJoinedByMakerAddress[makerAddress].poolId = poolId; - _poolJoinedByMakerAddress[makerAddress].confirmed = true; - } - function advanceEpoch() external { @@ -76,6 +69,7 @@ contract TestProtocolFees is for (uint256 i = 0; i < makerAddresses.length; ++i) { pool.isMaker[makerAddresses[i]] = true; _makersToTestPoolIds[makerAddresses[i]] = poolId; + poolIdByMaker[makerAddresses[i]] = poolId; } } diff --git a/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol b/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol index 21a577bc7d..67bf4088a5 100644 --- a/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol +++ b/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol @@ -183,8 +183,8 @@ contract TestStorageLayoutAndConstants is slot := add(slot, 0x1) assertSlotAndOffset( - _poolJoinedByMakerAddress_slot, - _poolJoinedByMakerAddress_offset, + poolIdByMaker_slot, + poolIdByMaker_offset, slot, offset ) @@ -270,14 +270,6 @@ contract TestStorageLayoutAndConstants is ) slot := add(slot, 0x1) - assertSlotAndOffset( - maximumMakersInPool_slot, - maximumMakersInPool_offset, - slot, - offset - ) - slot := add(slot, 0x1) - assertSlotAndOffset( cobbDouglasAlphaNumerator_slot, cobbDouglasAlphaNumerator_offset, diff --git a/contracts/staking/test/actors/maker_actor.ts b/contracts/staking/test/actors/maker_actor.ts index ecca34c9d1..da076b63be 100644 --- a/contracts/staking/test/actors/maker_actor.ts +++ b/contracts/staking/test/actors/maker_actor.ts @@ -2,28 +2,22 @@ import { expect } from '@0x/contracts-test-utils'; import { RevertError } from '@0x/utils'; import * as _ from 'lodash'; -import { constants as stakingConstants } from '../utils/constants'; - import { PoolOperatorActor } from './pool_operator_actor'; export class MakerActor extends PoolOperatorActor { - public async joinStakingPoolAsMakerAsync(poolId: string, revertError?: RevertError): Promise { - // Join pool - const txReceiptPromise = this._stakingApiWrapper.stakingContract.joinStakingPoolAsMaker.awaitTransactionSuccessAsync( + public async setMakerStakingPoolAsync(poolId: string, revertError?: RevertError): Promise { + // add maker + const txReceiptPromise = this._stakingApiWrapper.stakingContract.setMakerStakingPool.awaitTransactionSuccessAsync( poolId, - { from: this._owner }, + { from: this.getOwner() }, ); - if (revertError !== undefined) { await expect(txReceiptPromise).to.revertWith(revertError); return; } await txReceiptPromise; - - // Pool id of the maker should be nil (join would've thrown otherwise) - const poolIdOfMaker = await this._stakingApiWrapper.stakingContract.getStakingPoolIdOfMaker.callAsync( - this._owner, - ); - expect(poolIdOfMaker, 'pool id of maker').to.be.equal(stakingConstants.NIL_POOL_ID); + // check the pool id of the maker + const poolIdOfMaker = await this._stakingApiWrapper.stakingContract.poolIdByMaker.callAsync(this.getOwner()); + expect(poolIdOfMaker, 'pool id of maker').to.be.equal(poolId); } } diff --git a/contracts/staking/test/actors/pool_operator_actor.ts b/contracts/staking/test/actors/pool_operator_actor.ts index bd74e5bb17..5116ea25b1 100644 --- a/contracts/staking/test/actors/pool_operator_actor.ts +++ b/contracts/staking/test/actors/pool_operator_actor.ts @@ -2,8 +2,6 @@ import { expect } from '@0x/contracts-test-utils'; import { RevertError } from '@0x/utils'; import * as _ from 'lodash'; -import { constants as stakingConstants } from '../utils/constants'; - import { BaseActor } from './base_actor'; export class PoolOperatorActor extends BaseActor { @@ -30,60 +28,11 @@ export class PoolOperatorActor extends BaseActor { if (addOperatorAsMaker) { // check the pool id of the operator - const poolIdOfMaker = await this._stakingApiWrapper.stakingContract.getStakingPoolIdOfMaker.callAsync( - this._owner, - ); + const poolIdOfMaker = await this._stakingApiWrapper.stakingContract.poolIdByMaker.callAsync(this._owner); expect(poolIdOfMaker, 'pool id of maker').to.be.equal(poolId); - // check the number of makers in the pool - const pool = await this._stakingApiWrapper.stakingContract.getStakingPool.callAsync(poolId); - expect(pool.numberOfMakers, 'number of makers in pool').to.be.bignumber.equal(1); } return poolId; } - public async addMakerToStakingPoolAsync( - poolId: string, - makerAddress: string, - revertError?: RevertError, - ): Promise { - // add maker - const txReceiptPromise = this._stakingApiWrapper.stakingContract.addMakerToStakingPool.awaitTransactionSuccessAsync( - poolId, - makerAddress, - { from: this._owner }, - ); - if (revertError !== undefined) { - await expect(txReceiptPromise).to.revertWith(revertError); - return; - } - await txReceiptPromise; - // check the pool id of the maker - const poolIdOfMaker = await this._stakingApiWrapper.stakingContract.getStakingPoolIdOfMaker.callAsync( - makerAddress, - ); - expect(poolIdOfMaker, 'pool id of maker').to.be.equal(poolId); - } - public async removeMakerFromStakingPoolAsync( - poolId: string, - makerAddress: string, - revertError?: RevertError, - ): Promise { - // remove maker - const txReceiptPromise = this._stakingApiWrapper.stakingContract.removeMakerFromStakingPool.awaitTransactionSuccessAsync( - poolId, - makerAddress, - { from: this._owner }, - ); - if (revertError !== undefined) { - await expect(txReceiptPromise).to.revertWith(revertError); - return; - } - await txReceiptPromise; - // check the pool id of the maker - const poolIdOfMakerAfterRemoving = await this._stakingApiWrapper.stakingContract.getStakingPoolIdOfMaker.callAsync( - makerAddress, - ); - expect(poolIdOfMakerAfterRemoving, 'pool id of maker').to.be.equal(stakingConstants.NIL_POOL_ID); - } public async decreaseStakingPoolOperatorShareAsync( poolId: string, newOperatorShare: number, diff --git a/contracts/staking/test/migration_test.ts b/contracts/staking/test/migration_test.ts index e20569f8ea..7438bdeb7c 100644 --- a/contracts/staking/test/migration_test.ts +++ b/contracts/staking/test/migration_test.ts @@ -120,9 +120,8 @@ blockchainTests('Migration tests', env => { expect(params[0]).to.bignumber.eq(stakingConstants.DEFAULT_PARAMS.epochDurationInSeconds); expect(params[1]).to.bignumber.eq(stakingConstants.DEFAULT_PARAMS.rewardDelegatedStakeWeight); expect(params[2]).to.bignumber.eq(stakingConstants.DEFAULT_PARAMS.minimumPoolStake); - expect(params[3]).to.bignumber.eq(stakingConstants.DEFAULT_PARAMS.maximumMakersInPool); - expect(params[4]).to.bignumber.eq(stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaNumerator); - expect(params[5]).to.bignumber.eq(stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaDenominator); + expect(params[3]).to.bignumber.eq(stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaNumerator); + expect(params[4]).to.bignumber.eq(stakingConstants.DEFAULT_PARAMS.cobbDouglasAlphaDenominator); }); }); @@ -309,16 +308,6 @@ blockchainTests('Migration tests', env => { }); expect(tx).to.be.fulfilled(''); }); - it('reverts if max makers in pool is 0', async () => { - const tx = proxyContract.setAndAssertParams.awaitTransactionSuccessAsync({ - ...stakingConstants.DEFAULT_PARAMS, - maximumMakersInPool: constants.ZERO_AMOUNT, - }); - const expectedError = new StakingRevertErrors.InvalidParamValueError( - StakingRevertErrors.InvalidParamValueErrorCodes.InvalidMaximumMakersInPool, - ); - expect(tx).to.revertWith(expectedError); - }); }); }); // tslint:enable:no-unnecessary-type-assertion diff --git a/contracts/staking/test/pools_test.ts b/contracts/staking/test/pools_test.ts index 7aeb808faf..eddab9095e 100644 --- a/contracts/staking/test/pools_test.ts +++ b/contracts/staking/test/pools_test.ts @@ -54,24 +54,6 @@ blockchainTests('Staking Pool Management', env => { const poolId2 = await poolOperator.createStakingPoolAsync(operatorShare, false); expect(poolId2).to.be.equal(stakingConstants.SECOND_POOL_ID); }); - it('Should fail to create several staking pools with the operator as a maker in each', async () => { - // test parameters - const operatorAddress = users[0]; - const operatorShare = (39 / 100) * PPM_DENOMINATOR; - const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper); - // create pool - const poolId1 = await poolOperator.createStakingPoolAsync(operatorShare, true); - expect(poolId1).to.be.equal(stakingConstants.INITIAL_POOL_ID); - await poolOperator.createStakingPoolAsync( - operatorShare, - true, - new StakingRevertErrors.MakerPoolAssignmentError( - StakingRevertErrors.MakerPoolAssignmentErrorCodes.MakerAddressAlreadyRegistered, - poolOperator.getOwner(), - poolId1, - ), - ); - }); it('Should fail to create a pool with operator share > 100', async () => { // test parameters const operatorAddress = users[0]; @@ -86,48 +68,6 @@ blockchainTests('Staking Pool Management', env => { // create pool await poolOperator.createStakingPoolAsync(operatorShare, false, revertError); }); - it('should fail to add a maker to a pool if maker has not called `joinStakingPoolAsMaker` yet', async () => { - // test parameters - const operatorAddress = users[0]; - const operatorShare = (39 / 100) * PPM_DENOMINATOR; - const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper); - const makerAddress = users[1]; - // create pool - const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true); - expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - await poolOperator.addMakerToStakingPoolAsync( - poolId, - makerAddress, - new StakingRevertErrors.MakerPoolAssignmentError( - StakingRevertErrors.MakerPoolAssignmentErrorCodes.MakerAddressNotPendingAdd, - makerAddress, - constants.NULL_BYTES32, - ), - ); - }); - it('should fail to add a maker to a pool if maker has called `joinStakingPoolAsMaker` on a different pool', async () => { - // test parameters - const operatorAddress = users[0]; - const operatorShare = (39 / 100) * PPM_DENOMINATOR; - const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper); - const otherPoolOperator = new PoolOperatorActor(users[1], stakingApiWrapper); - const makerAddress = users[2]; - const maker = new MakerActor(makerAddress, stakingApiWrapper); - const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true); - expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - const otherPoolId = await otherPoolOperator.createStakingPoolAsync(operatorShare, true); - // create pool - await maker.joinStakingPoolAsMakerAsync(poolId); - await otherPoolOperator.addMakerToStakingPoolAsync( - otherPoolId, - makerAddress, - new StakingRevertErrors.MakerPoolAssignmentError( - StakingRevertErrors.MakerPoolAssignmentErrorCodes.MakerAddressNotPendingAdd, - makerAddress, - poolId, - ), - ); - }); it('Should successfully create a pool and add owner as a maker', async () => { // test parameters const operatorAddress = users[0]; @@ -156,7 +96,7 @@ blockchainTests('Staking Pool Management', env => { ); return expect(tx).to.revertWith(expectedError); }); - it('Should successfully add/remove a maker to a pool', async () => { + it('Should successfully add a maker to a pool', async () => { // test parameters const operatorAddress = users[0]; const operatorShare = (39 / 100) * PPM_DENOMINATOR; @@ -167,70 +107,7 @@ blockchainTests('Staking Pool Management', env => { const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true); expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); // maker joins pool - await maker.joinStakingPoolAsMakerAsync(poolId); - // operator adds maker to pool - await poolOperator.addMakerToStakingPoolAsync(poolId, makerAddress); - // operator removes maker from pool - await poolOperator.removeMakerFromStakingPoolAsync(poolId, makerAddress); - }); - it('Should successfully add/remove a maker to a pool if approved by maker', async () => { - // test parameters - const operatorAddress = users[0]; - const operatorShare = (39 / 100) * PPM_DENOMINATOR; - const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper); - const maker1Address = users[1]; - const maker1 = new MakerActor(maker1Address, stakingApiWrapper); - const maker2Address = users[2]; - const maker2 = new MakerActor(maker2Address, stakingApiWrapper); - // create pool - const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true); - expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - // maker joins pool - await maker1.joinStakingPoolAsMakerAsync(poolId); - // operator adds maker to pool - await poolOperator.addMakerToStakingPoolAsync(poolId, maker1Address); - // maker joins pool - await maker2.joinStakingPoolAsMakerAsync(poolId); - // approved maker adds new maker to pool - await maker1.addMakerToStakingPoolAsync(poolId, maker2Address); - }); - it('should fail to add a maker to a pool if called by pending maker', async () => { - // test parameters - const operatorAddress = users[0]; - const operatorShare = (39 / 100) * PPM_DENOMINATOR; - const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper); - const makerAddress = users[1]; - const maker = new MakerActor(makerAddress, stakingApiWrapper); - // create pool - const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true); - expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - // maker joins pool - await maker.joinStakingPoolAsMakerAsync(poolId); - await maker.addMakerToStakingPoolAsync( - poolId, - makerAddress, - new StakingRevertErrors.OnlyCallableByPoolOperatorOrMakerError(makerAddress, poolId), - ); - }); - it('should fail to add a maker to a pool if not called by operator/registered maker', async () => { - // test parameters - const operatorAddress = users[0]; - const operatorShare = (39 / 100) * PPM_DENOMINATOR; - const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper); - const maker1Address = users[1]; - const maker1 = new MakerActor(maker1Address, stakingApiWrapper); - const maker2Address = users[2]; - const maker2 = new MakerActor(maker2Address, stakingApiWrapper); - // create pool - const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true); - expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - // maker joins pool - await maker1.joinStakingPoolAsMakerAsync(poolId); - await maker2.addMakerToStakingPoolAsync( - poolId, - maker1Address, - new StakingRevertErrors.OnlyCallableByPoolOperatorOrMakerError(maker2Address, poolId), - ); + await maker.setMakerStakingPoolAsync(poolId); }); it('Maker should successfully remove themselves from a pool', async () => { // test parameters @@ -243,28 +120,9 @@ blockchainTests('Staking Pool Management', env => { const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true); expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); // maker joins pool - await maker.joinStakingPoolAsMakerAsync(poolId); - // operator adds maker to pool - await poolOperator.addMakerToStakingPoolAsync(poolId, makerAddress); + await maker.setMakerStakingPoolAsync(poolId); // maker removes themselves from pool - await maker.removeMakerFromStakingPoolAsync(poolId, makerAddress); - }); - it('operator can remove a maker from their pool', async () => { - // test parameters - const operatorAddress = users[0]; - const operatorShare = (39 / 100) * PPM_DENOMINATOR; - const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper); - const makerAddress = users[1]; - const maker = new MakerActor(makerAddress, stakingApiWrapper); - // create pool - const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true); - expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - // maker joins pool - await maker.joinStakingPoolAsMakerAsync(poolId); - // operator adds maker to pool - await poolOperator.addMakerToStakingPoolAsync(poolId, makerAddress); - // operator removes maker from pool - await poolOperator.removeMakerFromStakingPoolAsync(poolId, makerAddress); + await maker.setMakerStakingPoolAsync(stakingConstants.NIL_POOL_ID); }); it('Should successfully add/remove multiple makers to the same pool', async () => { // test parameters @@ -273,227 +131,13 @@ blockchainTests('Staking Pool Management', env => { const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper); const makerAddresses = users.slice(1, 4); const makers = makerAddresses.map(makerAddress => new MakerActor(makerAddress, stakingApiWrapper)); - // create pool const poolId = await poolOperator.createStakingPoolAsync(operatorShare, false); expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - // add makers to pool - await Promise.all(makers.map(async maker => maker.joinStakingPoolAsMakerAsync(poolId))); - await Promise.all( - makerAddresses.map(async makerAddress => poolOperator.addMakerToStakingPoolAsync(poolId, makerAddress)), - ); - - // check the number of makers in the pool - let pool = await stakingApiWrapper.stakingContract.getStakingPool.callAsync(poolId); - expect(pool.numberOfMakers, 'number of makers in pool after adding').to.be.bignumber.equal(3); - - // remove maker from pool - await Promise.all( - makerAddresses.map(async makerAddress => - poolOperator.removeMakerFromStakingPoolAsync(poolId, makerAddress), - ), - ); - - // check the number of makers in the pool - pool = await stakingApiWrapper.stakingContract.getStakingPool.callAsync(poolId); - expect(pool.numberOfMakers, 'number of makers in pool after removing').to.be.bignumber.equal(0); - }); - it('should fail to remove a maker from a pool if not called by operator/registered maker', async () => { - // test parameters - const operatorAddress = users[0]; - const operatorShare = (39 / 100) * PPM_DENOMINATOR; - const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper); - const maker1Address = users[1]; - const maker1 = new MakerActor(maker1Address, stakingApiWrapper); - const maker2Address = users[2]; - const maker2 = new MakerActor(maker2Address, stakingApiWrapper); - // create pool - const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true); - expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - // maker joins pool - await maker1.joinStakingPoolAsMakerAsync(poolId); - // operator adds maker to pool - await poolOperator.addMakerToStakingPoolAsync(poolId, maker1Address); - await maker2.removeMakerFromStakingPoolAsync( - poolId, - maker1Address, - new StakingRevertErrors.OnlyCallableByPoolOperatorOrMakerError(maker2Address, poolId), - ); - }); - it('Should fail if maker already assigned to another pool tries to join', async () => { - // test parameters - const operatorShare = (39 / 100) * PPM_DENOMINATOR; - const assignedPoolOperator = new PoolOperatorActor(users[0], stakingApiWrapper); - const otherPoolOperator = new PoolOperatorActor(users[1], stakingApiWrapper); - - const makerAddress = users[2]; - const maker = new MakerActor(makerAddress, stakingApiWrapper); - - // create pools - const assignedPoolId = await assignedPoolOperator.createStakingPoolAsync(operatorShare, true); - const otherPoolId = await otherPoolOperator.createStakingPoolAsync(operatorShare, true); - expect(assignedPoolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - expect(otherPoolId).to.be.equal(stakingConstants.SECOND_POOL_ID); - - // maker joins first pool - await maker.joinStakingPoolAsMakerAsync(assignedPoolId); - // first pool operator adds maker - await assignedPoolOperator.addMakerToStakingPoolAsync(assignedPoolId, makerAddress); - - const revertError = new StakingRevertErrors.MakerPoolAssignmentError( - StakingRevertErrors.MakerPoolAssignmentErrorCodes.MakerAddressAlreadyRegistered, - makerAddress, - assignedPoolId, - ); - // second pool operator now tries to add maker - await otherPoolOperator.addMakerToStakingPoolAsync(otherPoolId, makerAddress, revertError); - }); - it('Should fail to add maker to pool if the maker has not joined any pools', async () => { - // test parameters - const operatorAddress = users[0]; - const operatorShare = (39 / 100) * PPM_DENOMINATOR; - const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper); - - const makerAddress = users[1]; - - // create pool - const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true); - expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - - const revertError = new StakingRevertErrors.MakerPoolAssignmentError( - StakingRevertErrors.MakerPoolAssignmentErrorCodes.MakerAddressNotPendingAdd, - makerAddress, - stakingConstants.NIL_POOL_ID, - ); - // operator adds maker to pool - await poolOperator.addMakerToStakingPoolAsync(poolId, makerAddress, revertError); - }); - it('Should fail to add maker to pool if the maker joined a different pool', async () => { - // test parameters - const operatorShare = (39 / 100) * PPM_DENOMINATOR; - const assignedPoolOperator = new PoolOperatorActor(users[0], stakingApiWrapper); - const otherPoolOperator = new PoolOperatorActor(users[1], stakingApiWrapper); - - const makerAddress = users[2]; - const maker = new MakerActor(makerAddress, stakingApiWrapper); - - // create pools - const joinedPoolId = await assignedPoolOperator.createStakingPoolAsync(operatorShare, true); - const otherPoolId = await otherPoolOperator.createStakingPoolAsync(operatorShare, true); - expect(joinedPoolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - expect(otherPoolId).to.be.equal(stakingConstants.SECOND_POOL_ID); - - // maker joins first pool - await maker.joinStakingPoolAsMakerAsync(joinedPoolId); - - const revertError = new StakingRevertErrors.MakerPoolAssignmentError( - StakingRevertErrors.MakerPoolAssignmentErrorCodes.MakerAddressNotPendingAdd, - makerAddress, - joinedPoolId, - ); - // second pool operator now tries to add maker - await otherPoolOperator.addMakerToStakingPoolAsync(otherPoolId, makerAddress, revertError); - }); - it('Should fail to add the same maker twice', async () => { - // test parameters - const operatorAddress = users[0]; - const operatorShare = (39 / 100) * PPM_DENOMINATOR; - const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper); - const makerAddress = users[1]; - const maker = new MakerActor(makerAddress, stakingApiWrapper); - // create pool - const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true); - expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - // add maker to pool - await maker.joinStakingPoolAsMakerAsync(poolId); - await poolOperator.addMakerToStakingPoolAsync(poolId, makerAddress); - const revertError = new StakingRevertErrors.MakerPoolAssignmentError( - StakingRevertErrors.MakerPoolAssignmentErrorCodes.MakerAddressAlreadyRegistered, - makerAddress, - poolId, - ); - // add same maker to pool again - await poolOperator.addMakerToStakingPoolAsync(poolId, makerAddress, revertError); - }); - it('Should fail to remove a maker that does not exist', async () => { - // test parameters - const operatorAddress = users[0]; - const operatorShare = (39 / 100) * PPM_DENOMINATOR; - const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper); - const makerAddress = users[1]; - // create pool - const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true); - expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - const revertError = new StakingRevertErrors.MakerPoolAssignmentError( - StakingRevertErrors.MakerPoolAssignmentErrorCodes.MakerAddressNotRegistered, - makerAddress, - stakingConstants.NIL_POOL_ID, - ); - // remove non-existent maker from pool - await poolOperator.removeMakerFromStakingPoolAsync(poolId, makerAddress, revertError); - }); - it('Should fail to remove a maker when called by someone other than the pool operator or maker', async () => { - // test parameters - const operatorAddress = users[0]; - const operatorShare = (39 / 100) * PPM_DENOMINATOR; - const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper); - const makerAddress = users[1]; - const maker = new MakerActor(makerAddress, stakingApiWrapper); - const neitherOperatorNorMakerAddress = users[2]; - // create pool - const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true); - expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - // add maker to pool - await maker.joinStakingPoolAsMakerAsync(poolId); - await poolOperator.addMakerToStakingPoolAsync(poolId, makerAddress); - // try to remove the maker address from an address other than the operator - const revertError = new StakingRevertErrors.OnlyCallableByPoolOperatorOrMakerError( - neitherOperatorNorMakerAddress, - poolId, - ); - const tx = stakingApiWrapper.stakingContract.removeMakerFromStakingPool.awaitTransactionSuccessAsync( - poolId, - makerAddress, - { from: neitherOperatorNorMakerAddress }, - ); - await expect(tx).to.revertWith(revertError); - }); - it('Should fail to add a maker if the pool is full', async () => { - // test parameters - const operatorAddress = users[0]; - const operatorShare = (39 / 100) * PPM_DENOMINATOR; - const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper); - - const makerAddresses = users.slice(1, stakingConstants.DEFAULT_PARAMS.maximumMakersInPool.toNumber() + 2); - const makers = makerAddresses.map(makerAddress => new MakerActor(makerAddress, stakingApiWrapper)); - - // create pool - const poolId = await poolOperator.createStakingPoolAsync(operatorShare, false); - expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - - // add makers to pool - await Promise.all(makers.map(async maker => maker.joinStakingPoolAsMakerAsync(poolId))); - await Promise.all( - _.initial(makerAddresses).map(async makerAddress => - poolOperator.addMakerToStakingPoolAsync(poolId, makerAddress), - ), - ); - - // check the number of makers in the pool - const pool = await stakingApiWrapper.stakingContract.getStakingPool.callAsync(poolId); - expect(pool.numberOfMakers, 'number of makers in pool').to.be.bignumber.equal( - stakingConstants.DEFAULT_PARAMS.maximumMakersInPool, - ); - - const lastMakerAddress = _.last(makerAddresses) as string; - // Try to add last maker to the pool - const revertError = new StakingRevertErrors.MakerPoolAssignmentError( - StakingRevertErrors.MakerPoolAssignmentErrorCodes.PoolIsFull, - lastMakerAddress, - poolId, - ); - await poolOperator.addMakerToStakingPoolAsync(poolId, lastMakerAddress, revertError); + await Promise.all(makers.map(async maker => maker.setMakerStakingPoolAsync(poolId))); + // remove makers to pool + await Promise.all(makers.map(async maker => maker.setMakerStakingPoolAsync(stakingConstants.NIL_POOL_ID))); }); it('Operator should successfully decrease their share of rewards', async () => { // test parameters @@ -508,24 +152,6 @@ blockchainTests('Staking Pool Management', env => { // decrease operator share await poolOperator.decreaseStakingPoolOperatorShareAsync(poolId, operatorShare - 1); }); - it('Maker should successfuly decrease their share of rewards', async () => { - // test parameters - const operatorAddress = users[0]; - const operatorShare = (39 / 100) * PPM_DENOMINATOR; - const poolOperator = new PoolOperatorActor(operatorAddress, stakingApiWrapper); - const makerAddress = users[1]; - const maker = new MakerActor(makerAddress, stakingApiWrapper); - // create pool - const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true); - expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); - // maker joins pool - await maker.joinStakingPoolAsMakerAsync(poolId); - // operator adds maker to pool - await poolOperator.addMakerToStakingPoolAsync(poolId, makerAddress); - - // decrease operator share - await maker.decreaseStakingPoolOperatorShareAsync(poolId, operatorShare - 1); - }); it('Should fail if operator tries to increase their share of rewards', async () => { // test parameters const operatorAddress = users[0]; @@ -563,7 +189,7 @@ blockchainTests('Staking Pool Management', env => { // decrease operator share await poolOperator.decreaseStakingPoolOperatorShareAsync(poolId, operatorShare, revertError); }); - it('should fail to decrease operator share if not called by operator/registered maker', async () => { + it('should fail to decrease operator share if not called by operator', async () => { // test parameters const operatorAddress = users[0]; const operatorShare = (39 / 100) * PPM_DENOMINATOR; @@ -576,7 +202,7 @@ blockchainTests('Staking Pool Management', env => { await maker.decreaseStakingPoolOperatorShareAsync( poolId, operatorShare - 1, - new StakingRevertErrors.OnlyCallableByPoolOperatorOrMakerError(makerAddress, poolId), + new StakingRevertErrors.OnlyCallableByPoolOperatorError(makerAddress, poolId), ); }); }); diff --git a/contracts/staking/test/unit_tests/params_test.ts b/contracts/staking/test/unit_tests/params_test.ts index 5a0a45fe43..f24c6ec983 100644 --- a/contracts/staking/test/unit_tests/params_test.ts +++ b/contracts/staking/test/unit_tests/params_test.ts @@ -37,7 +37,6 @@ blockchainTests('Configurable Parameters unit tests', env => { new BigNumber(_params.epochDurationInSeconds), new BigNumber(_params.rewardDelegatedStakeWeight), new BigNumber(_params.minimumPoolStake), - new BigNumber(_params.maximumMakersInPool), new BigNumber(_params.cobbDouglasAlphaNumerator), new BigNumber(_params.cobbDouglasAlphaDenominator), { from }, @@ -49,7 +48,6 @@ blockchainTests('Configurable Parameters unit tests', env => { expect(event.epochDurationInSeconds).to.bignumber.eq(_params.epochDurationInSeconds); expect(event.rewardDelegatedStakeWeight).to.bignumber.eq(_params.rewardDelegatedStakeWeight); expect(event.minimumPoolStake).to.bignumber.eq(_params.minimumPoolStake); - expect(event.maximumMakersInPool).to.bignumber.eq(_params.maximumMakersInPool); expect(event.cobbDouglasAlphaNumerator).to.bignumber.eq(_params.cobbDouglasAlphaNumerator); expect(event.cobbDouglasAlphaDenominator).to.bignumber.eq(_params.cobbDouglasAlphaDenominator); // Assert `getParams()`. @@ -57,9 +55,8 @@ blockchainTests('Configurable Parameters unit tests', env => { expect(actual[0]).to.bignumber.eq(_params.epochDurationInSeconds); expect(actual[1]).to.bignumber.eq(_params.rewardDelegatedStakeWeight); expect(actual[2]).to.bignumber.eq(_params.minimumPoolStake); - expect(actual[3]).to.bignumber.eq(_params.maximumMakersInPool); - expect(actual[4]).to.bignumber.eq(_params.cobbDouglasAlphaNumerator); - expect(actual[5]).to.bignumber.eq(_params.cobbDouglasAlphaDenominator); + expect(actual[3]).to.bignumber.eq(_params.cobbDouglasAlphaNumerator); + expect(actual[4]).to.bignumber.eq(_params.cobbDouglasAlphaDenominator); return receipt; } diff --git a/contracts/staking/test/unit_tests/protocol_fees_test.ts b/contracts/staking/test/unit_tests/protocol_fees_test.ts index de2f8bf29b..4da63f00a1 100644 --- a/contracts/staking/test/unit_tests/protocol_fees_test.ts +++ b/contracts/staking/test/unit_tests/protocol_fees_test.ts @@ -183,6 +183,7 @@ blockchainTests('Protocol Fees unit tests', env => { DEFAULT_PROTOCOL_FEE_PAID, { from: exchangeAddress, value: DEFAULT_PROTOCOL_FEE_PAID }, ); + assertNoWETHTransferLogs(receipt.logs); const poolFees = await getProtocolFeesAsync(poolId); expect(poolFees).to.bignumber.eq(DEFAULT_PROTOCOL_FEE_PAID); diff --git a/contracts/staking/test/utils/api_wrapper.ts b/contracts/staking/test/utils/api_wrapper.ts index c40ef7fbaa..c53f46d36c 100644 --- a/contracts/staking/test/utils/api_wrapper.ts +++ b/contracts/staking/test/utils/api_wrapper.ts @@ -114,7 +114,6 @@ export class StakingApiWrapper { new BigNumber(_params.epochDurationInSeconds), new BigNumber(_params.rewardDelegatedStakeWeight), new BigNumber(_params.minimumPoolStake), - new BigNumber(_params.maximumMakersInPool), new BigNumber(_params.cobbDouglasAlphaNumerator), new BigNumber(_params.cobbDouglasAlphaDenominator), ); @@ -135,7 +134,6 @@ export class StakingApiWrapper { 'epochDurationInSeconds', 'rewardDelegatedStakeWeight', 'minimumPoolStake', - 'maximumMakersInPool', 'cobbDouglasAlphaNumerator', 'cobbDouglasAlphaDenominator', 'wethProxyAddress', diff --git a/contracts/staking/test/utils/constants.ts b/contracts/staking/test/utils/constants.ts index 5572234a20..de50d7cb21 100644 --- a/contracts/staking/test/utils/constants.ts +++ b/contracts/staking/test/utils/constants.ts @@ -5,8 +5,8 @@ const TEN_DAYS = 10 * 24 * 60 * 60; const PPM = 10 ** 6; export const constants = { TOKEN_MULTIPLIER: testConstants.DUMMY_TOKEN_DECIMALS, - INITIAL_POOL_ID: '0x0000000000000000000000000000000100000000000000000000000000000000', - SECOND_POOL_ID: '0x0000000000000000000000000000000200000000000000000000000000000000', + INITIAL_POOL_ID: '0x0000000000000000000000000000000000000000000000000000000000000001', + SECOND_POOL_ID: '0x0000000000000000000000000000000000000000000000000000000000000002', NIL_POOL_ID: '0x0000000000000000000000000000000000000000000000000000000000000000', NIL_ADDRESS: '0x0000000000000000000000000000000000000000', INITIAL_EPOCH: new BigNumber(0), @@ -14,7 +14,6 @@ export const constants = { epochDurationInSeconds: new BigNumber(TEN_DAYS), rewardDelegatedStakeWeight: new BigNumber(PPM * 0.9), minimumPoolStake: new BigNumber(10).pow(testConstants.DUMMY_TOKEN_DECIMALS).times(100), - maximumMakersInPool: new BigNumber(10), cobbDouglasAlphaNumerator: new BigNumber(1), cobbDouglasAlphaDenominator: new BigNumber(2), }, diff --git a/contracts/staking/test/utils/types.ts b/contracts/staking/test/utils/types.ts index d50d62549e..6134b5072f 100644 --- a/contracts/staking/test/utils/types.ts +++ b/contracts/staking/test/utils/types.ts @@ -8,7 +8,6 @@ export interface StakingParams { epochDurationInSeconds: Numberish; rewardDelegatedStakeWeight: Numberish; minimumPoolStake: Numberish; - maximumMakersInPool: Numberish; cobbDouglasAlphaNumerator: Numberish; cobbDouglasAlphaDenominator: Numberish; } diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index 294c26d183..aaa6645a01 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -109,6 +109,10 @@ { "note": "Add `InvalidMinimumPoolStake` to `StakingRevertErrors.InvalidParamValueErrorCode`.", "pr": 2155 + }, + { + "note": "Renamed `OnlyCallableByPoolOperatorOrMakerError` to `OnlyCallableByPoolOperatorError`.", + "pr": 2250 } ], "timestamp": 1570135330 diff --git a/packages/order-utils/src/staking_revert_errors.ts b/packages/order-utils/src/staking_revert_errors.ts index 0ffc0ec001..5b30bd5bb5 100644 --- a/packages/order-utils/src/staking_revert_errors.ts +++ b/packages/order-utils/src/staking_revert_errors.ts @@ -61,11 +61,11 @@ export class InsufficientBalanceError extends RevertError { } } -export class OnlyCallableByPoolOperatorOrMakerError extends RevertError { +export class OnlyCallableByPoolOperatorError extends RevertError { constructor(senderAddress?: string, poolId?: string) { super( - 'OnlyCallableByPoolOperatorOrMakerError', - 'OnlyCallableByPoolOperatorOrMakerError(address senderAddress, bytes32 poolId)', + 'OnlyCallableByPoolOperatorError', + 'OnlyCallableByPoolOperatorError(address senderAddress, bytes32 poolId)', { senderAddress, poolId }, ); } @@ -194,7 +194,7 @@ const types = [ InvalidParamValueError, MakerPoolAssignmentError, OnlyCallableByExchangeError, - OnlyCallableByPoolOperatorOrMakerError, + OnlyCallableByPoolOperatorError, OnlyCallableByStakingContractError, OnlyCallableIfInCatastrophicFailureError, OnlyCallableIfNotInCatastrophicFailureError, From e2e51526489bf111b060797f33592707752df084 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Fri, 4 Oct 2019 18:20:37 -0700 Subject: [PATCH 34/87] Always validate signatures for all types --- .../contracts/src/MixinExchangeCore.sol | 28 ++++++---------- .../contracts/src/MixinSignatureValidator.sol | 32 ------------------- 2 files changed, 9 insertions(+), 51 deletions(-) diff --git a/contracts/exchange/contracts/src/MixinExchangeCore.sol b/contracts/exchange/contracts/src/MixinExchangeCore.sol index ee32be26b8..7ff964cbed 100644 --- a/contracts/exchange/contracts/src/MixinExchangeCore.sol +++ b/contracts/exchange/contracts/src/MixinExchangeCore.sol @@ -366,29 +366,19 @@ contract MixinExchangeCore is } } - // Validate either on the first fill or if the signature type requires - // regular validation. - address makerAddress = order.makerAddress; - if (orderInfo.orderTakerAssetFilledAmount == 0 || - _doesSignatureRequireRegularValidation( + // Validate signature + if (!_isValidOrderWithHashSignature( + order, orderInfo.orderHash, - makerAddress, signature ) ) { - if (!_isValidOrderWithHashSignature( - order, - orderInfo.orderHash, - signature - ) - ) { - LibRichErrors.rrevert(LibExchangeRichErrors.SignatureError( - LibExchangeRichErrors.SignatureErrorCodes.BAD_ORDER_SIGNATURE, - orderInfo.orderHash, - makerAddress, - signature - )); - } + LibRichErrors.rrevert(LibExchangeRichErrors.SignatureError( + LibExchangeRichErrors.SignatureErrorCodes.BAD_ORDER_SIGNATURE, + orderInfo.orderHash, + order.makerAddress, + signature + )); } } diff --git a/contracts/exchange/contracts/src/MixinSignatureValidator.sol b/contracts/exchange/contracts/src/MixinSignatureValidator.sol index f0387fded0..39de699429 100644 --- a/contracts/exchange/contracts/src/MixinSignatureValidator.sol +++ b/contracts/exchange/contracts/src/MixinSignatureValidator.sol @@ -169,38 +169,6 @@ contract MixinSignatureValidator is return isValid; } - /// @dev Checks if a signature is of a type that should be verified for - /// every action. - /// @param hash The hash of the order/transaction. - /// @param signerAddress The address of the signer. - /// @param signature The signature for `hash`. - /// @return needsRegularValidation True if the signature should be validated - /// for every action. - function _doesSignatureRequireRegularValidation( - bytes32 hash, - address signerAddress, - bytes memory signature - ) - internal - pure - returns (bool needsRegularValidation) - { - // Read the signatureType from the signature - SignatureType signatureType = _readSignatureType( - hash, - signerAddress, - signature - ); - - // Any signature type that makes an external call needs to be revalidated - // with every partial fill - needsRegularValidation = - signatureType == SignatureType.Wallet || - signatureType == SignatureType.Validator || - signatureType == SignatureType.EIP1271Wallet; - return needsRegularValidation; - } - /// @dev Verifies that an order, with provided order hash, has been signed /// by the given signer. /// @param order The order. From d914f6fce9292283677e78d7be251a696f993bae Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Fri, 4 Oct 2019 18:26:44 -0700 Subject: [PATCH 35/87] Test for failure with bad signature after partial fill --- contracts/exchange/test/core.ts | 2 +- contracts/exchange/test/isolated_fill_order.ts | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/contracts/exchange/test/core.ts b/contracts/exchange/test/core.ts index 397ead2eb6..b2210f6e26 100644 --- a/contracts/exchange/test/core.ts +++ b/contracts/exchange/test/core.ts @@ -230,7 +230,7 @@ blockchainTests.resets('Exchange core', () => { signedOrder = await orderFactory.newSignedOrderAsync(); }); - describe('repeatable signature types', () => { + describe('signature types', () => { beforeEach(async () => { // Approve the ERC20 proxy with the test validator wallet. await validatorWallet.approveERC20.awaitTransactionSuccessAsync( diff --git a/contracts/exchange/test/isolated_fill_order.ts b/contracts/exchange/test/isolated_fill_order.ts index d0211f7e3f..6c3ce81d97 100644 --- a/contracts/exchange/test/isolated_fill_order.ts +++ b/contracts/exchange/test/isolated_fill_order.ts @@ -1,6 +1,7 @@ import { ReferenceFunctions as LibReferenceFunctions } from '@0x/contracts-exchange-libs'; import { blockchainTests, constants, expect, hexRandom } from '@0x/contracts-test-utils'; import { ExchangeRevertErrors, LibMathRevertErrors } from '@0x/order-utils'; +import { orderHashUtils } from '@0x/order-utils'; import { FillResults, OrderInfo, OrderStatus, SignatureType } from '@0x/types'; import { BigNumber, SafeMathRevertErrors } from '@0x/utils'; import * as _ from 'lodash'; @@ -587,13 +588,21 @@ blockchainTests('Isolated fillOrder() tests', env => { return fillOrderAndAssertResultsAsync(order, order.takerAssetAmount); }); - it('can complementary fill an order with a bad signature that is checked only once', async () => { + it('cannot fill an order with a bad signature that has already been partially filled', async () => { const order = createOrder(); const takerAssetFillAmounts = splitAmount(order.takerAssetAmount); const goodSignature = createGoodSignature(SignatureType.EthSign); const badSignature = createBadSignature(SignatureType.EthSign); await fillOrderAndAssertResultsAsync(order, takerAssetFillAmounts[0], goodSignature); - await fillOrderAndAssertResultsAsync(order, takerAssetFillAmounts[1], badSignature); + const expectedError = new ExchangeRevertErrors.SignatureError( + ExchangeRevertErrors.SignatureErrorCode.BadOrderSignature, + orderHashUtils.getOrderHashHex(order), + order.makerAddress, + badSignature, + ); + expect(fillOrderAndAssertResultsAsync(order, takerAssetFillAmounts[1], badSignature)).to.revertWith( + expectedError, + ); }); }); }); From 8b695f9b986a4186877a028cd5f4f43fbf5104ba Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Fri, 4 Oct 2019 19:22:21 -0700 Subject: [PATCH 36/87] Fix race condition in tests --- contracts/exchange/test/core.ts | 2 +- .../exchange/test/isolated_fill_order.ts | 5 +- yarn.lock | 236 ++++++++++++++++++ 3 files changed, 239 insertions(+), 4 deletions(-) diff --git a/contracts/exchange/test/core.ts b/contracts/exchange/test/core.ts index b2210f6e26..8951bb2627 100644 --- a/contracts/exchange/test/core.ts +++ b/contracts/exchange/test/core.ts @@ -230,7 +230,7 @@ blockchainTests.resets('Exchange core', () => { signedOrder = await orderFactory.newSignedOrderAsync(); }); - describe('signature types', () => { + describe('callback signature types', () => { beforeEach(async () => { // Approve the ERC20 proxy with the test validator wallet. await validatorWallet.approveERC20.awaitTransactionSuccessAsync( diff --git a/contracts/exchange/test/isolated_fill_order.ts b/contracts/exchange/test/isolated_fill_order.ts index 6c3ce81d97..ef889fd781 100644 --- a/contracts/exchange/test/isolated_fill_order.ts +++ b/contracts/exchange/test/isolated_fill_order.ts @@ -1,7 +1,6 @@ import { ReferenceFunctions as LibReferenceFunctions } from '@0x/contracts-exchange-libs'; import { blockchainTests, constants, expect, hexRandom } from '@0x/contracts-test-utils'; import { ExchangeRevertErrors, LibMathRevertErrors } from '@0x/order-utils'; -import { orderHashUtils } from '@0x/order-utils'; import { FillResults, OrderInfo, OrderStatus, SignatureType } from '@0x/types'; import { BigNumber, SafeMathRevertErrors } from '@0x/utils'; import * as _ from 'lodash'; @@ -596,11 +595,11 @@ blockchainTests('Isolated fillOrder() tests', env => { await fillOrderAndAssertResultsAsync(order, takerAssetFillAmounts[0], goodSignature); const expectedError = new ExchangeRevertErrors.SignatureError( ExchangeRevertErrors.SignatureErrorCode.BadOrderSignature, - orderHashUtils.getOrderHashHex(order), + exchange.getOrderHash(order), order.makerAddress, badSignature, ); - expect(fillOrderAndAssertResultsAsync(order, takerAssetFillAmounts[1], badSignature)).to.revertWith( + return expect(fillOrderAndAssertResultsAsync(order, takerAssetFillAmounts[1], badSignature)).to.revertWith( expectedError, ); }); diff --git a/yarn.lock b/yarn.lock index a368ab64ed..44eab8d016 100644 --- a/yarn.lock +++ b/yarn.lock @@ -643,6 +643,26 @@ npmlog "^4.1.2" write-file-atomic "^2.3.0" +"@0x/abi-gen-wrappers@^5.0.3", "@0x/abi-gen-wrappers@^5.3.2": + version "5.3.2" + resolved "https://registry.npmjs.org/@0x/abi-gen-wrappers/-/abi-gen-wrappers-5.3.2.tgz#bf7d1942f56916b7d13fae627f6455f309c5c8b5" + integrity sha512-zf5RDhdmPal06exhavdjpHknYxFJ9CJc6Fsc39Ju3hFhRUn57duQozKcFSwnpPHSqUq+gddZnRTfsSRfgpRplQ== + dependencies: + "@0x/base-contract" "^5.4.0" + "@0x/contract-addresses" "^3.2.0" + "@0x/contract-artifacts" "^2.2.2" + +"@0x/assert@^2.1.0", "@0x/assert@^2.1.1", "@0x/assert@^2.1.2", "@0x/assert@^2.1.6": + version "2.1.6" + resolved "https://registry.npmjs.org/@0x/assert/-/assert-2.1.6.tgz#61c5854b555bca1f1f0503754f2fd0169bee0ef1" + integrity sha512-Gu8eBnFdEuIAH2GubWYOSVz/BIoRccKof68AziduYDHxh4nSPM6NUH52xtfUGk4nXljiOXU1XHZJhcjTObI+8Q== + dependencies: + "@0x/json-schemas" "^4.0.2" + "@0x/typescript-typings" "^4.3.0" + "@0x/utils" "^4.5.2" + lodash "^4.17.11" + valid-url "^1.0.9" + "@0x/asset-buyer@6.1.8": version "6.1.8" resolved "https://registry.yarnpkg.com/@0x/asset-buyer/-/asset-buyer-6.1.8.tgz#71f6abb366e89e62457c256644edb37e12113e94" @@ -660,6 +680,55 @@ ethereum-types "^2.1.3" lodash "^4.17.11" +"@0x/base-contract@^5.4.0": + version "5.4.0" + resolved "https://registry.npmjs.org/@0x/base-contract/-/base-contract-5.4.0.tgz#466ea98af22d7e629a21a7d16211c825664e2a48" + integrity sha512-YYkv8NwoOFCPqYS4xHAhdhYzM9PrkS03E2L4EaTJmUGOwYkfoRkbzun26Ml1fh4co7NWCfYyBqq9gfeO+wYXrA== + dependencies: + "@0x/assert" "^2.1.6" + "@0x/json-schemas" "^4.0.2" + "@0x/typescript-typings" "^4.3.0" + "@0x/utils" "^4.5.2" + "@0x/web3-wrapper" "^6.0.13" + ethereum-types "^2.1.6" + ethereumjs-account "^3.0.0" + ethereumjs-blockstream "^7.0.0" + ethereumjs-util "^5.1.1" + ethereumjs-vm "^4.0.0" + ethers "~4.0.4" + js-sha3 "^0.7.0" + lodash "^4.17.11" + uuid "^3.3.2" + +"@0x/connect@^5.0.13": + version "5.0.19" + resolved "https://registry.npmjs.org/@0x/connect/-/connect-5.0.19.tgz#569679af661ef84a4c34958388e1be7f1c250a04" + integrity sha512-XdqCxXOZfqr/WwkHseRgG+Wf9/zcfhPsUNhGZ8KUr5agFeXnUjAiS0vfV5gDThPSW/Juu0eaDT6LPapBHp+C3A== + dependencies: + "@0x/assert" "^2.1.6" + "@0x/json-schemas" "^4.0.2" + "@0x/order-utils" "^8.4.0" + "@0x/types" "^2.4.3" + "@0x/typescript-typings" "^4.3.0" + "@0x/utils" "^4.5.2" + lodash "^4.17.11" + query-string "^6.0.0" + sinon "^4.0.0" + uuid "^3.3.2" + websocket "^1.0.26" + +"@0x/contract-addresses@^3.0.1", "@0x/contract-addresses@^3.0.2", "@0x/contract-addresses@^3.2.0": + version "3.2.0" + resolved "https://registry.npmjs.org/@0x/contract-addresses/-/contract-addresses-3.2.0.tgz#606307696d9622764220a34e9d4638b899093eec" + integrity sha512-jCVEOgXPa3his4h2qm+O7tn9A2r8UJDgSzDhqhk+za237XxFc2No8TnnMP6qjew3l9ElNM1L+exZHxSd06xB/w== + dependencies: + lodash "^4.17.11" + +"@0x/contract-artifacts@^2.0.2", "@0x/contract-artifacts@^2.2.2": + version "2.2.2" + resolved "https://registry.npmjs.org/@0x/contract-artifacts/-/contract-artifacts-2.2.2.tgz#e6d771afb58d0b59c19c5364af5a42a3dfd17219" + integrity sha512-sbFnSXE6PlmYsbPXpKtEOR3YdVlSn63HhbPgQB3J5jm27wwQtnZ2Lf21I7BdiRBsHwwbf75C/s2pjNqafaRrgQ== + "@0x/contract-wrappers@^9.1.6", "@0x/contract-wrappers@^9.1.7": version "9.1.8" resolved "https://registry.yarnpkg.com/@0x/contract-wrappers/-/contract-wrappers-9.1.8.tgz#5923d35af3e4b442a57d02f74e02620b2d5b1356" @@ -684,6 +753,36 @@ lodash "^4.17.11" uuid "^3.3.2" +"@0x/contracts-erc20@^2.2.7": + version "2.2.14" + resolved "https://registry.npmjs.org/@0x/contracts-erc20/-/contracts-erc20-2.2.14.tgz#bac2528a590c0f9668811cfd23948a941ae0ad30" + integrity sha512-zGCg0Yhu/0ZMnjfEZ4ho+VWv/f0sCUQa8xHz36owB3+vnBhzz2o3+vFCctdVVR33SVe2QSgS4A97iJ2M0UsH0g== + dependencies: + "@0x/base-contract" "^5.4.0" + "@0x/contracts-utils" "^3.2.4" + "@0x/types" "^2.4.3" + "@0x/typescript-typings" "^4.3.0" + "@0x/utils" "^4.5.2" + "@0x/web3-wrapper" "^6.0.13" + ethereum-types "^2.1.6" + lodash "^4.17.11" + +"@0x/contracts-utils@^3.2.4": + version "3.2.4" + resolved "https://registry.npmjs.org/@0x/contracts-utils/-/contracts-utils-3.2.4.tgz#b5ae80684ac0542eb59925f52113ce2c8b1bdb2b" + integrity sha512-Jk3Ntdt4SUNaHua49ZBty9hMv3gwUJN5US9OLxotbrJSmqdMpZ47FD4MzQ8ORLNcnMRbtyecQabq6pJbezu2jw== + dependencies: + "@0x/base-contract" "^5.4.0" + "@0x/order-utils" "^8.4.0" + "@0x/types" "^2.4.3" + "@0x/typescript-typings" "^4.3.0" + "@0x/utils" "^4.5.2" + "@0x/web3-wrapper" "^6.0.13" + bn.js "^4.11.8" + ethereum-types "^2.1.6" + ethereumjs-util "^5.1.1" + lodash "^4.17.11" + "@0x/coordinator-server@^0.1.3": version "0.1.3" resolved "https://registry.yarnpkg.com/@0x/coordinator-server/-/coordinator-server-0.1.3.tgz#5fbb7c11bb641aa5386797769cab9a68a7d15b79" @@ -713,6 +812,21 @@ typeorm "0.2.7" websocket "^1.0.25" +"@0x/dev-utils@^2.2.6": + version "2.3.3" + resolved "https://registry.npmjs.org/@0x/dev-utils/-/dev-utils-2.3.3.tgz#9b6df00fea357fa6da02b35ca93fc89d100e1992" + integrity sha512-Pi664W/jj1U6WU+kHEPyKpflBnmKRsclB69RaL7wpnvOOFjAPhFV2/0FvIZ25w62rMzKEpfD1/1NcZ7NjAk7OQ== + dependencies: + "@0x/subproviders" "^5.0.4" + "@0x/types" "^2.4.3" + "@0x/typescript-typings" "^4.3.0" + "@0x/utils" "^4.5.2" + "@0x/web3-wrapper" "^6.0.13" + "@types/web3-provider-engine" "^14.0.0" + chai "^4.0.1" + ethereum-types "^2.1.6" + lodash "^4.17.11" + "@0x/json-schemas@^3.0.11", "@0x/json-schemas@^3.1.11": version "3.1.13" resolved "https://registry.yarnpkg.com/@0x/json-schemas/-/json-schemas-3.1.13.tgz#4b9010f1bdeaf2aef1daba1753aa2e5ecf57f654" @@ -722,6 +836,16 @@ jsonschema "^1.2.0" lodash.values "^4.3.0" +"@0x/json-schemas@^4.0.2": + version "4.0.2" + resolved "https://registry.npmjs.org/@0x/json-schemas/-/json-schemas-4.0.2.tgz#6f7c1dcde04d3acc3e8ca2f24177b9705c10e772" + integrity sha512-JHOwESZeWKAzT5Z42ZNvOvQUQ5vuRIFQWS0FNjYwV8Cv4/dRlLHd7kwxxsvlm9NxgXnOW0ddEDBbVGxhVSYNIg== + dependencies: + "@0x/typescript-typings" "^4.3.0" + "@types/node" "*" + jsonschema "^1.2.0" + lodash.values "^4.3.0" + "@0x/mesh-rpc-client@^4.0.1-beta": version "4.0.1-beta" resolved "https://registry.yarnpkg.com/@0x/mesh-rpc-client/-/mesh-rpc-client-4.0.1-beta.tgz#14db219ea398af5232811e63b7a1e5ca1de19a88" @@ -736,6 +860,29 @@ uuid "^3.3.2" websocket "^1.0.29" +"@0x/order-utils@^8.2.1", "@0x/order-utils@^8.2.2", "@0x/order-utils@^8.2.3", "@0x/order-utils@^8.2.4", "@0x/order-utils@^8.4.0": + version "8.4.0" + resolved "https://registry.npmjs.org/@0x/order-utils/-/order-utils-8.4.0.tgz#f7fe9c73f9fd82ab05ec3c04951049e904aab46a" + integrity sha512-EQh/YpfSKZSbfxetgN6RQmYuc2EpbpWF4f6WUAzm/JjXkCNAK429cMgofVr6Zy4U9ldj89zcODsnK6y6gnNIZQ== + dependencies: + "@0x/abi-gen-wrappers" "^5.3.2" + "@0x/assert" "^2.1.6" + "@0x/base-contract" "^5.4.0" + "@0x/contract-addresses" "^3.2.0" + "@0x/contract-artifacts" "^2.2.2" + "@0x/json-schemas" "^4.0.2" + "@0x/types" "^2.4.3" + "@0x/typescript-typings" "^4.3.0" + "@0x/utils" "^4.5.2" + "@0x/web3-wrapper" "^6.0.13" + "@types/node" "*" + bn.js "^4.11.8" + ethereum-types "^2.1.6" + ethereumjs-abi "0.6.5" + ethereumjs-util "^5.1.1" + ethers "~4.0.4" + lodash "^4.17.11" + "@0x/subproviders@^4.1.1": version "4.1.2" resolved "https://registry.yarnpkg.com/@0x/subproviders/-/subproviders-4.1.2.tgz#ab7bb0f482b11ccb4615fb5dd8ca85199cd0ae23" @@ -765,6 +912,34 @@ optionalDependencies: "@ledgerhq/hw-transport-node-hid" "^4.3.0" +"@0x/subproviders@^5.0.4": + version "5.0.4" + resolved "https://registry.npmjs.org/@0x/subproviders/-/subproviders-5.0.4.tgz#e4b165634ef6a50c4bd41baacf0dbd2a9390c2f8" + integrity sha512-1LiGcOXkP5eUOl/0JRqkrqYtCvIL4NJj1GbbLIRq4TvkfqrRbF7zJM2SaayxPo3Z48zVsqk0ZE5+RrNAdK/Rrg== + dependencies: + "@0x/assert" "^2.1.6" + "@0x/types" "^2.4.3" + "@0x/typescript-typings" "^4.3.0" + "@0x/utils" "^4.5.2" + "@0x/web3-wrapper" "^6.0.13" + "@ledgerhq/hw-app-eth" "^4.3.0" + "@ledgerhq/hw-transport-u2f" "4.24.0" + "@types/hdkey" "^0.7.0" + "@types/web3-provider-engine" "^14.0.0" + bip39 "^2.5.0" + bn.js "^4.11.8" + ethereum-types "^2.1.6" + ethereumjs-tx "^1.3.5" + ethereumjs-util "^5.1.1" + ganache-core "^2.6.0" + hdkey "^0.7.1" + json-rpc-error "2.0.0" + lodash "^4.17.11" + semaphore-async-await "^1.5.1" + web3-provider-engine "14.0.6" + optionalDependencies: + "@ledgerhq/hw-transport-node-hid" "^4.3.0" + "@0x/ts-doc-gen@^0.0.22": version "0.0.22" resolved "https://registry.yarnpkg.com/@0x/ts-doc-gen/-/ts-doc-gen-0.0.22.tgz#c9c215899695dcd4320a1711291be40050ddbc0e" @@ -778,6 +953,45 @@ typedoc-plugin-markdown "^2.1.0" yargs "^10.0.3" +"@0x/types@^2.4.0", "@0x/types@^2.4.1", "@0x/types@^2.4.3": + version "2.4.3" + resolved "https://registry.npmjs.org/@0x/types/-/types-2.4.3.tgz#ea014889789e9013fdf48ce97b79f2c016e10fb3" + integrity sha512-3z4ca9fb9pyTu9lJhTSll5EuEthkA3tLAayyZixCoCnwi4ok6PJ83PnMMsSxlRY2iXr7QGbrQr6nU64YWk2WjA== + dependencies: + "@types/node" "*" + bignumber.js "~8.0.2" + ethereum-types "^2.1.6" + +"@0x/typescript-typings@^4.2.2", "@0x/typescript-typings@^4.2.3", "@0x/typescript-typings@^4.2.4", "@0x/typescript-typings@^4.3.0": + version "4.3.0" + resolved "https://registry.npmjs.org/@0x/typescript-typings/-/typescript-typings-4.3.0.tgz#4813a996ac5101841d1c22f4aa1738ab56168857" + integrity sha512-6IH2JyKyl33+40tJ5rEhaMPTS2mVuRvoNmoXlCd/F0GPYSsDHMGObIXOkx+Qsw5SyCmqNs/3CTLeeCCqiSUdaw== + dependencies: + "@types/bn.js" "^4.11.0" + "@types/react" "*" + bignumber.js "~8.0.2" + ethereum-types "^2.1.6" + popper.js "1.14.3" + +"@0x/utils@^4.3.3", "@0x/utils@^4.4.0", "@0x/utils@^4.4.1", "@0x/utils@^4.4.2", "@0x/utils@^4.5.2": + version "4.5.2" + resolved "https://registry.npmjs.org/@0x/utils/-/utils-4.5.2.tgz#6cc89f2d0dda341e0fb4e76049a35abfb67a4ac5" + integrity sha512-NWfNcvyiOhouk662AWxX0ZVe4ednBZJS9WZT/by3DBCY/WvN7WHMpEy9M5rBCxO+JJndLYeB5eBztDp7W+Ytkw== + dependencies: + "@0x/types" "^2.4.3" + "@0x/typescript-typings" "^4.3.0" + "@types/node" "*" + abortcontroller-polyfill "^1.1.9" + bignumber.js "~8.0.2" + chalk "^2.3.0" + detect-node "2.0.3" + ethereum-types "^2.1.6" + ethereumjs-util "^5.1.1" + ethers "~4.0.4" + isomorphic-fetch "2.2.1" + js-sha3 "^0.7.0" + lodash "^4.17.11" + "@0x/web3-providers-fork@0.0.7": version "0.0.7" resolved "https://registry.yarnpkg.com/@0x/web3-providers-fork/-/web3-providers-fork-0.0.7.tgz#9cf40ebb6a2aa230283c5accb195d92594bb0aa7" @@ -794,6 +1008,20 @@ websocket "^1.0.28" xhr2-cookies "1.1.0" +"@0x/web3-wrapper@^6.0.13", "@0x/web3-wrapper@^6.0.7", "@0x/web3-wrapper@^6.0.8": + version "6.0.13" + resolved "https://registry.npmjs.org/@0x/web3-wrapper/-/web3-wrapper-6.0.13.tgz#2e666221bd44ceebe02762028214d4aa41ad7247" + integrity sha512-LQjKBCCNdkJuhcJld+/sy+G0+sJu5qp9VDNNwJGLDxWIJpgoshhUpBPi7vUnZ79UY4SYuNcC4yM9yI61cs7ZiA== + dependencies: + "@0x/assert" "^2.1.6" + "@0x/json-schemas" "^4.0.2" + "@0x/typescript-typings" "^4.3.0" + "@0x/utils" "^4.5.2" + ethereum-types "^2.1.6" + ethereumjs-util "^5.1.1" + ethers "~4.0.4" + lodash "^4.17.11" + "@0xproject/npm-cli-login@^0.0.11": version "0.0.11" resolved "https://registry.yarnpkg.com/@0xproject/npm-cli-login/-/npm-cli-login-0.0.11.tgz#3f1ec06112ce62aad300ff0575358f68aeecde2e" @@ -6634,6 +6862,14 @@ ethereum-common@^0.0.18: version "0.0.18" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" +ethereum-types@^2.1.3, ethereum-types@^2.1.4, ethereum-types@^2.1.6: + version "2.1.6" + resolved "https://registry.npmjs.org/ethereum-types/-/ethereum-types-2.1.6.tgz#57d9d515fad86ab987c0f6962c4203be37da8579" + integrity sha512-xaN5TxLvkdFCGjGfUQ5wV00GHzDHStozP1j+K/YdmUeQXVGiD15cogYPhBVWG3pQJM/aBjtYrpMrjywvKkNC4A== + dependencies: + "@types/node" "*" + bignumber.js "~8.0.2" + ethereumjs-abi@0.6.5: version "0.6.5" resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241" From 53df2130ea734fe49e34d24a25d71aa662e4b72b Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Tue, 8 Oct 2019 09:27:53 +0900 Subject: [PATCH 37/87] `@0x/contracts-asset-proxy`: Remove `only` modifier on uniswap tests. --- contracts/asset-proxy/test/uniswap_bridge.ts | 2 +- packages/sol-compiler/src/cli.ts | 1 + packages/sol-compiler/src/compiler.ts | 14 +++++++++++-- packages/sol-compiler/src/utils/compiler.ts | 22 ++++++++++++++++---- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/contracts/asset-proxy/test/uniswap_bridge.ts b/contracts/asset-proxy/test/uniswap_bridge.ts index 92e70d5ca1..48c6d2883b 100644 --- a/contracts/asset-proxy/test/uniswap_bridge.ts +++ b/contracts/asset-proxy/test/uniswap_bridge.ts @@ -29,7 +29,7 @@ import { TestUniswapBridgeWethWithdrawEventArgs as WethWithdrawArgs, } from '../src'; -blockchainTests.resets.only('UniswapBridge unit tests', env => { +blockchainTests.resets('UniswapBridge unit tests', env => { const txHelper = new TransactionHelper(env.web3Wrapper, artifacts); let testContract: TestUniswapBridgeContract; let wethTokenAddress: string; diff --git a/packages/sol-compiler/src/cli.ts b/packages/sol-compiler/src/cli.ts index aa71246542..e53a680af2 100644 --- a/packages/sol-compiler/src/cli.ts +++ b/packages/sol-compiler/src/cli.ts @@ -40,6 +40,7 @@ const SEPARATOR = ','; contractsDir: argv.contractsDir, artifactsDir: argv.artifactsDir, contracts, + isOfflineMode: process.env.SOLC_OFFLINE ? true : undefined, }; const compiler = new Compiler(opts); if (argv.watch) { diff --git a/packages/sol-compiler/src/compiler.ts b/packages/sol-compiler/src/compiler.ts index 919f9909bc..1c16a72829 100644 --- a/packages/sol-compiler/src/compiler.ts +++ b/packages/sol-compiler/src/compiler.ts @@ -28,7 +28,10 @@ import { createDirIfDoesNotExistAsync, getContractArtifactIfExistsAsync, getDependencyNameToPackagePath, + getSolcJSAsync, + getSolcJSFromPath, getSolcJSReleasesAsync, + getSolcJSVersionFromPath, getSourcesWithDependencies, getSourceTreeHash, makeContractPathsRelative, @@ -106,7 +109,10 @@ export class Compiler { : {}; assert.doesConformToSchema('compiler.json', config, compilerOptionsSchema); this._contractsDir = path.resolve(passedOpts.contractsDir || config.contractsDir || DEFAULT_CONTRACTS_DIR); - this._solcVersionIfExists = passedOpts.solcVersion || config.solcVersion; + this._solcVersionIfExists = + process.env.SOLCJS_PATH !== undefined + ? getSolcJSVersionFromPath(process.env.SOLCJS_PATH) + : passedOpts.solcVersion || config.solcVersion; this._compilerSettings = { ...DEFAULT_COMPILER_SETTINGS, ...config.compilerSettings, @@ -292,7 +298,11 @@ export class Compiler { compilerOutput = await compileDockerAsync(solcVersion, input.standardInput); } else { fullSolcVersion = solcJSReleases[solcVersion]; - compilerOutput = await compileSolcJSAsync(solcVersion, input.standardInput, this._isOfflineMode); + const solcInstance = + process.env.SOLCJS_PATH !== undefined + ? getSolcJSFromPath(process.env.SOLCJS_PATH) + : await getSolcJSAsync(solcVersion, this._isOfflineMode); + compilerOutput = await compileSolcJSAsync(solcInstance, input.standardInput); } if (compilerOutput.errors !== undefined) { printCompilationErrorsAndWarnings(compilerOutput.errors); diff --git a/packages/sol-compiler/src/utils/compiler.ts b/packages/sol-compiler/src/utils/compiler.ts index 085e1a55f2..c5d96ca0cc 100644 --- a/packages/sol-compiler/src/utils/compiler.ts +++ b/packages/sol-compiler/src/utils/compiler.ts @@ -136,16 +136,14 @@ export async function getSolcJSReleasesAsync(isOfflineMode: boolean): Promise { - const solcInstance = await getSolcJSAsync(solcVersion, isOfflineMode); const standardInputStr = JSON.stringify(standardInput); const standardOutputStr = solcInstance.compileStandardWrapper(standardInputStr); const compiled: solc.StandardOutput = JSON.parse(standardOutputStr); @@ -364,6 +362,22 @@ export async function getSolcJSAsync(solcVersion: string, isOfflineMode: boolean return solcInstance; } +/** + * Gets the solidity compiler instance from a module path. + * @param path The path to the solc module. + */ +export function getSolcJSFromPath(modulePath: string): solc.SolcInstance { + return require(modulePath); +} + +/** + * Gets the solidity compiler version from a module path. + * @param path The path to the solc module. + */ +export function getSolcJSVersionFromPath(modulePath: string): string { + return require(modulePath).version(); +} + /** * Solidity compiler emits the bytecode without a 0x prefix for a hex. This function fixes it if bytecode is present. * @param compiledContract The standard JSON output section for a contract. Geth modified in place. From b3c7ccec5769ed684f37619cd8bc25800466d45d Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 8 Oct 2019 10:32:39 +0900 Subject: [PATCH 38/87] Changed `nextPoolId` to `lastPoolId` --- .../contracts/src/immutable/MixinStorage.sol | 4 ++-- .../contracts/src/interfaces/IStorage.sol | 2 +- .../src/staking_pools/MixinStakingPool.sol | 20 ++++--------------- .../test/TestStorageLayoutAndConstants.sol | 4 ++-- contracts/staking/test/actors/maker_actor.ts | 4 ++-- .../test/actors/pool_operator_actor.ts | 5 ++--- contracts/staking/test/pools_test.ts | 20 ++++++++++--------- contracts/staking/test/stake_test.ts | 6 +++++- 8 files changed, 29 insertions(+), 36 deletions(-) diff --git a/contracts/staking/contracts/src/immutable/MixinStorage.sol b/contracts/staking/contracts/src/immutable/MixinStorage.sol index f109726529..1b39c61f3f 100644 --- a/contracts/staking/contracts/src/immutable/MixinStorage.sol +++ b/contracts/staking/contracts/src/immutable/MixinStorage.sol @@ -68,8 +68,8 @@ contract MixinStorage is // mapping from Owner to Amount of Withdrawable Stake mapping (address => uint256) internal _withdrawableStakeByOwner; - // tracking Pool Id - bytes32 public nextPoolId = bytes32(uint256(1)); + // tracking Pool Id, a unique identifier for each staking pool. + bytes32 public lastPoolId; // mapping from Maker Address to Pool Id of maker mapping (address => bytes32) public poolIdByMaker; diff --git a/contracts/staking/contracts/src/interfaces/IStorage.sol b/contracts/staking/contracts/src/interfaces/IStorage.sol index 1a9a6fd478..a1d9d6ecee 100644 --- a/contracts/staking/contracts/src/interfaces/IStorage.sol +++ b/contracts/staking/contracts/src/interfaces/IStorage.sol @@ -40,7 +40,7 @@ interface IStorage { view returns (address); - function nextPoolId() + function lastPoolId() external view returns (bytes32); diff --git a/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol b/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol index f787dc09a9..2f239b839e 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol @@ -53,9 +53,8 @@ contract MixinStakingPool is // note that an operator must be payable address payable operator = msg.sender; - // assign pool id and generate next id - poolId = nextPoolId; - nextPoolId = _computeNextStakingPoolId(poolId); + // compute unique id for this pool + poolId = lastPoolId = bytes32(uint256(lastPoolId).safeAdd(1)); // sanity check on operator share _assertNewOperatorShare( @@ -80,7 +79,7 @@ contract MixinStakingPool is emit StakingPoolCreated(poolId, operator, operatorShare); if (addOperatorAsMaker) { - setMakerStakingPool(poolId); + joinStakingPoolAsMaker(poolId); } return poolId; @@ -112,7 +111,7 @@ contract MixinStakingPool is /// @dev Allows caller to join a staking pool as a maker. /// @param poolId Unique id of pool. - function setMakerStakingPool(bytes32 poolId) + function joinStakingPoolAsMaker(bytes32 poolId) public { address maker = msg.sender; @@ -133,17 +132,6 @@ contract MixinStakingPool is return _poolById[poolId]; } - /// @dev Computes the unique id that comes after the input pool id. - /// @param poolId Unique id of pool. - /// @return Next pool id after input pool. - function _computeNextStakingPoolId(bytes32 poolId) - internal - pure - returns (bytes32) - { - return bytes32(uint256(poolId).safeAdd(1)); - } - /// @dev Reverts iff a staking pool does not exist. /// @param poolId Unique id of pool. function _assertStakingPoolExists(bytes32 poolId) diff --git a/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol b/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol index 67bf4088a5..6979341eb3 100644 --- a/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol +++ b/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol @@ -175,8 +175,8 @@ contract TestStorageLayoutAndConstants is slot := add(slot, 0x1) assertSlotAndOffset( - nextPoolId_slot, - nextPoolId_offset, + lastPoolId_slot, + lastPoolId_offset, slot, offset ) diff --git a/contracts/staking/test/actors/maker_actor.ts b/contracts/staking/test/actors/maker_actor.ts index da076b63be..144aeee11b 100644 --- a/contracts/staking/test/actors/maker_actor.ts +++ b/contracts/staking/test/actors/maker_actor.ts @@ -5,9 +5,9 @@ import * as _ from 'lodash'; import { PoolOperatorActor } from './pool_operator_actor'; export class MakerActor extends PoolOperatorActor { - public async setMakerStakingPoolAsync(poolId: string, revertError?: RevertError): Promise { + public async joinStakingPoolAsMakerAsync(poolId: string, revertError?: RevertError): Promise { // add maker - const txReceiptPromise = this._stakingApiWrapper.stakingContract.setMakerStakingPool.awaitTransactionSuccessAsync( + const txReceiptPromise = this._stakingApiWrapper.stakingContract.joinStakingPoolAsMaker.awaitTransactionSuccessAsync( poolId, { from: this.getOwner() }, ); diff --git a/contracts/staking/test/actors/pool_operator_actor.ts b/contracts/staking/test/actors/pool_operator_actor.ts index 5116ea25b1..e7fd5f7e78 100644 --- a/contracts/staking/test/actors/pool_operator_actor.ts +++ b/contracts/staking/test/actors/pool_operator_actor.ts @@ -10,8 +10,6 @@ export class PoolOperatorActor extends BaseActor { addOperatorAsMaker: boolean, revertError?: RevertError, ): Promise { - // query next pool id - const nextPoolId = await this._stakingApiWrapper.stakingContract.nextPoolId.callAsync(); // create pool const poolIdPromise = this._stakingApiWrapper.utils.createStakingPoolAsync( this._owner, @@ -24,7 +22,8 @@ export class PoolOperatorActor extends BaseActor { } const poolId = await poolIdPromise; // validate pool id - expect(poolId, 'pool id').to.be.bignumber.equal(nextPoolId); + const lastPoolId = await this._stakingApiWrapper.stakingContract.lastPoolId.callAsync(); + expect(poolId, 'pool id').to.be.bignumber.equal(lastPoolId); if (addOperatorAsMaker) { // check the pool id of the operator diff --git a/contracts/staking/test/pools_test.ts b/contracts/staking/test/pools_test.ts index eddab9095e..7dc69c08c8 100644 --- a/contracts/staking/test/pools_test.ts +++ b/contracts/staking/test/pools_test.ts @@ -40,8 +40,8 @@ blockchainTests('Staking Pool Management', env => { const poolId = await poolOperator.createStakingPoolAsync(operatorShare, false); expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); // check that the next pool id was incremented - const nextPoolId = await stakingApiWrapper.stakingContract.nextPoolId.callAsync(); - expect(nextPoolId).to.be.equal(stakingConstants.SECOND_POOL_ID); + const lastPoolId = await stakingApiWrapper.stakingContract.lastPoolId.callAsync(); + expect(lastPoolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); }); it('Should successfully create several staking pools, as long as the operator is only a maker in one', async () => { // test parameters @@ -77,8 +77,8 @@ blockchainTests('Staking Pool Management', env => { const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true); expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); // check that the next pool id was incremented - const nextPoolId = await stakingApiWrapper.stakingContract.nextPoolId.callAsync(); - expect(nextPoolId).to.be.equal(stakingConstants.SECOND_POOL_ID); + const lastPoolId = await stakingApiWrapper.stakingContract.lastPoolId.callAsync(); + expect(lastPoolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); }); it('Should throw if operatorShare is > PPM_DENOMINATOR', async () => { // test parameters @@ -107,7 +107,7 @@ blockchainTests('Staking Pool Management', env => { const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true); expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); // maker joins pool - await maker.setMakerStakingPoolAsync(poolId); + await maker.joinStakingPoolAsMakerAsync(poolId); }); it('Maker should successfully remove themselves from a pool', async () => { // test parameters @@ -120,9 +120,9 @@ blockchainTests('Staking Pool Management', env => { const poolId = await poolOperator.createStakingPoolAsync(operatorShare, true); expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); // maker joins pool - await maker.setMakerStakingPoolAsync(poolId); + await maker.joinStakingPoolAsMakerAsync(poolId); // maker removes themselves from pool - await maker.setMakerStakingPoolAsync(stakingConstants.NIL_POOL_ID); + await maker.joinStakingPoolAsMakerAsync(stakingConstants.NIL_POOL_ID); }); it('Should successfully add/remove multiple makers to the same pool', async () => { // test parameters @@ -135,9 +135,11 @@ blockchainTests('Staking Pool Management', env => { const poolId = await poolOperator.createStakingPoolAsync(operatorShare, false); expect(poolId).to.be.equal(stakingConstants.INITIAL_POOL_ID); // add makers to pool - await Promise.all(makers.map(async maker => maker.setMakerStakingPoolAsync(poolId))); + await Promise.all(makers.map(async maker => maker.joinStakingPoolAsMakerAsync(poolId))); // remove makers to pool - await Promise.all(makers.map(async maker => maker.setMakerStakingPoolAsync(stakingConstants.NIL_POOL_ID))); + await Promise.all( + makers.map(async maker => maker.joinStakingPoolAsMakerAsync(stakingConstants.NIL_POOL_ID)), + ); }); it('Operator should successfully decrease their share of rewards', async () => { // test parameters diff --git a/contracts/staking/test/stake_test.ts b/contracts/staking/test/stake_test.ts index a8b0ad975d..63aa1d351e 100644 --- a/contracts/staking/test/stake_test.ts +++ b/contracts/staking/test/stake_test.ts @@ -44,7 +44,11 @@ blockchainTests.resets('Stake Statuses', env => { await stakingApiWrapper.utils.createStakingPoolAsync(poolOperator, 4, false), await stakingApiWrapper.utils.createStakingPoolAsync(poolOperator, 5, false), ]); - unusedPoolId = await stakingApiWrapper.stakingContract.nextPoolId.callAsync(); + const lastPoolId = await stakingApiWrapper.stakingContract.lastPoolId.callAsync(); + unusedPoolId = `0x${new BigNumber(lastPoolId) + .plus(1) + .toString(16) + .padStart(64, '0')}`; }); describe('Stake', () => { it('should successfully stake zero ZRX', async () => { From d1b0384aef41adf647f63e3346baa71d57e263fa Mon Sep 17 00:00:00 2001 From: Alex Towle Date: Tue, 8 Oct 2019 19:22:27 -0700 Subject: [PATCH 39/87] `@0x:contracts-utils` Added an event for ownership transfers --- contracts/utils/contracts/src/Ownable.sol | 1 + contracts/utils/contracts/src/interfaces/IOwnable.sol | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/contracts/utils/contracts/src/Ownable.sol b/contracts/utils/contracts/src/Ownable.sol index c03fac3b24..f87ecdc6bf 100644 --- a/contracts/utils/contracts/src/Ownable.sol +++ b/contracts/utils/contracts/src/Ownable.sol @@ -29,6 +29,7 @@ contract Ownable is LibRichErrors.rrevert(LibOwnableRichErrors.TransferOwnerToZeroError()); } else { owner = newOwner; + emit OwnershipTransferred(newOwner); } } diff --git a/contracts/utils/contracts/src/interfaces/IOwnable.sol b/contracts/utils/contracts/src/interfaces/IOwnable.sol index d4b1c5c6b6..732dfccacf 100644 --- a/contracts/utils/contracts/src/interfaces/IOwnable.sol +++ b/contracts/utils/contracts/src/interfaces/IOwnable.sol @@ -3,6 +3,12 @@ pragma solidity ^0.5.9; contract IOwnable { + /// @dev Emitted by Ownable when ownership is transferred. + /// @param newOwner The new owner of the contract. + event OwnershipTransferred(address newOwner); + + /// @dev Transfers ownership of the contract to a new address. + /// @param newOwner The address that will become the owner. function transferOwnership(address newOwner) public; } From dc0a78434de87aa11d7d7d407abd842014c9060f Mon Sep 17 00:00:00 2001 From: Alex Towle Date: Tue, 8 Oct 2019 19:23:23 -0700 Subject: [PATCH 40/87] `@0x:contracts-utils` Updated files --- contracts/utils/CHANGELOG.json | 4 ++ contracts/utils/contracts/src/Ownable.sol | 18 ++++++++ .../contracts/src/interfaces/IOwnable.sol | 18 ++++++++ contracts/utils/test/ownable.ts | 41 ++++++++++--------- 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/contracts/utils/CHANGELOG.json b/contracts/utils/CHANGELOG.json index ecd5d1401a..5820e68076 100644 --- a/contracts/utils/CHANGELOG.json +++ b/contracts/utils/CHANGELOG.json @@ -61,6 +61,10 @@ { "note": "Introduce automatic normalization and some zero-value shortcuts in `LibFractions`.", "pr": 2155 + }, + { + "note": "Emit an event in `transferOwnership`", + "pr": 2253 } ], "timestamp": 1570135330 diff --git a/contracts/utils/contracts/src/Ownable.sol b/contracts/utils/contracts/src/Ownable.sol index f87ecdc6bf..77ac7e0d26 100644 --- a/contracts/utils/contracts/src/Ownable.sol +++ b/contracts/utils/contracts/src/Ownable.sol @@ -1,3 +1,21 @@ +/* + + Copyright 2019 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + pragma solidity ^0.5.9; import "./interfaces/IOwnable.sol"; diff --git a/contracts/utils/contracts/src/interfaces/IOwnable.sol b/contracts/utils/contracts/src/interfaces/IOwnable.sol index 732dfccacf..cb72cf8ee5 100644 --- a/contracts/utils/contracts/src/interfaces/IOwnable.sol +++ b/contracts/utils/contracts/src/interfaces/IOwnable.sol @@ -1,3 +1,21 @@ +/* + + Copyright 2019 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + pragma solidity ^0.5.9; diff --git a/contracts/utils/test/ownable.ts b/contracts/utils/test/ownable.ts index 4b67312718..7d95cec505 100644 --- a/contracts/utils/test/ownable.ts +++ b/contracts/utils/test/ownable.ts @@ -1,32 +1,23 @@ -import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils'; -import { BlockchainLifecycle } from '@0x/dev-utils'; +import { blockchainTests, constants, expect, filterLogsToArguments } from '@0x/contracts-test-utils'; import { OwnableRevertErrors } from '@0x/utils'; -import * as chai from 'chai'; -import * as _ from 'lodash'; -import { artifacts, TestOwnableContract } from '../src'; +import { artifacts, IOwnableEvents, IOwnableOwnershipTransferredEventArgs, TestOwnableContract } from '../src'; -chaiSetup.configure(); -const expect = chai.expect; -const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); - -describe('Ownable', () => { +blockchainTests.resets('Ownable', env => { let ownable: TestOwnableContract; let owner: string; let nonOwner: string; before(async () => { - const accounts = await web3Wrapper.getAvailableAddressesAsync(); + const accounts = await env.getAccountAddressesAsync(); owner = await accounts[0]; nonOwner = await accounts[1]; - await blockchainLifecycle.startAsync(); - // Deploy Ownable from the owner address - txDefaults.from = owner; - ownable = await TestOwnableContract.deployFrom0xArtifactAsync(artifacts.TestOwnable, provider, txDefaults, {}); - }); - - after(async () => { - await blockchainLifecycle.revertAsync(); + ownable = await TestOwnableContract.deployFrom0xArtifactAsync( + artifacts.TestOwnable, + env.provider, + { ...env.txDefaults, from: owner }, + artifacts, + ); }); describe('onlyOwner', () => { @@ -49,7 +40,17 @@ describe('Ownable', () => { }); it('should transfer ownership if the specified new owner is not the zero address', async () => { - expect(ownable.transferOwnership.sendTransactionAsync(nonOwner, { from: owner })).to.be.fulfilled(''); + const receipt = await ownable.transferOwnership.awaitTransactionSuccessAsync(nonOwner, { from: owner }); + + // Ensure that the correct logs were emitted. + expect(receipt.logs.length).to.be.eq(1); + const args = filterLogsToArguments( + receipt.logs, + IOwnableEvents.OwnershipTransferred, + ); + expect(args).to.be.deep.eq([{ newOwner: nonOwner }]); + + // Ensure that the owner was actually updated const updatedOwner = await ownable.owner.callAsync(); expect(updatedOwner).to.be.eq(nonOwner); }); From f8ac986a0f5f7a540df6aad5cc6a3b974e6cdbe8 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sat, 5 Oct 2019 01:19:45 -0700 Subject: [PATCH 41/87] Remove unused struct field --- contracts/staking/contracts/src/interfaces/IStructs.sol | 2 -- contracts/staking/contracts/src/stake/MixinStakeStorage.sol | 1 - contracts/staking/contracts/test/TestDelegatorRewards.sol | 3 --- contracts/staking/test/unit_tests/mixin_stake_storage_test.ts | 4 ---- contracts/staking/test/utils/types.ts | 1 - 5 files changed, 11 deletions(-) diff --git a/contracts/staking/contracts/src/interfaces/IStructs.sol b/contracts/staking/contracts/src/interfaces/IStructs.sol index 61ebae8ada..7f0dfcc069 100644 --- a/contracts/staking/contracts/src/interfaces/IStructs.sol +++ b/contracts/staking/contracts/src/interfaces/IStructs.sol @@ -53,12 +53,10 @@ interface IStructs { /// Note that these balances may be stale if the current epoch /// is greater than `currentEpoch`. /// Always load this struct using _loadSyncedBalance or _loadUnsyncedBalance. - /// @param isInitialized /// @param currentEpoch the current epoch /// @param currentEpochBalance balance in the current epoch. /// @param nextEpochBalance balance in `currentEpoch+1`. struct StoredBalance { - bool isInitialized; uint32 currentEpoch; uint96 currentEpochBalance; uint96 nextEpochBalance; diff --git a/contracts/staking/contracts/src/stake/MixinStakeStorage.sol b/contracts/staking/contracts/src/stake/MixinStakeStorage.sol index 6588a0cc89..b145e09de0 100644 --- a/contracts/staking/contracts/src/stake/MixinStakeStorage.sol +++ b/contracts/staking/contracts/src/stake/MixinStakeStorage.sol @@ -177,7 +177,6 @@ contract MixinStakeStorage is { // note - this compresses into a single `sstore` when optimizations are enabled, // since the StakeBalance struct occupies a single word of storage. - balancePtr.isInitialized = true; balancePtr.currentEpoch = balance.currentEpoch; balancePtr.nextEpochBalance = balance.nextEpochBalance; balancePtr.currentEpochBalance = balance.currentEpochBalance; diff --git a/contracts/staking/contracts/test/TestDelegatorRewards.sol b/contracts/staking/contracts/test/TestDelegatorRewards.sol index 7f36151c5c..0766579a9d 100644 --- a/contracts/staking/contracts/test/TestDelegatorRewards.sol +++ b/contracts/staking/contracts/test/TestDelegatorRewards.sol @@ -117,7 +117,6 @@ contract TestDelegatorRewards is delegator ); IStructs.StoredBalance storage _stake = _delegatedStakeToPoolByOwner[delegator][poolId]; - _stake.isInitialized = true; _stake.currentEpochBalance += uint96(stake); _stake.nextEpochBalance += uint96(stake); _stake.currentEpoch = uint32(currentEpoch); @@ -146,7 +145,6 @@ contract TestDelegatorRewards is if (_stake.currentEpoch < currentEpoch) { _stake.currentEpochBalance = _stake.nextEpochBalance; } - _stake.isInitialized = true; _stake.nextEpochBalance += uint96(stake); _stake.currentEpoch = uint32(currentEpoch); } @@ -170,7 +168,6 @@ contract TestDelegatorRewards is if (_stake.currentEpoch < currentEpoch) { _stake.currentEpochBalance = _stake.nextEpochBalance; } - _stake.isInitialized = true; _stake.nextEpochBalance -= uint96(stake); _stake.currentEpoch = uint32(currentEpoch); } diff --git a/contracts/staking/test/unit_tests/mixin_stake_storage_test.ts b/contracts/staking/test/unit_tests/mixin_stake_storage_test.ts index d4487c4366..c7115c4474 100644 --- a/contracts/staking/test/unit_tests/mixin_stake_storage_test.ts +++ b/contracts/staking/test/unit_tests/mixin_stake_storage_test.ts @@ -26,19 +26,16 @@ blockchainTests.resets('MixinStakeStorage unit tests', env => { ); await testContract.setCurrentEpoch.awaitTransactionSuccessAsync(CURRENT_EPOCH); defaultUninitializedBalance = { - isInitialized: false, currentEpoch: constants.INITIAL_EPOCH, currentEpochBalance: new BigNumber(0), nextEpochBalance: new BigNumber(0), }; defaultSyncedBalance = { - isInitialized: true, currentEpoch: CURRENT_EPOCH, currentEpochBalance: new BigNumber(16), nextEpochBalance: new BigNumber(16), }; defaultUnsyncedBalance = { - isInitialized: true, currentEpoch: CURRENT_EPOCH.minus(1), currentEpochBalance: new BigNumber(10), nextEpochBalance: new BigNumber(16), @@ -48,7 +45,6 @@ blockchainTests.resets('MixinStakeStorage unit tests', env => { async function getTestBalancesAsync(index: Numberish): Promise { const storedBalance: Partial = {}; [ - storedBalance.isInitialized, storedBalance.currentEpoch, storedBalance.currentEpochBalance, storedBalance.nextEpochBalance, diff --git a/contracts/staking/test/utils/types.ts b/contracts/staking/test/utils/types.ts index 6134b5072f..83a8fffde1 100644 --- a/contracts/staking/test/utils/types.ts +++ b/contracts/staking/test/utils/types.ts @@ -59,7 +59,6 @@ export interface EndOfEpochInfo { } export interface StoredBalance { - isInitialized: boolean; currentEpoch: number | BigNumber; currentEpochBalance: BigNumber; nextEpochBalance: BigNumber; From 7b379f39334a7e7f179d4451e22483a474ef328e Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sat, 5 Oct 2019 15:50:31 -0700 Subject: [PATCH 42/87] Simplify withdrawal flow and storage layout --- .../contracts/src/immutable/MixinStorage.sol | 15 +-- .../contracts/src/stake/MixinStake.sol | 109 +++++++----------- .../src/stake/MixinStakeBalances.sol | 51 +------- .../src/staking_pools/MixinStakingPool.sol | 1 - .../test/TestStorageLayoutAndConstants.sol | 28 +---- 5 files changed, 50 insertions(+), 154 deletions(-) diff --git a/contracts/staking/contracts/src/immutable/MixinStorage.sol b/contracts/staking/contracts/src/immutable/MixinStorage.sol index 1b39c61f3f..45dae75d60 100644 --- a/contracts/staking/contracts/src/immutable/MixinStorage.sol +++ b/contracts/staking/contracts/src/immutable/MixinStorage.sol @@ -45,17 +45,9 @@ contract MixinStorage is // staking system. mapping (uint8 => IStructs.StoredBalance) public globalStakeByStatus; - // mapping from Owner to Amount of Active Stake + // mapping from StakeStatus to address of staker to stored balance // (access using _loadSyncedBalance or _loadUnsyncedBalance) - mapping (address => IStructs.StoredBalance) internal _activeStakeByOwner; - - // Mapping from Owner to Amount of Inactive Stake - // (access using _loadSyncedBalance or _loadUnsyncedBalance) - mapping (address => IStructs.StoredBalance) internal _inactiveStakeByOwner; - - // Mapping from Owner to Amount Delegated - // (access using _loadSyncedBalance or _loadUnsyncedBalance) - mapping (address => IStructs.StoredBalance) internal _delegatedStakeByOwner; + mapping (uint8 => mapping (address => IStructs.StoredBalance)) internal _ownerStakeByStatus; // Mapping from Owner to Pool Id to Amount Delegated // (access using _loadSyncedBalance or _loadUnsyncedBalance) @@ -65,9 +57,6 @@ contract MixinStorage is // (access using _loadSyncedBalance or _loadUnsyncedBalance) mapping (bytes32 => IStructs.StoredBalance) internal _delegatedStakeByPoolId; - // mapping from Owner to Amount of Withdrawable Stake - mapping (address => uint256) internal _withdrawableStakeByOwner; - // tracking Pool Id, a unique identifier for each staking pool. bytes32 public lastPoolId; diff --git a/contracts/staking/contracts/src/stake/MixinStake.sol b/contracts/staking/contracts/src/stake/MixinStake.sol index 62ac869a7c..c44cdfd143 100644 --- a/contracts/staking/contracts/src/stake/MixinStake.sol +++ b/contracts/staking/contracts/src/stake/MixinStake.sol @@ -41,10 +41,16 @@ contract MixinStake is getZrxVault().depositFrom(staker, amount); // mint stake - _increaseCurrentAndNextBalance(_activeStakeByOwner[staker], amount); + _increaseCurrentAndNextBalance( + _ownerStakeByStatus[uint8(IStructs.StakeStatus.ACTIVE)][staker], + amount + ); // update global total of active stake - _increaseCurrentAndNextBalance(globalStakeByStatus[uint8(IStructs.StakeStatus.ACTIVE)], amount); + _increaseCurrentAndNextBalance( + globalStakeByStatus[uint8(IStructs.StakeStatus.ACTIVE)], + amount + ); // notify emit Stake( @@ -60,10 +66,17 @@ contract MixinStake is function unstake(uint256 amount) external { - address payable staker = msg.sender; + address staker = msg.sender; + + IStructs.StoredBalance memory inactiveBalance = + _loadSyncedBalance(_ownerStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)][staker]); + + // stake must be inactive in current and next epoch to be withdrawn + uint256 currentWithdrawableStake = LibSafeMath.min256( + inactiveBalance.currentEpochBalance, + inactiveBalance.nextEpochBalance + ); - // sanity check - uint256 currentWithdrawableStake = getWithdrawableStake(staker); if (amount > currentWithdrawableStake) { LibRichErrors.rrevert( LibStakingRichErrors.InsufficientBalanceError( @@ -74,14 +87,16 @@ contract MixinStake is } // burn inactive stake - _decreaseCurrentAndNextBalance(_inactiveStakeByOwner[staker], amount); + _decreaseCurrentAndNextBalance( + _ownerStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)][staker], + amount + ); // update global total of inactive stake - _decreaseCurrentAndNextBalance(globalStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)], amount); - - // update withdrawable field - _withdrawableStakeByOwner[staker] = - currentWithdrawableStake.safeSub(amount); + _decreaseCurrentAndNextBalance( + globalStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)], + amount + ); // withdraw equivalent amount of ZRX from vault getZrxVault().withdrawFrom(staker, amount); @@ -105,17 +120,6 @@ contract MixinStake is ) external { - // sanity check - do nothing if moving stake between the same status - if (from.status != IStructs.StakeStatus.DELEGATED - && from.status == to.status) - { - return; - } else if (from.status == IStructs.StakeStatus.DELEGATED - && from.poolId == to.poolId) - { - return; - } - address payable staker = msg.sender; // handle delegation; this must be done before moving stake as the @@ -136,17 +140,14 @@ contract MixinStake is ); } - // cache the current withdrawal amount, which may change if we're - // moving out of the inactive status. - uint256 withdrawableStake = - (from.status == IStructs.StakeStatus.INACTIVE) - ? getWithdrawableStake(staker) - : 0; - // execute move - IStructs.StoredBalance storage fromPtr = _getBalancePtrFromStatus(staker, from.status); - IStructs.StoredBalance storage toPtr = _getBalancePtrFromStatus(staker, to.status); - _moveStake(fromPtr, toPtr, amount); + IStructs.StoredBalance storage fromPtr = _ownerStakeByStatus[uint8(from.status)][staker]; + IStructs.StoredBalance storage toPtr = _ownerStakeByStatus[uint8(to.status)][staker]; + _moveStake( + fromPtr, + toPtr, + amount + ); // update global total of stake in the statuses being moved between _moveStake( @@ -155,12 +156,6 @@ contract MixinStake is amount ); - // update withdrawable field, if necessary - if (from.status == IStructs.StakeStatus.INACTIVE) { - _withdrawableStakeByOwner[staker] = - _computeWithdrawableStake(staker, withdrawableStake); - } - // notify emit MoveStake( staker, @@ -198,7 +193,10 @@ contract MixinStake is ); // Increment how much stake has been delegated to pool. - _increaseNextBalance(_delegatedStakeByPoolId[poolId], amount); + _increaseNextBalance( + _delegatedStakeByPoolId[poolId], + amount + ); } /// @dev Un-Delegates a owners stake from a staking pool. @@ -227,36 +225,9 @@ contract MixinStake is ); // decrement how much stake has been delegated to pool - _decreaseNextBalance(_delegatedStakeByPoolId[poolId], amount); - } - - /// @dev Returns a storage pointer to a user's stake in a given status. - /// @param staker Owner of stake to query. - /// @param status Status of user's stake to lookup. - /// @return storage A storage pointer to the corresponding stake stake - function _getBalancePtrFromStatus( - address staker, - IStructs.StakeStatus status - ) - private - view - returns (IStructs.StoredBalance storage) - { - // lookup status - if (status == IStructs.StakeStatus.ACTIVE) { - return _activeStakeByOwner[staker]; - } else if (status == IStructs.StakeStatus.INACTIVE) { - return _inactiveStakeByOwner[staker]; - } else if (status == IStructs.StakeStatus.DELEGATED) { - return _delegatedStakeByOwner[staker]; - } - - // invalid status - LibRichErrors.rrevert( - LibStakingRichErrors.InvalidStakeStatusError(status) + _decreaseNextBalance( + _delegatedStakeByPoolId[poolId], + amount ); - - // required to compile ~ we should never hit this. - revert("INVALID_STATE"); } } diff --git a/contracts/staking/contracts/src/stake/MixinStakeBalances.sol b/contracts/staking/contracts/src/stake/MixinStakeBalances.sol index 9d227c6741..619fbb1913 100644 --- a/contracts/staking/contracts/src/stake/MixinStakeBalances.sol +++ b/contracts/staking/contracts/src/stake/MixinStakeBalances.sol @@ -96,7 +96,8 @@ contract MixinStakeBalances is view returns (IStructs.StakeBalance memory balance) { - IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(_activeStakeByOwner[staker]); + IStructs.StoredBalance memory storedBalance = + _loadSyncedBalance(_ownerStakeByStatus[uint8(IStructs.StakeStatus.ACTIVE)][staker]); return IStructs.StakeBalance({ currentEpochBalance: storedBalance.currentEpochBalance, nextEpochBalance: storedBalance.nextEpochBalance @@ -111,7 +112,8 @@ contract MixinStakeBalances is view returns (IStructs.StakeBalance memory balance) { - IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(_inactiveStakeByOwner[staker]); + IStructs.StoredBalance memory storedBalance = + _loadSyncedBalance(_ownerStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)][staker]); return IStructs.StakeBalance({ currentEpochBalance: storedBalance.currentEpochBalance, nextEpochBalance: storedBalance.nextEpochBalance @@ -126,24 +128,14 @@ contract MixinStakeBalances is view returns (IStructs.StakeBalance memory balance) { - IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(_delegatedStakeByOwner[staker]); + IStructs.StoredBalance memory storedBalance = + _loadSyncedBalance(_ownerStakeByStatus[uint8(IStructs.StakeStatus.DELEGATED)][staker]); return IStructs.StakeBalance({ currentEpochBalance: storedBalance.currentEpochBalance, nextEpochBalance: storedBalance.nextEpochBalance }); } - /// @dev Returns the amount stake that can be withdrawn for a given staker. - /// @param staker of stake. - /// @return Withdrawable stake for staker. - function getWithdrawableStake(address staker) - public - view - returns (uint256) - { - return _computeWithdrawableStake(staker, _withdrawableStakeByOwner[staker]); - } - /// @dev Returns the stake delegated to a specific staking pool, by a given staker. /// @param staker of stake. /// @param poolId Unique Id of pool. @@ -175,35 +167,4 @@ contract MixinStakeBalances is nextEpochBalance: storedBalance.nextEpochBalance }); } - - /// @dev Returns the stake that can be withdrawn for a given staker. - /// @param staker to query. - /// @param lastStoredWithdrawableStake The amount of withdrawable stake - /// that was last stored. - /// @return Withdrawable stake for staker. - function _computeWithdrawableStake( - address staker, - uint256 lastStoredWithdrawableStake - ) - internal - view - returns (uint256) - { - // stake cannot be withdrawn if it has been reallocated for the `next` epoch; - // so the upper bound of withdrawable stake is always limited by the value of `next`. - IStructs.StoredBalance memory storedBalance = _loadUnsyncedBalance(_inactiveStakeByOwner[staker]); - if (storedBalance.currentEpoch == currentEpoch) { - return LibSafeMath.min256( - storedBalance.nextEpochBalance, - lastStoredWithdrawableStake - ); - } else if (uint256(storedBalance.currentEpoch).safeAdd(1) == currentEpoch) { - return LibSafeMath.min256( - storedBalance.nextEpochBalance, - storedBalance.currentEpochBalance - ); - } else { - return storedBalance.nextEpochBalance; - } - } } diff --git a/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol b/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol index 2f239b839e..64710750ef 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol @@ -137,7 +137,6 @@ contract MixinStakingPool is function _assertStakingPoolExists(bytes32 poolId) internal view - returns (bool) { if (_poolById[poolId].operator == NIL_ADDRESS) { // we use the pool's operator as a proxy for its existence diff --git a/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol b/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol index 6979341eb3..e53a84ccf6 100644 --- a/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol +++ b/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol @@ -127,24 +127,8 @@ contract TestStorageLayoutAndConstants is slot := add(slot, 0x1) assertSlotAndOffset( - _activeStakeByOwner_slot, - _activeStakeByOwner_offset, - slot, - offset - ) - slot := add(slot, 0x1) - - assertSlotAndOffset( - _inactiveStakeByOwner_slot, - _inactiveStakeByOwner_offset, - slot, - offset - ) - slot := add(slot, 0x1) - - assertSlotAndOffset( - _delegatedStakeByOwner_slot, - _delegatedStakeByOwner_offset, + _ownerStakeByStatus_slot, + _ownerStakeByStatus_offset, slot, offset ) @@ -166,14 +150,6 @@ contract TestStorageLayoutAndConstants is ) slot := add(slot, 0x1) - assertSlotAndOffset( - _withdrawableStakeByOwner_slot, - _withdrawableStakeByOwner_offset, - slot, - offset - ) - slot := add(slot, 0x1) - assertSlotAndOffset( lastPoolId_slot, lastPoolId_offset, From 2ef546210d43e900afad1adca9f601869cc01d2c Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sat, 5 Oct 2019 16:02:32 -0700 Subject: [PATCH 43/87] Update tests to reflect new withdrawal logic --- contracts/staking/package.json | 1 - contracts/staking/test/actors/staker_actor.ts | 20 ------------------- contracts/staking/test/codesize_test.ts | 2 +- contracts/staking/test/stake_test.ts | 18 ++++------------- .../unit_tests/mixin_stake_storage_test.ts | 2 -- contracts/staking/test/utils/types.ts | 2 -- 6 files changed, 5 insertions(+), 40 deletions(-) diff --git a/contracts/staking/package.json b/contracts/staking/package.json index a168d7e721..838a32239c 100644 --- a/contracts/staking/package.json +++ b/contracts/staking/package.json @@ -55,7 +55,6 @@ "@0x/dev-utils": "^2.4.0-beta.0", "@0x/sol-compiler": "^3.2.0-beta.0", "@0x/tslint-config": "^3.0.1", - "@0x/utils": "^4.5.2", "@types/lodash": "4.14.104", "@types/node": "*", "chai": "^4.0.1", diff --git a/contracts/staking/test/actors/staker_actor.ts b/contracts/staking/test/actors/staker_actor.ts index 99b70c970e..9cdaf8ff55 100644 --- a/contracts/staking/test/actors/staker_actor.ts +++ b/contracts/staking/test/actors/staker_actor.ts @@ -108,7 +108,6 @@ export class StakerActor extends BaseActor { expectedBalances.stakeBalanceInVault = initBalances.stakeBalanceInVault.minus(amount); StakerActor._decrementCurrentAndNextBalance(expectedBalances.inactiveStakeBalance, amount); StakerActor._decrementCurrentAndNextBalance(expectedBalances.globalInactiveStakeBalance, amount); - expectedBalances.withdrawableStakeBalance = initBalances.withdrawableStakeBalance.minus(amount); await this._assertBalancesAsync(expectedBalances); // check zrx balance of vault const finalZrxBalanceOfVault = await this._stakingApiWrapper.utils.getZrxTokenBalanceOfZrxVaultAsync(); @@ -182,12 +181,6 @@ export class StakerActor extends BaseActor { } private _getNextEpochBalances(balances: StakeBalances): StakeBalances { const nextBalances = _.cloneDeep(balances); - nextBalances.withdrawableStakeBalance = nextBalances.inactiveStakeBalance.nextEpochBalance.isLessThan( - nextBalances.inactiveStakeBalance.currentEpochBalance, - ) - ? nextBalances.inactiveStakeBalance.nextEpochBalance - : nextBalances.inactiveStakeBalance.currentEpochBalance; - for (const balance of [ nextBalances.activeStakeBalance, nextBalances.inactiveStakeBalance, @@ -207,9 +200,6 @@ export class StakerActor extends BaseActor { zrxBalance: await this._stakingApiWrapper.zrxTokenContract.balanceOf.callAsync(this._owner), stakeBalance: await this._stakingApiWrapper.stakingContract.getTotalStake.callAsync(this._owner), stakeBalanceInVault: await this._stakingApiWrapper.zrxVaultContract.balanceOf.callAsync(this._owner), - withdrawableStakeBalance: await this._stakingApiWrapper.stakingContract.getWithdrawableStake.callAsync( - this._owner, - ), activeStakeBalance: await this._stakingApiWrapper.stakingContract.getActiveStake.callAsync(this._owner), inactiveStakeBalance: await this._stakingApiWrapper.stakingContract.getInactiveStake.callAsync(this._owner), delegatedStakeBalance: await this._stakingApiWrapper.stakingContract.getStakeDelegatedByOwner.callAsync( @@ -241,9 +231,6 @@ export class StakerActor extends BaseActor { expect(balances.stakeBalanceInVault, 'stake balance, recorded in vault').to.be.bignumber.equal( expectedBalances.stakeBalanceInVault, ); - expect(balances.withdrawableStakeBalance, 'withdrawable stake balance').to.be.bignumber.equal( - expectedBalances.withdrawableStakeBalance, - ); expect(balances.activeStakeBalance.currentEpochBalance, 'active stake balance (current)').to.be.bignumber.equal( expectedBalances.activeStakeBalance.currentEpochBalance, ); @@ -315,13 +302,6 @@ export class StakerActor extends BaseActor { } else if (from.status === StakeStatus.Inactive) { StakerActor._decrementNextBalance(expectedBalances.inactiveStakeBalance, amount); StakerActor._decrementNextBalance(expectedBalances.globalInactiveStakeBalance, amount); - if ( - expectedBalances.inactiveStakeBalance.nextEpochBalance.isLessThan( - expectedBalances.withdrawableStakeBalance, - ) - ) { - expectedBalances.withdrawableStakeBalance = expectedBalances.inactiveStakeBalance.nextEpochBalance; - } } else if (from.status === StakeStatus.Delegated && from.poolId !== undefined) { StakerActor._decrementNextBalance(expectedBalances.delegatedStakeBalance, amount); StakerActor._decrementNextBalance(expectedBalances.globalDelegatedStakeBalance, amount); diff --git a/contracts/staking/test/codesize_test.ts b/contracts/staking/test/codesize_test.ts index 912ac09fa4..2fe4af1b13 100644 --- a/contracts/staking/test/codesize_test.ts +++ b/contracts/staking/test/codesize_test.ts @@ -2,7 +2,7 @@ import { constants, expect, getCodesizeFromArtifact } from '@0x/contracts-test-u import { artifacts } from '../src'; -describe.skip('Contract Size Checks', () => { +describe('Contract Size Checks', () => { describe('Staking', () => { it('should have a codesize less than the maximum', async () => { const actualSize = getCodesizeFromArtifact(artifacts.Staking); diff --git a/contracts/staking/test/stake_test.ts b/contracts/staking/test/stake_test.ts index 63aa1d351e..3ebbc6ee06 100644 --- a/contracts/staking/test/stake_test.ts +++ b/contracts/staking/test/stake_test.ts @@ -344,12 +344,11 @@ blockchainTests.resets('Stake Statuses', env => { const amount = toBaseUnitAmount(0); await staker.unstakeAsync(amount); }); - it('should successfully unstake after being inactive for 1 epoch', async () => { + it('should successfully unstake after becoming inactive', async () => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), amount); await staker.goToNextEpochAsync(); // stake is now inactive - await staker.goToNextEpochAsync(); // stake is now withdrawable await staker.unstakeAsync(amount); }); it('should fail to unstake with insufficient balance', async () => { @@ -363,30 +362,21 @@ blockchainTests.resets('Stake Statuses', env => { await staker.moveStakeAsync(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), amount); await staker.unstakeAsync(amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO)); }); - it('should fail to unstake after being inactive for <1 epoch', async () => { - const amount = toBaseUnitAmount(10); - await staker.stakeAsync(amount); - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), amount); - await staker.goToNextEpochAsync(); - await staker.unstakeAsync(amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO)); - }); - it('should fail to unstake in same epoch that inactive/withdrawable stake has been reactivated', async () => { + it('should fail to unstake in same epoch that inactive stake has been reactivated', async () => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), amount); await staker.goToNextEpochAsync(); // stake is now inactive - await staker.goToNextEpochAsync(); // stake is now withdrawable await staker.moveStakeAsync(new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Active), amount); await staker.unstakeAsync(amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO)); }); - it('should fail to unstake one epoch after inactive/withdrawable stake has been reactivated', async () => { + it('should fail to unstake one epoch after inactive stake has been reactivated', async () => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), amount); await staker.goToNextEpochAsync(); // stake is now inactive - await staker.goToNextEpochAsync(); // stake is now withdrawable await staker.moveStakeAsync(new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Active), amount); - await staker.goToNextEpochAsync(); // stake is active and not withdrawable + await staker.goToNextEpochAsync(); // stake is active await staker.unstakeAsync(amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO)); }); it('should fail to unstake >1 epoch after inactive/withdrawable stake has been reactivated', async () => { diff --git a/contracts/staking/test/unit_tests/mixin_stake_storage_test.ts b/contracts/staking/test/unit_tests/mixin_stake_storage_test.ts index c7115c4474..5e31f7934c 100644 --- a/contracts/staking/test/unit_tests/mixin_stake_storage_test.ts +++ b/contracts/staking/test/unit_tests/mixin_stake_storage_test.ts @@ -67,13 +67,11 @@ blockchainTests.resets('MixinStakeStorage unit tests', env => { getTestBalancesAsync(INDEX_ONE), ]); expect(actualBalances[0]).to.deep.equal({ - isInitialized: true, currentEpoch: CURRENT_EPOCH, currentEpochBalance: fromBalance.currentEpochBalance, nextEpochBalance: fromBalance.nextEpochBalance.minus(amount), }); expect(actualBalances[1]).to.deep.equal({ - isInitialized: true, currentEpoch: CURRENT_EPOCH, currentEpochBalance: toBalance.currentEpochBalance, nextEpochBalance: toBalance.nextEpochBalance.plus(amount), diff --git a/contracts/staking/test/utils/types.ts b/contracts/staking/test/utils/types.ts index 83a8fffde1..5b38fbe3d7 100644 --- a/contracts/staking/test/utils/types.ts +++ b/contracts/staking/test/utils/types.ts @@ -16,7 +16,6 @@ export interface StakerBalances { zrxBalance: BigNumber; stakeBalance: BigNumber; stakeBalanceInVault: BigNumber; - withdrawableStakeBalance: BigNumber; activatableStakeBalance: BigNumber; activatedStakeBalance: BigNumber; deactivatedStakeBalance: BigNumber; @@ -93,7 +92,6 @@ export interface StakeBalances { zrxBalance: BigNumber; stakeBalance: BigNumber; stakeBalanceInVault: BigNumber; - withdrawableStakeBalance: BigNumber; activeStakeBalance: StakeBalance; inactiveStakeBalance: StakeBalance; delegatedStakeBalance: StakeBalance; From 43399a9ad9a4e7ff9d25de47690a4413774e331b Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sat, 5 Oct 2019 16:45:36 -0700 Subject: [PATCH 44/87] Refactor tests to use new getters --- .../contracts/src/immutable/MixinStorage.sol | 3 +- .../contracts/src/interfaces/IStructs.sol | 8 -- .../contracts/src/stake/MixinStake.sol | 8 +- .../src/stake/MixinStakeBalances.sol | 124 ++++-------------- .../contracts/src/stake/MixinStakeStorage.sol | 2 +- .../contracts/test/TestProtocolFees.sol | 20 +-- .../test/TestStorageLayoutAndConstants.sol | 4 +- contracts/staking/test/actors/staker_actor.ts | 37 ++++-- contracts/staking/test/catastrophe_test.ts | 19 ++- contracts/staking/test/stake_test.ts | 2 - contracts/staking/test/utils/types.ts | 20 ++- 11 files changed, 96 insertions(+), 151 deletions(-) diff --git a/contracts/staking/contracts/src/immutable/MixinStorage.sol b/contracts/staking/contracts/src/immutable/MixinStorage.sol index 45dae75d60..634e9da075 100644 --- a/contracts/staking/contracts/src/immutable/MixinStorage.sol +++ b/contracts/staking/contracts/src/immutable/MixinStorage.sol @@ -43,7 +43,8 @@ contract MixinStorage is // mapping from StakeStatus to the total amount of stake in that status for the entire // staking system. - mapping (uint8 => IStructs.StoredBalance) public globalStakeByStatus; + // (access using _loadSyncedBalance or _loadUnsyncedBalance) + mapping (uint8 => IStructs.StoredBalance) internal _globalStakeByStatus; // mapping from StakeStatus to address of staker to stored balance // (access using _loadSyncedBalance or _loadUnsyncedBalance) diff --git a/contracts/staking/contracts/src/interfaces/IStructs.sol b/contracts/staking/contracts/src/interfaces/IStructs.sol index 7f0dfcc069..18530ec979 100644 --- a/contracts/staking/contracts/src/interfaces/IStructs.sol +++ b/contracts/staking/contracts/src/interfaces/IStructs.sol @@ -62,14 +62,6 @@ interface IStructs { uint96 nextEpochBalance; } - /// @dev Balance struct for stake. - /// @param currentEpochBalance Balance in the current epoch. - /// @param nextEpochBalance Balance in the next epoch. - struct StakeBalance { - uint256 currentEpochBalance; - uint256 nextEpochBalance; - } - /// @dev Statuses that stake can exist in. enum StakeStatus { ACTIVE, diff --git a/contracts/staking/contracts/src/stake/MixinStake.sol b/contracts/staking/contracts/src/stake/MixinStake.sol index c44cdfd143..be79b9af37 100644 --- a/contracts/staking/contracts/src/stake/MixinStake.sol +++ b/contracts/staking/contracts/src/stake/MixinStake.sol @@ -48,7 +48,7 @@ contract MixinStake is // update global total of active stake _increaseCurrentAndNextBalance( - globalStakeByStatus[uint8(IStructs.StakeStatus.ACTIVE)], + _globalStakeByStatus[uint8(IStructs.StakeStatus.ACTIVE)], amount ); @@ -94,7 +94,7 @@ contract MixinStake is // update global total of inactive stake _decreaseCurrentAndNextBalance( - globalStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)], + _globalStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)], amount ); @@ -151,8 +151,8 @@ contract MixinStake is // update global total of stake in the statuses being moved between _moveStake( - globalStakeByStatus[uint8(from.status)], - globalStakeByStatus[uint8(to.status)], + _globalStakeByStatus[uint8(from.status)], + _globalStakeByStatus[uint8(to.status)], amount ); diff --git a/contracts/staking/contracts/src/stake/MixinStakeBalances.sol b/contracts/staking/contracts/src/stake/MixinStakeBalances.sol index 619fbb1913..d245246d06 100644 --- a/contracts/staking/contracts/src/stake/MixinStakeBalances.sol +++ b/contracts/staking/contracts/src/stake/MixinStakeBalances.sol @@ -29,52 +29,36 @@ contract MixinStakeBalances is { using LibSafeMath for uint256; - /// @dev Returns the total active stake across the entire staking system. - /// @return Global active stake. - function getGlobalActiveStake() + /// @dev Gets global stake for a given status. + /// @param stakeStatus ACTIVE, INACTIVE, or DELEGATED + /// @return Global stake for given status. + function getGlobalStakeByStatus(IStructs.StakeStatus stakeStatus) external view - returns (IStructs.StakeBalance memory balance) + returns (IStructs.StoredBalance memory balance) { - IStructs.StoredBalance memory storedBalance = _loadSyncedBalance( - globalStakeByStatus[uint8(IStructs.StakeStatus.ACTIVE)] + balance = _loadSyncedBalance( + _globalStakeByStatus[uint8(stakeStatus)] ); - return IStructs.StakeBalance({ - currentEpochBalance: storedBalance.currentEpochBalance, - nextEpochBalance: storedBalance.nextEpochBalance - }); + return balance; } - /// @dev Returns the total inactive stake across the entire staking system. - /// @return Global inactive stake. - function getGlobalInactiveStake() + /// @dev Gets an owner's stake balances by status. + /// @param staker Owner of stake. + /// @param stakeStatus ACTIVE, INACTIVE, or DELEGATED + /// @return Owner's stake balances for given status. + function getOwnerStakeByStatus( + address staker, + IStructs.StakeStatus stakeStatus + ) external view - returns (IStructs.StakeBalance memory balance) + returns (IStructs.StoredBalance memory balance) { - IStructs.StoredBalance memory storedBalance = _loadSyncedBalance( - globalStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)] + balance = _loadSyncedBalance( + _ownerStakeByStatus[uint8(stakeStatus)][staker] ); - return IStructs.StakeBalance({ - currentEpochBalance: storedBalance.currentEpochBalance, - nextEpochBalance: storedBalance.nextEpochBalance - }); - } - - /// @dev Returns the total stake delegated across the entire staking system. - /// @return Global delegated stake. - function getGlobalDelegatedStake() - external - view - returns (IStructs.StakeBalance memory balance) - { - IStructs.StoredBalance memory storedBalance = _loadSyncedBalance( - globalStakeByStatus[uint8(IStructs.StakeStatus.DELEGATED)] - ); - return IStructs.StakeBalance({ - currentEpochBalance: storedBalance.currentEpochBalance, - nextEpochBalance: storedBalance.nextEpochBalance - }); + return balance; } /// @dev Returns the total stake for a given staker. @@ -88,68 +72,17 @@ contract MixinStakeBalances is return getZrxVault().balanceOf(staker); } - /// @dev Returns the active stake for a given staker. - /// @param staker of stake. - /// @return Active stake for staker. - function getActiveStake(address staker) - external - view - returns (IStructs.StakeBalance memory balance) - { - IStructs.StoredBalance memory storedBalance = - _loadSyncedBalance(_ownerStakeByStatus[uint8(IStructs.StakeStatus.ACTIVE)][staker]); - return IStructs.StakeBalance({ - currentEpochBalance: storedBalance.currentEpochBalance, - nextEpochBalance: storedBalance.nextEpochBalance - }); - } - - /// @dev Returns the inactive stake for a given staker. - /// @param staker of stake. - /// @return Inactive stake for staker. - function getInactiveStake(address staker) - external - view - returns (IStructs.StakeBalance memory balance) - { - IStructs.StoredBalance memory storedBalance = - _loadSyncedBalance(_ownerStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)][staker]); - return IStructs.StakeBalance({ - currentEpochBalance: storedBalance.currentEpochBalance, - nextEpochBalance: storedBalance.nextEpochBalance - }); - } - - /// @dev Returns the stake delegated by a given staker. - /// @param staker of stake. - /// @return Delegated stake for staker. - function getStakeDelegatedByOwner(address staker) - external - view - returns (IStructs.StakeBalance memory balance) - { - IStructs.StoredBalance memory storedBalance = - _loadSyncedBalance(_ownerStakeByStatus[uint8(IStructs.StakeStatus.DELEGATED)][staker]); - return IStructs.StakeBalance({ - currentEpochBalance: storedBalance.currentEpochBalance, - nextEpochBalance: storedBalance.nextEpochBalance - }); - } - /// @dev Returns the stake delegated to a specific staking pool, by a given staker. /// @param staker of stake. /// @param poolId Unique Id of pool. - /// @return Stake delegaated to pool by staker. + /// @return Stake delegated to pool by staker. function getStakeDelegatedToPoolByOwner(address staker, bytes32 poolId) public view - returns (IStructs.StakeBalance memory balance) + returns (IStructs.StoredBalance memory balance) { - IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(_delegatedStakeToPoolByOwner[staker][poolId]); - return IStructs.StakeBalance({ - currentEpochBalance: storedBalance.currentEpochBalance, - nextEpochBalance: storedBalance.nextEpochBalance - }); + balance = _loadSyncedBalance(_delegatedStakeToPoolByOwner[staker][poolId]); + return balance; } /// @dev Returns the total stake delegated to a specific staking pool, @@ -159,12 +92,9 @@ contract MixinStakeBalances is function getTotalStakeDelegatedToPool(bytes32 poolId) public view - returns (IStructs.StakeBalance memory balance) + returns (IStructs.StoredBalance memory balance) { - IStructs.StoredBalance memory storedBalance = _loadSyncedBalance(_delegatedStakeByPoolId[poolId]); - return IStructs.StakeBalance({ - currentEpochBalance: storedBalance.currentEpochBalance, - nextEpochBalance: storedBalance.nextEpochBalance - }); + balance = _loadSyncedBalance(_delegatedStakeByPoolId[poolId]); + return balance; } } diff --git a/contracts/staking/contracts/src/stake/MixinStakeStorage.sol b/contracts/staking/contracts/src/stake/MixinStakeStorage.sol index b145e09de0..3cd89d9407 100644 --- a/contracts/staking/contracts/src/stake/MixinStakeStorage.sol +++ b/contracts/staking/contracts/src/stake/MixinStakeStorage.sol @@ -176,7 +176,7 @@ contract MixinStakeStorage is private { // note - this compresses into a single `sstore` when optimizations are enabled, - // since the StakeBalance struct occupies a single word of storage. + // since the StoredBalance struct occupies a single word of storage. balancePtr.currentEpoch = balance.currentEpoch; balancePtr.nextEpochBalance = balance.nextEpochBalance; balancePtr.currentEpochBalance = balance.currentEpochBalance; diff --git a/contracts/staking/contracts/test/TestProtocolFees.sol b/contracts/staking/contracts/test/TestProtocolFees.sol index 383eeef0cc..6d44d7ce53 100644 --- a/contracts/staking/contracts/test/TestProtocolFees.sol +++ b/contracts/staking/contracts/test/TestProtocolFees.sol @@ -27,8 +27,8 @@ contract TestProtocolFees is TestStakingNoWETH { struct TestPool { - uint256 operatorStake; - uint256 membersStake; + uint96 operatorStake; + uint96 membersStake; mapping(address => bool) isMaker; } @@ -57,8 +57,8 @@ contract TestProtocolFees is /// @dev Create a test pool. function createTestPool( bytes32 poolId, - uint256 operatorStake, - uint256 membersStake, + uint96 operatorStake, + uint96 membersStake, address[] calldata makerAddresses ) external @@ -99,11 +99,12 @@ contract TestProtocolFees is function getTotalStakeDelegatedToPool(bytes32 poolId) public view - returns (IStructs.StakeBalance memory balance) + returns (IStructs.StoredBalance memory balance) { TestPool memory pool = _testPools[poolId]; - uint256 stake = pool.operatorStake + pool.membersStake; - return IStructs.StakeBalance({ + uint96 stake = pool.operatorStake + pool.membersStake; + return IStructs.StoredBalance({ + currentEpoch: currentEpoch.downcastToUint32(), currentEpochBalance: stake, nextEpochBalance: stake }); @@ -113,10 +114,11 @@ contract TestProtocolFees is function getStakeDelegatedToPoolByOwner(address, bytes32 poolId) public view - returns (IStructs.StakeBalance memory balance) + returns (IStructs.StoredBalance memory balance) { TestPool memory pool = _testPools[poolId]; - return IStructs.StakeBalance({ + return IStructs.StoredBalance({ + currentEpoch: currentEpoch.downcastToUint32(), currentEpochBalance: pool.operatorStake, nextEpochBalance: pool.operatorStake }); diff --git a/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol b/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol index e53a84ccf6..2ec0a0f54e 100644 --- a/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol +++ b/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol @@ -119,8 +119,8 @@ contract TestStorageLayoutAndConstants is slot := add(slot, 0x1) assertSlotAndOffset( - globalStakeByStatus_slot, - globalStakeByStatus_offset, + _globalStakeByStatus_slot, + _globalStakeByStatus_offset, slot, offset ) diff --git a/contracts/staking/test/actors/staker_actor.ts b/contracts/staking/test/actors/staker_actor.ts index 9cdaf8ff55..af57bb537c 100644 --- a/contracts/staking/test/actors/staker_actor.ts +++ b/contracts/staking/test/actors/staker_actor.ts @@ -3,24 +3,24 @@ import { BigNumber, RevertError } from '@0x/utils'; import * as _ from 'lodash'; import { StakingApiWrapper } from '../utils/api_wrapper'; -import { StakeBalance, StakeBalances, StakeInfo, StakeStatus } from '../utils/types'; +import { StakeBalances, StakeInfo, StakeStatus, StoredBalance } from '../utils/types'; import { BaseActor } from './base_actor'; export class StakerActor extends BaseActor { private readonly _poolIds: string[]; - private static _incrementNextBalance(balance: StakeBalance, amount: BigNumber): void { + private static _incrementNextBalance(balance: StoredBalance, amount: BigNumber): void { balance.nextEpochBalance = balance.nextEpochBalance.plus(amount); } - private static _decrementNextBalance(balance: StakeBalance, amount: BigNumber): void { + private static _decrementNextBalance(balance: StoredBalance, amount: BigNumber): void { balance.nextEpochBalance = balance.nextEpochBalance.minus(amount); } - private static _incrementCurrentAndNextBalance(balance: StakeBalance, amount: BigNumber): void { + private static _incrementCurrentAndNextBalance(balance: StoredBalance, amount: BigNumber): void { balance.currentEpochBalance = balance.currentEpochBalance.plus(amount); balance.nextEpochBalance = balance.nextEpochBalance.plus(amount); } - private static _decrementCurrentAndNextBalance(balance: StakeBalance, amount: BigNumber): void { + private static _decrementCurrentAndNextBalance(balance: StoredBalance, amount: BigNumber): void { balance.currentEpochBalance = balance.currentEpochBalance.minus(amount); balance.nextEpochBalance = balance.nextEpochBalance.minus(amount); } @@ -191,23 +191,38 @@ export class StakerActor extends BaseActor { ...this._poolIds.map(poolId => nextBalances.delegatedStakeByPool[poolId]), ...this._poolIds.map(poolId => nextBalances.totalDelegatedStakeByPool[poolId]), ]) { + balance.currentEpoch = balances.currentEpoch.plus(1); balance.currentEpochBalance = balance.nextEpochBalance; } return nextBalances; } private async _getBalancesAsync(): Promise { const balances: StakeBalances = { + currentEpoch: await this._stakingApiWrapper.stakingContract.currentEpoch.callAsync(), zrxBalance: await this._stakingApiWrapper.zrxTokenContract.balanceOf.callAsync(this._owner), stakeBalance: await this._stakingApiWrapper.stakingContract.getTotalStake.callAsync(this._owner), stakeBalanceInVault: await this._stakingApiWrapper.zrxVaultContract.balanceOf.callAsync(this._owner), - activeStakeBalance: await this._stakingApiWrapper.stakingContract.getActiveStake.callAsync(this._owner), - inactiveStakeBalance: await this._stakingApiWrapper.stakingContract.getInactiveStake.callAsync(this._owner), - delegatedStakeBalance: await this._stakingApiWrapper.stakingContract.getStakeDelegatedByOwner.callAsync( + activeStakeBalance: await this._stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( this._owner, + StakeStatus.Active, + ), + inactiveStakeBalance: await this._stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( + this._owner, + StakeStatus.Inactive, + ), + delegatedStakeBalance: await this._stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( + this._owner, + StakeStatus.Delegated, + ), + globalActiveStakeBalance: await this._stakingApiWrapper.stakingContract.getGlobalStakeByStatus.callAsync( + StakeStatus.Active, + ), + globalInactiveStakeBalance: await this._stakingApiWrapper.stakingContract.getGlobalStakeByStatus.callAsync( + StakeStatus.Inactive, + ), + globalDelegatedStakeBalance: await this._stakingApiWrapper.stakingContract.getGlobalStakeByStatus.callAsync( + StakeStatus.Delegated, ), - globalActiveStakeBalance: await this._stakingApiWrapper.stakingContract.getGlobalActiveStake.callAsync(), - globalInactiveStakeBalance: await this._stakingApiWrapper.stakingContract.getGlobalInactiveStake.callAsync(), - globalDelegatedStakeBalance: await this._stakingApiWrapper.stakingContract.getGlobalDelegatedStake.callAsync(), delegatedStakeByPool: {}, totalDelegatedStakeByPool: {}, }; diff --git a/contracts/staking/test/catastrophe_test.ts b/contracts/staking/test/catastrophe_test.ts index e3bc9b8d43..9572704a30 100644 --- a/contracts/staking/test/catastrophe_test.ts +++ b/contracts/staking/test/catastrophe_test.ts @@ -8,6 +8,7 @@ import { StakingProxyReadOnlyModeSetEventArgs } from '../src'; import { deployAndConfigureContractsAsync, StakingApiWrapper } from './utils/api_wrapper'; import { toBaseUnitAmount } from './utils/number_utils'; +import { StakeStatus } from './utils/types'; // tslint:disable:no-unnecessary-type-assertion blockchainTests.resets('Catastrophe Tests', env => { @@ -39,7 +40,10 @@ blockchainTests.resets('Catastrophe Tests', env => { await stakingApiWrapper.stakingContract.stake.awaitTransactionSuccessAsync(amountToStake, { from: actors[0], }); - const activeStakeBalance = await stakingApiWrapper.stakingContract.getActiveStake.callAsync(actors[0]); + const activeStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( + actors[0], + StakeStatus.Active, + ); expect(activeStakeBalance.currentEpochBalance).to.be.bignumber.equal(amountToStake); }); it('should not change state when in read-only mode', async () => { @@ -50,7 +54,10 @@ blockchainTests.resets('Catastrophe Tests', env => { await stakingApiWrapper.stakingContract.stake.awaitTransactionSuccessAsync(amountToStake, { from: actors[0], }); - const activeStakeBalance = await stakingApiWrapper.stakingContract.getActiveStake.callAsync(actors[0]); + const activeStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( + actors[0], + StakeStatus.Active, + ); expect(activeStakeBalance.currentEpochBalance).to.be.bignumber.equal(ZERO); }); it('should read values correctly when in read-only mode', async () => { @@ -62,8 +69,9 @@ blockchainTests.resets('Catastrophe Tests', env => { // set to read-only mode await stakingApiWrapper.stakingProxyContract.setReadOnlyMode.awaitTransactionSuccessAsync(true); // read stake balance in read-only mode - const activeStakeBalanceReadOnly = await stakingApiWrapper.stakingContract.getActiveStake.callAsync( + const activeStakeBalanceReadOnly = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( actors[0], + StakeStatus.Active, ); expect(activeStakeBalanceReadOnly.currentEpochBalance).to.be.bignumber.equal(amountToStake); }); @@ -76,7 +84,10 @@ blockchainTests.resets('Catastrophe Tests', env => { await stakingApiWrapper.stakingContract.stake.awaitTransactionSuccessAsync(amountToStake, { from: actors[0], }); - const activeStakeBalance = await stakingApiWrapper.stakingContract.getActiveStake.callAsync(actors[0]); + const activeStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( + actors[0], + StakeStatus.Active, + ); expect(activeStakeBalance.currentEpochBalance).to.be.bignumber.equal(amountToStake); }); it('should emit event when setting read-only mode', async () => { diff --git a/contracts/staking/test/stake_test.ts b/contracts/staking/test/stake_test.ts index 3ebbc6ee06..32edcc0da7 100644 --- a/contracts/staking/test/stake_test.ts +++ b/contracts/staking/test/stake_test.ts @@ -239,10 +239,8 @@ blockchainTests.resets('Stake Statuses', env => { // run test, checking balances in epochs [n .. n + 2] // in epoch `n` - `next` is set // in epoch `n+1` - `current` is set - // in epoch `n+2` - only withdrawable balance should change. await staker.moveStakeAsync(from, to, amount.div(2)); await staker.goToNextEpochAsync(); - await staker.goToNextEpochAsync(); }; it('active -> active', async () => { await testMovePartialStake(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Active)); diff --git a/contracts/staking/test/utils/types.ts b/contracts/staking/test/utils/types.ts index 5b38fbe3d7..74882e4af3 100644 --- a/contracts/staking/test/utils/types.ts +++ b/contracts/staking/test/utils/types.ts @@ -63,13 +63,8 @@ export interface StoredBalance { nextEpochBalance: BigNumber; } -export interface StakeBalance { - currentEpochBalance: BigNumber; - nextEpochBalance: BigNumber; -} - export interface StakeBalanceByPool { - [key: string]: StakeBalance; + [key: string]: StoredBalance; } export enum StakeStatus { @@ -89,15 +84,16 @@ export class StakeInfo { } export interface StakeBalances { + currentEpoch: BigNumber; zrxBalance: BigNumber; stakeBalance: BigNumber; stakeBalanceInVault: BigNumber; - activeStakeBalance: StakeBalance; - inactiveStakeBalance: StakeBalance; - delegatedStakeBalance: StakeBalance; - globalActiveStakeBalance: StakeBalance; - globalInactiveStakeBalance: StakeBalance; - globalDelegatedStakeBalance: StakeBalance; + activeStakeBalance: StoredBalance; + inactiveStakeBalance: StoredBalance; + delegatedStakeBalance: StoredBalance; + globalActiveStakeBalance: StoredBalance; + globalInactiveStakeBalance: StoredBalance; + globalDelegatedStakeBalance: StoredBalance; delegatedStakeByPool: StakeBalanceByPool; totalDelegatedStakeByPool: StakeBalanceByPool; } From 2e36c7ef83d3e8fa7655d178a740df96ed34ac66 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sat, 5 Oct 2019 17:28:44 -0700 Subject: [PATCH 45/87] Remove ACTIVE state --- contracts/staking/contracts/src/interfaces/IStructs.sol | 3 ++- contracts/staking/contracts/src/stake/MixinStake.sol | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/contracts/staking/contracts/src/interfaces/IStructs.sol b/contracts/staking/contracts/src/interfaces/IStructs.sol index 18530ec979..b30baea2a5 100644 --- a/contracts/staking/contracts/src/interfaces/IStructs.sol +++ b/contracts/staking/contracts/src/interfaces/IStructs.sol @@ -63,8 +63,9 @@ interface IStructs { } /// @dev Statuses that stake can exist in. + /// Any stake can be (re)delegated effective at the next epoch + /// Inactive stake can be withdrawn if it is available in both the current and next epoch enum StakeStatus { - ACTIVE, INACTIVE, DELEGATED } diff --git a/contracts/staking/contracts/src/stake/MixinStake.sol b/contracts/staking/contracts/src/stake/MixinStake.sol index be79b9af37..a043e42b4e 100644 --- a/contracts/staking/contracts/src/stake/MixinStake.sol +++ b/contracts/staking/contracts/src/stake/MixinStake.sol @@ -42,13 +42,13 @@ contract MixinStake is // mint stake _increaseCurrentAndNextBalance( - _ownerStakeByStatus[uint8(IStructs.StakeStatus.ACTIVE)][staker], + _ownerStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)][staker], amount ); // update global total of active stake _increaseCurrentAndNextBalance( - _globalStakeByStatus[uint8(IStructs.StakeStatus.ACTIVE)], + _globalStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)], amount ); From aa0a1bb54dc2543d2a225295bfa987043c362ad0 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sat, 5 Oct 2019 17:29:05 -0700 Subject: [PATCH 46/87] Fix tests to no longer utilize active stake --- contracts/staking/test/actors/staker_actor.ts | 38 +-- contracts/staking/test/catastrophe_test.ts | 24 +- contracts/staking/test/rewards_test.ts | 26 +- contracts/staking/test/stake_test.ts | 292 +++++++----------- .../cumulative_reward_tracking_simulation.ts | 4 +- contracts/staking/test/utils/types.ts | 3 - 6 files changed, 149 insertions(+), 238 deletions(-) diff --git a/contracts/staking/test/actors/staker_actor.ts b/contracts/staking/test/actors/staker_actor.ts index af57bb537c..0f71575114 100644 --- a/contracts/staking/test/actors/staker_actor.ts +++ b/contracts/staking/test/actors/staker_actor.ts @@ -148,7 +148,7 @@ export class StakerActor extends BaseActor { public async stakeWithPoolAsync(poolId: string, amount: BigNumber): Promise { await this.stakeAsync(amount); await this.moveStakeAsync( - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Delegated, poolId), amount, ); @@ -182,10 +182,8 @@ export class StakerActor extends BaseActor { private _getNextEpochBalances(balances: StakeBalances): StakeBalances { const nextBalances = _.cloneDeep(balances); for (const balance of [ - nextBalances.activeStakeBalance, nextBalances.inactiveStakeBalance, nextBalances.delegatedStakeBalance, - nextBalances.globalActiveStakeBalance, nextBalances.globalInactiveStakeBalance, nextBalances.globalDelegatedStakeBalance, ...this._poolIds.map(poolId => nextBalances.delegatedStakeByPool[poolId]), @@ -202,10 +200,6 @@ export class StakerActor extends BaseActor { zrxBalance: await this._stakingApiWrapper.zrxTokenContract.balanceOf.callAsync(this._owner), stakeBalance: await this._stakingApiWrapper.stakingContract.getTotalStake.callAsync(this._owner), stakeBalanceInVault: await this._stakingApiWrapper.zrxVaultContract.balanceOf.callAsync(this._owner), - activeStakeBalance: await this._stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( - this._owner, - StakeStatus.Active, - ), inactiveStakeBalance: await this._stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( this._owner, StakeStatus.Inactive, @@ -214,9 +208,6 @@ export class StakerActor extends BaseActor { this._owner, StakeStatus.Delegated, ), - globalActiveStakeBalance: await this._stakingApiWrapper.stakingContract.getGlobalStakeByStatus.callAsync( - StakeStatus.Active, - ), globalInactiveStakeBalance: await this._stakingApiWrapper.stakingContract.getGlobalStakeByStatus.callAsync( StakeStatus.Inactive, ), @@ -246,12 +237,6 @@ export class StakerActor extends BaseActor { expect(balances.stakeBalanceInVault, 'stake balance, recorded in vault').to.be.bignumber.equal( expectedBalances.stakeBalanceInVault, ); - expect(balances.activeStakeBalance.currentEpochBalance, 'active stake balance (current)').to.be.bignumber.equal( - expectedBalances.activeStakeBalance.currentEpochBalance, - ); - expect(balances.activeStakeBalance.nextEpochBalance, 'active stake balance (next)').to.be.bignumber.equal( - expectedBalances.activeStakeBalance.nextEpochBalance, - ); expect( balances.inactiveStakeBalance.currentEpochBalance, 'inactive stake balance (current)', @@ -266,10 +251,6 @@ export class StakerActor extends BaseActor { expect(balances.delegatedStakeBalance.nextEpochBalance, 'delegated stake balance (next)').to.be.bignumber.equal( expectedBalances.delegatedStakeBalance.nextEpochBalance, ); - expect( - balances.globalActiveStakeBalance.currentEpochBalance, - 'global active stake (current)', - ).to.bignumber.equal(expectedBalances.globalActiveStakeBalance.currentEpochBalance); expect( balances.globalInactiveStakeBalance.currentEpochBalance, 'global inactive stake (current)', @@ -278,9 +259,6 @@ export class StakerActor extends BaseActor { balances.globalDelegatedStakeBalance.currentEpochBalance, 'global delegated stake (current)', ).to.bignumber.equal(expectedBalances.globalDelegatedStakeBalance.currentEpochBalance); - expect(balances.globalActiveStakeBalance.nextEpochBalance, 'global active stake (next)').to.bignumber.equal( - expectedBalances.globalActiveStakeBalance.nextEpochBalance, - ); expect(balances.globalInactiveStakeBalance.nextEpochBalance, 'global inactive stake (next)').to.bignumber.equal( expectedBalances.globalInactiveStakeBalance.nextEpochBalance, ); @@ -311,10 +289,7 @@ export class StakerActor extends BaseActor { // @TODO check receipt logs and return value via eth_call // check balances // from - if (from.status === StakeStatus.Active) { - StakerActor._decrementNextBalance(expectedBalances.activeStakeBalance, amount); - StakerActor._decrementNextBalance(expectedBalances.globalActiveStakeBalance, amount); - } else if (from.status === StakeStatus.Inactive) { + if (from.status === StakeStatus.Inactive) { StakerActor._decrementNextBalance(expectedBalances.inactiveStakeBalance, amount); StakerActor._decrementNextBalance(expectedBalances.globalInactiveStakeBalance, amount); } else if (from.status === StakeStatus.Delegated && from.poolId !== undefined) { @@ -324,10 +299,7 @@ export class StakerActor extends BaseActor { StakerActor._decrementNextBalance(expectedBalances.totalDelegatedStakeByPool[from.poolId], amount); } // to - if (to.status === StakeStatus.Active) { - StakerActor._incrementNextBalance(expectedBalances.activeStakeBalance, amount); - StakerActor._incrementNextBalance(expectedBalances.globalActiveStakeBalance, amount); - } else if (to.status === StakeStatus.Inactive) { + if (to.status === StakeStatus.Inactive) { StakerActor._incrementNextBalance(expectedBalances.inactiveStakeBalance, amount); StakerActor._incrementNextBalance(expectedBalances.globalInactiveStakeBalance, amount); } else if (to.status === StakeStatus.Delegated && to.poolId !== undefined) { @@ -347,8 +319,8 @@ export class StakerActor extends BaseActor { // check balances expectedBalances.zrxBalance = expectedBalances.zrxBalance.minus(amount); expectedBalances.stakeBalanceInVault = expectedBalances.stakeBalanceInVault.plus(amount); - StakerActor._incrementCurrentAndNextBalance(expectedBalances.activeStakeBalance, amount); - StakerActor._incrementCurrentAndNextBalance(expectedBalances.globalActiveStakeBalance, amount); + StakerActor._incrementCurrentAndNextBalance(expectedBalances.inactiveStakeBalance, amount); + StakerActor._incrementCurrentAndNextBalance(expectedBalances.globalInactiveStakeBalance, amount); return expectedBalances; } } diff --git a/contracts/staking/test/catastrophe_test.ts b/contracts/staking/test/catastrophe_test.ts index 9572704a30..727ac935ac 100644 --- a/contracts/staking/test/catastrophe_test.ts +++ b/contracts/staking/test/catastrophe_test.ts @@ -40,11 +40,11 @@ blockchainTests.resets('Catastrophe Tests', env => { await stakingApiWrapper.stakingContract.stake.awaitTransactionSuccessAsync(amountToStake, { from: actors[0], }); - const activeStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( + const inactiveStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( actors[0], - StakeStatus.Active, + StakeStatus.Inactive, ); - expect(activeStakeBalance.currentEpochBalance).to.be.bignumber.equal(amountToStake); + expect(inactiveStakeBalance.currentEpochBalance).to.be.bignumber.equal(amountToStake); }); it('should not change state when in read-only mode', async () => { // set to read-only mode @@ -54,11 +54,11 @@ blockchainTests.resets('Catastrophe Tests', env => { await stakingApiWrapper.stakingContract.stake.awaitTransactionSuccessAsync(amountToStake, { from: actors[0], }); - const activeStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( + const inactiveStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( actors[0], - StakeStatus.Active, + StakeStatus.Inactive, ); - expect(activeStakeBalance.currentEpochBalance).to.be.bignumber.equal(ZERO); + expect(inactiveStakeBalance.currentEpochBalance).to.be.bignumber.equal(ZERO); }); it('should read values correctly when in read-only mode', async () => { // stake some zrx @@ -69,11 +69,11 @@ blockchainTests.resets('Catastrophe Tests', env => { // set to read-only mode await stakingApiWrapper.stakingProxyContract.setReadOnlyMode.awaitTransactionSuccessAsync(true); // read stake balance in read-only mode - const activeStakeBalanceReadOnly = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( + const inactiveStakeBalanceReadOnly = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( actors[0], - StakeStatus.Active, + StakeStatus.Inactive, ); - expect(activeStakeBalanceReadOnly.currentEpochBalance).to.be.bignumber.equal(amountToStake); + expect(inactiveStakeBalanceReadOnly.currentEpochBalance).to.be.bignumber.equal(amountToStake); }); it('should exit read-only mode', async () => { // set to read-only mode @@ -84,11 +84,11 @@ blockchainTests.resets('Catastrophe Tests', env => { await stakingApiWrapper.stakingContract.stake.awaitTransactionSuccessAsync(amountToStake, { from: actors[0], }); - const activeStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( + const inactiveStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( actors[0], - StakeStatus.Active, + StakeStatus.Inactive, ); - expect(activeStakeBalance.currentEpochBalance).to.be.bignumber.equal(amountToStake); + expect(inactiveStakeBalance.currentEpochBalance).to.be.bignumber.equal(amountToStake); }); it('should emit event when setting read-only mode', async () => { // set to read-only mode diff --git a/contracts/staking/test/rewards_test.ts b/contracts/staking/test/rewards_test.ts index a43fcb5ae7..0940ed16b3 100644 --- a/contracts/staking/test/rewards_test.ts +++ b/contracts/staking/test/rewards_test.ts @@ -176,7 +176,7 @@ blockchainTests.resets('Testing Rewards', env => { const amount = toBaseUnitAmount(4); await stakers[0].stakeAsync(amount); await stakers[0].moveStakeAsync( - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Delegated, poolId), amount, ); @@ -248,7 +248,7 @@ blockchainTests.resets('Testing Rewards', env => { const totalStakeAmount = toBaseUnitAmount(10); await stakers[0].stakeAsync(stakeAmounts[0]); await stakers[0].moveStakeAsync( - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Delegated, poolId), stakeAmounts[0], ); @@ -259,7 +259,7 @@ blockchainTests.resets('Testing Rewards', env => { // second staker delegates (epoch 1) await stakers[1].stakeAsync(stakeAmounts[1]); await stakers[1].moveStakeAsync( - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Delegated, poolId), stakeAmounts[1], ); @@ -355,7 +355,7 @@ blockchainTests.resets('Testing Rewards', env => { // undelegate (withdraws delegator's rewards) await stakers[0].moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolId), - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Inactive), stakeAmount, ); // sanity check final balances @@ -436,7 +436,7 @@ blockchainTests.resets('Testing Rewards', env => { // undelegate stake and finalize epoch await stakers[0].moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolId), - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Inactive), stakeAmount, ); @@ -472,7 +472,7 @@ blockchainTests.resets('Testing Rewards', env => { // undelegate stake and finalize epoch await stakers[0].moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolId), - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Inactive), stakeAmount, ); await payProtocolFeeAndFinalize(); @@ -499,7 +499,7 @@ blockchainTests.resets('Testing Rewards', env => { // undelegate stake and finalize epoch await stakers[0].moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolId), - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Inactive), stakeAmount, ); await payProtocolFeeAndFinalize(); @@ -507,7 +507,7 @@ blockchainTests.resets('Testing Rewards', env => { await payProtocolFeeAndFinalize(rewardNotForDelegator); // delegate stake and go to next epoch await stakers[0].moveStakeAsync( - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Delegated, poolId), stakeAmount, ); @@ -530,7 +530,7 @@ blockchainTests.resets('Testing Rewards', env => { const stakeAmount = toBaseUnitAmount(4); await stakers[0].stakeAsync(stakeAmount); await stakers[0].moveStakeAsync( - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Delegated, poolId), stakeAmount, ); @@ -539,7 +539,7 @@ blockchainTests.resets('Testing Rewards', env => { // undelegate stake and finalize epoch await stakers[0].moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolId), - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Inactive), stakeAmount, ); // this should go to the delegator @@ -547,7 +547,7 @@ blockchainTests.resets('Testing Rewards', env => { // delegate stake ~ this will result in a payout where rewards are computed on // the balance's `currentEpochBalance` field but not the `nextEpochBalance` field. await stakers[0].moveStakeAsync( - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Delegated, poolId), stakeAmount, ); @@ -565,7 +565,7 @@ blockchainTests.resets('Testing Rewards', env => { const stakeAmount = toBaseUnitAmount(4); await stakers[0].stakeAsync(stakeAmount); await stakers[0].moveStakeAsync( - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Delegated, poolId), stakeAmount, ); @@ -595,7 +595,7 @@ blockchainTests.resets('Testing Rewards', env => { const undelegateAmount = toBaseUnitAmount(2.5); await staker.moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolId), - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Inactive), undelegateAmount, ); // finalize diff --git a/contracts/staking/test/stake_test.ts b/contracts/staking/test/stake_test.ts index 32edcc0da7..e5839c1d15 100644 --- a/contracts/staking/test/stake_test.ts +++ b/contracts/staking/test/stake_test.ts @@ -76,42 +76,47 @@ blockchainTests.resets('Stake Statuses', env => { // epoch 1 const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), amount); - // still epoch 1 ~ should be able to move stake again await staker.moveStakeAsync( new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); + // still epoch 1 ~ should be able to move stake again + await staker.moveStakeAsync( + new StakeInfo(StakeStatus.Delegated, poolIds[0]), + new StakeInfo(StakeStatus.Inactive), + amount, + ); }); - it('should fail to move the same stake more than once', async () => { + it("should be able to reassign next epoch's stake", async () => { // epoch 1 const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), amount); - // stake is now inactive, should not be able to move it out of active status again await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Delegated, poolIds[0]), + amount, + ); + // still epoch 1 ~ should be able to move stake again + await staker.moveStakeAsync( + new StakeInfo(StakeStatus.Delegated, poolIds[0]), + new StakeInfo(StakeStatus.Delegated, poolIds[1]), amount, - new StakingRevertErrors.InsufficientBalanceError(amount, ZERO), ); }); - it('should fail to reassign stake', async () => { + it('should fail to move the same stake more than once', async () => { // epoch 1 const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), amount); - // still epoch 1 ~ should be able to move stake again await staker.moveStakeAsync( new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); - // stake is now delegated; should fail to re-assign it from inactive back to active + // stake is now inactive, should not be able to move it out of active status again await staker.moveStakeAsync( new StakeInfo(StakeStatus.Inactive), - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Delegated, poolIds[1]), amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO), ); @@ -122,73 +127,35 @@ blockchainTests.resets('Stake Statuses', env => { // epoch 1 const amount = toBaseUnitAmount(10); await staker.stakeAndMoveAsync( - new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); // still epoch 1 ~ should be able to move stake again await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Delegated, poolIds[0]), - amount, - ); - }); - it('should fail to move the same stake more than once', async () => { - // epoch 1 - const amount = toBaseUnitAmount(10); - await staker.stakeAndMoveAsync( - new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), amount, ); - // stake is now inactive, should not be able to move it out of active status again - await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Active), - new StakeInfo(StakeStatus.Inactive), - amount, - new StakingRevertErrors.InsufficientBalanceError(amount, ZERO), - ); }); - it('should fail to reassign stake', async () => { + it('should fail to move the same stake more than once', async () => { // epoch 1 const amount = toBaseUnitAmount(10); await staker.stakeAndMoveAsync( - new StakeInfo(StakeStatus.Active), - new StakeInfo(StakeStatus.Inactive), - amount, - ); - // still epoch 1 ~ should be able to move stake again - await staker.moveStakeAsync( new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); - // stake is now delegated; should fail to re-assign it from inactive back to active + // stake is now inactive, should not be able to move it out of active status again await staker.moveStakeAsync( new StakeInfo(StakeStatus.Inactive), - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Delegated, poolIds[1]), amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO), ); }); }); describe('Move Zero Stake', () => { - it('active -> active', async () => { - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Active), ZERO); - }); - it('active -> inactive', async () => { - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), ZERO); - }); - it('active -> delegated', async () => { - await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Active), - new StakeInfo(StakeStatus.Delegated, poolIds[0]), - ZERO, - ); - }); - it('inactive -> active', async () => { - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Active), ZERO); - }); it('inactive -> inactive', async () => { await staker.moveStakeAsync(new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Inactive), ZERO); }); @@ -199,13 +166,6 @@ blockchainTests.resets('Stake Statuses', env => { ZERO, ); }); - it('delegated -> active', async () => { - await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Delegated, poolIds[0]), - new StakeInfo(StakeStatus.Active), - ZERO, - ); - }); it('delegated -> inactive', async () => { await staker.moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolIds[0]), @@ -233,8 +193,8 @@ blockchainTests.resets('Stake Statuses', env => { // setup const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); - if (from.status !== StakeStatus.Active) { - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Active), from, amount); + if (from.status !== StakeStatus.Inactive) { + await staker.moveStakeAsync(new StakeInfo(StakeStatus.Inactive), from, amount); } // run test, checking balances in epochs [n .. n + 2] // in epoch `n` - `next` is set @@ -242,21 +202,6 @@ blockchainTests.resets('Stake Statuses', env => { await staker.moveStakeAsync(from, to, amount.div(2)); await staker.goToNextEpochAsync(); }; - it('active -> active', async () => { - await testMovePartialStake(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Active)); - }); - it('active -> inactive', async () => { - await testMovePartialStake(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive)); - }); - it('active -> delegated', async () => { - await testMovePartialStake( - new StakeInfo(StakeStatus.Active), - new StakeInfo(StakeStatus.Delegated, poolIds[0]), - ); - }); - it('inactive -> active', async () => { - await testMovePartialStake(new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Active)); - }); it('inactive -> inactive', async () => { await testMovePartialStake(new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Inactive)); }); @@ -266,12 +211,6 @@ blockchainTests.resets('Stake Statuses', env => { new StakeInfo(StakeStatus.Delegated, poolIds[0]), ); }); - it('delegated -> active', async () => { - await testMovePartialStake( - new StakeInfo(StakeStatus.Delegated, poolIds[0]), - new StakeInfo(StakeStatus.Active), - ); - }); it('delegated -> inactive', async () => { await testMovePartialStake( new StakeInfo(StakeStatus.Delegated, poolIds[0]), @@ -290,20 +229,9 @@ blockchainTests.resets('Stake Statuses', env => { new StakeInfo(StakeStatus.Delegated, poolIds[1]), ); }); - it('active -> delegated (non-existent pool)', async () => { - const amount = toBaseUnitAmount(10); - await staker.stakeAsync(amount); - await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Active), - new StakeInfo(StakeStatus.Delegated, unusedPoolId), - amount, - new StakingRevertErrors.PoolExistenceError(unusedPoolId, false), - ); - }); it('inactive -> delegated (non-existent pool)', async () => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), amount); await staker.moveStakeAsync( new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Delegated, unusedPoolId), @@ -315,7 +243,7 @@ blockchainTests.resets('Stake Statuses', env => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); @@ -326,16 +254,6 @@ blockchainTests.resets('Stake Statuses', env => { new StakingRevertErrors.PoolExistenceError(unusedPoolId, false), ); }); - it('delegated (non-existent pool) -> active', async () => { - const amount = toBaseUnitAmount(10); - await staker.stakeAsync(amount); - await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Delegated, unusedPoolId), - new StakeInfo(StakeStatus.Active), - amount, - new StakingRevertErrors.PoolExistenceError(unusedPoolId, false), - ); - }); }); describe('Unstake', () => { it('should successfully unstake zero ZRX', async () => { @@ -345,102 +263,126 @@ blockchainTests.resets('Stake Statuses', env => { it('should successfully unstake after becoming inactive', async () => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), amount); + await staker.moveStakeAsync( + new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Delegated, poolIds[0]), + amount, + ); + await staker.moveStakeAsync( + new StakeInfo(StakeStatus.Delegated, poolIds[0]), + new StakeInfo(StakeStatus.Inactive), + amount, + ); await staker.goToNextEpochAsync(); // stake is now inactive await staker.unstakeAsync(amount); }); - it('should fail to unstake with insufficient balance', async () => { - const amount = toBaseUnitAmount(10); - await staker.stakeAsync(amount); - await staker.unstakeAsync(amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO)); - }); it('should fail to unstake in the same epoch as stake was set to inactive', async () => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), amount); + await staker.moveStakeAsync( + new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Delegated, poolIds[0]), + amount, + ); + await staker.goToNextEpochAsync(); // stake is now delegated + await staker.moveStakeAsync( + new StakeInfo(StakeStatus.Delegated, poolIds[0]), + new StakeInfo(StakeStatus.Inactive), + amount, + ); await staker.unstakeAsync(amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO)); }); it('should fail to unstake in same epoch that inactive stake has been reactivated', async () => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), amount); - await staker.goToNextEpochAsync(); // stake is now inactive - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Active), amount); + await staker.moveStakeAsync( + new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Delegated, poolIds[0]), + amount, + ); await staker.unstakeAsync(amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO)); }); it('should fail to unstake one epoch after inactive stake has been reactivated', async () => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), amount); + await staker.moveStakeAsync( + new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Delegated, poolIds[0]), + amount, + ); await staker.goToNextEpochAsync(); // stake is now inactive - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Active), amount); - await staker.goToNextEpochAsync(); // stake is active await staker.unstakeAsync(amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO)); }); - it('should fail to unstake >1 epoch after inactive/withdrawable stake has been reactivated', async () => { + it('should fail to unstake >1 epoch after inactive stake has been reactivated', async () => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Active), new StakeInfo(StakeStatus.Inactive), amount); + await staker.moveStakeAsync( + new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Delegated, poolIds[0]), + amount, + ); await staker.goToNextEpochAsync(); // stake is now inactive await staker.goToNextEpochAsync(); // stake is now withdrawable - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Active), amount); - await staker.goToNextEpochAsync(); // stake is active and not withdrawable - await staker.goToNextEpochAsync(); // stake is active and not withdrawable await staker.unstakeAsync(amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO)); }); + it('should successfuly unstake freshly deposited stake', async () => { + const amount = toBaseUnitAmount(10); + await staker.stakeAsync(amount); + await staker.unstakeAsync(amount); + }); }); describe('Simulations', () => { - it('Simulation from Staking Spec', async () => { - // Epoch 1: Stake some ZRX - await staker.stakeAsync(toBaseUnitAmount(4)); - // Later in Epoch 1: User delegates and deactivates some stake - await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Active), - new StakeInfo(StakeStatus.Inactive), - toBaseUnitAmount(1), - ); - await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Active), - new StakeInfo(StakeStatus.Delegated, poolIds[0]), - toBaseUnitAmount(2), - ); - // Epoch 2: Status updates (no user intervention required) - await staker.goToNextEpochAsync(); - // Epoch 3: Stake that has been inactive for an epoch can be withdrawn (no user intervention required) - await staker.goToNextEpochAsync(); - // Later in Epoch 3: User reactivates half of their inactive stake; this becomes Active next epoch - await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), - new StakeInfo(StakeStatus.Active), - toBaseUnitAmount(0.5), - ); - // Later in Epoch 3: User re-delegates half of their stake from Pool 1 to Pool 2 - await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Delegated, poolIds[0]), - new StakeInfo(StakeStatus.Delegated, poolIds[1]), - toBaseUnitAmount(1), - ); - // Epoch 4: Status updates (no user intervention required) - await staker.goToNextEpochAsync(); - // Later in Epoch 4: User deactivates all active stake - await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Active), - new StakeInfo(StakeStatus.Inactive), - toBaseUnitAmount(1.5), - ); - // Later in Epoch 4: User withdraws all available inactive stake - await staker.unstakeAsync(toBaseUnitAmount(0.5)); - // Epoch 5: Status updates (no user intervention required) - await staker.goToNextEpochAsync(); - // Later in Epoch 5: User reactivates a portion of their stake - await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), - new StakeInfo(StakeStatus.Active), - toBaseUnitAmount(1), - ); - // Epoch 6: Status updates (no user intervention required) - await staker.goToNextEpochAsync(); - }); + // it('Simulation from Staking Spec', async () => { + // // Epoch 1: Stake some ZRX + // await staker.stakeAsync(toBaseUnitAmount(4)); + // // Later in Epoch 1: User delegates and deactivates some stake + // await staker.moveStakeAsync( + // new StakeInfo(StakeStatus.Active), + // new StakeInfo(StakeStatus.Inactive), + // toBaseUnitAmount(1), + // ); + // await staker.moveStakeAsync( + // new StakeInfo(StakeStatus.Active), + // new StakeInfo(StakeStatus.Delegated, poolIds[0]), + // toBaseUnitAmount(2), + // ); + // // Epoch 2: Status updates (no user intervention required) + // await staker.goToNextEpochAsync(); + // // Epoch 3: Stake that has been inactive for an epoch can be withdrawn (no user intervention required) + // await staker.goToNextEpochAsync(); + // // Later in Epoch 3: User reactivates half of their inactive stake; this becomes Active next epoch + // await staker.moveStakeAsync( + // new StakeInfo(StakeStatus.Inactive), + // new StakeInfo(StakeStatus.Active), + // toBaseUnitAmount(0.5), + // ); + // // Later in Epoch 3: User re-delegates half of their stake from Pool 1 to Pool 2 + // await staker.moveStakeAsync( + // new StakeInfo(StakeStatus.Delegated, poolIds[0]), + // new StakeInfo(StakeStatus.Delegated, poolIds[1]), + // toBaseUnitAmount(1), + // ); + // // Epoch 4: Status updates (no user intervention required) + // await staker.goToNextEpochAsync(); + // // Later in Epoch 4: User deactivates all active stake + // await staker.moveStakeAsync( + // new StakeInfo(StakeStatus.Active), + // new StakeInfo(StakeStatus.Inactive), + // toBaseUnitAmount(1.5), + // ); + // // Later in Epoch 4: User withdraws all available inactive stake + // await staker.unstakeAsync(toBaseUnitAmount(0.5)); + // // Epoch 5: Status updates (no user intervention required) + // await staker.goToNextEpochAsync(); + // // Later in Epoch 5: User reactivates a portion of their stake + // await staker.moveStakeAsync( + // new StakeInfo(StakeStatus.Inactive), + // new StakeInfo(StakeStatus.Active), + // toBaseUnitAmount(1), + // ); + // // Epoch 6: Status updates (no user intervention required) + // await staker.goToNextEpochAsync(); + // }); }); }); // tslint:enable:no-unnecessary-type-assertion diff --git a/contracts/staking/test/utils/cumulative_reward_tracking_simulation.ts b/contracts/staking/test/utils/cumulative_reward_tracking_simulation.ts index 675f079f25..9bcadbd674 100644 --- a/contracts/staking/test/utils/cumulative_reward_tracking_simulation.ts +++ b/contracts/staking/test/utils/cumulative_reward_tracking_simulation.ts @@ -120,7 +120,7 @@ export class CumulativeRewardTrackingSimulation { from: this._staker, }); receipt = await this._stakingApiWrapper.stakingContract.moveStake.awaitTransactionSuccessAsync( - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Delegated, this._poolId), this._amountToStake, { from: this._staker }, @@ -130,7 +130,7 @@ export class CumulativeRewardTrackingSimulation { case TestAction.Undelegate: receipt = await this._stakingApiWrapper.stakingContract.moveStake.awaitTransactionSuccessAsync( new StakeInfo(StakeStatus.Delegated, this._poolId), - new StakeInfo(StakeStatus.Active), + new StakeInfo(StakeStatus.Inactive), this._amountToStake, { from: this._staker }, ); diff --git a/contracts/staking/test/utils/types.ts b/contracts/staking/test/utils/types.ts index 74882e4af3..9d36c818e0 100644 --- a/contracts/staking/test/utils/types.ts +++ b/contracts/staking/test/utils/types.ts @@ -68,7 +68,6 @@ export interface StakeBalanceByPool { } export enum StakeStatus { - Active, Inactive, Delegated, } @@ -88,10 +87,8 @@ export interface StakeBalances { zrxBalance: BigNumber; stakeBalance: BigNumber; stakeBalanceInVault: BigNumber; - activeStakeBalance: StoredBalance; inactiveStakeBalance: StoredBalance; delegatedStakeBalance: StoredBalance; - globalActiveStakeBalance: StoredBalance; globalInactiveStakeBalance: StoredBalance; globalDelegatedStakeBalance: StoredBalance; delegatedStakeByPool: StakeBalanceByPool; From 13afc65b546ed00d79c84f3b3c4964fc196abc54 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sat, 5 Oct 2019 18:05:11 -0700 Subject: [PATCH 47/87] Do not store global inactive state --- contracts/staking/contracts/src/ZrxVault.sol | 45 ++++++++++++------- .../contracts/src/immutable/MixinStorage.sol | 5 +-- .../contracts/src/interfaces/IZrxVault.sol | 6 +++ .../contracts/src/stake/MixinStake.sol | 31 +++++-------- .../src/stake/MixinStakeBalances.sol | 17 ++++--- .../test/TestStorageLayoutAndConstants.sol | 4 +- 6 files changed, 63 insertions(+), 45 deletions(-) diff --git a/contracts/staking/contracts/src/ZrxVault.sol b/contracts/staking/contracts/src/ZrxVault.sol index b3ae4eb578..5fca36d9b1 100644 --- a/contracts/staking/contracts/src/ZrxVault.sol +++ b/contracts/staking/contracts/src/ZrxVault.sol @@ -52,6 +52,24 @@ contract ZrxVault is // Asset data for the ERC20 Proxy bytes internal _zrxAssetData; + /// @dev Only stakingProxy can call this function. + modifier onlyStakingProxy() { + _assertSenderIsStakingProxy(); + _; + } + + /// @dev Function can only be called in catastrophic failure mode. + modifier onlyInCatastrophicFailure() { + _assertInCatastrophicFailure(); + _; + } + + /// @dev Function can only be called not in catastropic failure mode + modifier onlyNotInCatastrophicFailure() { + _assertNotInCatastrophicFailure(); + _; + } + /// @dev Constructor. /// @param _zrxProxyAddress Address of the 0x Zrx Proxy. /// @param _zrxTokenAddress Address of the Zrx Token. @@ -169,6 +187,15 @@ contract ZrxVault is return _balances[staker]; } + /// @dev Returns the entire balance of Zrx tokens in the vault. + function balanceOfVault() + external + view + returns (uint256) + { + return _zrxToken.balanceOf(address(this)); + } + /// @dev Withdraw an `amount` of Zrx Tokens to `staker` from the vault. /// @param staker of Zrx Tokens. /// @param amount of Zrx Tokens to withdraw. @@ -190,21 +217,7 @@ contract ZrxVault is ); } - modifier onlyStakingProxy() { - _assertSenderIsStakingProxy(); - _; - } - - modifier onlyInCatastrophicFailure() { - _assertInCatastrophicFailure(); - _; - } - - modifier onlyNotInCatastrophicFailure() { - _assertNotInCatastrophicFailure(); - _; - } - + /// @dev Asserts that sender is stakingProxy contract. function _assertSenderIsStakingProxy() private view @@ -216,6 +229,7 @@ contract ZrxVault is } } + /// @dev Asserts that vault is in catastrophic failure mode. function _assertInCatastrophicFailure() private view @@ -225,6 +239,7 @@ contract ZrxVault is } } + /// @dev Asserts that vault is not in catastrophic failure mode. function _assertNotInCatastrophicFailure() private view diff --git a/contracts/staking/contracts/src/immutable/MixinStorage.sol b/contracts/staking/contracts/src/immutable/MixinStorage.sol index 634e9da075..ce48e2c19e 100644 --- a/contracts/staking/contracts/src/immutable/MixinStorage.sol +++ b/contracts/staking/contracts/src/immutable/MixinStorage.sol @@ -41,10 +41,9 @@ contract MixinStorage is // address for read-only proxy to call address public readOnlyProxyCallee; - // mapping from StakeStatus to the total amount of stake in that status for the entire - // staking system. + // amount of stake currently being delegated in the system // (access using _loadSyncedBalance or _loadUnsyncedBalance) - mapping (uint8 => IStructs.StoredBalance) internal _globalStakeByStatus; + IStructs.StoredBalance internal _globalDelegatedStake; // mapping from StakeStatus to address of staker to stored balance // (access using _loadSyncedBalance or _loadUnsyncedBalance) diff --git a/contracts/staking/contracts/src/interfaces/IZrxVault.sol b/contracts/staking/contracts/src/interfaces/IZrxVault.sol index 2e4596170c..efe7a4b0c7 100644 --- a/contracts/staking/contracts/src/interfaces/IZrxVault.sol +++ b/contracts/staking/contracts/src/interfaces/IZrxVault.sol @@ -95,4 +95,10 @@ interface IZrxVault { external view returns (uint256); + + /// @dev Returns the entire balance of Zrx tokens in the vault. + function balanceOfVault() + external + view + returns (uint256); } diff --git a/contracts/staking/contracts/src/stake/MixinStake.sol b/contracts/staking/contracts/src/stake/MixinStake.sol index a043e42b4e..1e4101e459 100644 --- a/contracts/staking/contracts/src/stake/MixinStake.sol +++ b/contracts/staking/contracts/src/stake/MixinStake.sol @@ -46,12 +46,6 @@ contract MixinStake is amount ); - // update global total of active stake - _increaseCurrentAndNextBalance( - _globalStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)], - amount - ); - // notify emit Stake( staker, @@ -92,12 +86,6 @@ contract MixinStake is amount ); - // update global total of inactive stake - _decreaseCurrentAndNextBalance( - _globalStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)], - amount - ); - // withdraw equivalent amount of ZRX from vault getZrxVault().withdrawFrom(staker, amount); @@ -149,13 +137,6 @@ contract MixinStake is amount ); - // update global total of stake in the statuses being moved between - _moveStake( - _globalStakeByStatus[uint8(from.status)], - _globalStakeByStatus[uint8(to.status)], - amount - ); - // notify emit MoveStake( staker, @@ -197,6 +178,12 @@ contract MixinStake is _delegatedStakeByPoolId[poolId], amount ); + + // Increase next balance of global delegated stake + _increaseNextBalance( + _globalDelegatedStake, + amount + ); } /// @dev Un-Delegates a owners stake from a staking pool. @@ -229,5 +216,11 @@ contract MixinStake is _delegatedStakeByPoolId[poolId], amount ); + + // decrease next balance of global delegated stake + _decreaseNextBalance( + _globalDelegatedStake, + amount + ); } } diff --git a/contracts/staking/contracts/src/stake/MixinStakeBalances.sol b/contracts/staking/contracts/src/stake/MixinStakeBalances.sol index d245246d06..1a852052f5 100644 --- a/contracts/staking/contracts/src/stake/MixinStakeBalances.sol +++ b/contracts/staking/contracts/src/stake/MixinStakeBalances.sol @@ -30,22 +30,27 @@ contract MixinStakeBalances is using LibSafeMath for uint256; /// @dev Gets global stake for a given status. - /// @param stakeStatus ACTIVE, INACTIVE, or DELEGATED + /// @param stakeStatus INACTIVE or DELEGATED /// @return Global stake for given status. function getGlobalStakeByStatus(IStructs.StakeStatus stakeStatus) external view returns (IStructs.StoredBalance memory balance) { - balance = _loadSyncedBalance( - _globalStakeByStatus[uint8(stakeStatus)] - ); + balance = _loadSyncedBalance(_globalDelegatedStake); + if (stakeStatus == IStructs.StakeStatus.INACTIVE) { + // Inactive stake is the difference between total stake and delegated stake + // Note that any Zrx erroneously sent to the vault will be counted as inactive stake + uint256 totalStake = getZrxVault().balanceOfVault(); + balance.currentEpochBalance = totalStake.safeSub(balance.currentEpochBalance).downcastToUint96(); + balance.nextEpochBalance = totalStake.safeSub(balance.nextEpochBalance).downcastToUint96(); + } return balance; } /// @dev Gets an owner's stake balances by status. /// @param staker Owner of stake. - /// @param stakeStatus ACTIVE, INACTIVE, or DELEGATED + /// @param stakeStatus INACTIVE or DELEGATED /// @return Owner's stake balances for given status. function getOwnerStakeByStatus( address staker, @@ -65,7 +70,7 @@ contract MixinStakeBalances is /// @param staker of stake. /// @return Total active stake for staker. function getTotalStake(address staker) - external + public view returns (uint256) { diff --git a/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol b/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol index 2ec0a0f54e..2824b30a34 100644 --- a/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol +++ b/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol @@ -119,8 +119,8 @@ contract TestStorageLayoutAndConstants is slot := add(slot, 0x1) assertSlotAndOffset( - _globalStakeByStatus_slot, - _globalStakeByStatus_offset, + _globalDelegatedStake_slot, + _globalDelegatedStake_offset, slot, offset ) From ac75053f697bbadb1d748ded31ad3946c4d47e1a Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sat, 5 Oct 2019 21:01:33 -0700 Subject: [PATCH 48/87] Remove unused rich revert --- .../contracts/src/libs/LibStakingRichErrors.sol | 15 --------------- packages/order-utils/src/staking_revert_errors.ts | 7 ------- 2 files changed, 22 deletions(-) diff --git a/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol b/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol index 4051b44bda..ad8ceec25a 100644 --- a/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol +++ b/contracts/staking/contracts/src/libs/LibStakingRichErrors.sol @@ -92,10 +92,6 @@ library LibStakingRichErrors { bytes4 internal constant POOL_EXISTENCE_ERROR_SELECTOR = 0x9ae94f01; - // bytes4(keccak256("InvalidStakeStatusError(uint8)")) - bytes4 internal constant INVALID_STAKE_STATUS_ERROR_SELECTOR = - 0x7cf20260; - // bytes4(keccak256("ProxyDestinationCannotBeNilError()")) bytes internal constant PROXY_DESTINATION_CANNOT_BE_NIL_ERROR = hex"6eff8285"; @@ -268,17 +264,6 @@ library LibStakingRichErrors { ); } - function InvalidStakeStatusError(IStructs.StakeStatus status) - internal - pure - returns (bytes memory) - { - return abi.encodeWithSelector( - INVALID_STAKE_STATUS_ERROR_SELECTOR, - status - ); - } - function InitializationError(InitializationErrorCodes code) internal pure diff --git a/packages/order-utils/src/staking_revert_errors.ts b/packages/order-utils/src/staking_revert_errors.ts index 5b30bd5bb5..4298ca0f5d 100644 --- a/packages/order-utils/src/staking_revert_errors.ts +++ b/packages/order-utils/src/staking_revert_errors.ts @@ -142,12 +142,6 @@ export class InvalidParamValueError extends RevertError { } } -export class InvalidStakeStatusError extends RevertError { - constructor(status?: BigNumber | number | string) { - super('InvalidStakeStatusError', 'InvalidStakeStatusError(uint8 status)', { status }); - } -} - export class InvalidProtocolFeePaymentError extends RevertError { constructor( errorCode?: ProtocolFeePaymentErrorCodes, @@ -190,7 +184,6 @@ const types = [ InitializationError, InsufficientBalanceError, InvalidProtocolFeePaymentError, - InvalidStakeStatusError, InvalidParamValueError, MakerPoolAssignmentError, OnlyCallableByExchangeError, From 1626566f936b7a90050767984e3c50476427d76d Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Tue, 8 Oct 2019 10:43:28 +0900 Subject: [PATCH 49/87] Change getBalanceOfVault => getBalanceOfZrxVault --- contracts/staking/contracts/src/ZrxVault.sol | 2 +- contracts/staking/contracts/src/interfaces/IZrxVault.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/staking/contracts/src/ZrxVault.sol b/contracts/staking/contracts/src/ZrxVault.sol index 5fca36d9b1..f57400a4b4 100644 --- a/contracts/staking/contracts/src/ZrxVault.sol +++ b/contracts/staking/contracts/src/ZrxVault.sol @@ -188,7 +188,7 @@ contract ZrxVault is } /// @dev Returns the entire balance of Zrx tokens in the vault. - function balanceOfVault() + function balanceOfZrxVault() external view returns (uint256) diff --git a/contracts/staking/contracts/src/interfaces/IZrxVault.sol b/contracts/staking/contracts/src/interfaces/IZrxVault.sol index efe7a4b0c7..f1528f45ec 100644 --- a/contracts/staking/contracts/src/interfaces/IZrxVault.sol +++ b/contracts/staking/contracts/src/interfaces/IZrxVault.sol @@ -97,7 +97,7 @@ interface IZrxVault { returns (uint256); /// @dev Returns the entire balance of Zrx tokens in the vault. - function balanceOfVault() + function balanceOfZrxVault() external view returns (uint256); From cbd0ca4b6037550996297ee95982b038dcc3d30d Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Tue, 8 Oct 2019 10:44:44 +0900 Subject: [PATCH 50/87] Make currentEpoch uint64 type, change INACTIVE => UNDELEGATED, and make global balances state a mapping from uin8 => StoredBalance --- .../staking/contracts/src/immutable/MixinStorage.sol | 6 ++++-- .../staking/contracts/src/interfaces/IStructs.sol | 4 ++-- contracts/staking/contracts/src/stake/MixinStake.sol | 10 +++++----- .../contracts/src/stake/MixinStakeBalances.sol | 12 +++++++----- .../contracts/src/stake/MixinStakeStorage.sol | 2 +- .../staking/contracts/test/TestProtocolFees.sol | 4 ++-- .../contracts/test/TestStorageLayoutAndConstants.sol | 4 ++-- 7 files changed, 23 insertions(+), 19 deletions(-) diff --git a/contracts/staking/contracts/src/immutable/MixinStorage.sol b/contracts/staking/contracts/src/immutable/MixinStorage.sol index ce48e2c19e..7c63953732 100644 --- a/contracts/staking/contracts/src/immutable/MixinStorage.sol +++ b/contracts/staking/contracts/src/immutable/MixinStorage.sol @@ -41,9 +41,11 @@ contract MixinStorage is // address for read-only proxy to call address public readOnlyProxyCallee; - // amount of stake currently being delegated in the system + // mapping from StakeStatus to gloabl stored balance // (access using _loadSyncedBalance or _loadUnsyncedBalance) - IStructs.StoredBalance internal _globalDelegatedStake; + // NOTE: only Status.DELEGATED is used to access this mapping, but this format + // is used for extensibility + mapping (uint8 => IStructs.StoredBalance) internal _globalStakeByStatus; // mapping from StakeStatus to address of staker to stored balance // (access using _loadSyncedBalance or _loadUnsyncedBalance) diff --git a/contracts/staking/contracts/src/interfaces/IStructs.sol b/contracts/staking/contracts/src/interfaces/IStructs.sol index b30baea2a5..b0c2fec9d8 100644 --- a/contracts/staking/contracts/src/interfaces/IStructs.sol +++ b/contracts/staking/contracts/src/interfaces/IStructs.sol @@ -57,7 +57,7 @@ interface IStructs { /// @param currentEpochBalance balance in the current epoch. /// @param nextEpochBalance balance in `currentEpoch+1`. struct StoredBalance { - uint32 currentEpoch; + uint64 currentEpoch; uint96 currentEpochBalance; uint96 nextEpochBalance; } @@ -66,7 +66,7 @@ interface IStructs { /// Any stake can be (re)delegated effective at the next epoch /// Inactive stake can be withdrawn if it is available in both the current and next epoch enum StakeStatus { - INACTIVE, + UNDELEGATED, DELEGATED } diff --git a/contracts/staking/contracts/src/stake/MixinStake.sol b/contracts/staking/contracts/src/stake/MixinStake.sol index 1e4101e459..31d1ed2f7a 100644 --- a/contracts/staking/contracts/src/stake/MixinStake.sol +++ b/contracts/staking/contracts/src/stake/MixinStake.sol @@ -42,7 +42,7 @@ contract MixinStake is // mint stake _increaseCurrentAndNextBalance( - _ownerStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)][staker], + _ownerStakeByStatus[uint8(IStructs.StakeStatus.UNDELEGATED)][staker], amount ); @@ -63,7 +63,7 @@ contract MixinStake is address staker = msg.sender; IStructs.StoredBalance memory inactiveBalance = - _loadSyncedBalance(_ownerStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)][staker]); + _loadSyncedBalance(_ownerStakeByStatus[uint8(IStructs.StakeStatus.UNDELEGATED)][staker]); // stake must be inactive in current and next epoch to be withdrawn uint256 currentWithdrawableStake = LibSafeMath.min256( @@ -82,7 +82,7 @@ contract MixinStake is // burn inactive stake _decreaseCurrentAndNextBalance( - _ownerStakeByStatus[uint8(IStructs.StakeStatus.INACTIVE)][staker], + _ownerStakeByStatus[uint8(IStructs.StakeStatus.UNDELEGATED)][staker], amount ); @@ -181,7 +181,7 @@ contract MixinStake is // Increase next balance of global delegated stake _increaseNextBalance( - _globalDelegatedStake, + _globalStakeByStatus[uint8(IStructs.StakeStatus.DELEGATED)], amount ); } @@ -219,7 +219,7 @@ contract MixinStake is // decrease next balance of global delegated stake _decreaseNextBalance( - _globalDelegatedStake, + _globalStakeByStatus[uint8(IStructs.StakeStatus.DELEGATED)], amount ); } diff --git a/contracts/staking/contracts/src/stake/MixinStakeBalances.sol b/contracts/staking/contracts/src/stake/MixinStakeBalances.sol index 1a852052f5..0df40c4eab 100644 --- a/contracts/staking/contracts/src/stake/MixinStakeBalances.sol +++ b/contracts/staking/contracts/src/stake/MixinStakeBalances.sol @@ -30,18 +30,20 @@ contract MixinStakeBalances is using LibSafeMath for uint256; /// @dev Gets global stake for a given status. - /// @param stakeStatus INACTIVE or DELEGATED + /// @param stakeStatus UNDELEGATED or DELEGATED /// @return Global stake for given status. function getGlobalStakeByStatus(IStructs.StakeStatus stakeStatus) external view returns (IStructs.StoredBalance memory balance) { - balance = _loadSyncedBalance(_globalDelegatedStake); - if (stakeStatus == IStructs.StakeStatus.INACTIVE) { + balance = _loadSyncedBalance( + _globalStakeByStatus[uint8(IStructs.StakeStatus.DELEGATED)] + ); + if (stakeStatus == IStructs.StakeStatus.UNDELEGATED) { // Inactive stake is the difference between total stake and delegated stake // Note that any Zrx erroneously sent to the vault will be counted as inactive stake - uint256 totalStake = getZrxVault().balanceOfVault(); + uint256 totalStake = getZrxVault().balanceOfZrxVault(); balance.currentEpochBalance = totalStake.safeSub(balance.currentEpochBalance).downcastToUint96(); balance.nextEpochBalance = totalStake.safeSub(balance.nextEpochBalance).downcastToUint96(); } @@ -50,7 +52,7 @@ contract MixinStakeBalances is /// @dev Gets an owner's stake balances by status. /// @param staker Owner of stake. - /// @param stakeStatus INACTIVE or DELEGATED + /// @param stakeStatus UNDELEGATED or DELEGATED /// @return Owner's stake balances for given status. function getOwnerStakeByStatus( address staker, diff --git a/contracts/staking/contracts/src/stake/MixinStakeStorage.sol b/contracts/staking/contracts/src/stake/MixinStakeStorage.sol index 3cd89d9407..2c9c187dfc 100644 --- a/contracts/staking/contracts/src/stake/MixinStakeStorage.sol +++ b/contracts/staking/contracts/src/stake/MixinStakeStorage.sol @@ -87,7 +87,7 @@ contract MixinStakeStorage is // sync uint256 currentEpoch_ = currentEpoch; if (currentEpoch_ > balance.currentEpoch) { - balance.currentEpoch = currentEpoch_.downcastToUint32(); + balance.currentEpoch = currentEpoch_.downcastToUint64(); balance.currentEpochBalance = balance.nextEpochBalance; } return balance; diff --git a/contracts/staking/contracts/test/TestProtocolFees.sol b/contracts/staking/contracts/test/TestProtocolFees.sol index 6d44d7ce53..a6091e19a8 100644 --- a/contracts/staking/contracts/test/TestProtocolFees.sol +++ b/contracts/staking/contracts/test/TestProtocolFees.sol @@ -104,7 +104,7 @@ contract TestProtocolFees is TestPool memory pool = _testPools[poolId]; uint96 stake = pool.operatorStake + pool.membersStake; return IStructs.StoredBalance({ - currentEpoch: currentEpoch.downcastToUint32(), + currentEpoch: currentEpoch.downcastToUint64(), currentEpochBalance: stake, nextEpochBalance: stake }); @@ -118,7 +118,7 @@ contract TestProtocolFees is { TestPool memory pool = _testPools[poolId]; return IStructs.StoredBalance({ - currentEpoch: currentEpoch.downcastToUint32(), + currentEpoch: currentEpoch.downcastToUint64(), currentEpochBalance: pool.operatorStake, nextEpochBalance: pool.operatorStake }); diff --git a/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol b/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol index 2824b30a34..2ec0a0f54e 100644 --- a/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol +++ b/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol @@ -119,8 +119,8 @@ contract TestStorageLayoutAndConstants is slot := add(slot, 0x1) assertSlotAndOffset( - _globalDelegatedStake_slot, - _globalDelegatedStake_offset, + _globalStakeByStatus_slot, + _globalStakeByStatus_offset, slot, offset ) From 701b203c587c331affbca19175375035c4b26a92 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Tue, 8 Oct 2019 10:45:01 +0900 Subject: [PATCH 51/87] Fix tests --- contracts/staking/test/actors/staker_actor.ts | 10 +-- contracts/staking/test/catastrophe_test.ts | 8 +-- contracts/staking/test/rewards_test.ts | 26 ++++---- contracts/staking/test/stake_test.ts | 64 ++++++++++--------- .../cumulative_reward_tracking_simulation.ts | 4 +- contracts/staking/test/utils/types.ts | 4 +- 6 files changed, 60 insertions(+), 56 deletions(-) diff --git a/contracts/staking/test/actors/staker_actor.ts b/contracts/staking/test/actors/staker_actor.ts index 0f71575114..22edb7d812 100644 --- a/contracts/staking/test/actors/staker_actor.ts +++ b/contracts/staking/test/actors/staker_actor.ts @@ -148,7 +148,7 @@ export class StakerActor extends BaseActor { public async stakeWithPoolAsync(poolId: string, amount: BigNumber): Promise { await this.stakeAsync(amount); await this.moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolId), amount, ); @@ -202,14 +202,14 @@ export class StakerActor extends BaseActor { stakeBalanceInVault: await this._stakingApiWrapper.zrxVaultContract.balanceOf.callAsync(this._owner), inactiveStakeBalance: await this._stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( this._owner, - StakeStatus.Inactive, + StakeStatus.Undelegated, ), delegatedStakeBalance: await this._stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( this._owner, StakeStatus.Delegated, ), globalInactiveStakeBalance: await this._stakingApiWrapper.stakingContract.getGlobalStakeByStatus.callAsync( - StakeStatus.Inactive, + StakeStatus.Undelegated, ), globalDelegatedStakeBalance: await this._stakingApiWrapper.stakingContract.getGlobalStakeByStatus.callAsync( StakeStatus.Delegated, @@ -289,7 +289,7 @@ export class StakerActor extends BaseActor { // @TODO check receipt logs and return value via eth_call // check balances // from - if (from.status === StakeStatus.Inactive) { + if (from.status === StakeStatus.Undelegated) { StakerActor._decrementNextBalance(expectedBalances.inactiveStakeBalance, amount); StakerActor._decrementNextBalance(expectedBalances.globalInactiveStakeBalance, amount); } else if (from.status === StakeStatus.Delegated && from.poolId !== undefined) { @@ -299,7 +299,7 @@ export class StakerActor extends BaseActor { StakerActor._decrementNextBalance(expectedBalances.totalDelegatedStakeByPool[from.poolId], amount); } // to - if (to.status === StakeStatus.Inactive) { + if (to.status === StakeStatus.Undelegated) { StakerActor._incrementNextBalance(expectedBalances.inactiveStakeBalance, amount); StakerActor._incrementNextBalance(expectedBalances.globalInactiveStakeBalance, amount); } else if (to.status === StakeStatus.Delegated && to.poolId !== undefined) { diff --git a/contracts/staking/test/catastrophe_test.ts b/contracts/staking/test/catastrophe_test.ts index 727ac935ac..062a36695d 100644 --- a/contracts/staking/test/catastrophe_test.ts +++ b/contracts/staking/test/catastrophe_test.ts @@ -42,7 +42,7 @@ blockchainTests.resets('Catastrophe Tests', env => { }); const inactiveStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( actors[0], - StakeStatus.Inactive, + StakeStatus.Undelegated, ); expect(inactiveStakeBalance.currentEpochBalance).to.be.bignumber.equal(amountToStake); }); @@ -56,7 +56,7 @@ blockchainTests.resets('Catastrophe Tests', env => { }); const inactiveStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( actors[0], - StakeStatus.Inactive, + StakeStatus.Undelegated, ); expect(inactiveStakeBalance.currentEpochBalance).to.be.bignumber.equal(ZERO); }); @@ -71,7 +71,7 @@ blockchainTests.resets('Catastrophe Tests', env => { // read stake balance in read-only mode const inactiveStakeBalanceReadOnly = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( actors[0], - StakeStatus.Inactive, + StakeStatus.Undelegated, ); expect(inactiveStakeBalanceReadOnly.currentEpochBalance).to.be.bignumber.equal(amountToStake); }); @@ -86,7 +86,7 @@ blockchainTests.resets('Catastrophe Tests', env => { }); const inactiveStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( actors[0], - StakeStatus.Inactive, + StakeStatus.Undelegated, ); expect(inactiveStakeBalance.currentEpochBalance).to.be.bignumber.equal(amountToStake); }); diff --git a/contracts/staking/test/rewards_test.ts b/contracts/staking/test/rewards_test.ts index 0940ed16b3..1fdc68ff90 100644 --- a/contracts/staking/test/rewards_test.ts +++ b/contracts/staking/test/rewards_test.ts @@ -176,7 +176,7 @@ blockchainTests.resets('Testing Rewards', env => { const amount = toBaseUnitAmount(4); await stakers[0].stakeAsync(amount); await stakers[0].moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolId), amount, ); @@ -248,7 +248,7 @@ blockchainTests.resets('Testing Rewards', env => { const totalStakeAmount = toBaseUnitAmount(10); await stakers[0].stakeAsync(stakeAmounts[0]); await stakers[0].moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolId), stakeAmounts[0], ); @@ -259,7 +259,7 @@ blockchainTests.resets('Testing Rewards', env => { // second staker delegates (epoch 1) await stakers[1].stakeAsync(stakeAmounts[1]); await stakers[1].moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolId), stakeAmounts[1], ); @@ -355,7 +355,7 @@ blockchainTests.resets('Testing Rewards', env => { // undelegate (withdraws delegator's rewards) await stakers[0].moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolId), - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), stakeAmount, ); // sanity check final balances @@ -436,7 +436,7 @@ blockchainTests.resets('Testing Rewards', env => { // undelegate stake and finalize epoch await stakers[0].moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolId), - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), stakeAmount, ); @@ -472,7 +472,7 @@ blockchainTests.resets('Testing Rewards', env => { // undelegate stake and finalize epoch await stakers[0].moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolId), - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), stakeAmount, ); await payProtocolFeeAndFinalize(); @@ -499,7 +499,7 @@ blockchainTests.resets('Testing Rewards', env => { // undelegate stake and finalize epoch await stakers[0].moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolId), - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), stakeAmount, ); await payProtocolFeeAndFinalize(); @@ -507,7 +507,7 @@ blockchainTests.resets('Testing Rewards', env => { await payProtocolFeeAndFinalize(rewardNotForDelegator); // delegate stake and go to next epoch await stakers[0].moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolId), stakeAmount, ); @@ -530,7 +530,7 @@ blockchainTests.resets('Testing Rewards', env => { const stakeAmount = toBaseUnitAmount(4); await stakers[0].stakeAsync(stakeAmount); await stakers[0].moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolId), stakeAmount, ); @@ -539,7 +539,7 @@ blockchainTests.resets('Testing Rewards', env => { // undelegate stake and finalize epoch await stakers[0].moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolId), - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), stakeAmount, ); // this should go to the delegator @@ -547,7 +547,7 @@ blockchainTests.resets('Testing Rewards', env => { // delegate stake ~ this will result in a payout where rewards are computed on // the balance's `currentEpochBalance` field but not the `nextEpochBalance` field. await stakers[0].moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolId), stakeAmount, ); @@ -565,7 +565,7 @@ blockchainTests.resets('Testing Rewards', env => { const stakeAmount = toBaseUnitAmount(4); await stakers[0].stakeAsync(stakeAmount); await stakers[0].moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolId), stakeAmount, ); @@ -595,7 +595,7 @@ blockchainTests.resets('Testing Rewards', env => { const undelegateAmount = toBaseUnitAmount(2.5); await staker.moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolId), - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), undelegateAmount, ); // finalize diff --git a/contracts/staking/test/stake_test.ts b/contracts/staking/test/stake_test.ts index e5839c1d15..5d4e0c95fb 100644 --- a/contracts/staking/test/stake_test.ts +++ b/contracts/staking/test/stake_test.ts @@ -77,14 +77,14 @@ blockchainTests.resets('Stake Statuses', env => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); // still epoch 1 ~ should be able to move stake again await staker.moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolIds[0]), - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), amount, ); }); @@ -93,7 +93,7 @@ blockchainTests.resets('Stake Statuses', env => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); @@ -109,13 +109,13 @@ blockchainTests.resets('Stake Statuses', env => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); // stake is now inactive, should not be able to move it out of active status again await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[1]), amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO), @@ -127,14 +127,14 @@ blockchainTests.resets('Stake Statuses', env => { // epoch 1 const amount = toBaseUnitAmount(10); await staker.stakeAndMoveAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); // still epoch 1 ~ should be able to move stake again await staker.moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolIds[0]), - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), amount, ); }); @@ -142,13 +142,13 @@ blockchainTests.resets('Stake Statuses', env => { // epoch 1 const amount = toBaseUnitAmount(10); await staker.stakeAndMoveAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); // stake is now inactive, should not be able to move it out of active status again await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[1]), amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO), @@ -157,11 +157,15 @@ blockchainTests.resets('Stake Statuses', env => { }); describe('Move Zero Stake', () => { it('inactive -> inactive', async () => { - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Inactive), ZERO); + await staker.moveStakeAsync( + new StakeInfo(StakeStatus.Undelegated), + new StakeInfo(StakeStatus.Undelegated), + ZERO, + ); }); it('inactive -> delegated', async () => { await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[0]), ZERO, ); @@ -169,7 +173,7 @@ blockchainTests.resets('Stake Statuses', env => { it('delegated -> inactive', async () => { await staker.moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolIds[0]), - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), ZERO, ); }); @@ -193,8 +197,8 @@ blockchainTests.resets('Stake Statuses', env => { // setup const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); - if (from.status !== StakeStatus.Inactive) { - await staker.moveStakeAsync(new StakeInfo(StakeStatus.Inactive), from, amount); + if (from.status !== StakeStatus.Undelegated) { + await staker.moveStakeAsync(new StakeInfo(StakeStatus.Undelegated), from, amount); } // run test, checking balances in epochs [n .. n + 2] // in epoch `n` - `next` is set @@ -203,18 +207,18 @@ blockchainTests.resets('Stake Statuses', env => { await staker.goToNextEpochAsync(); }; it('inactive -> inactive', async () => { - await testMovePartialStake(new StakeInfo(StakeStatus.Inactive), new StakeInfo(StakeStatus.Inactive)); + await testMovePartialStake(new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Undelegated)); }); it('inactive -> delegated', async () => { await testMovePartialStake( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[0]), ); }); it('delegated -> inactive', async () => { await testMovePartialStake( new StakeInfo(StakeStatus.Delegated, poolIds[0]), - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), ); }); it('delegated -> delegated (same pool)', async () => { @@ -233,7 +237,7 @@ blockchainTests.resets('Stake Statuses', env => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, unusedPoolId), amount, new StakingRevertErrors.PoolExistenceError(unusedPoolId, false), @@ -243,7 +247,7 @@ blockchainTests.resets('Stake Statuses', env => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); @@ -264,13 +268,13 @@ blockchainTests.resets('Stake Statuses', env => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); await staker.moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolIds[0]), - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), amount, ); await staker.goToNextEpochAsync(); // stake is now inactive @@ -280,14 +284,14 @@ blockchainTests.resets('Stake Statuses', env => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); await staker.goToNextEpochAsync(); // stake is now delegated await staker.moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolIds[0]), - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), amount, ); await staker.unstakeAsync(amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO)); @@ -296,7 +300,7 @@ blockchainTests.resets('Stake Statuses', env => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); @@ -306,7 +310,7 @@ blockchainTests.resets('Stake Statuses', env => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); @@ -317,7 +321,7 @@ blockchainTests.resets('Stake Statuses', env => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); @@ -338,7 +342,7 @@ blockchainTests.resets('Stake Statuses', env => { // // Later in Epoch 1: User delegates and deactivates some stake // await staker.moveStakeAsync( // new StakeInfo(StakeStatus.Active), - // new StakeInfo(StakeStatus.Inactive), + // new StakeInfo(StakeStatus.Undelegated), // toBaseUnitAmount(1), // ); // await staker.moveStakeAsync( @@ -352,7 +356,7 @@ blockchainTests.resets('Stake Statuses', env => { // await staker.goToNextEpochAsync(); // // Later in Epoch 3: User reactivates half of their inactive stake; this becomes Active next epoch // await staker.moveStakeAsync( - // new StakeInfo(StakeStatus.Inactive), + // new StakeInfo(StakeStatus.Undelegated), // new StakeInfo(StakeStatus.Active), // toBaseUnitAmount(0.5), // ); @@ -367,7 +371,7 @@ blockchainTests.resets('Stake Statuses', env => { // // Later in Epoch 4: User deactivates all active stake // await staker.moveStakeAsync( // new StakeInfo(StakeStatus.Active), - // new StakeInfo(StakeStatus.Inactive), + // new StakeInfo(StakeStatus.Undelegated), // toBaseUnitAmount(1.5), // ); // // Later in Epoch 4: User withdraws all available inactive stake @@ -376,7 +380,7 @@ blockchainTests.resets('Stake Statuses', env => { // await staker.goToNextEpochAsync(); // // Later in Epoch 5: User reactivates a portion of their stake // await staker.moveStakeAsync( - // new StakeInfo(StakeStatus.Inactive), + // new StakeInfo(StakeStatus.Undelegated), // new StakeInfo(StakeStatus.Active), // toBaseUnitAmount(1), // ); diff --git a/contracts/staking/test/utils/cumulative_reward_tracking_simulation.ts b/contracts/staking/test/utils/cumulative_reward_tracking_simulation.ts index 9bcadbd674..f92406c207 100644 --- a/contracts/staking/test/utils/cumulative_reward_tracking_simulation.ts +++ b/contracts/staking/test/utils/cumulative_reward_tracking_simulation.ts @@ -120,7 +120,7 @@ export class CumulativeRewardTrackingSimulation { from: this._staker, }); receipt = await this._stakingApiWrapper.stakingContract.moveStake.awaitTransactionSuccessAsync( - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, this._poolId), this._amountToStake, { from: this._staker }, @@ -130,7 +130,7 @@ export class CumulativeRewardTrackingSimulation { case TestAction.Undelegate: receipt = await this._stakingApiWrapper.stakingContract.moveStake.awaitTransactionSuccessAsync( new StakeInfo(StakeStatus.Delegated, this._poolId), - new StakeInfo(StakeStatus.Inactive), + new StakeInfo(StakeStatus.Undelegated), this._amountToStake, { from: this._staker }, ); diff --git a/contracts/staking/test/utils/types.ts b/contracts/staking/test/utils/types.ts index 9d36c818e0..647e26e043 100644 --- a/contracts/staking/test/utils/types.ts +++ b/contracts/staking/test/utils/types.ts @@ -58,7 +58,7 @@ export interface EndOfEpochInfo { } export interface StoredBalance { - currentEpoch: number | BigNumber; + currentEpoch: BigNumber; currentEpochBalance: BigNumber; nextEpochBalance: BigNumber; } @@ -68,7 +68,7 @@ export interface StakeBalanceByPool { } export enum StakeStatus { - Inactive, + Undelegated, Delegated, } From 681e6eab7a294b8670a139a7ae5092e6db01ffb0 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Tue, 8 Oct 2019 11:37:36 +0900 Subject: [PATCH 52/87] Cleanup language used in comments and variable names --- .../contracts/src/interfaces/IStaking.sol | 3 +- .../contracts/src/interfaces/IStructs.sol | 2 +- .../contracts/src/stake/MixinStake.sol | 17 ++++--- .../src/stake/MixinStakeBalances.sol | 4 +- .../contracts/src/stake/MixinStakeStorage.sol | 2 +- contracts/staking/test/actors/staker_actor.ts | 50 ++++++++++--------- contracts/staking/test/catastrophe_test.ts | 16 +++--- contracts/staking/test/stake_test.ts | 40 +++++++-------- contracts/staking/test/utils/types.ts | 4 +- 9 files changed, 71 insertions(+), 67 deletions(-) diff --git a/contracts/staking/contracts/src/interfaces/IStaking.sol b/contracts/staking/contracts/src/interfaces/IStaking.sol index de938c2364..e5b3d9135e 100644 --- a/contracts/staking/contracts/src/interfaces/IStaking.sol +++ b/contracts/staking/contracts/src/interfaces/IStaking.sol @@ -24,7 +24,8 @@ import "./IStructs.sol"; interface IStaking { - /// @dev Moves stake between statuses: 'active', 'inactive' or 'delegated'. + /// @dev Moves stake between statuses: 'undelegated' or 'delegated'. + /// Delegated stake can also be moved between pools. /// This change comes into effect next epoch. /// @param from status to move stake out of. /// @param to status to move stake into. diff --git a/contracts/staking/contracts/src/interfaces/IStructs.sol b/contracts/staking/contracts/src/interfaces/IStructs.sol index b0c2fec9d8..8e19b52998 100644 --- a/contracts/staking/contracts/src/interfaces/IStructs.sol +++ b/contracts/staking/contracts/src/interfaces/IStructs.sol @@ -64,7 +64,7 @@ interface IStructs { /// @dev Statuses that stake can exist in. /// Any stake can be (re)delegated effective at the next epoch - /// Inactive stake can be withdrawn if it is available in both the current and next epoch + /// Undelegated stake can be withdrawn if it is available in both the current and next epoch enum StakeStatus { UNDELEGATED, DELEGATED diff --git a/contracts/staking/contracts/src/stake/MixinStake.sol b/contracts/staking/contracts/src/stake/MixinStake.sol index 31d1ed2f7a..da9542b08f 100644 --- a/contracts/staking/contracts/src/stake/MixinStake.sol +++ b/contracts/staking/contracts/src/stake/MixinStake.sol @@ -54,21 +54,21 @@ contract MixinStake is } /// @dev Unstake. Tokens are withdrawn from the ZRX Vault and returned to - /// the staker. Stake must be in the 'inactive' status for at least - /// one full epoch to unstake. + /// the staker. Stake must be in the 'undelegated' status in both the + /// current and next epoch in order to be unstaked. /// @param amount of ZRX to unstake. function unstake(uint256 amount) external { address staker = msg.sender; - IStructs.StoredBalance memory inactiveBalance = + IStructs.StoredBalance memory undelegatedBalance = _loadSyncedBalance(_ownerStakeByStatus[uint8(IStructs.StakeStatus.UNDELEGATED)][staker]); - // stake must be inactive in current and next epoch to be withdrawn + // stake must be undelegated in current and next epoch to be withdrawn uint256 currentWithdrawableStake = LibSafeMath.min256( - inactiveBalance.currentEpochBalance, - inactiveBalance.nextEpochBalance + undelegatedBalance.currentEpochBalance, + undelegatedBalance.nextEpochBalance ); if (amount > currentWithdrawableStake) { @@ -80,7 +80,7 @@ contract MixinStake is ); } - // burn inactive stake + // burn undelegated stake _decreaseCurrentAndNextBalance( _ownerStakeByStatus[uint8(IStructs.StakeStatus.UNDELEGATED)][staker], amount @@ -96,7 +96,8 @@ contract MixinStake is ); } - /// @dev Moves stake between statuses: 'active', 'inactive' or 'delegated'. + /// @dev Moves stake between statuses: 'undelegated' or 'delegated'. + /// Delegated stake can also be moved between pools. /// This change comes into effect next epoch. /// @param from status to move stake out of. /// @param to status to move stake into. diff --git a/contracts/staking/contracts/src/stake/MixinStakeBalances.sol b/contracts/staking/contracts/src/stake/MixinStakeBalances.sol index 0df40c4eab..87e275a207 100644 --- a/contracts/staking/contracts/src/stake/MixinStakeBalances.sol +++ b/contracts/staking/contracts/src/stake/MixinStakeBalances.sol @@ -41,8 +41,8 @@ contract MixinStakeBalances is _globalStakeByStatus[uint8(IStructs.StakeStatus.DELEGATED)] ); if (stakeStatus == IStructs.StakeStatus.UNDELEGATED) { - // Inactive stake is the difference between total stake and delegated stake - // Note that any Zrx erroneously sent to the vault will be counted as inactive stake + // Undelegated stake is the difference between total stake and delegated stake + // Note that any ZRX erroneously sent to the vault will be counted as undelegated stake uint256 totalStake = getZrxVault().balanceOfZrxVault(); balance.currentEpochBalance = totalStake.safeSub(balance.currentEpochBalance).downcastToUint96(); balance.nextEpochBalance = totalStake.safeSub(balance.nextEpochBalance).downcastToUint96(); diff --git a/contracts/staking/contracts/src/stake/MixinStakeStorage.sol b/contracts/staking/contracts/src/stake/MixinStakeStorage.sol index 2c9c187dfc..6c815d0205 100644 --- a/contracts/staking/contracts/src/stake/MixinStakeStorage.sol +++ b/contracts/staking/contracts/src/stake/MixinStakeStorage.sol @@ -31,7 +31,7 @@ contract MixinStakeStorage is using LibSafeMath for uint256; using LibSafeDowncast for uint256; - /// @dev Moves stake between states: 'active', 'inactive' or 'delegated'. + /// @dev Moves stake between states: 'undelegated' or 'delegated'. /// This change comes into effect next epoch. /// @param fromPtr pointer to storage location of `from` stake. /// @param toPtr pointer to storage location of `to` stake. diff --git a/contracts/staking/test/actors/staker_actor.ts b/contracts/staking/test/actors/staker_actor.ts index 22edb7d812..469f235730 100644 --- a/contracts/staking/test/actors/staker_actor.ts +++ b/contracts/staking/test/actors/staker_actor.ts @@ -106,8 +106,8 @@ export class StakerActor extends BaseActor { const expectedBalances = initBalances; expectedBalances.zrxBalance = initBalances.zrxBalance.plus(amount); expectedBalances.stakeBalanceInVault = initBalances.stakeBalanceInVault.minus(amount); - StakerActor._decrementCurrentAndNextBalance(expectedBalances.inactiveStakeBalance, amount); - StakerActor._decrementCurrentAndNextBalance(expectedBalances.globalInactiveStakeBalance, amount); + StakerActor._decrementCurrentAndNextBalance(expectedBalances.undelegatedStakeBalance, amount); + StakerActor._decrementCurrentAndNextBalance(expectedBalances.globalUndelegatedStakeBalance, amount); await this._assertBalancesAsync(expectedBalances); // check zrx balance of vault const finalZrxBalanceOfVault = await this._stakingApiWrapper.utils.getZrxTokenBalanceOfZrxVaultAsync(); @@ -182,9 +182,9 @@ export class StakerActor extends BaseActor { private _getNextEpochBalances(balances: StakeBalances): StakeBalances { const nextBalances = _.cloneDeep(balances); for (const balance of [ - nextBalances.inactiveStakeBalance, + nextBalances.undelegatedStakeBalance, nextBalances.delegatedStakeBalance, - nextBalances.globalInactiveStakeBalance, + nextBalances.globalUndelegatedStakeBalance, nextBalances.globalDelegatedStakeBalance, ...this._poolIds.map(poolId => nextBalances.delegatedStakeByPool[poolId]), ...this._poolIds.map(poolId => nextBalances.totalDelegatedStakeByPool[poolId]), @@ -200,7 +200,7 @@ export class StakerActor extends BaseActor { zrxBalance: await this._stakingApiWrapper.zrxTokenContract.balanceOf.callAsync(this._owner), stakeBalance: await this._stakingApiWrapper.stakingContract.getTotalStake.callAsync(this._owner), stakeBalanceInVault: await this._stakingApiWrapper.zrxVaultContract.balanceOf.callAsync(this._owner), - inactiveStakeBalance: await this._stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( + undelegatedStakeBalance: await this._stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( this._owner, StakeStatus.Undelegated, ), @@ -208,7 +208,7 @@ export class StakerActor extends BaseActor { this._owner, StakeStatus.Delegated, ), - globalInactiveStakeBalance: await this._stakingApiWrapper.stakingContract.getGlobalStakeByStatus.callAsync( + globalUndelegatedStakeBalance: await this._stakingApiWrapper.stakingContract.getGlobalStakeByStatus.callAsync( StakeStatus.Undelegated, ), globalDelegatedStakeBalance: await this._stakingApiWrapper.stakingContract.getGlobalStakeByStatus.callAsync( @@ -238,12 +238,13 @@ export class StakerActor extends BaseActor { expectedBalances.stakeBalanceInVault, ); expect( - balances.inactiveStakeBalance.currentEpochBalance, - 'inactive stake balance (current)', - ).to.be.bignumber.equal(expectedBalances.inactiveStakeBalance.currentEpochBalance); - expect(balances.inactiveStakeBalance.nextEpochBalance, 'inactive stake balance (next)').to.be.bignumber.equal( - expectedBalances.inactiveStakeBalance.nextEpochBalance, - ); + balances.undelegatedStakeBalance.currentEpochBalance, + 'undelegated stake balance (current)', + ).to.be.bignumber.equal(expectedBalances.undelegatedStakeBalance.currentEpochBalance); + expect( + balances.undelegatedStakeBalance.nextEpochBalance, + 'undelegated stake balance (next)', + ).to.be.bignumber.equal(expectedBalances.undelegatedStakeBalance.nextEpochBalance); expect( balances.delegatedStakeBalance.currentEpochBalance, 'delegated stake balance (current)', @@ -252,16 +253,17 @@ export class StakerActor extends BaseActor { expectedBalances.delegatedStakeBalance.nextEpochBalance, ); expect( - balances.globalInactiveStakeBalance.currentEpochBalance, - 'global inactive stake (current)', - ).to.bignumber.equal(expectedBalances.globalInactiveStakeBalance.currentEpochBalance); + balances.globalUndelegatedStakeBalance.currentEpochBalance, + 'global undelegated stake (current)', + ).to.bignumber.equal(expectedBalances.globalUndelegatedStakeBalance.currentEpochBalance); expect( balances.globalDelegatedStakeBalance.currentEpochBalance, 'global delegated stake (current)', ).to.bignumber.equal(expectedBalances.globalDelegatedStakeBalance.currentEpochBalance); - expect(balances.globalInactiveStakeBalance.nextEpochBalance, 'global inactive stake (next)').to.bignumber.equal( - expectedBalances.globalInactiveStakeBalance.nextEpochBalance, - ); + expect( + balances.globalUndelegatedStakeBalance.nextEpochBalance, + 'global undelegated stake (next)', + ).to.bignumber.equal(expectedBalances.globalUndelegatedStakeBalance.nextEpochBalance); expect( balances.globalDelegatedStakeBalance.nextEpochBalance, 'global delegated stake (next)', @@ -290,8 +292,8 @@ export class StakerActor extends BaseActor { // check balances // from if (from.status === StakeStatus.Undelegated) { - StakerActor._decrementNextBalance(expectedBalances.inactiveStakeBalance, amount); - StakerActor._decrementNextBalance(expectedBalances.globalInactiveStakeBalance, amount); + StakerActor._decrementNextBalance(expectedBalances.undelegatedStakeBalance, amount); + StakerActor._decrementNextBalance(expectedBalances.globalUndelegatedStakeBalance, amount); } else if (from.status === StakeStatus.Delegated && from.poolId !== undefined) { StakerActor._decrementNextBalance(expectedBalances.delegatedStakeBalance, amount); StakerActor._decrementNextBalance(expectedBalances.globalDelegatedStakeBalance, amount); @@ -300,8 +302,8 @@ export class StakerActor extends BaseActor { } // to if (to.status === StakeStatus.Undelegated) { - StakerActor._incrementNextBalance(expectedBalances.inactiveStakeBalance, amount); - StakerActor._incrementNextBalance(expectedBalances.globalInactiveStakeBalance, amount); + StakerActor._incrementNextBalance(expectedBalances.undelegatedStakeBalance, amount); + StakerActor._incrementNextBalance(expectedBalances.globalUndelegatedStakeBalance, amount); } else if (to.status === StakeStatus.Delegated && to.poolId !== undefined) { StakerActor._incrementNextBalance(expectedBalances.delegatedStakeBalance, amount); StakerActor._incrementNextBalance(expectedBalances.globalDelegatedStakeBalance, amount); @@ -319,8 +321,8 @@ export class StakerActor extends BaseActor { // check balances expectedBalances.zrxBalance = expectedBalances.zrxBalance.minus(amount); expectedBalances.stakeBalanceInVault = expectedBalances.stakeBalanceInVault.plus(amount); - StakerActor._incrementCurrentAndNextBalance(expectedBalances.inactiveStakeBalance, amount); - StakerActor._incrementCurrentAndNextBalance(expectedBalances.globalInactiveStakeBalance, amount); + StakerActor._incrementCurrentAndNextBalance(expectedBalances.undelegatedStakeBalance, amount); + StakerActor._incrementCurrentAndNextBalance(expectedBalances.globalUndelegatedStakeBalance, amount); return expectedBalances; } } diff --git a/contracts/staking/test/catastrophe_test.ts b/contracts/staking/test/catastrophe_test.ts index 062a36695d..0244de9136 100644 --- a/contracts/staking/test/catastrophe_test.ts +++ b/contracts/staking/test/catastrophe_test.ts @@ -40,11 +40,11 @@ blockchainTests.resets('Catastrophe Tests', env => { await stakingApiWrapper.stakingContract.stake.awaitTransactionSuccessAsync(amountToStake, { from: actors[0], }); - const inactiveStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( + const undelegatedStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( actors[0], StakeStatus.Undelegated, ); - expect(inactiveStakeBalance.currentEpochBalance).to.be.bignumber.equal(amountToStake); + expect(undelegatedStakeBalance.currentEpochBalance).to.be.bignumber.equal(amountToStake); }); it('should not change state when in read-only mode', async () => { // set to read-only mode @@ -54,11 +54,11 @@ blockchainTests.resets('Catastrophe Tests', env => { await stakingApiWrapper.stakingContract.stake.awaitTransactionSuccessAsync(amountToStake, { from: actors[0], }); - const inactiveStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( + const undelegatedStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( actors[0], StakeStatus.Undelegated, ); - expect(inactiveStakeBalance.currentEpochBalance).to.be.bignumber.equal(ZERO); + expect(undelegatedStakeBalance.currentEpochBalance).to.be.bignumber.equal(ZERO); }); it('should read values correctly when in read-only mode', async () => { // stake some zrx @@ -69,11 +69,11 @@ blockchainTests.resets('Catastrophe Tests', env => { // set to read-only mode await stakingApiWrapper.stakingProxyContract.setReadOnlyMode.awaitTransactionSuccessAsync(true); // read stake balance in read-only mode - const inactiveStakeBalanceReadOnly = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( + const undelegatedStakeBalanceReadOnly = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( actors[0], StakeStatus.Undelegated, ); - expect(inactiveStakeBalanceReadOnly.currentEpochBalance).to.be.bignumber.equal(amountToStake); + expect(undelegatedStakeBalanceReadOnly.currentEpochBalance).to.be.bignumber.equal(amountToStake); }); it('should exit read-only mode', async () => { // set to read-only mode @@ -84,11 +84,11 @@ blockchainTests.resets('Catastrophe Tests', env => { await stakingApiWrapper.stakingContract.stake.awaitTransactionSuccessAsync(amountToStake, { from: actors[0], }); - const inactiveStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( + const undelegatedStakeBalance = await stakingApiWrapper.stakingContract.getOwnerStakeByStatus.callAsync( actors[0], StakeStatus.Undelegated, ); - expect(inactiveStakeBalance.currentEpochBalance).to.be.bignumber.equal(amountToStake); + expect(undelegatedStakeBalance.currentEpochBalance).to.be.bignumber.equal(amountToStake); }); it('should emit event when setting read-only mode', async () => { // set to read-only mode diff --git a/contracts/staking/test/stake_test.ts b/contracts/staking/test/stake_test.ts index 5d4e0c95fb..bc98b41690 100644 --- a/contracts/staking/test/stake_test.ts +++ b/contracts/staking/test/stake_test.ts @@ -113,7 +113,7 @@ blockchainTests.resets('Stake Statuses', env => { new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); - // stake is now inactive, should not be able to move it out of active status again + // stake is now undelegated, should not be able to move it out of active status again await staker.moveStakeAsync( new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[1]), @@ -146,7 +146,7 @@ blockchainTests.resets('Stake Statuses', env => { new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); - // stake is now inactive, should not be able to move it out of active status again + // stake is now undelegated, should not be able to move it out of active status again await staker.moveStakeAsync( new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[1]), @@ -156,21 +156,21 @@ blockchainTests.resets('Stake Statuses', env => { }); }); describe('Move Zero Stake', () => { - it('inactive -> inactive', async () => { + it('undelegated -> undelegated', async () => { await staker.moveStakeAsync( new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Undelegated), ZERO, ); }); - it('inactive -> delegated', async () => { + it('undelegated -> delegated', async () => { await staker.moveStakeAsync( new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[0]), ZERO, ); }); - it('delegated -> inactive', async () => { + it('delegated -> undelegated', async () => { await staker.moveStakeAsync( new StakeInfo(StakeStatus.Delegated, poolIds[0]), new StakeInfo(StakeStatus.Undelegated), @@ -206,16 +206,16 @@ blockchainTests.resets('Stake Statuses', env => { await staker.moveStakeAsync(from, to, amount.div(2)); await staker.goToNextEpochAsync(); }; - it('inactive -> inactive', async () => { + it('undelegated -> undelegated', async () => { await testMovePartialStake(new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Undelegated)); }); - it('inactive -> delegated', async () => { + it('undelegated -> delegated', async () => { await testMovePartialStake( new StakeInfo(StakeStatus.Undelegated), new StakeInfo(StakeStatus.Delegated, poolIds[0]), ); }); - it('delegated -> inactive', async () => { + it('delegated -> undelegated', async () => { await testMovePartialStake( new StakeInfo(StakeStatus.Delegated, poolIds[0]), new StakeInfo(StakeStatus.Undelegated), @@ -233,7 +233,7 @@ blockchainTests.resets('Stake Statuses', env => { new StakeInfo(StakeStatus.Delegated, poolIds[1]), ); }); - it('inactive -> delegated (non-existent pool)', async () => { + it('undelegated -> delegated (non-existent pool)', async () => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync( @@ -264,7 +264,7 @@ blockchainTests.resets('Stake Statuses', env => { const amount = toBaseUnitAmount(0); await staker.unstakeAsync(amount); }); - it('should successfully unstake after becoming inactive', async () => { + it('should successfully unstake after becoming undelegated', async () => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync( @@ -277,10 +277,10 @@ blockchainTests.resets('Stake Statuses', env => { new StakeInfo(StakeStatus.Undelegated), amount, ); - await staker.goToNextEpochAsync(); // stake is now inactive + await staker.goToNextEpochAsync(); // stake is now undelegated await staker.unstakeAsync(amount); }); - it('should fail to unstake in the same epoch as stake was set to inactive', async () => { + it('should fail to unstake in the same epoch as stake was undelegated', async () => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync( @@ -296,7 +296,7 @@ blockchainTests.resets('Stake Statuses', env => { ); await staker.unstakeAsync(amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO)); }); - it('should fail to unstake in same epoch that inactive stake has been reactivated', async () => { + it('should fail to unstake in same epoch that undelegated stake has been delegated', async () => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync( @@ -306,7 +306,7 @@ blockchainTests.resets('Stake Statuses', env => { ); await staker.unstakeAsync(amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO)); }); - it('should fail to unstake one epoch after inactive stake has been reactivated', async () => { + it('should fail to unstake one epoch after undelegated stake has been delegated', async () => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync( @@ -314,10 +314,10 @@ blockchainTests.resets('Stake Statuses', env => { new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); - await staker.goToNextEpochAsync(); // stake is now inactive + await staker.goToNextEpochAsync(); // stake is now undelegated await staker.unstakeAsync(amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO)); }); - it('should fail to unstake >1 epoch after inactive stake has been reactivated', async () => { + it('should fail to unstake >1 epoch after undelegated stake has been delegated', async () => { const amount = toBaseUnitAmount(10); await staker.stakeAsync(amount); await staker.moveStakeAsync( @@ -325,7 +325,7 @@ blockchainTests.resets('Stake Statuses', env => { new StakeInfo(StakeStatus.Delegated, poolIds[0]), amount, ); - await staker.goToNextEpochAsync(); // stake is now inactive + await staker.goToNextEpochAsync(); // stake is now undelegated await staker.goToNextEpochAsync(); // stake is now withdrawable await staker.unstakeAsync(amount, new StakingRevertErrors.InsufficientBalanceError(amount, ZERO)); }); @@ -352,9 +352,9 @@ blockchainTests.resets('Stake Statuses', env => { // ); // // Epoch 2: Status updates (no user intervention required) // await staker.goToNextEpochAsync(); - // // Epoch 3: Stake that has been inactive for an epoch can be withdrawn (no user intervention required) + // // Epoch 3: Stake that has been undelegated for an epoch can be withdrawn (no user intervention required) // await staker.goToNextEpochAsync(); - // // Later in Epoch 3: User reactivates half of their inactive stake; this becomes Active next epoch + // // Later in Epoch 3: User reactivates half of their undelegated stake; this becomes Active next epoch // await staker.moveStakeAsync( // new StakeInfo(StakeStatus.Undelegated), // new StakeInfo(StakeStatus.Active), @@ -374,7 +374,7 @@ blockchainTests.resets('Stake Statuses', env => { // new StakeInfo(StakeStatus.Undelegated), // toBaseUnitAmount(1.5), // ); - // // Later in Epoch 4: User withdraws all available inactive stake + // // Later in Epoch 4: User withdraws all available undelegated stake // await staker.unstakeAsync(toBaseUnitAmount(0.5)); // // Epoch 5: Status updates (no user intervention required) // await staker.goToNextEpochAsync(); diff --git a/contracts/staking/test/utils/types.ts b/contracts/staking/test/utils/types.ts index 647e26e043..ae501a5a16 100644 --- a/contracts/staking/test/utils/types.ts +++ b/contracts/staking/test/utils/types.ts @@ -87,9 +87,9 @@ export interface StakeBalances { zrxBalance: BigNumber; stakeBalance: BigNumber; stakeBalanceInVault: BigNumber; - inactiveStakeBalance: StoredBalance; + undelegatedStakeBalance: StoredBalance; delegatedStakeBalance: StoredBalance; - globalInactiveStakeBalance: StoredBalance; + globalUndelegatedStakeBalance: StoredBalance; globalDelegatedStakeBalance: StoredBalance; delegatedStakeByPool: StakeBalanceByPool; totalDelegatedStakeByPool: StakeBalanceByPool; From 414084a7ad8ff48fbea1eeaa39ad7c0c55127965 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sun, 6 Oct 2019 00:11:55 -0700 Subject: [PATCH 53/87] Track state of read-only mode in stakingProxy --- .../staking/contracts/src/StakingProxy.sol | 21 ++++++++++++++----- contracts/staking/contracts/src/ZrxVault.sol | 1 + .../contracts/src/immutable/MixinStorage.sol | 5 ++++- .../src/interfaces/IStakingProxy.sol | 14 +++++++++++-- .../contracts/src/interfaces/IStructs.sol | 8 +++++++ .../test/TestStorageLayoutAndConstants.sol | 8 +++++++ 6 files changed, 49 insertions(+), 8 deletions(-) diff --git a/contracts/staking/contracts/src/StakingProxy.sol b/contracts/staking/contracts/src/StakingProxy.sol index e2135f7b87..36fa46c3e1 100644 --- a/contracts/staking/contracts/src/StakingProxy.sol +++ b/contracts/staking/contracts/src/StakingProxy.sol @@ -20,6 +20,7 @@ pragma solidity ^0.5.9; pragma experimental ABIEncoderV2; import "./libs/LibProxy.sol"; +import "./libs/LibSafeDowncast.sol"; import "./immutable/MixinStorage.sol"; import "./interfaces/IStorageInit.sol"; import "./interfaces/IStakingProxy.sol"; @@ -30,6 +31,7 @@ contract StakingProxy is MixinStorage { using LibProxy for address; + using LibSafeDowncast for uint256; /// @dev Constructor. /// @param _stakingContract Staking contract to delegate calls to. @@ -86,16 +88,25 @@ contract StakingProxy is } /// @dev Set read-only mode (state cannot be changed). - function setReadOnlyMode(bool readOnlyMode) + function setReadOnlyMode(bool shouldSetReadOnlyMode) external onlyAuthorized { - if (readOnlyMode) { + uint96 timestamp = block.timestamp.downcastToUint96(); + if (shouldSetReadOnlyMode) { stakingContract = readOnlyProxy; + readOnlyState = IStructs.ReadOnlyState({ + isReadOnlyModeSet: true, + lastSetTimestamp: timestamp + }); } else { stakingContract = readOnlyProxyCallee; + readOnlyState.isReadOnlyModeSet = false; } - emit ReadOnlyModeSet(readOnlyMode); + emit ReadOnlyModeSet( + shouldSetReadOnlyMode, + timestamp + ); } /// @dev Batch executes a series of calls to the staking contract. @@ -108,9 +119,9 @@ contract StakingProxy is // Initialize commonly used variables. bool success; bytes memory returnData; - batchReturnData = new bytes[](data.length); - address staking = stakingContract; uint256 dataLength = data.length; + batchReturnData = new bytes[](dataLength); + address staking = stakingContract; // Ensure that a staking contract has been attached to the proxy. if (staking == address(0)) { diff --git a/contracts/staking/contracts/src/ZrxVault.sol b/contracts/staking/contracts/src/ZrxVault.sol index f57400a4b4..529a936f64 100644 --- a/contracts/staking/contracts/src/ZrxVault.sol +++ b/contracts/staking/contracts/src/ZrxVault.sol @@ -105,6 +105,7 @@ contract ZrxVault is function enterCatastrophicFailure() external onlyAuthorized + onlyNotInCatastrophicFailure { isInCatastrophicFailure = true; emit InCatastrophicFailureMode(msg.sender); diff --git a/contracts/staking/contracts/src/immutable/MixinStorage.sol b/contracts/staking/contracts/src/immutable/MixinStorage.sol index 7c63953732..414aeff970 100644 --- a/contracts/staking/contracts/src/immutable/MixinStorage.sol +++ b/contracts/staking/contracts/src/immutable/MixinStorage.sol @@ -41,7 +41,10 @@ contract MixinStorage is // address for read-only proxy to call address public readOnlyProxyCallee; - // mapping from StakeStatus to gloabl stored balance + // state of read-only mode in stakingProxy + IStructs.ReadOnlyState public readOnlyState; + + // mapping from StakeStatus to global stored balance // (access using _loadSyncedBalance or _loadUnsyncedBalance) // NOTE: only Status.DELEGATED is used to access this mapping, but this format // is used for extensibility diff --git a/contracts/staking/contracts/src/interfaces/IStakingProxy.sol b/contracts/staking/contracts/src/interfaces/IStakingProxy.sol index 9eb6d49120..a07b42c49b 100644 --- a/contracts/staking/contracts/src/interfaces/IStakingProxy.sol +++ b/contracts/staking/contracts/src/interfaces/IStakingProxy.sol @@ -17,9 +17,12 @@ */ pragma solidity ^0.5.9; +pragma experimental ABIEncoderV2; +import "./IStructs.sol"; -interface IStakingProxy /* is IStaking */ + +contract IStakingProxy /* is IStaking */ { /// @dev Emitted by StakingProxy when a staking contract is attached. @@ -33,7 +36,8 @@ interface IStakingProxy /* is IStaking */ /// @dev Emitted by StakingProxy when read-only mode is set. event ReadOnlyModeSet( - bool readOnlyMode + bool readOnlyMode, + uint96 timestamp ); /// @dev Delegates calls to the staking contract, if it is set. @@ -52,4 +56,10 @@ interface IStakingProxy /* is IStaking */ /// Note that this is callable only by an authorized address. function detachStakingContract() external; + + /// @dev Gets state of stakingProxy read-only mode. + function readOnlyState() + external + view + returns (IStructs.ReadOnlyState memory); } diff --git a/contracts/staking/contracts/src/interfaces/IStructs.sol b/contracts/staking/contracts/src/interfaces/IStructs.sol index 8e19b52998..4857ec04d2 100644 --- a/contracts/staking/contracts/src/interfaces/IStructs.sol +++ b/contracts/staking/contracts/src/interfaces/IStructs.sol @@ -21,6 +21,14 @@ pragma solidity ^0.5.9; interface IStructs { + /// @dev State of stakingProxy read-only mode. + /// @param isReadOnlyModeSet True if in read-only mode. + /// @param lastSetTimestamp Timestamp at which read-only mode was last set. + struct ReadOnlyState { + bool isReadOnlyModeSet; + uint96 lastSetTimestamp; + } + /// @dev Status for a pool that actively traded during the current epoch. /// (see MixinExchangeFees). /// @param feesCollected Fees collected in ETH by this pool. diff --git a/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol b/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol index 2ec0a0f54e..7c9a5f1f85 100644 --- a/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol +++ b/contracts/staking/contracts/test/TestStorageLayoutAndConstants.sol @@ -118,6 +118,14 @@ contract TestStorageLayoutAndConstants is ) slot := add(slot, 0x1) + assertSlotAndOffset( + readOnlyState_slot, + readOnlyState_offset, + slot, + offset + ) + slot := add(slot, 0x1) + assertSlotAndOffset( _globalStakeByStatus_slot, _globalStakeByStatus_offset, From a7ef54dbff7c1109c2ac517b85190db299cb3e9c Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sun, 6 Oct 2019 12:02:40 -0700 Subject: [PATCH 54/87] Implement ZrxVaultBackstop --- .../contracts/src/ZrxVaultBackstop.sol | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 contracts/staking/contracts/src/ZrxVaultBackstop.sol diff --git a/contracts/staking/contracts/src/ZrxVaultBackstop.sol b/contracts/staking/contracts/src/ZrxVaultBackstop.sol new file mode 100644 index 0000000000..874291f131 --- /dev/null +++ b/contracts/staking/contracts/src/ZrxVaultBackstop.sol @@ -0,0 +1,69 @@ +/* + + Copyright 2019 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.5.9; +pragma experimental ABIEncoderV2; + +import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; +import "./interfaces/IStructs.sol"; +import "./interfaces/IZrxVault.sol"; +import "./interfaces/IStakingProxy.sol"; + + +contract ZrxVaultBackstop { + + using LibSafeMath for uint256; + + IStakingProxy public stakingProxy; + IZrxVault public zrxVault; + + /// @dev Constructor. Sets stakingProxy and zrxVault. + /// @param _stakingProxyAddress Address of stakingProxy. + /// @param _zrxVaultAddress Address of zrxVault. + constructor( + address payable _stakingProxyAddress, + address _zrxVaultAddress + ) + public + { + stakingProxy = IStakingProxy(_stakingProxyAddress); + zrxVault = IZrxVault(_zrxVaultAddress); + } + + /// @dev Triggers catastophic failure mode in the zrxzVault iff read-only mode + /// has been continuously set for at least 40 days. + function enterCatastrophicFailureIfProlongedReadOnlyMode() + external + { + IStructs.ReadOnlyState memory readOnlyState = stakingProxy.readOnlyState(); + + // Ensure read-only mode is set + require( + readOnlyState.isReadOnlyModeSet, + "READ_ONLY_MODE_NOT_SET" + ); + + // Ensure that the stakingProxy has been in read-only mode for a long enough time + require( + block.timestamp.safeSub(readOnlyState.lastSetTimestamp) >= 40 days, + "READ_ONLY_MODE_LENGTH_TOO_SHORT" + ); + + zrxVault.enterCatastrophicFailure(); + } +} From 9e41c648dc50edc1f41f2fcd44a48861602c47ef Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sun, 6 Oct 2019 13:17:02 -0700 Subject: [PATCH 55/87] Add backstop tests --- contracts/staking/compiler.json | 2 +- .../contracts/src/ZrxVaultBackstop.sol | 2 +- contracts/staking/package.json | 2 +- contracts/staking/src/artifacts.ts | 2 + contracts/staking/src/wrappers.ts | 1 + contracts/staking/test/catastrophe_test.ts | 7 ++- .../staking/test/unit_tests/zrx_vault_test.ts | 11 ++++ contracts/staking/test/utils/api_wrapper.ts | 19 ++++++- .../staking/test/zrx_vault_backstop_test.ts | 50 +++++++++++++++++++ contracts/staking/tsconfig.json | 3 +- 10 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 contracts/staking/test/zrx_vault_backstop_test.ts diff --git a/contracts/staking/compiler.json b/contracts/staking/compiler.json index f432301d36..b8225dc0c4 100644 --- a/contracts/staking/compiler.json +++ b/contracts/staking/compiler.json @@ -2,7 +2,7 @@ "artifactsDir": "./generated-artifacts", "contractsDir": "./contracts", "useDockerisedSolc": false, - "isOfflineMode": false, + "isOfflineMode": true, "compilerSettings": { "evmVersion": "constantinople", "optimizer": { diff --git a/contracts/staking/contracts/src/ZrxVaultBackstop.sol b/contracts/staking/contracts/src/ZrxVaultBackstop.sol index 874291f131..20a35b8091 100644 --- a/contracts/staking/contracts/src/ZrxVaultBackstop.sol +++ b/contracts/staking/contracts/src/ZrxVaultBackstop.sol @@ -61,7 +61,7 @@ contract ZrxVaultBackstop { // Ensure that the stakingProxy has been in read-only mode for a long enough time require( block.timestamp.safeSub(readOnlyState.lastSetTimestamp) >= 40 days, - "READ_ONLY_MODE_LENGTH_TOO_SHORT" + "READ_ONLY_MODE_DURATION_TOO_SHORT" ); zrxVault.enterCatastrophicFailure(); diff --git a/contracts/staking/package.json b/contracts/staking/package.json index 838a32239c..884892949b 100644 --- a/contracts/staking/package.json +++ b/contracts/staking/package.json @@ -37,7 +37,7 @@ }, "config": { "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.", - "abis": "./generated-artifacts/@(IStaking|IStakingEvents|IStakingProxy|IStorage|IStorageInit|IStructs|IZrxVault|LibCobbDouglas|LibFixedMath|LibFixedMathRichErrors|LibProxy|LibSafeDowncast|LibStakingRichErrors|MixinAbstract|MixinConstants|MixinCumulativeRewards|MixinDeploymentConstants|MixinExchangeFees|MixinExchangeManager|MixinFinalizer|MixinParams|MixinScheduler|MixinStake|MixinStakeBalances|MixinStakeStorage|MixinStakingPool|MixinStakingPoolRewards|MixinStorage|ReadOnlyProxy|Staking|StakingProxy|TestAssertStorageParams|TestCobbDouglas|TestCumulativeRewardTracking|TestDelegatorRewards|TestExchangeManager|TestFinalizer|TestInitTarget|TestLibFixedMath|TestLibProxy|TestLibProxyReceiver|TestLibSafeDowncast|TestMixinStakeStorage|TestProtocolFees|TestStaking|TestStakingNoWETH|TestStakingProxy|TestStorageLayoutAndConstants|ZrxVault).json" + "abis": "./generated-artifacts/@(IStaking|IStakingEvents|IStakingProxy|IStorage|IStorageInit|IStructs|IZrxVault|LibCobbDouglas|LibFixedMath|LibFixedMathRichErrors|LibProxy|LibSafeDowncast|LibStakingRichErrors|MixinAbstract|MixinConstants|MixinCumulativeRewards|MixinDeploymentConstants|MixinExchangeFees|MixinExchangeManager|MixinFinalizer|MixinParams|MixinScheduler|MixinStake|MixinStakeBalances|MixinStakeStorage|MixinStakingPool|MixinStakingPoolRewards|MixinStorage|ReadOnlyProxy|Staking|StakingProxy|TestAssertStorageParams|TestCobbDouglas|TestCumulativeRewardTracking|TestDelegatorRewards|TestExchangeManager|TestFinalizer|TestInitTarget|TestLibFixedMath|TestLibProxy|TestLibProxyReceiver|TestLibSafeDowncast|TestMixinStakeStorage|TestProtocolFees|TestStaking|TestStakingNoWETH|TestStakingProxy|TestStorageLayoutAndConstants|ZrxVault|ZrxVaultBackstop).json" }, "repository": { "type": "git", diff --git a/contracts/staking/src/artifacts.ts b/contracts/staking/src/artifacts.ts index 9e27fb471e..5cd2b8ff12 100644 --- a/contracts/staking/src/artifacts.ts +++ b/contracts/staking/src/artifacts.ts @@ -54,11 +54,13 @@ import * as TestStakingNoWETH from '../generated-artifacts/TestStakingNoWETH.jso import * as TestStakingProxy from '../generated-artifacts/TestStakingProxy.json'; import * as TestStorageLayoutAndConstants from '../generated-artifacts/TestStorageLayoutAndConstants.json'; import * as ZrxVault from '../generated-artifacts/ZrxVault.json'; +import * as ZrxVaultBackstop from '../generated-artifacts/ZrxVaultBackstop.json'; export const artifacts = { ReadOnlyProxy: ReadOnlyProxy as ContractArtifact, Staking: Staking as ContractArtifact, StakingProxy: StakingProxy as ContractArtifact, ZrxVault: ZrxVault as ContractArtifact, + ZrxVaultBackstop: ZrxVaultBackstop as ContractArtifact, MixinExchangeFees: MixinExchangeFees as ContractArtifact, MixinExchangeManager: MixinExchangeManager as ContractArtifact, MixinConstants: MixinConstants as ContractArtifact, diff --git a/contracts/staking/src/wrappers.ts b/contracts/staking/src/wrappers.ts index 2c7589178b..149d989f78 100644 --- a/contracts/staking/src/wrappers.ts +++ b/contracts/staking/src/wrappers.ts @@ -52,3 +52,4 @@ export * from '../generated-wrappers/test_staking_no_w_e_t_h'; export * from '../generated-wrappers/test_staking_proxy'; export * from '../generated-wrappers/test_storage_layout_and_constants'; export * from '../generated-wrappers/zrx_vault'; +export * from '../generated-wrappers/zrx_vault_backstop'; diff --git a/contracts/staking/test/catastrophe_test.ts b/contracts/staking/test/catastrophe_test.ts index 0244de9136..1f3cfa783e 100644 --- a/contracts/staking/test/catastrophe_test.ts +++ b/contracts/staking/test/catastrophe_test.ts @@ -90,7 +90,7 @@ blockchainTests.resets('Catastrophe Tests', env => { ); expect(undelegatedStakeBalance.currentEpochBalance).to.be.bignumber.equal(amountToStake); }); - it('should emit event when setting read-only mode', async () => { + it('should emit event and store correct configuration when setting read-only mode', async () => { // set to read-only mode const txReceipt = await stakingApiWrapper.stakingProxyContract.setReadOnlyMode.awaitTransactionSuccessAsync( true, @@ -98,6 +98,11 @@ blockchainTests.resets('Catastrophe Tests', env => { expect(txReceipt.logs.length).to.be.equal(1); const trueLog = txReceipt.logs[0] as LogWithDecodedArgs; expect(trueLog.args.readOnlyMode).to.be.true(); + const timestamp = await env.web3Wrapper.getBlockTimestampAsync(txReceipt.blockNumber); + expect(trueLog.args.timestamp).to.bignumber.equal(timestamp); + const readOnlyState = await stakingApiWrapper.stakingProxyContract.readOnlyState.callAsync(); + expect(readOnlyState[0]).to.be.true(); + expect(readOnlyState[1]).to.bignumber.equal(timestamp); }); }); }); diff --git a/contracts/staking/test/unit_tests/zrx_vault_test.ts b/contracts/staking/test/unit_tests/zrx_vault_test.ts index d2db51e722..c2c3a10b4e 100644 --- a/contracts/staking/test/unit_tests/zrx_vault_test.ts +++ b/contracts/staking/test/unit_tests/zrx_vault_test.ts @@ -336,6 +336,17 @@ blockchainTests.resets('ZrxVault unit tests', env => { expect(tx).to.revertWith(expectedError); expect(await zrxVault.isInCatastrophicFailure.callAsync()).to.be.false(); }); + it('Catastrophic Failure Mode can only be turned on once', async () => { + const authorized = nonOwnerAddresses[0]; + await zrxVault.addAuthorizedAddress.awaitTransactionSuccessAsync(authorized, { from: owner }); + await zrxVault.enterCatastrophicFailure.awaitTransactionSuccessAsync({ + from: authorized, + }); + const expectedError = new StakingRevertErrors.OnlyCallableIfNotInCatastrophicFailureError(); + return expect(zrxVault.enterCatastrophicFailure.awaitTransactionSuccessAsync()).to.revertWith( + expectedError, + ); + }); }); describe('Affected functionality', () => { diff --git a/contracts/staking/test/utils/api_wrapper.ts b/contracts/staking/test/utils/api_wrapper.ts index c53f46d36c..b2a9726275 100644 --- a/contracts/staking/test/utils/api_wrapper.ts +++ b/contracts/staking/test/utils/api_wrapper.ts @@ -15,6 +15,7 @@ import { TestCobbDouglasContract, TestStakingContract, TestStakingEvents, + ZrxVaultBackstopContract, ZrxVaultContract, } from '../../src'; @@ -32,6 +33,7 @@ export class StakingApiWrapper { public zrxTokenContract: DummyERC20TokenContract; public wethContract: WETH9Contract; public cobbDouglasContract: TestCobbDouglasContract; + public zrxVaultBackstopContract: ZrxVaultBackstopContract; public utils = { // Epoch Utils fastForwardToNextEpochAsync: async (): Promise => { @@ -174,13 +176,14 @@ export class StakingApiWrapper { zrxTokenContract: DummyERC20TokenContract, wethContract: WETH9Contract, cobbDouglasContract: TestCobbDouglasContract, + zrxVaultBackstopContract: ZrxVaultBackstopContract, ) { this._web3Wrapper = env.web3Wrapper; this.zrxVaultContract = zrxVaultContract; this.zrxTokenContract = zrxTokenContract; this.wethContract = wethContract; this.cobbDouglasContract = cobbDouglasContract; - + this.zrxVaultBackstopContract = zrxVaultBackstopContract; this.stakingContractAddress = stakingContract.address; this.stakingProxyContract = stakingProxyContract; // disguise the staking proxy as a StakingContract @@ -274,10 +277,23 @@ export async function deployAndConfigureContractsAsync( artifacts, ); + const zrxVaultBackstopContract = await ZrxVaultBackstopContract.deployFrom0xArtifactAsync( + artifacts.ZrxVaultBackstop, + env.provider, + env.txDefaults, + artifacts, + stakingProxyContract.address, + zrxVaultContract.address, + ); + // configure erc20 proxy to accept calls from zrx vault await erc20ProxyContract.addAuthorizedAddress.awaitTransactionSuccessAsync(zrxVaultContract.address); // set staking proxy contract in zrx vault await zrxVaultContract.setStakingProxy.awaitTransactionSuccessAsync(stakingProxyContract.address); + // add zrxVaultBackstop as an authorized address + await zrxVaultContract.addAuthorizedAddress.awaitTransactionSuccessAsync(zrxVaultBackstopContract.address, { + from: ownerAddress, + }); return new StakingApiWrapper( env, ownerAddress, @@ -287,5 +303,6 @@ export async function deployAndConfigureContractsAsync( zrxTokenContract, wethContract, cobbDouglasContract, + zrxVaultBackstopContract, ); } diff --git a/contracts/staking/test/zrx_vault_backstop_test.ts b/contracts/staking/test/zrx_vault_backstop_test.ts new file mode 100644 index 0000000000..b0bc6d1f19 --- /dev/null +++ b/contracts/staking/test/zrx_vault_backstop_test.ts @@ -0,0 +1,50 @@ +import { ERC20Wrapper } from '@0x/contracts-asset-proxy'; +import { blockchainTests, describe, expect, increaseTimeAndMineBlockAsync } from '@0x/contracts-test-utils'; +import { StringRevertError } from '@0x/utils'; +import { LogWithDecodedArgs } from 'ethereum-types'; + +import { ZrxVaultInCatastrophicFailureModeEventArgs } from '../src'; + +import { deployAndConfigureContractsAsync, StakingApiWrapper } from './utils/api_wrapper'; +blockchainTests.resets('ZrxVaultBackstop', env => { + let stakingApiWrapper: StakingApiWrapper; + let authorizedAddress: string; + let notAuthorizedAddress: string; + before(async () => { + const accounts = await env.web3Wrapper.getAvailableAddressesAsync(); + [authorizedAddress, notAuthorizedAddress] = accounts; + const erc20Wrapper = new ERC20Wrapper(env.provider, [], authorizedAddress); + stakingApiWrapper = await deployAndConfigureContractsAsync(env, authorizedAddress, erc20Wrapper); + }); + + describe('enterCatastrophicFailureIfProlongedReadOnlyMode', () => { + it('should revert if read-only mode is not set', async () => { + const expectedError = new StringRevertError('READ_ONLY_MODE_NOT_SET'); + expect( + stakingApiWrapper.zrxVaultBackstopContract.enterCatastrophicFailureIfProlongedReadOnlyMode.awaitTransactionSuccessAsync(), + ).to.revertWith(expectedError); + }); + it('should revert if read-only mode has been set for less than 40 days', async () => { + await stakingApiWrapper.stakingProxyContract.setReadOnlyMode.awaitTransactionSuccessAsync(true, { + from: authorizedAddress, + }); + const expectedError = new StringRevertError('READ_ONLY_MODE_DURATION_TOO_SHORT'); + expect( + stakingApiWrapper.zrxVaultBackstopContract.enterCatastrophicFailureIfProlongedReadOnlyMode.awaitTransactionSuccessAsync(), + ).to.revertWith(expectedError); + }); + it('should enter catastophic failure mode if read-only mode has been set for 40 days', async () => { + await stakingApiWrapper.stakingProxyContract.setReadOnlyMode.awaitTransactionSuccessAsync(true, { + from: authorizedAddress, + }); + const fourtyDaysInSec = 40 * 24 * 60 * 60; + await increaseTimeAndMineBlockAsync(fourtyDaysInSec); + const txReceipt = await stakingApiWrapper.zrxVaultBackstopContract.enterCatastrophicFailureIfProlongedReadOnlyMode.awaitTransactionSuccessAsync( + { from: notAuthorizedAddress }, + ); + expect(txReceipt.logs.length).to.equal(1); + const logArgs = (txReceipt.logs[0] as LogWithDecodedArgs).args; + expect(logArgs.sender).to.equal(stakingApiWrapper.zrxVaultBackstopContract.address); + }); + }); +}); diff --git a/contracts/staking/tsconfig.json b/contracts/staking/tsconfig.json index 9e51fd5193..69497c153e 100644 --- a/contracts/staking/tsconfig.json +++ b/contracts/staking/tsconfig.json @@ -51,7 +51,8 @@ "generated-artifacts/TestStakingNoWETH.json", "generated-artifacts/TestStakingProxy.json", "generated-artifacts/TestStorageLayoutAndConstants.json", - "generated-artifacts/ZrxVault.json" + "generated-artifacts/ZrxVault.json", + "generated-artifacts/ZrxVaultBackstop.json" ], "exclude": ["./deploy/solc/solc_bin"] } From 93edb083fabcfa73f862e65ef678e9e5d8e2d260 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Tue, 8 Oct 2019 09:28:14 +0900 Subject: [PATCH 56/87] Remove payable fallback from IStakingProxy, fix linting errors --- contracts/staking/contracts/src/StakingProxy.sol | 1 + contracts/staking/contracts/src/ZrxVaultBackstop.sol | 4 +++- .../staking/contracts/src/interfaces/IStakingProxy.sol | 9 +-------- contracts/staking/test/zrx_vault_backstop_test.ts | 1 + 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/contracts/staking/contracts/src/StakingProxy.sol b/contracts/staking/contracts/src/StakingProxy.sol index 36fa46c3e1..9946df7dfa 100644 --- a/contracts/staking/contracts/src/StakingProxy.sol +++ b/contracts/staking/contracts/src/StakingProxy.sol @@ -92,6 +92,7 @@ contract StakingProxy is external onlyAuthorized { + // solhint-disable-next-line not-rely-on-time uint96 timestamp = block.timestamp.downcastToUint96(); if (shouldSetReadOnlyMode) { stakingContract = readOnlyProxy; diff --git a/contracts/staking/contracts/src/ZrxVaultBackstop.sol b/contracts/staking/contracts/src/ZrxVaultBackstop.sol index 20a35b8091..68a47c9c5f 100644 --- a/contracts/staking/contracts/src/ZrxVaultBackstop.sol +++ b/contracts/staking/contracts/src/ZrxVaultBackstop.sol @@ -36,7 +36,7 @@ contract ZrxVaultBackstop { /// @param _stakingProxyAddress Address of stakingProxy. /// @param _zrxVaultAddress Address of zrxVault. constructor( - address payable _stakingProxyAddress, + address _stakingProxyAddress, address _zrxVaultAddress ) public @@ -59,7 +59,9 @@ contract ZrxVaultBackstop { ); // Ensure that the stakingProxy has been in read-only mode for a long enough time + // TODO: Ensure correct value is set in production require( + // solhint-disable-next-line not-rely-on-time block.timestamp.safeSub(readOnlyState.lastSetTimestamp) >= 40 days, "READ_ONLY_MODE_DURATION_TOO_SHORT" ); diff --git a/contracts/staking/contracts/src/interfaces/IStakingProxy.sol b/contracts/staking/contracts/src/interfaces/IStakingProxy.sol index a07b42c49b..c29560cfdf 100644 --- a/contracts/staking/contracts/src/interfaces/IStakingProxy.sol +++ b/contracts/staking/contracts/src/interfaces/IStakingProxy.sol @@ -22,8 +22,7 @@ pragma experimental ABIEncoderV2; import "./IStructs.sol"; -contract IStakingProxy /* is IStaking */ -{ +contract IStakingProxy { /// @dev Emitted by StakingProxy when a staking contract is attached. /// @param newStakingContractAddress Address of newly attached staking contract. @@ -40,12 +39,6 @@ contract IStakingProxy /* is IStaking */ uint96 timestamp ); - /// @dev Delegates calls to the staking contract, if it is set. - // solhint-disable no-complex-fallback - function () - external - payable; - /// @dev Attach a staking contract; future calls will be delegated to the staking contract. /// Note that this is callable only by an authorized address. /// @param _stakingContract Address of staking contract. diff --git a/contracts/staking/test/zrx_vault_backstop_test.ts b/contracts/staking/test/zrx_vault_backstop_test.ts index b0bc6d1f19..73271cfbe5 100644 --- a/contracts/staking/test/zrx_vault_backstop_test.ts +++ b/contracts/staking/test/zrx_vault_backstop_test.ts @@ -43,6 +43,7 @@ blockchainTests.resets('ZrxVaultBackstop', env => { { from: notAuthorizedAddress }, ); expect(txReceipt.logs.length).to.equal(1); + // tslint:disable:no-unnecessary-type-assertion const logArgs = (txReceipt.logs[0] as LogWithDecodedArgs).args; expect(logArgs.sender).to.equal(stakingApiWrapper.zrxVaultBackstopContract.address); }); From 7815da7257ebdad4bbc8498526a3f5426f5c298e Mon Sep 17 00:00:00 2001 From: Alex Towle Date: Wed, 9 Oct 2019 10:49:38 -0700 Subject: [PATCH 57/87] `@0x:contracts-utils` Addressed review feedback --- contracts/utils/test/ownable.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/utils/test/ownable.ts b/contracts/utils/test/ownable.ts index 7d95cec505..2e45914f75 100644 --- a/contracts/utils/test/ownable.ts +++ b/contracts/utils/test/ownable.ts @@ -44,11 +44,11 @@ blockchainTests.resets('Ownable', env => { // Ensure that the correct logs were emitted. expect(receipt.logs.length).to.be.eq(1); - const args = filterLogsToArguments( + const [event] = filterLogsToArguments( receipt.logs, IOwnableEvents.OwnershipTransferred, ); - expect(args).to.be.deep.eq([{ newOwner: nonOwner }]); + expect(event).to.be.deep.eq({ newOwner: nonOwner }); // Ensure that the owner was actually updated const updatedOwner = await ownable.owner.callAsync(); From a42f3d189c9f2ca0087af8b36acbb2ef6e1a319c Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Sat, 5 Oct 2019 21:12:52 -0500 Subject: [PATCH 58/87] `@0x/contracts-staking`: Implement better overflow detection in `LibFixedMath`. --- .../contracts/src/libs/LibFixedMath.sol | 17 ++-- .../src/libs/LibFixedMathRichErrors.sol | 1 - .../test/unit_tests/lib_fixed_math_test.ts | 87 ++++++++++++++++++- .../utils/src/fixed_math_revert_errors.ts | 1 - 4 files changed, 93 insertions(+), 13 deletions(-) diff --git a/contracts/staking/contracts/src/libs/LibFixedMath.sol b/contracts/staking/contracts/src/libs/LibFixedMath.sol index bab8d2db75..dc5ed65802 100644 --- a/contracts/staking/contracts/src/libs/LibFixedMath.sol +++ b/contracts/staking/contracts/src/libs/LibFixedMath.sol @@ -27,6 +27,8 @@ library LibFixedMath { // 1 int256 private constant FIXED_1 = int256(0x0000000000000000000000000000000080000000000000000000000000000000); + // 2**255 + int256 private constant MIN_FIXED_VAL = int256(0x8000000000000000000000000000000000000000000000000000000000000000); // 1^2 (in fixed-point) int256 private constant FIXED_1_SQUARED = int256(0x4000000000000000000000000000000000000000000000000000000000000000); // 1 @@ -50,6 +52,12 @@ library LibFixedMath { /// @dev Returns the addition of two fixed point numbers, reverting on overflow. function sub(int256 a, int256 b) internal pure returns (int256 c) { + if (b == MIN_FIXED_VAL) { + LibRichErrors.rrevert(LibFixedMathRichErrors.SignedValueError( + LibFixedMathRichErrors.ValueErrorCodes.TOO_SMALL, + b + )); + } c = _add(a, -b); } @@ -359,14 +367,7 @@ library LibFixedMath { /// @dev Adds two numbers, reverting on overflow. function _add(int256 a, int256 b) private pure returns (int256 c) { c = a + b; - if (c > 0 && a < 0 && b < 0) { - LibRichErrors.rrevert(LibFixedMathRichErrors.BinOpError( - LibFixedMathRichErrors.BinOpErrorCodes.SUBTRACTION_OVERFLOW, - a, - b - )); - } - if (c < 0 && a > 0 && b > 0) { + if ((a < 0 && b < 0 && c > a) || (a > 0 && b > 0 && c < a)) { LibRichErrors.rrevert(LibFixedMathRichErrors.BinOpError( LibFixedMathRichErrors.BinOpErrorCodes.ADDITION_OVERFLOW, a, diff --git a/contracts/staking/contracts/src/libs/LibFixedMathRichErrors.sol b/contracts/staking/contracts/src/libs/LibFixedMathRichErrors.sol index 8ea570bb87..4a4f111fcb 100644 --- a/contracts/staking/contracts/src/libs/LibFixedMathRichErrors.sol +++ b/contracts/staking/contracts/src/libs/LibFixedMathRichErrors.sol @@ -30,7 +30,6 @@ library LibFixedMathRichErrors { enum BinOpErrorCodes { ADDITION_OVERFLOW, - SUBTRACTION_OVERFLOW, MULTIPLICATION_OVERFLOW, DIVISION_BY_ZERO } diff --git a/contracts/staking/test/unit_tests/lib_fixed_math_test.ts b/contracts/staking/test/unit_tests/lib_fixed_math_test.ts index 5e1eae7aff..eebfeaecbe 100644 --- a/contracts/staking/test/unit_tests/lib_fixed_math_test.ts +++ b/contracts/staking/test/unit_tests/lib_fixed_math_test.ts @@ -7,7 +7,7 @@ import { artifacts, TestLibFixedMathContract } from '../../src'; import { assertRoughlyEquals, fromFixed, toDecimal, toFixed } from '../utils/number_utils'; -blockchainTests('LibFixedMath unit tests', env => { +blockchainTests.only('LibFixedMath unit tests', env => { let testContract: TestLibFixedMathContract; before(async () => { @@ -131,6 +131,19 @@ blockchainTests('LibFixedMath unit tests', env => { const tx = testContract.mulDiv.callAsync(toFixed(a), new BigNumber(n), new BigNumber(d)); return expect(tx).to.revertWith(expectedError); }); + + it('int(-1) * int(1) / int(-1) == int(1)', async () => { + const [a, n, d] = [-1, 1, -1]; + const r = await testContract.mulDiv.callAsync(new BigNumber(a), new BigNumber(n), new BigNumber(d)); + assertFixedEquals(r, fromFixed(1)); + }); + + it('-1 * int(1) / int(-1) == 1', async () => { + const [a, n, d] = [-1, 1, -1]; + const r = await testContract.mulDiv.callAsync(toFixed(a), new BigNumber(n), new BigNumber(d)); + assertFixedEquals(r, 1); + }); + }); describe('add()', () => { @@ -170,13 +183,41 @@ blockchainTests('LibFixedMath unit tests', env => { it('throws on underflow', async () => { const [a, b] = [MIN_FIXED_VALUE, new BigNumber(-1)]; const expectedError = new FixedMathRevertErrors.BinOpError( - FixedMathRevertErrors.BinOpErrorCodes.SubtractionUnderflow, + FixedMathRevertErrors.BinOpErrorCodes.AdditionOverflow, a, b, ); const tx = testContract.add.callAsync(a, b); return expect(tx).to.revertWith(expectedError); }); + + it('MIN_FIXED + MIN_FIXED throws', async () => { + const [a, b] = [MIN_FIXED_VALUE, MIN_FIXED_VALUE]; + const expectedError = new FixedMathRevertErrors.BinOpError( + FixedMathRevertErrors.BinOpErrorCodes.AdditionOverflow, + a, + b, + ); + const tx = testContract.add.callAsync(a, b); + return expect(tx).to.revertWith(expectedError); + }); + + it('MAX_FIXED + MAX_FIXED throws', async () => { + const [a, b] = [MAX_FIXED_VALUE, MAX_FIXED_VALUE]; + const expectedError = new FixedMathRevertErrors.BinOpError( + FixedMathRevertErrors.BinOpErrorCodes.AdditionOverflow, + a, + b, + ); + const tx = testContract.add.callAsync(a, b); + return expect(tx).to.revertWith(expectedError); + }); + + it('MIN_FIXED + MAX_FIXED == int(-1)', async () => { + const [a, b] = [MIN_FIXED_VALUE, MAX_FIXED_VALUE]; + const r = await testContract.add.callAsync(a, b); + expect(r).to.bignumber.eq(-1); + }); }); describe('sub()', () => { @@ -205,7 +246,7 @@ blockchainTests('LibFixedMath unit tests', env => { it('throws on underflow', async () => { const [a, b] = [MIN_FIXED_VALUE, new BigNumber(1)]; const expectedError = new FixedMathRevertErrors.BinOpError( - FixedMathRevertErrors.BinOpErrorCodes.SubtractionUnderflow, + FixedMathRevertErrors.BinOpErrorCodes.AdditionOverflow, a, b.negated(), ); @@ -223,6 +264,46 @@ blockchainTests('LibFixedMath unit tests', env => { const tx = testContract.sub.callAsync(a, b); return expect(tx).to.revertWith(expectedError); }); + + it('MIN_FIXED - MIN_FIXED throws', async () => { + const [a, b] = [MIN_FIXED_VALUE, MIN_FIXED_VALUE]; + // This fails because `-MIN_FIXED_VALUE == MIN_FIXED_VALUE` because of + // twos-complement. + const expectedError = new FixedMathRevertErrors.BinOpError( + FixedMathRevertErrors.BinOpErrorCodes.AdditionOverflow, + a, + b, + ); + const tx = testContract.sub.callAsync(a, b); + return expect(tx).to.revertWith(expectedError); + }); + + it('MAX_FIXED - MAX_FIXED == 0', async () => { + const [a, b] = [MAX_FIXED_VALUE, MAX_FIXED_VALUE]; + const r = await testContract.sub.callAsync(a, b); + return expect(r).to.bignumber.eq(0); + }); + + it('MIN_FIXED - MAX_FIXED throws', async () => { + const [a, b] = [MIN_FIXED_VALUE, MAX_FIXED_VALUE]; + const expectedError = new FixedMathRevertErrors.BinOpError( + FixedMathRevertErrors.BinOpErrorCodes.AdditionOverflow, + a, + b.negated(), + ); + const tx = testContract.sub.callAsync(a, b); + return expect(tx).to.revertWith(expectedError); + }); + + it('MAX_FIXED - MIN_FIXED throws', async () => { + const [a, b] = [MAX_FIXED_VALUE, MIN_FIXED_VALUE]; + const expectedError = new FixedMathRevertErrors.SignedValueError( + FixedMathRevertErrors.ValueErrorCodes.TooSmall, + b, + ); + const tx = testContract.sub.callAsync(a, b); + return expect(tx).to.revertWith(expectedError); + }); }); describe('mul()', () => { diff --git a/packages/utils/src/fixed_math_revert_errors.ts b/packages/utils/src/fixed_math_revert_errors.ts index b405653e6d..0782600611 100644 --- a/packages/utils/src/fixed_math_revert_errors.ts +++ b/packages/utils/src/fixed_math_revert_errors.ts @@ -10,7 +10,6 @@ export enum ValueErrorCodes { export enum BinOpErrorCodes { AdditionOverflow, - SubtractionUnderflow, MultiplicationOverflow, DivisionByZero, } From 09c0b83fe36ed660a5261d571c7c370dc1cdcbcc Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Thu, 10 Oct 2019 09:13:25 +0900 Subject: [PATCH 59/87] `@0x/utils`: Consolidated FixedMathRevertErrors --- packages/utils/CHANGELOG.json | 9 +++++++++ packages/utils/src/fixed_math_revert_errors.ts | 1 + 2 files changed, 10 insertions(+) diff --git a/packages/utils/CHANGELOG.json b/packages/utils/CHANGELOG.json index c9fd40d73f..c35b30f6fa 100644 --- a/packages/utils/CHANGELOG.json +++ b/packages/utils/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "4.6.0-beta.1", + "changes": [ + { + "note": "Consolidated FixedMathRevertErrors", + "pr": "TODO" + } + ] + }, { "version": "4.6.0-beta.0", "changes": [ diff --git a/packages/utils/src/fixed_math_revert_errors.ts b/packages/utils/src/fixed_math_revert_errors.ts index 0782600611..5fb1f3ffc4 100644 --- a/packages/utils/src/fixed_math_revert_errors.ts +++ b/packages/utils/src/fixed_math_revert_errors.ts @@ -12,6 +12,7 @@ export enum BinOpErrorCodes { AdditionOverflow, MultiplicationOverflow, DivisionByZero, + DivisionOverflow, } export class SignedValueError extends RevertError { From 063d6ff24e7b3a135e3b232b76ffae3c9a5f6a39 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Thu, 10 Oct 2019 09:15:00 +0900 Subject: [PATCH 60/87] `@0x/contracts-staking`: Add more overflow safeguards to `LibFixedMath`. --- .../contracts/src/libs/LibFixedMath.sol | 13 ++ .../src/libs/LibFixedMathRichErrors.sol | 3 +- .../test/unit_tests/lib_fixed_math_test.ts | 189 +++++++++++++++++- 3 files changed, 193 insertions(+), 12 deletions(-) diff --git a/contracts/staking/contracts/src/libs/LibFixedMath.sol b/contracts/staking/contracts/src/libs/LibFixedMath.sol index dc5ed65802..d5c3e52f76 100644 --- a/contracts/staking/contracts/src/libs/LibFixedMath.sol +++ b/contracts/staking/contracts/src/libs/LibFixedMath.sol @@ -95,6 +95,12 @@ library LibFixedMath { /// @dev Returns the absolute value of a fixed point number. function abs(int256 f) internal pure returns (int256 c) { + if (f == MIN_FIXED_VAL) { + LibRichErrors.rrevert(LibFixedMathRichErrors.SignedValueError( + LibFixedMathRichErrors.ValueErrorCodes.TOO_SMALL, + f + )); + } if (f >= 0) { c = f; } else { @@ -361,6 +367,13 @@ library LibFixedMath { b )); } + if (a == MIN_FIXED_VAL && b == -1) { + LibRichErrors.rrevert(LibFixedMathRichErrors.BinOpError( + LibFixedMathRichErrors.BinOpErrorCodes.DIVISION_OVERFLOW, + a, + b + )); + } c = a / b; } diff --git a/contracts/staking/contracts/src/libs/LibFixedMathRichErrors.sol b/contracts/staking/contracts/src/libs/LibFixedMathRichErrors.sol index 4a4f111fcb..5b310150f4 100644 --- a/contracts/staking/contracts/src/libs/LibFixedMathRichErrors.sol +++ b/contracts/staking/contracts/src/libs/LibFixedMathRichErrors.sol @@ -31,7 +31,8 @@ library LibFixedMathRichErrors { enum BinOpErrorCodes { ADDITION_OVERFLOW, MULTIPLICATION_OVERFLOW, - DIVISION_BY_ZERO + DIVISION_BY_ZERO, + DIVISION_OVERFLOW } // bytes4(keccak256("SignedValueError(uint8,int256)")) diff --git a/contracts/staking/test/unit_tests/lib_fixed_math_test.ts b/contracts/staking/test/unit_tests/lib_fixed_math_test.ts index eebfeaecbe..e2f2c8f48c 100644 --- a/contracts/staking/test/unit_tests/lib_fixed_math_test.ts +++ b/contracts/staking/test/unit_tests/lib_fixed_math_test.ts @@ -7,7 +7,7 @@ import { artifacts, TestLibFixedMathContract } from '../../src'; import { assertRoughlyEquals, fromFixed, toDecimal, toFixed } from '../utils/number_utils'; -blockchainTests.only('LibFixedMath unit tests', env => { +blockchainTests('LibFixedMath unit tests', env => { let testContract: TestLibFixedMathContract; before(async () => { @@ -21,6 +21,7 @@ blockchainTests.only('LibFixedMath unit tests', env => { const BITS_OF_PRECISION = 127; const FIXED_POINT_DIVISOR = new BigNumber(2).pow(BITS_OF_PRECISION); + const FIXED_1 = FIXED_POINT_DIVISOR; const MAX_FIXED_VALUE = new BigNumber(2).pow(255).minus(1); const MIN_FIXED_VALUE = new BigNumber(2).pow(255).times(-1); const MIN_EXP_NUMBER = new BigNumber('-63.875'); @@ -60,7 +61,35 @@ blockchainTests.only('LibFixedMath unit tests', env => { it('abs(0) == 0', async () => { const n = 0; const r = await testContract.abs.callAsync(toFixed(n)); - assertFixedEquals(r, n); + expect(r).to.bignumber.eq(0); + }); + + it('abs(MAX_FIXED) == MAX_FIXED', async () => { + const n = MAX_FIXED_VALUE; + const r = await testContract.abs.callAsync(n); + expect(r).to.bignumber.eq(n); + }); + + it('abs(MIN_FIXED) throws', async () => { + const n = MIN_FIXED_VALUE; + const expectedError = new FixedMathRevertErrors.SignedValueError( + FixedMathRevertErrors.ValueErrorCodes.TooSmall, + n, + ); + const tx = testContract.abs.callAsync(n); + return expect(tx).to.revertWith(expectedError); + }); + + it('abs(int(-1)) == int(1)', async () => { + const n = -1; + const r = await testContract.abs.callAsync(new BigNumber(n)); + expect(r).to.bignumber.eq(1); + }); + + it('abs(int(1)) == int(1)', async () => { + const n = 1; + const r = await testContract.abs.callAsync(new BigNumber(n)); + expect(r).to.bignumber.eq(1); }); }); @@ -132,18 +161,62 @@ blockchainTests.only('LibFixedMath unit tests', env => { return expect(tx).to.revertWith(expectedError); }); - it('int(-1) * int(1) / int(-1) == int(1)', async () => { + it('mulDiv(int(-1), int(1), int(-1)) == int(1)', async () => { const [a, n, d] = [-1, 1, -1]; const r = await testContract.mulDiv.callAsync(new BigNumber(a), new BigNumber(n), new BigNumber(d)); assertFixedEquals(r, fromFixed(1)); }); - it('-1 * int(1) / int(-1) == 1', async () => { - const [a, n, d] = [-1, 1, -1]; - const r = await testContract.mulDiv.callAsync(toFixed(a), new BigNumber(n), new BigNumber(d)); - assertFixedEquals(r, 1); + it('mulDiv(int(1), int(-1), int(-1)) == int(1)', async () => { + const [a, n, d] = [1, -1, -1]; + const r = await testContract.mulDiv.callAsync(new BigNumber(a), new BigNumber(n), new BigNumber(d)); + assertFixedEquals(r, fromFixed(1)); + }); + + it('mulDiv(MIN_FIXED, int(-1), int(1)) throws', async () => { + const [a, n, d] = [MIN_FIXED_VALUE, -1, 1]; + const expectedError = new FixedMathRevertErrors.BinOpError( + FixedMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow, + a, + n, + ); + const tx = testContract.mulDiv.callAsync(a, new BigNumber(n), new BigNumber(d)); + return expect(tx).to.revertWith(expectedError); + }); + + it('mulDiv(MIN_FIXED, int(-1), int(1)) throws', async () => { + const [a, n, d] = [MIN_FIXED_VALUE, -1, 1]; + const expectedError = new FixedMathRevertErrors.BinOpError( + FixedMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow, + a, + n, + ); + const tx = testContract.mulDiv.callAsync(a, new BigNumber(n), new BigNumber(d)); + return expect(tx).to.revertWith(expectedError); }); + it('mulDiv(MIN_FIXED, int(1), int(-1)) throws', async () => { + const [a, n, d] = [MIN_FIXED_VALUE, 1, -1]; + const expectedError = new FixedMathRevertErrors.BinOpError( + FixedMathRevertErrors.BinOpErrorCodes.DivisionOverflow, + a, + d, + ); + const tx = testContract.mulDiv.callAsync(a, new BigNumber(n), new BigNumber(d)); + return expect(tx).to.revertWith(expectedError); + }); + + it('mulDiv(MAX_FIXED, int(-1), int(1)) == -MAX_FIXED', async () => { + const [a, n, d] = [MAX_FIXED_VALUE, -1, 1]; + const r = await testContract.mulDiv.callAsync(a, new BigNumber(n), new BigNumber(d)); + expect(r).to.bignumber.eq(MAX_FIXED_VALUE.negated()); + }); + + it('mulDiv(MAX_FIXED, int(1), int(-1)) == -MAX_FIXED', async () => { + const [a, n, d] = [MAX_FIXED_VALUE, 1, -1]; + const r = await testContract.mulDiv.callAsync(a, new BigNumber(n), new BigNumber(d)); + expect(r).to.bignumber.eq(MAX_FIXED_VALUE.negated()); + }); }); describe('add()', () => { @@ -269,9 +342,8 @@ blockchainTests.only('LibFixedMath unit tests', env => { const [a, b] = [MIN_FIXED_VALUE, MIN_FIXED_VALUE]; // This fails because `-MIN_FIXED_VALUE == MIN_FIXED_VALUE` because of // twos-complement. - const expectedError = new FixedMathRevertErrors.BinOpError( - FixedMathRevertErrors.BinOpErrorCodes.AdditionOverflow, - a, + const expectedError = new FixedMathRevertErrors.SignedValueError( + FixedMathRevertErrors.ValueErrorCodes.TooSmall, b, ); const tx = testContract.sub.callAsync(a, b); @@ -281,7 +353,7 @@ blockchainTests.only('LibFixedMath unit tests', env => { it('MAX_FIXED - MAX_FIXED == 0', async () => { const [a, b] = [MAX_FIXED_VALUE, MAX_FIXED_VALUE]; const r = await testContract.sub.callAsync(a, b); - return expect(r).to.bignumber.eq(0); + expect(r).to.bignumber.eq(0); }); it('MIN_FIXED - MAX_FIXED throws', async () => { @@ -366,6 +438,73 @@ blockchainTests.only('LibFixedMath unit tests', env => { const tx = testContract.mul.callAsync(a, b); return expect(tx).to.revertWith(expectedError); }); + + it('MAX_FIXED * int(1) == MAX_FIXED / FIXED_1', async () => { + const [a, b] = [MAX_FIXED_VALUE, 1]; + const r = await testContract.mul.callAsync(a, new BigNumber(b)); + expect(r).to.bignumber.eq(MAX_FIXED_VALUE.dividedToIntegerBy(FIXED_1)); + }); + + it('MAX_FIXED * int(2) throws', async () => { + const [a, b] = [MAX_FIXED_VALUE, 2]; + const expectedError = new FixedMathRevertErrors.BinOpError( + FixedMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow, + a, + b, + ); + const tx = testContract.mul.callAsync(a, new BigNumber(b)); + return expect(tx).to.revertWith(expectedError); + }); + + it('MAX_FIXED * MAX_FIXED throws', async () => { + const [a, b] = [MAX_FIXED_VALUE, MAX_FIXED_VALUE]; + const expectedError = new FixedMathRevertErrors.BinOpError( + FixedMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow, + a, + b, + ); + const tx = testContract.mul.callAsync(a, b); + return expect(tx).to.revertWith(expectedError); + }); + + it('MIN_FIXED * MIN_FIXED throws', async () => { + const [a, b] = [MIN_FIXED_VALUE, MIN_FIXED_VALUE]; + const expectedError = new FixedMathRevertErrors.BinOpError( + FixedMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow, + a, + b, + ); + const tx = testContract.mul.callAsync(a, b); + return expect(tx).to.revertWith(expectedError); + }); + + it('MAX_FIXED * MIN_FIXED throws', async () => { + const [a, b] = [MAX_FIXED_VALUE, MIN_FIXED_VALUE]; + const expectedError = new FixedMathRevertErrors.BinOpError( + FixedMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow, + a, + b, + ); + const tx = testContract.mul.callAsync(a, b); + return expect(tx).to.revertWith(expectedError); + }); + + it('MIN_FIXED * int(-1) throws', async () => { + const [a, b] = [MIN_FIXED_VALUE, -1]; + const expectedError = new FixedMathRevertErrors.BinOpError( + FixedMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow, + a, + b, + ); + const tx = testContract.mul.callAsync(a, new BigNumber(b)); + return expect(tx).to.revertWith(expectedError); + }); + + it('MAX_FIXED * int(-1) == -MAX_FIXED / FIXED_1', async () => { + const [a, b] = [MAX_FIXED_VALUE, -1]; + const r = await testContract.mul.callAsync(a, new BigNumber(b)); + expect(r).to.bignumber.eq(MAX_FIXED_VALUE.negated().dividedToIntegerBy(FIXED_1)); + }); }); describe('div()', () => { @@ -411,6 +550,34 @@ blockchainTests.only('LibFixedMath unit tests', env => { const r = await testContract.div.callAsync(toFixed(a), toFixed(b)); assertFixedEquals(r, div(a, b)); }); + + it('MIN_FIXED / int(-1) throws', async () => { + const [a, b] = [MIN_FIXED_VALUE, -1]; + const expectedError = new FixedMathRevertErrors.BinOpError( + FixedMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow, + a, + FIXED_1, + ); + const tx = testContract.div.callAsync(a, new BigNumber(b)); + return expect(tx).to.revertWith(expectedError); + }); + + it('MAX_FIXED / int(-1) throws', async () => { + const [a, b] = [MIN_FIXED_VALUE, -1]; + const expectedError = new FixedMathRevertErrors.BinOpError( + FixedMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow, + a, + FIXED_1, + ); + const tx = testContract.div.callAsync(a, new BigNumber(b)); + return expect(tx).to.revertWith(expectedError); + }); + + it('int(-1) / MIN_FIXED == 0', async () => { + const [a, b] = [-1, MIN_FIXED_VALUE]; + const r = await testContract.div.callAsync(new BigNumber(a), b); + expect(r).to.bignumber.eq(0); + }); }); describe('uintMul()', () => { From 22fc0b43372082999828787d2a3baae4388ffaf8 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Thu, 10 Oct 2019 09:31:53 +0900 Subject: [PATCH 61/87] `@0x/contracts-staking`: Add another `LibFixedMath.add()` test. --- contracts/staking/CHANGELOG.json | 9 +++++++++ contracts/staking/test/unit_tests/lib_fixed_math_test.ts | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/contracts/staking/CHANGELOG.json b/contracts/staking/CHANGELOG.json index 6ffc8f5be0..8e7a3d3a51 100644 --- a/contracts/staking/CHANGELOG.json +++ b/contracts/staking/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "1.1.0-beta.1", + "changes": [ + { + "note": "Add more overflow safeguards to `LibFixedMath`", + "pr": "TODO" + } + ] + }, { "version": "1.1.0-beta.0", "changes": [ diff --git a/contracts/staking/test/unit_tests/lib_fixed_math_test.ts b/contracts/staking/test/unit_tests/lib_fixed_math_test.ts index e2f2c8f48c..6dd3a42fdf 100644 --- a/contracts/staking/test/unit_tests/lib_fixed_math_test.ts +++ b/contracts/staking/test/unit_tests/lib_fixed_math_test.ts @@ -291,6 +291,12 @@ blockchainTests('LibFixedMath unit tests', env => { const r = await testContract.add.callAsync(a, b); expect(r).to.bignumber.eq(-1); }); + + it('MAX_FIXED + (MIN_FIXED + int(1)) == 0', async () => { + const [a, b] = [MAX_FIXED_VALUE, MIN_FIXED_VALUE.plus(1)]; + const r = await testContract.add.callAsync(a, b); + expect(r).to.bignumber.eq(0); + }); }); describe('sub()', () => { From a22ba8647c1bdcb6f992c2b4338a4286d9712e4f Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Thu, 10 Oct 2019 09:41:57 +0900 Subject: [PATCH 62/87] Update changelogs --- contracts/staking/CHANGELOG.json | 2 +- packages/utils/CHANGELOG.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/staking/CHANGELOG.json b/contracts/staking/CHANGELOG.json index 8e7a3d3a51..51328f4e8c 100644 --- a/contracts/staking/CHANGELOG.json +++ b/contracts/staking/CHANGELOG.json @@ -4,7 +4,7 @@ "changes": [ { "note": "Add more overflow safeguards to `LibFixedMath`", - "pr": "TODO" + "pr": 2255 } ] }, diff --git a/packages/utils/CHANGELOG.json b/packages/utils/CHANGELOG.json index c35b30f6fa..356ae9535e 100644 --- a/packages/utils/CHANGELOG.json +++ b/packages/utils/CHANGELOG.json @@ -4,7 +4,7 @@ "changes": [ { "note": "Consolidated FixedMathRevertErrors", - "pr": "TODO" + "pr": 2255 } ] }, From 7e58385a788cbea2948658e95961307e49428ba1 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Thu, 10 Oct 2019 15:00:35 +0900 Subject: [PATCH 63/87] Separate immutable contracts, only inherit as needed --- contracts/staking/contracts/src/StakingProxy.sol | 4 +++- .../contracts/src/immutable/MixinConstants.sol | 15 +-------------- .../contracts/src/immutable/MixinStorage.sol | 1 - .../contracts/src/stake/MixinStakeBalances.sol | 4 +++- .../src/staking_pools/MixinCumulativeRewards.sol | 4 +++- .../staking/contracts/src/sys/MixinParams.sol | 4 +++- 6 files changed, 13 insertions(+), 19 deletions(-) diff --git a/contracts/staking/contracts/src/StakingProxy.sol b/contracts/staking/contracts/src/StakingProxy.sol index 9946df7dfa..cae4fff6af 100644 --- a/contracts/staking/contracts/src/StakingProxy.sol +++ b/contracts/staking/contracts/src/StakingProxy.sol @@ -22,13 +22,15 @@ pragma experimental ABIEncoderV2; import "./libs/LibProxy.sol"; import "./libs/LibSafeDowncast.sol"; import "./immutable/MixinStorage.sol"; +import "./immutable/MixinConstants.sol"; import "./interfaces/IStorageInit.sol"; import "./interfaces/IStakingProxy.sol"; contract StakingProxy is IStakingProxy, - MixinStorage + MixinStorage, + MixinConstants { using LibProxy for address; using LibSafeDowncast for uint256; diff --git a/contracts/staking/contracts/src/immutable/MixinConstants.sol b/contracts/staking/contracts/src/immutable/MixinConstants.sol index 837b2b1d68..942c6d8c26 100644 --- a/contracts/staking/contracts/src/immutable/MixinConstants.sol +++ b/contracts/staking/contracts/src/immutable/MixinConstants.sol @@ -18,28 +18,15 @@ pragma solidity ^0.5.9; -import "./MixinDeploymentConstants.sol"; +contract MixinConstants { -contract MixinConstants is - MixinDeploymentConstants -{ // 100% in parts-per-million. uint32 constant internal PPM_DENOMINATOR = 10**6; - // The upper 16 bytes represent the pool id, so this would be pool id 1. See MixinStakinPool for more information. - bytes32 constant internal INITIAL_POOL_ID = 0x0000000000000000000000000000000100000000000000000000000000000000; - - // The upper 16 bytes represent the pool id, so this would be an increment of 1. See MixinStakinPool for more information. - uint256 constant internal POOL_ID_INCREMENT_AMOUNT = 0x0000000000000000000000000000000100000000000000000000000000000000; - bytes32 constant internal NIL_POOL_ID = 0x0000000000000000000000000000000000000000000000000000000000000000; address constant internal NIL_ADDRESS = 0x0000000000000000000000000000000000000000; - bytes32 constant internal UNKNOWN_STAKING_POOL_ID = 0x0000000000000000000000000000000000000000000000000000000000000000; - - uint64 constant internal INITIAL_EPOCH = 0; - uint256 constant internal MIN_TOKEN_VALUE = 10**18; } diff --git a/contracts/staking/contracts/src/immutable/MixinStorage.sol b/contracts/staking/contracts/src/immutable/MixinStorage.sol index 414aeff970..0bb150a148 100644 --- a/contracts/staking/contracts/src/immutable/MixinStorage.sol +++ b/contracts/staking/contracts/src/immutable/MixinStorage.sol @@ -29,7 +29,6 @@ import "../libs/LibStakingRichErrors.sol"; // solhint-disable max-states-count, no-empty-blocks contract MixinStorage is - MixinConstants, Authorizable { // address of staking contract diff --git a/contracts/staking/contracts/src/stake/MixinStakeBalances.sol b/contracts/staking/contracts/src/stake/MixinStakeBalances.sol index 87e275a207..37f0f73195 100644 --- a/contracts/staking/contracts/src/stake/MixinStakeBalances.sol +++ b/contracts/staking/contracts/src/stake/MixinStakeBalances.sol @@ -21,11 +21,13 @@ pragma experimental ABIEncoderV2; import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; import "../interfaces/IStructs.sol"; +import "../immutable/MixinDeploymentConstants.sol"; import "./MixinStakeStorage.sol"; contract MixinStakeBalances is - MixinStakeStorage + MixinStakeStorage, + MixinDeploymentConstants { using LibSafeMath for uint256; diff --git a/contracts/staking/contracts/src/staking_pools/MixinCumulativeRewards.sol b/contracts/staking/contracts/src/staking_pools/MixinCumulativeRewards.sol index ed5626049d..c873be205d 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinCumulativeRewards.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinCumulativeRewards.sol @@ -22,10 +22,12 @@ pragma experimental ABIEncoderV2; import "@0x/contracts-utils/contracts/src/LibFractions.sol"; import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; import "../stake/MixinStakeBalances.sol"; +import "../immutable/MixinConstants.sol"; contract MixinCumulativeRewards is - MixinStakeBalances + MixinStakeBalances, + MixinConstants { using LibSafeMath for uint256; diff --git a/contracts/staking/contracts/src/sys/MixinParams.sol b/contracts/staking/contracts/src/sys/MixinParams.sol index a242e8b35d..169578f209 100644 --- a/contracts/staking/contracts/src/sys/MixinParams.sol +++ b/contracts/staking/contracts/src/sys/MixinParams.sol @@ -20,13 +20,15 @@ pragma solidity ^0.5.9; import "@0x/contracts-utils/contracts/src/LibRichErrors.sol"; import "../immutable/MixinStorage.sol"; +import "../immutable/MixinConstants.sol"; import "../interfaces/IStakingEvents.sol"; import "../libs/LibStakingRichErrors.sol"; contract MixinParams is IStakingEvents, - MixinStorage + MixinStorage, + MixinConstants { /// @dev Set all configurable parameters at once. /// @param _epochDurationInSeconds Minimum seconds between epochs. From 361576814c83fc1a3655f8419c863165af0eb1f2 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 10 Oct 2019 15:31:10 +0900 Subject: [PATCH 64/87] Removed loadSyncedBalance and loadUnsyncedBalance --- .../contracts/src/immutable/MixinStorage.sol | 4 -- .../contracts/src/interfaces/IStructs.sol | 1 - .../contracts/src/stake/MixinStake.sol | 5 +-- .../src/stake/MixinStakeBalances.sol | 8 ++-- .../contracts/src/stake/MixinStakeStorage.sol | 42 +++++-------------- .../staking_pools/MixinStakingPoolRewards.sol | 39 ++++++++--------- .../contracts/test/TestMixinStakeStorage.sol | 8 ++-- .../unit_tests/mixin_stake_storage_test.ts | 16 +++---- 8 files changed, 47 insertions(+), 76 deletions(-) diff --git a/contracts/staking/contracts/src/immutable/MixinStorage.sol b/contracts/staking/contracts/src/immutable/MixinStorage.sol index 0bb150a148..a8ee6ac7f9 100644 --- a/contracts/staking/contracts/src/immutable/MixinStorage.sol +++ b/contracts/staking/contracts/src/immutable/MixinStorage.sol @@ -44,21 +44,17 @@ contract MixinStorage is IStructs.ReadOnlyState public readOnlyState; // mapping from StakeStatus to global stored balance - // (access using _loadSyncedBalance or _loadUnsyncedBalance) // NOTE: only Status.DELEGATED is used to access this mapping, but this format // is used for extensibility mapping (uint8 => IStructs.StoredBalance) internal _globalStakeByStatus; // mapping from StakeStatus to address of staker to stored balance - // (access using _loadSyncedBalance or _loadUnsyncedBalance) mapping (uint8 => mapping (address => IStructs.StoredBalance)) internal _ownerStakeByStatus; // Mapping from Owner to Pool Id to Amount Delegated - // (access using _loadSyncedBalance or _loadUnsyncedBalance) mapping (address => mapping (bytes32 => IStructs.StoredBalance)) internal _delegatedStakeToPoolByOwner; // Mapping from Pool Id to Amount Delegated - // (access using _loadSyncedBalance or _loadUnsyncedBalance) mapping (bytes32 => IStructs.StoredBalance) internal _delegatedStakeByPoolId; // tracking Pool Id, a unique identifier for each staking pool. diff --git a/contracts/staking/contracts/src/interfaces/IStructs.sol b/contracts/staking/contracts/src/interfaces/IStructs.sol index 4857ec04d2..3c5ca8ecc4 100644 --- a/contracts/staking/contracts/src/interfaces/IStructs.sol +++ b/contracts/staking/contracts/src/interfaces/IStructs.sol @@ -60,7 +60,6 @@ interface IStructs { /// @dev Encapsulates a balance for the current and next epochs. /// Note that these balances may be stale if the current epoch /// is greater than `currentEpoch`. - /// Always load this struct using _loadSyncedBalance or _loadUnsyncedBalance. /// @param currentEpoch the current epoch /// @param currentEpochBalance balance in the current epoch. /// @param nextEpochBalance balance in `currentEpoch+1`. diff --git a/contracts/staking/contracts/src/stake/MixinStake.sol b/contracts/staking/contracts/src/stake/MixinStake.sol index da9542b08f..08ead69be2 100644 --- a/contracts/staking/contracts/src/stake/MixinStake.sol +++ b/contracts/staking/contracts/src/stake/MixinStake.sol @@ -63,7 +63,7 @@ contract MixinStake is address staker = msg.sender; IStructs.StoredBalance memory undelegatedBalance = - _loadSyncedBalance(_ownerStakeByStatus[uint8(IStructs.StakeStatus.UNDELEGATED)][staker]); + _loadCurrentBalance(_ownerStakeByStatus[uint8(IStructs.StakeStatus.UNDELEGATED)][staker]); // stake must be undelegated in current and next epoch to be withdrawn uint256 currentWithdrawableStake = LibSafeMath.min256( @@ -111,8 +111,7 @@ contract MixinStake is { address payable staker = msg.sender; - // handle delegation; this must be done before moving stake as the - // current (out-of-sync) status is used during delegation. + // handle delegation if (from.status == IStructs.StakeStatus.DELEGATED) { _undelegateStake( from.poolId, diff --git a/contracts/staking/contracts/src/stake/MixinStakeBalances.sol b/contracts/staking/contracts/src/stake/MixinStakeBalances.sol index 37f0f73195..bc089d9651 100644 --- a/contracts/staking/contracts/src/stake/MixinStakeBalances.sol +++ b/contracts/staking/contracts/src/stake/MixinStakeBalances.sol @@ -39,7 +39,7 @@ contract MixinStakeBalances is view returns (IStructs.StoredBalance memory balance) { - balance = _loadSyncedBalance( + balance = _loadCurrentBalance( _globalStakeByStatus[uint8(IStructs.StakeStatus.DELEGATED)] ); if (stakeStatus == IStructs.StakeStatus.UNDELEGATED) { @@ -64,7 +64,7 @@ contract MixinStakeBalances is view returns (IStructs.StoredBalance memory balance) { - balance = _loadSyncedBalance( + balance = _loadCurrentBalance( _ownerStakeByStatus[uint8(stakeStatus)][staker] ); return balance; @@ -90,7 +90,7 @@ contract MixinStakeBalances is view returns (IStructs.StoredBalance memory balance) { - balance = _loadSyncedBalance(_delegatedStakeToPoolByOwner[staker][poolId]); + balance = _loadCurrentBalance(_delegatedStakeToPoolByOwner[staker][poolId]); return balance; } @@ -103,7 +103,7 @@ contract MixinStakeBalances is view returns (IStructs.StoredBalance memory balance) { - balance = _loadSyncedBalance(_delegatedStakeByPoolId[poolId]); + balance = _loadCurrentBalance(_delegatedStakeByPoolId[poolId]); return balance; } } diff --git a/contracts/staking/contracts/src/stake/MixinStakeStorage.sol b/contracts/staking/contracts/src/stake/MixinStakeStorage.sol index 6c815d0205..92d1a642ce 100644 --- a/contracts/staking/contracts/src/stake/MixinStakeStorage.sol +++ b/contracts/staking/contracts/src/stake/MixinStakeStorage.sol @@ -48,9 +48,9 @@ contract MixinStakeStorage is return; } - // load balance from storage and synchronize it - IStructs.StoredBalance memory from = _loadSyncedBalance(fromPtr); - IStructs.StoredBalance memory to = _loadSyncedBalance(toPtr); + // load current balances from storage + IStructs.StoredBalance memory from = _loadCurrentBalance(fromPtr); + IStructs.StoredBalance memory to = _loadCurrentBalance(toPtr); // sanity check on balance if (amount > from.nextEpochBalance) { @@ -71,20 +71,15 @@ contract MixinStakeStorage is _storeBalance(toPtr, to); } - /// @dev Loads a balance from storage and synchronizes its current/next fields. - /// The structs `current` field is set to `next` if the - /// current epoch is greater than the epoch in which the struct - /// was stored. - /// @param balancePtr to load and sync. - /// @return synchronized balance. - function _loadSyncedBalance(IStructs.StoredBalance storage balancePtr) + /// @dev Loads a balance from storage and updates its fields to reflect values for the current epoch. + /// @param balancePtr to load. + /// @return current balance. + function _loadCurrentBalance(IStructs.StoredBalance storage balancePtr) internal view returns (IStructs.StoredBalance memory balance) { - // load from storage balance = balancePtr; - // sync uint256 currentEpoch_ = currentEpoch; if (currentEpoch_ > balance.currentEpoch) { balance.currentEpoch = currentEpoch_.downcastToUint64(); @@ -93,21 +88,6 @@ contract MixinStakeStorage is return balance; } - /// @dev Loads a balance from storage without synchronizing its fields. - /// This function exists so that developers will have to explicitly - /// communicate that they're loading a synchronized or unsynchronized balance. - /// These balances should never be accessed directly. - /// @param balancePtr to load. - /// @return unsynchronized balance. - function _loadUnsyncedBalance(IStructs.StoredBalance storage balancePtr) - internal - pure - returns (IStructs.StoredBalance memory balance) - { - balance = balancePtr; - return balance; - } - /// @dev Increments both the `current` and `next` fields. /// @param balancePtr storage pointer to balance. /// @param amount to mint. @@ -115,7 +95,7 @@ contract MixinStakeStorage is internal { // Remove stake from balance - IStructs.StoredBalance memory balance = _loadSyncedBalance(balancePtr); + IStructs.StoredBalance memory balance = _loadCurrentBalance(balancePtr); balance.nextEpochBalance = uint256(balance.nextEpochBalance).safeAdd(amount).downcastToUint96(); balance.currentEpochBalance = uint256(balance.currentEpochBalance).safeAdd(amount).downcastToUint96(); @@ -130,7 +110,7 @@ contract MixinStakeStorage is internal { // Remove stake from balance - IStructs.StoredBalance memory balance = _loadSyncedBalance(balancePtr); + IStructs.StoredBalance memory balance = _loadCurrentBalance(balancePtr); balance.nextEpochBalance = uint256(balance.nextEpochBalance).safeSub(amount).downcastToUint96(); balance.currentEpochBalance = uint256(balance.currentEpochBalance).safeSub(amount).downcastToUint96(); @@ -145,7 +125,7 @@ contract MixinStakeStorage is internal { // Add stake to balance - IStructs.StoredBalance memory balance = _loadSyncedBalance(balancePtr); + IStructs.StoredBalance memory balance = _loadCurrentBalance(balancePtr); balance.nextEpochBalance = uint256(balance.nextEpochBalance).safeAdd(amount).downcastToUint96(); // update state @@ -159,7 +139,7 @@ contract MixinStakeStorage is internal { // Remove stake from balance - IStructs.StoredBalance memory balance = _loadSyncedBalance(balancePtr); + IStructs.StoredBalance memory balance = _loadCurrentBalance(balancePtr); balance.nextEpochBalance = uint256(balance.nextEpochBalance).safeSub(amount).downcastToUint96(); // update state diff --git a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol b/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol index 282010d6a7..35de11be6f 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol @@ -49,10 +49,8 @@ contract MixinStakingPoolRewards is member ); - // Update stored balance with synchronized version; this prevents - // redundant withdrawals. _delegatedStakeToPoolByOwner[member][poolId] = - _loadSyncedBalance(_delegatedStakeToPoolByOwner[member][poolId]); + _loadCurrentBalance(_delegatedStakeToPoolByOwner[member][poolId]); } /// @dev Computes the reward balance in ETH of the operator of a pool. @@ -268,13 +266,12 @@ contract MixinStakingPoolRewards is return 0; } - IStructs.StoredBalance memory unsyncedStake = - _loadUnsyncedBalance(_delegatedStakeToPoolByOwner[member][poolId]); + IStructs.StoredBalance memory delegatedStake = _delegatedStakeToPoolByOwner[member][poolId]; - // There can be no rewards if the last epoch when stake was synced is + // There can be no rewards if the last epoch when stake was stored is // equal to the current epoch, because all prior rewards, including // rewards finalized this epoch have been claimed. - if (unsyncedStake.currentEpoch == _currentEpoch) { + if (delegatedStake.currentEpoch == _currentEpoch) { return 0; } @@ -282,29 +279,29 @@ contract MixinStakingPoolRewards is // 1/3 Unfinalized rewards earned in `currentEpoch - 1`. reward = _computeUnfinalizedDelegatorReward( - unsyncedStake, + delegatedStake, _currentEpoch, unfinalizedMembersReward, unfinalizedMembersStake ); - // 2/3 Finalized rewards earned in epochs [`unsyncedStake.currentEpoch + 1` .. `currentEpoch - 1`] - uint256 unsyncedStakeNextEpoch = uint256(unsyncedStake.currentEpoch).safeAdd(1); + // 2/3 Finalized rewards earned in epochs [`delegatedStake.currentEpoch + 1` .. `currentEpoch - 1`] + uint256 delegatedStakeNextEpoch = uint256(delegatedStake.currentEpoch).safeAdd(1); reward = reward.safeAdd( _computeMemberRewardOverInterval( poolId, - unsyncedStake.currentEpochBalance, - unsyncedStake.currentEpoch, - unsyncedStakeNextEpoch + delegatedStake.currentEpochBalance, + delegatedStake.currentEpoch, + delegatedStakeNextEpoch ) ); - // 3/3 Finalized rewards earned in epoch `unsyncedStake.currentEpoch`. + // 3/3 Finalized rewards earned in epoch `delegatedStake.currentEpoch`. reward = reward.safeAdd( _computeMemberRewardOverInterval( poolId, - unsyncedStake.nextEpochBalance, - unsyncedStakeNextEpoch, + delegatedStake.nextEpochBalance, + delegatedStakeNextEpoch, _currentEpoch ) ); @@ -313,13 +310,13 @@ contract MixinStakingPoolRewards is } /// @dev Computes the unfinalized rewards earned by a delegator in the last epoch. - /// @param unsyncedStake Unsynced delegated stake to pool by staker + /// @param delegatedStake Amount of stake delegated to pool by a specific staker /// @param currentEpoch_ The epoch in which this call is executing /// @param unfinalizedMembersReward Unfinalized total members reward (if any). /// @param unfinalizedMembersStake Unfinalized total members stake (if any). /// @return reward Balance in WETH. function _computeUnfinalizedDelegatorReward( - IStructs.StoredBalance memory unsyncedStake, + IStructs.StoredBalance memory delegatedStake, uint256 currentEpoch_, uint256 unfinalizedMembersReward, uint256 unfinalizedMembersStake @@ -336,9 +333,9 @@ contract MixinStakingPoolRewards is // Unfinalized rewards are always earned from stake in // the prior epoch so we want the stake at `currentEpoch_-1`. - uint256 unfinalizedStakeBalance = unsyncedStake.currentEpoch >= currentEpoch_.safeSub(1) ? - unsyncedStake.currentEpochBalance : - unsyncedStake.nextEpochBalance; + uint256 unfinalizedStakeBalance = delegatedStake.currentEpoch >= currentEpoch_.safeSub(1) ? + delegatedStake.currentEpochBalance : + delegatedStake.nextEpochBalance; // Sanity check to save gas on computation if (unfinalizedStakeBalance == 0) { diff --git a/contracts/staking/contracts/test/TestMixinStakeStorage.sol b/contracts/staking/contracts/test/TestMixinStakeStorage.sol index e3eabbfa39..82882130f6 100644 --- a/contracts/staking/contracts/test/TestMixinStakeStorage.sol +++ b/contracts/staking/contracts/test/TestMixinStakeStorage.sol @@ -72,19 +72,19 @@ contract TestMixinStakeStorage is _decreaseNextBalance(testBalances[index], amount); } - function loadSyncedBalance(uint256 index) + function loadCurrentBalance(uint256 index) external returns (IStructs.StoredBalance memory balance) { - return _loadSyncedBalance(testBalances[index]); + return _loadCurrentBalance(testBalances[index]); } - function loadUnsyncedBalance(uint256 index) + function loadStaleBalance(uint256 index) external view returns (IStructs.StoredBalance memory balance) { - return _loadUnsyncedBalance(testBalances[index]); + return testBalances[index]; } function setStoredBalance( diff --git a/contracts/staking/test/unit_tests/mixin_stake_storage_test.ts b/contracts/staking/test/unit_tests/mixin_stake_storage_test.ts index 5e31f7934c..066e4077a4 100644 --- a/contracts/staking/test/unit_tests/mixin_stake_storage_test.ts +++ b/contracts/staking/test/unit_tests/mixin_stake_storage_test.ts @@ -121,24 +121,24 @@ blockchainTests.resets('MixinStakeStorage unit tests', env => { }); describe('Load balance', () => { - it('_loadSyncedBalance does not change state if balance was previously synced in the current epoch', async () => { + it('Balance does not change state if balance was previously synced in the current epoch', async () => { await testContract.setStoredBalance.awaitTransactionSuccessAsync(defaultSyncedBalance, INDEX_ZERO); - const actualBalance = await testContract.loadSyncedBalance.callAsync(INDEX_ZERO); + const actualBalance = await testContract.loadCurrentBalance.callAsync(INDEX_ZERO); expect(actualBalance).to.deep.equal(defaultSyncedBalance); }); - it('_loadSyncedBalance updates current epoch fields if the balance has not yet been synced in the current epoch', async () => { + it('Balance updates current epoch fields if the balance has not yet been synced in the current epoch', async () => { await testContract.setStoredBalance.awaitTransactionSuccessAsync(defaultUnsyncedBalance, INDEX_ZERO); - const actualBalance = await testContract.loadSyncedBalance.callAsync(INDEX_ZERO); + const actualBalance = await testContract.loadCurrentBalance.callAsync(INDEX_ZERO); expect(actualBalance).to.deep.equal(defaultSyncedBalance); }); - it('_loadUnsyncedBalance loads unsynced balance from storage without changing fields', async () => { + it('Balance loads unsynced balance from storage without changing fields', async () => { await testContract.setStoredBalance.awaitTransactionSuccessAsync(defaultUnsyncedBalance, INDEX_ZERO); - const actualBalance = await testContract.loadUnsyncedBalance.callAsync(INDEX_ZERO); + const actualBalance = await testContract.loadStaleBalance.callAsync(INDEX_ZERO); expect(actualBalance).to.deep.equal(defaultUnsyncedBalance); }); - it('_loadUnsyncedBalance loads synced balance from storage without changing fields', async () => { + it('Balance loads synced balance from storage without changing fields', async () => { await testContract.setStoredBalance.awaitTransactionSuccessAsync(defaultSyncedBalance, INDEX_ZERO); - const actualBalance = await testContract.loadUnsyncedBalance.callAsync(INDEX_ZERO); + const actualBalance = await testContract.loadStaleBalance.callAsync(INDEX_ZERO); expect(actualBalance).to.deep.equal(defaultSyncedBalance); }); }); From 65f26265446d1906841b1b28e5c29d465aac194b Mon Sep 17 00:00:00 2001 From: Alex Towle Date: Thu, 10 Oct 2019 10:58:58 -0700 Subject: [PATCH 65/87] `@0x:contracts-utils` Updated the `OwnershipTransferred` event to be closer to OpenZeppelin's event --- contracts/utils/contracts/src/Ownable.sol | 2 +- contracts/utils/contracts/src/interfaces/IOwnable.sol | 3 ++- contracts/utils/test/ownable.ts | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/contracts/utils/contracts/src/Ownable.sol b/contracts/utils/contracts/src/Ownable.sol index 77ac7e0d26..704648795b 100644 --- a/contracts/utils/contracts/src/Ownable.sol +++ b/contracts/utils/contracts/src/Ownable.sol @@ -47,7 +47,7 @@ contract Ownable is LibRichErrors.rrevert(LibOwnableRichErrors.TransferOwnerToZeroError()); } else { owner = newOwner; - emit OwnershipTransferred(newOwner); + emit OwnershipTransferred(msg.sender, newOwner); } } diff --git a/contracts/utils/contracts/src/interfaces/IOwnable.sol b/contracts/utils/contracts/src/interfaces/IOwnable.sol index cb72cf8ee5..2b15d32877 100644 --- a/contracts/utils/contracts/src/interfaces/IOwnable.sol +++ b/contracts/utils/contracts/src/interfaces/IOwnable.sol @@ -22,8 +22,9 @@ pragma solidity ^0.5.9; contract IOwnable { /// @dev Emitted by Ownable when ownership is transferred. + /// @param previousOwner The previous owner of the contract. /// @param newOwner The new owner of the contract. - event OwnershipTransferred(address newOwner); + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /// @dev Transfers ownership of the contract to a new address. /// @param newOwner The address that will become the owner. diff --git a/contracts/utils/test/ownable.ts b/contracts/utils/test/ownable.ts index 2e45914f75..d4859f730f 100644 --- a/contracts/utils/test/ownable.ts +++ b/contracts/utils/test/ownable.ts @@ -48,7 +48,7 @@ blockchainTests.resets('Ownable', env => { receipt.logs, IOwnableEvents.OwnershipTransferred, ); - expect(event).to.be.deep.eq({ newOwner: nonOwner }); + expect(event).to.be.deep.eq({ previousOwner: owner, newOwner: nonOwner }); // Ensure that the owner was actually updated const updatedOwner = await ownable.owner.callAsync(); From 8bf7c4cf486aec5d62740e3593b78f2b6307bb4a Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Thu, 10 Oct 2019 16:05:58 +0900 Subject: [PATCH 66/87] Remove unnecessary assert --- .../contracts/src/staking_pools/MixinCumulativeRewards.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/contracts/staking/contracts/src/staking_pools/MixinCumulativeRewards.sol b/contracts/staking/contracts/src/staking_pools/MixinCumulativeRewards.sol index c873be205d..e100dafa82 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinCumulativeRewards.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinCumulativeRewards.sol @@ -70,10 +70,7 @@ contract MixinCumulativeRewards is { uint256 currentEpoch_ = currentEpoch; _cumulativeRewardsByPool[poolId][currentEpoch_] = value; - // Update state to reflect the most recent cumulative reward - uint256 currentMostRecentEpoch = _cumulativeRewardsByPoolLastStored[poolId]; - assert(currentEpoch_ >= currentMostRecentEpoch); _cumulativeRewardsByPoolLastStored[poolId] = currentEpoch_; } From b0699fc2389354d92e47f09b6669f5c041b5b30f Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sun, 13 Oct 2019 08:54:03 +0900 Subject: [PATCH 67/87] Always set cumulative rewards when _withdrawAndSyncDelegatorRewards is called --- .../src/staking_pools/MixinStakingPoolRewards.sol | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol b/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol index 35de11be6f..0fc899fd4d 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol @@ -139,12 +139,10 @@ contract MixinStakingPoolRewards is } // Add a cumulative reward entry for this epoch. - if (!_isCumulativeRewardSet(_cumulativeRewardsByPool[poolId][currentEpoch])) { - _forceSetCumulativeReward( - poolId, - _getMostRecentCumulativeReward(poolId) - ); - } + _forceSetCumulativeReward( + poolId, + _getMostRecentCumulativeReward(poolId) + ); } /// @dev Handles a pool's reward at the current epoch. From ce6c05637fffd830fae82863f90b4b10e94adab4 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sun, 13 Oct 2019 08:54:27 +0900 Subject: [PATCH 68/87] Update cumulative rewards tracking tests --- contracts/staking/test/cumulative_reward_tracking_test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/staking/test/cumulative_reward_tracking_test.ts b/contracts/staking/test/cumulative_reward_tracking_test.ts index b2b4e360fc..1abd31c169 100644 --- a/contracts/staking/test/cumulative_reward_tracking_test.ts +++ b/contracts/staking/test/cumulative_reward_tracking_test.ts @@ -53,7 +53,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => { // Creates CR for epoch 1 TestAction.Delegate, ], - [], + [{ event: 'SetCumulativeReward', epoch: 0 }], ); }); it('re-delegating in the same epoch', async () => { @@ -68,7 +68,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => { // Updates CR for epoch 0 TestAction.Delegate, ], - [], + [{ event: 'SetCumulativeReward', epoch: 0 }, { event: 'SetCumulativeReward', epoch: 0 }], ); }); it('delegating in new epoch', async () => { @@ -268,7 +268,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => { // Clears CR for epoch 2 TestAction.Delegate, ], - [], + [{ event: 'SetCumulativeReward', epoch: 3 }], ); }); it('delegate in epoch 0 and 1, earn reward in epoch 3, then undelegate half', async () => { @@ -303,7 +303,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => { // Clears CR for epoch 2 TestAction.Undelegate, ], - [], + [{ event: 'SetCumulativeReward', epoch: 3 }], ); }); it('delegate in epoch 1, 2, earn rewards in epoch 3, skip to epoch 4, then delegate', async () => { From c21932d149549d3dbb5183eaae3e463b7159215e Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Sun, 13 Oct 2019 17:31:38 +0900 Subject: [PATCH 69/87] Remove _creditRewardsToPool and remove return values from finalizePool --- .../contracts/src/sys/MixinAbstract.sol | 7 +- .../contracts/src/sys/MixinFinalizer.sol | 111 ++++++------------ .../contracts/test/TestDelegatorRewards.sol | 9 +- 3 files changed, 40 insertions(+), 87 deletions(-) diff --git a/contracts/staking/contracts/src/sys/MixinAbstract.sol b/contracts/staking/contracts/src/sys/MixinAbstract.sol index a5ee43efbc..2ca468b689 100644 --- a/contracts/staking/contracts/src/sys/MixinAbstract.sol +++ b/contracts/staking/contracts/src/sys/MixinAbstract.sol @@ -35,12 +35,7 @@ contract MixinAbstract { /// @return membersStake The total stake for all non-operator members in /// this pool. function finalizePool(bytes32 poolId) - public - returns ( - uint256 operatorReward, - uint256 membersReward, - uint256 membersStake - ); + public; /// @dev Computes the reward owed to a pool during finalization. /// Does nothing if the pool is already finalized. diff --git a/contracts/staking/contracts/src/sys/MixinFinalizer.sol b/contracts/staking/contracts/src/sys/MixinFinalizer.sol index 0db85a3e4c..72c9907d9c 100644 --- a/contracts/staking/contracts/src/sys/MixinFinalizer.sol +++ b/contracts/staking/contracts/src/sys/MixinFinalizer.sol @@ -96,54 +96,61 @@ contract MixinFinalizer is /// to finalize a pool immediately. Does nothing if the pool is already /// finalized or was not active in the previous epoch. /// @param poolId The pool ID to finalize. - /// @return operatorReward The reward credited to the pool operator. - /// @return membersReward The reward credited to the pool members. - /// @return membersStake The total stake for all non-operator members in - /// this pool. function finalizePool(bytes32 poolId) public - returns ( - uint256 operatorReward, - uint256 membersReward, - uint256 membersStake - ) { - uint256 epoch = currentEpoch; - // There are no pools to finalize at epoch 0. - if (epoch == 0) { - return (0, 0, 0); + // Noop on epoch 0 + uint256 currentEpoch_ = currentEpoch; + if (currentEpoch_ == 0) { + return; } - uint256 prevEpoch = epoch - 1; - // Load the finalization state into memory. + // Load the finalization and pool state into memory. IStructs.UnfinalizedState memory state = unfinalizedState; - // If there are no more unfinalized pools remaining, there's nothing - // to do. + // Noop if all active pools have been finalized. if (state.poolsRemaining == 0) { - return (0, 0, 0); + return; } + uint256 prevEpoch = currentEpoch_.safeSub(1); IStructs.ActivePool memory pool = _getActivePoolFromEpoch(prevEpoch, poolId); - // Do nothing if the pool was not active or already finalized (has no fees). + + // Noop if the pool was not active or already finalized (has no fees). if (pool.feesCollected == 0) { - return (operatorReward, membersReward, membersStake); + return; } - (operatorReward, membersReward) = _creditRewardsToPool( - epoch, + // Clear the pool state so we don't finalize it again, and to recoup + // some gas. + delete _getActivePoolsFromEpoch(prevEpoch)[poolId]; + + // Compute the rewards. + uint256 rewards = _getUnfinalizedPoolRewardsFromState(pool, state); + + // Pay the operator and update rewards for the pool. + // Note that we credit at the CURRENT epoch even though these rewards + // were earned in the previous epoch. + (uint256 operatorReward, uint256 membersReward) = _syncPoolRewards( + poolId, + rewards, + pool.membersStake + ); + + // Emit an event. + emit RewardsPaid( + currentEpoch_, poolId, - pool, - state + operatorReward, + membersReward ); + uint256 totalReward = operatorReward.safeAdd(membersReward); - if (totalReward > 0) { - // Increase `totalRewardsFinalized`. - unfinalizedState.totalRewardsFinalized = - state.totalRewardsFinalized = - state.totalRewardsFinalized.safeAdd(totalReward); - } + // Increase `totalRewardsFinalized`. + unfinalizedState.totalRewardsFinalized = + state.totalRewardsFinalized = + state.totalRewardsFinalized.safeAdd(totalReward); // Decrease the number of unfinalized pools left. unfinalizedState.poolsRemaining = @@ -159,8 +166,6 @@ contract MixinFinalizer is state.rewardsAvailable.safeSub(state.totalRewardsFinalized) ); } - membersStake = pool.membersStake; - return (operatorReward, membersReward, membersStake); } /// @dev Computes the reward owed to a pool during finalization. @@ -279,46 +284,4 @@ contract MixinFinalizer is rewards = rewardsRemaining; } } - - /// @dev Credits finalization rewards to a pool that was active in the - /// last epoch. - /// @param epoch The current epoch. - /// @param poolId The pool ID to finalize. - /// @param pool The active pool to finalize. - /// @param state The current state of finalization. - /// @return operatorReward The reward credited to the pool operator. - /// @return membersReward The reward credited to the pool members. - function _creditRewardsToPool( - uint256 epoch, - bytes32 poolId, - IStructs.ActivePool memory pool, - IStructs.UnfinalizedState memory state - ) - private - returns (uint256 operatorReward, uint256 membersReward) - { - // Clear the pool state so we don't finalize it again, and to recoup - // some gas. - delete _getActivePoolsFromEpoch(epoch.safeSub(1))[poolId]; - - // Compute the rewards. - uint256 rewards = _getUnfinalizedPoolRewardsFromState(pool, state); - - // Pay the pool. - // Note that we credit at the CURRENT epoch even though these rewards - // were earned in the previous epoch. - (operatorReward, membersReward) = _syncPoolRewards( - poolId, - rewards, - pool.membersStake - ); - - // Emit an event. - emit RewardsPaid( - epoch, - poolId, - operatorReward, - membersReward - ); - } } diff --git a/contracts/staking/contracts/test/TestDelegatorRewards.sol b/contracts/staking/contracts/test/TestDelegatorRewards.sol index 0766579a9d..e91ce5954c 100644 --- a/contracts/staking/contracts/test/TestDelegatorRewards.sol +++ b/contracts/staking/contracts/test/TestDelegatorRewards.sol @@ -177,11 +177,6 @@ contract TestDelegatorRewards is /// the current epoch and emit a event, function finalizePool(bytes32 poolId) public - returns ( - uint256 operatorReward, - uint256 membersReward, - uint256 membersStake - ) { UnfinalizedPoolReward memory reward = unfinalizedPoolRewardsByEpoch[currentEpoch][poolId]; delete unfinalizedPoolRewardsByEpoch[currentEpoch][poolId]; @@ -189,8 +184,8 @@ contract TestDelegatorRewards is _setOperatorShare(poolId, reward.operatorReward, reward.membersReward); uint256 totalRewards = reward.operatorReward + reward.membersReward; - membersStake = reward.membersStake; - (operatorReward, membersReward) = + uint256 membersStake = reward.membersStake; + (uint256 operatorReward, uint256 membersReward) = _syncPoolRewards(poolId, totalRewards, membersStake); emit FinalizePool(poolId, operatorReward, membersReward, membersStake); } From 9a5752fff99d65bd7b3a43915f21ac88ac9bce93 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Mon, 14 Oct 2019 09:45:37 +0900 Subject: [PATCH 70/87] Remove unused param in Pool struct --- contracts/staking/contracts/src/interfaces/IStructs.sol | 2 -- .../staking/contracts/src/staking_pools/MixinStakingPool.sol | 1 - 2 files changed, 3 deletions(-) diff --git a/contracts/staking/contracts/src/interfaces/IStructs.sol b/contracts/staking/contracts/src/interfaces/IStructs.sol index 3c5ca8ecc4..ae3bd9d9b7 100644 --- a/contracts/staking/contracts/src/interfaces/IStructs.sol +++ b/contracts/staking/contracts/src/interfaces/IStructs.sol @@ -94,11 +94,9 @@ interface IStructs { } /// @dev Holds the metadata for a staking pool. - /// @param initialized True iff the balance struct is initialized. /// @param operator of the pool. /// @param operatorShare Fraction of the total balance owned by the operator, in ppm. struct Pool { - bool initialized; address payable operator; uint32 operatorShare; } diff --git a/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol b/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol index 64710750ef..ca1832bbab 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol @@ -65,7 +65,6 @@ contract MixinStakingPool is // create and store pool IStructs.Pool memory pool = IStructs.Pool({ - initialized: true, operator: operator, operatorShare: operatorShare }); From 4f6958b7b537a0084d64fffddc6598f5e8b04cf1 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Mon, 14 Oct 2019 09:46:06 +0900 Subject: [PATCH 71/87] Do not import @0x/contracts-extensions to fix build --- contracts/integrations/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/integrations/package.json b/contracts/integrations/package.json index ec3050c0e7..f96a82547b 100644 --- a/contracts/integrations/package.json +++ b/contracts/integrations/package.json @@ -80,7 +80,6 @@ "@0x/contracts-exchange": "^2.2.0-beta.0", "@0x/contracts-exchange-forwarder": "^3.1.0-beta.0", "@0x/contracts-exchange-libs": "^3.1.0-beta.0", - "@0x/contracts-extensions": "^4.1.0-beta.0", "@0x/contracts-multisig": "^3.2.0-beta.0", "@0x/contracts-staking": "^1.1.0-beta.0", "@0x/contracts-test-utils": "^3.2.0-beta.0", From 9d9fe882b67c99242ad38c60d49f7a8d2a00b5a4 Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Mon, 14 Oct 2019 09:58:31 +0900 Subject: [PATCH 72/87] Remove unnecessary payable keywords --- contracts/staking/contracts/src/ZrxVault.sol | 4 ++-- contracts/staking/contracts/src/interfaces/IStructs.sol | 2 +- contracts/staking/contracts/src/interfaces/IZrxVault.sol | 2 +- contracts/staking/contracts/src/stake/MixinStake.sol | 8 ++++---- .../contracts/src/staking_pools/MixinStakingPool.sol | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contracts/staking/contracts/src/ZrxVault.sol b/contracts/staking/contracts/src/ZrxVault.sol index 529a936f64..12b5462f6d 100644 --- a/contracts/staking/contracts/src/ZrxVault.sol +++ b/contracts/staking/contracts/src/ZrxVault.sol @@ -35,7 +35,7 @@ contract ZrxVault is using LibSafeMath for uint256; // Address of staking proxy contract - address payable public stakingProxyAddress; + address public stakingProxyAddress; // True iff vault has been set to Catastrophic Failure Mode bool public isInCatastrophicFailure; @@ -91,7 +91,7 @@ contract ZrxVault is /// @dev Sets the address of the StakingProxy contract. /// Note that only the contract owner can call this function. /// @param _stakingProxyAddress Address of Staking proxy contract. - function setStakingProxy(address payable _stakingProxyAddress) + function setStakingProxy(address _stakingProxyAddress) external onlyAuthorized { diff --git a/contracts/staking/contracts/src/interfaces/IStructs.sol b/contracts/staking/contracts/src/interfaces/IStructs.sol index ae3bd9d9b7..3b889f2f7b 100644 --- a/contracts/staking/contracts/src/interfaces/IStructs.sol +++ b/contracts/staking/contracts/src/interfaces/IStructs.sol @@ -97,7 +97,7 @@ interface IStructs { /// @param operator of the pool. /// @param operatorShare Fraction of the total balance owned by the operator, in ppm. struct Pool { - address payable operator; + address operator; uint32 operatorShare; } } diff --git a/contracts/staking/contracts/src/interfaces/IZrxVault.sol b/contracts/staking/contracts/src/interfaces/IZrxVault.sol index f1528f45ec..0b17be0d11 100644 --- a/contracts/staking/contracts/src/interfaces/IZrxVault.sol +++ b/contracts/staking/contracts/src/interfaces/IZrxVault.sol @@ -50,7 +50,7 @@ interface IZrxVault { /// @dev Sets the address of the StakingProxy contract. /// Note that only the contract staker can call this function. /// @param _stakingProxyAddress Address of Staking proxy contract. - function setStakingProxy(address payable _stakingProxyAddress) + function setStakingProxy(address _stakingProxyAddress) external; /// @dev Vault enters into Catastrophic Failure Mode. diff --git a/contracts/staking/contracts/src/stake/MixinStake.sol b/contracts/staking/contracts/src/stake/MixinStake.sol index 08ead69be2..415792238e 100644 --- a/contracts/staking/contracts/src/stake/MixinStake.sol +++ b/contracts/staking/contracts/src/stake/MixinStake.sol @@ -35,7 +35,7 @@ contract MixinStake is function stake(uint256 amount) external { - address payable staker = msg.sender; + address staker = msg.sender; // deposit equivalent amount of ZRX into vault getZrxVault().depositFrom(staker, amount); @@ -109,7 +109,7 @@ contract MixinStake is ) external { - address payable staker = msg.sender; + address staker = msg.sender; // handle delegation if (from.status == IStructs.StakeStatus.DELEGATED) { @@ -154,7 +154,7 @@ contract MixinStake is /// @param amount Amount of stake to delegate. function _delegateStake( bytes32 poolId, - address payable staker, + address staker, uint256 amount ) private @@ -192,7 +192,7 @@ contract MixinStake is /// @param amount Amount of stake to un-delegate. function _undelegateStake( bytes32 poolId, - address payable staker, + address staker, uint256 amount ) private diff --git a/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol b/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol index ca1832bbab..8869c00c64 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol @@ -51,7 +51,7 @@ contract MixinStakingPool is returns (bytes32 poolId) { // note that an operator must be payable - address payable operator = msg.sender; + address operator = msg.sender; // compute unique id for this pool poolId = lastPoolId = bytes32(uint256(lastPoolId).safeAdd(1)); From 54a03eacd67625e7318df35bfb7d3cd1fa4b876f Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Sun, 13 Oct 2019 21:37:41 +1000 Subject: [PATCH 73/87] `@0x/contracts-staking`: Refactor `MixinCumulativeRewards` and `MixinStakingPoolRewards` to better encapsulate cumulative rewards. `@0x/contracts-staking`: Make sure we don't overwrite an existing CR. `@0x/contracts-staking`: Remove the need to initialize cumulative rewards when creating a pool. `@0x/contracts-staking`: Just return an empty CR in `_getCumulativeRewardAtEpoch()` if one can't be found. --- .../staking_pools/MixinCumulativeRewards.sol | 108 +++++++++++------- .../src/staking_pools/MixinStakingPool.sol | 4 - .../staking_pools/MixinStakingPoolRewards.sol | 35 +----- .../test/TestCumulativeRewardTracking.sol | 16 ++- .../contracts/test/TestDelegatorRewards.sol | 18 --- .../test/cumulative_reward_tracking_test.ts | 16 +-- .../cumulative_reward_tracking_simulation.ts | 9 +- 7 files changed, 94 insertions(+), 112 deletions(-) diff --git a/contracts/staking/contracts/src/staking_pools/MixinCumulativeRewards.sol b/contracts/staking/contracts/src/staking_pools/MixinCumulativeRewards.sol index e100dafa82..98bfc13a24 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinCumulativeRewards.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinCumulativeRewards.sol @@ -31,21 +31,6 @@ contract MixinCumulativeRewards is { using LibSafeMath for uint256; - /// @dev Initializes Cumulative Rewards for a given pool. - /// @param poolId Unique id of pool. - function _initializeCumulativeRewards(bytes32 poolId) - internal - { - // Sets the default cumulative reward - _forceSetCumulativeReward( - poolId, - IStructs.Fraction({ - numerator: 0, - denominator: MIN_TOKEN_VALUE - }) - ); - } - /// @dev returns true iff Cumulative Rewards are set function _isCumulativeRewardSet(IStructs.Fraction memory cumulativeReward) internal @@ -58,22 +43,71 @@ contract MixinCumulativeRewards is return cumulativeReward.denominator != 0; } - /// @dev Sets a cumulative reward for `poolId` at `epoch`. - /// This can be used to overwrite an existing value. - /// @param poolId Unique Id of pool. - /// @param value Value of cumulative reward. - function _forceSetCumulativeReward( + /// @dev Sets a pool's cumulative delegator rewards for the current epoch, + /// given the rewards earned and stake from the last epoch, which will + /// be summed with the previous cumulative rewards for this pool. + /// If the last cumulative reward epoch is the current epoch, this is a + /// no-op. + /// @param poolId The pool ID. + /// @param reward The total reward earned by pool delegators from the last epoch. + /// @param stake The total delegated stake in the pool in the last epoch. + function _addCumulativeReward( bytes32 poolId, - IStructs.Fraction memory value + uint256 reward, + uint256 stake ) internal { + // Fetch the last epoch at which we stored an entry for this pool; + // this is the most up-to-date cumulative rewards for this pool. + uint256 lastStoredEpoch = _cumulativeRewardsByPoolLastStored[poolId]; uint256 currentEpoch_ = currentEpoch; - _cumulativeRewardsByPool[poolId][currentEpoch_] = value; - // Update state to reflect the most recent cumulative reward + + // If we already have a record for this epoch, don't overwrite it. + if (lastStoredEpoch == currentEpoch_) { + return; + } + + IStructs.Fraction memory mostRecentCumulativeReward = + _cumulativeRewardsByPool[poolId][lastStoredEpoch]; + + // Compute new cumulative reward + IStructs.Fraction memory cumulativeReward; + if (_isCumulativeRewardSet(mostRecentCumulativeReward)) { + // If we have a prior cumulative reward entry, we sum them as fractions. + (cumulativeReward.numerator, cumulativeReward.denominator) = LibFractions.add( + mostRecentCumulativeReward.numerator, + mostRecentCumulativeReward.denominator, + reward, + stake + ); + // Normalize to prevent overflows in future operations. + (cumulativeReward.numerator, cumulativeReward.denominator) = LibFractions.normalize( + cumulativeReward.numerator, + cumulativeReward.denominator + ); + } else { + (cumulativeReward.numerator, cumulativeReward.denominator) = (reward, stake); + } + + // Store cumulative rewards for this epoch. + _cumulativeRewardsByPool[poolId][currentEpoch_] = cumulativeReward; _cumulativeRewardsByPoolLastStored[poolId] = currentEpoch_; } + /// @dev Sets a pool's cumulative delegator rewards for the current epoch, + /// using the last stored cumulative rewards. If we've already set + /// a CR for this epoch, this is a no-op. + /// @param poolId The pool ID. + function _updateCumulativeReward(bytes32 poolId) + internal + { + // Just create add an empty CR for this epoch, which will be added to + // the previous CR, so we end up with the previous CR being set for + // this epoch. + _addCumulativeReward(poolId, 0, 1); + } + /// @dev Computes a member's reward over a given epoch interval. /// @param poolId Uniqud Id of pool. /// @param memberStakeOverInterval Stake delegated to pool by member over @@ -100,13 +134,8 @@ contract MixinCumulativeRewards is require(beginEpoch < endEpoch, "CR_INTERVAL_INVALID"); // Sanity check begin reward - (IStructs.Fraction memory beginReward, uint256 beginRewardStoredAt) = _getCumulativeRewardAtEpoch(poolId, beginEpoch); - (IStructs.Fraction memory endReward, uint256 endRewardStoredAt) = _getCumulativeRewardAtEpoch(poolId, endEpoch); - - // If the rewards were stored at the same epoch then the computation will result in zero. - if (beginRewardStoredAt == endRewardStoredAt) { - return 0; - } + IStructs.Fraction memory beginReward = _getCumulativeRewardAtEpoch(poolId, beginEpoch); + IStructs.Fraction memory endReward = _getCumulativeRewardAtEpoch(poolId, endEpoch); // Compute reward reward = LibFractions.scaleDifference( @@ -122,7 +151,7 @@ contract MixinCumulativeRewards is /// @param poolId Unique ID of pool. /// @return cumulativeReward The most recent cumulative reward `poolId`. function _getMostRecentCumulativeReward(bytes32 poolId) - internal + private view returns (IStructs.Fraction memory cumulativeReward) { @@ -138,24 +167,21 @@ contract MixinCumulativeRewards is /// @return cumulativeReward The cumulative reward for `poolId` at `epoch`. /// @return cumulativeRewardStoredAt Epoch that the `cumulativeReward` is stored at. function _getCumulativeRewardAtEpoch(bytes32 poolId, uint256 epoch) - internal + private view - returns ( - IStructs.Fraction memory cumulativeReward, - uint256 cumulativeRewardStoredAt - ) + returns (IStructs.Fraction memory cumulativeReward) { // Return CR at `epoch`, given it's set. cumulativeReward = _cumulativeRewardsByPool[poolId][epoch]; if (_isCumulativeRewardSet(cumulativeReward)) { - return (cumulativeReward, epoch); + return cumulativeReward; } // Return CR at `epoch-1`, given it's set. uint256 lastEpoch = epoch.safeSub(1); cumulativeReward = _cumulativeRewardsByPool[poolId][lastEpoch]; if (_isCumulativeRewardSet(cumulativeReward)) { - return (cumulativeReward, lastEpoch); + return cumulativeReward; } // Return the most recent CR, given it's less than `epoch`. @@ -163,11 +189,11 @@ contract MixinCumulativeRewards is if (mostRecentEpoch < epoch) { cumulativeReward = _cumulativeRewardsByPool[poolId][mostRecentEpoch]; if (_isCumulativeRewardSet(cumulativeReward)) { - return (cumulativeReward, mostRecentEpoch); + return cumulativeReward; } } - // Could not find a CR for `epoch` - revert("CR_INVALID_EPOCH"); + // Otherwise return an empty CR. + return IStructs.Fraction(0, 1); } } diff --git a/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol b/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol index 8869c00c64..66294d7244 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinStakingPool.sol @@ -70,10 +70,6 @@ contract MixinStakingPool is }); _poolById[poolId] = pool; - // initialize cumulative rewards for this pool; - // this is used to track rewards earned by delegators. - _initializeCumulativeRewards(poolId); - // Staking pool has been created emit StakingPoolCreated(poolId, operator, operatorShare); diff --git a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol b/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol index 0fc899fd4d..3b78364784 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinStakingPoolRewards.sol @@ -20,7 +20,6 @@ pragma solidity ^0.5.9; pragma experimental ABIEncoderV2; import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol"; -import "@0x/contracts-utils/contracts/src/LibFractions.sol"; import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; import "./MixinCumulativeRewards.sol"; import "../sys/MixinAbstract.sol"; @@ -138,11 +137,9 @@ contract MixinStakingPoolRewards is getWethContract().transfer(member, balance); } - // Add a cumulative reward entry for this epoch. - _forceSetCumulativeReward( - poolId, - _getMostRecentCumulativeReward(poolId) - ); + // Ensure a cumulative reward entry exists for this epoch, + // copying the previous epoch's CR if one doesn't exist already. + _updateCumulativeReward(poolId); } /// @dev Handles a pool's reward at the current epoch. @@ -181,30 +178,8 @@ contract MixinStakingPoolRewards is if (membersReward > 0) { // Increase the balance of the pool _increasePoolRewards(poolId, membersReward); - - // Fetch the last epoch at which we stored an entry for this pool; - // this is the most up-to-date cumulative rewards for this pool. - IStructs.Fraction memory mostRecentCumulativeReward = _getMostRecentCumulativeReward(poolId); - - // Compute new cumulative reward - IStructs.Fraction memory cumulativeReward; - (cumulativeReward.numerator, cumulativeReward.denominator) = LibFractions.add( - mostRecentCumulativeReward.numerator, - mostRecentCumulativeReward.denominator, - membersReward, - membersStake - ); - // Normalize to prevent overflows. - (cumulativeReward.numerator, cumulativeReward.denominator) = LibFractions.normalize( - cumulativeReward.numerator, - cumulativeReward.denominator - ); - - // Store cumulative rewards for this epoch. - _forceSetCumulativeReward( - poolId, - cumulativeReward - ); + // Create a cumulative reward entry at the current epoch. + _addCumulativeReward(poolId, membersReward, membersStake); } return (operatorReward, membersReward); diff --git a/contracts/staking/contracts/test/TestCumulativeRewardTracking.sol b/contracts/staking/contracts/test/TestCumulativeRewardTracking.sol index bad0b3d143..94c254e7d3 100644 --- a/contracts/staking/contracts/test/TestCumulativeRewardTracking.sol +++ b/contracts/staking/contracts/test/TestCumulativeRewardTracking.sol @@ -43,16 +43,22 @@ contract TestCumulativeRewardTracking is function init() public {} - function _forceSetCumulativeReward( + function _addCumulativeReward( bytes32 poolId, - IStructs.Fraction memory value + uint256 reward, + uint256 stake ) internal { - emit SetCumulativeReward(poolId, currentEpoch); - MixinCumulativeRewards._forceSetCumulativeReward( + uint256 lastStoredEpoch = _cumulativeRewardsByPoolLastStored[poolId]; + MixinCumulativeRewards._addCumulativeReward( poolId, - value + reward, + stake ); + uint256 newLastStoredEpoch = _cumulativeRewardsByPoolLastStored[poolId]; + if (newLastStoredEpoch != lastStoredEpoch) { + emit SetCumulativeReward(poolId, currentEpoch); + } } } diff --git a/contracts/staking/contracts/test/TestDelegatorRewards.sol b/contracts/staking/contracts/test/TestDelegatorRewards.sol index e91ce5954c..f88cd9c0a6 100644 --- a/contracts/staking/contracts/test/TestDelegatorRewards.sol +++ b/contracts/staking/contracts/test/TestDelegatorRewards.sol @@ -71,7 +71,6 @@ contract TestDelegatorRewards is // Lazily initialize this pool. _poolById[poolId].operator = operatorAddress; _setOperatorShare(poolId, operatorReward, membersReward); - _initGenesisCumulativeRewards(poolId); } /// @dev Expose/wrap `_syncPoolRewards`. @@ -87,7 +86,6 @@ contract TestDelegatorRewards is // Lazily initialize this pool. _poolById[poolId].operator = operatorAddress; _setOperatorShare(poolId, operatorReward, membersReward); - _initGenesisCumulativeRewards(poolId); _syncPoolRewards( poolId, @@ -111,7 +109,6 @@ contract TestDelegatorRewards is ) external { - _initGenesisCumulativeRewards(poolId); _withdrawAndSyncDelegatorRewards( poolId, delegator @@ -136,7 +133,6 @@ contract TestDelegatorRewards is ) external { - _initGenesisCumulativeRewards(poolId); _withdrawAndSyncDelegatorRewards( poolId, delegator @@ -159,7 +155,6 @@ contract TestDelegatorRewards is ) external { - _initGenesisCumulativeRewards(poolId); _withdrawAndSyncDelegatorRewards( poolId, delegator @@ -204,19 +199,6 @@ contract TestDelegatorRewards is membersStake = reward.membersStake; } - /// @dev Create a cumulative rewards entry for a pool if one doesn't - /// already exist to get around having to create pools in advance. - function _initGenesisCumulativeRewards(bytes32 poolId) - private - { - uint256 lastRewardEpoch = _cumulativeRewardsByPoolLastStored[poolId]; - IStructs.Fraction memory cumulativeReward = - _cumulativeRewardsByPool[poolId][lastRewardEpoch]; - if (!_isCumulativeRewardSet(cumulativeReward)) { - _initializeCumulativeRewards(poolId); - } - } - /// @dev Set the operator share of a pool based on reward ratios. function _setOperatorShare( bytes32 poolId, diff --git a/contracts/staking/test/cumulative_reward_tracking_test.ts b/contracts/staking/test/cumulative_reward_tracking_test.ts index 1abd31c169..7693903d08 100644 --- a/contracts/staking/test/cumulative_reward_tracking_test.ts +++ b/contracts/staking/test/cumulative_reward_tracking_test.ts @@ -33,14 +33,10 @@ blockchainTests.resets('Cumulative Reward Tracking', env => { describe('Tracking Cumulative Rewards (CR)', () => { it('pool created at epoch 0', async () => { - await simulation.runTestAsync([], [TestAction.CreatePool], [{ event: 'SetCumulativeReward', epoch: 0 }]); + await simulation.runTestAsync([], [TestAction.CreatePool], []); }); it('pool created in epoch >0', async () => { - await simulation.runTestAsync( - [TestAction.Finalize], - [TestAction.CreatePool], - [{ event: 'SetCumulativeReward', epoch: 1 }], - ); + await simulation.runTestAsync([TestAction.Finalize], [TestAction.CreatePool], []); }); it('delegating in the same epoch pool is created', async () => { await simulation.runTestAsync( @@ -53,7 +49,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => { // Creates CR for epoch 1 TestAction.Delegate, ], - [{ event: 'SetCumulativeReward', epoch: 0 }], + [], ); }); it('re-delegating in the same epoch', async () => { @@ -68,7 +64,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => { // Updates CR for epoch 0 TestAction.Delegate, ], - [{ event: 'SetCumulativeReward', epoch: 0 }, { event: 'SetCumulativeReward', epoch: 0 }], + [], ); }); it('delegating in new epoch', async () => { @@ -268,7 +264,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => { // Clears CR for epoch 2 TestAction.Delegate, ], - [{ event: 'SetCumulativeReward', epoch: 3 }], + [], ); }); it('delegate in epoch 0 and 1, earn reward in epoch 3, then undelegate half', async () => { @@ -303,7 +299,7 @@ blockchainTests.resets('Cumulative Reward Tracking', env => { // Clears CR for epoch 2 TestAction.Undelegate, ], - [{ event: 'SetCumulativeReward', epoch: 3 }], + [], ); }); it('delegate in epoch 1, 2, earn rewards in epoch 3, skip to epoch 4, then delegate', async () => { diff --git a/contracts/staking/test/utils/cumulative_reward_tracking_simulation.ts b/contracts/staking/test/utils/cumulative_reward_tracking_simulation.ts index f92406c207..e321c0b0cb 100644 --- a/contracts/staking/test/utils/cumulative_reward_tracking_simulation.ts +++ b/contracts/staking/test/utils/cumulative_reward_tracking_simulation.ts @@ -36,7 +36,8 @@ export class CumulativeRewardTrackingSimulation { private static _extractTestLogs(txReceiptLogs: DecodedLogs): TestLog[] { const logs = []; for (const log of txReceiptLogs) { - if (log.event === TestCumulativeRewardTrackingEvents.SetCumulativeReward) { + const wantedEvents = [TestCumulativeRewardTrackingEvents.SetCumulativeReward] as string[]; + if (wantedEvents.indexOf(log.event) !== -1) { logs.push({ event: log.event, epoch: log.args.epoch.toNumber(), @@ -53,10 +54,10 @@ export class CumulativeRewardTrackingSimulation { const expectedLog = expectedSequence[i]; const actualLog = logs[i]; expect(expectedLog.event).to.exist(''); - expect(expectedLog.event, `testing event name of ${JSON.stringify(expectedLog)}`).to.be.equal( - actualLog.event, + expect(actualLog.event, `testing event name of ${JSON.stringify(expectedLog)}`).to.be.equal( + expectedLog.event, ); - expect(expectedLog.epoch, `testing epoch of ${JSON.stringify(expectedLog)}`).to.be.equal(actualLog.epoch); + expect(actualLog.epoch, `testing epoch of ${JSON.stringify(expectedLog)}`).to.be.equal(expectedLog.epoch); } } From a6603d6bd624b01671478c48a0ffd01659bb0e83 Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Mon, 14 Oct 2019 15:19:34 +1000 Subject: [PATCH 74/87] `@0x/contracts-staking`: Fix typo in `MixinCumulativeRewards` --- .../contracts/src/staking_pools/MixinCumulativeRewards.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/staking/contracts/src/staking_pools/MixinCumulativeRewards.sol b/contracts/staking/contracts/src/staking_pools/MixinCumulativeRewards.sol index 98bfc13a24..27b051c898 100644 --- a/contracts/staking/contracts/src/staking_pools/MixinCumulativeRewards.sol +++ b/contracts/staking/contracts/src/staking_pools/MixinCumulativeRewards.sol @@ -102,7 +102,7 @@ contract MixinCumulativeRewards is function _updateCumulativeReward(bytes32 poolId) internal { - // Just create add an empty CR for this epoch, which will be added to + // Just add empty rewards for this epoch, which will be added to // the previous CR, so we end up with the previous CR being set for // this epoch. _addCumulativeReward(poolId, 0, 1); From 1cf8ae590974140adfbb2f3ad9210cb8ba43d22c Mon Sep 17 00:00:00 2001 From: Alex Towle Date: Thu, 10 Oct 2019 11:09:41 -0700 Subject: [PATCH 75/87] `@0x:contracts-utils` Removed several functions from LibBytes --- contracts/utils/contracts/src/LibBytes.sol | 121 ------------------ .../utils/contracts/test/TestLibBytes.sol | 63 +-------- 2 files changed, 1 insertion(+), 183 deletions(-) diff --git a/contracts/utils/contracts/src/LibBytes.sol b/contracts/utils/contracts/src/LibBytes.sol index e5b9cd99d9..4646d3b622 100644 --- a/contracts/utils/contracts/src/LibBytes.sol +++ b/contracts/utils/contracts/src/LibBytes.sol @@ -271,33 +271,6 @@ library LibBytes { return result; } - /// @dev Pops the last 20 bytes off of a byte array by modifying its length. - /// @param b Byte array that will be modified. - /// @return The 20 byte address that was popped off. - function popLast20Bytes(bytes memory b) - internal - pure - returns (address result) - { - if (b.length < 20) { - LibRichErrors.rrevert(LibBytesRichErrors.InvalidByteOperationError( - LibBytesRichErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsTwentyRequired, - b.length, - 20 // 20 is length of address - )); - } - - // Store last 20 bytes. - result = readAddress(b, b.length - 20); - - assembly { - // Subtract 20 from byte array length. - let newLen := sub(mload(b), 20) - mstore(b, newLen) - } - return result; - } - /// @dev Tests equality of two byte arrays. /// @param lhs First byte array to compare. /// @param rhs Second byte array to compare. @@ -523,100 +496,6 @@ library LibBytes { return result; } - /// @dev Reads nested bytes from a specific position. - /// @dev NOTE: the returned value overlaps with the input value. - /// Both should be treated as immutable. - /// @param b Byte array containing nested bytes. - /// @param index Index of nested bytes. - /// @return result Nested bytes. - function readBytesWithLength( - bytes memory b, - uint256 index - ) - internal - pure - returns (bytes memory result) - { - // Read length of nested bytes - uint256 nestedBytesLength = readUint256(b, index); - index += 32; - - // Assert length of is valid, given - // length of nested bytes - if (b.length < index + nestedBytesLength) { - LibRichErrors.rrevert(LibBytesRichErrors.InvalidByteOperationError( - LibBytesRichErrors - .InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsNestedBytesLengthRequired, - b.length, - index + nestedBytesLength - )); - } - - // Return a pointer to the byte array as it exists inside `b` - assembly { - result := add(b, index) - } - return result; - } - - /// @dev Inserts bytes at a specific position in a byte array. - /// @param b Byte array to insert into. - /// @param index Index in byte array of . - /// @param input bytes to insert. - function writeBytesWithLength( - bytes memory b, - uint256 index, - bytes memory input - ) - internal - pure - { - // Assert length of is valid, given - // length of input - if (b.length < index + 32 + input.length) { - LibRichErrors.rrevert(LibBytesRichErrors.InvalidByteOperationError( - LibBytesRichErrors - .InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsNestedBytesLengthRequired, - b.length, - index + 32 + input.length // 32 bytes to store length - )); - } - - // Copy into - memCopy( - b.contentAddress() + index, - input.rawAddress(), // includes length of - input.length + 32 // +32 bytes to store length - ); - } - - /// @dev Performs a deep copy of a byte array onto another byte array of greater than or equal length. - /// @param dest Byte array that will be overwritten with source bytes. - /// @param source Byte array to copy onto dest bytes. - function deepCopyBytes( - bytes memory dest, - bytes memory source - ) - internal - pure - { - uint256 sourceLen = source.length; - // Dest length must be >= source length, or some bytes would not be copied. - if (dest.length < sourceLen) { - LibRichErrors.rrevert(LibBytesRichErrors.InvalidByteOperationError( - LibBytesRichErrors - .InvalidByteOperationErrorCodes.DestinationLengthGreaterThanOrEqualSourceLengthRequired, - dest.length, - sourceLen - )); - } - memCopy( - dest.contentAddress(), - source.contentAddress(), - sourceLen - ); - } - /// @dev Writes a new length to a byte array. /// Decreasing length will lead to removing the corresponding lower order bytes from the byte array. /// Increasing length may lead to appending adjacent in-memory bytes to the end of the byte array. diff --git a/contracts/utils/contracts/test/TestLibBytes.sol b/contracts/utils/contracts/test/TestLibBytes.sol index b2f39e5fcc..361b71164a 100644 --- a/contracts/utils/contracts/test/TestLibBytes.sol +++ b/contracts/utils/contracts/test/TestLibBytes.sol @@ -37,18 +37,6 @@ contract TestLibBytes { return (b, result); } - /// @dev Pops the last 20 bytes off of a byte array by modifying its length. - /// @param b Byte array that will be modified. - /// @return The 20 byte address that was popped off. - function publicPopLast20Bytes(bytes memory b) - public - pure - returns (bytes memory, address result) - { - result = b.popLast20Bytes(); - return (b, result); - } - /// @dev Tests equality of two byte arrays. /// @param lhs First byte array to compare. /// @param rhs Second byte array to compare. @@ -73,21 +61,6 @@ contract TestLibBytes { return equal; } - /// @dev Performs a deep copy of a byte array onto another byte array of greater than or equal length. - /// @param dest Byte array that will be overwritten with source bytes. - /// @param source Byte array to copy onto dest bytes. - function publicDeepCopyBytes( - bytes memory dest, - bytes memory source - ) - public - pure - returns (bytes memory) - { - LibBytes.deepCopyBytes(dest, source); - return dest; - } - /// @dev Reads an address from a position in a byte array. /// @param b Byte array containing an address. /// @param index Index in byte array of address. @@ -203,40 +176,6 @@ contract TestLibBytes { return result; } - /// @dev Reads nested bytes from a specific position. - /// @param b Byte array containing nested bytes. - /// @param index Index of nested bytes. - /// @return result Nested bytes. - function publicReadBytesWithLength( - bytes memory b, - uint256 index - ) - public - pure - returns (bytes memory result) - { - result = b.readBytesWithLength(index); - return result; - } - - /// @dev Inserts bytes at a specific position in a byte array. - /// @param b Byte array to insert into. - /// @param index Index in byte array of . - /// @param input bytes to insert. - /// @return b Updated input byte array - function publicWriteBytesWithLength( - bytes memory b, - uint256 index, - bytes memory input - ) - public - pure - returns (bytes memory) - { - b.writeBytesWithLength(index, input); - return b; - } - /// @dev Copies a block of memory from one location to another. /// @param mem Memory contents we want to apply memCopy to /// @param dest Destination offset into . @@ -305,7 +244,7 @@ contract TestLibBytes { } /// @dev Returns a byte array with an updated length. - /// @dev Writes a new length to a byte array. + /// @dev Writes a new length to a byte array. /// Decreasing length will lead to removing the corresponding lower order bytes from the byte array. /// Increasing length may lead to appending adjacent in-memory bytes to the end of the byte array. /// @param b Bytes array to write new length to. From 52c3dc4ad88874f300c16876e6ba1b5b4091bd41 Mon Sep 17 00:00:00 2001 From: Alex Towle Date: Thu, 10 Oct 2019 11:27:38 -0700 Subject: [PATCH 76/87] `@0x:contracts-utils` Fixed and improved the LibBytes tests --- contracts/utils/test/lib_bytes.ts | 349 +----------------------------- 1 file changed, 6 insertions(+), 343 deletions(-) diff --git a/contracts/utils/test/lib_bytes.ts b/contracts/utils/test/lib_bytes.ts index b7e90e2487..541ea43dff 100644 --- a/contracts/utils/test/lib_bytes.ts +++ b/contracts/utils/test/lib_bytes.ts @@ -1,25 +1,18 @@ -import { chaiSetup, constants, provider, txDefaults, typeEncodingUtils, web3Wrapper } from '@0x/contracts-test-utils'; -import { BlockchainLifecycle } from '@0x/dev-utils'; -import { generatePseudoRandomSalt } from '@0x/order-utils'; +import { blockchainTests, constants, expect } from '@0x/contracts-test-utils'; import { BigNumber, LibBytesRevertErrors } from '@0x/utils'; import BN = require('bn.js'); -import * as chai from 'chai'; -import ethUtil = require('ethereumjs-util'); +import * as ethUtil from 'ethereumjs-util'; import * as _ from 'lodash'; import { artifacts, TestLibBytesContract } from '../src'; -chaiSetup.configure(); -const expect = chai.expect; -const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); - // BUG: Ideally we would use fromHex(memory).toString('hex') // https://github.com/Microsoft/TypeScript/issues/23155 const toHex = (buf: Uint8Array): string => buf.reduce((a, v) => a + `00${v.toString(16)}`.slice(-2), '0x'); const fromHex = (str: string): Uint8Array => Uint8Array.from(Buffer.from(str.slice(2), 'hex')); -describe('LibBytes', () => { +blockchainTests('LibBytes', env => { let libBytes: TestLibBytesContract; const byteArrayShorterThan32Bytes = '0x012345'; const byteArrayShorterThan20Bytes = byteArrayShorterThan32Bytes; @@ -37,32 +30,17 @@ describe('LibBytes', () => { const testUint256B = new BigNumber(testBytes32B, 16); const testBytes4 = '0xabcdef12'; const testByte = '0xab'; - let shortData: string; - let shortTestBytes: string; - let shortTestBytesAsBuffer: Buffer; - let wordOfData: string; - let wordOfTestBytes: string; - let wordOfTestBytesAsBuffer: Buffer; - let longData: string; - let longTestBytes: string; - let longTestBytesAsBuffer: Buffer; - before(async () => { - await blockchainLifecycle.startAsync(); - }); - after(async () => { - await blockchainLifecycle.revertAsync(); - }); before(async () => { // Setup accounts & addresses - const accounts = await web3Wrapper.getAvailableAddressesAsync(); + const accounts = await env.getAccountAddressesAsync(); testAddress = accounts[1]; testAddressB = accounts[2]; // Deploy LibBytes libBytes = await TestLibBytesContract.deployFrom0xArtifactAsync( artifacts.TestLibBytes, - provider, - txDefaults, + env.provider, + env.txDefaults, artifacts, ); // Verify lengths of test data @@ -72,32 +50,6 @@ describe('LibBytes', () => { expect(byteArrayLongerThan32BytesLength).to.be.greaterThan(32); const testBytes32Length = ethUtil.toBuffer(testBytes32).byteLength; expect(testBytes32Length).to.be.equal(32); - // Create short test bytes - shortData = '0xffffaa'; - const encodedShortData = ethUtil.toBuffer(shortData); - const shortDataLength = new BigNumber(encodedShortData.byteLength); - const encodedShortDataLength = typeEncodingUtils.encodeUint256(shortDataLength); - shortTestBytesAsBuffer = Buffer.concat([encodedShortDataLength, encodedShortData]); - shortTestBytes = ethUtil.bufferToHex(shortTestBytesAsBuffer); - // Create test bytes one word in length - wordOfData = ethUtil.bufferToHex(typeEncodingUtils.encodeUint256(generatePseudoRandomSalt())); - const encodedWordOfData = ethUtil.toBuffer(wordOfData); - const wordOfDataLength = new BigNumber(encodedWordOfData.byteLength); - const encodedWordOfDataLength = typeEncodingUtils.encodeUint256(wordOfDataLength); - wordOfTestBytesAsBuffer = Buffer.concat([encodedWordOfDataLength, encodedWordOfData]); - wordOfTestBytes = ethUtil.bufferToHex(wordOfTestBytesAsBuffer); - // Create long test bytes (combines short test bytes with word of test bytes) - longData = ethUtil.bufferToHex(Buffer.concat([encodedShortData, encodedWordOfData])); - const longDataLength = new BigNumber(encodedShortData.byteLength + encodedWordOfData.byteLength); - const encodedLongDataLength = typeEncodingUtils.encodeUint256(longDataLength); - longTestBytesAsBuffer = Buffer.concat([encodedLongDataLength, encodedShortData, encodedWordOfData]); - longTestBytes = ethUtil.bufferToHex(longTestBytesAsBuffer); - }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); }); describe('popLastByte', () => { @@ -124,34 +76,6 @@ describe('LibBytes', () => { }); }); - describe('popLast20Bytes', () => { - it('should revert if length is less than 20', async () => { - const byteLen = fromHex(byteArrayShorterThan20Bytes).length; - const expectedError = new LibBytesRevertErrors.InvalidByteOperationError( - LibBytesRevertErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsTwentyRequired, - new BigNumber(byteLen), // length of byteArrayShorterThan20Byte - new BigNumber(20), - ); - return expect(libBytes.publicPopLast20Bytes.callAsync(byteArrayShorterThan20Bytes)).to.revertWith( - expectedError, - ); - }); - it('should pop the last 20 bytes from the input and return it when array holds more than 20 bytes', async () => { - const [newBytes, poppedAddress] = await libBytes.publicPopLast20Bytes.callAsync(byteArrayLongerThan32Bytes); - const expectedNewBytes = byteArrayLongerThan32Bytes.slice(0, -40); - const expectedPoppedAddress = `0x${byteArrayLongerThan32Bytes.slice(-40)}`; - expect(newBytes).to.equal(expectedNewBytes); - expect(poppedAddress).to.equal(expectedPoppedAddress); - }); - it('should pop the last 20 bytes from the input and return it when array is exactly 20 bytes', async () => { - const [newBytes, poppedAddress] = await libBytes.publicPopLast20Bytes.callAsync(testAddress); - const expectedNewBytes = '0x'; - const expectedPoppedAddress = testAddress; - expect(newBytes).to.equal(expectedNewBytes); - expect(poppedAddress).to.equal(expectedPoppedAddress); - }); - }); - describe('equals', () => { it('should return true if byte arrays are equal (both arrays < 32 bytes)', async () => { const isEqual = await libBytes.publicEquals.callAsync( @@ -204,48 +128,6 @@ describe('LibBytes', () => { }); }); - describe('deepCopyBytes', () => { - it('should revert if dest is shorter than source', async () => { - const endpointByteLen = (byteArrayShorterThan20Bytes.length - 2) / 2; - const requiredByteLen = (byteArrayLongerThan32Bytes.length - 2) / 2; - const expectedError = new LibBytesRevertErrors.InvalidByteOperationError( - LibBytesRevertErrors.InvalidByteOperationErrorCodes.DestinationLengthGreaterThanOrEqualSourceLengthRequired, - new BigNumber(endpointByteLen), // length of byteArrayShorterThan20Byte - new BigNumber(requiredByteLen), // length of byteArrayShorterThan20Byte - ); - return expect( - libBytes.publicDeepCopyBytes.callAsync(byteArrayShorterThan32Bytes, byteArrayLongerThan32Bytes), - ).to.revertWith(expectedError); - }); - it('should overwrite dest with source if source and dest have equal length', async () => { - const zeroedByteArrayLongerThan32Bytes = `0x${_.repeat('0', byteArrayLongerThan32Bytes.length - 2)}`; - const zeroedBytesAfterCopy = await libBytes.publicDeepCopyBytes.callAsync( - zeroedByteArrayLongerThan32Bytes, - byteArrayLongerThan32Bytes, - ); - return expect(zeroedBytesAfterCopy).to.be.equal(byteArrayLongerThan32Bytes); - }); - it('should overwrite the leftmost len(source) bytes of dest if dest is larger than source', async () => { - const zeroedByteArrayLongerThan32Bytes = `0x${_.repeat('0', byteArrayLongerThan32Bytes.length * 2)}`; - const zeroedBytesAfterCopy = await libBytes.publicDeepCopyBytes.callAsync( - zeroedByteArrayLongerThan32Bytes, - byteArrayLongerThan32Bytes, - ); - const copiedBytes = zeroedBytesAfterCopy.slice(0, byteArrayLongerThan32Bytes.length); - return expect(copiedBytes).to.be.equal(byteArrayLongerThan32Bytes); - }); - it('should not overwrite the rightmost bytes of dest if dest is larger than source', async () => { - const zeroedByteArrayLongerThan32Bytes = `0x${_.repeat('0', byteArrayLongerThan32Bytes.length * 2)}`; - const zeroedBytesAfterCopy = await libBytes.publicDeepCopyBytes.callAsync( - zeroedByteArrayLongerThan32Bytes, - byteArrayLongerThan32Bytes, - ); - const expectedNotCopiedBytes = zeroedByteArrayLongerThan32Bytes.slice(byteArrayLongerThan32Bytes.length); - const notCopiedBytes = zeroedBytesAfterCopy.slice(byteArrayLongerThan32Bytes.length); - return expect(notCopiedBytes).to.be.equal(expectedNotCopiedBytes); - }); - }); - describe('readAddress', () => { it('should successfully read address when the address takes up the whole array', async () => { const byteArray = ethUtil.addHexPrefix(testAddress); @@ -576,225 +458,6 @@ describe('LibBytes', () => { }); }); - describe('readBytesWithLength', () => { - it('should successfully read short, nested array of bytes when it takes up the whole array', async () => { - const testBytesOffset = new BigNumber(0); - const bytes = await libBytes.publicReadBytesWithLength.callAsync(shortTestBytes, testBytesOffset); - return expect(bytes).to.be.equal(shortData); - }); - it('should successfully read short, nested array of bytes when it is offset in the array', async () => { - const prefixByteArrayBuffer = ethUtil.toBuffer('0xabcdef'); - const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, shortTestBytesAsBuffer]); - const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer); - const testUint256Offset = new BigNumber(prefixByteArrayBuffer.byteLength); - const bytes = await libBytes.publicReadBytesWithLength.callAsync(combinedByteArray, testUint256Offset); - return expect(bytes).to.be.equal(shortData); - }); - it('should successfully read a nested array of bytes - one word in length - when it takes up the whole array', async () => { - const testBytesOffset = new BigNumber(0); - const bytes = await libBytes.publicReadBytesWithLength.callAsync(wordOfTestBytes, testBytesOffset); - return expect(bytes).to.be.equal(wordOfData); - }); - it('should successfully read a nested array of bytes - one word in length - when it is offset in the array', async () => { - const prefixByteArrayBuffer = ethUtil.toBuffer('0xabcdef'); - const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, wordOfTestBytesAsBuffer]); - const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer); - const testUint256Offset = new BigNumber(prefixByteArrayBuffer.byteLength); - const bytes = await libBytes.publicReadBytesWithLength.callAsync(combinedByteArray, testUint256Offset); - return expect(bytes).to.be.equal(wordOfData); - }); - it('should successfully read long, nested array of bytes when it takes up the whole array', async () => { - const testBytesOffset = new BigNumber(0); - const bytes = await libBytes.publicReadBytesWithLength.callAsync(longTestBytes, testBytesOffset); - return expect(bytes).to.be.equal(longData); - }); - it('should successfully read long, nested array of bytes when it is offset in the array', async () => { - const prefixByteArrayBuffer = ethUtil.toBuffer('0xabcdef'); - const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, longTestBytesAsBuffer]); - const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer); - const testUint256Offset = new BigNumber(prefixByteArrayBuffer.byteLength); - const bytes = await libBytes.publicReadBytesWithLength.callAsync(combinedByteArray, testUint256Offset); - return expect(bytes).to.be.equal(longData); - }); - it('should fail if the byte array is too short to hold the length of a nested byte array', async () => { - // The length of the nested array is 32 bytes. By storing less than 32 bytes, a length cannot be read. - const offset = new BigNumber(0); - const byteLen = new BigNumber(fromHex(byteArrayShorterThan32Bytes).length); - const expectedError = new LibBytesRevertErrors.InvalidByteOperationError( - LibBytesRevertErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsThirtyTwoRequired, - byteLen, - new BigNumber(32), - ); - return expect( - libBytes.publicReadBytesWithLength.callAsync(byteArrayShorterThan32Bytes, offset), - ).to.revertWith(expectedError); - }); - it('should fail if we store a nested byte array length, without a nested byte array', async () => { - const offset = new BigNumber(0); - const byteLen = new BigNumber(fromHex(testBytes32).length); - const expectedError = new LibBytesRevertErrors.InvalidByteOperationError( - LibBytesRevertErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsNestedBytesLengthRequired, - byteLen, - new BigNumber(testBytes32).plus(32), - ); - return expect(libBytes.publicReadBytesWithLength.callAsync(testBytes32, offset)).to.revertWith( - expectedError, - ); - }); - it('should fail if the length between the offset and end of the byte array is too short to hold the length of a nested byte array', async () => { - const badOffset = new BigNumber(ethUtil.toBuffer(byteArrayShorterThan32Bytes).byteLength); - const expectedError = new LibBytesRevertErrors.InvalidByteOperationError( - LibBytesRevertErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsThirtyTwoRequired, - badOffset, - badOffset.plus(new BigNumber(32)), - ); - return expect( - libBytes.publicReadBytesWithLength.callAsync(byteArrayShorterThan32Bytes, badOffset), - ).to.revertWith(expectedError); - }); - it('should fail if the length between the offset and end of the byte array is too short to hold the nested byte array', async () => { - const badOffset = new BigNumber(ethUtil.toBuffer(testBytes32).byteLength); - const expectedError = new LibBytesRevertErrors.InvalidByteOperationError( - LibBytesRevertErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsThirtyTwoRequired, - badOffset, - badOffset.plus(new BigNumber(32)), - ); - return expect(libBytes.publicReadBytesWithLength.callAsync(testBytes32, badOffset)).to.revertWith( - expectedError, - ); - }); - }); - - describe('writeBytesWithLength', () => { - it('should successfully write short, nested array of bytes when it takes up the whole array', async () => { - const testBytesOffset = new BigNumber(0); - const emptyByteArray = ethUtil.bufferToHex(Buffer.alloc(shortTestBytesAsBuffer.byteLength)); - const bytesWritten = await libBytes.publicWriteBytesWithLength.callAsync( - emptyByteArray, - testBytesOffset, - shortData, - ); - const bytesRead = await libBytes.publicReadBytesWithLength.callAsync(bytesWritten, testBytesOffset); - return expect(bytesRead).to.be.equal(shortData); - }); - it('should successfully write short, nested array of bytes when it is offset in the array', async () => { - // Write a prefix to the array - const prefixData = '0xabcdef'; - const prefixDataAsBuffer = ethUtil.toBuffer(prefixData); - const prefixOffset = new BigNumber(0); - const emptyByteArray = ethUtil.bufferToHex( - Buffer.alloc(prefixDataAsBuffer.byteLength + shortTestBytesAsBuffer.byteLength), - ); - let bytesWritten = await libBytes.publicWriteBytesWithLength.callAsync( - emptyByteArray, - prefixOffset, - prefixData, - ); - // Write data after prefix - const testBytesOffset = new BigNumber(prefixDataAsBuffer.byteLength); - bytesWritten = await libBytes.publicWriteBytesWithLength.callAsync( - bytesWritten, - testBytesOffset, - shortData, - ); - // Read data after prefix and validate - const bytes = await libBytes.publicReadBytesWithLength.callAsync(bytesWritten, testBytesOffset); - return expect(bytes).to.be.equal(shortData); - }); - it('should successfully write a nested array of bytes - one word in length - when it takes up the whole array', async () => { - const testBytesOffset = new BigNumber(0); - const emptyByteArray = ethUtil.bufferToHex(Buffer.alloc(wordOfTestBytesAsBuffer.byteLength)); - const bytesWritten = await libBytes.publicWriteBytesWithLength.callAsync( - emptyByteArray, - testBytesOffset, - wordOfData, - ); - const bytesRead = await libBytes.publicReadBytesWithLength.callAsync(bytesWritten, testBytesOffset); - return expect(bytesRead).to.be.equal(wordOfData); - }); - it('should successfully write a nested array of bytes - one word in length - when it is offset in the array', async () => { - // Write a prefix to the array - const prefixData = '0xabcdef'; - const prefixDataAsBuffer = ethUtil.toBuffer(prefixData); - const prefixOffset = new BigNumber(0); - const emptyByteArray = ethUtil.bufferToHex( - Buffer.alloc(prefixDataAsBuffer.byteLength + wordOfTestBytesAsBuffer.byteLength), - ); - let bytesWritten = await libBytes.publicWriteBytesWithLength.callAsync( - emptyByteArray, - prefixOffset, - prefixData, - ); - // Write data after prefix - const testBytesOffset = new BigNumber(prefixDataAsBuffer.byteLength); - bytesWritten = await libBytes.publicWriteBytesWithLength.callAsync( - bytesWritten, - testBytesOffset, - wordOfData, - ); - // Read data after prefix and validate - const bytes = await libBytes.publicReadBytesWithLength.callAsync(bytesWritten, testBytesOffset); - return expect(bytes).to.be.equal(wordOfData); - }); - it('should successfully write a long, nested bytes when it takes up the whole array', async () => { - const testBytesOffset = new BigNumber(0); - const emptyByteArray = ethUtil.bufferToHex(Buffer.alloc(longTestBytesAsBuffer.byteLength)); - const bytesWritten = await libBytes.publicWriteBytesWithLength.callAsync( - emptyByteArray, - testBytesOffset, - longData, - ); - const bytesRead = await libBytes.publicReadBytesWithLength.callAsync(bytesWritten, testBytesOffset); - return expect(bytesRead).to.be.equal(longData); - }); - it('should successfully write long, nested array of bytes when it is offset in the array', async () => { - // Write a prefix to the array - const prefixData = '0xabcdef'; - const prefixDataAsBuffer = ethUtil.toBuffer(prefixData); - const prefixOffset = new BigNumber(0); - const emptyByteArray = ethUtil.bufferToHex( - Buffer.alloc(prefixDataAsBuffer.byteLength + longTestBytesAsBuffer.byteLength), - ); - let bytesWritten = await libBytes.publicWriteBytesWithLength.callAsync( - emptyByteArray, - prefixOffset, - prefixData, - ); - // Write data after prefix - const testBytesOffset = new BigNumber(prefixDataAsBuffer.byteLength); - bytesWritten = await libBytes.publicWriteBytesWithLength.callAsync(bytesWritten, testBytesOffset, longData); - // Read data after prefix and validate - const bytes = await libBytes.publicReadBytesWithLength.callAsync(bytesWritten, testBytesOffset); - return expect(bytes).to.be.equal(longData); - }); - it('should fail if the byte array is too short to hold the length of a nested byte array', async () => { - const offset = new BigNumber(0); - const emptyByteArray = ethUtil.bufferToHex(Buffer.alloc(1)); - const inputLen = new BigNumber((longData.length - 2) / 2); - const expectedError = new LibBytesRevertErrors.InvalidByteOperationError( - LibBytesRevertErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsNestedBytesLengthRequired, - new BigNumber(1), - new BigNumber(32).plus(inputLen), - ); - return expect( - libBytes.publicWriteBytesWithLength.callAsync(emptyByteArray, offset, longData), - ).to.revertWith(expectedError); - }); - it('should fail if the length between the offset and end of the byte array is too short to hold the length of a nested byte array', async () => { - const emptyByteArray = ethUtil.bufferToHex(Buffer.alloc(shortTestBytesAsBuffer.byteLength)); - const badOffset = new BigNumber(ethUtil.toBuffer(shortTestBytesAsBuffer).byteLength); - const inputLen = new BigNumber((shortData.length - 2) / 2); - const expectedError = new LibBytesRevertErrors.InvalidByteOperationError( - LibBytesRevertErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsNestedBytesLengthRequired, - badOffset, - badOffset.plus(new BigNumber(32)).plus(inputLen), - ); - return expect( - libBytes.publicWriteBytesWithLength.callAsync(emptyByteArray, badOffset, shortData), - ).to.revertWith(expectedError); - }); - }); - describe('memCopy', () => { // Create memory 0x000102...FF const memSize = 256; From 7283a1671065499737af7e9d8728547c3f972dfb Mon Sep 17 00:00:00 2001 From: Alex Towle Date: Thu, 10 Oct 2019 11:38:25 -0700 Subject: [PATCH 77/87] `@0x:contracts-utils` Updated changelog --- contracts/utils/CHANGELOG.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contracts/utils/CHANGELOG.json b/contracts/utils/CHANGELOG.json index 5820e68076..acea499521 100644 --- a/contracts/utils/CHANGELOG.json +++ b/contracts/utils/CHANGELOG.json @@ -65,6 +65,10 @@ { "note": "Emit an event in `transferOwnership`", "pr": 2253 + }, + { + "note": "Removed `deepCopyBytes`, `popLast20Bytes`, `readBytesWithLength`, and `writeBytesWithLength` in `LibBytes`.", + "pr": 2265 } ], "timestamp": 1570135330 From 6f5c62914e8d45486614c8b2d17296683d32c479 Mon Sep 17 00:00:00 2001 From: Alex Towle Date: Tue, 8 Oct 2019 22:38:44 -0700 Subject: [PATCH 78/87] `@0x:contracts-multisig` Switched to SafeMath in `pastTimeLock` --- .../multisig/contracts/src/MultiSigWalletWithTimeLock.sol | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contracts/multisig/contracts/src/MultiSigWalletWithTimeLock.sol b/contracts/multisig/contracts/src/MultiSigWalletWithTimeLock.sol index aab693e44a..72b616da68 100644 --- a/contracts/multisig/contracts/src/MultiSigWalletWithTimeLock.sol +++ b/contracts/multisig/contracts/src/MultiSigWalletWithTimeLock.sol @@ -18,6 +18,7 @@ pragma solidity ^0.5.9; +import "@0x/contracts-utils/contracts/src/SafeMath.sol"; import "./MultiSigWallet.sol"; @@ -25,8 +26,10 @@ import "./MultiSigWallet.sol"; /// @author Amir Bandeali - // solhint-disable not-rely-on-time contract MultiSigWalletWithTimeLock is - MultiSigWallet + MultiSigWallet, + SafeMath { + event ConfirmationTimeSet(uint256 indexed transactionId, uint256 confirmationTime); event TimeLockChange(uint256 secondsTimeLocked); @@ -52,7 +55,7 @@ contract MultiSigWalletWithTimeLock is modifier pastTimeLock(uint256 transactionId) { require( - block.timestamp >= confirmationTimes[transactionId] + secondsTimeLocked, + block.timestamp >= _safeAdd(confirmationTimes[transactionId], secondsTimeLocked), "TIME_LOCK_INCOMPLETE" ); _; From 90193c81978a486762f37ebde3983182ab17f6f9 Mon Sep 17 00:00:00 2001 From: Alex Towle Date: Tue, 15 Oct 2019 11:52:06 -0700 Subject: [PATCH 79/87] `@0x:contracts-multisig` Changed SafeMath to LibSafeMath --- .../multisig/contracts/src/MultiSigWalletWithTimeLock.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/multisig/contracts/src/MultiSigWalletWithTimeLock.sol b/contracts/multisig/contracts/src/MultiSigWalletWithTimeLock.sol index 72b616da68..0fa163180e 100644 --- a/contracts/multisig/contracts/src/MultiSigWalletWithTimeLock.sol +++ b/contracts/multisig/contracts/src/MultiSigWalletWithTimeLock.sol @@ -18,7 +18,7 @@ pragma solidity ^0.5.9; -import "@0x/contracts-utils/contracts/src/SafeMath.sol"; +import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; import "./MultiSigWallet.sol"; @@ -26,9 +26,9 @@ import "./MultiSigWallet.sol"; /// @author Amir Bandeali - // solhint-disable not-rely-on-time contract MultiSigWalletWithTimeLock is - MultiSigWallet, - SafeMath + MultiSigWallet { + using LibSafeMath for uint256; event ConfirmationTimeSet(uint256 indexed transactionId, uint256 confirmationTime); event TimeLockChange(uint256 secondsTimeLocked); @@ -55,7 +55,7 @@ contract MultiSigWalletWithTimeLock is modifier pastTimeLock(uint256 transactionId) { require( - block.timestamp >= _safeAdd(confirmationTimes[transactionId], secondsTimeLocked), + block.timestamp >= confirmationTimes[transactionId].safeAdd(secondsTimeLocked), "TIME_LOCK_INCOMPLETE" ); _; From 41d99e77c7fd16906c3a7c499e33d6fc5ff23d26 Mon Sep 17 00:00:00 2001 From: Alex Towle Date: Tue, 15 Oct 2019 14:29:48 -0700 Subject: [PATCH 80/87] `@0x:contracts-utils` Removed SafeMath and the use of the contract throughout `contracts/` --- .../contracts/src/ERC1155Proxy.sol | 6 +- contracts/erc1155/contracts/src/ERC1155.sol | 16 ++-- .../erc1155/contracts/src/ERC1155Mintable.sol | 11 +-- .../contracts/src/MintableERC20Token.sol | 15 ++-- .../erc20/contracts/test/DummyERC20Token.sol | 9 +- .../erc721/contracts/src/ERC721Token.sol | 15 ++-- .../contracts/src/MintableERC721Token.sol | 9 +- .../exchange-libs/contracts/src/LibMath.sol | 8 +- .../src/DutchAuction/DutchAuction.sol | 20 ++--- contracts/utils/contracts/src/SafeMath.sol | 90 ------------------- .../{TestSafeMath.sol => TestLibSafeMath.sol} | 21 ++--- contracts/utils/package.json | 2 +- contracts/utils/src/artifacts.ts | 6 +- contracts/utils/src/wrappers.ts | 3 +- .../test/{safe_math.ts => lib_safe_math.ts} | 20 ++--- contracts/utils/tsconfig.json | 5 +- 16 files changed, 84 insertions(+), 172 deletions(-) delete mode 100644 contracts/utils/contracts/src/SafeMath.sol rename contracts/utils/contracts/test/{TestSafeMath.sol => TestLibSafeMath.sol} (83%) rename contracts/utils/test/{safe_math.ts => lib_safe_math.ts} (95%) diff --git a/contracts/asset-proxy/contracts/src/ERC1155Proxy.sol b/contracts/asset-proxy/contracts/src/ERC1155Proxy.sol index 2e43635325..9ae6e5bc88 100644 --- a/contracts/asset-proxy/contracts/src/ERC1155Proxy.sol +++ b/contracts/asset-proxy/contracts/src/ERC1155Proxy.sol @@ -19,7 +19,7 @@ pragma solidity ^0.5.9; import "@0x/contracts-utils/contracts/src/LibBytes.sol"; -import "@0x/contracts-utils/contracts/src/SafeMath.sol"; +import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol"; import "../archive/MixinAuthorizable.sol"; import "./interfaces/IAssetProxy.sol"; @@ -27,10 +27,10 @@ import "./interfaces/IAssetProxy.sol"; contract ERC1155Proxy is MixinAuthorizable, - SafeMath, IAssetProxy { using LibBytes for bytes; + using LibSafeMath for uint256; // Id of this proxy. bytes4 constant internal PROXY_ID = bytes4(keccak256("ERC1155Assets(address,uint256[],uint256[],bytes)")); @@ -71,7 +71,7 @@ contract ERC1155Proxy is // to avoid copying over `ids` or `data`. This is possible if they are // identical to `values` and the offsets for each are pointing to the // same location in the ABI encoded calldata. - scaledValues[i] = _safeMul(values[i], amount); + scaledValues[i] = values[i].safeMul(amount); } // Execute `safeBatchTransferFrom` call diff --git a/contracts/erc1155/contracts/src/ERC1155.sol b/contracts/erc1155/contracts/src/ERC1155.sol index afebfbc634..ab81c61aec 100644 --- a/contracts/erc1155/contracts/src/ERC1155.sol +++ b/contracts/erc1155/contracts/src/ERC1155.sol @@ -18,7 +18,7 @@ pragma solidity ^0.5.9; -import "@0x/contracts-utils/contracts/src/SafeMath.sol"; +import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; import "@0x/contracts-utils/contracts/src/LibAddress.sol"; import "./interfaces/IERC1155.sol"; import "./interfaces/IERC1155Receiver.sol"; @@ -26,11 +26,11 @@ import "./MixinNonFungibleToken.sol"; contract ERC1155 is - SafeMath, IERC1155, MixinNonFungibleToken { using LibAddress for address; + using LibSafeMath for uint256; // selectors for receiver callbacks bytes4 constant public ERC1155_RECEIVED = 0xf23a6e61; @@ -88,11 +88,11 @@ contract ERC1155 is nfOwners[id] = to; // You could keep balance of NF type in base type id like so: // uint256 baseType = getNonFungibleBaseType(_id); - // balances[baseType][_from] = balances[baseType][_from]._safeSub(_value); - // balances[baseType][_to] = balances[baseType][_to]._safeAdd(_value); + // balances[baseType][_from] = balances[baseType][_from].safeSub(_value); + // balances[baseType][_to] = balances[baseType][_to].safeAdd(_value); } else { - balances[id][from] = _safeSub(balances[id][from], value); - balances[id][to] = _safeAdd(balances[id][to], value); + balances[id][from] = balances[id][from].safeSub(value); + balances[id][to] = balances[id][to].safeAdd(value); } emit TransferSingle(msg.sender, from, to, id, value); @@ -170,8 +170,8 @@ contract ERC1155 is ); nfOwners[id] = to; } else { - balances[id][from] = _safeSub(balances[id][from], value); - balances[id][to] = _safeAdd(balances[id][to], value); + balances[id][from] = balances[id][from].safeSub(value); + balances[id][to] = balances[id][to].safeAdd(value); } } emit TransferBatch(msg.sender, from, to, ids, values); diff --git a/contracts/erc1155/contracts/src/ERC1155Mintable.sol b/contracts/erc1155/contracts/src/ERC1155Mintable.sol index 5057f956c7..5d99a535cf 100644 --- a/contracts/erc1155/contracts/src/ERC1155Mintable.sol +++ b/contracts/erc1155/contracts/src/ERC1155Mintable.sol @@ -1,6 +1,6 @@ pragma solidity ^0.5.9; -import "@0x/contracts-utils/contracts/src/SafeMath.sol"; +import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; import "./ERC1155.sol"; import "./interfaces/IERC1155Mintable.sol"; @@ -11,6 +11,7 @@ contract ERC1155Mintable is IERC1155Mintable, ERC1155 { + using LibSafeMath for uint256; /// token nonce uint256 internal nonce; @@ -37,7 +38,7 @@ contract ERC1155Mintable is ) external returns (uint256 type_) - { + { // Store the type in the upper 128 bits type_ = (++nonce << 128); @@ -114,7 +115,7 @@ contract ERC1155Mintable is uint256 quantity = quantities[i]; // Grant the items to the caller - balances[id][dst] = _safeAdd(quantity, balances[id][dst]); + balances[id][dst] = quantity.safeAdd(balances[id][dst]); // Emit the Transfer/Mint event. // the 0x0 source address implies a mint @@ -172,7 +173,7 @@ contract ERC1155Mintable is nfOwners[id] = dst; // You could use base-type id to store NF type balances if you wish. - // balances[_type][dst] = quantity._safeAdd(balances[_type][dst]); + // balances[_type][dst] = quantity.safeAdd(balances[_type][dst]); emit TransferSingle(msg.sender, address(0x0), dst, id, 1); @@ -194,6 +195,6 @@ contract ERC1155Mintable is // record the `maxIndex` of this nft type // this allows us to mint more nft's of this type in a subsequent call. - maxIndex[type_] = _safeAdd(to.length, maxIndex[type_]); + maxIndex[type_] = to.length.safeAdd(maxIndex[type_]); } } diff --git a/contracts/erc20/contracts/src/MintableERC20Token.sol b/contracts/erc20/contracts/src/MintableERC20Token.sol index 65e102135b..fab2aac164 100644 --- a/contracts/erc20/contracts/src/MintableERC20Token.sol +++ b/contracts/erc20/contracts/src/MintableERC20Token.sol @@ -18,22 +18,23 @@ pragma solidity ^0.5.9; -import "@0x/contracts-utils/contracts/src/SafeMath.sol"; +import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; import "./UnlimitedAllowanceERC20Token.sol"; -contract MintableERC20Token is - SafeMath, +contract MintableERC20Token is UnlimitedAllowanceERC20Token { + using LibSafeMath for uint256; + /// @dev Mints new tokens /// @param _to Address of the beneficiary that will own the minted token /// @param _value Amount of tokens to mint function _mint(address _to, uint256 _value) internal { - balances[_to] = _safeAdd(_value, balances[_to]); - _totalSupply = _safeAdd(_totalSupply, _value); + balances[_to] = _value.safeAdd(balances[_to]); + _totalSupply = _totalSupply.safeAdd(_value); emit Transfer( address(0), @@ -48,8 +49,8 @@ contract MintableERC20Token is function _burn(address _owner, uint256 _value) internal { - balances[_owner] = _safeSub(balances[_owner], _value); - _totalSupply = _safeSub(_totalSupply, _value); + balances[_owner] = balances[_owner].safeSub(_value); + _totalSupply = _totalSupply.safeSub(_value); emit Transfer( _owner, diff --git a/contracts/erc20/contracts/test/DummyERC20Token.sol b/contracts/erc20/contracts/test/DummyERC20Token.sol index 2a74d21237..be39ac3048 100644 --- a/contracts/erc20/contracts/test/DummyERC20Token.sol +++ b/contracts/erc20/contracts/test/DummyERC20Token.sol @@ -18,14 +18,17 @@ pragma solidity ^0.5.5; +import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; import "@0x/contracts-utils/contracts/src/Ownable.sol"; import "../src/MintableERC20Token.sol"; -contract DummyERC20Token is +contract DummyERC20Token is Ownable, MintableERC20Token { + using LibSafeMath for uint256; + string public name; string public symbol; uint256 public decimals; @@ -55,9 +58,9 @@ contract DummyERC20Token is { uint256 currBalance = balances[_target]; if (_value < currBalance) { - _totalSupply = _safeSub(_totalSupply, _safeSub(currBalance, _value)); + _totalSupply = _totalSupply.safeSub(currBalance.safeSub(_value)); } else { - _totalSupply = _safeAdd(_totalSupply, _safeSub(_value, currBalance)); + _totalSupply = _totalSupply.safeAdd(_value.safeSub(currBalance)); } balances[_target] = _value; } diff --git a/contracts/erc721/contracts/src/ERC721Token.sol b/contracts/erc721/contracts/src/ERC721Token.sol index aa2ba3cca0..810016d195 100644 --- a/contracts/erc721/contracts/src/ERC721Token.sol +++ b/contracts/erc721/contracts/src/ERC721Token.sol @@ -20,13 +20,14 @@ pragma solidity ^0.5.9; import "./interfaces/IERC721Token.sol"; import "./interfaces/IERC721Receiver.sol"; -import "@0x/contracts-utils/contracts/src/SafeMath.sol"; +import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; contract ERC721Token is - IERC721Token, - SafeMath + IERC721Token { + using LibSafeMath for uint256; + // Function selector for ERC721Receiver.onERC721Received // 0x150b7a02 bytes4 constant internal ERC721_RECEIVED = bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")); @@ -163,7 +164,7 @@ contract ERC721Token is _approved ); } - + /// @notice Count all NFTs assigned to an owner /// @dev NFTs assigned to the zero address are considered invalid, and this /// function throws for queries about the zero address. @@ -223,9 +224,9 @@ contract ERC721Token is } owners[_tokenId] = _to; - balances[_from] = _safeSub(balances[_from], 1); - balances[_to] = _safeAdd(balances[_to], 1); - + balances[_from] = balances[_from].safeSub(1); + balances[_to] = balances[_to].safeAdd(1); + emit Transfer( _from, _to, diff --git a/contracts/erc721/contracts/src/MintableERC721Token.sol b/contracts/erc721/contracts/src/MintableERC721Token.sol index c3e0a6dca9..667b5994a9 100644 --- a/contracts/erc721/contracts/src/MintableERC721Token.sol +++ b/contracts/erc721/contracts/src/MintableERC721Token.sol @@ -18,16 +18,19 @@ pragma solidity ^0.5.9; +import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; import "./ERC721Token.sol"; contract MintableERC721Token is ERC721Token { + using LibSafeMath for uint256; + /// @dev Function to mint a new token /// Reverts if the given token ID already exists /// @param _to Address of the beneficiary that will own the minted token - /// @param _tokenId ID of the token to be minted by the msg.sender + /// @param _tokenId ID of the token to be minted by the msg.sender function _mint(address _to, uint256 _tokenId) internal { @@ -43,7 +46,7 @@ contract MintableERC721Token is ); owners[_tokenId] = _to; - balances[_to] = _safeAdd(balances[_to], 1); + balances[_to] = balances[_to].safeAdd(1); emit Transfer( address(0), @@ -71,7 +74,7 @@ contract MintableERC721Token is ); owners[_tokenId] = address(0); - balances[_owner] = _safeSub(balances[_owner], 1); + balances[_owner] = balances[_owner].safeSub(1); emit Transfer( _owner, diff --git a/contracts/exchange-libs/contracts/src/LibMath.sol b/contracts/exchange-libs/contracts/src/LibMath.sol index 29d61afdd7..e18c746bf1 100644 --- a/contracts/exchange-libs/contracts/src/LibMath.sol +++ b/contracts/exchange-libs/contracts/src/LibMath.sol @@ -85,9 +85,9 @@ library LibMath { )); } - // _safeDiv computes `floor(a / b)`. We use the identity (a, b integer): + // safeDiv computes `floor(a / b)`. We use the identity (a, b integer): // ceil(a / b) = floor((a + b - 1) / b) - // To implement `ceil(a / b)` using _safeDiv. + // To implement `ceil(a / b)` using safeDiv. partialAmount = numerator.safeMul(target) .safeAdd(denominator.safeSub(1)) .safeDiv(denominator); @@ -127,9 +127,9 @@ library LibMath { pure returns (uint256 partialAmount) { - // _safeDiv computes `floor(a / b)`. We use the identity (a, b integer): + // safeDiv computes `floor(a / b)`. We use the identity (a, b integer): // ceil(a / b) = floor((a + b - 1) / b) - // To implement `ceil(a / b)` using _safeDiv. + // To implement `ceil(a / b)` using safeDiv. partialAmount = numerator.safeMul(target) .safeAdd(denominator.safeSub(1)) .safeDiv(denominator); diff --git a/contracts/extensions/contracts/src/DutchAuction/DutchAuction.sol b/contracts/extensions/contracts/src/DutchAuction/DutchAuction.sol index 78f69fa4c3..e8ddfaca64 100644 --- a/contracts/extensions/contracts/src/DutchAuction/DutchAuction.sol +++ b/contracts/extensions/contracts/src/DutchAuction/DutchAuction.sol @@ -23,13 +23,13 @@ import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; import "@0x/contracts-utils/contracts/src/LibBytes.sol"; -import "@0x/contracts-utils/contracts/src/SafeMath.sol"; +import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; -contract DutchAuction is - SafeMath -{ +contract DutchAuction { + using LibBytes for bytes; + using LibSafeMath for uint256; // solhint-disable var-name-mixedcase IExchange internal EXCHANGE; @@ -120,8 +120,8 @@ contract DutchAuction is address token = assetData.readAddress(16); // Calculate the excess from the buy order. This can occur if the buyer sends in a higher // amount than the calculated current amount - uint256 buyerExcessAmount = _safeSub(buyOrder.makerAssetAmount, auctionDetails.currentAmount); - uint256 sellerExcessAmount = _safeSub(leftMakerAssetSpreadAmount, buyerExcessAmount); + uint256 buyerExcessAmount = buyOrder.makerAssetAmount.safeSub(auctionDetails.currentAmount); + uint256 sellerExcessAmount = leftMakerAssetSpreadAmount.safeSub(buyerExcessAmount); // Return the difference between auctionDetails.currentAmount and sellOrder.takerAssetAmount // to the seller if (sellerExcessAmount > 0) { @@ -190,12 +190,8 @@ contract DutchAuction is // Auction end time is guaranteed by 0x Exchange due to the order expiration auctionDetails.currentAmount = minAmount; } else { - auctionDetails.currentAmount = _safeAdd( - minAmount, - _safeDiv( - _safeMul(remainingDurationSeconds, amountDelta), - auctionDurationSeconds - ) + auctionDetails.currentAmount = minAmount.safeAdd( + remainingDurationSeconds.safeMul(amountDelta).safeDiv(auctionDurationSeconds) ); } return auctionDetails; diff --git a/contracts/utils/contracts/src/SafeMath.sol b/contracts/utils/contracts/src/SafeMath.sol deleted file mode 100644 index bf0e95145a..0000000000 --- a/contracts/utils/contracts/src/SafeMath.sol +++ /dev/null @@ -1,90 +0,0 @@ -pragma solidity ^0.5.9; - -import "./LibRichErrors.sol"; -import "./LibSafeMathRichErrors.sol"; - - -contract SafeMath { - - function _safeMul(uint256 a, uint256 b) - internal - pure - returns (uint256) - { - if (a == 0) { - return 0; - } - uint256 c = a * b; - if (c / a != b) { - LibRichErrors.rrevert(LibSafeMathRichErrors.Uint256BinOpError( - LibSafeMathRichErrors.BinOpErrorCodes.MULTIPLICATION_OVERFLOW, - a, - b - )); - } - return c; - } - - function _safeDiv(uint256 a, uint256 b) - internal - pure - returns (uint256) - { - if (b == 0) { - LibRichErrors.rrevert(LibSafeMathRichErrors.Uint256BinOpError( - LibSafeMathRichErrors.BinOpErrorCodes.DIVISION_BY_ZERO, - a, - b - )); - } - uint256 c = a / b; - return c; - } - - function _safeSub(uint256 a, uint256 b) - internal - pure - returns (uint256) - { - if (b > a) { - LibRichErrors.rrevert(LibSafeMathRichErrors.Uint256BinOpError( - LibSafeMathRichErrors.BinOpErrorCodes.SUBTRACTION_UNDERFLOW, - a, - b - )); - } - return a - b; - } - - function _safeAdd(uint256 a, uint256 b) - internal - pure - returns (uint256) - { - uint256 c = a + b; - if (c < a) { - LibRichErrors.rrevert(LibSafeMathRichErrors.Uint256BinOpError( - LibSafeMathRichErrors.BinOpErrorCodes.ADDITION_OVERFLOW, - a, - b - )); - } - return c; - } - - function _max256(uint256 a, uint256 b) - internal - pure - returns (uint256) - { - return a >= b ? a : b; - } - - function _min256(uint256 a, uint256 b) - internal - pure - returns (uint256) - { - return a < b ? a : b; - } -} diff --git a/contracts/utils/contracts/test/TestSafeMath.sol b/contracts/utils/contracts/test/TestLibSafeMath.sol similarity index 83% rename from contracts/utils/contracts/test/TestSafeMath.sol rename to contracts/utils/contracts/test/TestLibSafeMath.sol index 36670e13af..a3ee8555c0 100644 --- a/contracts/utils/contracts/test/TestSafeMath.sol +++ b/contracts/utils/contracts/test/TestLibSafeMath.sol @@ -18,18 +18,19 @@ pragma solidity ^0.5.9; -import "../src/SafeMath.sol"; +import "../src/LibSafeMath.sol"; -contract TestSafeMath is - SafeMath -{ +contract TestLibSafeMath { + + using LibSafeMath for uint256; + function externalSafeMul(uint256 a, uint256 b) external pure returns (uint256) { - return _safeMul(a, b); + return a.safeMul(b); } function externalSafeDiv(uint256 a, uint256 b) @@ -37,7 +38,7 @@ contract TestSafeMath is pure returns (uint256) { - return _safeDiv(a, b); + return a.safeDiv(b); } function externalSafeSub(uint256 a, uint256 b) @@ -45,7 +46,7 @@ contract TestSafeMath is pure returns (uint256) { - return _safeSub(a, b); + return a.safeSub(b); } function externalSafeAdd(uint256 a, uint256 b) @@ -53,7 +54,7 @@ contract TestSafeMath is pure returns (uint256) { - return _safeAdd(a, b); + return a.safeAdd(b); } function externalMaxUint256(uint256 a, uint256 b) @@ -61,7 +62,7 @@ contract TestSafeMath is pure returns (uint256) { - return _max256(a, b); + return a.max256(b); } function externalMinUint256(uint256 a, uint256 b) @@ -69,6 +70,6 @@ contract TestSafeMath is pure returns (uint256) { - return _min256(a, b); + return a.min256(b); } } diff --git a/contracts/utils/package.json b/contracts/utils/package.json index 7f9631d7fc..76834fe6d9 100644 --- a/contracts/utils/package.json +++ b/contracts/utils/package.json @@ -36,7 +36,7 @@ }, "config": { "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.", - "abis": "./generated-artifacts/@(Authorizable|IAuthorizable|IOwnable|LibAddress|LibAddressArray|LibAddressArrayRichErrors|LibAuthorizableRichErrors|LibBytes|LibBytesRichErrors|LibEIP1271|LibEIP712|LibFractions|LibOwnableRichErrors|LibReentrancyGuardRichErrors|LibRichErrors|LibSafeMath|LibSafeMathRichErrors|Ownable|ReentrancyGuard|Refundable|SafeMath|TestLibAddress|TestLibAddressArray|TestLibBytes|TestLibEIP712|TestLibRichErrors|TestLogDecoding|TestLogDecodingDownstream|TestOwnable|TestReentrancyGuard|TestRefundable|TestRefundableReceiver|TestSafeMath).json" + "abis": "./generated-artifacts/@(Authorizable|IAuthorizable|IOwnable|LibAddress|LibAddressArray|LibAddressArrayRichErrors|LibAuthorizableRichErrors|LibBytes|LibBytesRichErrors|LibEIP1271|LibEIP712|LibFractions|LibOwnableRichErrors|LibReentrancyGuardRichErrors|LibRichErrors|LibSafeMath|LibSafeMathRichErrors|Ownable|ReentrancyGuard|Refundable|TestLibAddress|TestLibAddressArray|TestLibBytes|TestLibEIP712|TestLibRichErrors|TestLibSafeMath|TestLogDecoding|TestLogDecodingDownstream|TestOwnable|TestReentrancyGuard|TestRefundable|TestRefundableReceiver).json" }, "repository": { "type": "git", diff --git a/contracts/utils/src/artifacts.ts b/contracts/utils/src/artifacts.ts index 47a2d61628..983f2951ed 100644 --- a/contracts/utils/src/artifacts.ts +++ b/contracts/utils/src/artifacts.ts @@ -25,19 +25,18 @@ import * as LibSafeMathRichErrors from '../generated-artifacts/LibSafeMathRichEr import * as Ownable from '../generated-artifacts/Ownable.json'; import * as ReentrancyGuard from '../generated-artifacts/ReentrancyGuard.json'; import * as Refundable from '../generated-artifacts/Refundable.json'; -import * as SafeMath from '../generated-artifacts/SafeMath.json'; import * as TestLibAddress from '../generated-artifacts/TestLibAddress.json'; import * as TestLibAddressArray from '../generated-artifacts/TestLibAddressArray.json'; import * as TestLibBytes from '../generated-artifacts/TestLibBytes.json'; import * as TestLibEIP712 from '../generated-artifacts/TestLibEIP712.json'; import * as TestLibRichErrors from '../generated-artifacts/TestLibRichErrors.json'; +import * as TestLibSafeMath from '../generated-artifacts/TestLibSafeMath.json'; import * as TestLogDecoding from '../generated-artifacts/TestLogDecoding.json'; import * as TestLogDecodingDownstream from '../generated-artifacts/TestLogDecodingDownstream.json'; import * as TestOwnable from '../generated-artifacts/TestOwnable.json'; import * as TestReentrancyGuard from '../generated-artifacts/TestReentrancyGuard.json'; import * as TestRefundable from '../generated-artifacts/TestRefundable.json'; import * as TestRefundableReceiver from '../generated-artifacts/TestRefundableReceiver.json'; -import * as TestSafeMath from '../generated-artifacts/TestSafeMath.json'; export const artifacts = { Authorizable: Authorizable as ContractArtifact, LibAddress: LibAddress as ContractArtifact, @@ -57,7 +56,6 @@ export const artifacts = { Ownable: Ownable as ContractArtifact, ReentrancyGuard: ReentrancyGuard as ContractArtifact, Refundable: Refundable as ContractArtifact, - SafeMath: SafeMath as ContractArtifact, IAuthorizable: IAuthorizable as ContractArtifact, IOwnable: IOwnable as ContractArtifact, TestLibAddress: TestLibAddress as ContractArtifact, @@ -65,11 +63,11 @@ export const artifacts = { TestLibBytes: TestLibBytes as ContractArtifact, TestLibEIP712: TestLibEIP712 as ContractArtifact, TestLibRichErrors: TestLibRichErrors as ContractArtifact, + TestLibSafeMath: TestLibSafeMath as ContractArtifact, TestLogDecoding: TestLogDecoding as ContractArtifact, TestLogDecodingDownstream: TestLogDecodingDownstream as ContractArtifact, TestOwnable: TestOwnable as ContractArtifact, TestReentrancyGuard: TestReentrancyGuard as ContractArtifact, TestRefundable: TestRefundable as ContractArtifact, TestRefundableReceiver: TestRefundableReceiver as ContractArtifact, - TestSafeMath: TestSafeMath as ContractArtifact, }; diff --git a/contracts/utils/src/wrappers.ts b/contracts/utils/src/wrappers.ts index 78edd2ddec..da266a03dd 100644 --- a/contracts/utils/src/wrappers.ts +++ b/contracts/utils/src/wrappers.ts @@ -23,16 +23,15 @@ export * from '../generated-wrappers/lib_safe_math_rich_errors'; export * from '../generated-wrappers/ownable'; export * from '../generated-wrappers/reentrancy_guard'; export * from '../generated-wrappers/refundable'; -export * from '../generated-wrappers/safe_math'; export * from '../generated-wrappers/test_lib_address'; export * from '../generated-wrappers/test_lib_address_array'; export * from '../generated-wrappers/test_lib_bytes'; export * from '../generated-wrappers/test_lib_e_i_p712'; export * from '../generated-wrappers/test_lib_rich_errors'; +export * from '../generated-wrappers/test_lib_safe_math'; export * from '../generated-wrappers/test_log_decoding'; export * from '../generated-wrappers/test_log_decoding_downstream'; export * from '../generated-wrappers/test_ownable'; export * from '../generated-wrappers/test_reentrancy_guard'; export * from '../generated-wrappers/test_refundable'; export * from '../generated-wrappers/test_refundable_receiver'; -export * from '../generated-wrappers/test_safe_math'; diff --git a/contracts/utils/test/safe_math.ts b/contracts/utils/test/lib_safe_math.ts similarity index 95% rename from contracts/utils/test/safe_math.ts rename to contracts/utils/test/lib_safe_math.ts index 15590b29ff..39e1ae5d1a 100644 --- a/contracts/utils/test/safe_math.ts +++ b/contracts/utils/test/lib_safe_math.ts @@ -2,7 +2,7 @@ import { blockchainTests, constants, describe, expect } from '@0x/contracts-test import { BigNumber, SafeMathRevertErrors } from '@0x/utils'; import * as _ from 'lodash'; -import { artifacts, TestSafeMathContract } from '../src'; +import { artifacts, TestLibSafeMathContract } from '../src'; import * as ReferenceFunctions from '../src/reference_functions'; function toBigNumber(a: number | string): BigNumber { @@ -11,19 +11,19 @@ function toBigNumber(a: number | string): BigNumber { blockchainTests('SafeMath', env => { const { ONE_ETHER } = constants; - let safeMath: TestSafeMathContract; + let safeMath: TestLibSafeMathContract; before(async () => { // Deploy SafeMath - safeMath = await TestSafeMathContract.deployFrom0xArtifactAsync( - artifacts.TestSafeMath, + safeMath = await TestLibSafeMathContract.deployFrom0xArtifactAsync( + artifacts.TestLibSafeMath, env.provider, env.txDefaults, {}, ); }); - describe('_safeMul', () => { + describe('safeMul', () => { it('should match the output of the reference function', async () => { const a = ONE_ETHER; const b = ONE_ETHER.times(2); @@ -59,7 +59,7 @@ blockchainTests('SafeMath', env => { }); }); - describe('_safeDiv', () => { + describe('safeDiv', () => { it('should match the output of the reference function', async () => { const a = ONE_ETHER; const b = ONE_ETHER.times(2); @@ -100,7 +100,7 @@ blockchainTests('SafeMath', env => { }); }); - describe('_safeSub', () => { + describe('safeSub', () => { it('should match the output of the reference function', async () => { const a = ONE_ETHER; const b = ONE_ETHER.dividedToIntegerBy(2); @@ -131,7 +131,7 @@ blockchainTests('SafeMath', env => { }); }); - describe('_safeAdd', () => { + describe('safeAdd', () => { it('should match the output of the reference function', async () => { const a = ONE_ETHER; const b = ONE_ETHER.dividedToIntegerBy(2); @@ -167,7 +167,7 @@ blockchainTests('SafeMath', env => { }); }); - describe('_maxUint256', () => { + describe('maxUint256', () => { it('should return first argument if it is greater than the second', async () => { const result = await safeMath.externalMaxUint256.callAsync(toBigNumber(13), constants.ZERO_AMOUNT); expect(result).bignumber.to.be.eq(toBigNumber(13)); @@ -184,7 +184,7 @@ blockchainTests('SafeMath', env => { }); }); - describe('_minUint256', () => { + describe('minUint256', () => { it('should return first argument if it is less than the second', async () => { const result = await safeMath.externalMaxUint256.callAsync(constants.ZERO_AMOUNT, toBigNumber(13)); expect(result).bignumber.to.be.eq(toBigNumber(13)); diff --git a/contracts/utils/tsconfig.json b/contracts/utils/tsconfig.json index 13059711d1..58803aad69 100644 --- a/contracts/utils/tsconfig.json +++ b/contracts/utils/tsconfig.json @@ -23,19 +23,18 @@ "generated-artifacts/Ownable.json", "generated-artifacts/ReentrancyGuard.json", "generated-artifacts/Refundable.json", - "generated-artifacts/SafeMath.json", "generated-artifacts/TestLibAddress.json", "generated-artifacts/TestLibAddressArray.json", "generated-artifacts/TestLibBytes.json", "generated-artifacts/TestLibEIP712.json", "generated-artifacts/TestLibRichErrors.json", + "generated-artifacts/TestLibSafeMath.json", "generated-artifacts/TestLogDecoding.json", "generated-artifacts/TestLogDecodingDownstream.json", "generated-artifacts/TestOwnable.json", "generated-artifacts/TestReentrancyGuard.json", "generated-artifacts/TestRefundable.json", - "generated-artifacts/TestRefundableReceiver.json", - "generated-artifacts/TestSafeMath.json" + "generated-artifacts/TestRefundableReceiver.json" ], "exclude": ["./deploy/solc/solc_bin"] } From 523bc3f95165c7f4847607bfebcbb52b079a51d0 Mon Sep 17 00:00:00 2001 From: Alex Towle Date: Tue, 15 Oct 2019 14:45:27 -0700 Subject: [PATCH 81/87] Updated Changelogs --- contracts/asset-proxy/CHANGELOG.json | 4 ++++ contracts/erc1155/CHANGELOG.json | 4 ++++ contracts/erc20/CHANGELOG.json | 4 ++++ contracts/erc721/CHANGELOG.json | 4 ++++ contracts/extensions/CHANGELOG.json | 4 ++++ contracts/utils/CHANGELOG.json | 4 ++++ 6 files changed, 24 insertions(+) diff --git a/contracts/asset-proxy/CHANGELOG.json b/contracts/asset-proxy/CHANGELOG.json index e51f943a2b..c601dcce07 100644 --- a/contracts/asset-proxy/CHANGELOG.json +++ b/contracts/asset-proxy/CHANGELOG.json @@ -29,6 +29,10 @@ { "note": "Add `UniswapBridge`", "pr": 2233 + }, + { + "note": "Replaced `SafeMath` with `LibSafeMath`", + "pr": 2254 } ], "timestamp": 1570135330 diff --git a/contracts/erc1155/CHANGELOG.json b/contracts/erc1155/CHANGELOG.json index b2d85d92cc..f42944b3be 100644 --- a/contracts/erc1155/CHANGELOG.json +++ b/contracts/erc1155/CHANGELOG.json @@ -5,6 +5,10 @@ { "note": "Add `mintKnownFungibleTokensAsync()`, `isNonFungibleItemAsync()`, `isFungibleItemAsync()`, `getOwnerOfAsync()`, `getBalanceAsync()` to `Erc1155Wrapper`.", "pr": 1819 + }, + { + "note": "Replaced `SafeMath` with `LibSafeMath`", + "pr": 2254 } ], "timestamp": 1570135330 diff --git a/contracts/erc20/CHANGELOG.json b/contracts/erc20/CHANGELOG.json index 4c349e24df..74e072b7b5 100644 --- a/contracts/erc20/CHANGELOG.json +++ b/contracts/erc20/CHANGELOG.json @@ -4,6 +4,10 @@ "changes": [ { "note": "Dependencies updated" + }, + { + "note": "Replaced `SafeMath` with `LibSafeMath`", + "pr": 2254 } ], "timestamp": 1570135330 diff --git a/contracts/erc721/CHANGELOG.json b/contracts/erc721/CHANGELOG.json index 7b77e700de..4ad739fabc 100644 --- a/contracts/erc721/CHANGELOG.json +++ b/contracts/erc721/CHANGELOG.json @@ -4,6 +4,10 @@ "changes": [ { "note": "Dependencies updated" + }, + { + "note": "Replaced `SafeMath` with `LibSafeMath`", + "pr": 2254 } ], "timestamp": 1570135330 diff --git a/contracts/extensions/CHANGELOG.json b/contracts/extensions/CHANGELOG.json index e357e80602..5f12dbaa04 100644 --- a/contracts/extensions/CHANGELOG.json +++ b/contracts/extensions/CHANGELOG.json @@ -4,6 +4,10 @@ "changes": [ { "note": "Dependencies updated" + }, + { + "note": "Replaced the use of `SafeMath` with `LibSafeMath`", + "pr": 2254 } ], "timestamp": 1570135330 diff --git a/contracts/utils/CHANGELOG.json b/contracts/utils/CHANGELOG.json index acea499521..dc3f8d93a4 100644 --- a/contracts/utils/CHANGELOG.json +++ b/contracts/utils/CHANGELOG.json @@ -69,6 +69,10 @@ { "note": "Removed `deepCopyBytes`, `popLast20Bytes`, `readBytesWithLength`, and `writeBytesWithLength` in `LibBytes`.", "pr": 2265 + }, + { + "note": "Replaced `SafeMath` with `LibSafeMath`", + "pr": 2254 } ], "timestamp": 1570135330 From 0e90b0e7d068fea59ad9c5fbfcd4aa4e5e9abad6 Mon Sep 17 00:00:00 2001 From: Xianny <8582774+xianny@users.noreply.github.com> Date: Wed, 16 Oct 2019 09:38:34 -0700 Subject: [PATCH 82/87] Make wrappers small again (#2243) * introduce --debug option to abi-gen and remove debug functions from @0x/abi-gen-wrappers * make evmExecAsync protected; ignore deployedBytecode in doc comment * trim deployedBytecode so it's undefined unless a contract has pure functions * remove validateAndSendTransactionAsync * Create `AwaitTransactionSuccessOpts` and `SendTransactionOpts` types * Remove duplicate types `IndexedFilterValues`, `DecodedLogEvent`, `EventCallback` from `@0x/base-contract` --- contracts/asset-proxy/package.json | 2 +- contracts/asset-proxy/test/authorizable.ts | 90 +- contracts/asset-proxy/test/erc1155_proxy.ts | 91 +- contracts/asset-proxy/test/proxies.ts | 110 +- .../asset-proxy/test/utils/erc20_wrapper.ts | 18 +- .../asset-proxy/test/utils/erc721_wrapper.ts | 42 +- contracts/coordinator/package.json | 2 +- contracts/dev-utils/package.json | 2 +- contracts/erc1155/package.json | 2 +- .../erc1155/test/utils/erc1155_wrapper.ts | 12 +- contracts/erc20/package.json | 2 +- contracts/erc721/package.json | 2 +- contracts/exchange-forwarder/package.json | 2 +- contracts/exchange-libs/package.json | 2 +- contracts/exchange/package.json | 2 +- contracts/exchange/src/wrapper_interfaces.ts | 13 +- contracts/exchange/test/match_orders.ts | 74 +- .../utils/fill_order_combinatorial_utils.ts | 72 +- contracts/extensions/package.json | 2 +- contracts/multisig/package.json | 2 +- contracts/staking/package.json | 2 +- contracts/utils/package.json | 2 +- contracts/utils/test/authorizable.ts | 75 +- packages/0x.js/src/index.ts | 2 + packages/abi-gen-wrappers/CHANGELOG.json | 21 + packages/abi-gen-wrappers/package.json | 17 +- .../generated-wrappers/asset_proxy_owner.ts | 1121 +----- .../src/generated-wrappers/coordinator.ts | 443 +-- .../coordinator_registry.ts | 101 +- .../src/generated-wrappers/dev_utils.ts | 1905 +-------- .../generated-wrappers/dummy_erc20_token.ts | 590 +-- .../generated-wrappers/dummy_erc721_token.ts | 655 +--- .../src/generated-wrappers/dutch_auction.ts | 260 +- .../src/generated-wrappers/erc1155_proxy.ts | 434 +-- .../src/generated-wrappers/erc20_proxy.ts | 386 +- .../src/generated-wrappers/erc20_token.ts | 269 +- .../src/generated-wrappers/erc721_proxy.ts | 386 +- .../src/generated-wrappers/erc721_token.ts | 408 +- .../generated-wrappers/eth_balance_checker.ts | 51 +- .../src/generated-wrappers/exchange.ts | 3467 ++--------------- .../src/generated-wrappers/forwarder.ts | 463 +-- .../src/generated-wrappers/i_asset_proxy.ts | 96 +- .../src/generated-wrappers/i_validator.ts | 56 +- .../src/generated-wrappers/i_wallet.ts | 53 +- .../generated-wrappers/multi_asset_proxy.ts | 510 +-- .../src/generated-wrappers/order_validator.ts | 597 +-- .../generated-wrappers/static_call_proxy.ts | 95 +- .../src/generated-wrappers/weth9.ts | 480 +-- .../src/generated-wrappers/zrx_token.ts | 371 +- packages/abi-gen/package.json | 5 +- packages/abi-gen/src/index.ts | 12 +- .../templates/TypeScript/contract.handlebars | 7 +- .../partials/method_abi_helper.handlebars | 25 + .../partials/method_call_pure.handlebars | 2 +- .../TypeScript/partials/method_tx.handlebars | 39 +- .../output/typescript/abi_gen_dummy.ts | 156 +- .../test-cli/output/typescript/lib_dummy.ts | 14 +- .../output/typescript/test_lib_dummy.ts | 15 +- .../test/abi_gen_dummy_test.ts | 15 +- packages/asset-buyer/src/asset_buyer.ts | 2 +- .../exchange_swap_quote_consumer.ts | 4 +- .../forwarder_swap_quote_consumer.ts | 4 +- packages/base-contract/CHANGELOG.json | 13 + packages/base-contract/src/index.ts | 2 +- .../base-contract/src/subscription_manager.ts | 6 +- packages/base-contract/src/types.ts | 15 +- packages/contract-wrappers/src/index.ts | 2 + packages/contract-wrappers/src/types.ts | 2 + packages/types/CHANGELOG.json | 9 + packages/types/src/index.ts | 78 +- 70 files changed, 1921 insertions(+), 12366 deletions(-) diff --git a/contracts/asset-proxy/package.json b/contracts/asset-proxy/package.json index a39c3c18b5..4bd866af5b 100644 --- a/contracts/asset-proxy/package.json +++ b/contracts/asset-proxy/package.json @@ -22,7 +22,7 @@ "compile": "sol-compiler", "watch": "sol-compiler -w", "clean": "shx rm -rf lib generated-artifacts generated-wrappers", - "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", + "generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "coverage:report:text": "istanbul report text", diff --git a/contracts/asset-proxy/test/authorizable.ts b/contracts/asset-proxy/test/authorizable.ts index 37b8cbaee1..4a7794734c 100644 --- a/contracts/asset-proxy/test/authorizable.ts +++ b/contracts/asset-proxy/test/authorizable.ts @@ -1,11 +1,4 @@ -import { - chaiSetup, - constants, - expectTransactionFailedAsync, - provider, - txDefaults, - web3Wrapper, -} from '@0x/contracts-test-utils'; +import { chaiSetup, expectTransactionFailedAsync, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { RevertReason } from '@0x/types'; import { BigNumber } from '@0x/utils'; @@ -60,21 +53,13 @@ describe('Authorizable', () => { }); it('should allow owner to add an authorized address', async () => { - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); const isAuthorized = await authorizable.authorized.callAsync(address); expect(isAuthorized).to.be.true(); }); it('should revert if owner attempts to authorize a duplicate address', async () => { - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); return expectTransactionFailedAsync( authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }), RevertReason.TargetAlreadyAuthorized, @@ -84,11 +69,7 @@ describe('Authorizable', () => { describe('removeAuthorizedAddress', () => { it('should revert if not called by owner', async () => { - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); await expectTransactionFailedAsync( authorizable.removeAuthorizedAddress.sendTransactionAsync(address, { from: notOwner }), RevertReason.OnlyContractOwner, @@ -96,16 +77,8 @@ describe('Authorizable', () => { }); it('should allow owner to remove an authorized address', async () => { - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await authorizable.removeAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); + await authorizable.removeAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); const isAuthorized = await authorizable.authorized.callAsync(address); expect(isAuthorized).to.be.false(); }); @@ -122,11 +95,7 @@ describe('Authorizable', () => { describe('removeAuthorizedAddressAtIndex', () => { it('should revert if not called by owner', async () => { - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); const index = new BigNumber(0); await expectTransactionFailedAsync( authorizable.removeAuthorizedAddressAtIndex.sendTransactionAsync(address, index, { @@ -137,11 +106,7 @@ describe('Authorizable', () => { }); it('should revert if index is >= authorities.length', async () => { - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); const index = new BigNumber(1); return expectTransactionFailedAsync( authorizable.removeAuthorizedAddressAtIndex.sendTransactionAsync(address, index, { @@ -164,16 +129,8 @@ describe('Authorizable', () => { it('should revert if address at index does not match target', async () => { const address1 = address; const address2 = notOwner; - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address1, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address2, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address1, { from: owner }); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address2, { from: owner }); const address1Index = new BigNumber(0); return expectTransactionFailedAsync( authorizable.removeAuthorizedAddressAtIndex.sendTransactionAsync(address2, address1Index, { @@ -184,18 +141,11 @@ describe('Authorizable', () => { }); it('should allow owner to remove an authorized address', async () => { - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); const index = new BigNumber(0); - await authorizable.removeAuthorizedAddressAtIndex.awaitTransactionSuccessAsync( - address, - index, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.removeAuthorizedAddressAtIndex.awaitTransactionSuccessAsync(address, index, { + from: owner, + }); const isAuthorized = await authorizable.authorized.callAsync(address); expect(isAuthorized).to.be.false(); }); @@ -205,19 +155,11 @@ describe('Authorizable', () => { it('should return all authorized addresses', async () => { const initial = await authorizable.getAuthorizedAddresses.callAsync(); expect(initial).to.have.length(0); - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); const afterAdd = await authorizable.getAuthorizedAddresses.callAsync(); expect(afterAdd).to.have.length(1); expect(afterAdd).to.include(address); - await authorizable.removeAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.removeAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); const afterRemove = await authorizable.getAuthorizedAddresses.callAsync(); expect(afterRemove).to.have.length(0); }); diff --git a/contracts/asset-proxy/test/erc1155_proxy.ts b/contracts/asset-proxy/test/erc1155_proxy.ts index 64783ba085..c06f351e23 100644 --- a/contracts/asset-proxy/test/erc1155_proxy.ts +++ b/contracts/asset-proxy/test/erc1155_proxy.ts @@ -72,16 +72,8 @@ describe('ERC1155Proxy', () => { const usedAddresses = ([owner, notAuthorized, authorized, spender, receiver] = _.slice(accounts, 0, 5)); erc1155ProxyWrapper = new ERC1155ProxyWrapper(provider, usedAddresses, owner); erc1155Proxy = await erc1155ProxyWrapper.deployProxyAsync(); - await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - authorized, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - erc1155Proxy.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(authorized, { from: owner }); + await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(erc1155Proxy.address, { from: owner }); // deploy & configure ERC1155 tokens and receiver [erc1155Wrapper] = await erc1155ProxyWrapper.deployDummyContractsAsync(); erc1155Contract = erc1155Wrapper.getContract(); @@ -696,25 +688,18 @@ describe('ERC1155Proxy', () => { const tokenUri = ''; for (const tokenToCreate of tokensToCreate) { // create token - await erc1155Wrapper.getContract().createWithType.awaitTransactionSuccessAsync( - tokenToCreate, - tokenUri, - { + await erc1155Wrapper + .getContract() + .createWithType.awaitTransactionSuccessAsync(tokenToCreate, tokenUri, { from: owner, - }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + }); // mint balance for spender - await erc1155Wrapper.getContract().mintFungible.awaitTransactionSuccessAsync( - tokenToCreate, - [spender], - [spenderInitialBalance], - { + await erc1155Wrapper + .getContract() + .mintFungible.awaitTransactionSuccessAsync(tokenToCreate, [spender], [spenderInitialBalance], { from: owner, - }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + }); } ///// Step 2/5 ///// // Check balances before transfer @@ -805,25 +790,18 @@ describe('ERC1155Proxy', () => { const tokenUri = ''; for (const tokenToCreate of tokensToCreate) { // create token - await erc1155Wrapper.getContract().createWithType.awaitTransactionSuccessAsync( - tokenToCreate, - tokenUri, - { + await erc1155Wrapper + .getContract() + .createWithType.awaitTransactionSuccessAsync(tokenToCreate, tokenUri, { from: owner, - }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + }); // mint balance for spender - await erc1155Wrapper.getContract().mintFungible.awaitTransactionSuccessAsync( - tokenToCreate, - [spender], - [spenderInitialBalance], - { + await erc1155Wrapper + .getContract() + .mintFungible.awaitTransactionSuccessAsync(tokenToCreate, [spender], [spenderInitialBalance], { from: owner, - }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + }); } ///// Step 2/5 ///// // Check balances before transfer @@ -937,25 +915,18 @@ describe('ERC1155Proxy', () => { const tokenUri = ''; for (const tokenToCreate of tokensToCreate) { // create token - await erc1155Wrapper.getContract().createWithType.awaitTransactionSuccessAsync( - tokenToCreate, - tokenUri, - { + await erc1155Wrapper + .getContract() + .createWithType.awaitTransactionSuccessAsync(tokenToCreate, tokenUri, { from: owner, - }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + }); // mint balance for spender - await erc1155Wrapper.getContract().mintFungible.awaitTransactionSuccessAsync( - tokenToCreate, - [spender], - [spenderInitialBalance], - { + await erc1155Wrapper + .getContract() + .mintFungible.awaitTransactionSuccessAsync(tokenToCreate, [spender], [spenderInitialBalance], { from: owner, - }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + }); } ///// Step 2/5 ///// // Check balances before transfer @@ -1667,13 +1638,9 @@ describe('ERC1155Proxy', () => { it('should propagate revert reason from erc1155 contract failure', async () => { // disable transfers const shouldRejectTransfer = true; - await erc1155Receiver.setRejectTransferFlag.awaitTransactionSuccessAsync( - shouldRejectTransfer, - { - from: owner, - }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await erc1155Receiver.setRejectTransferFlag.awaitTransactionSuccessAsync(shouldRejectTransfer, { + from: owner, + }); // setup test parameters const tokenHolders = [spender, receiverContract]; const tokensToTransfer = fungibleTokens.slice(0, 1); diff --git a/contracts/asset-proxy/test/proxies.ts b/contracts/asset-proxy/test/proxies.ts index 2d7d01aa9f..20a00b98e3 100644 --- a/contracts/asset-proxy/test/proxies.ts +++ b/contracts/asset-proxy/test/proxies.ts @@ -105,64 +105,24 @@ describe('Asset Transfer Proxies', () => { ); // Configure ERC20Proxy - await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - authorized, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - multiAssetProxy.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(authorized, { from: owner }); + await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(multiAssetProxy.address, { from: owner }); // Configure ERC721Proxy - await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - authorized, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - multiAssetProxy.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(authorized, { from: owner }); + await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(multiAssetProxy.address, { from: owner }); // Configure ERC115Proxy erc1155ProxyWrapper = new ERC1155ProxyWrapper(provider, usedAddresses, owner); erc1155Proxy = await erc1155ProxyWrapper.deployProxyAsync(); - await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - authorized, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - multiAssetProxy.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(authorized, { from: owner }); + await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(multiAssetProxy.address, { from: owner }); // Configure MultiAssetProxy - await multiAssetProxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - authorized, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync( - erc20Proxy.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync( - erc721Proxy.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync( - erc1155Proxy.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await multiAssetProxy.addAuthorizedAddress.awaitTransactionSuccessAsync(authorized, { from: owner }); + await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, { from: owner }); + await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(erc721Proxy.address, { from: owner }); + await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(erc1155Proxy.address, { from: owner }); // Deploy and configure ERC20 tokens const numDummyErc20ToDeploy = 2; @@ -192,19 +152,13 @@ describe('Asset Transfer Proxies', () => { ); await erc20Wrapper.setBalancesAndAllowancesAsync(); - await noReturnErc20Token.setBalance.awaitTransactionSuccessAsync( - fromAddress, - constants.INITIAL_ERC20_BALANCE, - { - from: owner, - }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await noReturnErc20Token.setBalance.awaitTransactionSuccessAsync(fromAddress, constants.INITIAL_ERC20_BALANCE, { + from: owner, + }); await noReturnErc20Token.approve.awaitTransactionSuccessAsync( erc20Proxy.address, constants.INITIAL_ERC20_ALLOWANCE, { from: fromAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, ); await multipleReturnErc20Token.setBalance.awaitTransactionSuccessAsync( fromAddress, @@ -212,13 +166,11 @@ describe('Asset Transfer Proxies', () => { { from: owner, }, - constants.AWAIT_TRANSACTION_MINED_MS, ); await multipleReturnErc20Token.approve.awaitTransactionSuccessAsync( erc20Proxy.address, constants.INITIAL_ERC20_ALLOWANCE, { from: fromAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, ); // Deploy and configure ERC721 tokens and receiver @@ -407,12 +359,9 @@ describe('Asset Transfer Proxies', () => { toAddress, amount, ); - await erc20TokenA.approve.awaitTransactionSuccessAsync( - erc20Proxy.address, - allowance, - { from: fromAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await erc20TokenA.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, { + from: fromAddress, + }); const erc20Balances = await erc20Wrapper.getBalancesAsync(); // Perform a transfer; expect this to fail. await expectTransactionFailedAsync( @@ -439,12 +388,9 @@ describe('Asset Transfer Proxies', () => { toAddress, amount, ); - await noReturnErc20Token.approve.awaitTransactionSuccessAsync( - erc20Proxy.address, - allowance, - { from: fromAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await noReturnErc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, { + from: fromAddress, + }); const initialFromBalance = await noReturnErc20Token.balanceOf.callAsync(fromAddress); const initialToBalance = await noReturnErc20Token.balanceOf.callAsync(toAddress); // Perform a transfer; expect this to fail. @@ -680,19 +626,13 @@ describe('Asset Transfer Proxies', () => { const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId); expect(ownerFromAsset).to.be.equal(fromAddress); // Remove blanket transfer approval for fromAddress. - await erc721TokenA.setApprovalForAll.awaitTransactionSuccessAsync( - erc721Proxy.address, - false, - { from: fromAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await erc721TokenA.setApprovalForAll.awaitTransactionSuccessAsync(erc721Proxy.address, false, { + from: fromAddress, + }); // Remove token transfer approval for fromAddress. - await erc721TokenA.approve.awaitTransactionSuccessAsync( - constants.NULL_ADDRESS, - erc721AFromTokenId, - { from: fromAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await erc721TokenA.approve.awaitTransactionSuccessAsync(constants.NULL_ADDRESS, erc721AFromTokenId, { + from: fromAddress, + }); // Perform a transfer; expect this to fail. const amount = new BigNumber(1); const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( diff --git a/contracts/asset-proxy/test/utils/erc20_wrapper.ts b/contracts/asset-proxy/test/utils/erc20_wrapper.ts index 8fdd210b24..2076040bd8 100644 --- a/contracts/asset-proxy/test/utils/erc20_wrapper.ts +++ b/contracts/asset-proxy/test/utils/erc20_wrapper.ts @@ -70,13 +70,11 @@ export class ERC20Wrapper { tokenOwnerAddress, constants.INITIAL_ERC20_BALANCE, { from: this._contractOwnerAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, ); await dummyTokenContract.approve.awaitTransactionSuccessAsync( (this._proxyContract as ERC20ProxyContract).address, constants.INITIAL_ERC20_ALLOWANCE, { from: tokenOwnerAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, ); } } @@ -88,12 +86,9 @@ export class ERC20Wrapper { } public async setBalanceAsync(userAddress: string, assetData: string, amount: BigNumber): Promise { const tokenContract = this._getTokenContractFromAssetData(assetData); - await tokenContract.setBalance.awaitTransactionSuccessAsync( - userAddress, - amount, - { from: this._contractOwnerAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await tokenContract.setBalance.awaitTransactionSuccessAsync(userAddress, amount, { + from: this._contractOwnerAddress, + }); } public async getProxyAllowanceAsync(userAddress: string, assetData: string): Promise { const tokenContract = this._getTokenContractFromAssetData(assetData); @@ -104,12 +99,7 @@ export class ERC20Wrapper { public async setAllowanceAsync(userAddress: string, assetData: string, amount: BigNumber): Promise { const tokenContract = this._getTokenContractFromAssetData(assetData); const proxyAddress = (this._proxyContract as ERC20ProxyContract).address; - await tokenContract.approve.awaitTransactionSuccessAsync( - proxyAddress, - amount, - { from: userAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await tokenContract.approve.awaitTransactionSuccessAsync(proxyAddress, amount, { from: userAddress }); } public async getBalancesAsync(): Promise { this._validateDummyTokenContractsExistOrThrow(); diff --git a/contracts/asset-proxy/test/utils/erc721_wrapper.ts b/contracts/asset-proxy/test/utils/erc721_wrapper.ts index 3ff03f3d19..e2ae988930 100644 --- a/contracts/asset-proxy/test/utils/erc721_wrapper.ts +++ b/contracts/asset-proxy/test/utils/erc721_wrapper.ts @@ -93,22 +93,14 @@ export class ERC721Wrapper { ): Promise { const tokenContract = this._getTokenContractFromAssetData(tokenAddress); const proxyAddress = (this._proxyContract as ERC721ProxyContract).address; - await tokenContract.setApprovalForAll.awaitTransactionSuccessAsync( - proxyAddress, - isApproved, - { from: ownerAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await tokenContract.setApprovalForAll.awaitTransactionSuccessAsync(proxyAddress, isApproved, { + from: ownerAddress, + }); } public async approveAsync(to: string, tokenAddress: string, tokenId: BigNumber): Promise { const tokenContract = this._getTokenContractFromAssetData(tokenAddress); const tokenOwner = await this.ownerOfAsync(tokenAddress, tokenId); - await tokenContract.approve.awaitTransactionSuccessAsync( - to, - tokenId, - { from: tokenOwner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await tokenContract.approve.awaitTransactionSuccessAsync(to, tokenId, { from: tokenOwner }); } public async transferFromAsync( tokenAddress: string, @@ -117,31 +109,19 @@ export class ERC721Wrapper { userAddress: string, ): Promise { const tokenContract = this._getTokenContractFromAssetData(tokenAddress); - await tokenContract.transferFrom.awaitTransactionSuccessAsync( - currentOwner, - userAddress, - tokenId, - { from: currentOwner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await tokenContract.transferFrom.awaitTransactionSuccessAsync(currentOwner, userAddress, tokenId, { + from: currentOwner, + }); } public async mintAsync(tokenAddress: string, tokenId: BigNumber, userAddress: string): Promise { const tokenContract = this._getTokenContractFromAssetData(tokenAddress); - await tokenContract.mint.awaitTransactionSuccessAsync( - userAddress, - tokenId, - { from: this._contractOwnerAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await tokenContract.mint.awaitTransactionSuccessAsync(userAddress, tokenId, { + from: this._contractOwnerAddress, + }); } public async burnAsync(tokenAddress: string, tokenId: BigNumber, owner: string): Promise { const tokenContract = this._getTokenContractFromAssetData(tokenAddress); - await tokenContract.burn.awaitTransactionSuccessAsync( - owner, - tokenId, - { from: this._contractOwnerAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await tokenContract.burn.awaitTransactionSuccessAsync(owner, tokenId, { from: this._contractOwnerAddress }); } public async ownerOfAsync(tokenAddress: string, tokenId: BigNumber): Promise { const tokenContract = this._getTokenContractFromAssetData(tokenAddress); diff --git a/contracts/coordinator/package.json b/contracts/coordinator/package.json index 16de8c364c..037ea6909f 100644 --- a/contracts/coordinator/package.json +++ b/contracts/coordinator/package.json @@ -22,7 +22,7 @@ "compile": "sol-compiler", "watch": "sol-compiler -w", "clean": "shx rm -rf lib generated-artifacts generated-wrappers", - "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", + "generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "coverage:report:text": "istanbul report text", diff --git a/contracts/dev-utils/package.json b/contracts/dev-utils/package.json index b88780e996..99ba92c705 100644 --- a/contracts/dev-utils/package.json +++ b/contracts/dev-utils/package.json @@ -22,7 +22,7 @@ "compile": "sol-compiler", "watch": "sol-compiler -w", "clean": "shx rm -rf lib generated-artifacts generated-wrappers", - "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", + "generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "coverage:report:text": "istanbul report text", diff --git a/contracts/erc1155/package.json b/contracts/erc1155/package.json index f931f4ec11..f3111ac48c 100644 --- a/contracts/erc1155/package.json +++ b/contracts/erc1155/package.json @@ -22,7 +22,7 @@ "compile": "sol-compiler", "watch": "sol-compiler -w", "clean": "shx rm -rf lib generated-artifacts generated-wrappers", - "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", + "generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "coverage:report:text": "istanbul report text", diff --git a/contracts/erc1155/test/utils/erc1155_wrapper.ts b/contracts/erc1155/test/utils/erc1155_wrapper.ts index 5f2ea1483f..984935db17 100644 --- a/contracts/erc1155/test/utils/erc1155_wrapper.ts +++ b/contracts/erc1155/test/utils/erc1155_wrapper.ts @@ -1,4 +1,4 @@ -import { constants, LogDecoder } from '@0x/contracts-test-utils'; +import { LogDecoder } from '@0x/contracts-test-utils'; import { BigNumber } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; import * as chai from 'chai'; @@ -100,7 +100,6 @@ export class Erc1155Wrapper { beneficiaries, tokenAmountsAsArray, { from: this._contractOwner }, - constants.AWAIT_TRANSACTION_MINED_MS, ); } public async mintNonFungibleTokensAsync(beneficiaries: string[]): Promise<[BigNumber, BigNumber[]]> { @@ -114,12 +113,9 @@ export class Erc1155Wrapper { // tslint:disable-next-line no-unnecessary-type-assertion const createFungibleTokenLog = tx.logs[0] as LogWithDecodedArgs; const token = createFungibleTokenLog.args.id; - await this._erc1155Contract.mintNonFungible.awaitTransactionSuccessAsync( - token, - beneficiaries, - { from: this._contractOwner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await this._erc1155Contract.mintNonFungible.awaitTransactionSuccessAsync(token, beneficiaries, { + from: this._contractOwner, + }); const encodedNftIds: BigNumber[] = []; const nftIdBegin = 1; const nftIdEnd = beneficiaries.length + 1; diff --git a/contracts/erc20/package.json b/contracts/erc20/package.json index 6e2d280cfc..bd851a7056 100644 --- a/contracts/erc20/package.json +++ b/contracts/erc20/package.json @@ -22,7 +22,7 @@ "compile": "sol-compiler", "watch": "sol-compiler -w", "clean": "shx rm -rf lib generated-artifacts generated-wrappers", - "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", + "generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "coverage:report:text": "istanbul report text", diff --git a/contracts/erc721/package.json b/contracts/erc721/package.json index cc3c04f2a1..2bbebbba84 100644 --- a/contracts/erc721/package.json +++ b/contracts/erc721/package.json @@ -22,7 +22,7 @@ "compile": "sol-compiler", "watch": "sol-compiler -w", "clean": "shx rm -rf lib generated-artifacts generated-wrappers", - "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", + "generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "coverage:report:text": "istanbul report text", diff --git a/contracts/exchange-forwarder/package.json b/contracts/exchange-forwarder/package.json index a14a5a8cd1..7a517399ea 100644 --- a/contracts/exchange-forwarder/package.json +++ b/contracts/exchange-forwarder/package.json @@ -23,7 +23,7 @@ "compile": "sol-compiler", "watch": "sol-compiler -w", "clean": "shx rm -rf lib generated-artifacts generated-wrappers", - "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", + "generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "coverage:report:text": "istanbul report text", "coverage:report:html": "istanbul report html && open coverage/index.html", diff --git a/contracts/exchange-libs/package.json b/contracts/exchange-libs/package.json index e21a07ead7..0e88be8bd4 100644 --- a/contracts/exchange-libs/package.json +++ b/contracts/exchange-libs/package.json @@ -22,7 +22,7 @@ "compile": "sol-compiler", "watch": "sol-compiler -w", "clean": "shx rm -rf lib generated-artifacts generated-wrappers", - "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", + "generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "coverage:report:text": "istanbul report text", diff --git a/contracts/exchange/package.json b/contracts/exchange/package.json index 6f09054ea8..e61e224f68 100644 --- a/contracts/exchange/package.json +++ b/contracts/exchange/package.json @@ -22,7 +22,7 @@ "compile": "sol-compiler", "watch": "sol-compiler -w", "clean": "shx rm -rf lib generated-artifacts generated-wrappers", - "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", + "generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "coverage:report:text": "istanbul report text", diff --git a/contracts/exchange/src/wrapper_interfaces.ts b/contracts/exchange/src/wrapper_interfaces.ts index 88ed09502b..2c8fe219b1 100644 --- a/contracts/exchange/src/wrapper_interfaces.ts +++ b/contracts/exchange/src/wrapper_interfaces.ts @@ -1,4 +1,5 @@ import { PromiseWithTransactionHash } from '@0x/base-contract'; +import { AwaitTransactionSuccessOpts } from '@0x/types'; import { BlockParam, CallData, TransactionReceiptWithDecodedLogs, TxData } from 'ethereum-types'; // Generated Wrapper Interfaces @@ -7,8 +8,7 @@ export interface AssetProxyDispatcher { awaitTransactionSuccessAsync: ( assetProxy: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + txOpts?: AwaitTransactionSuccessOpts, ) => PromiseWithTransactionHash; }; getAssetProxy: { @@ -21,16 +21,14 @@ export interface Authorizable extends Ownable { awaitTransactionSuccessAsync: ( target: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + txOpts?: AwaitTransactionSuccessOpts, ) => PromiseWithTransactionHash; }; removeAuthorizedAddress: { awaitTransactionSuccessAsync: ( target: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + txOpts?: AwaitTransactionSuccessOpts, ) => PromiseWithTransactionHash; }; authorized: { @@ -46,8 +44,7 @@ export interface Ownable { awaitTransactionSuccessAsync: ( newOwner: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + txOpts?: AwaitTransactionSuccessOpts, ) => PromiseWithTransactionHash; }; owner: { diff --git a/contracts/exchange/test/match_orders.ts b/contracts/exchange/test/match_orders.ts index 3c74932c8c..c2d1a09bb3 100644 --- a/contracts/exchange/test/match_orders.ts +++ b/contracts/exchange/test/match_orders.ts @@ -141,56 +141,30 @@ describe('matchOrders', () => { await exchangeWrapper.registerAssetProxyAsync(erc1155Proxy.address, owner); await exchangeWrapper.registerAssetProxyAsync(multiAssetProxyContract.address, owner); // Authorize proxies. - await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - exchange.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - exchange.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - exchange.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await multiAssetProxyContract.addAuthorizedAddress.awaitTransactionSuccessAsync( - exchange.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - multiAssetProxyContract.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - multiAssetProxyContract.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - multiAssetProxyContract.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await multiAssetProxyContract.registerAssetProxy.awaitTransactionSuccessAsync( - erc20Proxy.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await multiAssetProxyContract.registerAssetProxy.awaitTransactionSuccessAsync( - erc721Proxy.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await multiAssetProxyContract.registerAssetProxy.awaitTransactionSuccessAsync( - erc1155Proxy.address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchange.address, { from: owner }); + await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchange.address, { from: owner }); + await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchange.address, { from: owner }); + await multiAssetProxyContract.addAuthorizedAddress.awaitTransactionSuccessAsync(exchange.address, { + from: owner, + }); + await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(multiAssetProxyContract.address, { + from: owner, + }); + await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(multiAssetProxyContract.address, { + from: owner, + }); + await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(multiAssetProxyContract.address, { + from: owner, + }); + await multiAssetProxyContract.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, { + from: owner, + }); + await multiAssetProxyContract.registerAssetProxy.awaitTransactionSuccessAsync(erc721Proxy.address, { + from: owner, + }); + await multiAssetProxyContract.registerAssetProxy.awaitTransactionSuccessAsync(erc1155Proxy.address, { + from: owner, + }); // Set default addresses defaultERC20MakerAssetAddress = erc20Tokens[0].address; diff --git a/contracts/exchange/test/utils/fill_order_combinatorial_utils.ts b/contracts/exchange/test/utils/fill_order_combinatorial_utils.ts index 89cf4e801e..bee9116bc4 100644 --- a/contracts/exchange/test/utils/fill_order_combinatorial_utils.ts +++ b/contracts/exchange/test/utils/fill_order_combinatorial_utils.ts @@ -123,65 +123,37 @@ export async function fillOrderCombinatorialUtilsFactoryAsync( await exchangeWrapper.registerAssetProxyAsync(erc1155Proxy.address, ownerAddress); await exchangeWrapper.registerAssetProxyAsync(multiAssetProxy.address, ownerAddress); - await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - exchangeContract.address, - { from: ownerAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchangeContract.address, { + from: ownerAddress, + }); - await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - exchangeContract.address, - { from: ownerAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchangeContract.address, { + from: ownerAddress, + }); - await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - exchangeContract.address, - { from: ownerAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchangeContract.address, { + from: ownerAddress, + }); - await multiAssetProxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - exchangeContract.address, - { from: ownerAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await multiAssetProxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchangeContract.address, { + from: ownerAddress, + }); - await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - multiAssetProxy.address, - { from: ownerAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(multiAssetProxy.address, { from: ownerAddress }); - await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - multiAssetProxy.address, - { from: ownerAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await erc721Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(multiAssetProxy.address, { + from: ownerAddress, + }); - await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync( - multiAssetProxy.address, - { from: ownerAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await erc1155Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(multiAssetProxy.address, { + from: ownerAddress, + }); - await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync( - erc20Proxy.address, - { from: ownerAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, { from: ownerAddress }); - await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync( - erc721Proxy.address, - { from: ownerAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(erc721Proxy.address, { from: ownerAddress }); - await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync( - erc1155Proxy.address, - { from: ownerAddress }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(erc1155Proxy.address, { from: ownerAddress }); const orderFactory = new OrderFactoryFromScenario( userAddresses, diff --git a/contracts/extensions/package.json b/contracts/extensions/package.json index 982f4edf5e..6d7716c0a3 100644 --- a/contracts/extensions/package.json +++ b/contracts/extensions/package.json @@ -22,7 +22,7 @@ "compile": "sol-compiler", "watch": "sol-compiler -w", "clean": "shx rm -rf lib generated-artifacts generated-wrappers", - "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", + "generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "coverage:report:text": "istanbul report text", diff --git a/contracts/multisig/package.json b/contracts/multisig/package.json index 1e4d940868..bc861442a5 100644 --- a/contracts/multisig/package.json +++ b/contracts/multisig/package.json @@ -22,7 +22,7 @@ "compile": "sol-compiler", "watch": "sol-compiler -w", "clean": "shx rm -rf lib generated-artifacts generated-wrappers", - "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", + "generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "coverage:report:text": "istanbul report text", diff --git a/contracts/staking/package.json b/contracts/staking/package.json index 884892949b..47e010ba2f 100644 --- a/contracts/staking/package.json +++ b/contracts/staking/package.json @@ -23,7 +23,7 @@ "compile": "sol-compiler", "watch": "sol-compiler -w", "clean": "shx rm -rf lib generated-artifacts generated-wrappers", - "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", + "generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "coverage:report:text": "istanbul report text", diff --git a/contracts/utils/package.json b/contracts/utils/package.json index 76834fe6d9..a1d1f697dd 100644 --- a/contracts/utils/package.json +++ b/contracts/utils/package.json @@ -22,7 +22,7 @@ "compile": "sol-compiler", "watch": "sol-compiler -w", "clean": "shx rm -rf lib generated-artifacts generated-wrappers", - "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", + "generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output generated-wrappers --backend ethers", "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "coverage:report:text": "istanbul report text", diff --git a/contracts/utils/test/authorizable.ts b/contracts/utils/test/authorizable.ts index df70f84e19..b2a1a46876 100644 --- a/contracts/utils/test/authorizable.ts +++ b/contracts/utils/test/authorizable.ts @@ -63,11 +63,7 @@ describe('Authorizable', () => { }); it('should revert if owner attempts to authorize a duplicate address', async () => { - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); const expectedError = new AuthorizableRevertErrors.TargetAlreadyAuthorizedError(address); const tx = authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }); return expect(tx).to.revertWith(expectedError); @@ -76,27 +72,15 @@ describe('Authorizable', () => { describe('removeAuthorizedAddress', () => { it('should revert if not called by owner', async () => { - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); const expectedError = new OwnableRevertErrors.OnlyOwnerError(notOwner, owner); const tx = authorizable.removeAuthorizedAddress.sendTransactionAsync(address, { from: notOwner }); return expect(tx).to.revertWith(expectedError); }); it('should allow owner to remove an authorized address', async () => { - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await authorizable.removeAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); + await authorizable.removeAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); const isAuthorized = await authorizable.authorized.callAsync(address); expect(isAuthorized).to.be.false(); }); @@ -110,11 +94,7 @@ describe('Authorizable', () => { describe('removeAuthorizedAddressAtIndex', () => { it('should revert if not called by owner', async () => { - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); const index = new BigNumber(0); const expectedError = new OwnableRevertErrors.OnlyOwnerError(notOwner, owner); const tx = authorizable.removeAuthorizedAddressAtIndex.sendTransactionAsync(address, index, { @@ -124,11 +104,7 @@ describe('Authorizable', () => { }); it('should revert if index is >= authorities.length', async () => { - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); const index = new BigNumber(1); const expectedError = new AuthorizableRevertErrors.IndexOutOfBoundsError(index, index); const tx = authorizable.removeAuthorizedAddressAtIndex.sendTransactionAsync(address, index, { @@ -149,16 +125,8 @@ describe('Authorizable', () => { it('should revert if address at index does not match target', async () => { const address1 = address; const address2 = notOwner; - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address1, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address2, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address1, { from: owner }); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address2, { from: owner }); const address1Index = new BigNumber(0); const expectedError = new AuthorizableRevertErrors.AuthorizedAddressMismatchError(address1, address2); const tx = authorizable.removeAuthorizedAddressAtIndex.sendTransactionAsync(address2, address1Index, { @@ -168,18 +136,11 @@ describe('Authorizable', () => { }); it('should allow owner to remove an authorized address', async () => { - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); const index = new BigNumber(0); - await authorizable.removeAuthorizedAddressAtIndex.awaitTransactionSuccessAsync( - address, - index, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.removeAuthorizedAddressAtIndex.awaitTransactionSuccessAsync(address, index, { + from: owner, + }); const isAuthorized = await authorizable.authorized.callAsync(address); expect(isAuthorized).to.be.false(); }); @@ -189,19 +150,11 @@ describe('Authorizable', () => { it('should return all authorized addresses', async () => { const initial = await authorizable.getAuthorizedAddresses.callAsync(); expect(initial).to.have.length(0); - await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); const afterAdd = await authorizable.getAuthorizedAddresses.callAsync(); expect(afterAdd).to.have.length(1); expect(afterAdd).to.include(address); - await authorizable.removeAuthorizedAddress.awaitTransactionSuccessAsync( - address, - { from: owner }, - constants.AWAIT_TRANSACTION_MINED_MS, - ); + await authorizable.removeAuthorizedAddress.awaitTransactionSuccessAsync(address, { from: owner }); const afterRemove = await authorizable.getAuthorizedAddresses.callAsync(); expect(afterRemove).to.have.length(0); }); diff --git a/packages/0x.js/src/index.ts b/packages/0x.js/src/index.ts index 5f857bb0fa..291ab39c5b 100644 --- a/packages/0x.js/src/index.ts +++ b/packages/0x.js/src/index.ts @@ -83,6 +83,8 @@ export { SimpleEvmOutput, SimpleEvmBytecodeOutput, EIP712DomainWithDefaultSchema, + AwaitTransactionSuccessOpts, + SendTransactionOpts, EventCallback, IndexedFilterValues, DecodedLogEvent, diff --git a/packages/abi-gen-wrappers/CHANGELOG.json b/packages/abi-gen-wrappers/CHANGELOG.json index d1fb15b3c8..e58a45f47a 100644 --- a/packages/abi-gen-wrappers/CHANGELOG.json +++ b/packages/abi-gen-wrappers/CHANGELOG.json @@ -1,4 +1,25 @@ [ + { + "version": "5.4.0-beta.1", + "changes": [ + { + "note": "Remove debug functions `getABIDecodedTransactionData` and `getABIDecodedReturnData`", + "pr": 2243 + }, + { + "note": "Remove `getABIEncodedTransactionData` for constant functions (pure and view)", + "pr": 2243 + }, + { + "note": "Introduce TxOpts object for `sendTransactionAsync` and `awaitTransactionSuccessAsync`. Replaces `timeoutMs` and `pollingIntervalMs` arguments for `awaitTransactionSuccessAsync`", + "pr": 2243 + }, + { + "note": "Remove `validateAndSendTransactionAsync`. Replaced with `shouldValidate` key in TxOpts. Defaults to true", + "pr": 2243 + } + ] + }, { "version": "5.4.0-beta.0", "changes": [ diff --git a/packages/abi-gen-wrappers/package.json b/packages/abi-gen-wrappers/package.json index 48925f10e3..74d41fee72 100644 --- a/packages/abi-gen-wrappers/package.json +++ b/packages/abi-gen-wrappers/package.json @@ -34,21 +34,20 @@ "homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen-wrappers/README.md", "devDependencies": { "@0x/abi-gen": "^4.3.0-beta.0", - "@0x/assert": "^2.2.0-beta.0", - "@0x/json-schemas": "^4.1.0-beta.0", + "@0x/contract-artifacts": "^2.3.0-beta.0", "@0x/tslint-config": "^3.0.1", - "@0x/types": "^2.5.0-beta.0", - "@0x/utils": "^4.6.0-beta.0", - "@0x/web3-wrapper": "^6.1.0-beta.0", - "ethereum-types": "^2.2.0-beta.0", - "ethers": "~4.0.4", - "lodash": "^4.17.11", "shx": "^0.2.2" }, "dependencies": { + "@0x/assert": "^2.2.0-beta.0", "@0x/base-contract": "^5.5.0-beta.0", "@0x/contract-addresses": "^3.3.0-beta.0", - "@0x/contract-artifacts": "^2.3.0-beta.0" + "@0x/json-schemas": "^4.1.0-beta.0", + "@0x/types": "^2.5.0-beta.0", + "@0x/utils": "^4.6.0-beta.0", + "@0x/web3-wrapper": "^6.1.0-beta.0", + "ethereum-types": "^2.2.0-beta.0", + "ethers": "~4.0.4" }, "publishConfig": { "access": "public" diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/asset_proxy_owner.ts b/packages/abi-gen-wrappers/src/generated-wrappers/asset_proxy_owner.ts index 7f9cb9d1e0..1e6aee0d1a 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/asset_proxy_owner.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/asset_proxy_owner.ts @@ -19,7 +19,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -113,8 +119,10 @@ export interface AssetProxyOwnerTimeLockChangeEventArgs extends DecodedLogArgs { // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class AssetProxyOwnerContract extends BaseContract { - public static deployedBytecode = - '0x6080604052600436106101a15760003560e01c80639ace38c2116100e1578063c01a8c841161008a578063d74f8edd11610064578063d74f8edd146104ff578063dc8452cd14610514578063e20056e614610529578063ee22610b14610549576101a1565b8063c01a8c841461049f578063c6427474146104bf578063d38f2d82146104df576101a1565b8063b5dc40c3116100bb578063b5dc40c31461044a578063b77bf6001461046a578063ba51a6df1461047f576101a1565b80639ace38c2146103cb578063a0e67e2b146103fb578063a8abe69a1461041d576101a1565b8063547415251161014e578063784547a711610128578063784547a71461033d5780637ad28c511461035d5780637f05c8b61461037d5780638b51d13f146103ab576101a1565b806354741525146102dd5780637065cb48146102fd578063751ad5601461031d576101a1565b80632f54bf6e1161017f5780632f54bf6e1461026e5780633411c81c1461029b57806337bd78a0146102bb576101a1565b8063025e7c27146101f8578063173825d91461022e57806320ea8d861461024e575b34156101f6573373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040516101ed9190612b44565b60405180910390a25b005b34801561020457600080fd5b50610218610213366004612580565b610569565b6040516102259190612616565b60405180910390f35b34801561023a57600080fd5b506101f6610249366004612303565b61059d565b34801561025a57600080fd5b506101f6610269366004612580565b61084c565b34801561027a57600080fd5b5061028e610289366004612303565b6109a7565b6040516102259190612745565b3480156102a757600080fd5b5061028e6102b6366004612598565b6109bc565b3480156102c757600080fd5b506102d06109dc565b6040516102259190612b44565b3480156102e957600080fd5b506102d06102f83660046124c0565b6109e2565b34801561030957600080fd5b506101f6610318366004612303565b610a4e565b34801561032957600080fd5b506101f66103383660046124f4565b610c73565b34801561034957600080fd5b5061028e610358366004612580565b610cbe565b34801561036957600080fd5b506101f6610378366004612580565b610d52565b34801561038957600080fd5b5061039d610398366004612563565b610dcb565b604051610225929190612750565b3480156103b757600080fd5b506102d06103c6366004612580565b610e04565b3480156103d757600080fd5b506103eb6103e6366004612580565b610e80565b6040516102259493929190612637565b34801561040757600080fd5b50610410610f69565b60405161022591906126b4565b34801561042957600080fd5b5061043d6104383660046125bc565b610fd9565b604051610225919061270d565b34801561045657600080fd5b50610410610465366004612580565b611104565b34801561047657600080fd5b506102d06112bc565b34801561048b57600080fd5b506101f661049a366004612580565b6112c2565b3480156104ab57600080fd5b506101f66104ba366004612580565b61139e565b3480156104cb57600080fd5b506102d06104da366004612357565b611568565b3480156104eb57600080fd5b506102d06104fa366004612580565b611587565b34801561050b57600080fd5b506102d0611599565b34801561052057600080fd5b506102d061159e565b34801561053557600080fd5b506101f661054436600461231f565b6115a4565b34801561055557600080fd5b506101f6610564366004612580565b61182e565b6003818154811061057657fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b3330146105df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d690612a68565b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116600090815260026020526040902054819060ff16610640576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d6906129fa565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260026020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b6003547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018110156107bc578273ffffffffffffffffffffffffffffffffffffffff16600382815481106106dc57fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1614156107b457600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190811061073457fe5b6000918252602090912001546003805473ffffffffffffffffffffffffffffffffffffffff909216918390811061076757fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506107bc565b60010161068c565b50600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01906107ee9082612100565b50600354600454111561080757600354610807906112c2565b60405173ffffffffffffffffffffffffffffffffffffffff8316907f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9090600090a25050565b3360008181526002602052604090205460ff16610895576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d6906129fa565b60008281526001602090815260408083203380855292529091205483919060ff166108ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d690612955565b600084815260208190526040902060030154849060ff161561093a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d690612ad6565b600085815260016020908152604080832033808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555187927ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e991a35050505050565b60026020526000908152604090205460ff1681565b600160209081526000928352604080842090915290825290205460ff1681565b60065481565b6000805b600554811015610a4757838015610a0f575060008181526020819052604090206003015460ff16155b80610a335750828015610a33575060008181526020819052604090206003015460ff165b15610a3f576001820191505b6001016109e6565b5092915050565b333014610a87576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d690612a68565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260026020526040902054819060ff1615610ae9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d690612879565b8173ffffffffffffffffffffffffffffffffffffffff8116610b37576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d69061280b565b60038054905060010160045460328211158015610b545750818111155b8015610b5f57508015155b8015610b6a57508115155b610ba0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d690612b0d565b73ffffffffffffffffffffffffffffffffffffffff851660008181526002602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915560038054918201815583527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180547fffffffffffffffffffffffff00000000000000000000000000000000000000001684179055517ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d9190a25050505050565b333014610cac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d690612a68565b610cb884848484611b79565b50505050565b600080805b600354811015610d4a5760008481526001602052604081206003805491929184908110610cec57fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff1615610d2d576001820191505b600454821415610d4257600192505050610d4d565b600101610cc3565b50505b919050565b333014610d8b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d690612a68565b60068190556040517fd1c9101a34feff75cccef14a28785a0279cb0b49c1f321f21f5f422e746b437790610dc0908390612b44565b60405180910390a150565b600860209081526000928352604080842090915290825290205460ff81169061010090046fffffffffffffffffffffffffffffffff1682565b6000805b600354811015610e7a5760008381526001602052604081206003805491929184908110610e3157fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff1615610e72576001820191505b600101610e08565b50919050565b60006020818152918152604090819020805460018083015460028085018054875161010095821615959095027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff011691909104601f810188900488028401880190965285835273ffffffffffffffffffffffffffffffffffffffff90931695909491929190830182828015610f565780601f10610f2b57610100808354040283529160200191610f56565b820191906000526020600020905b815481529060010190602001808311610f3957829003601f168201915b5050506003909301549192505060ff1684565b60606003805480602002602001604051908101604052809291908181526020018280548015610fce57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610fa3575b505050505090505b90565b606080600554604051908082528060200260200182016040528015611008578160200160208202803883390190505b5090506000805b60055481101561108957858015611038575060008181526020819052604090206003015460ff16155b8061105c575084801561105c575060008181526020819052604090206003015460ff165b15611081578083838151811061106e57fe5b6020026020010181815250506001820191505b60010161100f565b8787036040519080825280602002602001820160405280156110b5578160200160208202803883390190505b5093508790505b868110156110f9578281815181106110d057fe5b602002602001015184898303815181106110e657fe5b60209081029190910101526001016110bc565b505050949350505050565b606080600380549050604051908082528060200260200182016040528015611136578160200160208202803883390190505b5090506000805b60035481101561122d576000858152600160205260408120600380549192918490811061116657fe5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff161561122557600381815481106111ad57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168383815181106111e457fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506001820191505b60010161113d565b81604051908082528060200260200182016040528015611257578160200160208202803883390190505b509350600090505b818110156112b45782818151811061127357fe5b602002602001015184828151811061128757fe5b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015260010161125f565b505050919050565b60055481565b3330146112fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d690612a68565b60035481603282118015906113105750818111155b801561131b57508015155b801561132657508115155b61135c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d690612b0d565b60048390556040517fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a90611391908590612b44565b60405180910390a1505050565b3360008181526002602052604090205460ff166113e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d6906129fa565b600082815260208190526040902054829073ffffffffffffffffffffffffffffffffffffffff16611444576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d69061291e565b60008381526001602090815260408083203380855292529091205484919060ff161561149c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d6906128b0565b846114a681610cbe565b156114dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d690612a9f565b600086815260016020818152604080842033808652925280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909317909255905188927f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef91a361155186610cbe565b15611560576115608642611cb1565b505050505050565b6000611575848484611d00565b90506115808161139e565b9392505050565b60076020526000908152604090205481565b603281565b60045481565b3330146115dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d690612a68565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260026020526040902054829060ff1661163e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d6906129fa565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260026020526040902054829060ff16156116a0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d690612879565b60005b60035481101561175c578473ffffffffffffffffffffffffffffffffffffffff16600382815481106116d157fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16141561175457836003828154811061170757fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061175c565b6001016116a3565b5073ffffffffffffffffffffffffffffffffffffffff80851660008181526002602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090811690915593871682528082208054909416600117909355915190917f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9091a260405173ffffffffffffffffffffffffffffffffffffffff8416907ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d90600090a250505050565b600081815260208190526040902060030154819060ff161561187c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d690612ad6565b8161188681610cbe565b6118bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d6906128e7565b6000838152602081815260409182902060038101805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116811790915560028083018054865161010094821615949094027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff011691909104601f81018590048502830185019095528482529193606093849384939290918301828280156119a85780601f1061197d576101008083540402835291602001916119a8565b820191906000526020600020905b81548152906001019060200180831161198b57829003601f168201915b50505050508060200190516119c091908101906123ec565b9250925092506000835190508251811480156119dc5750815181145b611a12576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d69061298c565b600088815260076020526040812054905b828114611b4257611a5b82878381518110611a3a57fe5b6020026020010151878481518110611a4e57fe5b6020026020010151611e5e565b6000858281518110611a6957fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16858381518110611a9357fe5b6020026020010151888481518110611aa757fe5b6020026020010151604051611abc91906125fa565b60006040518083038185875af1925050503d8060008114611af9576040519150601f19603f3d011682016040523d82523d6000602084013e611afe565b606091505b5050905080611b39576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d6906129c3565b50600101611a23565b5060405189907f33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed7590600090a2505050505050505050565b600084611b87576000611b89565b815b9050611b93612129565b5060408051808201825286151581526fffffffffffffffffffffffffffffffff80841660208084019182527fffffffff00000000000000000000000000000000000000000000000000000000891660009081526008825285812073ffffffffffffffffffffffffffffffffffffffff8a168252909152849020835181549251909316610100027fffffffffffffffffffffffffffffff00000000000000000000000000000000ff9315157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179290921617905590517f694405724de467488eda192d814f39ffe7f6503fe0b1eefd4ea332f9c611c5ec90611ca190879087908a908790612772565b60405180910390a1505050505050565b600082815260076020526040908190208290555182907f0b237afe65f1514fd7ea3f923ea4fe792bdd07000a912b6cd1602a8e7f573c8d90611cf4908490612b44565b60405180910390a25050565b60008373ffffffffffffffffffffffffffffffffffffffff8116611d50576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d69061280b565b6005546040805160808101825273ffffffffffffffffffffffffffffffffffffffff8881168252602080830189815283850189815260006060860181905287815280845295909520845181547fffffffffffffffffffffffff00000000000000000000000000000000000000001694169390931783555160018301559251805194965091939092611de8926002850192910190612140565b5060609190910151600390910180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905560058054600101905560405182907fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5190600090a2509392505050565b6000611e70838263ffffffff611fbd16565b9050611e7a612129565b507fffffffff000000000000000000000000000000000000000000000000000000008116600090815260086020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845282529182902082518084019093525460ff811615801584526101009091046fffffffffffffffffffffffffffffffff1691830191909152611f69576020810151611f2b9086906fffffffffffffffffffffffffffffffff1663ffffffff61201816565b421015611f64576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d690612a31565b611fb6565b600654611f7d90869063ffffffff61201816565b421015611fb6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d690612842565b5050505050565b60008160040183511015611fe357611fe3611fde6003855185600401612034565b6120d9565b5060208183018101519101907fffffffff00000000000000000000000000000000000000000000000000000000165b92915050565b60008282018381101561158057611580611fde600086866120e1565b6060632800659560e01b848484604051602401612053939291906127fd565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290509392505050565b805160208201fd5b606063e946c1bb60e01b848484604051602401612053939291906127db565b815481835581811115612124576000838152602090206121249181019083016121be565b505050565b604080518082019091526000808252602082015290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061218157805160ff19168380011785556121ae565b828001600101855582156121ae579182015b828111156121ae578251825591602001919060010190612193565b506121ba9291506121be565b5090565b610fd691905b808211156121ba57600081556001016121c4565b600082601f8301126121e8578081fd5b81516121fb6121f682612b74565b612b4d565b81815291506020808301908481018184028601820187101561221c57600080fd5b60005b8481101561224457815161223281612c02565b8452928201929082019060010161221f565b505050505092915050565b600082601f83011261225f578081fd5b815161226d6121f682612b74565b81815291506020808301908481018184028601820187101561228e57600080fd5b60005b8481101561224457815184529282019290820190600101612291565b8035801515811461201257600080fd5b600082601f8301126122cd578081fd5b81516122db6121f682612b94565b91508082528360208285010111156122f257600080fd5b610a47816020840160208601612bd6565b600060208284031215612314578081fd5b813561158081612c02565b60008060408385031215612331578081fd5b823561233c81612c02565b9150602083013561234c81612c02565b809150509250929050565b60008060006060848603121561236b578081fd5b833561237681612c02565b925060208401359150604084013567ffffffffffffffff811115612398578182fd5b80850186601f8201126123a9578283fd5b803591506123b96121f683612b94565b8281528760208484010111156123cd578384fd5b8260208301602083013783602084830101528093505050509250925092565b600080600060608486031215612400578283fd5b835167ffffffffffffffff80821115612417578485fd5b81860187601f820112612428578586fd5b805192506124386121f684612b74565b83815260208082019190838101895b878110156124705761245e8d8484518901016122bd565b85529382019390820190600101612447565b50508901519097509350505080821115612488578384fd5b612494878388016121d8565b935060408601519150808211156124a9578283fd5b506124b68682870161224f565b9150509250925092565b600080604083850312156124d2578182fd5b6124dc84846122ad565b91506124eb84602085016122ad565b90509250929050565b60008060008060808587031215612509578081fd5b843561251481612c27565b9350602085013561252481612c35565b9250604085013561253481612c02565b915060608501356fffffffffffffffffffffffffffffffff81168114612558578182fd5b939692955090935050565b60008060408385031215612575578182fd5b823561233c81612c35565b600060208284031215612591578081fd5b5035919050565b600080604083850312156125aa578182fd5b82359150602083013561234c81612c02565b600080600080608085870312156125d1578182fd5b843593506020850135925060408501356125ea81612c27565b9150606085013561255881612c27565b6000825161260c818460208701612bd6565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff861682528460208301526080604083015283518060808401526126788160a0850160208801612bd6565b921515606083015250601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160160a0019392505050565b602080825282518282018190526000918401906040840190835b8181101561270257835173ffffffffffffffffffffffffffffffffffffffff168352602093840193909201916001016126ce565b509095945050505050565b602080825282518282018190526000918401906040840190835b81811015612702578351835260209384019390920191600101612727565b901515815260200190565b91151582526fffffffffffffffffffffffffffffffff16602082015260400190565b7fffffffff0000000000000000000000000000000000000000000000000000000094909416845273ffffffffffffffffffffffffffffffffffffffff929092166020840152151560408301526fffffffffffffffffffffffffffffffff16606082015260800190565b60608101600485106127e957fe5b938152602081019290925260409091015290565b60608101600885106127e957fe5b6020808252600c908201527f4e554c4c5f414444524553530000000000000000000000000000000000000000604082015260600190565b6020808252601c908201527f44454641554c545f54494d455f4c4f434b5f494e434f4d504c45544500000000604082015260600190565b6020808252600c908201527f4f574e45525f4558495354530000000000000000000000000000000000000000604082015260600190565b60208082526014908201527f54585f414c52454144595f434f4e4649524d4544000000000000000000000000604082015260600190565b60208082526016908201527f54585f4e4f545f46554c4c595f434f4e4649524d454400000000000000000000604082015260600190565b6020808252600f908201527f54585f444f45534e545f45584953540000000000000000000000000000000000604082015260600190565b60208082526010908201527f54585f4e4f545f434f4e4649524d454400000000000000000000000000000000604082015260600190565b60208082526016908201527f455155414c5f4c454e475448535f524551554952454400000000000000000000604082015260600190565b60208082526010908201527f4641494c45445f455845435554494f4e00000000000000000000000000000000604082015260600190565b60208082526012908201527f4f574e45525f444f45534e545f45584953540000000000000000000000000000604082015260600190565b6020808252601b908201527f435553544f4d5f54494d455f4c4f434b5f494e434f4d504c4554450000000000604082015260600190565b60208082526017908201527f4f4e4c595f43414c4c41424c455f42595f57414c4c4554000000000000000000604082015260600190565b60208082526012908201527f54585f46554c4c595f434f4e4649524d45440000000000000000000000000000604082015260600190565b60208082526013908201527f54585f414c52454144595f455845435554454400000000000000000000000000604082015260600190565b60208082526014908201527f494e56414c49445f524551554952454d454e5453000000000000000000000000604082015260600190565b90815260200190565b60405181810167ffffffffffffffff81118282101715612b6c57600080fd5b604052919050565b600067ffffffffffffffff821115612b8a578081fd5b5060209081020190565b600067ffffffffffffffff821115612baa578081fd5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b83811015612bf1578181015183820152602001612bd9565b83811115610cb85750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114612c2457600080fd5b50565b8015158114612c2457600080fd5b7fffffffff0000000000000000000000000000000000000000000000000000000081168114612c2457600080fdfea365627a7a723158200ac5186607cd3ec8212bb7bd34d7047a94bed6fb931222d7ea453055d00701cd6c6578706572696d656e74616cf564736f6c634300050c0040'; + /** + * @ignore + */ + public static deployedBytecode: string | undefined; public MAX_OWNER_COUNT = { /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an @@ -157,41 +165,6 @@ export class AssetProxyOwnerContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncodedTransactionData = self._strictEncodeArguments('MAX_OWNER_COUNT()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('MAX_OWNER_COUNT()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('MAX_OWNER_COUNT()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Allows to add a new owner. Transaction has to be sent by wallet. @@ -204,7 +177,11 @@ export class AssetProxyOwnerContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(owner: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + owner: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('owner', owner); const self = (this as any) as AssetProxyOwnerContract; const encodedData = self._strictEncodeArguments('addOwner(address)', [owner.toLowerCase()]); @@ -220,6 +197,10 @@ export class AssetProxyOwnerContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.addOwner.callAsync(owner, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -234,20 +215,19 @@ export class AssetProxyOwnerContract extends BaseContract { awaitTransactionSuccessAsync( owner: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('owner', owner); const self = (this as any) as AssetProxyOwnerContract; - const txHashPromise = self.addOwner.sendTransactionAsync(owner.toLowerCase(), txData); + const txHashPromise = self.addOwner.sendTransactionAsync(owner.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -277,11 +257,6 @@ export class AssetProxyOwnerContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(owner: string, txData?: Partial | undefined): Promise { - await (this as any).addOwner.callAsync(owner, txData); - const txHash = await (this as any).addOwner.sendTransactionAsync(owner, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -338,30 +313,6 @@ export class AssetProxyOwnerContract extends BaseContract { const abiEncodedTransactionData = self._strictEncodeArguments('addOwner(address)', [owner.toLowerCase()]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('addOwner(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('addOwner(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Allows to change the number of required confirmations. Transaction has to be sent by wallet. @@ -374,7 +325,11 @@ export class AssetProxyOwnerContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(_required: BigNumber, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + _required: BigNumber, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isBigNumber('_required', _required); const self = (this as any) as AssetProxyOwnerContract; const encodedData = self._strictEncodeArguments('changeRequirement(uint256)', [_required]); @@ -390,6 +345,10 @@ export class AssetProxyOwnerContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.changeRequirement.callAsync(_required, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -404,20 +363,19 @@ export class AssetProxyOwnerContract extends BaseContract { awaitTransactionSuccessAsync( _required: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isBigNumber('_required', _required); const self = (this as any) as AssetProxyOwnerContract; - const txHashPromise = self.changeRequirement.sendTransactionAsync(_required, txData); + const txHashPromise = self.changeRequirement.sendTransactionAsync(_required, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -447,14 +405,6 @@ export class AssetProxyOwnerContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _required: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).changeRequirement.callAsync(_required, txData); - const txHash = await (this as any).changeRequirement.sendTransactionAsync(_required, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -515,30 +465,6 @@ export class AssetProxyOwnerContract extends BaseContract { const abiEncodedTransactionData = self._strictEncodeArguments('changeRequirement(uint256)', [_required]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [BigNumber] { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('changeRequirement(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('changeRequirement(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Changes the duration of the time lock for transactions. @@ -555,6 +481,7 @@ export class AssetProxyOwnerContract extends BaseContract { async sendTransactionAsync( _secondsTimeLocked: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isBigNumber('_secondsTimeLocked', _secondsTimeLocked); const self = (this as any) as AssetProxyOwnerContract; @@ -571,6 +498,10 @@ export class AssetProxyOwnerContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.changeTimeLock.callAsync(_secondsTimeLocked, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -586,20 +517,19 @@ export class AssetProxyOwnerContract extends BaseContract { awaitTransactionSuccessAsync( _secondsTimeLocked: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isBigNumber('_secondsTimeLocked', _secondsTimeLocked); const self = (this as any) as AssetProxyOwnerContract; - const txHashPromise = self.changeTimeLock.sendTransactionAsync(_secondsTimeLocked, txData); + const txHashPromise = self.changeTimeLock.sendTransactionAsync(_secondsTimeLocked, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -630,14 +560,6 @@ export class AssetProxyOwnerContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _secondsTimeLocked: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).changeTimeLock.callAsync(_secondsTimeLocked, txData); - const txHash = await (this as any).changeTimeLock.sendTransactionAsync(_secondsTimeLocked, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -702,30 +624,6 @@ export class AssetProxyOwnerContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [BigNumber] { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('changeTimeLock(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('changeTimeLock(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Allows an owner to confirm a transaction. @@ -738,7 +636,11 @@ export class AssetProxyOwnerContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(transactionId: BigNumber, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + transactionId: BigNumber, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isBigNumber('transactionId', transactionId); const self = (this as any) as AssetProxyOwnerContract; const encodedData = self._strictEncodeArguments('confirmTransaction(uint256)', [transactionId]); @@ -754,6 +656,10 @@ export class AssetProxyOwnerContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.confirmTransaction.callAsync(transactionId, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -768,20 +674,19 @@ export class AssetProxyOwnerContract extends BaseContract { awaitTransactionSuccessAsync( transactionId: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isBigNumber('transactionId', transactionId); const self = (this as any) as AssetProxyOwnerContract; - const txHashPromise = self.confirmTransaction.sendTransactionAsync(transactionId, txData); + const txHashPromise = self.confirmTransaction.sendTransactionAsync(transactionId, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -811,14 +716,6 @@ export class AssetProxyOwnerContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - transactionId: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).confirmTransaction.callAsync(transactionId, txData); - const txHash = await (this as any).confirmTransaction.sendTransactionAsync(transactionId, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -881,30 +778,6 @@ export class AssetProxyOwnerContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [BigNumber] { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('confirmTransaction(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('confirmTransaction(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public confirmationTimes = { /** @@ -953,42 +826,6 @@ export class AssetProxyOwnerContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: BigNumber): string { - assert.isBigNumber('index_0', index_0); - const self = (this as any) as AssetProxyOwnerContract; - const abiEncodedTransactionData = self._strictEncodeArguments('confirmationTimes(uint256)', [index_0]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): BigNumber { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('confirmationTimes(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('confirmationTimes(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public confirmations = { /** @@ -1042,46 +879,6 @@ export class AssetProxyOwnerContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: BigNumber, index_1: string): string { - assert.isBigNumber('index_0', index_0); - assert.isString('index_1', index_1); - const self = (this as any) as AssetProxyOwnerContract; - const abiEncodedTransactionData = self._strictEncodeArguments('confirmations(uint256,address)', [ - index_0, - index_1.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): BigNumber { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('confirmations(uint256,address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('confirmations(uint256,address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Allows anyone to execute a confirmed transaction. @@ -1097,7 +894,11 @@ export class AssetProxyOwnerContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(transactionId: BigNumber, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + transactionId: BigNumber, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isBigNumber('transactionId', transactionId); const self = (this as any) as AssetProxyOwnerContract; const encodedData = self._strictEncodeArguments('executeTransaction(uint256)', [transactionId]); @@ -1113,6 +914,10 @@ export class AssetProxyOwnerContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.executeTransaction.callAsync(transactionId, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1127,20 +932,19 @@ export class AssetProxyOwnerContract extends BaseContract { awaitTransactionSuccessAsync( transactionId: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isBigNumber('transactionId', transactionId); const self = (this as any) as AssetProxyOwnerContract; - const txHashPromise = self.executeTransaction.sendTransactionAsync(transactionId, txData); + const txHashPromise = self.executeTransaction.sendTransactionAsync(transactionId, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1170,14 +974,6 @@ export class AssetProxyOwnerContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - transactionId: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).executeTransaction.callAsync(transactionId, txData); - const txHash = await (this as any).executeTransaction.sendTransactionAsync(transactionId, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1240,30 +1036,6 @@ export class AssetProxyOwnerContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [BigNumber] { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('executeTransaction(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('executeTransaction(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public functionCallTimeLocks = { /** @@ -1317,46 +1089,6 @@ export class AssetProxyOwnerContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: string, index_1: string): string { - assert.isString('index_0', index_0); - assert.isString('index_1', index_1); - const self = (this as any) as AssetProxyOwnerContract; - const abiEncodedTransactionData = self._strictEncodeArguments('functionCallTimeLocks(bytes4,address)', [ - index_0, - index_1.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, string] { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('functionCallTimeLocks(bytes4,address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [boolean, BigNumber] { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('functionCallTimeLocks(bytes4,address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[boolean, BigNumber]>(returnData); - return abiDecodedReturnData; - }, }; /** * Returns number of confirmations of a transaction. @@ -1410,45 +1142,6 @@ export class AssetProxyOwnerContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param transactionId Transaction ID. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(transactionId: BigNumber): string { - assert.isBigNumber('transactionId', transactionId); - const self = (this as any) as AssetProxyOwnerContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getConfirmationCount(uint256)', [ - transactionId, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): BigNumber { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('getConfirmationCount(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('getConfirmationCount(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Returns array with owner addresses, which confirmed transaction. @@ -1502,43 +1195,6 @@ export class AssetProxyOwnerContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param transactionId Transaction ID. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(transactionId: BigNumber): string { - assert.isBigNumber('transactionId', transactionId); - const self = (this as any) as AssetProxyOwnerContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getConfirmations(uint256)', [transactionId]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): BigNumber { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('getConfirmations(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string[] { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('getConfirmations(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Returns list of owners. @@ -1586,41 +1242,6 @@ export class AssetProxyOwnerContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getOwners()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('getOwners()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string[] { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('getOwners()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Returns total number of transactions after filers are applied. @@ -1677,48 +1298,6 @@ export class AssetProxyOwnerContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param pending Include pending transactions. - * @param executed Include executed transactions. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(pending: boolean, executed: boolean): string { - assert.isBoolean('pending', pending); - assert.isBoolean('executed', executed); - const self = (this as any) as AssetProxyOwnerContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getTransactionCount(bool,bool)', [ - pending, - executed, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): boolean { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('getTransactionCount(bool,bool)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('getTransactionCount(bool,bool)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Returns list of transaction IDs in defined range. @@ -1786,52 +1365,6 @@ export class AssetProxyOwnerContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param from Index start position of transaction array. - * @param to Index end position of transaction array. - * @param pending Include pending transactions. - * @param executed Include executed transactions. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(from: BigNumber, to: BigNumber, pending: boolean, executed: boolean): string { - assert.isBigNumber('from', from); - assert.isBigNumber('to', to); - assert.isBoolean('pending', pending); - assert.isBoolean('executed', executed); - const self = (this as any) as AssetProxyOwnerContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'getTransactionIds(uint256,uint256,bool,bool)', - [from, to, pending, executed], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): BigNumber { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('getTransactionIds(uint256,uint256,bool,bool)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber[] { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('getTransactionIds(uint256,uint256,bool,bool)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Returns the confirmation status of a transaction. @@ -1885,43 +1418,6 @@ export class AssetProxyOwnerContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param transactionId Transaction ID. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(transactionId: BigNumber): string { - assert.isBigNumber('transactionId', transactionId); - const self = (this as any) as AssetProxyOwnerContract; - const abiEncodedTransactionData = self._strictEncodeArguments('isConfirmed(uint256)', [transactionId]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): BigNumber { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('isConfirmed(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('isConfirmed(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public isOwner = { /** @@ -1970,42 +1466,6 @@ export class AssetProxyOwnerContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: string): string { - assert.isString('index_0', index_0); - const self = (this as any) as AssetProxyOwnerContract; - const abiEncodedTransactionData = self._strictEncodeArguments('isOwner(address)', [index_0.toLowerCase()]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('isOwner(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('isOwner(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public owners = { /** @@ -2054,42 +1514,6 @@ export class AssetProxyOwnerContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: BigNumber): string { - assert.isBigNumber('index_0', index_0); - const self = (this as any) as AssetProxyOwnerContract; - const abiEncodedTransactionData = self._strictEncodeArguments('owners(uint256)', [index_0]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): BigNumber { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('owners(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('owners(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Registers a custom timelock to a specific function selector / destination combo @@ -2112,6 +1536,7 @@ export class AssetProxyOwnerContract extends BaseContract { destination: string, newSecondsTimeLocked: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isBoolean('hasCustomTimeLock', hasCustomTimeLock); assert.isString('functionSelector', functionSelector); @@ -2136,6 +1561,16 @@ export class AssetProxyOwnerContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.registerFunctionCall.callAsync( + hasCustomTimeLock, + functionSelector, + destination, + newSecondsTimeLocked, + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -2157,8 +1592,7 @@ export class AssetProxyOwnerContract extends BaseContract { destination: string, newSecondsTimeLocked: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isBoolean('hasCustomTimeLock', hasCustomTimeLock); assert.isString('functionSelector', functionSelector); @@ -2171,6 +1605,7 @@ export class AssetProxyOwnerContract extends BaseContract { destination.toLowerCase(), newSecondsTimeLocked, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -2178,8 +1613,8 @@ export class AssetProxyOwnerContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -2227,29 +1662,6 @@ export class AssetProxyOwnerContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - hasCustomTimeLock: boolean, - functionSelector: string, - destination: string, - newSecondsTimeLocked: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).registerFunctionCall.callAsync( - hasCustomTimeLock, - functionSelector, - destination, - newSecondsTimeLocked, - txData, - ); - const txHash = await (this as any).registerFunctionCall.sendTransactionAsync( - hasCustomTimeLock, - functionSelector, - destination, - newSecondsTimeLocked, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -2340,30 +1752,6 @@ export class AssetProxyOwnerContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [boolean, string, string, BigNumber] { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('registerFunctionCall(bool,bytes4,address,uint128)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[boolean, string, string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('registerFunctionCall(bool,bytes4,address,uint128)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Allows to remove an owner. Transaction has to be sent by wallet. @@ -2376,7 +1764,11 @@ export class AssetProxyOwnerContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(owner: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + owner: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('owner', owner); const self = (this as any) as AssetProxyOwnerContract; const encodedData = self._strictEncodeArguments('removeOwner(address)', [owner.toLowerCase()]); @@ -2392,6 +1784,10 @@ export class AssetProxyOwnerContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.removeOwner.callAsync(owner, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -2406,20 +1802,19 @@ export class AssetProxyOwnerContract extends BaseContract { awaitTransactionSuccessAsync( owner: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('owner', owner); const self = (this as any) as AssetProxyOwnerContract; - const txHashPromise = self.removeOwner.sendTransactionAsync(owner.toLowerCase(), txData); + const txHashPromise = self.removeOwner.sendTransactionAsync(owner.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -2449,11 +1844,6 @@ export class AssetProxyOwnerContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(owner: string, txData?: Partial | undefined): Promise { - await (this as any).removeOwner.callAsync(owner, txData); - const txHash = await (this as any).removeOwner.sendTransactionAsync(owner, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -2512,30 +1902,6 @@ export class AssetProxyOwnerContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('removeOwner(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('removeOwner(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Allows to replace an owner with a new owner. Transaction has to be sent by wallet. @@ -2553,6 +1919,7 @@ export class AssetProxyOwnerContract extends BaseContract { owner: string, newOwner: string, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('owner', owner); assert.isString('newOwner', newOwner); @@ -2573,6 +1940,10 @@ export class AssetProxyOwnerContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.replaceOwner.callAsync(owner, newOwner, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -2589,8 +1960,7 @@ export class AssetProxyOwnerContract extends BaseContract { owner: string, newOwner: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('owner', owner); assert.isString('newOwner', newOwner); @@ -2599,6 +1969,7 @@ export class AssetProxyOwnerContract extends BaseContract { owner.toLowerCase(), newOwner.toLowerCase(), txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -2606,8 +1977,8 @@ export class AssetProxyOwnerContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -2642,15 +2013,6 @@ export class AssetProxyOwnerContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - owner: string, - newOwner: string, - txData?: Partial | undefined, - ): Promise { - await (this as any).replaceOwner.callAsync(owner, newOwner, txData); - const txHash = await (this as any).replaceOwner.sendTransactionAsync(owner, newOwner, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -2722,30 +2084,6 @@ export class AssetProxyOwnerContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, string] { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('replaceOwner(address,address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('replaceOwner(address,address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public required = { /** @@ -2789,41 +2127,6 @@ export class AssetProxyOwnerContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncodedTransactionData = self._strictEncodeArguments('required()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('required()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('required()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Allows an owner to revoke a confirmation for a transaction. @@ -2836,7 +2139,11 @@ export class AssetProxyOwnerContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(transactionId: BigNumber, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + transactionId: BigNumber, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isBigNumber('transactionId', transactionId); const self = (this as any) as AssetProxyOwnerContract; const encodedData = self._strictEncodeArguments('revokeConfirmation(uint256)', [transactionId]); @@ -2852,6 +2159,10 @@ export class AssetProxyOwnerContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.revokeConfirmation.callAsync(transactionId, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -2866,20 +2177,19 @@ export class AssetProxyOwnerContract extends BaseContract { awaitTransactionSuccessAsync( transactionId: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isBigNumber('transactionId', transactionId); const self = (this as any) as AssetProxyOwnerContract; - const txHashPromise = self.revokeConfirmation.sendTransactionAsync(transactionId, txData); + const txHashPromise = self.revokeConfirmation.sendTransactionAsync(transactionId, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -2909,14 +2219,6 @@ export class AssetProxyOwnerContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - transactionId: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).revokeConfirmation.callAsync(transactionId, txData); - const txHash = await (this as any).revokeConfirmation.sendTransactionAsync(transactionId, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -2979,30 +2281,6 @@ export class AssetProxyOwnerContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [BigNumber] { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('revokeConfirmation(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('revokeConfirmation(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public secondsTimeLocked = { /** @@ -3046,41 +2324,6 @@ export class AssetProxyOwnerContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncodedTransactionData = self._strictEncodeArguments('secondsTimeLocked()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('secondsTimeLocked()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('secondsTimeLocked()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Allows an owner to submit and confirm a transaction. @@ -3100,6 +2343,7 @@ export class AssetProxyOwnerContract extends BaseContract { value: BigNumber, data: string, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('destination', destination); assert.isBigNumber('value', value); @@ -3122,6 +2366,10 @@ export class AssetProxyOwnerContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.submitTransaction.callAsync(destination, value, data, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -3140,8 +2388,7 @@ export class AssetProxyOwnerContract extends BaseContract { value: BigNumber, data: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('destination', destination); assert.isBigNumber('value', value); @@ -3152,6 +2399,7 @@ export class AssetProxyOwnerContract extends BaseContract { value, data, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -3159,8 +2407,8 @@ export class AssetProxyOwnerContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -3203,16 +2451,6 @@ export class AssetProxyOwnerContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - destination: string, - value: BigNumber, - data: string, - txData?: Partial | undefined, - ): Promise { - await (this as any).submitTransaction.callAsync(destination, value, data, txData); - const txHash = await (this as any).submitTransaction.sendTransactionAsync(destination, value, data, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -3292,30 +2530,6 @@ export class AssetProxyOwnerContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('submitTransaction(address,uint256,bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('submitTransaction(address,uint256,bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public transactionCount = { /** @@ -3359,41 +2573,6 @@ export class AssetProxyOwnerContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncodedTransactionData = self._strictEncodeArguments('transactionCount()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('transactionCount()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('transactionCount()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public transactions = { /** @@ -3442,44 +2621,6 @@ export class AssetProxyOwnerContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: BigNumber): string { - assert.isBigNumber('index_0', index_0); - const self = (this as any) as AssetProxyOwnerContract; - const abiEncodedTransactionData = self._strictEncodeArguments('transactions(uint256)', [index_0]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [BigNumber] { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('transactions(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [string, BigNumber, string, boolean] { - const self = (this as any) as AssetProxyOwnerContract; - const abiEncoder = self._lookupAbiEncoder('transactions(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[string, BigNumber, string, boolean]>( - returnData, - ); - return abiDecodedReturnData; - }, }; private readonly _subscriptionManager: SubscriptionManager; public static async deployFrom0xArtifactAsync( diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/coordinator.ts b/packages/abi-gen-wrappers/src/generated-wrappers/coordinator.ts index 482663decc..56348dfb51 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/coordinator.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/coordinator.ts @@ -18,7 +18,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -28,6 +34,9 @@ import * as ethers from 'ethers'; // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class CoordinatorContract extends BaseContract { + /** + * @ignore + */ public static deployedBytecode: string | undefined; /** * Recovers the address of a signer given a hash and signature. @@ -62,7 +71,7 @@ export class CoordinatorContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -75,48 +84,6 @@ export class CoordinatorContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param hash Any 32 byte hash. - * @param signature Proof that the hash has been signed by signer. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(hash: string, signature: string): string { - assert.isString('hash', hash); - assert.isString('signature', signature); - const self = (this as any) as CoordinatorContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getSignerAddress(bytes32,bytes)', [ - hash, - signature, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as CoordinatorContract; - const abiEncoder = self._lookupAbiEncoder('getSignerAddress(bytes32,bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as CoordinatorContract; - const abiEncoder = self._lookupAbiEncoder('getSignerAddress(bytes32,bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Calculates the EIP712 hash of a 0x transaction using the domain separator of the Exchange contract. @@ -171,49 +138,6 @@ export class CoordinatorContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param transaction 0x transaction containing salt, signerAddress, and data. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(transaction: { salt: BigNumber; signerAddress: string; data: string }): string { - const self = (this as any) as CoordinatorContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'getTransactionHash((uint256,address,bytes))', - [transaction], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): { salt: BigNumber; signerAddress: string; data: string } { - const self = (this as any) as CoordinatorContract; - const abiEncoder = self._lookupAbiEncoder('getTransactionHash((uint256,address,bytes))'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<{ - salt: BigNumber; - signerAddress: string; - data: string; - }>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as CoordinatorContract; - const abiEncoder = self._lookupAbiEncoder('getTransactionHash((uint256,address,bytes))'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Calculated the EIP712 hash of the Coordinator approval mesasage using the domain separator of this contract. @@ -275,63 +199,6 @@ export class CoordinatorContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param approval Coordinator approval message containing the transaction - * hash, transaction signature, and expiration of the approval. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(approval: { - txOrigin: string; - transactionHash: string; - transactionSignature: string; - approvalExpirationTimeSeconds: BigNumber; - }): string { - const self = (this as any) as CoordinatorContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'getCoordinatorApprovalHash((address,bytes32,bytes,uint256))', - [approval], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): { - txOrigin: string; - transactionHash: string; - transactionSignature: string; - approvalExpirationTimeSeconds: BigNumber; - } { - const self = (this as any) as CoordinatorContract; - const abiEncoder = self._lookupAbiEncoder('getCoordinatorApprovalHash((address,bytes32,bytes,uint256))'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<{ - txOrigin: string; - transactionHash: string; - transactionSignature: string; - approvalExpirationTimeSeconds: BigNumber; - }>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as CoordinatorContract; - const abiEncoder = self._lookupAbiEncoder('getCoordinatorApprovalHash((address,bytes32,bytes,uint256))'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Executes a 0x transaction that has been signed by the feeRecipients that correspond to each order in the transaction's Exchange calldata. @@ -359,6 +226,7 @@ export class CoordinatorContract extends BaseContract { approvalExpirationTimeSeconds: BigNumber[], approvalSignatures: string[], txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('txOrigin', txOrigin); assert.isString('transactionSignature', transactionSignature); @@ -387,6 +255,17 @@ export class CoordinatorContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.executeTransaction.callAsync( + transaction, + txOrigin, + transactionSignature, + approvalExpirationTimeSeconds, + approvalSignatures, + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -413,8 +292,7 @@ export class CoordinatorContract extends BaseContract { approvalExpirationTimeSeconds: BigNumber[], approvalSignatures: string[], txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('txOrigin', txOrigin); assert.isString('transactionSignature', transactionSignature); @@ -428,6 +306,7 @@ export class CoordinatorContract extends BaseContract { approvalExpirationTimeSeconds, approvalSignatures, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -435,8 +314,8 @@ export class CoordinatorContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -493,32 +372,6 @@ export class CoordinatorContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - transaction: { salt: BigNumber; signerAddress: string; data: string }, - txOrigin: string, - transactionSignature: string, - approvalExpirationTimeSeconds: BigNumber[], - approvalSignatures: string[], - txData?: Partial | undefined, - ): Promise { - await (this as any).executeTransaction.callAsync( - transaction, - txOrigin, - transactionSignature, - approvalExpirationTimeSeconds, - approvalSignatures, - txData, - ); - const txHash = await (this as any).executeTransaction.sendTransactionAsync( - transaction, - txOrigin, - transactionSignature, - approvalExpirationTimeSeconds, - approvalSignatures, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -631,38 +484,6 @@ export class CoordinatorContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): [{ salt: BigNumber; signerAddress: string; data: string }, string, string, BigNumber[], string[]] { - const self = (this as any) as CoordinatorContract; - const abiEncoder = self._lookupAbiEncoder( - 'executeTransaction((uint256,address,bytes),address,bytes,uint256[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - [{ salt: BigNumber; signerAddress: string; data: string }, string, string, BigNumber[], string[]] - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as CoordinatorContract; - const abiEncoder = self._lookupAbiEncoder( - 'executeTransaction((uint256,address,bytes),address,bytes,uint256[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public EIP712_EXCHANGE_DOMAIN_HASH = { /** @@ -706,41 +527,6 @@ export class CoordinatorContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as CoordinatorContract; - const abiEncodedTransactionData = self._strictEncodeArguments('EIP712_EXCHANGE_DOMAIN_HASH()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as CoordinatorContract; - const abiEncoder = self._lookupAbiEncoder('EIP712_EXCHANGE_DOMAIN_HASH()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as CoordinatorContract; - const abiEncoder = self._lookupAbiEncoder('EIP712_EXCHANGE_DOMAIN_HASH()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Validates that the 0x transaction has been approved by all of the feeRecipients @@ -820,77 +606,6 @@ export class CoordinatorContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param transaction 0x transaction containing salt, signerAddress, and data. - * @param txOrigin Required signer of Ethereum transaction calling this - * function. - * @param transactionSignature Proof that the transaction has been signed by - * the signer. - * @param approvalExpirationTimeSeconds Array of expiration times in seconds - * for which each corresponding approval signature expires. - * @param approvalSignatures Array of signatures that correspond to the - * feeRecipients of each order in the transaction's Exchange calldata. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData( - transaction: { salt: BigNumber; signerAddress: string; data: string }, - txOrigin: string, - transactionSignature: string, - approvalExpirationTimeSeconds: BigNumber[], - approvalSignatures: string[], - ): string { - assert.isString('txOrigin', txOrigin); - assert.isString('transactionSignature', transactionSignature); - assert.isArray('approvalExpirationTimeSeconds', approvalExpirationTimeSeconds); - assert.isArray('approvalSignatures', approvalSignatures); - const self = (this as any) as CoordinatorContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'assertValidCoordinatorApprovals((uint256,address,bytes),address,bytes,uint256[],bytes[])', - [ - transaction, - txOrigin.toLowerCase(), - transactionSignature, - approvalExpirationTimeSeconds, - approvalSignatures, - ], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): [{ salt: BigNumber; signerAddress: string; data: string }, string, string, BigNumber[], string[]] { - const self = (this as any) as CoordinatorContract; - const abiEncoder = self._lookupAbiEncoder( - 'assertValidCoordinatorApprovals((uint256,address,bytes),address,bytes,uint256[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - [{ salt: BigNumber; signerAddress: string; data: string }, string, string, BigNumber[], string[]] - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as CoordinatorContract; - const abiEncoder = self._lookupAbiEncoder( - 'assertValidCoordinatorApprovals((uint256,address,bytes),address,bytes,uint256[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Decodes the orders from Exchange calldata representing any fill method. @@ -938,7 +653,7 @@ export class CoordinatorContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -966,73 +681,6 @@ export class CoordinatorContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param data Exchange calldata representing a fill method. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(data: string): string { - assert.isString('data', data); - const self = (this as any) as CoordinatorContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeOrdersFromFillData(bytes)', [data]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as CoordinatorContract; - const abiEncoder = self._lookupAbiEncoder('decodeOrdersFromFillData(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }> { - const self = (this as any) as CoordinatorContract; - const abiEncoder = self._lookupAbiEncoder('decodeOrdersFromFillData(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue< - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }> - >(returnData); - return abiDecodedReturnData; - }, }; public EIP712_COORDINATOR_DOMAIN_HASH = { /** @@ -1076,41 +724,6 @@ export class CoordinatorContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as CoordinatorContract; - const abiEncodedTransactionData = self._strictEncodeArguments('EIP712_COORDINATOR_DOMAIN_HASH()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as CoordinatorContract; - const abiEncoder = self._lookupAbiEncoder('EIP712_COORDINATOR_DOMAIN_HASH()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as CoordinatorContract; - const abiEncoder = self._lookupAbiEncoder('EIP712_COORDINATOR_DOMAIN_HASH()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public static async deployFrom0xArtifactAsync( artifact: ContractArtifact | SimpleContractArtifact, diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/coordinator_registry.ts b/packages/abi-gen-wrappers/src/generated-wrappers/coordinator_registry.ts index 827b221b04..f76b2ed8a3 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/coordinator_registry.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/coordinator_registry.ts @@ -19,7 +19,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -40,6 +46,9 @@ export interface CoordinatorRegistryCoordinatorEndpointSetEventArgs extends Deco // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class CoordinatorRegistryContract extends BaseContract { + /** + * @ignore + */ public static deployedBytecode: string | undefined; /** * Called by a Coordinator operator to set the endpoint of their Coordinator. @@ -52,7 +61,11 @@ export class CoordinatorRegistryContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(coordinatorEndpoint: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + coordinatorEndpoint: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('coordinatorEndpoint', coordinatorEndpoint); const self = (this as any) as CoordinatorRegistryContract; const encodedData = self._strictEncodeArguments('setCoordinatorEndpoint(string)', [coordinatorEndpoint]); @@ -68,6 +81,10 @@ export class CoordinatorRegistryContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.setCoordinatorEndpoint.callAsync(coordinatorEndpoint, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -82,20 +99,19 @@ export class CoordinatorRegistryContract extends BaseContract { awaitTransactionSuccessAsync( coordinatorEndpoint: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('coordinatorEndpoint', coordinatorEndpoint); const self = (this as any) as CoordinatorRegistryContract; - const txHashPromise = self.setCoordinatorEndpoint.sendTransactionAsync(coordinatorEndpoint, txData); + const txHashPromise = self.setCoordinatorEndpoint.sendTransactionAsync(coordinatorEndpoint, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -125,14 +141,6 @@ export class CoordinatorRegistryContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - coordinatorEndpoint: string, - txData?: Partial | undefined, - ): Promise { - await (this as any).setCoordinatorEndpoint.callAsync(coordinatorEndpoint, txData); - const txHash = await (this as any).setCoordinatorEndpoint.sendTransactionAsync(coordinatorEndpoint, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -195,30 +203,6 @@ export class CoordinatorRegistryContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as CoordinatorRegistryContract; - const abiEncoder = self._lookupAbiEncoder('setCoordinatorEndpoint(string)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as CoordinatorRegistryContract; - const abiEncoder = self._lookupAbiEncoder('setCoordinatorEndpoint(string)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Gets the endpoint for a Coordinator. @@ -273,45 +257,6 @@ export class CoordinatorRegistryContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param coordinatorOperator operator of the Coordinator endpoint. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(coordinatorOperator: string): string { - assert.isString('coordinatorOperator', coordinatorOperator); - const self = (this as any) as CoordinatorRegistryContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getCoordinatorEndpoint(address)', [ - coordinatorOperator.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as CoordinatorRegistryContract; - const abiEncoder = self._lookupAbiEncoder('getCoordinatorEndpoint(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as CoordinatorRegistryContract; - const abiEncoder = self._lookupAbiEncoder('getCoordinatorEndpoint(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; private readonly _subscriptionManager: SubscriptionManager; public static async deployFrom0xArtifactAsync( diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/dev_utils.ts b/packages/abi-gen-wrappers/src/generated-wrappers/dev_utils.ts index ea3cf1904a..0f25b73cce 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/dev_utils.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/dev_utils.ts @@ -18,7 +18,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -28,6 +34,9 @@ import * as ethers from 'ethers'; // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class DevUtilsContract extends BaseContract { + /** + * @ignore + */ public static deployedBytecode = '0x608060405234801561001057600080fd5b506004361061025c5760003560e01c80639a7e752611610145578063cafd3a07116100bd578063d3d862d11161008c578063e4e6e7da11610071578063e4e6e7da1461063a578063e77286eb1461065b578063ee4f5a941461067d5761025c565b8063d3d862d114610605578063e25cabf7146106185761025c565b8063cafd3a071461059e578063d001c5dc146105bf578063d186037f146105d2578063d3637905146105e55761025c565b8063a6627e9f11610114578063b43cffe1116100f9578063b43cffe114610548578063bbb2dcf61461055b578063bc03f9641461057d5761025c565b8063a6627e9f14610512578063acaedc74146105255761025c565b80639a7e7526146104985780639eadc835146104bb578063a0901e51146104df578063a5cd62ba146104f25761025c565b8063459be5e2116101d85780636f83188e116101a75780637b66ad341161018c5780637b66ad34146104515780637d727512146104725780638f4ce479146104855761025c565b80636f83188e1461040d5780637914b2ec146104305761025c565b8063459be5e21461038a5780634dfdac20146103ab578063590aa875146103cb57806365129042146103eb5761025c565b80632322cf761161022f578063327d305411610214578063327d30541461033257806332aae3ad146103455780633db6dc61146103675761025c565b80632322cf76146102f0578063314853ff146103105761025c565b806302d0aec31461026157806304a5618a1461028b5780630d7b7d76146102ad578063165979e1146102ce575b600080fd5b61027461026f3660046149dd565b61069f565b6040516102829291906152e4565b60405180910390f35b61029e6102993660046149dd565b6106fb565b60405161028293929190615387565b6102c06102bb366004614565565b6107a9565b604051610282929190615292565b6102e16102dc3660046149dd565b6107cb565b604051610282939291906154c2565b6103036102fe366004614565565b610828565b6040516102829190615731565b61032361031e3660046149dd565b610850565b604051610282939291906152b9565b6102c06103403660046149dd565b610897565b6103586103533660046149dd565b6108d9565b60405161028293929190615438565b61037a6103753660046149dd565b61092c565b6040516102829493929190615258565b61039d6103983660046149dd565b610976565b6040516102829291906154ab565b6103be6103b936600461448c565b6109cc565b60405161028291906151f2565b6103de6103d936600461435d565b610a4f565b60405161028291906153e7565b6103fe6103f93660046149dd565b610ad3565b60405161028293929190614fdf565b61042061041b3660046149dd565b610b0d565b6040516102829493929190615535565b61044361043e3660046149dd565b61164e565b604051610282929190615301565b61046461045f3660046149dd565b611686565b604051610282929190614fc5565b610303610480366004614565565b6116be565b6104436104933660046149dd565b611dd3565b6104ab6104a63660046149dd565b611e63565b60405161028294939291906154f1565b6104ce6104c93660046149dd565b611ec4565b604051610282959493929190615324565b6103be6104ed3660046145d4565b611f6f565b61050561050036600461463a565b611fe8565b60405161028291906150f9565b6103de6105203660046145a9565b6120ac565b6105386105333660046149dd565b612133565b6040516102829493929190615055565b6103de6105563660046144da565b61216f565b61056e6105693660046149dd565b6121fc565b604051610282939291906153b2565b61059061058b3660046149dd565b6122a9565b6040516102829291906152a0565b6105b16105ac3660046149dd565b6122e2565b604051610282929190615528565b6103be6105cd36600461448c565b612330565b6103036105e0366004614565565b61239e565b6105f86105f3366004614a94565b6129e1565b60405161028291906154dd565b6103de6106133660046147e2565b612f7e565b61062b6106263660046146be565b612fb6565b60405161028293929190615146565b61064d61064836600461448c565b6130ee565b604051610282929190615233565b61066e610669366004614aec565b613107565b604051610282939291906156d5565b61069061068b3660046149dd565b613341565b60405161028293929190615481565b6000806106b3836106ae61337e565b6133a2565b60006106cc60048551866133fc9092919063ffffffff16565b8060200190516106df9190810190614990565b909350905060ff811660068111156106f357fe5b915050915091565b6000808061070f848263ffffffff61343f16565b92506001600160e01b031983167f02571792000000000000000000000000000000000000000000000000000000001461077d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107749061569e565b60405180910390fd5b61078e84601063ffffffff61347316565b91506107a184602463ffffffff6134a616565b929491935050565b6000806107b684846116be565b91506107c2848461239e565b90509250929050565b60008060006107dc846106ae6134b2565b60006107f560048651876133fc9092919063ffffffff16565b8060200190516108089190810190614d20565b9094509250905060ff8116600281111561081e57fe5b9350509193909250565b600080600061083785856107a9565b9150915061084582826134d6565b925050505b92915050565b6000606080610861846106ae6134ec565b835161087790859060049063ffffffff6133fc16565b80602001905161088a9190810190614930565b9196909550909350915050565b6000806108a6836106ae613510565b82516108bc90849060049063ffffffff6133fc16565b8060200190516108cf91908101906148d2565b9094909350915050565b60008060606108ea846106ae613534565b600061090360048651876133fc9092919063ffffffff16565b8060200190516109169190810190614cd4565b9094509250905060ff8116600181111561081e57fe5b60008060608061093e856106ae613558565b845161095490869060049063ffffffff6133fc16565b806020019051610967919081019061488e565b92989197509550909350915050565b600080610985836106ae61357c565b600061099e60048551866133fc9092919063ffffffff16565b8060200190516109b19190810190614c07565b9250905060ff811660038111156109c457fe5b925050915091565b6060600082519050806040519080825280602002602001820160405280156109fe578160200160208202803883390190505b50915060005b818114610a4757610a2885858381518110610a1b57fe5b602002602001015161239e565b838281518110610a3457fe5b6020908102919091010152600101610a04565b505092915050565b6040516060907ff47261b00000000000000000000000000000000000000000000000000000000090610a85908490602401614fb1565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b0319909316929092179091529050919050565b6000806000610ae4846106ae6135a0565b8351610afa90859060049063ffffffff6133fc16565b80602001905161088a91908101906143b2565b60608080806000610b24868263ffffffff61343f16565b90506001600160e01b031981167fdedfc1f1000000000000000000000000000000000000000000000000000000001415610b95576040518060400160405280601181526020017f626174636843616e63656c4f72646572730000000000000000000000000000008152509450611124565b6001600160e01b031981167f9694a402000000000000000000000000000000000000000000000000000000001415610c04576040518060400160405280600f81526020017f626174636846696c6c4f726465727300000000000000000000000000000000008152509450611124565b6001600160e01b031981167f8ea8dfe4000000000000000000000000000000000000000000000000000000001415610c73576040518060400160405280601681526020017f626174636846696c6c4f72646572734e6f5468726f77000000000000000000008152509450611124565b6001600160e01b031981167fbeee2e14000000000000000000000000000000000000000000000000000000001415610ce2576040518060400160405280601581526020017f626174636846696c6c4f724b696c6c4f726465727300000000000000000000008152509450611124565b6001600160e01b031981167f2da62987000000000000000000000000000000000000000000000000000000001415610d51576040518060400160405280600b81526020017f63616e63656c4f726465720000000000000000000000000000000000000000008152509450611124565b6001600160e01b031981167f9b44d556000000000000000000000000000000000000000000000000000000001415610dc0576040518060400160405280600981526020017f66696c6c4f7264657200000000000000000000000000000000000000000000008152509450611124565b6001600160e01b031981167fe14b58c4000000000000000000000000000000000000000000000000000000001415610e2f576040518060400160405280600f81526020017f66696c6c4f724b696c6c4f7264657200000000000000000000000000000000008152509450611124565b6001600160e01b031981167f78d29ac1000000000000000000000000000000000000000000000000000000001415610e9e576040518060400160405280601681526020017f6d61726b65744275794f72646572734e6f5468726f77000000000000000000008152509450611124565b6001600160e01b031981167f369da099000000000000000000000000000000000000000000000000000000001415610f0d576040518060400160405280601781526020017f6d61726b657453656c6c4f72646572734e6f5468726f770000000000000000008152509450611124565b6001600160e01b031981167f8bc8efb3000000000000000000000000000000000000000000000000000000001415610f7c576040518060400160405280601981526020017f6d61726b65744275794f726465727346696c6c4f724b696c6c000000000000008152509450611124565b6001600160e01b031981167fa6c3bf33000000000000000000000000000000000000000000000000000000001415610feb576040518060400160405280601a81526020017f6d61726b657453656c6c4f726465727346696c6c4f724b696c6c0000000000008152509450611124565b6001600160e01b031981167f88ec79fb00000000000000000000000000000000000000000000000000000000141561105a576040518060400160405280600b81526020017f6d617463684f72646572730000000000000000000000000000000000000000008152509450611124565b6001600160e01b031981167f4f9559b10000000000000000000000000000000000000000000000000000000014806110bb57506001600160e01b031981167f2280c91000000000000000000000000000000000000000000000000000000000145b156110f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077490615630565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610774906155f9565b6001600160e01b031981167fdedfc1f10000000000000000000000000000000000000000000000000000000014156111c957855161116c90879060049063ffffffff6135c416565b80602001905161117f9190810190614607565b604080516000808252602082019092529195505b50604080516000808252602082019092529194506111c1565b60608152602001906001900390816111ac5790505b509150611646565b6001600160e01b031981167fbeee2e1400000000000000000000000000000000000000000000000000000000148061122a57506001600160e01b031981167f9694a40200000000000000000000000000000000000000000000000000000000145b8061125e57506001600160e01b031981167f8ea8dfe400000000000000000000000000000000000000000000000000000000145b156112785761126c86613644565b91955093509150611646565b6001600160e01b031981167f2da629870000000000000000000000000000000000000000000000000000000014156113605760408051600180825281830190925290816020015b6112c7613c90565b8152602001906001900390816112bf57505086519094506112f290879060049063ffffffff6135c416565b8060200190516113059190810190614a61565b8460008151811061131257fe5b602002602001018190525060006040519080825280602002602001820160405280156111935781602001602082028038833901905050604080516000808252602082019092529194506111c1565b6001600160e01b031981167fe14b58c40000000000000000000000000000000000000000000000000000000014806113c157506001600160e01b031981167f9b44d55600000000000000000000000000000000000000000000000000000000145b156113cf5761126c86613673565b6001600160e01b031981167f78d29ac100000000000000000000000000000000000000000000000000000000148061143057506001600160e01b031981167f369da09900000000000000000000000000000000000000000000000000000000145b8061146457506001600160e01b031981167f8bc8efb300000000000000000000000000000000000000000000000000000000145b8061149857506001600160e01b031981167fa6c3bf3300000000000000000000000000000000000000000000000000000000145b156114a65761126c8661376d565b6001600160e01b031981167f88ec79fb000000000000000000000000000000000000000000000000000000001415611646576114e0613c90565b6114e8613c90565b60608061150260048b518c6135c49092919063ffffffff16565b8060200190516115159190810190614b43565b604080516002808252606082019092529498509296509094509250816020015b61153d613c90565b815260200190600190039081611535579050509750838860008151811061156057fe5b6020026020010181905250828860018151811061157957fe5b602090810291909101015260408051600280825260608201909252908160200160208202803883390190505096508360a00151876000815181106115b957fe5b6020026020010181815250508260a00151876001815181106115d757fe5b60209081029190910101526040805160028082526060820190925290816020015b60608152602001906001900390816115f8579050509550818660008151811061161d57fe5b6020026020010181905250808660018151811061163657fe5b6020026020010181905250505050505b509193509193565b60008061165d836106ae6137e1565b825161167390849060049063ffffffff6133fc16565b8060200190516108cf91908101906149b4565b600080611695836106ae613805565b82516116ab90849060049063ffffffff6133fc16565b8060200190516108cf9190810190614379565b6000806116d1838263ffffffff61343f16565b90506001600160e01b031981167ff47261b000000000000000000000000000000000000000000000000000000000141561184657600061171884601063ffffffff61347316565b6040519091506060907f70a082310000000000000000000000000000000000000000000000000000000090611751908890602401614fb1565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006060836001600160a01b0316836040516117cc9190614f95565b600060405180830381855afa9150503d8060008114611807576040519150601f19603f3d011682016040523d82523d6000602084013e61180c565b606091505b509150915081801561181f575080516020145b61182a57600061183b565b61183b81600063ffffffff6134a616565b955050505050611dcc565b6001600160e01b031981167f025717920000000000000000000000000000000000000000000000000000000014156119e157600080611884856106fb565b6040519194509250606091507f6352211e00000000000000000000000000000000000000000000000000000000906118c0908490602401615731565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006060846001600160a01b03168360405161193b9190614f95565b600060405180830381855afa9150503d8060008114611976576040519150601f19603f3d011682016040523d82523d6000602084013e61197b565b606091505b50915091506000828015611990575081516020145b61199b5760006119ac565b6119ac82600c63ffffffff61347316565b9050896001600160a01b0316816001600160a01b0316146119ce5760006119d1565b60015b60ff169750505050505050611dcc565b6001600160e01b031981167fa7cb5fb7000000000000000000000000000000000000000000000000000000001415611bc4576000606080611a2186611ec4565b5081519296509094509250905060005b818114611bba5783516060907efdd58e00000000000000000000000000000000000000000000000000000000908b90879085908110611a6c57fe5b6020026020010151604051602401611a85929190615089565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006060876001600160a01b031683604051611b009190614f95565b600060405180830381855afa9150503d8060008114611b3b576040519150601f19603f3d011682016040523d82523d6000602084013e611b40565b606091505b50915091506000828015611b55575081516020145b611b60576000611b71565b611b7182600063ffffffff6134a616565b90506000878681518110611b8157fe5b60200260200101518281611b9157fe5b0490508b811080611ba057508b155b15611ba957809b505b505060019093019250611a31915050565b5050505050611dcc565b6001600160e01b031981167fc339d10a000000000000000000000000000000000000000000000000000000001415611d15576040516060907fa85e59e40000000000000000000000000000000000000000000000000000000090611c33908690600090819081906024016153fa565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199094169390931790925260045491519092506000916001600160a01b031690611c9a908490614f95565b600060405180830381855afa9150503d8060008114611cd5576040519150601f19603f3d011682016040523d82523d6000602084013e611cda565b606091505b5050905080611cea576000611d0c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b93505050611dcc565b6001600160e01b031981167f94cfcdd7000000000000000000000000000000000000000000000000000000001415611dcc57606080611d53856121fc565b80519194509250905060005b818114611dc7576000611d8589858481518110611d7857fe5b60200260200101516116be565b90506000858381518110611d9557fe5b60200260200101518281611da557fe5b04905087811080611db4575087155b15611dbd578097505b5050600101611d5f565b505050505b5092915050565b600080611de6838263ffffffff61343f16565b91506001600160e01b031982167ff47261b00000000000000000000000000000000000000000000000000000000014611e4b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107749061569e565b611e5c83601063ffffffff61347316565b9050915091565b60008060006060611e76856106ae613829565b6000611e8f60048751886133fc9092919063ffffffff16565b806020019051611ea29190810190614c76565b91965094509250905060ff81166006811115611eba57fe5b9450509193509193565b60008060608080611edb868563ffffffff61343f16565b94506001600160e01b031985167fa7cb5fb70000000000000000000000000000000000000000000000000000000014611f40576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107749061569e565b505050506024828101516044840151606485015160848601519496929591820184019490820184019391010190565b6060808251604051908082528060200260200182016040528015611f9d578160200160208202803883390190505b50905060005b83518114611dcc57838181518110611fb757fe5b60200260200101516001600160a01b031631828281518110611fd557fe5b6020908102919091010152600101611fa3565b60606000845190508060405190808252806020026020018201604052801561201a578160200160208202803883390190505b50915060005b8181146120a25761206b86828151811061203657fe5b602002602001015186838151811061204a57fe5b602002602001015186848151811061205e57fe5b60200260200101516129e1565b83828151811061207757fe5b6020026020010190600481111561208a57fe5b9081600481111561209757fe5b905250600101612020565b50505b9392505050565b6040516060907f0257179200000000000000000000000000000000000000000000000000000000906120e49085908590602401615089565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152905092915050565b60006060806060612146856106ae61384d565b845161215c90869060049063ffffffff6133fc16565b80602001905161096791908101906143f4565b6040516060907fa7cb5fb700000000000000000000000000000000000000000000000000000000906121ab908790879087908790602401615003565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b0319909316929092179091529050949350505050565b6000606080612211848463ffffffff61343f16565b92506001600160e01b031983167f94cfcdd70000000000000000000000000000000000000000000000000000000014612276576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107749061569e565b835161228c90859060049063ffffffff6135c416565b80602001905161229f9190810190614817565b9395909450915050565b600060606122b9836106ae613871565b82516122cf90849060049063ffffffff6133fc16565b8060200190516108cf91908101906148f5565b6000806122f1836106ae613895565b600061230a60048551866133fc9092919063ffffffff16565b80602001905161231d9190810190614c07565b9250905060ff811660018111156109c457fe5b606060008251905080604051908082528060200260200182016040528015612362578160200160208202803883390190505b50915060005b818114610a475761237f85858381518110611d7857fe5b83828151811061238b57fe5b6020908102919091010152600101612368565b6000806123b1838263ffffffff61343f16565b90506001600160e01b031981167f94cfcdd7000000000000000000000000000000000000000000000000000000001415612463576060806123f1856121fc565b80519194509250905060005b81811461245857600061241689858481518110610a1b57fe5b9050600085838151811061242657fe5b6020026020010151828161243657fe5b04905087811080612445575087155b1561244e578097505b50506001016123fd565b5061084a9350505050565b6001600160e01b031981167ff47261b00000000000000000000000000000000000000000000000000000000014156124ee5760006124a884601063ffffffff61347316565b6001546040519192506060917fdd62ed3e00000000000000000000000000000000000000000000000000000000916117519189916001600160a01b031690602401614fc5565b6001600160e01b031981167f025717920000000000000000000000000000000000000000000000000000000014156127de5760008061252c856106fb565b600254604051929550909350606092507fe985e9c50000000000000000000000000000000000000000000000000000000091612578918a916001600160a01b0390911690602401614fc5565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006060846001600160a01b0316836040516125f39190614f95565b600060405180830381855afa9150503d806000811461262e576040519150601f19603f3d011682016040523d82523d6000602084013e612633565b606091505b509150915081158061264757508051602014155b80612663575061265e81600063ffffffff6134a616565b600114155b156127b1576040516060907f081812fc000000000000000000000000000000000000000000000000000000009061269e908790602401615731565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050856001600160a01b0316816040516127159190614f95565b600060405180830381855afa9150503d8060008114612750576040519150601f19603f3d011682016040523d82523d6000602084013e612755565b606091505b509093509150828015612769575081516020145b801561279857506002546001600160a01b031661278d83600c63ffffffff61347316565b6001600160a01b0316145b6127a35760006127a6565b60015b60ff16975050611bba565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff96505050505050611dcc565b6001600160e01b031981167fa7cb5fb700000000000000000000000000000000000000000000000000000000141561298657600061281b84611ec4565b5050600354604051929450606093507fe985e9c50000000000000000000000000000000000000000000000000000000092612865925089916001600160a01b031690602401614fc5565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006060836001600160a01b0316836040516128e09190614f95565b600060405180830381855afa9150503d806000811461291b576040519150601f19603f3d011682016040523d82523d6000602084013e612920565b606091505b5091509150818015612933575080516020145b801561294f575061294b81600063ffffffff6134a616565b6001145b61295a57600061183b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff955050505050611dcc565b6001600160e01b031981167fc339d10a000000000000000000000000000000000000000000000000000000001415611dcc57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9392505050565b60006129eb613d23565b612a7c8584600560009054906101000a90046001600160a01b03166001600160a01b0316631ce4c78b6040518163ffffffff1660e01b815260040160206040518083038186803b158015612a3e57600080fd5b505afa158015612a52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612a769190810190614bef565b3a6138b9565b60408051600480825260a0820190925291925060609190816020015b6060815260200190600190039081612a9857505060408051600480825260a082019092529192506060919060208201608080388339505060408051600480825260a08201909252929350606092915060208201608080388339505060408051600480825260a0820190925292935060609291506020820160808038833901905050905088610160015184600081518110612b2e57fe5b60200260200101819052508783600081518110612b4757fe5b60200260200101906001600160a01b031690816001600160a01b031681525050886000015182600081518110612b7957fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508681600081518110612ba757fe5b60200260200101818152505088610140015184600181518110612bc657fe5b6020026020010181905250886000015183600181518110612be357fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508782600181518110612c1157fe5b60200260200101906001600160a01b031690816001600160a01b031681525050846000015181600181518110612c4357fe5b602002602001018181525050886101a0015184600281518110612c6257fe5b60200260200101819052508783600281518110612c7b57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050886040015182600281518110612cad57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050846060015181600281518110612cdf57fe5b60200260200101818152505088610180015184600381518110612cfe57fe5b6020026020010181905250886000015183600381518110612d1b57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050886040015182600381518110612d4d57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050846040015181600381518110612d7f57fe5b60209081029190910101526040516060907fb04fbddd0000000000000000000000000000000000000000000000000000000090612dc69087908790879087906024016150a2565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199094169390931790925260055491519092506060916001600160a01b031690612e2d908490614f95565b6000604051808303816000865af19150503d8060008114612e6a576040519150601f19603f3d011682016040523d82523d6000602084013e612e6f565b606091505b50915060009050612e86828263ffffffff61343f16565b9050612e90613534565b6001600160e01b031982811691161415612ed2576000612eaf836108d9565b5091505060ff81166004811115612ec257fe5b99505050505050505050506120a5565b612eda6134ec565b6001600160e01b031982811691161415612f0d576000612ef983610850565b509091505060ff81166004811115612ec257fe5b815160208301207ff43f26ea5a94b478394a975e856464913dc1a8a1ca70939d974aa7c238aa0ce01415612f4c576004985050505050505050506120a5565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610774906155c2565b6040516060907f94cfcdd700000000000000000000000000000000000000000000000000000000906120e49085908590602401615205565b606080606060008551905080604051908082528060200260200182016040528015612ffb57816020015b612fe8613d52565b815260200190600190039081612fe05790505b50935080604051908082528060200260200182016040528015613028578160200160208202803883390190505b50925080604051908082528060200260200182016040528015613055578160200160208202803883390190505b50915060005b8181146130e55761309287828151811061307157fe5b602002602001015187838151811061308557fe5b6020026020010151613107565b87518890859081106130a057fe5b602002602001018785815181106130b357fe5b602002602001018786815181106130c657fe5b931515602094850291909101909301929092529190525260010161305b565b50509250925092565b6060806130fb8484612330565b91506107c284846109cc565b61310f613d52565b600080546040517f9d3fa4b900000000000000000000000000000000000000000000000000000000815282916001600160a01b031690639d3fa4b9906131599088906004016156f9565b60606040518083038186803b15801561317157600080fd5b505afa158015613185573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506131a99190810190614a10565b85516000546040517fa12dcc6f00000000000000000000000000000000000000000000000000000000815292955090916001600160a01b039091169063a12dcc6f906131fb908990899060040161570c565b60206040518083038186803b15801561321357600080fd5b505afa158015613227573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061324b919081019061486e565b9150600061325e82886101400151610828565b60a088015160c08901516101808a01516101408b01519394509192909160009161328d9163ffffffff61393016565b156132ba576132b3846132ad848d6080015161395590919063ffffffff16565b85613971565b9050613313565b816132ce576132b3848b6080015185613971565b60006132df868c6101800151610828565b905060006132f2868d6080015187613971565b90506000613301838688613971565b905061330d82826134d6565b93505050505b61333361332d89604001518561399b90919063ffffffff16565b826134d6565b965050505050509250925092565b6000806000613352846106ae6139ba565b600061336b60048651876133fc9092919063ffffffff16565b8060200190516108089190810190614c34565b7ffdb6ca8d0000000000000000000000000000000000000000000000000000000090565b60006133af83600061343f565b90506001600160e01b0319808216908316146133f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077490615667565b505050565b60608183111561341a5761341a613415600085856139de565b613a4d565b83518211156134335761343361341560018487516139de565b50819003910190815290565b600081600401835110156134605761346061341560038551856004016139de565b5001602001516001600160e01b03191690565b600081601401835110156134945761349461341560048551856014016139de565b5001601401516001600160a01b031690565b60006120a58383613a55565b7f18e4b1410000000000000000000000000000000000000000000000000000000090565b60008183106134e557816120a5565b5090919050565b7f4678472b0000000000000000000000000000000000000000000000000000000090565b7fb6555d6f0000000000000000000000000000000000000000000000000000000090565b7f488219a60000000000000000000000000000000000000000000000000000000090565b7f1b8388f70000000000000000000000000000000000000000000000000000000090565b7fe94a7ed00000000000000000000000000000000000000000000000000000000090565b7f4ad312750000000000000000000000000000000000000000000000000000000090565b6060818311156135dd576135dd613415600085856139de565b83518211156135f6576135f661341560018487516139de565b8282036040519080825280601f01601f191660200182016040528015613623576020820181803883390190505b5090506120a561363282613a7f565b8461363c87613a7f565b018351613a85565b606080606061366060048551866135c49092919063ffffffff16565b80602001905161088a9190810190614715565b60408051600180825281830190925260609182918291816020015b613696613c90565b81526020019060019003908161368e5750506040805160018082528183019092529194506020808301908038833901905050604080516001808252818301909252919350816020015b60608152602001906001900390816136df575050845190915061370c90859060049063ffffffff6135c416565b80602001905161371f9190810190614b9c565b8560008151811061372c57fe5b602002602001018560008151811061374057fe5b602002602001018560008151811061375457fe5b6020908102919091010192909252919052529193909250565b6040805160018082528183019092526060918291829160208083019080388339505085519193506137a99186915060049063ffffffff6135c416565b8060200190516137bc919081019061478f565b845185906000906137c957fe5b60209081029190910101919091529095929450925050565b7f11c7b7200000000000000000000000000000000000000000000000000000000090565b7fa15c0d060000000000000000000000000000000000000000000000000000000090565b7f7e5a23180000000000000000000000000000000000000000000000000000000090565b7f5bd0428d0000000000000000000000000000000000000000000000000000000090565b7f20d11f610000000000000000000000000000000000000000000000000000000090565b7ff59851840000000000000000000000000000000000000000000000000000000090565b6138c1613d23565b6020810184905260a085015160808601516138dd918691613b2a565b815260a085015160c08601516138f4918691613b2a565b604082015260a085015160e086015161390e918691613b2a565b6060820152613923828463ffffffff613b5e16565b6080820152949350505050565b6000815183511480156120a55750508051602091820120825192909101919091201490565b6000828201838110156120a5576120a561341560008686613b8b565b600061399383613987868563ffffffff613b5e16565b9063ffffffff613baa16565b949350505050565b6000828211156139b4576139b461341560028585613b8b565b50900390565b7fe53c76c80000000000000000000000000000000000000000000000000000000090565b6060632800659560e01b8484846040516024016139fd939291906154cf565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199093169290921790915290509392505050565b805160208201fd5b60008160200183511015613a7657613a7661341560058551856020016139de565b50016020015190565b60200190565b6020811015613aaf576001816020036101000a0380198351168185511680821786525050506133f7565b82821415613abc576133f7565b82821115613af65760208103905080820181840181515b82851015613aee578451865260209586019590940193613ad3565b9052506133f7565b60208103905080820181840183515b81861215613b215782518252601f199283019290910190613b05565b85525050505050565b6000613b37848484613bd4565b15613b4a57613b4a613415858585613c3a565b61399383613987868563ffffffff613b5e16565b600082613b6d5750600061084a565b82820282848281613b7a57fe5b04146120a5576120a5613415600186865b606063e946c1bb60e01b8484846040516024016139fd93929190615460565b600081613bc057613bc061341560038585613b8b565b6000828481613bcb57fe5b04949350505050565b600082613be657613be6613415613c59565b811580613bf1575083155b15613bfe575060006120a5565b60008380613c0857fe5b8584099050613c1d858463ffffffff613b5e16565b613c2f826103e863ffffffff613b5e16565b101595945050505050565b606063339f3de260e01b8484846040516024016139fd9392919061573a565b60408051808201909152600481527fa791837c00000000000000000000000000000000000000000000000000000000602082015290565b604051806101c0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001606081526020016060815260200160608152602001606081525090565b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b604080516060810182526000808252602082018190529181019190915290565b803561084a81615816565b805161084a81615816565b600082601f830112613d98578081fd5b8135613dab613da682615777565b615750565b818152915060208083019084810181840286018201871015613dcc57600080fd5b60005b84811015611dc7578135613de281615816565b84529282019290820190600101613dcf565b600082601f830112613e04578081fd5b8151613e12613da682615777565b8181529150602080830190840160005b83811015613e4f57613e3a8760208451890101614074565b83526020928301929190910190600101613e22565b5050505092915050565b600082601f830112613e69578081fd5b8135613e77613da682615777565b8181529150602080830190840160005b83811015613e4f57613e9f8760208435890101614026565b83526020928301929190910190600101613e87565b600082601f830112613ec4578081fd5b8151613ed2613da682615777565b8181529150602080830190840160005b83811015613e4f57613efa8760208451890101614209565b83526020928301929190910190600101613ee2565b600082601f830112613f1f578081fd5b8135613f2d613da682615777565b8181529150602080830190840160005b83811015613e4f57613f5587602084358901016140ba565b83526020928301929190910190600101613f3d565b600082601f830112613f7a578081fd5b8151613f88613da682615777565b818152915060208083019084810181840286018201871015613fa957600080fd5b60005b84811015611dc757815184529282019290820190600101613fac565b600082601f830112613fd8578081fd5b8135613fe6613da682615777565b81815291506020808301908481018184028601820187101561400757600080fd5b60005b84811015611dc75781358452928201929082019060010161400a565b600082601f830112614036578081fd5b8135614044613da682615797565b915080825283602082850101111561405b57600080fd5b8060208401602084013760009082016020015292915050565b600082601f830112614084578081fd5b8151614092613da682615797565b91508082528360208285010111156140a957600080fd5b611dcc8160208401602086016157bb565b60006101c08083850312156140cd578182fd5b6140d681615750565b9150506140e38383613d72565b81526140f28360208401613d72565b60208201526141048360408401613d72565b60408201526141168360608401613d72565b60608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e08201526101008083013581830152506101208083013581830152506101408083013567ffffffffffffffff8082111561417857600080fd5b61418486838701614026565b838501526101609250828501359150808211156141a057600080fd5b6141ac86838701614026565b838501526101809250828501359150808211156141c857600080fd5b6141d486838701614026565b838501526101a09250828501359150808211156141f057600080fd5b506141fd85828601614026565b82840152505092915050565b60006101c080838503121561421c578182fd5b61422581615750565b9150506142328383613d7d565b81526142418360208401613d7d565b60208201526142538360408401613d7d565b60408201526142658360608401613d7d565b60608201526080820151608082015260a082015160a082015260c082015160c082015260e082015160e08201526101008083015181830152506101208083015181830152506101408083015167ffffffffffffffff808211156142c757600080fd5b6142d386838701614074565b838501526101609250828501519150808211156142ef57600080fd5b6142fb86838701614074565b8385015261018092508285015191508082111561431757600080fd5b61432386838701614074565b838501526101a092508285015191508082111561433f57600080fd5b506141fd85828601614074565b805160ff8116811461084a57600080fd5b60006020828403121561436e578081fd5b81356120a581615816565b6000806040838503121561438b578081fd5b825161439681615816565b60208401519092506143a781615816565b809150509250929050565b6000806000606084860312156143c6578081fd5b83516143d181615816565b60208501519093506143e281615816565b80925050604084015190509250925092565b60008060008060808587031215614409578182fd5b845161441481615816565b602086015190945067ffffffffffffffff80821115614431578384fd5b61443d88838901614074565b94506040870151915080821115614452578384fd5b61445e88838901614074565b93506060870151915080821115614473578283fd5b5061448087828801614074565b91505092959194509250565b6000806040838503121561449e578182fd5b82356144a981615816565b9150602083013567ffffffffffffffff8111156144c4578182fd5b6144d085828601613e59565b9150509250929050565b600080600080608085870312156144ef578182fd5b84356144fa81615816565b9350602085013567ffffffffffffffff80821115614516578384fd5b61452288838901613fc8565b94506040870135915080821115614537578384fd5b61454388838901613fc8565b93506060870135915080821115614558578283fd5b5061448087828801614026565b60008060408385031215614577578182fd5b823561458281615816565b9150602083013567ffffffffffffffff81111561459d578182fd5b6144d085828601614026565b600080604083850312156145bb578182fd5b82356145c681615816565b946020939093013593505050565b6000602082840312156145e5578081fd5b813567ffffffffffffffff8111156145fb578182fd5b61399384828501613d88565b600060208284031215614618578081fd5b815167ffffffffffffffff81111561462e578182fd5b61399384828501613eb4565b60008060006060848603121561464e578081fd5b833567ffffffffffffffff80821115614665578283fd5b61467187838801613f0f565b94506020860135915080821115614686578283fd5b61469287838801613d88565b935060408601359150808211156146a7578283fd5b506146b486828701613fc8565b9150509250925092565b600080604083850312156146d0578182fd5b823567ffffffffffffffff808211156146e7578384fd5b6146f386838701613f0f565b93506020850135915080821115614708578283fd5b506144d085828601613e59565b600080600060608486031215614729578081fd5b835167ffffffffffffffff80821115614740578283fd5b61474c87838801613eb4565b94506020860151915080821115614761578283fd5b61476d87838801613f6a565b93506040860151915080821115614782578283fd5b506146b486828701613df4565b6000806000606084860312156147a3578081fd5b835167ffffffffffffffff808211156147ba578283fd5b6147c687838801613eb4565b9450602086015193506040860151915080821115614782578283fd5b600080604083850312156147f4578182fd5b823567ffffffffffffffff8082111561480b578384fd5b6146f386838701613fc8565b60008060408385031215614829578182fd5b825167ffffffffffffffff80821115614840578384fd5b61484c86838701613f6a565b93506020850151915080821115614861578283fd5b506144d085828601613df4565b60006020828403121561487f578081fd5b815180151581146120a5578182fd5b600080600080608085870312156148a3578182fd5b8451935060208501516148b581615816565b604086015190935067ffffffffffffffff80821115614452578384fd5b600080604083850312156148e4578182fd5b505080516020909101519092909150565b60008060408385031215614907578182fd5b82519150602083015167ffffffffffffffff811115614924578182fd5b6144d085828601614074565b600080600060608486031215614944578081fd5b83519250602084015167ffffffffffffffff80821115614962578283fd5b61496e87838801614074565b93506040860151915080821115614983578283fd5b506146b486828701614074565b600080604083850312156149a2578182fd5b8251915060208301516143a78161582b565b600080604083850312156149c6578182fd5b82516001600160e01b031981168114614396578283fd5b6000602082840312156149ee578081fd5b813567ffffffffffffffff811115614a04578182fd5b61399384828501614026565b60006060828403128015614a22578182fd5b8015614a2c578182fd5b50614a376060615750565b8251614a428161582b565b8152602083810151908201526040928301519281019290925250919050565b600060208284031215614a72578081fd5b815167ffffffffffffffff811115614a88578182fd5b61399384828501614209565b600080600060608486031215614aa8578081fd5b833567ffffffffffffffff811115614abe578182fd5b614aca868287016140ba565b9350506020840135614adb81615816565b929592945050506040919091013590565b60008060408385031215614afe578182fd5b823567ffffffffffffffff80821115614b15578384fd5b614b21868387016140ba565b93506020850135915080821115614b36578283fd5b506144d085828601614026565b60008060008060808587031215614b58578182fd5b845167ffffffffffffffff80821115614b6f578384fd5b614b7b88838901614209565b95506020870151915080821115614b90578384fd5b61443d88838901614209565b600080600060608486031215614bb0578081fd5b835167ffffffffffffffff80821115614bc7578283fd5b614bd387838801614209565b9450602086015193506040860151915080821115614983578283fd5b600060208284031215614c00578081fd5b5051919050565b60008060408385031215614c19578182fd5b8251614c248161582b565b6020939093015192949293505050565b600080600060608486031215614c48578081fd5b8351614c538161582b565b602085015160408601519194509250614c6b81615816565b809150509250925092565b60008060008060808587031215614c8b578182fd5b614c95868661434c565b9350602085015192506040850151614cac81615816565b606086015190925067ffffffffffffffff811115614cc8578182fd5b61448087828801614074565b600080600060608486031215614ce8578081fd5b614cf2858561434c565b925060208401519150604084015167ffffffffffffffff811115614d14578182fd5b6146b486828701614074565b600080600060608486031215614d34578081fd5b614d3e858561434c565b925060208401519150604084015190509250925092565b1515815260200190565b6000614d6b8383614e78565b505060600190565b6001600160a01b03169052565b6000815180845260208401935060208301825b82811015614dba5781516001600160a01b0316865260209586019590910190600101614d93565b5093949350505050565b600081518084526020840180819550602083028101915060208501845b84811015614e0f578284038852614df9848351614e4c565b6020988901989094509190910190600101614de1565b50919695505050505050565b6000815180845260208401935060208301825b82811015614dba578151865260209586019590910190600101614e2e565b60008151808452614e648160208601602086016157bb565b601f01601f19169290920160200192915050565b805160ff16825260208082015190830152604090810151910152565b60006101c0614ea4848451614d73565b6020830151614eb66020860182614d73565b506040830151614ec96040860182614d73565b506060830151614edc6060860182614d73565b506080830151608085015260a083015160a085015260c083015160c085015260e083015160e0850152610100808401518186015250610120808401518186015250610140808401518282870152614f3583870182614e4c565b91505061016091508184015185820383870152614f528282614e4c565b925050506101808084015185830382870152614f6e8382614e4c565b9150506101a091508184015185820383870152614f8b8282614e4c565b9695505050505050565b60008251614fa78184602087016157bb565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001600160a01b0386168252608060208301526150256080830186614e1b565b82810360408401526150378186614e1b565b83810360608501526150498186614e4c565b98975050505050505050565b60006001600160a01b0386168252608060208301526150776080830186614e4c565b82810360408401526150378186614e4c565b6001600160a01b03929092168252602082015260400190565b6000608082526150b56080830187614dc4565b82810360208401526150c78187614d80565b83810360408501526150d98187614d80565b91505082810360608401526150ee8185614e1b565b979650505050505050565b602080825282518282018190526000918401906040840190835b8181101561513b5783516005811061512757fe5b835260209384019390920191600101615113565b509095945050505050565b6000606082016060835280865161515d8184615731565b9150602088019250835b8181101561518b5761517a838551614d5f565b602094909401939250600101615167565b5050838103602085015261519f8187614e1b565b91505082810360408401528084516151b78184615731565b9150602086019250835b818110156151e5576151d4838551614d55565b6020949094019392506001016151c1565b5090979650505050505050565b6000602082526120a56020830184614e1b565b6000604082526152186040830185614e1b565b828103602084015261522a8185614dc4565b95945050505050565b6000604082526152466040830185614e1b565b828103602084015261522a8185614e1b565b60008582526001600160a01b0385166020830152608060408301526152806080830185614e4c565b82810360608401526150ee8185614e4c565b918252602082015260400190565b6000838252604060208301526139936040830184614e4c565b6000848252606060208301526152d26060830185614e4c565b8281036040840152614f8b8185614e4c565b828152604081016152f48361580c565b8260208301529392505050565b6001600160e01b03199290921682526001600160a01b0316602082015260400190565b60006001600160e01b0319871682526001600160a01b038616602083015260a0604083015261535660a0830186614e1b565b82810360608401526153688186614e1b565b838103608085015261537a8186614e4c565b9998505050505050505050565b6001600160e01b03199390931683526001600160a01b03919091166020830152604082015260600190565b60006001600160e01b031985168252606060208301526153d56060830185614e1b565b8281036040840152614f8b8185614dc4565b6000602082526120a56020830184614e4c565b60006080825261540d6080830187614e4c565b6001600160a01b03958616602084015293909416604082015260ff9190911660609091015292915050565b6000615443856157eb565b8482528360208301526060604083015261522a6060830184614e4c565b6060810161546d856157f8565b938152602081019290925260409091015290565b6060810161548e85615802565b93815260208101929092526001600160a01b031660409091015290565b604081016154b8846157f8565b9281526020015290565b6060810161546d85615802565b606081016008851061546d57fe5b60208101600583106154eb57fe5b91905290565b60006154fc8661580c565b8582528460208301526001600160a01b038416604083015260806060830152614f8b6080830184614e4c565b604081016154b8846157eb565b6000608082526155486080830187614e4c565b602083820381850152818751808452828401915082838202850101838a01865b8381101561559657601f19878403018552615584838351614e94565b94860194925090850190600101615568565b505086810360408801526155aa818a614e1b565b94505050505082810360608401526150ee8185614dc4565b60208082526013908201527f554e4b4e4f574e5f52455455524e5f4441544100000000000000000000000000604082015260600190565b60208082526019908201527f554e4b4e4f574e5f46554e4354494f4e5f53454c4543544f5200000000000000604082015260600190565b6020808252600d908201527f554e494d504c454d454e54454400000000000000000000000000000000000000604082015260600190565b6020808252600c908201527f4241445f53454c4543544f520000000000000000000000000000000000000000604082015260600190565b6020808252600e908201527f57524f4e475f50524f58595f4944000000000000000000000000000000000000604082015260600190565b60a081016156e38286614e78565b8360608301528215156080830152949350505050565b6000602082526120a56020830184614e94565b60006040825261571f6040830185614e94565b828103602084015261522a8185614e4c565b90815260200190565b9283526020830191909152604082015260600190565b60405181810167ffffffffffffffff8111828210171561576f57600080fd5b604052919050565b600067ffffffffffffffff82111561578d578081fd5b5060209081020190565b600067ffffffffffffffff8211156157ad578081fd5b50601f01601f191660200190565b60005b838110156157d65781810151838201526020016157be565b838111156157e5576000848401525b50505050565b600281106157f557fe5b50565b600481106157f557fe5b600381106157f557fe5b600781106157f557fe5b6001600160a01b03811681146157f557600080fd5b60ff811681146157f557600080fdfea365627a7a723158200ea049525ebc74d73f3bf7858c601bd21168267b0dfb4abbdb7787cfd7233a2c6c6578706572696d656e74616cf564736f6c634300050c0040'; /** @@ -61,7 +70,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -74,45 +83,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param encoded ABI-encoded revert error. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(encoded: string): string { - assert.isString('encoded', encoded); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeAssetProxyDispatchError(bytes)', [ - encoded, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeAssetProxyDispatchError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [number, string, string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeAssetProxyDispatchError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[number, string, string]>(returnData); - return abiDecodedReturnData; - }, }; /** * Decompose an ABI-encoded AssetProxyExistsError. @@ -145,7 +115,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -158,45 +128,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param encoded ABI-encoded revert error. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(encoded: string): string { - assert.isString('encoded', encoded); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeAssetProxyExistsError(bytes)', [ - encoded, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeAssetProxyExistsError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [string, string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeAssetProxyExistsError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[string, string]>(returnData); - return abiDecodedReturnData; - }, }; /** * Decompose an ABI-encoded AssetProxyTransferError. @@ -229,7 +160,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -242,45 +173,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param encoded ABI-encoded revert error. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(encoded: string): string { - assert.isString('encoded', encoded); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeAssetProxyTransferError(bytes)', [ - encoded, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeAssetProxyTransferError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [string, string, string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeAssetProxyTransferError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[string, string, string]>(returnData); - return abiDecodedReturnData; - }, }; /** * Decompose an ABI-encoded SignatureValidatorError. @@ -313,7 +205,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -326,47 +218,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param encoded ABI-encoded revert error. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(encoded: string): string { - assert.isString('encoded', encoded); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeEIP1271SignatureError(bytes)', [ - encoded, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeEIP1271SignatureError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [string, string, string, string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeEIP1271SignatureError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[string, string, string, string]>( - returnData, - ); - return abiDecodedReturnData; - }, }; /** * Decode ERC-1155 asset data from the format described in the AssetProxy contract specification. @@ -400,7 +251,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -415,46 +266,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param assetData AssetProxy-compliant asset data describing an ERC-1155 set - * of assets. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(assetData: string): string { - assert.isString('assetData', assetData); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeERC1155AssetData(bytes)', [assetData]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeERC1155AssetData(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [string, string, BigNumber[], BigNumber[], string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeERC1155AssetData(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue< - [string, string, BigNumber[], BigNumber[], string] - >(returnData); - return abiDecodedReturnData; - }, }; /** * Decode ERC-20 asset data from the format described in the AssetProxy contract specification. @@ -487,7 +298,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -500,43 +311,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param assetData AssetProxy-compliant asset data describing an ERC-20 asset. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(assetData: string): string { - assert.isString('assetData', assetData); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeERC20AssetData(bytes)', [assetData]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeERC20AssetData(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [string, string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeERC20AssetData(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[string, string]>(returnData); - return abiDecodedReturnData; - }, }; /** * Decode ERC-721 asset data from the format described in the AssetProxy contract specification. @@ -570,7 +344,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -583,44 +357,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param assetData AssetProxy-compliant asset data describing an ERC-721 - * asset. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(assetData: string): string { - assert.isString('assetData', assetData); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeERC721AssetData(bytes)', [assetData]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeERC721AssetData(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [string, string, BigNumber] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeERC721AssetData(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[string, string, BigNumber]>(returnData); - return abiDecodedReturnData; - }, }; /** * Decompose an ABI-encoded OrderStatusError. @@ -653,7 +389,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -666,45 +402,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param encoded ABI-encoded revert error. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(encoded: string): string { - assert.isString('encoded', encoded); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeExchangeInvalidContextError(bytes)', [ - encoded, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeExchangeInvalidContextError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [number, string, string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeExchangeInvalidContextError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[number, string, string]>(returnData); - return abiDecodedReturnData; - }, }; /** * Decompose an ABI-encoded FillError. @@ -737,7 +434,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -750,43 +447,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param encoded ABI-encoded revert error. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(encoded: string): string { - assert.isString('encoded', encoded); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeFillError(bytes)', [encoded]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeFillError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [number, string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeFillError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[number, string]>(returnData); - return abiDecodedReturnData; - }, }; /** * Decompose an ABI-encoded IncompleteFillError. @@ -819,7 +479,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -832,45 +492,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param encoded ABI-encoded revert error. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(encoded: string): string { - assert.isString('encoded', encoded); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeIncompleteFillError(bytes)', [ - encoded, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeIncompleteFillError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [number, BigNumber, BigNumber] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeIncompleteFillError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[number, BigNumber, BigNumber]>(returnData); - return abiDecodedReturnData; - }, }; /** * Decode multi-asset data from the format described in the AssetProxy contract specification. @@ -903,7 +524,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -916,50 +537,11 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param assetData AssetProxy-compliant data describing a multi-asset basket. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(assetData: string): string { - assert.isString('assetData', assetData); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeMultiAssetData(bytes)', [assetData]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeMultiAssetData(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [string, BigNumber[], string[]] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeMultiAssetData(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[string, BigNumber[], string[]]>( - returnData, - ); - return abiDecodedReturnData; - }, - }; - /** - * Decompose an ABI-encoded NegativeSpreadError. - */ - public decodeNegativeSpreadError = { + }; + /** + * Decompose an ABI-encoded NegativeSpreadError. + */ + public decodeNegativeSpreadError = { /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -987,7 +569,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1000,45 +582,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param encoded ABI-encoded revert error. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(encoded: string): string { - assert.isString('encoded', encoded); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeNegativeSpreadError(bytes)', [ - encoded, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeNegativeSpreadError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [string, string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeNegativeSpreadError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[string, string]>(returnData); - return abiDecodedReturnData; - }, }; /** * Decompose an ABI-encoded OrderEpochError. @@ -1071,7 +614,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1084,43 +627,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param encoded ABI-encoded revert error. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(encoded: string): string { - assert.isString('encoded', encoded); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeOrderEpochError(bytes)', [encoded]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeOrderEpochError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [string, string, BigNumber] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeOrderEpochError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[string, string, BigNumber]>(returnData); - return abiDecodedReturnData; - }, }; /** * Decompose an ABI-encoded OrderStatusError. @@ -1153,7 +659,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1166,43 +672,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param encoded ABI-encoded revert error. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(encoded: string): string { - assert.isString('encoded', encoded); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeOrderStatusError(bytes)', [encoded]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeOrderStatusError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [string, number] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeOrderStatusError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[string, number]>(returnData); - return abiDecodedReturnData; - }, }; /** * Decompose an ABI-encoded SignatureError. @@ -1235,7 +704,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1248,45 +717,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param encoded ABI-encoded revert error. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(encoded: string): string { - assert.isString('encoded', encoded); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeSignatureError(bytes)', [encoded]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeSignatureError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [number, string, string, string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeSignatureError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[number, string, string, string]>( - returnData, - ); - return abiDecodedReturnData; - }, }; /** * Decompose an ABI-encoded SignatureValidatorNotApprovedError. @@ -1321,7 +751,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1334,46 +764,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param encoded ABI-encoded revert error. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(encoded: string): string { - assert.isString('encoded', encoded); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'decodeSignatureValidatorNotApprovedError(bytes)', - [encoded], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeSignatureValidatorNotApprovedError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [string, string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeSignatureValidatorNotApprovedError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[string, string]>(returnData); - return abiDecodedReturnData; - }, }; /** * Decompose an ABI-encoded SignatureWalletError. @@ -1406,7 +796,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1419,47 +809,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param encoded ABI-encoded revert error. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(encoded: string): string { - assert.isString('encoded', encoded); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeSignatureWalletError(bytes)', [ - encoded, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeSignatureWalletError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [string, string, string, string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeSignatureWalletError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[string, string, string, string]>( - returnData, - ); - return abiDecodedReturnData; - }, }; /** * Decompose an ABI-encoded TransactionError. @@ -1492,7 +841,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1505,43 +854,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param encoded ABI-encoded revert error. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(encoded: string): string { - assert.isString('encoded', encoded); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeTransactionError(bytes)', [encoded]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeTransactionError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [number, string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeTransactionError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[number, string]>(returnData); - return abiDecodedReturnData; - }, }; /** * Decompose an ABI-encoded TransactionExecutionError. @@ -1574,7 +886,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1587,45 +899,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param encoded ABI-encoded revert error. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(encoded: string): string { - assert.isString('encoded', encoded); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeTransactionExecutionError(bytes)', [ - encoded, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeTransactionExecutionError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [string, string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeTransactionExecutionError(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[string, string]>(returnData); - return abiDecodedReturnData; - }, }; /** * Decodes the call data for an Exchange contract method call. @@ -1681,7 +954,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1716,106 +989,22 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, + }; + /** + * Encode ERC-1155 asset data into the format described in the AssetProxy contract specification. + */ + public encodeERC1155AssetData = { /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param transactionData ABI-encoded calldata for an Exchange contract - * method call. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(transactionData: string): string { - assert.isString('transactionData', transactionData); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decodeZeroExTransactionData(bytes)', [ - transactionData, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeZeroExTransactionData(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): [ - string, - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - BigNumber[], - string[] - ] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('decodeZeroExTransactionData(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue< - [ - string, - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - BigNumber[], - string[] - ] - >(returnData); - return abiDecodedReturnData; - }, - }; - /** - * Encode ERC-1155 asset data into the format described in the AssetProxy contract specification. - */ - public encodeERC1155AssetData = { - /** - * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an - * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas - * since they don't modify state. - * @param tokenAddress The address of the ERC-1155 contract hosting the - * asset(s) to be traded. - * @param tokenIds The identifiers of the specific assets to be traded. - * @param tokenValues The amounts of each asset to be traded. - * @param callbackData Data to be passed to receiving contracts when a transfer - * is performed. - * @returns AssetProxy-compliant asset data describing the set of assets. + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + * @param tokenAddress The address of the ERC-1155 contract hosting the + * asset(s) to be traded. + * @param tokenIds The identifiers of the specific assets to be traded. + * @param tokenValues The amounts of each asset to be traded. + * @param callbackData Data to be passed to receiving contracts when a transfer + * is performed. + * @returns AssetProxy-compliant asset data describing the set of assets. */ async callAsync( tokenAddress: string, @@ -1846,7 +1035,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1859,59 +1048,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param tokenAddress The address of the ERC-1155 contract hosting the - * asset(s) to be traded. - * @param tokenIds The identifiers of the specific assets to be traded. - * @param tokenValues The amounts of each asset to be traded. - * @param callbackData Data to be passed to receiving contracts when a transfer - * is performed. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData( - tokenAddress: string, - tokenIds: BigNumber[], - tokenValues: BigNumber[], - callbackData: string, - ): string { - assert.isString('tokenAddress', tokenAddress); - assert.isArray('tokenIds', tokenIds); - assert.isArray('tokenValues', tokenValues); - assert.isString('callbackData', callbackData); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'encodeERC1155AssetData(address,uint256[],uint256[],bytes)', - [tokenAddress.toLowerCase(), tokenIds, tokenValues, callbackData], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('encodeERC1155AssetData(address,uint256[],uint256[],bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('encodeERC1155AssetData(address,uint256[],uint256[],bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Encode ERC-20 asset data into the format described in the AssetProxy contract specification. @@ -1947,7 +1083,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1960,46 +1096,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param tokenAddress The address of the ERC-20 contract hosting the asset to - * be traded. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(tokenAddress: string): string { - assert.isString('tokenAddress', tokenAddress); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('encodeERC20AssetData(address)', [ - tokenAddress.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('encodeERC20AssetData(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('encodeERC20AssetData(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Encode ERC-721 asset data into the format described in the AssetProxy specification. @@ -2039,7 +1135,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -2052,49 +1148,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param tokenAddress The address of the ERC-721 contract hosting the asset to - * be traded. - * @param tokenId The identifier of the specific asset to be traded. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(tokenAddress: string, tokenId: BigNumber): string { - assert.isString('tokenAddress', tokenAddress); - assert.isBigNumber('tokenId', tokenId); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('encodeERC721AssetData(address,uint256)', [ - tokenAddress.toLowerCase(), - tokenId, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('encodeERC721AssetData(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('encodeERC721AssetData(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Encode data for multiple assets, per the AssetProxy contract specification. @@ -2134,7 +1187,7 @@ export class DevUtilsContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -2147,49 +1200,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param amounts The amounts of each asset to be traded. - * @param nestedAssetData AssetProxy-compliant data describing each asset to be - * traded. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(amounts: BigNumber[], nestedAssetData: string[]): string { - assert.isArray('amounts', amounts); - assert.isArray('nestedAssetData', nestedAssetData); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('encodeMultiAssetData(uint256[],bytes[])', [ - amounts, - nestedAssetData, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): BigNumber[] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('encodeMultiAssetData(uint256[],bytes[])'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('encodeMultiAssetData(uint256[],bytes[])'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Returns the number of asset(s) (described by assetData) that the corresponding AssetProxy contract is authorized to spend. When the asset data contains multiple assets (eg for Multi-Asset), the return value indicates how many complete "baskets" of those assets may be spent by all of the corresponding AssetProxy contracts. @@ -2250,49 +1260,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param ownerAddress Owner of the assets specified by assetData. - * @param assetData Details of asset, encoded per the AssetProxy contract - * specification. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(ownerAddress: string, assetData: string): string { - assert.isString('ownerAddress', ownerAddress); - assert.isString('assetData', assetData); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getAssetProxyAllowance(address,bytes)', [ - ownerAddress.toLowerCase(), - assetData, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('getAssetProxyAllowance(address,bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('getAssetProxyAllowance(address,bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Returns the owner's balance of the assets(s) specified in assetData. When the asset data contains multiple assets (eg in ERC1155 or Multi-Asset), the return value indicates how many complete "baskets" of those assets are owned by owner. @@ -2353,49 +1320,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param ownerAddress Owner of the assets specified by assetData. - * @param assetData Details of asset, encoded per the AssetProxy contract - * specification. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(ownerAddress: string, assetData: string): string { - assert.isString('ownerAddress', ownerAddress); - assert.isString('assetData', assetData); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getBalance(address,bytes)', [ - ownerAddress.toLowerCase(), - assetData, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('getBalance(address,bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('getBalance(address,bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Calls getBalance() and getAllowance() for assetData. @@ -2456,49 +1380,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param ownerAddress Owner of the assets specified by assetData. - * @param assetData Details of asset, encoded per the AssetProxy contract - * specification. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(ownerAddress: string, assetData: string): string { - assert.isString('ownerAddress', ownerAddress); - assert.isString('assetData', assetData); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'getBalanceAndAssetProxyAllowance(address,bytes)', - [ownerAddress.toLowerCase(), assetData], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, string] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('getBalanceAndAssetProxyAllowance(address,bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [BigNumber, BigNumber] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('getBalanceAndAssetProxyAllowance(address,bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[BigNumber, BigNumber]>(returnData); - return abiDecodedReturnData; - }, }; /** * Calls getAssetProxyAllowance() for each element of assetData. @@ -2559,49 +1440,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param ownerAddress Owner of the assets specified by assetData. - * @param assetData Array of asset details, each encoded per the AssetProxy - * contract specification. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(ownerAddress: string, assetData: string[]): string { - assert.isString('ownerAddress', ownerAddress); - assert.isArray('assetData', assetData); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'getBatchAssetProxyAllowances(address,bytes[])', - [ownerAddress.toLowerCase(), assetData], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('getBatchAssetProxyAllowances(address,bytes[])'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber[] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('getBatchAssetProxyAllowances(address,bytes[])'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Calls getBalance() for each element of assetData. @@ -2662,49 +1500,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param ownerAddress Owner of the assets specified by assetData. - * @param assetData Array of asset details, each encoded per the AssetProxy - * contract specification. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(ownerAddress: string, assetData: string[]): string { - assert.isString('ownerAddress', ownerAddress); - assert.isArray('assetData', assetData); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getBatchBalances(address,bytes[])', [ - ownerAddress.toLowerCase(), - assetData, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('getBatchBalances(address,bytes[])'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber[] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('getBatchBalances(address,bytes[])'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Calls getBatchBalances() and getBatchAllowances() for each element of assetData. @@ -2765,49 +1560,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param ownerAddress Owner of the assets specified by assetData. - * @param assetData Array of asset details, each encoded per the AssetProxy - * contract specification. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(ownerAddress: string, assetData: string[]): string { - assert.isString('ownerAddress', ownerAddress); - assert.isArray('assetData', assetData); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'getBatchBalancesAndAssetProxyAllowances(address,bytes[])', - [ownerAddress.toLowerCase(), assetData], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, string[]] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('getBatchBalancesAndAssetProxyAllowances(address,bytes[])'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, string[]]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [BigNumber[], BigNumber[]] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('getBatchBalancesAndAssetProxyAllowances(address,bytes[])'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[BigNumber[], BigNumber[]]>(returnData); - return abiDecodedReturnData; - }, }; /** * Batch fetches ETH balances @@ -2861,43 +1613,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param addresses Array of addresses. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(addresses: string[]): string { - assert.isArray('addresses', addresses); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getEthBalances(address[])', [addresses]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string[] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('getEthBalances(address[])'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber[] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('getEthBalances(address[])'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Fetches all order-relevant information needed to validate if the supplied order is fillable. @@ -2966,127 +1681,18 @@ export class DevUtilsContract extends BaseContract { rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); - throw err; - } - BaseContract._throwIfCallResultIsRevertError(rawCallResult); - const abiEncoder = self._lookupAbiEncoder( - 'getOrderRelevantState((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),bytes)', - ); - // tslint:disable boolean-naming - const result = abiEncoder.strictDecodeReturnValue< - [{ orderStatus: number; orderHash: string; orderTakerAssetFilledAmount: BigNumber }, BigNumber, boolean] - >(rawCallResult); - // tslint:enable boolean-naming - return result; - }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param order The order structure. - * @param signature Signature provided by maker that proves the order's - * authenticity. `0x01` can always be provided if the signature does not - * need to be validated. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData( - order: { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }, - signature: string, - ): string { - assert.isString('signature', signature); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'getOrderRelevantState((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),bytes)', - [order, signature], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): [ - { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }, - string - ] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder( - 'getOrderRelevantState((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),bytes)', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - [ - { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }, - string - ] - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): [{ orderStatus: number; orderHash: string; orderTakerAssetFilledAmount: BigNumber }, BigNumber, boolean] { - const self = (this as any) as DevUtilsContract; + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); const abiEncoder = self._lookupAbiEncoder( 'getOrderRelevantState((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),bytes)', ); // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue< + const result = abiEncoder.strictDecodeReturnValue< [{ orderStatus: number; orderHash: string; orderTakerAssetFilledAmount: BigNumber }, BigNumber, boolean] - >(returnData); - return abiDecodedReturnData; + >(rawCallResult); + // tslint:enable boolean-naming + return result; }, }; /** @@ -3178,124 +1784,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param orders Array of order structures. - * @param signatures Array of signatures provided by makers that prove the - * authenticity of the orders. `0x01` can always be provided if a signature - * does not need to be validated. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - signatures: string[], - ): string { - assert.isArray('orders', orders); - assert.isArray('signatures', signatures); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'getOrderRelevantStates((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[])', - [orders, signatures], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): [ - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - string[] - ] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder( - 'getOrderRelevantStates((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - [ - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - string[] - ] - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): [ - Array<{ orderStatus: number; orderHash: string; orderTakerAssetFilledAmount: BigNumber }>, - BigNumber[], - boolean[] - ] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder( - 'getOrderRelevantStates((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue< - [ - Array<{ orderStatus: number; orderHash: string; orderTakerAssetFilledAmount: BigNumber }>, - BigNumber[], - boolean[] - ] - >(returnData); - return abiDecodedReturnData; - }, }; /** * Simulates all of the transfers within an order and returns the index of the first failed transfer. @@ -3331,6 +1819,7 @@ export class DevUtilsContract extends BaseContract { takerAddress: string, takerAssetFillAmount: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('takerAddress', takerAddress); assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); @@ -3351,6 +1840,15 @@ export class DevUtilsContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.getSimulatedOrderTransferResults.callAsync( + order, + takerAddress, + takerAssetFillAmount, + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -3385,8 +1883,7 @@ export class DevUtilsContract extends BaseContract { takerAddress: string, takerAssetFillAmount: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('takerAddress', takerAddress); assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); @@ -3396,6 +1893,7 @@ export class DevUtilsContract extends BaseContract { takerAddress.toLowerCase(), takerAssetFillAmount, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -3403,8 +1901,8 @@ export class DevUtilsContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -3461,41 +1959,6 @@ export class DevUtilsContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - order: { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }, - takerAddress: string, - takerAssetFillAmount: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).getSimulatedOrderTransferResults.callAsync( - order, - takerAddress, - takerAssetFillAmount, - txData, - ); - const txHash = await (this as any).getSimulatedOrderTransferResults.sendTransactionAsync( - order, - takerAddress, - takerAssetFillAmount, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -3609,66 +2072,6 @@ export class DevUtilsContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - } { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder( - 'getSimulatedOrderTransferResults((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),address,uint256)', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): number { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder( - 'getSimulatedOrderTransferResults((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),address,uint256)', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Simulates all of the transfers for each given order and returns the indices of each first failed transfer. @@ -3705,6 +2108,7 @@ export class DevUtilsContract extends BaseContract { takerAddresses: string[], takerAssetFillAmounts: BigNumber[], txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isArray('orders', orders); assert.isArray('takerAddresses', takerAddresses); @@ -3726,6 +2130,15 @@ export class DevUtilsContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.getSimulatedOrdersTransferResults.callAsync( + orders, + takerAddresses, + takerAssetFillAmounts, + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -3761,8 +2174,7 @@ export class DevUtilsContract extends BaseContract { takerAddresses: string[], takerAssetFillAmounts: BigNumber[], txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isArray('orders', orders); assert.isArray('takerAddresses', takerAddresses); @@ -3773,6 +2185,7 @@ export class DevUtilsContract extends BaseContract { takerAddresses, takerAssetFillAmounts, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -3780,8 +2193,8 @@ export class DevUtilsContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -3840,41 +2253,6 @@ export class DevUtilsContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - takerAddresses: string[], - takerAssetFillAmounts: BigNumber[], - txData?: Partial | undefined, - ): Promise { - await (this as any).getSimulatedOrdersTransferResults.callAsync( - orders, - takerAddresses, - takerAssetFillAmounts, - txData, - ); - const txHash = await (this as any).getSimulatedOrdersTransferResults.sendTransactionAsync( - orders, - takerAddresses, - takerAssetFillAmounts, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -3992,68 +2370,6 @@ export class DevUtilsContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder( - 'getSimulatedOrdersTransferResults((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],address[],uint256[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): number[] { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder( - 'getSimulatedOrdersTransferResults((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],address[],uint256[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Gets the amount of an asset transferable by the owner. @@ -4114,49 +2430,6 @@ export class DevUtilsContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param ownerAddress Address of the owner of the asset. - * @param assetData Description of tokens, per the AssetProxy contract - * specification. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(ownerAddress: string, assetData: string): string { - assert.isString('ownerAddress', ownerAddress); - assert.isString('assetData', assetData); - const self = (this as any) as DevUtilsContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getTransferableAssetAmount(address,bytes)', [ - ownerAddress.toLowerCase(), - assetData, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('getTransferableAssetAmount(address,bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as DevUtilsContract; - const abiEncoder = self._lookupAbiEncoder('getTransferableAssetAmount(address,bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public static async deployFrom0xArtifactAsync( artifact: ContractArtifact | SimpleContractArtifact, diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/dummy_erc20_token.ts b/packages/abi-gen-wrappers/src/generated-wrappers/dummy_erc20_token.ts index b8b2279a97..6821ab56f8 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/dummy_erc20_token.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/dummy_erc20_token.ts @@ -19,7 +19,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -48,8 +54,10 @@ export interface DummyERC20TokenTransferEventArgs extends DecodedLogArgs { // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class DummyERC20TokenContract extends BaseContract { - public static deployedBytecode = - '0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c806395d89b411161008c578063dd62ed3e11610066578063dd62ed3e146102e2578063e30443bc1461031d578063f2fde38b14610356578063fa9b701814610389576100ea565b806395d89b4114610282578063a0712d681461028a578063a9059cbb146102a9576100ea565b806323b872dd116100c857806323b872dd146101d3578063313ce5671461021657806370a082311461021e5780638da5cb5b14610251576100ea565b806306fdde03146100ef578063095ea7b31461016c57806318160ddd146101b9575b600080fd5b6100f7610391565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610131578181015183820152602001610119565b50505050905090810190601f16801561015e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101a56004803603604081101561018257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561043d565b604080519115158252519081900360200190f35b6101c16104b0565b60408051918252519081900360200190f35b6101a5600480360360608110156101e957600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356104b6565b6101c1610772565b6101c16004803603602081101561023457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610778565b6102596107a0565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6100f76107bc565b6102a7600480360360208110156102a057600080fd5b5035610835565b005b6101a5600480360360408110156102bf57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356108bb565b6101c1600480360360408110156102f857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516610a4a565b6102a76004803603604081101561033357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610a82565b6102a76004803603602081101561036c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610b18565b6101c1610b95565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156104355780601f1061040a57610100808354040283529160200191610435565b820191906000526020600020905b81548152906001019060200180831161041857829003601f168201915b505050505081565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b60035490565b73ffffffffffffffffffffffffffffffffffffffff83166000818152600260209081526040808320338452825280832054938352600190915281205490919083111561056357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f45524332305f494e53554646494349454e545f42414c414e4345000000000000604482015290519081900360640190fd5b828110156105d257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f45524332305f494e53554646494349454e545f414c4c4f57414e434500000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8416600090815260016020526040902054838101101561066857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f55494e543235365f4f564552464c4f5700000000000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff808516600090815260016020526040808220805487019055918716815220805484900390557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156107025773ffffffffffffffffffffffffffffffffffffffff851660009081526002602090815260408083203384529091529020805484900390555b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a3506001949350505050565b60065481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205490565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156104355780601f1061040a57610100808354040283529160200191610435565b69021e19e0c9bab24000008111156108ae57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f56414c55455f544f4f5f4c415247450000000000000000000000000000000000604482015290519081900360640190fd5b6108b83382610ba3565b50565b3360009081526001602052604081205482111561093957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f45524332305f494e53554646494349454e545f42414c414e4345000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604090205482810110156109cf57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f55494e543235365f4f564552464c4f5700000000000000000000000000000000604482015290519081900360640190fd5b3360008181526001602090815260408083208054879003905573ffffffffffffffffffffffffffffffffffffffff871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350600192915050565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260026020908152604080832093909416825291909152205490565b610a8a610c5c565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604090205480821015610ad557610acd600354610ac88385610ca5565b610ca5565b600355610aee565b610aea600354610ae58484610ca5565b610cc4565b6003555b5073ffffffffffffffffffffffffffffffffffffffff909116600090815260016020526040902055565b610b20610c5c565b73ffffffffffffffffffffffffffffffffffffffff8116610b5057610b4b610b46610ce7565b610d1e565b6108b8565b6000805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905550565b69021e19e0c9bab240000081565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260016020526040902054610bd4908290610cc4565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260016020526040902055600354610c079082610cc4565b60035560408051828152905173ffffffffffffffffffffffffffffffffffffffff8416916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ca357600054610ca390610b4690339073ffffffffffffffffffffffffffffffffffffffff16610d26565b565b600082821115610cbe57610cbe610b4660028585610db2565b50900390565b600082820183811015610ce057610ce0610b4660008686610db2565b9392505050565b60408051808201909152600481527fe69edc3e00000000000000000000000000000000000000000000000000000000602082015290565b805160208201fd5b6040805173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044808301919091528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1de45ad10000000000000000000000000000000000000000000000000000000017905292915050565b606063e946c1bb60e01b84848460405160240180846003811115610dd257fe5b60ff1681526020018381526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050939250505056fea265627a7a7231582089c03e503c77db7069bea8a94ec1c47ee5201d8bdb53857e70a882a1130e1ac364736f6c634300050c0032'; + /** + * @ignore + */ + public static deployedBytecode: string | undefined; public MAX_MINT_AMOUNT = { /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an @@ -92,41 +100,6 @@ export class DummyERC20TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as DummyERC20TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('MAX_MINT_AMOUNT()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('MAX_MINT_AMOUNT()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('MAX_MINT_AMOUNT()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public allowance = { /** @@ -183,48 +156,6 @@ export class DummyERC20TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param _owner The address of the account owning tokens - * @param _spender The address of the account able to transfer the tokens - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(_owner: string, _spender: string): string { - assert.isString('_owner', _owner); - assert.isString('_spender', _spender); - const self = (this as any) as DummyERC20TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('allowance(address,address)', [ - _owner.toLowerCase(), - _spender.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('allowance(address,address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('allowance(address,address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * `msg.sender` approves `_spender` to spend `_value` tokens @@ -242,6 +173,7 @@ export class DummyERC20TokenContract extends BaseContract { _spender: string, _value: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_spender', _spender); assert.isBigNumber('_value', _value); @@ -262,6 +194,10 @@ export class DummyERC20TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.approve.callAsync(_spender, _value, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -278,21 +214,20 @@ export class DummyERC20TokenContract extends BaseContract { _spender: string, _value: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_spender', _spender); assert.isBigNumber('_value', _value); const self = (this as any) as DummyERC20TokenContract; - const txHashPromise = self.approve.sendTransactionAsync(_spender.toLowerCase(), _value, txData); + const txHashPromise = self.approve.sendTransactionAsync(_spender.toLowerCase(), _value, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -331,15 +266,6 @@ export class DummyERC20TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _spender: string, - _value: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).approve.callAsync(_spender, _value, txData); - const txHash = await (this as any).approve.sendTransactionAsync(_spender, _value, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -412,30 +338,6 @@ export class DummyERC20TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('approve(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('approve(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Query the balance of owner @@ -489,43 +391,6 @@ export class DummyERC20TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param _owner The address from which the balance will be retrieved - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(_owner: string): string { - assert.isString('_owner', _owner); - const self = (this as any) as DummyERC20TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('balanceOf(address)', [_owner.toLowerCase()]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('balanceOf(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('balanceOf(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public decimals = { /** @@ -569,41 +434,6 @@ export class DummyERC20TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as DummyERC20TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decimals()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('decimals()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('decimals()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Mints new tokens for sender @@ -616,7 +446,11 @@ export class DummyERC20TokenContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(_value: BigNumber, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + _value: BigNumber, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isBigNumber('_value', _value); const self = (this as any) as DummyERC20TokenContract; const encodedData = self._strictEncodeArguments('mint(uint256)', [_value]); @@ -632,6 +466,10 @@ export class DummyERC20TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.mint.callAsync(_value, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -646,20 +484,19 @@ export class DummyERC20TokenContract extends BaseContract { awaitTransactionSuccessAsync( _value: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isBigNumber('_value', _value); const self = (this as any) as DummyERC20TokenContract; - const txHashPromise = self.mint.sendTransactionAsync(_value, txData); + const txHashPromise = self.mint.sendTransactionAsync(_value, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -689,14 +526,6 @@ export class DummyERC20TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _value: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).mint.callAsync(_value, txData); - const txHash = await (this as any).mint.sendTransactionAsync(_value, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -753,30 +582,6 @@ export class DummyERC20TokenContract extends BaseContract { const abiEncodedTransactionData = self._strictEncodeArguments('mint(uint256)', [_value]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [BigNumber] { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('mint(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('mint(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public name = { /** @@ -820,41 +625,6 @@ export class DummyERC20TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as DummyERC20TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('name()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('name()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('name()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public owner = { /** @@ -898,41 +668,6 @@ export class DummyERC20TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as DummyERC20TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('owner()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('owner()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('owner()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Sets the balance of target address @@ -950,6 +685,7 @@ export class DummyERC20TokenContract extends BaseContract { _target: string, _value: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_target', _target); assert.isBigNumber('_value', _value); @@ -970,6 +706,10 @@ export class DummyERC20TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.setBalance.callAsync(_target, _value, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -986,21 +726,20 @@ export class DummyERC20TokenContract extends BaseContract { _target: string, _value: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_target', _target); assert.isBigNumber('_value', _value); const self = (this as any) as DummyERC20TokenContract; - const txHashPromise = self.setBalance.sendTransactionAsync(_target.toLowerCase(), _value, txData); + const txHashPromise = self.setBalance.sendTransactionAsync(_target.toLowerCase(), _value, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1039,15 +778,6 @@ export class DummyERC20TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _target: string, - _value: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).setBalance.callAsync(_target, _value, txData); - const txHash = await (this as any).setBalance.sendTransactionAsync(_target, _value, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1119,30 +849,6 @@ export class DummyERC20TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, BigNumber] { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('setBalance(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('setBalance(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public symbol = { /** @@ -1186,41 +892,6 @@ export class DummyERC20TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as DummyERC20TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('symbol()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('symbol()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('symbol()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Query total supply of token @@ -1268,41 +939,6 @@ export class DummyERC20TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as DummyERC20TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('totalSupply()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('totalSupply()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('totalSupply()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * send `value` token to `to` from `msg.sender` @@ -1320,6 +956,7 @@ export class DummyERC20TokenContract extends BaseContract { _to: string, _value: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_to', _to); assert.isBigNumber('_value', _value); @@ -1337,6 +974,10 @@ export class DummyERC20TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transfer.callAsync(_to, _value, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1353,21 +994,20 @@ export class DummyERC20TokenContract extends BaseContract { _to: string, _value: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_to', _to); assert.isBigNumber('_value', _value); const self = (this as any) as DummyERC20TokenContract; - const txHashPromise = self.transfer.sendTransactionAsync(_to.toLowerCase(), _value, txData); + const txHashPromise = self.transfer.sendTransactionAsync(_to.toLowerCase(), _value, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1399,15 +1039,6 @@ export class DummyERC20TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _to: string, - _value: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).transfer.callAsync(_to, _value, txData); - const txHash = await (this as any).transfer.sendTransactionAsync(_to, _value, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1477,30 +1108,6 @@ export class DummyERC20TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('transfer(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('transfer(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * ERC20 transferFrom, modified such that an allowance of MAX_UINT represents an unlimited allowance. See https://github.com/ethereum/EIPs/issues/717 @@ -1520,6 +1127,7 @@ export class DummyERC20TokenContract extends BaseContract { _to: string, _value: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_from', _from); assert.isString('_to', _to); @@ -1542,6 +1150,10 @@ export class DummyERC20TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transferFrom.callAsync(_from, _to, _value, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1560,8 +1172,7 @@ export class DummyERC20TokenContract extends BaseContract { _to: string, _value: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_from', _from); assert.isString('_to', _to); @@ -1572,6 +1183,7 @@ export class DummyERC20TokenContract extends BaseContract { _to.toLowerCase(), _value, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -1579,8 +1191,8 @@ export class DummyERC20TokenContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1623,16 +1235,6 @@ export class DummyERC20TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _from: string, - _to: string, - _value: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).transferFrom.callAsync(_from, _to, _value, txData); - const txHash = await (this as any).transferFrom.sendTransactionAsync(_from, _to, _value, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1712,30 +1314,6 @@ export class DummyERC20TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public transferOwnership = { /** @@ -1744,7 +1322,11 @@ export class DummyERC20TokenContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(newOwner: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + newOwner: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('newOwner', newOwner); const self = (this as any) as DummyERC20TokenContract; const encodedData = self._strictEncodeArguments('transferOwnership(address)', [newOwner.toLowerCase()]); @@ -1760,6 +1342,10 @@ export class DummyERC20TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transferOwnership.callAsync(newOwner, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1773,20 +1359,19 @@ export class DummyERC20TokenContract extends BaseContract { awaitTransactionSuccessAsync( newOwner: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('newOwner', newOwner); const self = (this as any) as DummyERC20TokenContract; - const txHashPromise = self.transferOwnership.sendTransactionAsync(newOwner.toLowerCase(), txData); + const txHashPromise = self.transferOwnership.sendTransactionAsync(newOwner.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1815,11 +1400,6 @@ export class DummyERC20TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(newOwner: string, txData?: Partial | undefined): Promise { - await (this as any).transferOwnership.callAsync(newOwner, txData); - const txHash = await (this as any).transferOwnership.sendTransactionAsync(newOwner, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1876,30 +1456,6 @@ export class DummyERC20TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('transferOwnership(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as DummyERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('transferOwnership(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; private readonly _subscriptionManager: SubscriptionManager; public static async deployFrom0xArtifactAsync( diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/dummy_erc721_token.ts b/packages/abi-gen-wrappers/src/generated-wrappers/dummy_erc721_token.ts index 5540962892..8e78e37b76 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/dummy_erc721_token.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/dummy_erc721_token.ts @@ -19,7 +19,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -58,8 +64,10 @@ export interface DummyERC721TokenTransferEventArgs extends DecodedLogArgs { // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class DummyERC721TokenContract extends BaseContract { - public static deployedBytecode = - '0x608060405234801561001057600080fd5b50600436106100f55760003560e01c806370a0823111610097578063a22cb46511610066578063a22cb46514610362578063b88d4fde1461039d578063e985e9c51461043a578063f2fde38b14610489576100f5565b806370a08231146102d45780638da5cb5b1461031957806395d89b41146103215780639dc29fac14610329576100f5565b806323b872dd116100d357806323b872dd146101f857806340c10f191461023b57806342842e0e146102745780636352211e146102b7576100f5565b806306fdde03146100fa578063081812fc14610177578063095ea7b3146101bd575b600080fd5b6101026104bc565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561013c578181015183820152602001610124565b50505050905090810190601f1680156101695780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101946004803603602081101561018d57600080fd5b5035610568565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6101f6600480360360408110156101d357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610590565b005b6101f66004803603606081101561020e57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356106b2565b6101f66004803603604081101561025157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610a20565b6101f66004803603606081101561028a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610a2e565b610194600480360360208110156102cd57600080fd5b5035610bc8565b610307600480360360208110156102ea57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610c5f565b60408051918252519081900360200190f35b610194610d0c565b610102610d28565b6101f66004803603604081101561033f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610da1565b6101f66004803603604081101561037857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001351515610db3565b6101f6600480360360808110156103b357600080fd5b73ffffffffffffffffffffffffffffffffffffffff8235811692602081013590911691604082013591908101906080810160608201356401000000008111156103fb57600080fd5b82018360208201111561040d57600080fd5b8035906020019184600183028401116401000000008311171561042f57600080fd5b509092509050610e4c565b6104756004803603604081101561045057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516611017565b604080519115158252519081900360200190f35b6101f66004803603602081101561049f57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611052565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156105605780601f1061053557610100808354040283529160200191610560565b820191906000526020600020905b81548152906001019060200180831161054357829003601f168201915b505050505081565b60009081526002602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b600061059b82610bc8565b90503373ffffffffffffffffffffffffffffffffffffffff821614806105c657506105c68133611017565b61063157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4552433732315f494e56414c49445f53454e4445520000000000000000000000604482015290519081900360640190fd5b60008281526002602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff87811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b73ffffffffffffffffffffffffffffffffffffffff821661073457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4552433732315f5a45524f5f544f5f4144445245535300000000000000000000604482015290519081900360640190fd5b600061073f82610bc8565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146107db57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4552433732315f4f574e45525f4d49534d415443480000000000000000000000604482015290519081900360640190fd5b3360006107e784610568565b90508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16148061082857506108288383611017565b8061085e57508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b6108c957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4552433732315f494e56414c49445f5350454e44455200000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81161561091a57600084815260026020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555b600084815260016020818152604080842080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8b8116919091179091558a168452600390915290912054610984916110ce565b73ffffffffffffffffffffffffffffffffffffffff80881660009081526003602052604080822093909355908716815220546109c19060016110ed565b73ffffffffffffffffffffffffffffffffffffffff808716600081815260036020526040808220949094559251879391928a16917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050505050565b610a2a8282611110565b5050565b610a398383836106b2565b813b8015610bc257604080517f150b7a0200000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8681166024830152604482018590526080606483015260006084830181905292519086169163150b7a029160c480830192602092919082900301818787803b158015610ace57600080fd5b505af1158015610ae2573d6000803e3d6000fd5b505050506040513d6020811015610af857600080fd5b505160405190915080602f61166c8239602f01905060405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610bc057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4552433732315f494e56414c49445f53454c4543544f52000000000000000000604482015290519081900360640190fd5b505b50505050565b60008181526001602052604081205473ffffffffffffffffffffffffffffffffffffffff1680610c5957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4552433732315f5a45524f5f4f574e4552000000000000000000000000000000604482015290519081900360640190fd5b92915050565b600073ffffffffffffffffffffffffffffffffffffffff8216610ce357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4552433732315f5a45524f5f4f574e4552000000000000000000000000000000604482015290519081900360640190fd5b5073ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205490565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b6006805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156105605780601f1061053557610100808354040283529160200191610560565b610da96112e3565b610a2a828261132c565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b610e578585856106b2565b833b801561100f576040517f150b7a02000000000000000000000000000000000000000000000000000000008152336004820181815273ffffffffffffffffffffffffffffffffffffffff89811660248501526044840188905260806064850190815260848501879052600094918a169363150b7a029390928c928b928b928b929060a401848480828437600081840152601f19601f8201169050808301925050509650505050505050602060405180830381600087803b158015610f1b57600080fd5b505af1158015610f2f573d6000803e3d6000fd5b505050506040513d6020811015610f4557600080fd5b505160405190915080602f61166c8239602f01905060405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461100d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4552433732315f494e56414c49445f53454c4543544f52000000000000000000604482015290519081900360640190fd5b505b505050505050565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260046020908152604080832093909416825291909152205460ff1690565b61105a6112e3565b73ffffffffffffffffffffffffffffffffffffffff811661108a57611085611080611501565b611538565b6110cb565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83161790555b50565b6000828211156110e7576110e761108060028585611540565b50900390565b6000828201838110156111095761110961108060008686611540565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff821661119257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4552433732315f5a45524f5f544f5f4144445245535300000000000000000000604482015290519081900360640190fd5b60008181526001602052604090205473ffffffffffffffffffffffffffffffffffffffff16801561122457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4552433732315f4f574e45525f414c52454144595f4558495354530000000000604482015290519081900360640190fd5b600082815260016020818152604080842080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8916908117909155845260039091529091205461128a916110ed565b73ffffffffffffffffffffffffffffffffffffffff84166000818152600360205260408082209390935591518492907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461132a5760005461132a9061108090339073ffffffffffffffffffffffffffffffffffffffff166115df565b565b73ffffffffffffffffffffffffffffffffffffffff82166113ae57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4552433732315f5a45524f5f4f574e45525f4144445245535300000000000000604482015290519081900360640190fd5b60008181526001602052604090205473ffffffffffffffffffffffffffffffffffffffff908116908316811461144557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4552433732315f4f574e45525f4d49534d415443480000000000000000000000604482015290519081900360640190fd5b600082815260016020818152604080842080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905573ffffffffffffffffffffffffffffffffffffffff871684526003909152909120546114a7916110ce565b73ffffffffffffffffffffffffffffffffffffffff8416600081815260036020526040808220939093559151849291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a4505050565b60408051808201909152600481527fe69edc3e00000000000000000000000000000000000000000000000000000000602082015290565b805160208201fd5b606063e946c1bb60e01b8484846040516024018084600381111561156057fe5b60ff1681526020018381526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090509392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044808301919091528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1de45ad1000000000000000000000000000000000000000000000000000000001790529291505056fe6f6e455243373231526563656976656428616464726573732c616464726573732c75696e743235362c627974657329a265627a7a723158207bb3c4b1d40aa051fbb8e4f8230bb310013e75ca9fa97c528018b4c4aba3b92564736f6c634300050c0032'; + /** + * @ignore + */ + public static deployedBytecode: string | undefined; /** * The zero address indicates there is no approved address. * Throws unless `msg.sender` is the current NFT owner, or an authorized @@ -78,6 +86,7 @@ export class DummyERC721TokenContract extends BaseContract { _approved: string, _tokenId: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_approved', _approved); assert.isBigNumber('_tokenId', _tokenId); @@ -98,6 +107,10 @@ export class DummyERC721TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.approve.callAsync(_approved, _tokenId, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -114,21 +127,20 @@ export class DummyERC721TokenContract extends BaseContract { _approved: string, _tokenId: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_approved', _approved); assert.isBigNumber('_tokenId', _tokenId); const self = (this as any) as DummyERC721TokenContract; - const txHashPromise = self.approve.sendTransactionAsync(_approved.toLowerCase(), _tokenId, txData); + const txHashPromise = self.approve.sendTransactionAsync(_approved.toLowerCase(), _tokenId, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -167,15 +179,6 @@ export class DummyERC721TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _approved: string, - _tokenId: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).approve.callAsync(_approved, _tokenId, txData); - const txHash = await (this as any).approve.sendTransactionAsync(_approved, _tokenId, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -247,30 +250,6 @@ export class DummyERC721TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, BigNumber] { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('approve(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('approve(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * NFTs assigned to the zero address are considered invalid, and this @@ -325,43 +304,6 @@ export class DummyERC721TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param _owner An address for whom to query the balance - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(_owner: string): string { - assert.isString('_owner', _owner); - const self = (this as any) as DummyERC721TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('balanceOf(address)', [_owner.toLowerCase()]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('balanceOf(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('balanceOf(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Function to burn a token @@ -380,6 +322,7 @@ export class DummyERC721TokenContract extends BaseContract { _owner: string, _tokenId: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_owner', _owner); assert.isBigNumber('_tokenId', _tokenId); @@ -397,6 +340,10 @@ export class DummyERC721TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.burn.callAsync(_owner, _tokenId, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -413,21 +360,20 @@ export class DummyERC721TokenContract extends BaseContract { _owner: string, _tokenId: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_owner', _owner); assert.isBigNumber('_tokenId', _tokenId); const self = (this as any) as DummyERC721TokenContract; - const txHashPromise = self.burn.sendTransactionAsync(_owner.toLowerCase(), _tokenId, txData); + const txHashPromise = self.burn.sendTransactionAsync(_owner.toLowerCase(), _tokenId, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -463,15 +409,6 @@ export class DummyERC721TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _owner: string, - _tokenId: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).burn.callAsync(_owner, _tokenId, txData); - const txHash = await (this as any).burn.sendTransactionAsync(_owner, _tokenId, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -540,30 +477,6 @@ export class DummyERC721TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, BigNumber] { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('burn(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('burn(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Throws if `_tokenId` is not a valid NFT. @@ -617,43 +530,6 @@ export class DummyERC721TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param _tokenId The NFT to find the approved address for - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(_tokenId: BigNumber): string { - assert.isBigNumber('_tokenId', _tokenId); - const self = (this as any) as DummyERC721TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getApproved(uint256)', [_tokenId]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): BigNumber { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('getApproved(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('getApproved(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public isApprovedForAll = { /** @@ -710,48 +586,6 @@ export class DummyERC721TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param _owner The address that owns the NFTs - * @param _operator The address that acts on behalf of the owner - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(_owner: string, _operator: string): string { - assert.isString('_owner', _owner); - assert.isString('_operator', _operator); - const self = (this as any) as DummyERC721TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('isApprovedForAll(address,address)', [ - _owner.toLowerCase(), - _operator.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('isApprovedForAll(address,address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('isApprovedForAll(address,address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Function to mint a new token @@ -770,6 +604,7 @@ export class DummyERC721TokenContract extends BaseContract { _to: string, _tokenId: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_to', _to); assert.isBigNumber('_tokenId', _tokenId); @@ -787,6 +622,10 @@ export class DummyERC721TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.mint.callAsync(_to, _tokenId, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -803,21 +642,20 @@ export class DummyERC721TokenContract extends BaseContract { _to: string, _tokenId: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_to', _to); assert.isBigNumber('_tokenId', _tokenId); const self = (this as any) as DummyERC721TokenContract; - const txHashPromise = self.mint.sendTransactionAsync(_to.toLowerCase(), _tokenId, txData); + const txHashPromise = self.mint.sendTransactionAsync(_to.toLowerCase(), _tokenId, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -853,15 +691,6 @@ export class DummyERC721TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _to: string, - _tokenId: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).mint.callAsync(_to, _tokenId, txData); - const txHash = await (this as any).mint.sendTransactionAsync(_to, _tokenId, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -930,30 +759,6 @@ export class DummyERC721TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, BigNumber] { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('mint(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('mint(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public name = { /** @@ -997,41 +802,6 @@ export class DummyERC721TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as DummyERC721TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('name()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('name()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('name()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public owner = { /** @@ -1075,41 +845,6 @@ export class DummyERC721TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as DummyERC721TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('owner()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('owner()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('owner()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * NFTs assigned to zero address are considered invalid, and queries @@ -1164,43 +899,6 @@ export class DummyERC721TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param _tokenId The identifier for an NFT - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(_tokenId: BigNumber): string { - assert.isBigNumber('_tokenId', _tokenId); - const self = (this as any) as DummyERC721TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('ownerOf(uint256)', [_tokenId]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): BigNumber { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('ownerOf(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('ownerOf(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * This works identically to the other function with an extra data parameter, @@ -1221,6 +919,7 @@ export class DummyERC721TokenContract extends BaseContract { _to: string, _tokenId: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_from', _from); assert.isString('_to', _to); @@ -1243,6 +942,10 @@ export class DummyERC721TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.safeTransferFrom1.callAsync(_from, _to, _tokenId, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1261,8 +964,7 @@ export class DummyERC721TokenContract extends BaseContract { _to: string, _tokenId: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_from', _from); assert.isString('_to', _to); @@ -1273,6 +975,7 @@ export class DummyERC721TokenContract extends BaseContract { _to.toLowerCase(), _tokenId, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -1280,8 +983,8 @@ export class DummyERC721TokenContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1324,16 +1027,6 @@ export class DummyERC721TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _from: string, - _to: string, - _tokenId: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).safeTransferFrom1.callAsync(_from, _to, _tokenId, txData); - const txHash = await (this as any).safeTransferFrom1.sendTransactionAsync(_from, _to, _tokenId, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1412,30 +1105,6 @@ export class DummyERC721TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, string, BigNumber] { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('safeTransferFrom(address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('safeTransferFrom(address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Throws unless `msg.sender` is the current owner, an authorized @@ -1463,6 +1132,7 @@ export class DummyERC721TokenContract extends BaseContract { _tokenId: BigNumber, _data: string, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_from', _from); assert.isString('_to', _to); @@ -1487,6 +1157,10 @@ export class DummyERC721TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.safeTransferFrom2.callAsync(_from, _to, _tokenId, _data, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1507,8 +1181,7 @@ export class DummyERC721TokenContract extends BaseContract { _tokenId: BigNumber, _data: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_from', _from); assert.isString('_to', _to); @@ -1521,6 +1194,7 @@ export class DummyERC721TokenContract extends BaseContract { _tokenId, _data, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -1528,8 +1202,8 @@ export class DummyERC721TokenContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1576,23 +1250,6 @@ export class DummyERC721TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _from: string, - _to: string, - _tokenId: BigNumber, - _data: string, - txData?: Partial | undefined, - ): Promise { - await (this as any).safeTransferFrom2.callAsync(_from, _to, _tokenId, _data, txData); - const txHash = await (this as any).safeTransferFrom2.sendTransactionAsync( - _from, - _to, - _tokenId, - _data, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1676,30 +1333,6 @@ export class DummyERC721TokenContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, string, BigNumber, string] { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('safeTransferFrom(address,address,uint256,bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, string, BigNumber, string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('safeTransferFrom(address,address,uint256,bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Emits the ApprovalForAll event. The contract MUST allow @@ -1718,6 +1351,7 @@ export class DummyERC721TokenContract extends BaseContract { _operator: string, _approved: boolean, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_operator', _operator); assert.isBoolean('_approved', _approved); @@ -1738,6 +1372,10 @@ export class DummyERC721TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.setApprovalForAll.callAsync(_operator, _approved, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1754,8 +1392,7 @@ export class DummyERC721TokenContract extends BaseContract { _operator: string, _approved: boolean, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_operator', _operator); assert.isBoolean('_approved', _approved); @@ -1764,6 +1401,7 @@ export class DummyERC721TokenContract extends BaseContract { _operator.toLowerCase(), _approved, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -1771,8 +1409,8 @@ export class DummyERC721TokenContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1811,15 +1449,6 @@ export class DummyERC721TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _operator: string, - _approved: boolean, - txData?: Partial | undefined, - ): Promise { - await (this as any).setApprovalForAll.callAsync(_operator, _approved, txData); - const txHash = await (this as any).setApprovalForAll.sendTransactionAsync(_operator, _approved, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1891,30 +1520,6 @@ export class DummyERC721TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, boolean] { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('setApprovalForAll(address,bool)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, boolean]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('setApprovalForAll(address,bool)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public symbol = { /** @@ -1958,41 +1563,6 @@ export class DummyERC721TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as DummyERC721TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('symbol()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('symbol()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('symbol()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Throws unless `msg.sender` is the current owner, an authorized @@ -2015,6 +1585,7 @@ export class DummyERC721TokenContract extends BaseContract { _to: string, _tokenId: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_from', _from); assert.isString('_to', _to); @@ -2037,6 +1608,10 @@ export class DummyERC721TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transferFrom.callAsync(_from, _to, _tokenId, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -2055,8 +1630,7 @@ export class DummyERC721TokenContract extends BaseContract { _to: string, _tokenId: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_from', _from); assert.isString('_to', _to); @@ -2067,6 +1641,7 @@ export class DummyERC721TokenContract extends BaseContract { _to.toLowerCase(), _tokenId, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -2074,8 +1649,8 @@ export class DummyERC721TokenContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -2118,16 +1693,6 @@ export class DummyERC721TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _from: string, - _to: string, - _tokenId: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).transferFrom.callAsync(_from, _to, _tokenId, txData); - const txHash = await (this as any).transferFrom.sendTransactionAsync(_from, _to, _tokenId, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -2206,30 +1771,6 @@ export class DummyERC721TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, string, BigNumber] { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public transferOwnership = { /** @@ -2238,7 +1779,11 @@ export class DummyERC721TokenContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(newOwner: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + newOwner: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('newOwner', newOwner); const self = (this as any) as DummyERC721TokenContract; const encodedData = self._strictEncodeArguments('transferOwnership(address)', [newOwner.toLowerCase()]); @@ -2254,6 +1799,10 @@ export class DummyERC721TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transferOwnership.callAsync(newOwner, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -2267,20 +1816,19 @@ export class DummyERC721TokenContract extends BaseContract { awaitTransactionSuccessAsync( newOwner: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('newOwner', newOwner); const self = (this as any) as DummyERC721TokenContract; - const txHashPromise = self.transferOwnership.sendTransactionAsync(newOwner.toLowerCase(), txData); + const txHashPromise = self.transferOwnership.sendTransactionAsync(newOwner.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -2309,11 +1857,6 @@ export class DummyERC721TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(newOwner: string, txData?: Partial | undefined): Promise { - await (this as any).transferOwnership.callAsync(newOwner, txData); - const txHash = await (this as any).transferOwnership.sendTransactionAsync(newOwner, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -2370,30 +1913,6 @@ export class DummyERC721TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('transferOwnership(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as DummyERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('transferOwnership(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; private readonly _subscriptionManager: SubscriptionManager; public static async deployFrom0xArtifactAsync( diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/dutch_auction.ts b/packages/abi-gen-wrappers/src/generated-wrappers/dutch_auction.ts index c0d8d3fb7c..7111992209 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/dutch_auction.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/dutch_auction.ts @@ -18,7 +18,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -28,6 +34,9 @@ import * as ethers from 'ethers'; // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class DutchAuctionContract extends BaseContract { + /** + * @ignore + */ public static deployedBytecode: string | undefined; /** * Calculates the Auction Details for the given order @@ -56,6 +65,7 @@ export class DutchAuctionContract extends BaseContract { takerAssetData: string; }, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { const self = (this as any) as DutchAuctionContract; const encodedData = self._strictEncodeArguments( @@ -74,6 +84,10 @@ export class DutchAuctionContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.getAuctionDetails.callAsync(order, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -101,19 +115,18 @@ export class DutchAuctionContract extends BaseContract { takerAssetData: string; }, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { const self = (this as any) as DutchAuctionContract; - const txHashPromise = self.getAuctionDetails.sendTransactionAsync(order, txData); + const txHashPromise = self.getAuctionDetails.sendTransactionAsync(order, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -161,27 +174,6 @@ export class DutchAuctionContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - order: { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }, - txData?: Partial | undefined, - ): Promise { - await (this as any).getAuctionDetails.callAsync(order, txData); - const txHash = await (this as any).getAuctionDetails.sendTransactionAsync(order, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -289,78 +281,6 @@ export class DutchAuctionContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - } { - const self = (this as any) as DutchAuctionContract; - const abiEncoder = self._lookupAbiEncoder( - 'getAuctionDetails((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes))', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): { - beginTimeSeconds: BigNumber; - endTimeSeconds: BigNumber; - beginAmount: BigNumber; - endAmount: BigNumber; - currentAmount: BigNumber; - currentTimeSeconds: BigNumber; - } { - const self = (this as any) as DutchAuctionContract; - const abiEncoder = self._lookupAbiEncoder( - 'getAuctionDetails((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes))', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<{ - beginTimeSeconds: BigNumber; - endTimeSeconds: BigNumber; - beginAmount: BigNumber; - endAmount: BigNumber; - currentAmount: BigNumber; - currentTimeSeconds: BigNumber; - }>(returnData); - return abiDecodedReturnData; - }, }; /** * Matches the buy and sell orders at an amount given the following: the current block time, the auction @@ -424,6 +344,7 @@ export class DutchAuctionContract extends BaseContract { buySignature: string, sellSignature: string, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('buySignature', buySignature); assert.isString('sellSignature', sellSignature); @@ -444,6 +365,10 @@ export class DutchAuctionContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.matchOrders.callAsync(buyOrder, sellOrder, buySignature, sellSignature, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -492,8 +417,7 @@ export class DutchAuctionContract extends BaseContract { buySignature: string, sellSignature: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('buySignature', buySignature); assert.isString('sellSignature', sellSignature); @@ -504,6 +428,7 @@ export class DutchAuctionContract extends BaseContract { buySignature, sellSignature, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -511,8 +436,8 @@ export class DutchAuctionContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -583,49 +508,6 @@ export class DutchAuctionContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - buyOrder: { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }, - sellOrder: { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }, - buySignature: string, - sellSignature: string, - txData?: Partial | undefined, - ): Promise { - await (this as any).matchOrders.callAsync(buyOrder, sellOrder, buySignature, sellSignature, txData); - const txHash = await (this as any).matchOrders.sendTransactionAsync( - buyOrder, - sellOrder, - buySignature, - sellSignature, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -795,92 +677,6 @@ export class DutchAuctionContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - } { - const self = (this as any) as DutchAuctionContract; - const abiEncoder = self._lookupAbiEncoder( - 'matchOrders((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes),(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes),bytes,bytes)', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): { - left: { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - }; - right: { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - }; - leftMakerAssetSpreadAmount: BigNumber; - } { - const self = (this as any) as DutchAuctionContract; - const abiEncoder = self._lookupAbiEncoder( - 'matchOrders((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes),(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes),bytes,bytes)', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<{ - left: { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - }; - right: { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - }; - leftMakerAssetSpreadAmount: BigNumber; - }>(returnData); - return abiDecodedReturnData; - }, }; public static async deployFrom0xArtifactAsync( artifact: ContractArtifact | SimpleContractArtifact, diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/erc1155_proxy.ts b/packages/abi-gen-wrappers/src/generated-wrappers/erc1155_proxy.ts index ad2fcd745e..8fe2202022 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/erc1155_proxy.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/erc1155_proxy.ts @@ -19,7 +19,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -48,6 +54,9 @@ export interface ERC1155ProxyAuthorizedAddressRemovedEventArgs extends DecodedLo // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class ERC1155ProxyContract extends BaseContract { + /** + * @ignore + */ public static deployedBytecode = '0x608060405234801561001057600080fd5b50600436106100be5760003560e01c8063a85e59e411610076578063b91816111161005b578063b918161114610285578063d39de6e9146102cc578063f2fde38b14610324576100be565b8063a85e59e4146101b2578063ae25532e14610248576100be565b806370712939116100a7578063707129391461013e5780638da5cb5b146101715780639ad2674414610179576100be565b806342f1181e146100c3578063494503d4146100f8575b600080fd5b6100f6600480360360208110156100d957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610357565b005b6101156004803603602081101561010e57600080fd5b5035610543565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6100f66004803603602081101561015457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610577565b61011561086a565b6100f66004803603604081101561018f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610886565b6100f6600480360360808110156101c857600080fd5b8101906020810181356401000000008111156101e357600080fd5b8201836020820111156101f557600080fd5b8035906020019184600183028401116401000000008311171561021757600080fd5b919350915073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610c37565b610250611138565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b6102b86004803603602081101561029b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611159565b604080519115158252519081900360200190f35b6102d461116e565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156103105781810151838201526020016102f8565b505050509050019250505060405180910390f35b6100f66004803603602081101561033a57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166111dd565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103dd57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604090205460ff161561047257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5441524745545f414c52454144595f415554484f52495a454400000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116600081815260016020819052604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168317905560028054928301815583527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace90910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001684179055513392917f3147867c59d17e8fa9d522465651d44aae0a9e38f902f3475b97e58072f0ed4c91a350565b6002818154811061055057fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105fd57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604090205460ff1661069157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5441524745545f4e4f545f415554484f52495a45440000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b600254811015610823578173ffffffffffffffffffffffffffffffffffffffff166002828154811061070b57fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16141561081b57600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190811061076357fe5b6000918252602090912001546002805473ffffffffffffffffffffffffffffffffffffffff909216918390811061079657fe5b600091825260209091200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01906108159082611407565b50610823565b6001016106dd565b50604051339073ffffffffffffffffffffffffffffffffffffffff8316907f1f32c1b084e2de0713b8fb16bd46bb9df710a3dbeae2f3ca93af46e016dcc6b090600090a350565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff16331461090c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604090205460ff166109a057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5441524745545f4e4f545f415554484f52495a45440000000000000000000000604482015290519081900360640190fd5b6002548110610a1057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e4445585f4f55545f4f465f424f554e445300000000000000000000000000604482015290519081900360640190fd5b8173ffffffffffffffffffffffffffffffffffffffff1660028281548110610a3457fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1614610ac257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f415554484f52495a45445f414444524553535f4d49534d415443480000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101908110610b3d57fe5b6000918252602090912001546002805473ffffffffffffffffffffffffffffffffffffffff9092169183908110610b7057fe5b600091825260209091200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190610bef9082611407565b50604051339073ffffffffffffffffffffffffffffffffffffffff8416907f1f32c1b084e2de0713b8fb16bd46bb9df710a3dbeae2f3ca93af46e016dcc6b090600090a35050565b3360009081526001602052604090205460ff16610cb557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f53454e4445525f4e4f545f415554484f52495a45440000000000000000000000604482015290519081900360640190fd5b60006060806060610d0b60048a8a90508b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092949392505063ffffffff6112c3169050565b8060200190516080811015610d1f57600080fd5b815160208301805160405192949293830192919084640100000000821115610d4657600080fd5b908301906020820185811115610d5b57600080fd5b8251866020820283011164010000000082111715610d7857600080fd5b82525081516020918201928201910280838360005b83811015610da5578181015183820152602001610d8d565b5050505090500160405260200180516040519392919084640100000000821115610dce57600080fd5b908301906020820185811115610de357600080fd5b8251866020820283011164010000000082111715610e0057600080fd5b82525081516020918201928201910280838360005b83811015610e2d578181015183820152602001610e15565b5050505090500160405260200180516040519392919084640100000000821115610e5657600080fd5b908301906020820185811115610e6b57600080fd5b8251640100000000811182820188101715610e8557600080fd5b82525081516020918201929091019080838360005b83811015610eb2578181015183820152602001610e9a565b50505050905090810190601f168015610edf5780820380516001836020036101000a031916815260200191505b506040525050509350935093509350600082519050606081604051908082528060200260200182016040528015610f20578160200160208202803883390190505b50905060005b828114610f6957610f4a858281518110610f3c57fe5b602002602001015189611306565b828281518110610f5657fe5b6020908102919091010152600101610f26565b508573ffffffffffffffffffffffffffffffffffffffff16632eb2c2d68a8a8885886040518663ffffffff1660e01b8152600401808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b8381101561104657818101518382015260200161102e565b50505050905001848103835286818151815260200191508051906020019060200280838360005b8381101561108557818101518382015260200161106d565b50505050905001848103825285818151815260200191508051906020019080838360005b838110156110c15781810151838201526020016110a9565b50505050905090810190601f1680156110ee5780820380516001836020036101000a031916815260200191505b5098505050505050505050600060405180830381600087803b15801561111357600080fd5b505af1158015611127573d6000803e3d6000fd5b505050505050505050505050505050565b6000604051808061144f603091396030019050604051809103902090505b90565b60016020526000908152604090205460ff1681565b606060028054806020026020016040519081016040528092919081815260200182805480156111d357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116111a8575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff16331461126357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116156112c057600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83161790555b50565b6060818311156112e1576112e16112dc60008585611340565b6113df565b83518211156112fa576112fa6112dc6001848751611340565b50819003910190815290565b6000826113155750600061133a565b8282028284828161132257fe5b0414611337576113376112dc600186866113e7565b90505b92915050565b6060632800659560e01b8484846040516024018084600781111561136057fe5b60ff1681526020018381526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090509392505050565b805160208201fd5b606063e946c1bb60e01b8484846040516024018084600381111561136057fe5b81548183558181111561142b5760008381526020902061142b918101908301611430565b505050565b61115691905b8082111561144a5760008155600101611436565b509056fe4552433131353541737365747328616464726573732c75696e743235365b5d2c75696e743235365b5d2c627974657329a265627a7a72315820be5e6597d38133fd52aac17250498790f106d5d4d0e4ab30d0e854a2db1e2ffe64736f6c634300050c0032'; /** @@ -61,7 +70,11 @@ export class ERC1155ProxyContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(target: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + target: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('target', target); const self = (this as any) as ERC1155ProxyContract; const encodedData = self._strictEncodeArguments('addAuthorizedAddress(address)', [target.toLowerCase()]); @@ -77,6 +90,10 @@ export class ERC1155ProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.addAuthorizedAddress.callAsync(target, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -91,20 +108,19 @@ export class ERC1155ProxyContract extends BaseContract { awaitTransactionSuccessAsync( target: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('target', target); const self = (this as any) as ERC1155ProxyContract; - const txHashPromise = self.addAuthorizedAddress.sendTransactionAsync(target.toLowerCase(), txData); + const txHashPromise = self.addAuthorizedAddress.sendTransactionAsync(target.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -134,11 +150,6 @@ export class ERC1155ProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(target: string, txData?: Partial | undefined): Promise { - await (this as any).addAuthorizedAddress.callAsync(target, txData); - const txHash = await (this as any).addAuthorizedAddress.sendTransactionAsync(target, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -197,30 +208,6 @@ export class ERC1155ProxyContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('addAuthorizedAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('addAuthorizedAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public authorities = { /** @@ -269,42 +256,6 @@ export class ERC1155ProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: BigNumber): string { - assert.isBigNumber('index_0', index_0); - const self = (this as any) as ERC1155ProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('authorities(uint256)', [index_0]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): BigNumber { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('authorities(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('authorities(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public authorized = { /** @@ -353,44 +304,6 @@ export class ERC1155ProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: string): string { - assert.isString('index_0', index_0); - const self = (this as any) as ERC1155ProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('authorized(address)', [ - index_0.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('authorized(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('authorized(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Gets all authorized addresses. @@ -438,41 +351,6 @@ export class ERC1155ProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ERC1155ProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getAuthorizedAddresses()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('getAuthorizedAddresses()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string[] { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('getAuthorizedAddresses()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Gets the proxy id associated with the proxy address. @@ -499,7 +377,7 @@ export class ERC1155ProxyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -512,41 +390,6 @@ export class ERC1155ProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ERC1155ProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getProxyId()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('getProxyId()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('getProxyId()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public owner = { /** @@ -590,41 +433,6 @@ export class ERC1155ProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ERC1155ProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('owner()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('owner()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('owner()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Removes authorizion of an address. @@ -637,7 +445,11 @@ export class ERC1155ProxyContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(target: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + target: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('target', target); const self = (this as any) as ERC1155ProxyContract; const encodedData = self._strictEncodeArguments('removeAuthorizedAddress(address)', [target.toLowerCase()]); @@ -653,6 +465,10 @@ export class ERC1155ProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.removeAuthorizedAddress.callAsync(target, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -667,20 +483,19 @@ export class ERC1155ProxyContract extends BaseContract { awaitTransactionSuccessAsync( target: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('target', target); const self = (this as any) as ERC1155ProxyContract; - const txHashPromise = self.removeAuthorizedAddress.sendTransactionAsync(target.toLowerCase(), txData); + const txHashPromise = self.removeAuthorizedAddress.sendTransactionAsync(target.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -710,11 +525,6 @@ export class ERC1155ProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(target: string, txData?: Partial | undefined): Promise { - await (this as any).removeAuthorizedAddress.callAsync(target, txData); - const txHash = await (this as any).removeAuthorizedAddress.sendTransactionAsync(target, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -773,30 +583,6 @@ export class ERC1155ProxyContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Removes authorizion of an address. @@ -814,6 +600,7 @@ export class ERC1155ProxyContract extends BaseContract { target: string, index: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('target', target); assert.isBigNumber('index', index); @@ -834,6 +621,10 @@ export class ERC1155ProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.removeAuthorizedAddressAtIndex.callAsync(target, index, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -850,8 +641,7 @@ export class ERC1155ProxyContract extends BaseContract { target: string, index: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('target', target); assert.isBigNumber('index', index); @@ -860,6 +650,7 @@ export class ERC1155ProxyContract extends BaseContract { target.toLowerCase(), index, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -867,8 +658,8 @@ export class ERC1155ProxyContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -907,19 +698,6 @@ export class ERC1155ProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - target: string, - index: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).removeAuthorizedAddressAtIndex.callAsync(target, index, txData); - const txHash = await (this as any).removeAuthorizedAddressAtIndex.sendTransactionAsync( - target, - index, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -991,30 +769,6 @@ export class ERC1155ProxyContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, BigNumber] { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddressAtIndex(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddressAtIndex(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Transfers batch of ERC1155 assets. Either succeeds or throws. @@ -1038,6 +792,7 @@ export class ERC1155ProxyContract extends BaseContract { to: string, amount: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('assetData', assetData); assert.isString('from', from); @@ -1062,6 +817,10 @@ export class ERC1155ProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transferFrom.callAsync(assetData, from, to, amount, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1084,8 +843,7 @@ export class ERC1155ProxyContract extends BaseContract { to: string, amount: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('assetData', assetData); assert.isString('from', from); @@ -1098,6 +856,7 @@ export class ERC1155ProxyContract extends BaseContract { to.toLowerCase(), amount, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -1105,8 +864,8 @@ export class ERC1155ProxyContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1155,17 +914,6 @@ export class ERC1155ProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - assetData: string, - from: string, - to: string, - amount: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).transferFrom.callAsync(assetData, from, to, amount, txData); - const txHash = await (this as any).transferFrom.sendTransactionAsync(assetData, from, to, amount, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1253,30 +1001,6 @@ export class ERC1155ProxyContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, string, string, BigNumber] { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(bytes,address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, string, string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(bytes,address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public transferOwnership = { /** @@ -1285,7 +1009,11 @@ export class ERC1155ProxyContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(newOwner: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + newOwner: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('newOwner', newOwner); const self = (this as any) as ERC1155ProxyContract; const encodedData = self._strictEncodeArguments('transferOwnership(address)', [newOwner.toLowerCase()]); @@ -1301,6 +1029,10 @@ export class ERC1155ProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transferOwnership.callAsync(newOwner, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1314,20 +1046,19 @@ export class ERC1155ProxyContract extends BaseContract { awaitTransactionSuccessAsync( newOwner: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('newOwner', newOwner); const self = (this as any) as ERC1155ProxyContract; - const txHashPromise = self.transferOwnership.sendTransactionAsync(newOwner.toLowerCase(), txData); + const txHashPromise = self.transferOwnership.sendTransactionAsync(newOwner.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1356,11 +1087,6 @@ export class ERC1155ProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(newOwner: string, txData?: Partial | undefined): Promise { - await (this as any).transferOwnership.callAsync(newOwner, txData); - const txHash = await (this as any).transferOwnership.sendTransactionAsync(newOwner, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1417,30 +1143,6 @@ export class ERC1155ProxyContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('transferOwnership(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC1155ProxyContract; - const abiEncoder = self._lookupAbiEncoder('transferOwnership(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; private readonly _subscriptionManager: SubscriptionManager; public static async deployFrom0xArtifactAsync( diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/erc20_proxy.ts b/packages/abi-gen-wrappers/src/generated-wrappers/erc20_proxy.ts index f50041fe22..59ae25dd46 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/erc20_proxy.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/erc20_proxy.ts @@ -19,7 +19,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -48,6 +54,9 @@ export interface ERC20ProxyAuthorizedAddressRemovedEventArgs extends DecodedLogA // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class ERC20ProxyContract extends BaseContract { + /** + * @ignore + */ public static deployedBytecode = '0x608060405234801561001057600080fd5b50600436106100a35760003560e01c80639ad2674411610076578063b91816111161005b578063b918161114610374578063d39de6e9146103bb578063f2fde38b14610413576100a3565b80639ad26744146102fe578063ae25532e14610337576100a3565b806342f1181e14610248578063494503d41461027d57806370712939146102c35780638da5cb5b146102f6575b7fffffffff00000000000000000000000000000000000000000000000000000000600035167fa85e59e40000000000000000000000000000000000000000000000000000000081141561024257604080513381526001602082015290812054610177577f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c1553454e4445525f4e4f545f415554484f52495a454400000000000000604052600060605260646000fd5b50602860043501357f23b872dd0000000000000000000000000000000000000000000000000000000060005260606024600437602060006064600080855af1600080511160203d14163d15178116905080156101cf57005b50507f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c0f5452414e534645525f4641494c454400000000000000000000000000604052600060605260646000fd5b50600080fd5b61027b6004803603602081101561025e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610446565b005b61029a6004803603602081101561029357600080fd5b5035610632565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61027b600480360360208110156102d957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610666565b61029a610959565b61027b6004803603604081101561031457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610975565b61033f610d26565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b6103a76004803603602081101561038a57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610d5c565b604080519115158252519081900360200190f35b6103c3610d71565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156103ff5781810151838201526020016103e7565b505050509050019250505060405180910390f35b61027b6004803603602081101561042957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610de0565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104cc57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604090205460ff161561056157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5441524745545f414c52454144595f415554484f52495a454400000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116600081815260016020819052604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168317905560028054928301815583527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace90910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001684179055513392917f3147867c59d17e8fa9d522465651d44aae0a9e38f902f3475b97e58072f0ed4c91a350565b6002818154811061063f57fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106ec57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604090205460ff1661078057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5441524745545f4e4f545f415554484f52495a45440000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b600254811015610912578173ffffffffffffffffffffffffffffffffffffffff16600282815481106107fa57fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16141561090a57600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190811061085257fe5b6000918252602090912001546002805473ffffffffffffffffffffffffffffffffffffffff909216918390811061088557fe5b600091825260209091200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01906109049082610ec6565b50610912565b6001016107cc565b50604051339073ffffffffffffffffffffffffffffffffffffffff8316907f1f32c1b084e2de0713b8fb16bd46bb9df710a3dbeae2f3ca93af46e016dcc6b090600090a350565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109fb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604090205460ff16610a8f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5441524745545f4e4f545f415554484f52495a45440000000000000000000000604482015290519081900360640190fd5b6002548110610aff57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e4445585f4f55545f4f465f424f554e445300000000000000000000000000604482015290519081900360640190fd5b8173ffffffffffffffffffffffffffffffffffffffff1660028281548110610b2357fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1614610bb157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f415554484f52495a45445f414444524553535f4d49534d415443480000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101908110610c2c57fe5b6000918252602090912001546002805473ffffffffffffffffffffffffffffffffffffffff9092169183908110610c5f57fe5b600091825260209091200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190610cde9082610ec6565b50604051339073ffffffffffffffffffffffffffffffffffffffff8416907f1f32c1b084e2de0713b8fb16bd46bb9df710a3dbeae2f3ca93af46e016dcc6b090600090a35050565b604080517f4552433230546f6b656e28616464726573732900000000000000000000000000815290519081900360130190205b90565b60016020526000908152604090205460ff1681565b60606002805480602002602001604051908101604052809291908181526020018280548015610dd657602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610dab575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e6657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811615610ec357600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83161790555b50565b815481835581811115610eea57600083815260209020610eea918101908301610eef565b505050565b610d5991905b80821115610f095760008155600101610ef5565b509056fea265627a7a72315820cb3312567959522bd12ea03b9812cab2bace85fe5f172b3ae8014b3eacc85fa864736f6c634300050b0032'; /** @@ -61,7 +70,11 @@ export class ERC20ProxyContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(target: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + target: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('target', target); const self = (this as any) as ERC20ProxyContract; const encodedData = self._strictEncodeArguments('addAuthorizedAddress(address)', [target.toLowerCase()]); @@ -77,6 +90,10 @@ export class ERC20ProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.addAuthorizedAddress.callAsync(target, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -91,20 +108,19 @@ export class ERC20ProxyContract extends BaseContract { awaitTransactionSuccessAsync( target: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('target', target); const self = (this as any) as ERC20ProxyContract; - const txHashPromise = self.addAuthorizedAddress.sendTransactionAsync(target.toLowerCase(), txData); + const txHashPromise = self.addAuthorizedAddress.sendTransactionAsync(target.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -134,11 +150,6 @@ export class ERC20ProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(target: string, txData?: Partial | undefined): Promise { - await (this as any).addAuthorizedAddress.callAsync(target, txData); - const txHash = await (this as any).addAuthorizedAddress.sendTransactionAsync(target, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -197,30 +208,6 @@ export class ERC20ProxyContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('addAuthorizedAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('addAuthorizedAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public authorities = { /** @@ -269,42 +256,6 @@ export class ERC20ProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: BigNumber): string { - assert.isBigNumber('index_0', index_0); - const self = (this as any) as ERC20ProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('authorities(uint256)', [index_0]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): BigNumber { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('authorities(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('authorities(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Removes authorizion of an address. @@ -317,7 +268,11 @@ export class ERC20ProxyContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(target: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + target: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('target', target); const self = (this as any) as ERC20ProxyContract; const encodedData = self._strictEncodeArguments('removeAuthorizedAddress(address)', [target.toLowerCase()]); @@ -333,6 +288,10 @@ export class ERC20ProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.removeAuthorizedAddress.callAsync(target, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -347,20 +306,19 @@ export class ERC20ProxyContract extends BaseContract { awaitTransactionSuccessAsync( target: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('target', target); const self = (this as any) as ERC20ProxyContract; - const txHashPromise = self.removeAuthorizedAddress.sendTransactionAsync(target.toLowerCase(), txData); + const txHashPromise = self.removeAuthorizedAddress.sendTransactionAsync(target.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -390,11 +348,6 @@ export class ERC20ProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(target: string, txData?: Partial | undefined): Promise { - await (this as any).removeAuthorizedAddress.callAsync(target, txData); - const txHash = await (this as any).removeAuthorizedAddress.sendTransactionAsync(target, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -453,30 +406,6 @@ export class ERC20ProxyContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public owner = { /** @@ -520,41 +449,6 @@ export class ERC20ProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ERC20ProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('owner()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('owner()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('owner()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Removes authorizion of an address. @@ -572,6 +466,7 @@ export class ERC20ProxyContract extends BaseContract { target: string, index: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('target', target); assert.isBigNumber('index', index); @@ -592,6 +487,10 @@ export class ERC20ProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.removeAuthorizedAddressAtIndex.callAsync(target, index, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -608,8 +507,7 @@ export class ERC20ProxyContract extends BaseContract { target: string, index: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('target', target); assert.isBigNumber('index', index); @@ -618,6 +516,7 @@ export class ERC20ProxyContract extends BaseContract { target.toLowerCase(), index, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -625,8 +524,8 @@ export class ERC20ProxyContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -665,19 +564,6 @@ export class ERC20ProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - target: string, - index: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).removeAuthorizedAddressAtIndex.callAsync(target, index, txData); - const txHash = await (this as any).removeAuthorizedAddressAtIndex.sendTransactionAsync( - target, - index, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -749,30 +635,6 @@ export class ERC20ProxyContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, BigNumber] { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddressAtIndex(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddressAtIndex(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Gets the proxy id associated with the proxy address. @@ -799,7 +661,7 @@ export class ERC20ProxyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -812,41 +674,6 @@ export class ERC20ProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ERC20ProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getProxyId()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('getProxyId()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('getProxyId()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public authorized = { /** @@ -895,44 +722,6 @@ export class ERC20ProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: string): string { - assert.isString('index_0', index_0); - const self = (this as any) as ERC20ProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('authorized(address)', [ - index_0.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('authorized(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('authorized(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Gets all authorized addresses. @@ -980,41 +769,6 @@ export class ERC20ProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ERC20ProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getAuthorizedAddresses()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('getAuthorizedAddresses()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string[] { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('getAuthorizedAddresses()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public transferOwnership = { /** @@ -1023,7 +777,11 @@ export class ERC20ProxyContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(newOwner: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + newOwner: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('newOwner', newOwner); const self = (this as any) as ERC20ProxyContract; const encodedData = self._strictEncodeArguments('transferOwnership(address)', [newOwner.toLowerCase()]); @@ -1039,6 +797,10 @@ export class ERC20ProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transferOwnership.callAsync(newOwner, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1052,20 +814,19 @@ export class ERC20ProxyContract extends BaseContract { awaitTransactionSuccessAsync( newOwner: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('newOwner', newOwner); const self = (this as any) as ERC20ProxyContract; - const txHashPromise = self.transferOwnership.sendTransactionAsync(newOwner.toLowerCase(), txData); + const txHashPromise = self.transferOwnership.sendTransactionAsync(newOwner.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1094,11 +855,6 @@ export class ERC20ProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(newOwner: string, txData?: Partial | undefined): Promise { - await (this as any).transferOwnership.callAsync(newOwner, txData); - const txHash = await (this as any).transferOwnership.sendTransactionAsync(newOwner, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1155,30 +911,6 @@ export class ERC20ProxyContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('transferOwnership(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC20ProxyContract; - const abiEncoder = self._lookupAbiEncoder('transferOwnership(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; private readonly _subscriptionManager: SubscriptionManager; public static async deployFrom0xArtifactAsync( diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/erc20_token.ts b/packages/abi-gen-wrappers/src/generated-wrappers/erc20_token.ts index 7ce2e25780..1cc9c8e0d0 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/erc20_token.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/erc20_token.ts @@ -19,7 +19,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -48,8 +54,10 @@ export interface ERC20TokenApprovalEventArgs extends DecodedLogArgs { // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class ERC20TokenContract extends BaseContract { - public static deployedBytecode = - '0x608060405234801561001057600080fd5b50600436106100725760003560e01c806370a082311161005057806370a0823114610121578063a9059cbb14610154578063dd62ed3e1461018d57610072565b8063095ea7b31461007757806318160ddd146100c457806323b872dd146100de575b600080fd5b6100b06004803603604081101561008d57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356101c8565b604080519115158252519081900360200190f35b6100cc61023b565b60408051918252519081900360200190f35b6100b0600480360360608110156100f457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610241565b6100cc6004803603602081101561013757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661049d565b6100b06004803603604081101561016a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356104c5565b6100cc600480360360408110156101a357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516610652565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b60025490565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260408120548211156102d557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f45524332305f494e53554646494349454e545f42414c414e4345000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8416600090815260016020908152604080832033845290915290205482111561037457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f45524332305f494e53554646494349454e545f414c4c4f57414e434500000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040902054828101101561040a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f55494e543235365f4f564552464c4f5700000000000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff80841660008181526020818152604080832080548801905593881680835284832080548890039055600182528483203384528252918490208054879003905583518681529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35060019392505050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b3360009081526020819052604081205482111561054357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f45524332305f494e53554646494349454e545f42414c414e4345000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205482810110156105d957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f55494e543235365f4f564552464c4f5700000000000000000000000000000000604482015290519081900360640190fd5b336000818152602081815260408083208054879003905573ffffffffffffffffffffffffffffffffffffffff871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350600192915050565b73ffffffffffffffffffffffffffffffffffffffff91821660009081526001602090815260408083209390941682529190915220549056fea265627a7a723158205713efa92f66e67a8d01b80af8500df66bd6e9862dcf791e587181109d8ab0c464736f6c634300050b0032'; + /** + * @ignore + */ + public static deployedBytecode: string | undefined; /** * `msg.sender` approves `_spender` to spend `_value` tokens */ @@ -66,6 +74,7 @@ export class ERC20TokenContract extends BaseContract { _spender: string, _value: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_spender', _spender); assert.isBigNumber('_value', _value); @@ -86,6 +95,10 @@ export class ERC20TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.approve.callAsync(_spender, _value, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -102,21 +115,20 @@ export class ERC20TokenContract extends BaseContract { _spender: string, _value: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_spender', _spender); assert.isBigNumber('_value', _value); const self = (this as any) as ERC20TokenContract; - const txHashPromise = self.approve.sendTransactionAsync(_spender.toLowerCase(), _value, txData); + const txHashPromise = self.approve.sendTransactionAsync(_spender.toLowerCase(), _value, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -155,15 +167,6 @@ export class ERC20TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _spender: string, - _value: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).approve.callAsync(_spender, _value, txData); - const txHash = await (this as any).approve.sendTransactionAsync(_spender, _value, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -236,30 +239,6 @@ export class ERC20TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('approve(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as ERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('approve(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Query total supply of token @@ -307,41 +286,6 @@ export class ERC20TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ERC20TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('totalSupply()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('totalSupply()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as ERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('totalSupply()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * send `value` token to `to` from `from` on the condition it is approved by `from` @@ -361,6 +305,7 @@ export class ERC20TokenContract extends BaseContract { _to: string, _value: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_from', _from); assert.isString('_to', _to); @@ -383,6 +328,10 @@ export class ERC20TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transferFrom.callAsync(_from, _to, _value, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -401,8 +350,7 @@ export class ERC20TokenContract extends BaseContract { _to: string, _value: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_from', _from); assert.isString('_to', _to); @@ -413,6 +361,7 @@ export class ERC20TokenContract extends BaseContract { _to.toLowerCase(), _value, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -420,8 +369,8 @@ export class ERC20TokenContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -464,16 +413,6 @@ export class ERC20TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _from: string, - _to: string, - _value: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).transferFrom.callAsync(_from, _to, _value, txData); - const txHash = await (this as any).transferFrom.sendTransactionAsync(_from, _to, _value, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -553,30 +492,6 @@ export class ERC20TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as ERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Query the balance of owner @@ -630,43 +545,6 @@ export class ERC20TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param _owner The address from which the balance will be retrieved - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(_owner: string): string { - assert.isString('_owner', _owner); - const self = (this as any) as ERC20TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('balanceOf(address)', [_owner.toLowerCase()]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('balanceOf(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as ERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('balanceOf(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * send `value` token to `to` from `msg.sender` @@ -684,6 +562,7 @@ export class ERC20TokenContract extends BaseContract { _to: string, _value: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_to', _to); assert.isBigNumber('_value', _value); @@ -701,6 +580,10 @@ export class ERC20TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transfer.callAsync(_to, _value, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -717,21 +600,20 @@ export class ERC20TokenContract extends BaseContract { _to: string, _value: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_to', _to); assert.isBigNumber('_value', _value); const self = (this as any) as ERC20TokenContract; - const txHashPromise = self.transfer.sendTransactionAsync(_to.toLowerCase(), _value, txData); + const txHashPromise = self.transfer.sendTransactionAsync(_to.toLowerCase(), _value, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -763,15 +645,6 @@ export class ERC20TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _to: string, - _value: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).transfer.callAsync(_to, _value, txData); - const txHash = await (this as any).transfer.sendTransactionAsync(_to, _value, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -841,30 +714,6 @@ export class ERC20TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('transfer(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as ERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('transfer(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public allowance = { /** @@ -921,48 +770,6 @@ export class ERC20TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param _owner The address of the account owning tokens - * @param _spender The address of the account able to transfer the tokens - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(_owner: string, _spender: string): string { - assert.isString('_owner', _owner); - assert.isString('_spender', _spender); - const self = (this as any) as ERC20TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('allowance(address,address)', [ - _owner.toLowerCase(), - _spender.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('allowance(address,address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as ERC20TokenContract; - const abiEncoder = self._lookupAbiEncoder('allowance(address,address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; private readonly _subscriptionManager: SubscriptionManager; public static async deployFrom0xArtifactAsync( diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/erc721_proxy.ts b/packages/abi-gen-wrappers/src/generated-wrappers/erc721_proxy.ts index c93e5df751..9f3d13bc8a 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/erc721_proxy.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/erc721_proxy.ts @@ -19,7 +19,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -48,6 +54,9 @@ export interface ERC721ProxyAuthorizedAddressRemovedEventArgs extends DecodedLog // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class ERC721ProxyContract extends BaseContract { + /** + * @ignore + */ public static deployedBytecode = '0x608060405234801561001057600080fd5b50600436106100a35760003560e01c80639ad2674411610076578063b91816111161005b578063b9181611146103ea578063d39de6e914610431578063f2fde38b14610489576100a3565b80639ad2674414610374578063ae25532e146103ad576100a3565b806342f1181e146102be578063494503d4146102f357806370712939146103395780638da5cb5b1461036c575b7fffffffff00000000000000000000000000000000000000000000000000000000600035167fa85e59e4000000000000000000000000000000000000000000000000000000008114156102b857604080513381526001602082015290812054610177577f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c1553454e4445525f4e4f545f415554484f52495a454400000000000000604052600060605260646000fd5b50600160643503156101f4577f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c0e494e56414c49445f414d4f554e540000000000000000000000000000604052600060605260646000fd5b7f23b872dd000000000000000000000000000000000000000000000000000000006000526040602460043760043560206048820160443760288101356000806064600080855af1915050801561024657005b507f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c0f5452414e534645525f4641494c454400000000000000000000000000604052600060605260646000fd5b50600080fd5b6102f1600480360360208110156102d457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166104bc565b005b6103106004803603602081101561030957600080fd5b50356106a8565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6102f16004803603602081101561034f57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166106dc565b6103106109cf565b6102f16004803603604081101561038a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356109eb565b6103b5610d9c565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b61041d6004803603602081101561040057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610dd2565b604080519115158252519081900360200190f35b610439610de7565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561047557818101518382015260200161045d565b505050509050019250505060405180910390f35b6102f16004803603602081101561049f57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610e56565b60005473ffffffffffffffffffffffffffffffffffffffff16331461054257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604090205460ff16156105d757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5441524745545f414c52454144595f415554484f52495a454400000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116600081815260016020819052604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168317905560028054928301815583527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace90910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001684179055513392917f3147867c59d17e8fa9d522465651d44aae0a9e38f902f3475b97e58072f0ed4c91a350565b600281815481106106b557fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60005473ffffffffffffffffffffffffffffffffffffffff16331461076257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604090205460ff166107f657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5441524745545f4e4f545f415554484f52495a45440000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116600090815260016020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b600254811015610988578173ffffffffffffffffffffffffffffffffffffffff166002828154811061087057fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16141561098057600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81019081106108c857fe5b6000918252602090912001546002805473ffffffffffffffffffffffffffffffffffffffff90921691839081106108fb57fe5b600091825260209091200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019061097a9082610f3c565b50610988565b600101610842565b50604051339073ffffffffffffffffffffffffffffffffffffffff8316907f1f32c1b084e2de0713b8fb16bd46bb9df710a3dbeae2f3ca93af46e016dcc6b090600090a350565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a7157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604090205460ff16610b0557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5441524745545f4e4f545f415554484f52495a45440000000000000000000000604482015290519081900360640190fd5b6002548110610b7557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e4445585f4f55545f4f465f424f554e445300000000000000000000000000604482015290519081900360640190fd5b8173ffffffffffffffffffffffffffffffffffffffff1660028281548110610b9957fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1614610c2757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f415554484f52495a45445f414444524553535f4d49534d415443480000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101908110610ca257fe5b6000918252602090912001546002805473ffffffffffffffffffffffffffffffffffffffff9092169183908110610cd557fe5b600091825260209091200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190610d549082610f3c565b50604051339073ffffffffffffffffffffffffffffffffffffffff8416907f1f32c1b084e2de0713b8fb16bd46bb9df710a3dbeae2f3ca93af46e016dcc6b090600090a35050565b604080517f455243373231546f6b656e28616464726573732c75696e7432353629000000008152905190819003601c0190205b90565b60016020526000908152604090205460ff1681565b60606002805480602002602001604051908101604052809291908181526020018280548015610e4c57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610e21575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610edc57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811615610f3957600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83161790555b50565b815481835581811115610f6057600083815260209020610f60918101908301610f65565b505050565b610dcf91905b80821115610f7f5760008155600101610f6b565b509056fea265627a7a723158201e53a891f6df3931041b820f71387e9eecd97f7ea0d346c54fab37668bd022ec64736f6c634300050b0032'; /** @@ -61,7 +70,11 @@ export class ERC721ProxyContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(target: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + target: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('target', target); const self = (this as any) as ERC721ProxyContract; const encodedData = self._strictEncodeArguments('addAuthorizedAddress(address)', [target.toLowerCase()]); @@ -77,6 +90,10 @@ export class ERC721ProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.addAuthorizedAddress.callAsync(target, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -91,20 +108,19 @@ export class ERC721ProxyContract extends BaseContract { awaitTransactionSuccessAsync( target: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('target', target); const self = (this as any) as ERC721ProxyContract; - const txHashPromise = self.addAuthorizedAddress.sendTransactionAsync(target.toLowerCase(), txData); + const txHashPromise = self.addAuthorizedAddress.sendTransactionAsync(target.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -134,11 +150,6 @@ export class ERC721ProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(target: string, txData?: Partial | undefined): Promise { - await (this as any).addAuthorizedAddress.callAsync(target, txData); - const txHash = await (this as any).addAuthorizedAddress.sendTransactionAsync(target, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -197,30 +208,6 @@ export class ERC721ProxyContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('addAuthorizedAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('addAuthorizedAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public authorities = { /** @@ -269,42 +256,6 @@ export class ERC721ProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: BigNumber): string { - assert.isBigNumber('index_0', index_0); - const self = (this as any) as ERC721ProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('authorities(uint256)', [index_0]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): BigNumber { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('authorities(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('authorities(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Removes authorizion of an address. @@ -317,7 +268,11 @@ export class ERC721ProxyContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(target: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + target: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('target', target); const self = (this as any) as ERC721ProxyContract; const encodedData = self._strictEncodeArguments('removeAuthorizedAddress(address)', [target.toLowerCase()]); @@ -333,6 +288,10 @@ export class ERC721ProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.removeAuthorizedAddress.callAsync(target, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -347,20 +306,19 @@ export class ERC721ProxyContract extends BaseContract { awaitTransactionSuccessAsync( target: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('target', target); const self = (this as any) as ERC721ProxyContract; - const txHashPromise = self.removeAuthorizedAddress.sendTransactionAsync(target.toLowerCase(), txData); + const txHashPromise = self.removeAuthorizedAddress.sendTransactionAsync(target.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -390,11 +348,6 @@ export class ERC721ProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(target: string, txData?: Partial | undefined): Promise { - await (this as any).removeAuthorizedAddress.callAsync(target, txData); - const txHash = await (this as any).removeAuthorizedAddress.sendTransactionAsync(target, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -453,30 +406,6 @@ export class ERC721ProxyContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public owner = { /** @@ -520,41 +449,6 @@ export class ERC721ProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ERC721ProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('owner()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('owner()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('owner()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Removes authorizion of an address. @@ -572,6 +466,7 @@ export class ERC721ProxyContract extends BaseContract { target: string, index: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('target', target); assert.isBigNumber('index', index); @@ -592,6 +487,10 @@ export class ERC721ProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.removeAuthorizedAddressAtIndex.callAsync(target, index, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -608,8 +507,7 @@ export class ERC721ProxyContract extends BaseContract { target: string, index: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('target', target); assert.isBigNumber('index', index); @@ -618,6 +516,7 @@ export class ERC721ProxyContract extends BaseContract { target.toLowerCase(), index, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -625,8 +524,8 @@ export class ERC721ProxyContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -665,19 +564,6 @@ export class ERC721ProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - target: string, - index: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).removeAuthorizedAddressAtIndex.callAsync(target, index, txData); - const txHash = await (this as any).removeAuthorizedAddressAtIndex.sendTransactionAsync( - target, - index, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -749,30 +635,6 @@ export class ERC721ProxyContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, BigNumber] { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddressAtIndex(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddressAtIndex(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Gets the proxy id associated with the proxy address. @@ -799,7 +661,7 @@ export class ERC721ProxyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -812,41 +674,6 @@ export class ERC721ProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ERC721ProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getProxyId()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('getProxyId()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('getProxyId()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public authorized = { /** @@ -895,44 +722,6 @@ export class ERC721ProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: string): string { - assert.isString('index_0', index_0); - const self = (this as any) as ERC721ProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('authorized(address)', [ - index_0.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('authorized(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('authorized(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Gets all authorized addresses. @@ -980,41 +769,6 @@ export class ERC721ProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ERC721ProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getAuthorizedAddresses()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('getAuthorizedAddresses()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string[] { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('getAuthorizedAddresses()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public transferOwnership = { /** @@ -1023,7 +777,11 @@ export class ERC721ProxyContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(newOwner: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + newOwner: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('newOwner', newOwner); const self = (this as any) as ERC721ProxyContract; const encodedData = self._strictEncodeArguments('transferOwnership(address)', [newOwner.toLowerCase()]); @@ -1039,6 +797,10 @@ export class ERC721ProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transferOwnership.callAsync(newOwner, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1052,20 +814,19 @@ export class ERC721ProxyContract extends BaseContract { awaitTransactionSuccessAsync( newOwner: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('newOwner', newOwner); const self = (this as any) as ERC721ProxyContract; - const txHashPromise = self.transferOwnership.sendTransactionAsync(newOwner.toLowerCase(), txData); + const txHashPromise = self.transferOwnership.sendTransactionAsync(newOwner.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1094,11 +855,6 @@ export class ERC721ProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(newOwner: string, txData?: Partial | undefined): Promise { - await (this as any).transferOwnership.callAsync(newOwner, txData); - const txHash = await (this as any).transferOwnership.sendTransactionAsync(newOwner, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1155,30 +911,6 @@ export class ERC721ProxyContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('transferOwnership(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC721ProxyContract; - const abiEncoder = self._lookupAbiEncoder('transferOwnership(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; private readonly _subscriptionManager: SubscriptionManager; public static async deployFrom0xArtifactAsync( diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/erc721_token.ts b/packages/abi-gen-wrappers/src/generated-wrappers/erc721_token.ts index 6609198dec..883ba300c3 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/erc721_token.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/erc721_token.ts @@ -19,7 +19,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -58,8 +64,10 @@ export interface ERC721TokenTransferEventArgs extends DecodedLogArgs { // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class ERC721TokenContract extends BaseContract { - public static deployedBytecode = - '0x608060405234801561001057600080fd5b50600436106100a35760003560e01c80636352211e11610076578063a22cb4651161005b578063a22cb46514610211578063b88d4fde1461024c578063e985e9c5146102e9576100a3565b80636352211e146101af57806370a08231146101cc576100a3565b8063081812fc146100a8578063095ea7b3146100ee57806323b872dd1461012957806342842e0e1461016c575b600080fd5b6100c5600480360360208110156100be57600080fd5b5035610338565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6101276004803603604081101561010457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610360565b005b6101276004803603606081101561013f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610482565b6101276004803603606081101561018257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356107ef565b6100c5600480360360208110156101c557600080fd5b5035610989565b6101ff600480360360208110156101e257600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610a20565b60408051918252519081900360200190f35b6101276004803603604081101561022757600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001351515610acd565b6101276004803603608081101561026257600080fd5b73ffffffffffffffffffffffffffffffffffffffff8235811692602081013590911691604082013591908101906080810160608201356401000000008111156102aa57600080fd5b8201836020820111156102bc57600080fd5b803590602001918460018302840111640100000000831117156102de57600080fd5b509092509050610b66565b610324600480360360408110156102ff57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516610d31565b604080519115158252519081900360200190f35b60009081526001602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b600061036b82610989565b90503373ffffffffffffffffffffffffffffffffffffffff8216148061039657506103968133610d31565b61040157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4552433732315f494e56414c49445f53454e4445520000000000000000000000604482015290519081900360640190fd5b60008281526001602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff87811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b73ffffffffffffffffffffffffffffffffffffffff821661050457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4552433732315f5a45524f5f544f5f4144445245535300000000000000000000604482015290519081900360640190fd5b600061050f82610989565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146105ab57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4552433732315f4f574e45525f4d49534d415443480000000000000000000000604482015290519081900360640190fd5b3360006105b784610338565b90508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614806105f857506105f88383610d31565b8061062e57508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b61069957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4552433732315f494e56414c49445f5350454e44455200000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116156106ea57600084815260016020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555b60008481526020818152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a811691909117909155891683526002909152902054610753906001610d6c565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260205260408082209390935590871681522054610790906001610d90565b73ffffffffffffffffffffffffffffffffffffffff808716600081815260026020526040808220949094559251879391928a16917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050505050565b6107fa838383610482565b813b801561098357604080517f150b7a0200000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8681166024830152604482018590526080606483015260006084830181905292519086169163150b7a029160c480830192602092919082900301818787803b15801561088f57600080fd5b505af11580156108a3573d6000803e3d6000fd5b505050506040513d60208110156108b957600080fd5b505160405190915080602f610e5b8239602f01905060405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461098157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4552433732315f494e56414c49445f53454c4543544f52000000000000000000604482015290519081900360640190fd5b505b50505050565b60008181526020819052604081205473ffffffffffffffffffffffffffffffffffffffff1680610a1a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4552433732315f5a45524f5f4f574e4552000000000000000000000000000000604482015290519081900360640190fd5b92915050565b600073ffffffffffffffffffffffffffffffffffffffff8216610aa457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4552433732315f5a45524f5f4f574e4552000000000000000000000000000000604482015290519081900360640190fd5b5073ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205490565b33600081815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b610b71858585610482565b833b8015610d29576040517f150b7a02000000000000000000000000000000000000000000000000000000008152336004820181815273ffffffffffffffffffffffffffffffffffffffff89811660248501526044840188905260806064850190815260848501879052600094918a169363150b7a029390928c928b928b928b929060a401848480828437600081840152601f19601f8201169050808301925050509650505050505050602060405180830381600087803b158015610c3557600080fd5b505af1158015610c49573d6000803e3d6000fd5b505050506040513d6020811015610c5f57600080fd5b505160405190915080602f610e5b8239602f01905060405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610d2757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4552433732315f494e56414c49445f53454c4543544f52000000000000000000604482015290519081900360640190fd5b505b505050505050565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260036020908152604080832093909416825291909152205460ff1690565b600082821115610d8a57610d8a610d8560028585610db3565b610e52565b50900390565b600082820183811015610dac57610dac610d8560008686610db3565b9392505050565b606063e946c1bb60e01b84848460405160240180846003811115610dd357fe5b60ff1681526020018381526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090509392505050565b805160208201fdfe6f6e455243373231526563656976656428616464726573732c616464726573732c75696e743235362c627974657329a265627a7a723158204bc74831490bca4fbe1805808d58d6b0e12f618a37565e744e91d8dc73dc18b164736f6c634300050c0032'; + /** + * @ignore + */ + public static deployedBytecode: string | undefined; /** * The zero address indicates there is no approved address. * Throws unless `msg.sender` is the current NFT owner, or an authorized @@ -78,6 +86,7 @@ export class ERC721TokenContract extends BaseContract { _approved: string, _tokenId: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_approved', _approved); assert.isBigNumber('_tokenId', _tokenId); @@ -98,6 +107,10 @@ export class ERC721TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.approve.callAsync(_approved, _tokenId, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -114,21 +127,20 @@ export class ERC721TokenContract extends BaseContract { _approved: string, _tokenId: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_approved', _approved); assert.isBigNumber('_tokenId', _tokenId); const self = (this as any) as ERC721TokenContract; - const txHashPromise = self.approve.sendTransactionAsync(_approved.toLowerCase(), _tokenId, txData); + const txHashPromise = self.approve.sendTransactionAsync(_approved.toLowerCase(), _tokenId, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -167,15 +179,6 @@ export class ERC721TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _approved: string, - _tokenId: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).approve.callAsync(_approved, _tokenId, txData); - const txHash = await (this as any).approve.sendTransactionAsync(_approved, _tokenId, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -247,30 +250,6 @@ export class ERC721TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, BigNumber] { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('approve(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('approve(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * NFTs assigned to the zero address are considered invalid, and this @@ -325,43 +304,6 @@ export class ERC721TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param _owner An address for whom to query the balance - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(_owner: string): string { - assert.isString('_owner', _owner); - const self = (this as any) as ERC721TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('balanceOf(address)', [_owner.toLowerCase()]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('balanceOf(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('balanceOf(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Throws if `_tokenId` is not a valid NFT. @@ -415,43 +357,6 @@ export class ERC721TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param _tokenId The NFT to find the approved address for - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(_tokenId: BigNumber): string { - assert.isBigNumber('_tokenId', _tokenId); - const self = (this as any) as ERC721TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getApproved(uint256)', [_tokenId]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): BigNumber { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('getApproved(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('getApproved(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public isApprovedForAll = { /** @@ -508,48 +413,6 @@ export class ERC721TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param _owner The address that owns the NFTs - * @param _operator The address that acts on behalf of the owner - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(_owner: string, _operator: string): string { - assert.isString('_owner', _owner); - assert.isString('_operator', _operator); - const self = (this as any) as ERC721TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('isApprovedForAll(address,address)', [ - _owner.toLowerCase(), - _operator.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('isApprovedForAll(address,address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('isApprovedForAll(address,address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * NFTs assigned to zero address are considered invalid, and queries @@ -604,43 +467,6 @@ export class ERC721TokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param _tokenId The identifier for an NFT - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(_tokenId: BigNumber): string { - assert.isBigNumber('_tokenId', _tokenId); - const self = (this as any) as ERC721TokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('ownerOf(uint256)', [_tokenId]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): BigNumber { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('ownerOf(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('ownerOf(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * This works identically to the other function with an extra data parameter, @@ -661,6 +487,7 @@ export class ERC721TokenContract extends BaseContract { _to: string, _tokenId: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_from', _from); assert.isString('_to', _to); @@ -683,6 +510,10 @@ export class ERC721TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.safeTransferFrom1.callAsync(_from, _to, _tokenId, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -701,8 +532,7 @@ export class ERC721TokenContract extends BaseContract { _to: string, _tokenId: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_from', _from); assert.isString('_to', _to); @@ -713,6 +543,7 @@ export class ERC721TokenContract extends BaseContract { _to.toLowerCase(), _tokenId, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -720,8 +551,8 @@ export class ERC721TokenContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -764,16 +595,6 @@ export class ERC721TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _from: string, - _to: string, - _tokenId: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).safeTransferFrom1.callAsync(_from, _to, _tokenId, txData); - const txHash = await (this as any).safeTransferFrom1.sendTransactionAsync(_from, _to, _tokenId, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -852,30 +673,6 @@ export class ERC721TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, string, BigNumber] { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('safeTransferFrom(address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('safeTransferFrom(address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Throws unless `msg.sender` is the current owner, an authorized @@ -903,6 +700,7 @@ export class ERC721TokenContract extends BaseContract { _tokenId: BigNumber, _data: string, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_from', _from); assert.isString('_to', _to); @@ -927,6 +725,10 @@ export class ERC721TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.safeTransferFrom2.callAsync(_from, _to, _tokenId, _data, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -947,8 +749,7 @@ export class ERC721TokenContract extends BaseContract { _tokenId: BigNumber, _data: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_from', _from); assert.isString('_to', _to); @@ -961,6 +762,7 @@ export class ERC721TokenContract extends BaseContract { _tokenId, _data, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -968,8 +770,8 @@ export class ERC721TokenContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1016,23 +818,6 @@ export class ERC721TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _from: string, - _to: string, - _tokenId: BigNumber, - _data: string, - txData?: Partial | undefined, - ): Promise { - await (this as any).safeTransferFrom2.callAsync(_from, _to, _tokenId, _data, txData); - const txHash = await (this as any).safeTransferFrom2.sendTransactionAsync( - _from, - _to, - _tokenId, - _data, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1116,30 +901,6 @@ export class ERC721TokenContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, string, BigNumber, string] { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('safeTransferFrom(address,address,uint256,bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, string, BigNumber, string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('safeTransferFrom(address,address,uint256,bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Emits the ApprovalForAll event. The contract MUST allow @@ -1158,6 +919,7 @@ export class ERC721TokenContract extends BaseContract { _operator: string, _approved: boolean, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_operator', _operator); assert.isBoolean('_approved', _approved); @@ -1178,6 +940,10 @@ export class ERC721TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.setApprovalForAll.callAsync(_operator, _approved, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1194,8 +960,7 @@ export class ERC721TokenContract extends BaseContract { _operator: string, _approved: boolean, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_operator', _operator); assert.isBoolean('_approved', _approved); @@ -1204,6 +969,7 @@ export class ERC721TokenContract extends BaseContract { _operator.toLowerCase(), _approved, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -1211,8 +977,8 @@ export class ERC721TokenContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1251,15 +1017,6 @@ export class ERC721TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _operator: string, - _approved: boolean, - txData?: Partial | undefined, - ): Promise { - await (this as any).setApprovalForAll.callAsync(_operator, _approved, txData); - const txHash = await (this as any).setApprovalForAll.sendTransactionAsync(_operator, _approved, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1331,30 +1088,6 @@ export class ERC721TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, boolean] { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('setApprovalForAll(address,bool)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, boolean]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('setApprovalForAll(address,bool)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Throws unless `msg.sender` is the current owner, an authorized @@ -1377,6 +1110,7 @@ export class ERC721TokenContract extends BaseContract { _to: string, _tokenId: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_from', _from); assert.isString('_to', _to); @@ -1399,6 +1133,10 @@ export class ERC721TokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transferFrom.callAsync(_from, _to, _tokenId, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1417,8 +1155,7 @@ export class ERC721TokenContract extends BaseContract { _to: string, _tokenId: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_from', _from); assert.isString('_to', _to); @@ -1429,6 +1166,7 @@ export class ERC721TokenContract extends BaseContract { _to.toLowerCase(), _tokenId, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -1436,8 +1174,8 @@ export class ERC721TokenContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1480,16 +1218,6 @@ export class ERC721TokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _from: string, - _to: string, - _tokenId: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).transferFrom.callAsync(_from, _to, _tokenId, txData); - const txHash = await (this as any).transferFrom.sendTransactionAsync(_from, _to, _tokenId, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1568,30 +1296,6 @@ export class ERC721TokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, string, BigNumber] { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ERC721TokenContract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; private readonly _subscriptionManager: SubscriptionManager; public static async deployFrom0xArtifactAsync( diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/eth_balance_checker.ts b/packages/abi-gen-wrappers/src/generated-wrappers/eth_balance_checker.ts index c973546cf0..ef8097adfd 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/eth_balance_checker.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/eth_balance_checker.ts @@ -18,7 +18,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -28,8 +34,10 @@ import * as ethers from 'ethers'; // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class EthBalanceCheckerContract extends BaseContract { - public static deployedBytecode = - '0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a0901e5114610030575b600080fd5b6100d36004803603602081101561004657600080fd5b81019060208101813564010000000081111561006157600080fd5b82018360208201111561007357600080fd5b8035906020019184602083028401116401000000008311171561009557600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610123945050505050565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561010f5781810151838201526020016100f7565b505050509050019250505060405180910390f35b6060808251604051908082528060200260200182016040528015610151578160200160208202803883390190505b50905060005b835181146101a95783818151811061016b57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff163182828151811061019657fe5b6020908102919091010152600101610157565b509291505056fea265627a7a7231582094309783f0b63086d85d9cb4f6e5be253699056ac1580a863367c5076ecb5c1864736f6c634300050b0032'; + /** + * @ignore + */ + public static deployedBytecode: string | undefined; /** * Batch fetches ETH balances */ @@ -82,43 +90,6 @@ export class EthBalanceCheckerContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param addresses Array of addresses. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(addresses: string[]): string { - assert.isArray('addresses', addresses); - const self = (this as any) as EthBalanceCheckerContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getEthBalances(address[])', [addresses]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string[] { - const self = (this as any) as EthBalanceCheckerContract; - const abiEncoder = self._lookupAbiEncoder('getEthBalances(address[])'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber[] { - const self = (this as any) as EthBalanceCheckerContract; - const abiEncoder = self._lookupAbiEncoder('getEthBalances(address[])'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public static async deployFrom0xArtifactAsync( artifact: ContractArtifact | SimpleContractArtifact, diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/exchange.ts b/packages/abi-gen-wrappers/src/generated-wrappers/exchange.ts index bb8fc0584c..64458c76b3 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/exchange.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/exchange.ts @@ -19,7 +19,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -107,8 +113,10 @@ export interface ExchangeTransactionExecutionEventArgs extends DecodedLogArgs { // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class ExchangeContract extends BaseContract { - public static deployedBytecode = - '0x6080604052600436106102d15760003560e01c80638da5cb5b11610179578063beee2e14116100d6578063dd885e2d1161008a578063eea086ba11610064578063eea086ba14610715578063f2fde38b1461072a578063fc74896d1461074a576102d1565b8063dd885e2d146106cd578063dedfc1f1146106ef578063e14b58c414610702576102d1565b8063c26cfecd116100bb578063c26cfecd14610678578063c585bb931461068d578063d9bfa73e146106ad576102d1565b8063beee2e1414610645578063c0fa16cc14610658576102d1565b80639d3fa4b91161012d578063a6c3bf3311610112578063a6c3bf33146105ff578063b04fbddd14610612578063b718e29214610632576102d1565b80639d3fa4b9146105b2578063a12dcc6f146105df576102d1565b80639331c7421161015e5780639331c7421461056c5780639694a4021461058c5780639b44d5561461059f576102d1565b80638da5cb5b146105375780638ea8dfe41461054c576102d1565b80636a1a80fd116102325780638171c407116101e657806388ec79fb116101c057806388ec79fb146104e45780638bc8efb3146105045780638d45cd2314610517576102d1565b80638171c4071461048f57806382c174d0146104af578063850a1501146104cf576102d1565b806377fcce681161021757806377fcce681461044957806378d29ac11461045c5780637b8e35141461046f576102d1565b80636a1a80fd146104165780636fcf3e9e14610436576102d1565b80632da629871161028957806346c02d7a1161026e57806346c02d7a146103c35780634f9559b1146103d657806360704108146103e9576102d1565b80632da629871461038e578063369da099146103a3576102d1565b80632280c910116102ba5780632280c9101461032e578063288cdc911461034e5780632ac126221461036e576102d1565b80630228e168146102d65780631ce4c78b1461030c575b600080fd5b3480156102e257600080fd5b506102f66102f1366004614e64565b61076a565b60405161030391906154c4565b60405180910390f35b34801561031857600080fd5b5061032161077f565b60405161030391906154cf565b61034161033c366004615108565b610785565b60405161030391906156a0565b34801561035a57600080fd5b50610321610369366004614e64565b6107c7565b34801561037a57600080fd5b506102f6610389366004614e64565b6107d9565b6103a161039c366004614f82565b6107ee565b005b6103b66103b1366004614d60565b610812565b60405161030391906159c2565b6103a16103d1366004614e64565b610939565b6103a16103e4366004614e64565b6109ac565b3480156103f557600080fd5b50610409610404366004614eed565b610ab9565b604051610303919061535b565b610429610424366004614c40565b610b07565b604051610303919061594b565b610429610444366004614c40565b610b3f565b6103a1610457366004614b2a565b610b5d565b6103b661046a366004614d60565b610c20565b34801561047b57600080fd5b506102f661048a366004614af6565b610d70565b34801561049b57600080fd5b506102f66104aa366004614ea0565b610d90565b3480156104bb57600080fd5b506102f66104ca366004614e7c565b610def565b3480156104db57600080fd5b50610409610e0f565b6104f76104f236600461500c565b610e2b565b60405161030391906159d0565b6103b6610512366004614d60565b610e49565b34801561052357600080fd5b506102f6610532366004615108565b610e7d565b34801561054357600080fd5b50610409610ea2565b61055f61055a366004614cdc565b610ebe565b60405161030391906154b1565b34801561057857600080fd5b506103a1610587366004614e64565b610fe9565b61055f61059a366004614cdc565b611031565b6103b66105ad3660046150a8565b6110f8565b3480156105be57600080fd5b506105d26105cd366004614f82565b61111d565b6040516103039190615a12565b3480156105eb57600080fd5b506102f66105fa366004614fb5565b611201565b6103b661060d366004614d60565b611226565b34801561061e57600080fd5b506103a161062d366004614b65565b61125a565b6104f761064036600461500c565b611306565b61055f610653366004614cdc565b611324565b34801561066457600080fd5b506103a1610673366004614adb565b6113d9565b34801561068457600080fd5b5061032161147c565b34801561069957600080fd5b506103a16106a8366004614adb565b611482565b3480156106b957600080fd5b506103216106c8366004614af6565b611616565b3480156106d957600080fd5b506106e2611633565b604051610303919061562b565b6103a16106fd366004614c0d565b611657565b6103b66107103660046150a8565b611699565b34801561072157600080fd5b506104096116b4565b34801561073657600080fd5b506103a1610745366004614adb565b6116d0565b61075d610758366004614db3565b611748565b6040516103039190615433565b60056020526000908152604090205460ff1681565b60035481565b606061078f61187b565b156107a55761079e838361189d565b90506107c1565b6107ad6119b7565b6107b7838361189d565b90506107c16119f9565b92915050565b60096020526000908152604090205481565b600a6020526000908152604090205460ff1681565b6107f6611a2b565b6107ff81611a9a565b610807611ad7565b61080f611aeb565b50565b61081a614561565b61082261187b565b156108b857835160005b8181146108b157600061084c846020015187611b1590919063ffffffff16565b9050610856614561565b61088788848151811061086557fe5b60200260200101518388868151811061087a57fe5b6020026020010151611b34565b90506108938582611c75565b9450868560200151106108a75750506108b1565b505060010161082c565b5050610932565b6108c06119b7565b835160005b8181146109285760006108e5846020015187611b1590919063ffffffff16565b90506108ef614561565b6108fe88848151811061086557fe5b905061090a8582611c75565b94508685602001511061091e575050610928565b50506001016108c5565b50506109326119f9565b9392505050565b610941611a2b565b600061094b611d10565b600083815260076020908152604080832073ffffffffffffffffffffffffffffffffffffffff90941683529290522080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905550610807611ad7565b6109b4611a2b565b60006109be611d10565b9050600073ffffffffffffffffffffffffffffffffffffffff821633146109e557336109e8565b60005b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600b60209081526040808320938516835292905220549091506001840190808211610a3d57610a3d610a38858584611d42565b611de7565b73ffffffffffffffffffffffffffffffffffffffff8085166000818152600b602090815260408083209488168084529490915290819020859055517f82af639571738f4ebd4268fb0363d8957ebe1bbb9e78dba5ebd69eed39b154f090610aa59086906154cf565b60405180910390a350505050610807611ad7565b7fffffffff00000000000000000000000000000000000000000000000000000000811660009081526002602052604090205473ffffffffffffffffffffffffffffffffffffffff165b919050565b610b0f614590565b610b17611a2b565b610b25858585856001611def565b9050610b2f611ad7565b610b37611aeb565b949350505050565b610b47614590565b610b4f611a2b565b610b25858585856000611def565b610b65611a2b565b6000610b6f611d10565b73ffffffffffffffffffffffffffffffffffffffff8181166000818152600860209081526040808320948916808452949091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168715151790555192935090917fa8656e308026eeabce8f0bc18048433252318ab80ac79da0b3d3d8697dfba89190610c039086906154c4565b60405180910390a350610c14611ad7565b610c1c611aeb565b5050565b610c28614561565b610c3061187b565b15610cee57835160005b8181146108b1578251600090610c5790879063ffffffff611b1516565b90506000610c94888481518110610c6a57fe5b602002602001015160a00151898581518110610c8257fe5b6020026020010151608001518461215c565b9050610c9e614561565b610cc2898581518110610cad57fe5b60200260200101518389878151811061087a57fe5b9050610cce8682611c75565b955087866000015110610ce3575050506108b1565b505050600101610c3a565b610cf66119b7565b835160005b818114610928578251600090610d1890879063ffffffff611b1516565b90506000610d2b888481518110610c6a57fe5b9050610d35614561565b610d44898581518110610cad57fe5b9050610d508682611c75565b955087866000015110610d6557505050610928565b505050600101610cfb565b600860209081526000928352604080842090915290825290205460ff1681565b600080610d9e85858561217e565b90506005816008811115610dae57fe5b1480610dc557506007816008811115610dc357fe5b145b15610dda57610dda610a3860058787876121fd565b610de6818686866122a5565b95945050505050565b600760209081526000928352604080842090915290825290205460ff1681565b60045473ffffffffffffffffffffffffffffffffffffffff1681565b610e336145b8565b610e3b611a2b565b610b25858585856000612515565b610e51614561565b610e5c848484610c20565b9050828160000151101561093257610932610a386000858460000151612602565b600080610e956001548561262190919063ffffffff16565b9050610b37848285612635565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b6060610ec861187b565b15610f6b578351604080518281526020808402820101909152818015610f0857816020015b610ef5614561565b815260200190600190039081610eed5790505b50915060005b8181146108b157610f4c868281518110610f2457fe5b6020026020010151868381518110610f3857fe5b602002602001015186848151811061087a57fe5b838281518110610f5857fe5b6020908102919091010152600101610f0e565b610f736119b7565b8351604080518281526020808402820101909152818015610fae57816020015b610f9b614561565b815260200190600190039081610f935790505b50915060005b81811461092857610fca868281518110610f2457fe5b838281518110610fd657fe5b6020908102919091010152600101610fb4565b610ff16126bb565b7f3a3e76d7a75e198aef1f53137e4f2a8a2ec74e2e9526db8404d08ccc9f1e621d60035482604051611024929190615543565b60405180910390a1600355565b606061103b611a2b565b835160408051828152602080840282010190915281801561107657816020015b611063614561565b81526020019060019003908161105b5790505b50915060005b8181146110e6576110c786828151811061109257fe5b60200260200101518683815181106110a657fe5b60200260200101518684815181106110ba57fe5b6020026020010151612702565b8382815181106110d357fe5b602090810291909101015260010161107c565b50506110f0611ad7565b610932611aeb565b611100614561565b611108611a2b565b611113848484612702565b90506110f0611ad7565b6111256145ec565b61112e826127a4565b60408301526020820152608082015161114e5760015b60ff168152610b02565b60a082015161115e576002611144565b8160a00151816040015110611174576005611144565b8161010001514210611187576004611144565b6020808201516000908152600a909152604090205460ff16156111ab576006611144565b610120820151825173ffffffffffffffffffffffffffffffffffffffff9081166000908152600b6020908152604080832060608801519094168352929052205411156111f8576006611144565b60038152919050565b600080611219600154856127d590919063ffffffff16565b9050610b378482856127e4565b61122e614561565b611239848484610812565b9050828160200151101561093257610932610a386001858460200151612602565b835160005b8181146112ca576112c28160001b87838151811061127957fe5b602002602001015187848151811061128d57fe5b60200260200101518785815181106112a157fe5b60200260200101518786815181106112b557fe5b6020026020010151612839565b60010161125f565b506040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112fd90615914565b60405180910390fd5b61130e6145b8565b611316611a2b565b610b25858585856001612515565b606061132e611a2b565b835160408051828152602080840282010190915281801561136957816020015b611356614561565b81526020019060019003908161134e5790505b50915060005b8181146110e6576113ba86828151811061138557fe5b602002602001015186838151811061139957fe5b60200260200101518684815181106113ad57fe5b60200260200101516129f3565b8382815181106113c657fe5b602090810291909101015260010161136f565b6113e16126bb565b6004546040517fe1a5430ebec577336427f40f15822f1f36c5e3509ff209d6db9e6c9e6941cb0b9161142d9173ffffffffffffffffffffffffffffffffffffffff90911690849061537c565b60405180910390a1600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60015481565b61148a6126bb565b60008173ffffffffffffffffffffffffffffffffffffffff1663ae25532e6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114d257600080fd5b505afa1580156114e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061150a9190810190614f09565b7fffffffff00000000000000000000000000000000000000000000000000000000811660009081526002602052604090205490915073ffffffffffffffffffffffffffffffffffffffff16801561156857611568610a388383612a26565b7fffffffff0000000000000000000000000000000000000000000000000000000082166000908152600260205260409081902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616179055517fd2c6b762299c609bdb96520b58a49bfb80186934d4f71a86a367571a15c03194906116099084908690615658565b60405180910390a1505050565b600b60209081526000928352604080842090915290825290205481565b7f20c13b0b0000000000000000000000000000000000000000000000000000000081565b61165f611a2b565b805160005b81811461168f5761168783828151811061167a57fe5b6020026020010151611a9a565b600101611664565b5050610807611ad7565b6116a1614561565b6116a9611a2b565b6111138484846129f3565b60065473ffffffffffffffffffffffffffffffffffffffff1681565b6116d86126bb565b73ffffffffffffffffffffffffffffffffffffffff8116611703576116fe610a38612ac8565b61080f565b6000805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905550565b606061175261187b565b156117f457825160408051828152602080840282010190915260609082801561178f57816020015b606081526020019060019003908161177a5790505b50905060005b8281146117eb576117cc8682815181106117ab57fe5b60200260200101518683815181106117bf57fe5b602002602001015161189d565b8282815181106117d857fe5b6020908102919091010152600101611795565b509150506107c1565b6117fc6119b7565b825160408051828152602080840282010190915260609082801561183457816020015b606081526020019060019003908161181f5790505b50905060005b82811461186f576118508682815181106117ab57fe5b82828151811061185c57fe5b602090810291909101015260010161183a565b509150506107c16119f9565b6000547501000000000000000000000000000000000000000000900460ff1690565b606060006118b66001548561262190919063ffffffff16565b90506118c3848483612aff565b60608401516118d28180612bd3565b60008281526005602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055608087015190516060913091611920919061530e565b600060405180830381855af49150503d806000811461195b576040519150601f19603f3d011682016040523d82523d6000602084013e611960565b606091505b50915091508161197757611977610a388583612c36565b611982836000612bd3565b60405184907fa4a7329f1dd821363067e07d359e347b4af9b1efe4b6cccf13240228af3c800d90600090a29695505050505050565b600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055611a29612c53565b565b60005474010000000000000000000000000000000000000000900460ff1615611a5957611a59610a38612c88565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b611aa26145ec565b611aab8261111d565b9050611ab78282612cbf565b805160ff16600314611ac9575061080f565b610c1c828260200151612d6e565b611adf61187b565b611a2957611a29612c53565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b600082821115611b2e57611b2e610a3860028585612e17565b50900390565b611b3c614561565b6040516060907f9b44d5560000000000000000000000000000000000000000000000000000000090611b7690879087908790602401615a58565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600060603073ffffffffffffffffffffffffffffffffffffffff1683604051611bfe919061530e565b600060405180830381855af49150503d8060008114611c39576040519150601f19603f3d011682016040523d82523d6000602084013e611c3e565b606091505b50915091508115611c6b57805160a014611c5457fe5b80806020019051611c689190810190614f25565b93505b5050509392505050565b611c7d614561565b81518351611c909163ffffffff612e3616565b815260208083015190840151611cab9163ffffffff612e3616565b602082015260408083015190840151611cc99163ffffffff612e3616565b604082015260608083015190840151611ce79163ffffffff612e3616565b606082015260808083015190840151611d059163ffffffff612e3616565b608082015292915050565b60065460009073ffffffffffffffffffffffffffffffffffffffff16818115611d395781611d3b565b335b9250505090565b6060634ad3127560e01b848484604051602401611d61939291906153a3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290509392505050565b805160208201fd5b611df7614590565b8551611e0a57611e0a610a386000612e52565b8451611e1d57611e1d610a386001612e52565b8351865114611e3357611e33610a386002612e52565b8251855114611e4957611e49610a386003612e52565b8551604051908082528060200260200182016040528015611e8457816020015b611e71614561565b815260200190600190039081611e695790505b5081528451604080518281526020808402820101909152908015611ec257816020015b611eaf614561565b815260200190600190039081611ea75790505b506020820152600080611ed361460c565b88600081518110611ee057fe5b60200260200101519050611ef261460c565b88600081518110611eff57fe5b602002602001015190506000611f14836127a4565b9150506000611f22836127a4565b915050611f2d614561565b611f35614561565b611f3d6145b8565b611f7087878f8c81518110611f4e57fe5b60200260200101518f8c81518110611f6257fe5b60200260200101518f612515565b805160200151909150611f8a90869063ffffffff612e3616565b9450611fa781602001516020015185612e3690919063ffffffff16565b9350611fb7838260000151611c75565b9250611fc7828260200151611c75565b9150611fe481604001518b60400151612e3690919063ffffffff16565b60408b0152606080820151908b01516120029163ffffffff612e3616565b60608b015260a087015185106120ad578951805160018b019a859291811061202657fe5b60200260200101819052506040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525092508e5189141561208a57818a60200151898151811061207957fe5b60200260200101819052505061214b565b8e898151811061209657fe5b602002602001015196506120a9876127a4565b9550505b8560a00151841061214557818a6020015189806001019a50815181106120cf57fe5b60200260200101819052506040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525091508d5188141561212257828a600001518a8151811061207957fe5b8d888151811061212e57fe5b60200260200101519550612141866127a4565b9450505b50611f35565b505050505050505095945050505050565b6000610b3783612172868563ffffffff612ef116565b9063ffffffff612f2216565b600061218b848484612f4c565b905073ffffffffffffffffffffffffffffffffffffffff83166121b8576121b8610a3860068686866121fd565b600881818111156121c557fe5b60ff16106121dd576121dd610a3860038686866121fd565b60008160088111156121eb57fe5b141561093257610932610a3860048686865b6060637e5a231860e01b8585858560405160240161221e94939291906158b9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050949350505050565b600060018560088111156122b557fe5b14156122dc5781516001146122d4576122d4610a3860028686866121fd565b506000610b37565b60028560088111156122ea57fe5b14156123e357815160421461230957612309610a3860028686866121fd565b60008260008151811061231857fe5b016020015160f81c9050600061233584600163ffffffff612f8b16565b9050600061234a85602163ffffffff612f8b16565b9050600060018885858560405160008152602001604052604051612371949392919061560d565b6020604051602081039080840390855afa158015612393573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015173ffffffffffffffffffffffffffffffffffffffff8981169116149550610b37945050505050565b60038560088111156123f157fe5b141561249e57815160421461241057612410610a3860028686866121fd565b60008260008151811061241f57fe5b016020015160f81c9050600061243c84600163ffffffff612f8b16565b9050600061245185602163ffffffff612f8b16565b90506000600188604051602001612468919061532a565b6040516020818303038152906040528051906020012085858560405160008152602001604052604051612371949392919061560d565b60048560088111156124ac57fe5b14156124c4576124bd848484612fb5565b9050610b37565b60068560088111156124d257fe5b146124d957fe5b50600083815260076020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290205460ff16949350505050565b61251d6145b8565b61016080870151610140808801919091528701519086015261253d6145ec565b6125468761111d565b90506125506145ec565b6125598761111d565b90506000612565611d10565b90506125738984838a6131ab565b61257f888383896131ab565b6125938989856020015185602001516132e1565b6125ac8989856040015185604001516003543a8b61332c565b93506125c78982856020015186604001518860000151613481565b6125e08882846020015185604001518860200151613481565b6125f6836020015183602001518b8b858961355f565b50505095945050505050565b60606318e4b14160e01b848484604051602401611d619392919061589e565b60006109328261263085613706565b61378e565b60608301516000908161264985838661217e565b9050600581600881111561265957fe5b141561267b5761267461266c87876137c8565b868487613800565b92506126b2565b600781600881111561268957fe5b14156126a35761267461269c87876137c8565b83866138b4565b6126af818684876122a5565b92505b50509392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611a2957600054611a2990610a3890339073ffffffffffffffffffffffffffffffffffffffff166138c3565b61270a614561565b6127126145ec565b61271b8561111d565b90506000612727611d10565b9050612735868383876131ab565b600061275283604001518860a00151611b1590919063ffffffff16565b9050600061276087836138e0565b905061277088826003543a6138f6565b945060008460200151905061278c89858388604001518a613481565b612798818a868961396d565b50505050509392505050565b6000806127bc600154846127d590919063ffffffff16565b6000818152600960205260409020549092509050915091565b60006109328261263085613a04565b8251600090816127f585838661217e565b9050600581600881111561280557fe5b14156128185761267461266c8787613adb565b600781600881111561282657fe5b14156126a35761267461269c8787613adb565b80156129ec57600384511161285757612857610a3860008787613b13565b6000612869858263ffffffff613b3216565b7fffffffff00000000000000000000000000000000000000000000000000000000811660009081526002602052604090205490915073ffffffffffffffffffffffffffffffffffffffff16806128c8576128c8610a3860018989613b13565b6040516060907fa85e59e400000000000000000000000000000000000000000000000000000000906129049089908990899089906024016156b3565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600060608373ffffffffffffffffffffffffffffffffffffffff168360405161298c919061530e565b6000604051808303816000865af19150503d80600081146129c9576040519150601f19603f3d011682016040523d82523d6000602084013e6129ce565b606091505b5091509150816129e6576129e6610a388b8b84613b7e565b50505050505b5050505050565b6129fb614561565b612a06848484612702565b90508281602001511461093257610932610a386002858460200151612602565b60606311c7b72060e01b8383604051602401612a43929190615658565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152905092915050565b60408051808201909152600481527fe69edc3e00000000000000000000000000000000000000000000000000000000602082015290565b82602001514210612b1857612b18610a38600183613b9d565b60408301513a8114612b3257612b32610a38833a84613bba565b60065473ffffffffffffffffffffffffffffffffffffffff168015612b5e57612b5e610a388483613bd9565b60008381526005602052604090205460ff1615612b8357612b83610a38600085613b9d565b606085015173ffffffffffffffffffffffffffffffffffffffff81163314801590612bb65750612bb4868587612635565b155b15612bcb57612bcb610a3860018684896121fd565b505050505050565b73ffffffffffffffffffffffffffffffffffffffff82163314610c1c576006805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff00000000000000000000000000000000000000009091161790555050565b60606320d11f6160e01b8383604051602401612a43929190615551565b3031801561080f57604051339082156108fc029083906000818181858888f19350505050158015610c1c573d6000803e3d6000fd5b60408051808201909152600481527f0c3b823f00000000000000000000000000000000000000000000000000000000602082015290565b606082015173ffffffffffffffffffffffffffffffffffffffff1615612d1357606082015173ffffffffffffffffffffffffffffffffffffffff163314612d1357612d13610a386002836020015133613bf6565b6000612d1d611d10565b90508073ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff1614612d6957612d69610a386000846020015184613bf6565b505050565b6000818152600a60205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558281015183516101408501516101608601519351859473ffffffffffffffffffffffffffffffffffffffff9485169493909316927f02c310a9a43963ff31a754a4099cc435ed498049687539d72d7818d9b093415c92612e0b92909190339061571b565b60405180910390a45050565b606063e946c1bb60e01b848484604051602401611d6193929190615846565b60008282018381101561093257610932610a3860008686612e17565b606063d4092f4f60e01b82604051602401612e6d9190615833565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050919050565b600082612f00575060006107c1565b82820282848281612f0d57fe5b041461093257610932610a3860018686612e17565b600081612f3857612f38610a3860038585612e17565b6000828481612f4357fe5b04949350505050565b6000815160001415612f6857612f68610a3860028686866121fd565b81600183510381518110612f7857fe5b016020015160f81c6008811115610b3757fe5b60008160200183511015612fac57612fac610a386005855185602001613c15565b50016020015190565b8051600090612fec837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830163ffffffff613c3416565b6040516060907f1626ba7e00000000000000000000000000000000000000000000000000000000906130249088908790602401615551565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290506130b3848363ffffffff613c3416565b600060608673ffffffffffffffffffffffffffffffffffffffff16836040516130dc919061530e565b600060405180830381855afa9150503d8060008114613117576040519150601f19603f3d011682016040523d82523d6000602084013e61311c565b606091505b509150915081801561312f575080516020145b15613191577fb06713810000000000000000000000000000000000000000000000000000000061316682600063ffffffff613b3216565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614945050505050610932565b6131a0610a3889898985613c38565b505050509392505050565b825160ff166003146131da576131da610a388460200151856000015160ff1660068111156131d557fe5b613c59565b606084015173ffffffffffffffffffffffffffffffffffffffff161561322e57606084015173ffffffffffffffffffffffffffffffffffffffff16331461322e5761322e610a386002856020015133613bf6565b602084015173ffffffffffffffffffffffffffffffffffffffff1615613298578173ffffffffffffffffffffffffffffffffffffffff16846020015173ffffffffffffffffffffffffffffffffffffffff161461329857613298610a386001856020015185613bf6565b8351604084015115806132b557506132b584602001518284613c76565b156129ec576132c9858560200151846127e4565b6129ec576129ec610a386000866020015184866121fd565b60a080840151908501516132fa9163ffffffff612ef116565b608080850151908601516133139163ffffffff612ef116565b101561332657613326610a388383613cc9565b50505050565b6133346145b8565b60a088015160009061334c908863ffffffff611b1516565b905060006133638a608001518b60a0015184613ce6565b9050600061337e888b60a00151611b1590919063ffffffff16565b905060006133958b608001518c60a0015184613ce6565b905085156133b2576133ab8c8c85878587613d1a565b94506133c3565b6133c08c8c85878587613dec565b94505b84515160808d015160c08e01516133db929190613ce6565b85516040015284516020015160a08d015160e08e01516133fc929190613ce6565b85516060015260208501515160808c015160c08d015161341d929190613ce6565b856020015160400181815250506134458560200151602001518c60a001518d60e00151613ce6565b6020860151606001526000613460888a63ffffffff612ef116565b86516080908101829052602088015101525050505050979650505050505050565b602081015161349790839063ffffffff612e3616565b600960008581526020019081526020016000208190555082856040015173ffffffffffffffffffffffffffffffffffffffff16866000015173ffffffffffffffffffffffffffffffffffffffff167f6869791f0a34781b29882982cc39e882768cf2c96995c2a110c577c53bc932d58861014001518961016001518a61018001518b6101a001518b338a600001518b602001518c604001518d606001518e608001516040516135509b9a99989796959493929190615767565b60405180910390a45050505050565b8351835160408087015190860151610140870151855160200151613588918b9186908890612839565b6135a28a8961014001518686896020015160200151612839565b6135bc898861018001518584896020015160400151612839565b6135d68a8961018001518685896000015160400151612839565b6135ec8a89610140015186898960400151612839565b6136028988610140015185898960600151612839565b600061361a8b8b88600001516080015188888c613e85565b905080613637578551600060809182018190526020880151909101525b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614801561368757506101a080890151908a01516136879163ffffffff613ee216565b156136c5576136c08b8a6101a0015189866136bb8b60200151606001518c6000015160600151612e3690919063ffffffff16565b612839565b6136f9565b6136df8a896101a0015189858a6020015160600151612839565b6136f98b8a6101a0015189868a6000015160600151612839565b5050505050505050505050565b608081810151825160208085015160408087015160609788015186519685019690962082517fec69816980a3a3ca4554410e60253953e9ff375ba4536a98adfa15cc71541508815294850195909552908301919091529481019490945273ffffffffffffffffffffffffffffffffffffffff9091169183019190915260a082015260c0902090565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b6040516060907fde047db40000000000000000000000000000000000000000000000000000000090612a439085908590602401615a83565b8051600090601581101561381e5761381e610a3860028787876121fd565b6000613852847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb840163ffffffff613f0716565b73ffffffffffffffffffffffffffffffffffffffff80871660009081526008602090815260408083209385168352929052205490915060ff1661389c5761389c610a388683613f47565b6138a98188866015613f64565b979650505050505050565b6000610b378385846001613f64565b6060631de45ad160e01b8383604051602401612a4392919061537c565b60008183106138ef5781610932565b5090919050565b6138fe614561565b6020810184905260a0850151608086015161391a918691613ce6565b815260a085015160c0860151613931918691613ce6565b604082015260a085015160e086015161394b918691613ce6565b6060820152613960828463ffffffff612ef116565b6080820152949350505050565b613987848461016001518486600001518560200151612839565b6139a1848461014001518560000151858560000151612839565b6139bb84846101a001518486604001518560600151612839565b6139d984846101800151856000015186604001518560400151612839565b60006139ef85836080015186600001518661413b565b9050806129ec57600060808301525050505050565b6101408101516101608201516101808301516101a08401516000937ff80322eb8376aafb64eadf8f0d7623f22130fd9491a221e902b713cb984a753493909290916020871015613a5057fe5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe087018051610140890180516101608b0180516101808d0180516101a08f0180519d89528c5160209d8e012087528b519b8d019b909b2084528951998c01999099208152875197909a019690962088526101e085209390945290529190529252919091529050919050565b6040516060907f3efe50c80000000000000000000000000000000000000000000000000000000090612a439085908590602401615a36565b606063488219a660e01b848484604051602401611d619392919061580b565b60008160040183511015613b5357613b53610a386003855185600401613c15565b5001602001517fffffffff000000000000000000000000000000000000000000000000000000001690565b6060634678472b60e01b848484604051602401611d619392919061556a565b606063f598518460e01b8383604051602401612a439291906158fd565b606063a26dac0960e01b848484604051602401611d61939291906155f7565b606063dec4aedf60e01b8383604051602401612a439291906154d8565b606063e53c76c860e01b848484604051602401611d6193929190615867565b6060632800659560e01b848484604051602401611d61939291906158ab565b9052565b6060631b8388f760e01b8585858560405160240161221e94939291906154fc565b606063fdb6ca8d60e01b8383604051602401612a43929190615595565b600080613c84858585612f4c565b90506004816008811115613c9457fe5b1480613cab57506005816008811115613ca957fe5b145b80610de657506007816008811115613cbf57fe5b1495945050505050565b606063b6555d6f60e01b8383604051602401612a43929190615543565b6000613cf3848484614181565b15613d0657613d06610a388585856141e7565b610b3783612172868563ffffffff612ef116565b613d226145b8565b81851184841184861115613d4257613d3b898686614206565b9250613d91565b86841115613d825782518790528251602001869052608088015160a0890151613d6c919089613ce6565b6020808501805192909252905101879052613d91565b613d8e87878787614243565b92505b8115613db7576020808401510151835151613db19163ffffffff611b1516565b60408401525b8015613ddf5782516020908101519084015151613dd99163ffffffff611b1516565b60608401525b50505b9695505050505050565b613df46145b8565b82841115613e0e57613e07878484614206565b9050613e5c565b82841015613e4d5780518590528051602090810185905281015184905260a08601516080870151613e4091908661426e565b6020808301510152613e5c565b613e5985858585614243565b90505b6020808201510151815151613e769163ffffffff611b1516565b60408201529695505050505050565b60045460009073ffffffffffffffffffffffffffffffffffffffff168015613ed85730316000613eb98a84848b8b8a6142c2565b9050613ecb89848385038b8a8a6142c2565b5060019350505050613de2565b6000915050613de2565b6000815183511480156109325750508051602091820120825192909101919091201490565b60008160140183511015613f2857613f28610a386004855185601401613c15565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b606063a15c0d0660e01b8383604051602401612a4392919061537c565b8151600090613f7b8484830363ffffffff613c3416565b6040516060907f20c13b0b0000000000000000000000000000000000000000000000000000000090613fb390889088906024016156f6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050614042858363ffffffff613c3416565b600060608873ffffffffffffffffffffffffffffffffffffffff168360405161406b919061530e565b600060405180830381855afa9150503d80600081146140a6576040519150601f19603f3d011682016040523d82523d6000602084013e6140ab565b606091505b50915091508180156140be575080516020145b15614120577f20c13b0b000000000000000000000000000000000000000000000000000000006140f582600063ffffffff613b3216565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614945050505050610b37565b61412f610a388a8a8a856143fa565b50505050949350505050565b60045460009073ffffffffffffffffffffffffffffffffffffffff1680156141775761416c868230318888886142c2565b506001915050610b37565b6000915050610b37565b60008261419357614193610a3861441b565b81158061419e575083155b156141ab57506000610932565b600083806141b557fe5b85840990506141ca858463ffffffff612ef116565b6141dc826103e863ffffffff612ef116565b101595945050505050565b606063339f3de260e01b848484604051602401611d61939291906155f7565b61420e6145b8565b60208082018051859052518101839052815101839052608084015160a0850151614239919085613ce6565b8151529392505050565b61424b6145b8565b805194909452835160209081019390935282840180519290925290519091015290565b600061427b848484614452565b1561428e5761428e610a388585856141e7565b610b37836121726142a682600163ffffffff611b1516565b6142b6888763ffffffff612ef116565b9063ffffffff612e3616565b60008385106142ce5750825b6040516060907fa3b4a3270000000000000000000000000000000000000000000000000000000090614308908690869089906024016153a3565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600060608873ffffffffffffffffffffffffffffffffffffffff168484604051614391919061530e565b60006040518083038185875af1925050503d80600081146143ce576040519150601f19603f3d011682016040523d82523d6000602084013e6143d3565b606091505b5091509150816143ed576143ed610a388b898989866144b6565b5050509695505050505050565b6060635bd0428d60e01b8585858560405160240161221e94939291906153d4565b60408051808201909152600481527fa791837c00000000000000000000000000000000000000000000000000000000602082015290565b60008261446457614464610a3861441b565b81158061446f575083155b1561447c57506000610932565b6000838061448657fe5b85840990508361449c818363ffffffff611b1516565b816144a357fe5b0690506141ca858463ffffffff612ef116565b60606387cb1e7560e01b86868686866040516024016144d99594939291906155b2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152905095945050505050565b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6040518060800160405280606081526020016060815260200160008152602001600081525090565b60405180608001604052806145cb614561565b81526020016145d8614561565b815260200160008152602001600081525090565b604080516060810182526000808252602082018190529181019190915290565b604051806101c00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001606081526020016060815260200160608152602001606081525090565b803573ffffffffffffffffffffffffffffffffffffffff811681146107c157600080fd5b600082601f830112614707578081fd5b813561471a61471582615b14565b615aed565b81815291506020808301908481018184028601820187101561473b57600080fd5b60005b848110156147625761475088836146d3565b8452928201929082019060010161473e565b505050505092915050565b600082601f83011261477d578081fd5b813561478b61471582615b14565b8181529150602080830190840160005b838110156147c8576147b3876020843589010161488b565b8352602092830192919091019060010161479b565b5050505092915050565b600082601f8301126147e2578081fd5b81356147f061471582615b14565b8181529150602080830190840160005b838110156147c8576148188760208435890101614912565b83526020928301929190910190600101614800565b600082601f83011261483d578081fd5b813561484b61471582615b14565b81815291506020808301908481018184028601820187101561486c57600080fd5b60005b848110156147625781358452928201929082019060010161486f565b600082601f83011261489b578081fd5b813567ffffffffffffffff8111156148b1578182fd5b6148e260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601615aed565b91508082528360208285010111156148f957600080fd5b8060208401602084013760009082016020015292915050565b60006101c0808385031215614925578182fd5b61492e81615aed565b91505061493b83836146d3565b815261494a83602084016146d3565b602082015261495c83604084016146d3565b604082015261496e83606084016146d3565b60608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e08201526101008083013581830152506101208083013581830152506101408083013567ffffffffffffffff808211156149d057600080fd5b6149dc8683870161488b565b838501526101609250828501359150808211156149f857600080fd5b614a048683870161488b565b83850152610180925082850135915080821115614a2057600080fd5b614a2c8683870161488b565b838501526101a0925082850135915080821115614a4857600080fd5b50614a558582860161488b565b82840152505092915050565b600060a08284031215614a72578081fd5b614a7c60a0615aed565b90508135815260208201356020820152604082013560408201526060820135614aa481615b88565b6060820152608082013567ffffffffffffffff811115614ac357600080fd5b614acf8482850161488b565b60808301525092915050565b600060208284031215614aec578081fd5b61093283836146d3565b60008060408385031215614b08578081fd5b614b1284846146d3565b9150614b2184602085016146d3565b90509250929050565b60008060408385031215614b3c578182fd5b614b4684846146d3565b915060208301358015158114614b5a578182fd5b809150509250929050565b60008060008060808587031215614b7a578182fd5b843567ffffffffffffffff80821115614b91578384fd5b614b9d8883890161476d565b95506020870135915080821115614bb2578384fd5b614bbe888389016146f7565b94506040870135915080821115614bd3578384fd5b614bdf888389016146f7565b93506060870135915080821115614bf4578283fd5b50614c018782880161482d565b91505092959194509250565b600060208284031215614c1e578081fd5b813567ffffffffffffffff811115614c34578182fd5b610b37848285016147d2565b60008060008060808587031215614c55578182fd5b843567ffffffffffffffff80821115614c6c578384fd5b614c78888389016147d2565b95506020870135915080821115614c8d578384fd5b614c99888389016147d2565b94506040870135915080821115614cae578384fd5b614cba8883890161476d565b93506060870135915080821115614ccf578283fd5b50614c018782880161476d565b600080600060608486031215614cf0578081fd5b833567ffffffffffffffff80821115614d07578283fd5b614d13878388016147d2565b94506020860135915080821115614d28578283fd5b614d348783880161482d565b93506040860135915080821115614d49578283fd5b50614d568682870161476d565b9150509250925092565b600080600060608486031215614d74578081fd5b833567ffffffffffffffff80821115614d8b578283fd5b614d97878388016147d2565b9450602086013593506040860135915080821115614d49578283fd5b60008060408385031215614dc5578182fd5b823567ffffffffffffffff80821115614ddc578384fd5b81850186601f820112614ded578485fd5b80359250614dfd61471584615b14565b83815260208082019190838101885b87811015614e3557614e238c848435890101614a61565b85529382019390820190600101614e0c565b50919750880135945050505080821115614e4d578283fd5b50614e5a8582860161476d565b9150509250929050565b600060208284031215614e75578081fd5b5035919050565b60008060408385031215614e8e578182fd5b823591506020830135614b5a81615b88565b600080600060608486031215614eb4578081fd5b833592506020840135614ec681615b88565b9150604084013567ffffffffffffffff811115614ee1578182fd5b614d568682870161488b565b600060208284031215614efe578081fd5b813561093281615baa565b600060208284031215614f1a578081fd5b815161093281615baa565b600060a0828403128015614f37578182fd5b8015614f41578182fd5b50614f4c60a0615aed565b82518152602083015160208201526040830151604082015260608301516060820152608083015160808201528091505092915050565b600060208284031215614f93578081fd5b813567ffffffffffffffff811115614fa9578182fd5b610b3784828501614912565b60008060408385031215614fc7578182fd5b823567ffffffffffffffff80821115614fde578384fd5b614fea86838701614912565b93506020850135915080821115614fff578283fd5b50614e5a8582860161488b565b60008060008060808587031215615021578182fd5b843567ffffffffffffffff80821115615038578384fd5b61504488838901614912565b95506020870135915080821115615059578384fd5b61506588838901614912565b9450604087013591508082111561507a578384fd5b6150868883890161488b565b9350606087013591508082111561509b578283fd5b50614c018782880161488b565b6000806000606084860312156150bc578081fd5b833567ffffffffffffffff808211156150d3578283fd5b6150df87838801614912565b94506020860135935060408601359150808211156150fb578283fd5b50614d568682870161488b565b6000806040838503121561511a578182fd5b823567ffffffffffffffff80821115615131578384fd5b614fea86838701614a61565b73ffffffffffffffffffffffffffffffffffffffff169052565b6000815180845260208401935060208301825b828110156151935761517d8683516151e7565b60a095909501946020919091019060010161516a565b5093949350505050565b600081518084526151b5816020860160208601615b34565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b80518252602081015160208301526040810151604083015260608101516060830152608081015160808301525050565b60006101c061522784845161513d565b6020830151615239602086018261513d565b50604083015161524c604086018261513d565b50606083015161525f606086018261513d565b506080830151608085015260a083015160a085015260c083015160c085015260e083015160e08501526101008084015181860152506101208084015181860152506101408084015182828701526152b88387018261519d565b915050610160915081840151858203838701526152d5828261519d565b9250505061018080840151858303828701526152f1838261519d565b9150506101a091508184015185820383870152613de2828261519d565b60008251615320818460208701615b34565b9190910192915050565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b600073ffffffffffffffffffffffffffffffffffffffff8616825260806020830152615403608083018661519d565b8281036040840152615415818661519d565b8381036060850152615427818661519d565b98975050505050505050565b6000602080830181845280855180835260408601915060408482028701019250838701855b828110156154a4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261549285835161519d565b94509285019290850190600101615458565b5092979650505050505050565b6000602082526109326020830184615157565b901515815260200190565b90815260200190565b91825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b600085825273ffffffffffffffffffffffffffffffffffffffff8516602083015260806040830152615531608083018561519d565b82810360608401526138a9818561519d565b918252602082015260400190565b600083825260406020830152610b37604083018461519d565b600084825260606020830152615583606083018561519d565b8281036040840152613de2818561519d565b828152604081016155a583615b7e565b8260208301529392505050565b600086825285602083015273ffffffffffffffffffffffffffffffffffffffff808616604084015280851660608401525060a060808301526138a960a083018461519d565b9283526020830191909152604082015260600190565b93845260ff9290921660208401526040830152606082015260800190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b7fffffffff0000000000000000000000000000000000000000000000000000000092909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b600060208252610932602083018461519d565b6000608082526156c6608083018761519d565b73ffffffffffffffffffffffffffffffffffffffff95861660208401529390941660408201526060015292915050565b600060408252615709604083018561519d565b8281036020840152610de6818561519d565b60006060825261572e606083018661519d565b8281036020840152615740818661519d565b91505073ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b600061016080835261577b8184018f61519d565b838103602085015261578d818f61519d565b91505082810360408401526157a2818d61519d565b83810360608501526157b4818d61519d565b73ffffffffffffffffffffffffffffffffffffffff9b8c16608086015299909a1660a0840152505060c081019590955260e08501939093526101008401919091526101208301526101409091015295945050505050565b600061581685615b60565b84825283602083015260606040830152610de6606083018461519d565b6020810161584083615b6a565b91905290565b6060810161585385615b6a565b938152602081019290925260409091015290565b6060810161587485615b74565b938152602081019290925273ffffffffffffffffffffffffffffffffffffffff1660409091015290565b6060810161585385615b74565b606081016008851061585357fe5b60006158c486615b7e565b85825284602083015273ffffffffffffffffffffffffffffffffffffffff8416604083015260806060830152613de2608083018461519d565b6040810161590a84615b60565b9281526020015290565b60208082526014908201527f5452414e53464552535f5355434345535346554c000000000000000000000000604082015260600190565b60006020825282516080602084015261596760a0840182615157565b602085015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08482030160408501526159a28183615157565b604086015160608601526060860151608086015280935050505092915050565b60a081016107c182846151e7565b6000610180820190506159e48284516151e7565b60208301516159f660a08401826151e7565b5060408301516101408301526060909201516101609091015290565b815160ff168152602080830151908201526040918201519181019190915260600190565b600060408252615a496040830185615217565b90508260208301529392505050565b600060608252615a6b6060830186615217565b8460208401528281036040840152613de2818561519d565b60006040825283516040830152602084015160608301526040840151608083015273ffffffffffffffffffffffffffffffffffffffff60608501511660a0830152608084015160a060c0840152615add60e084018261519d565b9150508260208301529392505050565b60405181810167ffffffffffffffff81118282101715615b0c57600080fd5b604052919050565b600067ffffffffffffffff821115615b2a578081fd5b5060209081020190565b60005b83811015615b4f578181015183820152602001615b37565b838111156133265750506000910152565b6002811061080f57fe5b6004811061080f57fe5b6003811061080f57fe5b6007811061080f57fe5b73ffffffffffffffffffffffffffffffffffffffff8116811461080f57600080fd5b7fffffffff000000000000000000000000000000000000000000000000000000008116811461080f57600080fd5b8351602094850120835193850193909320604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815295860194909452928401929092526060830152608082015260a090209056fea365627a7a723158206fc97c5a1d6fde6b2ada9eb4429966e52d7e2da39180893c04bf55c840b346a16c6578706572696d656e74616cf564736f6c634300050c0040'; + /** + * @ignore + */ + public static deployedBytecode: string | undefined; public EIP1271_MAGIC_VALUE = { /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an @@ -151,41 +159,6 @@ export class ExchangeContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ExchangeContract; - const abiEncodedTransactionData = self._strictEncodeArguments('EIP1271_MAGIC_VALUE()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('EIP1271_MAGIC_VALUE()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('EIP1271_MAGIC_VALUE()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public EIP712_EXCHANGE_DOMAIN_HASH = { /** @@ -229,41 +202,6 @@ export class ExchangeContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ExchangeContract; - const abiEncodedTransactionData = self._strictEncodeArguments('EIP712_EXCHANGE_DOMAIN_HASH()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('EIP712_EXCHANGE_DOMAIN_HASH()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('EIP712_EXCHANGE_DOMAIN_HASH()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public allowedValidators = { /** @@ -317,46 +255,6 @@ export class ExchangeContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: string, index_1: string): string { - assert.isString('index_0', index_0); - assert.isString('index_1', index_1); - const self = (this as any) as ExchangeContract; - const abiEncodedTransactionData = self._strictEncodeArguments('allowedValidators(address,address)', [ - index_0.toLowerCase(), - index_1.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('allowedValidators(address,address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('allowedValidators(address,address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Executes multiple calls of cancelOrder. @@ -387,6 +285,7 @@ export class ExchangeContract extends BaseContract { takerFeeAssetData: string; }>, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isArray('orders', orders); const self = (this as any) as ExchangeContract; @@ -406,6 +305,10 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.batchCancelOrders.callAsync(orders, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -435,20 +338,19 @@ export class ExchangeContract extends BaseContract { takerFeeAssetData: string; }>, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isArray('orders', orders); const self = (this as any) as ExchangeContract; - const txHashPromise = self.batchCancelOrders.sendTransactionAsync(orders, txData); + const txHashPromise = self.batchCancelOrders.sendTransactionAsync(orders, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -499,29 +401,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - txData?: Partial | undefined, - ): Promise { - await (this as any).batchCancelOrders.callAsync(orders, txData); - const txHash = await (this as any).batchCancelOrders.sendTransactionAsync(orders, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -622,72 +501,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): [ - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> - ] { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'batchCancelOrders((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - [ - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> - ] - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'batchCancelOrders((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Executes a batch of Exchange method calls in the context of signer(s). @@ -712,6 +525,7 @@ export class ExchangeContract extends BaseContract { }>, signatures: string[], txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isArray('transactions', transactions); assert.isArray('signatures', signatures); @@ -732,6 +546,10 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.batchExecuteTransactions.callAsync(transactions, signatures, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -755,21 +573,25 @@ export class ExchangeContract extends BaseContract { }>, signatures: string[], txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isArray('transactions', transactions); assert.isArray('signatures', signatures); const self = (this as any) as ExchangeContract; - const txHashPromise = self.batchExecuteTransactions.sendTransactionAsync(transactions, signatures, txData); + const txHashPromise = self.batchExecuteTransactions.sendTransactionAsync( + transactions, + signatures, + txData, + opts, + ); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -815,25 +637,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - transactions: Array<{ - salt: BigNumber; - expirationTimeSeconds: BigNumber; - gasPrice: BigNumber; - signerAddress: string; - data: string; - }>, - signatures: string[], - txData?: Partial | undefined, - ): Promise { - await (this as any).batchExecuteTransactions.callAsync(transactions, signatures, txData); - const txHash = await (this as any).batchExecuteTransactions.sendTransactionAsync( - transactions, - signatures, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -925,50 +728,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): Array<{ - salt: BigNumber; - expirationTimeSeconds: BigNumber; - gasPrice: BigNumber; - signerAddress: string; - data: string; - }> { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'batchExecuteTransactions((uint256,uint256,uint256,address,bytes)[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - Array<{ - salt: BigNumber; - expirationTimeSeconds: BigNumber; - gasPrice: BigNumber; - signerAddress: string; - data: string; - }> - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string[] { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'batchExecuteTransactions((uint256,uint256,uint256,address,bytes)[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Executes multiple calls of fillOrKillOrder. @@ -1004,6 +763,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmounts: BigNumber[], signatures: string[], txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isArray('orders', orders); assert.isArray('takerAssetFillAmounts', takerAssetFillAmounts); @@ -1025,6 +785,15 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.batchFillOrKillOrders.callAsync( + orders, + takerAssetFillAmounts, + signatures, + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1059,8 +828,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmounts: BigNumber[], signatures: string[], txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isArray('orders', orders); assert.isArray('takerAssetFillAmounts', takerAssetFillAmounts); @@ -1071,6 +839,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmounts, signatures, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -1078,8 +847,8 @@ export class ExchangeContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1137,36 +906,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - takerAssetFillAmounts: BigNumber[], - signatures: string[], - txData?: Partial | undefined, - ): Promise { - await (this as any).batchFillOrKillOrders.callAsync(orders, takerAssetFillAmounts, signatures, txData); - const txHash = await (this as any).batchFillOrKillOrders.sendTransactionAsync( - orders, - takerAssetFillAmounts, - signatures, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1298,84 +1037,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'batchFillOrKillOrders((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): Array<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }> { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'batchFillOrKillOrders((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue< - Array<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }> - >(returnData); - return abiDecodedReturnData; - }, }; /** * Executes multiple calls of fillOrder. @@ -1411,6 +1072,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmounts: BigNumber[], signatures: string[], txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isArray('orders', orders); assert.isArray('takerAssetFillAmounts', takerAssetFillAmounts); @@ -1432,6 +1094,10 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.batchFillOrders.callAsync(orders, takerAssetFillAmounts, signatures, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1466,8 +1132,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmounts: BigNumber[], signatures: string[], txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isArray('orders', orders); assert.isArray('takerAssetFillAmounts', takerAssetFillAmounts); @@ -1478,6 +1143,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmounts, signatures, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -1485,8 +1151,8 @@ export class ExchangeContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1544,47 +1210,17 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - takerAssetFillAmounts: BigNumber[], - signatures: string[], - txData?: Partial | undefined, - ): Promise { - await (this as any).batchFillOrders.callAsync(orders, takerAssetFillAmounts, signatures, txData); - const txHash = await (this as any).batchFillOrders.sendTransactionAsync( - orders, - takerAssetFillAmounts, - signatures, - txData, - ); - return txHash; - }, - /** - * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an - * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas - * since they don't modify state. - * @param orders Array of order specifications. - * @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell - * in orders. - * @param signatures Proofs that orders have been created by makers. - * @returns Array of amounts filled and fees paid by makers and taker. - */ - async callAsync( + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + * @param orders Array of order specifications. + * @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell + * in orders. + * @param signatures Proofs that orders have been created by makers. + * @returns Array of amounts filled and fees paid by makers and taker. + */ + async callAsync( orders: Array<{ makerAddress: string; takerAddress: string; @@ -1705,84 +1341,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'batchFillOrders((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): Array<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }> { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'batchFillOrders((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue< - Array<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }> - >(returnData); - return abiDecodedReturnData; - }, }; /** * Executes multiple calls of fillOrder. If any fill reverts, the error is caught and ignored. @@ -1818,6 +1376,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmounts: BigNumber[], signatures: string[], txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isArray('orders', orders); assert.isArray('takerAssetFillAmounts', takerAssetFillAmounts); @@ -1839,6 +1398,15 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.batchFillOrdersNoThrow.callAsync( + orders, + takerAssetFillAmounts, + signatures, + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1873,8 +1441,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmounts: BigNumber[], signatures: string[], txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isArray('orders', orders); assert.isArray('takerAssetFillAmounts', takerAssetFillAmounts); @@ -1885,6 +1452,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmounts, signatures, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -1892,8 +1460,8 @@ export class ExchangeContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1951,36 +1519,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - takerAssetFillAmounts: BigNumber[], - signatures: string[], - txData?: Partial | undefined, - ): Promise { - await (this as any).batchFillOrdersNoThrow.callAsync(orders, takerAssetFillAmounts, signatures, txData); - const txHash = await (this as any).batchFillOrdersNoThrow.sendTransactionAsync( - orders, - takerAssetFillAmounts, - signatures, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -2112,84 +1650,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'batchFillOrdersNoThrow((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): Array<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }> { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'batchFillOrdersNoThrow((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue< - Array<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }> - >(returnData); - return abiDecodedReturnData; - }, }; /** * Match complementary orders that have a profitable spread. @@ -2245,6 +1705,7 @@ export class ExchangeContract extends BaseContract { leftSignatures: string[], rightSignatures: string[], txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isArray('leftOrders', leftOrders); assert.isArray('rightOrders', rightOrders); @@ -2267,6 +1728,16 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.batchMatchOrders.callAsync( + leftOrders, + rightOrders, + leftSignatures, + rightSignatures, + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -2319,8 +1790,7 @@ export class ExchangeContract extends BaseContract { leftSignatures: string[], rightSignatures: string[], txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isArray('leftOrders', leftOrders); assert.isArray('rightOrders', rightOrders); @@ -2333,6 +1803,7 @@ export class ExchangeContract extends BaseContract { leftSignatures, rightSignatures, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -2340,8 +1811,8 @@ export class ExchangeContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -2418,59 +1889,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - leftOrders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - rightOrders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - leftSignatures: string[], - rightSignatures: string[], - txData?: Partial | undefined, - ): Promise { - await (this as any).batchMatchOrders.callAsync( - leftOrders, - rightOrders, - leftSignatures, - rightSignatures, - txData, - ); - const txHash = await (this as any).batchMatchOrders.sendTransactionAsync( - leftOrders, - rightOrders, - leftSignatures, - rightSignatures, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -2658,123 +2076,25 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, + }; + /** + * Match complementary orders that have a profitable spread. + * Each order is maximally filled at their respective price point, and + * the matcher receives a profit denominated in either the left maker asset, + * right maker asset, or a combination of both. + */ + public batchMatchOrdersWithMaximalFill = { /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'batchMatchOrders((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): { - left: Array<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }>; - right: Array<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }>; - profitInLeftMakerAsset: BigNumber; - profitInRightMakerAsset: BigNumber; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'batchMatchOrders((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<{ - left: Array<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }>; - right: Array<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }>; - profitInLeftMakerAsset: BigNumber; - profitInRightMakerAsset: BigNumber; - }>(returnData); - return abiDecodedReturnData; - }, - }; - /** - * Match complementary orders that have a profitable spread. - * Each order is maximally filled at their respective price point, and - * the matcher receives a profit denominated in either the left maker asset, - * right maker asset, or a combination of both. - */ - public batchMatchOrdersWithMaximalFill = { - /** - * Sends an Ethereum transaction executing this method with the supplied parameters. This is a read/write - * Ethereum operation and will cost gas. - * @param leftOrders Set of orders with the same maker / taker asset. - * @param rightOrders Set of orders to match against `leftOrders` - * @param leftSignatures Proof that left orders were created by the left - * makers. - * @param rightSignatures Proof that right orders were created by the right - * makers. - * @param txData Additional data for transaction - * @returns The hash of the transaction + * Sends an Ethereum transaction executing this method with the supplied parameters. This is a read/write + * Ethereum operation and will cost gas. + * @param leftOrders Set of orders with the same maker / taker asset. + * @param rightOrders Set of orders to match against `leftOrders` + * @param leftSignatures Proof that left orders were created by the left + * makers. + * @param rightSignatures Proof that right orders were created by the right + * makers. + * @param txData Additional data for transaction + * @returns The hash of the transaction */ async sendTransactionAsync( leftOrders: Array<{ @@ -2812,6 +2132,7 @@ export class ExchangeContract extends BaseContract { leftSignatures: string[], rightSignatures: string[], txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isArray('leftOrders', leftOrders); assert.isArray('rightOrders', rightOrders); @@ -2834,6 +2155,16 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.batchMatchOrdersWithMaximalFill.callAsync( + leftOrders, + rightOrders, + leftSignatures, + rightSignatures, + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -2886,8 +2217,7 @@ export class ExchangeContract extends BaseContract { leftSignatures: string[], rightSignatures: string[], txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isArray('leftOrders', leftOrders); assert.isArray('rightOrders', rightOrders); @@ -2900,6 +2230,7 @@ export class ExchangeContract extends BaseContract { leftSignatures, rightSignatures, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -2907,8 +2238,8 @@ export class ExchangeContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -2985,59 +2316,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - leftOrders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - rightOrders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - leftSignatures: string[], - rightSignatures: string[], - txData?: Partial | undefined, - ): Promise { - await (this as any).batchMatchOrdersWithMaximalFill.callAsync( - leftOrders, - rightOrders, - leftSignatures, - rightSignatures, - txData, - ); - const txHash = await (this as any).batchMatchOrdersWithMaximalFill.sendTransactionAsync( - leftOrders, - rightOrders, - leftSignatures, - rightSignatures, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -3225,104 +2503,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'batchMatchOrdersWithMaximalFill((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): { - left: Array<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }>; - right: Array<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }>; - profitInLeftMakerAsset: BigNumber; - profitInRightMakerAsset: BigNumber; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'batchMatchOrdersWithMaximalFill((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<{ - left: Array<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }>; - right: Array<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }>; - profitInLeftMakerAsset: BigNumber; - profitInRightMakerAsset: BigNumber; - }>(returnData); - return abiDecodedReturnData; - }, }; /** * After calling, the order can not be filled anymore. @@ -3353,6 +2533,7 @@ export class ExchangeContract extends BaseContract { takerFeeAssetData: string; }, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { const self = (this as any) as ExchangeContract; const encodedData = self._strictEncodeArguments( @@ -3371,6 +2552,10 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.cancelOrder.callAsync(order, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -3400,19 +2585,18 @@ export class ExchangeContract extends BaseContract { takerFeeAssetData: string; }, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { const self = (this as any) as ExchangeContract; - const txHashPromise = self.cancelOrder.sendTransactionAsync(order, txData); + const txHashPromise = self.cancelOrder.sendTransactionAsync(order, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -3462,29 +2646,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - order: { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }, - txData?: Partial | undefined, - ): Promise { - await (this as any).cancelOrder.callAsync(order, txData); - const txHash = await (this as any).cancelOrder.sendTransactionAsync(order, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -3581,72 +2742,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): [ - { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - } - ] { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'cancelOrder((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes))', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - [ - { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - } - ] - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'cancelOrder((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes))', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Cancels all orders created by makerAddress with a salt less than or equal to the targetOrderEpoch @@ -3661,7 +2756,11 @@ export class ExchangeContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(targetOrderEpoch: BigNumber, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + targetOrderEpoch: BigNumber, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isBigNumber('targetOrderEpoch', targetOrderEpoch); const self = (this as any) as ExchangeContract; const encodedData = self._strictEncodeArguments('cancelOrdersUpTo(uint256)', [targetOrderEpoch]); @@ -3677,6 +2776,10 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.cancelOrdersUpTo.callAsync(targetOrderEpoch, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -3692,20 +2795,19 @@ export class ExchangeContract extends BaseContract { awaitTransactionSuccessAsync( targetOrderEpoch: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isBigNumber('targetOrderEpoch', targetOrderEpoch); const self = (this as any) as ExchangeContract; - const txHashPromise = self.cancelOrdersUpTo.sendTransactionAsync(targetOrderEpoch, txData); + const txHashPromise = self.cancelOrdersUpTo.sendTransactionAsync(targetOrderEpoch, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -3736,14 +2838,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - targetOrderEpoch: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).cancelOrdersUpTo.callAsync(targetOrderEpoch, txData); - const txHash = await (this as any).cancelOrdersUpTo.sendTransactionAsync(targetOrderEpoch, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -3808,30 +2902,6 @@ export class ExchangeContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [BigNumber] { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('cancelOrdersUpTo(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('cancelOrdersUpTo(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public cancelled = { /** @@ -3880,48 +2950,12 @@ export class ExchangeContract extends BaseContract { // tslint:enable boolean-naming return result; }, + }; + public currentContextAddress = { /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: string): string { - assert.isString('index_0', index_0); - const self = (this as any) as ExchangeContract; - const abiEncodedTransactionData = self._strictEncodeArguments('cancelled(bytes32)', [index_0]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('cancelled(bytes32)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('cancelled(bytes32)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, - }; - public currentContextAddress = { - /** - * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an - * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas - * since they don't modify state. + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. */ async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ @@ -3959,41 +2993,6 @@ export class ExchangeContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ExchangeContract; - const abiEncodedTransactionData = self._strictEncodeArguments('currentContextAddress()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('currentContextAddress()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('currentContextAddress()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Executes an Exchange method call in the context of signer. @@ -4017,6 +3016,7 @@ export class ExchangeContract extends BaseContract { }, signature: string, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('signature', signature); const self = (this as any) as ExchangeContract; @@ -4036,6 +3036,10 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.executeTransaction.callAsync(transaction, signature, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -4058,20 +3062,19 @@ export class ExchangeContract extends BaseContract { }, signature: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('signature', signature); const self = (this as any) as ExchangeContract; - const txHashPromise = self.executeTransaction.sendTransactionAsync(transaction, signature, txData); + const txHashPromise = self.executeTransaction.sendTransactionAsync(transaction, signature, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -4115,21 +3118,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - transaction: { - salt: BigNumber; - expirationTimeSeconds: BigNumber; - gasPrice: BigNumber; - signerAddress: string; - data: string; - }, - signature: string, - txData?: Partial | undefined, - ): Promise { - await (this as any).executeTransaction.callAsync(transaction, signature, txData); - const txHash = await (this as any).executeTransaction.sendTransactionAsync(transaction, signature, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -4217,48 +3205,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): { - salt: BigNumber; - expirationTimeSeconds: BigNumber; - gasPrice: BigNumber; - signerAddress: string; - data: string; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'executeTransaction((uint256,uint256,uint256,address,bytes),bytes)', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<{ - salt: BigNumber; - expirationTimeSeconds: BigNumber; - gasPrice: BigNumber; - signerAddress: string; - data: string; - }>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'executeTransaction((uint256,uint256,uint256,address,bytes),bytes)', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Fills the input order. Reverts if exact takerAssetFillAmount not filled. @@ -4293,6 +3239,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmount: BigNumber, signature: string, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); assert.isString('signature', signature); @@ -4313,6 +3260,10 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.fillOrKillOrder.callAsync(order, takerAssetFillAmount, signature, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -4346,8 +3297,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmount: BigNumber, signature: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); assert.isString('signature', signature); @@ -4357,6 +3307,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmount, signature, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -4364,8 +3315,8 @@ export class ExchangeContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -4421,36 +3372,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - order: { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }, - takerAssetFillAmount: BigNumber, - signature: string, - txData?: Partial | undefined, - ): Promise { - await (this as any).fillOrKillOrder.callAsync(order, takerAssetFillAmount, signature, txData); - const txHash = await (this as any).fillOrKillOrder.sendTransactionAsync( - order, - takerAssetFillAmount, - signature, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -4573,80 +3494,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'fillOrKillOrder((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),uint256,bytes)', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'fillOrKillOrder((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),uint256,bytes)', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }>(returnData); - return abiDecodedReturnData; - }, }; /** * Fills the input order. @@ -4681,6 +3528,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmount: BigNumber, signature: string, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); assert.isString('signature', signature); @@ -4701,6 +3549,10 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.fillOrder.callAsync(order, takerAssetFillAmount, signature, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -4734,21 +3586,26 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmount: BigNumber, signature: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); assert.isString('signature', signature); const self = (this as any) as ExchangeContract; - const txHashPromise = self.fillOrder.sendTransactionAsync(order, takerAssetFillAmount, signature, txData); + const txHashPromise = self.fillOrder.sendTransactionAsync( + order, + takerAssetFillAmount, + signature, + txData, + opts, + ); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -4804,36 +3661,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - order: { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }, - takerAssetFillAmount: BigNumber, - signature: string, - txData?: Partial | undefined, - ): Promise { - await (this as any).fillOrder.callAsync(order, takerAssetFillAmount, signature, txData); - const txHash = await (this as any).fillOrder.sendTransactionAsync( - order, - takerAssetFillAmount, - signature, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -4957,80 +3784,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'fillOrder((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),uint256,bytes)', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'fillOrder((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),uint256,bytes)', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }>(returnData); - return abiDecodedReturnData; - }, }; public filled = { /** @@ -5079,47 +3832,11 @@ export class ExchangeContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: string): string { - assert.isString('index_0', index_0); - const self = (this as any) as ExchangeContract; - const abiEncodedTransactionData = self._strictEncodeArguments('filled(bytes32)', [index_0]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('filled(bytes32)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('filled(bytes32)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, - }; - /** - * Gets an asset proxy. - */ - public getAssetProxy = { + }; + /** + * Gets an asset proxy. + */ + public getAssetProxy = { /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -5168,43 +3885,6 @@ export class ExchangeContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param assetProxyId Id of the asset proxy. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(assetProxyId: string): string { - assert.isString('assetProxyId', assetProxyId); - const self = (this as any) as ExchangeContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getAssetProxy(bytes4)', [assetProxyId]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('getAssetProxy(bytes4)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('getAssetProxy(bytes4)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Gets information about an order: status, hash, and amount filled. @@ -5281,102 +3961,6 @@ export class ExchangeContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param order Order to gather information on. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(order: { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }): string { - const self = (this as any) as ExchangeContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'getOrderInfo((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes))', - [order], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'getOrderInfo((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes))', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): { orderStatus: number; orderHash: string; orderTakerAssetFilledAmount: BigNumber } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'getOrderInfo((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes))', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<{ - orderStatus: number; - orderHash: string; - orderTakerAssetFilledAmount: BigNumber; - }>(returnData); - return abiDecodedReturnData; - }, }; /** * Verifies that a hash has been signed by the given signer. @@ -5440,50 +4024,6 @@ export class ExchangeContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param hash Any 32-byte hash. - * @param signerAddress Address that should have signed the given hash. - * @param signature Proof that the hash has been signed by signer. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(hash: string, signerAddress: string, signature: string): string { - assert.isString('hash', hash); - assert.isString('signerAddress', signerAddress); - assert.isString('signature', signature); - const self = (this as any) as ExchangeContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'isValidHashSignature(bytes32,address,bytes)', - [hash, signerAddress.toLowerCase(), signature], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('isValidHashSignature(bytes32,address,bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('isValidHashSignature(bytes32,address,bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Verifies that a signature for an order is valid. @@ -5559,101 +4099,6 @@ export class ExchangeContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param order The order. - * @param signature Proof that the order has been signed by signer. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData( - order: { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }, - signature: string, - ): string { - assert.isString('signature', signature); - const self = (this as any) as ExchangeContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'isValidOrderSignature((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),bytes)', - [order, signature], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'isValidOrderSignature((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),bytes)', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'isValidOrderSignature((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),bytes)', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Verifies that a signature for a transaction is valid. @@ -5720,74 +4165,6 @@ export class ExchangeContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param transaction The transaction. - * @param signature Proof that the order has been signed by signer. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData( - transaction: { - salt: BigNumber; - expirationTimeSeconds: BigNumber; - gasPrice: BigNumber; - signerAddress: string; - data: string; - }, - signature: string, - ): string { - assert.isString('signature', signature); - const self = (this as any) as ExchangeContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'isValidTransactionSignature((uint256,uint256,uint256,address,bytes),bytes)', - [transaction, signature], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): { - salt: BigNumber; - expirationTimeSeconds: BigNumber; - gasPrice: BigNumber; - signerAddress: string; - data: string; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'isValidTransactionSignature((uint256,uint256,uint256,address,bytes),bytes)', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<{ - salt: BigNumber; - expirationTimeSeconds: BigNumber; - gasPrice: BigNumber; - signerAddress: string; - data: string; - }>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'isValidTransactionSignature((uint256,uint256,uint256,address,bytes),bytes)', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Calls marketBuyOrdersNoThrow then reverts if < makerAssetFillAmount has been bought. @@ -5823,6 +4200,7 @@ export class ExchangeContract extends BaseContract { makerAssetFillAmount: BigNumber, signatures: string[], txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isArray('orders', orders); assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); @@ -5844,6 +4222,15 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.marketBuyOrdersFillOrKill.callAsync( + orders, + makerAssetFillAmount, + signatures, + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -5877,8 +4264,7 @@ export class ExchangeContract extends BaseContract { makerAssetFillAmount: BigNumber, signatures: string[], txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isArray('orders', orders); assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); @@ -5889,6 +4275,7 @@ export class ExchangeContract extends BaseContract { makerAssetFillAmount, signatures, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -5896,8 +4283,8 @@ export class ExchangeContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -5954,36 +4341,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - makerAssetFillAmount: BigNumber, - signatures: string[], - txData?: Partial | undefined, - ): Promise { - await (this as any).marketBuyOrdersFillOrKill.callAsync(orders, makerAssetFillAmount, signatures, txData); - const txHash = await (this as any).marketBuyOrdersFillOrKill.sendTransactionAsync( - orders, - makerAssetFillAmount, - signatures, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -6109,82 +4466,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'marketBuyOrdersFillOrKill((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256,bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'marketBuyOrdersFillOrKill((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256,bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }>(returnData); - return abiDecodedReturnData; - }, }; /** * Executes multiple calls of fillOrder until total amount of makerAsset is bought by taker. @@ -6221,6 +4502,7 @@ export class ExchangeContract extends BaseContract { makerAssetFillAmount: BigNumber, signatures: string[], txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isArray('orders', orders); assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); @@ -6242,6 +4524,15 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.marketBuyOrdersNoThrow.callAsync( + orders, + makerAssetFillAmount, + signatures, + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -6275,8 +4566,7 @@ export class ExchangeContract extends BaseContract { makerAssetFillAmount: BigNumber, signatures: string[], txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isArray('orders', orders); assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); @@ -6287,6 +4577,7 @@ export class ExchangeContract extends BaseContract { makerAssetFillAmount, signatures, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -6294,8 +4585,8 @@ export class ExchangeContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -6332,55 +4623,25 @@ export class ExchangeContract extends BaseContract { assert.isArray('orders', orders); assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); assert.isArray('signatures', signatures); - const self = (this as any) as ExchangeContract; - const encodedData = self._strictEncodeArguments( - 'marketBuyOrdersNoThrow((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256,bytes[])', - [orders, makerAssetFillAmount, signatures], - ); - const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( - { - to: self.address, - ...txData, - data: encodedData, - }, - self._web3Wrapper.getContractDefaults(), - ); - if (txDataWithDefaults.from !== undefined) { - txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); - } - - const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); - return gas; - }, - async validateAndSendTransactionAsync( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - makerAssetFillAmount: BigNumber, - signatures: string[], - txData?: Partial | undefined, - ): Promise { - await (this as any).marketBuyOrdersNoThrow.callAsync(orders, makerAssetFillAmount, signatures, txData); - const txHash = await (this as any).marketBuyOrdersNoThrow.sendTransactionAsync( - orders, - makerAssetFillAmount, - signatures, - txData, + const self = (this as any) as ExchangeContract; + const encodedData = self._strictEncodeArguments( + 'marketBuyOrdersNoThrow((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256,bytes[])', + [orders, makerAssetFillAmount, signatures], ); - return txHash; + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); + return gas; }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an @@ -6507,82 +4768,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'marketBuyOrdersNoThrow((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256,bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'marketBuyOrdersNoThrow((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256,bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }>(returnData); - return abiDecodedReturnData; - }, }; /** * Calls marketSellOrdersNoThrow then reverts if < takerAssetFillAmount has been sold. @@ -6618,6 +4803,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmount: BigNumber, signatures: string[], txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isArray('orders', orders); assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); @@ -6639,6 +4825,15 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.marketSellOrdersFillOrKill.callAsync( + orders, + takerAssetFillAmount, + signatures, + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -6672,8 +4867,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmount: BigNumber, signatures: string[], txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isArray('orders', orders); assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); @@ -6684,6 +4878,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmount, signatures, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -6691,8 +4886,8 @@ export class ExchangeContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -6749,36 +4944,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - takerAssetFillAmount: BigNumber, - signatures: string[], - txData?: Partial | undefined, - ): Promise { - await (this as any).marketSellOrdersFillOrKill.callAsync(orders, takerAssetFillAmount, signatures, txData); - const txHash = await (this as any).marketSellOrdersFillOrKill.sendTransactionAsync( - orders, - takerAssetFillAmount, - signatures, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -6904,82 +5069,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'marketSellOrdersFillOrKill((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256,bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'marketSellOrdersFillOrKill((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256,bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }>(returnData); - return abiDecodedReturnData; - }, }; /** * Executes multiple calls of fillOrder until total amount of takerAsset is sold by taker. @@ -7016,6 +5105,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmount: BigNumber, signatures: string[], txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isArray('orders', orders); assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); @@ -7037,6 +5127,15 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.marketSellOrdersNoThrow.callAsync( + orders, + takerAssetFillAmount, + signatures, + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -7070,8 +5169,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmount: BigNumber, signatures: string[], txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isArray('orders', orders); assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); @@ -7082,6 +5180,7 @@ export class ExchangeContract extends BaseContract { takerAssetFillAmount, signatures, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -7089,8 +5188,8 @@ export class ExchangeContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -7147,36 +5246,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - takerAssetFillAmount: BigNumber, - signatures: string[], - txData?: Partial | undefined, - ): Promise { - await (this as any).marketSellOrdersNoThrow.callAsync(orders, takerAssetFillAmount, signatures, txData); - const txHash = await (this as any).marketSellOrdersNoThrow.sendTransactionAsync( - orders, - takerAssetFillAmount, - signatures, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -7302,82 +5371,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'marketSellOrdersNoThrow((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256,bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }> - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'marketSellOrdersNoThrow((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256,bytes[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<{ - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }>(returnData); - return abiDecodedReturnData; - }, }; /** * Match two complementary orders that have a profitable spread. @@ -7432,6 +5425,7 @@ export class ExchangeContract extends BaseContract { leftSignature: string, rightSignature: string, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('leftSignature', leftSignature); assert.isString('rightSignature', rightSignature); @@ -7452,6 +5446,16 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.matchOrders.callAsync( + leftOrder, + rightOrder, + leftSignature, + rightSignature, + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -7502,8 +5506,7 @@ export class ExchangeContract extends BaseContract { leftSignature: string, rightSignature: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('leftSignature', leftSignature); assert.isString('rightSignature', rightSignature); @@ -7514,6 +5517,7 @@ export class ExchangeContract extends BaseContract { leftSignature, rightSignature, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -7521,8 +5525,8 @@ export class ExchangeContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -7590,57 +5594,10 @@ export class ExchangeContract extends BaseContract { ); if (txDataWithDefaults.from !== undefined) { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); - } - - const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); - return gas; - }, - async validateAndSendTransactionAsync( - leftOrder: { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }, - rightOrder: { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }, - leftSignature: string, - rightSignature: string, - txData?: Partial | undefined, - ): Promise { - await (this as any).matchOrders.callAsync(leftOrder, rightOrder, leftSignature, rightSignature, txData); - const txHash = await (this as any).matchOrders.sendTransactionAsync( - leftOrder, - rightOrder, - leftSignature, - rightSignature, - txData, - ); - return txHash; + } + + const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); + return gas; }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an @@ -7821,102 +5778,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'matchOrders((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),bytes,bytes)', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): { - left: { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }; - right: { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }; - profitInLeftMakerAsset: BigNumber; - profitInRightMakerAsset: BigNumber; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'matchOrders((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),bytes,bytes)', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<{ - left: { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }; - right: { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }; - profitInLeftMakerAsset: BigNumber; - profitInRightMakerAsset: BigNumber; - }>(returnData); - return abiDecodedReturnData; - }, }; /** * Match two complementary orders that have a profitable spread. @@ -7971,6 +5832,7 @@ export class ExchangeContract extends BaseContract { leftSignature: string, rightSignature: string, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('leftSignature', leftSignature); assert.isString('rightSignature', rightSignature); @@ -7991,6 +5853,16 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.matchOrdersWithMaximalFill.callAsync( + leftOrder, + rightOrder, + leftSignature, + rightSignature, + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -8041,8 +5913,7 @@ export class ExchangeContract extends BaseContract { leftSignature: string, rightSignature: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('leftSignature', leftSignature); assert.isString('rightSignature', rightSignature); @@ -8053,6 +5924,7 @@ export class ExchangeContract extends BaseContract { leftSignature, rightSignature, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -8060,8 +5932,8 @@ export class ExchangeContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -8134,59 +6006,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - leftOrder: { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }, - rightOrder: { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }, - leftSignature: string, - rightSignature: string, - txData?: Partial | undefined, - ): Promise { - await (this as any).matchOrdersWithMaximalFill.callAsync( - leftOrder, - rightOrder, - leftSignature, - rightSignature, - txData, - ); - const txHash = await (this as any).matchOrdersWithMaximalFill.sendTransactionAsync( - leftOrder, - rightOrder, - leftSignature, - rightSignature, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -8366,102 +6185,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'matchOrdersWithMaximalFill((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),bytes,bytes)', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): { - left: { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }; - right: { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }; - profitInLeftMakerAsset: BigNumber; - profitInRightMakerAsset: BigNumber; - } { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'matchOrdersWithMaximalFill((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes),bytes,bytes)', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<{ - left: { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }; - right: { - makerAssetFilledAmount: BigNumber; - takerAssetFilledAmount: BigNumber; - makerFeePaid: BigNumber; - takerFeePaid: BigNumber; - protocolFeePaid: BigNumber; - }; - profitInLeftMakerAsset: BigNumber; - profitInRightMakerAsset: BigNumber; - }>(returnData); - return abiDecodedReturnData; - }, }; public orderEpoch = { /** @@ -8515,46 +6238,6 @@ export class ExchangeContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: string, index_1: string): string { - assert.isString('index_0', index_0); - assert.isString('index_1', index_1); - const self = (this as any) as ExchangeContract; - const abiEncodedTransactionData = self._strictEncodeArguments('orderEpoch(address,address)', [ - index_0.toLowerCase(), - index_1.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('orderEpoch(address,address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('orderEpoch(address,address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public owner = { /** @@ -8598,41 +6281,6 @@ export class ExchangeContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ExchangeContract; - const abiEncodedTransactionData = self._strictEncodeArguments('owner()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('owner()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('owner()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Approves a hash on-chain. @@ -8646,7 +6294,11 @@ export class ExchangeContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(hash: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + hash: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('hash', hash); const self = (this as any) as ExchangeContract; const encodedData = self._strictEncodeArguments('preSign(bytes32)', [hash]); @@ -8662,6 +6314,10 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.preSign.callAsync(hash, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -8676,20 +6332,19 @@ export class ExchangeContract extends BaseContract { awaitTransactionSuccessAsync( hash: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('hash', hash); const self = (this as any) as ExchangeContract; - const txHashPromise = self.preSign.sendTransactionAsync(hash, txData); + const txHashPromise = self.preSign.sendTransactionAsync(hash, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -8719,11 +6374,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(hash: string, txData?: Partial | undefined): Promise { - await (this as any).preSign.callAsync(hash, txData); - const txHash = await (this as any).preSign.sendTransactionAsync(hash, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -8780,30 +6430,6 @@ export class ExchangeContract extends BaseContract { const abiEncodedTransactionData = self._strictEncodeArguments('preSign(bytes32)', [hash]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('preSign(bytes32)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('preSign(bytes32)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public preSigned = { /** @@ -8857,46 +6483,6 @@ export class ExchangeContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: string, index_1: string): string { - assert.isString('index_0', index_0); - assert.isString('index_1', index_1); - const self = (this as any) as ExchangeContract; - const abiEncodedTransactionData = self._strictEncodeArguments('preSigned(bytes32,address)', [ - index_0, - index_1.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('preSigned(bytes32,address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('preSigned(bytes32,address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public protocolFeeCollector = { /** @@ -8940,41 +6526,6 @@ export class ExchangeContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ExchangeContract; - const abiEncodedTransactionData = self._strictEncodeArguments('protocolFeeCollector()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('protocolFeeCollector()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('protocolFeeCollector()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public protocolFeeMultiplier = { /** @@ -9018,41 +6569,6 @@ export class ExchangeContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ExchangeContract; - const abiEncodedTransactionData = self._strictEncodeArguments('protocolFeeMultiplier()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('protocolFeeMultiplier()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('protocolFeeMultiplier()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Registers an asset proxy to its asset proxy id. @@ -9066,7 +6582,11 @@ export class ExchangeContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(assetProxy: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + assetProxy: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('assetProxy', assetProxy); const self = (this as any) as ExchangeContract; const encodedData = self._strictEncodeArguments('registerAssetProxy(address)', [assetProxy.toLowerCase()]); @@ -9082,6 +6602,10 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.registerAssetProxy.callAsync(assetProxy, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -9096,20 +6620,19 @@ export class ExchangeContract extends BaseContract { awaitTransactionSuccessAsync( assetProxy: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('assetProxy', assetProxy); const self = (this as any) as ExchangeContract; - const txHashPromise = self.registerAssetProxy.sendTransactionAsync(assetProxy.toLowerCase(), txData); + const txHashPromise = self.registerAssetProxy.sendTransactionAsync(assetProxy.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -9139,14 +6662,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - assetProxy: string, - txData?: Partial | undefined, - ): Promise { - await (this as any).registerAssetProxy.callAsync(assetProxy, txData); - const txHash = await (this as any).registerAssetProxy.sendTransactionAsync(assetProxy, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -9209,30 +6724,6 @@ export class ExchangeContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('registerAssetProxy(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('registerAssetProxy(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Allows the owner to update the protocolFeeCollector address. @@ -9249,6 +6740,7 @@ export class ExchangeContract extends BaseContract { async sendTransactionAsync( updatedProtocolFeeCollector: string, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('updatedProtocolFeeCollector', updatedProtocolFeeCollector); const self = (this as any) as ExchangeContract; @@ -9267,6 +6759,10 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.setProtocolFeeCollectorAddress.callAsync(updatedProtocolFeeCollector, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -9282,14 +6778,14 @@ export class ExchangeContract extends BaseContract { awaitTransactionSuccessAsync( updatedProtocolFeeCollector: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('updatedProtocolFeeCollector', updatedProtocolFeeCollector); const self = (this as any) as ExchangeContract; const txHashPromise = self.setProtocolFeeCollectorAddress.sendTransactionAsync( updatedProtocolFeeCollector.toLowerCase(), txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -9297,8 +6793,8 @@ export class ExchangeContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -9334,17 +6830,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - updatedProtocolFeeCollector: string, - txData?: Partial | undefined, - ): Promise { - await (this as any).setProtocolFeeCollectorAddress.callAsync(updatedProtocolFeeCollector, txData); - const txHash = await (this as any).setProtocolFeeCollectorAddress.sendTransactionAsync( - updatedProtocolFeeCollector, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -9411,30 +6896,6 @@ export class ExchangeContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('setProtocolFeeCollectorAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('setProtocolFeeCollectorAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Allows the owner to update the protocol fee multiplier. @@ -9450,6 +6911,7 @@ export class ExchangeContract extends BaseContract { async sendTransactionAsync( updatedProtocolFeeMultiplier: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isBigNumber('updatedProtocolFeeMultiplier', updatedProtocolFeeMultiplier); const self = (this as any) as ExchangeContract; @@ -9468,6 +6930,10 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.setProtocolFeeMultiplier.callAsync(updatedProtocolFeeMultiplier, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -9482,14 +6948,14 @@ export class ExchangeContract extends BaseContract { awaitTransactionSuccessAsync( updatedProtocolFeeMultiplier: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isBigNumber('updatedProtocolFeeMultiplier', updatedProtocolFeeMultiplier); const self = (this as any) as ExchangeContract; const txHashPromise = self.setProtocolFeeMultiplier.sendTransactionAsync( updatedProtocolFeeMultiplier, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -9497,8 +6963,8 @@ export class ExchangeContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -9533,17 +6999,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - updatedProtocolFeeMultiplier: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).setProtocolFeeMultiplier.callAsync(updatedProtocolFeeMultiplier, txData); - const txHash = await (this as any).setProtocolFeeMultiplier.sendTransactionAsync( - updatedProtocolFeeMultiplier, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -9608,30 +7063,6 @@ export class ExchangeContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [BigNumber] { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('setProtocolFeeMultiplier(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('setProtocolFeeMultiplier(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Approves/unnapproves a Validator contract to verify signatures on signer's behalf @@ -9650,6 +7081,7 @@ export class ExchangeContract extends BaseContract { validatorAddress: string, approval: boolean, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('validatorAddress', validatorAddress); assert.isBoolean('approval', approval); @@ -9670,6 +7102,10 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.setSignatureValidatorApproval.callAsync(validatorAddress, approval, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -9686,8 +7122,7 @@ export class ExchangeContract extends BaseContract { validatorAddress: string, approval: boolean, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('validatorAddress', validatorAddress); assert.isBoolean('approval', approval); @@ -9696,6 +7131,7 @@ export class ExchangeContract extends BaseContract { validatorAddress.toLowerCase(), approval, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -9703,8 +7139,8 @@ export class ExchangeContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -9743,19 +7179,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - validatorAddress: string, - approval: boolean, - txData?: Partial | undefined, - ): Promise { - await (this as any).setSignatureValidatorApproval.callAsync(validatorAddress, approval, txData); - const txHash = await (this as any).setSignatureValidatorApproval.sendTransactionAsync( - validatorAddress, - approval, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -9827,30 +7250,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, boolean] { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('setSignatureValidatorApproval(address,bool)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, boolean]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('setSignatureValidatorApproval(address,bool)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * This function may be used to simulate any amount of transfers As they would occur through the Exchange contract. Note that this function will always revert, even if all transfers are successful. However, it may be used with eth_call or with a try/catch pattern in order to simulate the results of the transfers. @@ -9876,6 +7275,7 @@ export class ExchangeContract extends BaseContract { toAddresses: string[], amounts: BigNumber[], txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isArray('assetData', assetData); assert.isArray('fromAddresses', fromAddresses); @@ -9898,6 +7298,16 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.simulateDispatchTransferFromCalls.callAsync( + assetData, + fromAddresses, + toAddresses, + amounts, + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -9922,8 +7332,7 @@ export class ExchangeContract extends BaseContract { toAddresses: string[], amounts: BigNumber[], txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isArray('assetData', assetData); assert.isArray('fromAddresses', fromAddresses); @@ -9936,6 +7345,7 @@ export class ExchangeContract extends BaseContract { toAddresses, amounts, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -9943,8 +7353,8 @@ export class ExchangeContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -9993,29 +7403,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - assetData: string[], - fromAddresses: string[], - toAddresses: string[], - amounts: BigNumber[], - txData?: Partial | undefined, - ): Promise { - await (this as any).simulateDispatchTransferFromCalls.callAsync( - assetData, - fromAddresses, - toAddresses, - amounts, - txData, - ); - const txHash = await (this as any).simulateDispatchTransferFromCalls.sendTransactionAsync( - assetData, - fromAddresses, - toAddresses, - amounts, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -10113,34 +7500,6 @@ export class ExchangeContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string[], string[], string[], BigNumber[]] { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'simulateDispatchTransferFromCalls(bytes[],address[],address[],uint256[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string[], string[], string[], BigNumber[]]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder( - 'simulateDispatchTransferFromCalls(bytes[],address[],address[],uint256[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public transactionsExecuted = { /** @@ -10189,42 +7548,6 @@ export class ExchangeContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: string): string { - assert.isString('index_0', index_0); - const self = (this as any) as ExchangeContract; - const abiEncodedTransactionData = self._strictEncodeArguments('transactionsExecuted(bytes32)', [index_0]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('transactionsExecuted(bytes32)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('transactionsExecuted(bytes32)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public transferOwnership = { /** @@ -10233,7 +7556,11 @@ export class ExchangeContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(newOwner: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + newOwner: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('newOwner', newOwner); const self = (this as any) as ExchangeContract; const encodedData = self._strictEncodeArguments('transferOwnership(address)', [newOwner.toLowerCase()]); @@ -10249,6 +7576,10 @@ export class ExchangeContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transferOwnership.callAsync(newOwner, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -10262,20 +7593,19 @@ export class ExchangeContract extends BaseContract { awaitTransactionSuccessAsync( newOwner: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('newOwner', newOwner); const self = (this as any) as ExchangeContract; - const txHashPromise = self.transferOwnership.sendTransactionAsync(newOwner.toLowerCase(), txData); + const txHashPromise = self.transferOwnership.sendTransactionAsync(newOwner.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -10304,11 +7634,6 @@ export class ExchangeContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(newOwner: string, txData?: Partial | undefined): Promise { - await (this as any).transferOwnership.callAsync(newOwner, txData); - const txHash = await (this as any).transferOwnership.sendTransactionAsync(newOwner, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -10365,30 +7690,6 @@ export class ExchangeContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('transferOwnership(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ExchangeContract; - const abiEncoder = self._lookupAbiEncoder('transferOwnership(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; private readonly _subscriptionManager: SubscriptionManager; public static async deployFrom0xArtifactAsync( diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/forwarder.ts b/packages/abi-gen-wrappers/src/generated-wrappers/forwarder.ts index 64e7d4abd3..33a486db3b 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/forwarder.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/forwarder.ts @@ -18,7 +18,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -28,8 +34,10 @@ import * as ethers from 'ethers'; // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class ForwarderContract extends BaseContract { - public static deployedBytecode = - '0x6080604052600436106100655760003560e01c8063942d33c011610043578063942d33c014610102578063ae93b97a14610124578063f2fde38b1461013757610065565b8063442026ed14610097578063630f1e6c146100b75780638da5cb5b146100d7575b60025473ffffffffffffffffffffffffffffffffffffffff1633146100955761009561009033610157565b6101f6565b005b3480156100a357600080fd5b506100956100b2366004611bc6565b6101fe565b3480156100c357600080fd5b506100956100d2366004611c06565b6104a8565b3480156100e357600080fd5b506100ec6104f1565b6040516100f99190611dc0565b60405180910390f35b610115610110366004611b1d565b61050d565b6040516100f993929190612047565b610115610132366004611aa0565b610542565b34801561014357600080fd5b50610095610152366004611a68565b61059d565b60606308b1869860e01b826040516024016101729190611dc0565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050919050565b805160208201fd5b600061024a600084848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505063ffffffff610614169050565b905060405161025890611d97565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614156104a35760015460405160009173ffffffffffffffffffffffffffffffffffffffff16906360704108906102d490611d97565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16825261031291600401611e5f565b60206040518083038186803b15801561032a57600080fd5b505afa15801561033e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506103629190810190611a84565b905073ffffffffffffffffffffffffffffffffffffffff811661038a5761038a61009061066a565b60006103d6601086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505063ffffffff6106c4169050565b6040517f095ea7b300000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063095ea7b39061044d9085907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90600401611de1565b602060405180830381600087803b15801561046757600080fd5b505af115801561047b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061049f9190810190611ba6565b5050505b505050565b6104b0610704565b6104a383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525085925061074d915050565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b600080600061051a610838565b6105258888886108cd565b90935091506105358386866109f0565b9050955095509592505050565b600080600061054f610838565b6000610573670de0b6b3a764000061056d888263ffffffff610b8f16565b34610bb2565b9050610580888289610bdc565b90945092506105908487876109f0565b9150509450945094915050565b6105a5610704565b73ffffffffffffffffffffffffffffffffffffffff81166105d0576105cb610090610d9f565b610611565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83161790555b50565b60008160040183511015610635576106356100906003855185600401610dd6565b5060208183018101519101907fffffffff00000000000000000000000000000000000000000000000000000000165b92915050565b6040805160048152602481019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff3b96b8d0000000000000000000000000000000000000000000000000000000017905290565b600081601401835110156106e5576106e56100906004855185601401610dd6565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b60005473ffffffffffffffffffffffffffffffffffffffff16331461074b5760005461074b9061009090339073ffffffffffffffffffffffffffffffffffffffff16610e7b565b565b600061075f838263ffffffff61061416565b905060405161076d90611d97565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614156107c9576107c48383610f1d565b6104a3565b6040516107d590611d45565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141561082c576107c48383611085565b6104a361009082611152565b346108485761084861009061116d565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108b257600080fd5b505af11580156108c6573d6000803e3d6000fd5b5050505050565b82516000908190815b8181146109d1578681815181106108e957fe5b6020026020010151608001516000148061091a575086818151811061090a57fe5b602002602001015160a001516000145b15610924576109c9565b6000610936878563ffffffff6111c716565b905060008061096c8a858151811061094a57fe5b602002602001015189868151811061095e57fe5b6020026020010151856111e6565b915091506109928a858151811061097f57fe5b602002602001015161014001518261074d565b6109a2878363ffffffff610b8f16565b96506109b4868263ffffffff610b8f16565b95508886106109c5575050506109d1565b5050505b6001016108d6565b50848210156109e7576109e76100908684611339565b50935093915050565b600066b1a2bc2ec50000831115610a0d57610a0d61009084611356565b34841115610a2257610a226100908534611371565b6000610a34348663ffffffff6111c716565b9050610a4984670de0b6b3a764000087610bb2565b915080821115610a6057610a60610090838361138e565b8015610b87576002546040517f2e1a7d4d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690632e1a7d4d90610abc908490600401612030565b600060405180830381600087803b158015610ad657600080fd5b505af1158015610aea573d6000803e3d6000fd5b505050506000821115610b3c5760405173ffffffffffffffffffffffffffffffffffffffff84169083156108fc029084906000818181858888f19350505050158015610b3a573d6000803e3d6000fd5b505b6000610b4e828463ffffffff6111c716565b90508015610b8557604051339082156108fc029083906000818181858888f19350505050158015610b83573d6000803e3d6000fd5b505b505b509392505050565b600082820183811015610bab57610bab610090600086866113ab565b9392505050565b6000610bd483610bc8868563ffffffff6113ca16565b9063ffffffff6113fb16565b949350505050565b6000806000855190506000610c97600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631ce4c78b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c5257600080fd5b505afa158015610c66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610c8a9190810190611cad565b3a9063ffffffff6113ca16565b905060005b828114610d9457878181518110610caf57fe5b60200260200101516080015160001480610ce05750878181518110610cd057fe5b602002602001015160a001516000145b15610cea57610d8c565b6000610d0c83610d008a8963ffffffff6111c716565b9063ffffffff6111c716565b9050600080610d428b8581518110610d2057fe5b60200260200101518a8681518110610d3457fe5b602002602001015185611425565b91509150610d558b858151811061097f57fe5b610d65888363ffffffff610b8f16565b9750610d77878263ffffffff610b8f16565b9650898810610d8857505050610d94565b5050505b600101610c9c565b505050935093915050565b60408051808201909152600481527fe69edc3e00000000000000000000000000000000000000000000000000000000602082015290565b6060632800659560e01b848484604051602401610df593929190611ec1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290509392505050565b6060631de45ad160e01b8383604051602401610e98929190611e07565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152905092915050565b6000610f3083601063ffffffff6106c416565b9050600060608273ffffffffffffffffffffffffffffffffffffffff16604051610f5990611d6e565b60405180910390203386604051602401610f74929190611de1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051610ffd9190611d29565b6000604051808303816000865af19150503d806000811461103a576040519150601f19603f3d011682016040523d82523d6000602084013e61103f565b606091505b50915091508161105557611055610090826114ea565b3d15611074576000915060203d14156110745760206000803e60005191505b816108c6576108c6610090826114ea565b806001146110995761109961009082611505565b60006110ac83601063ffffffff6106c416565b905060006110c184602463ffffffff61152016565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8316906323b872dd9061111a90309033908690600401611e2e565b600060405180830381600087803b15801561113457600080fd5b505af1158015611148573d6000803e3d6000fd5b5050505050505050565b6060637996a27160e01b826040516024016101729190611e5f565b6040805160048152602481019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8c0e562b0000000000000000000000000000000000000000000000000000000017905290565b6000828211156111e0576111e0610090600285856113ab565b50900390565b6000808460e001516000148061121257506101608501516101a08601516112129163ffffffff61152c16565b1561128057600061122c8660a00151876080015186611552565b905061123661172e565b61124187838861157c565b9050611272816080015161126683606001518460200151610b8f90919063ffffffff16565b9063ffffffff610b8f16565b905190935091506113319050565b6101408501516101a086015161129b9163ffffffff61152c16565b156113205760006112cb8660a001516112c58860e0015189608001516111c790919063ffffffff16565b86611552565b90506112d561172e565b6112e087838861157c565b90506112fd81608001518260200151610b8f90919063ffffffff16565b60608201518251919550611317919063ffffffff6111c716565b92505050611331565b611331610090866101a001516116e9565b935093915050565b60606391353a0c60e01b8383604051602401610e98929190612039565b6060631174fb8060e01b826040516024016101729190612030565b606063cdcbed5d60e01b8383604051602401610e98929190612039565b606063ecf40fd960e01b8383604051602401610e98929190612039565b606063e946c1bb60e01b848484604051602401610df593929190611e9f565b6000826113d957506000610664565b828202828482816113e657fe5b0414610bab57610bab610090600186866113ab565b60008161141157611411610090600385856113ab565b600082848161141c57fe5b04949350505050565b6000808460e001516000148061145157506101408501516101a08601516114519163ffffffff61152c16565b156114a85761145e61172e565b61146986858761157c565b905061148681608001518260200151610b8f90919063ffffffff16565b606082015182519194506114a0919063ffffffff6111c716565b915050611331565b6101608501516101a08601516114c39163ffffffff61152c16565b156113205760a085015160e086015160009161122c916112c590829063ffffffff610b8f16565b6060635e7eb60f60e01b826040516024016101729190611e8c565b606063baffa47460e01b826040516024016101729190612030565b6000610bab8383611704565b600081518351148015610bab575081805190602001208380519060200120149392505050565b6000610bd483610bc861156c82600163ffffffff6111c716565b611266888763ffffffff6113ca16565b61158461172e565b6040516060907f9b44d55600000000000000000000000000000000000000000000000000000000906115be90879087908790602401611ecf565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252600154915190925073ffffffffffffffffffffffffffffffffffffffff90911690600090606090839061166f908690611d29565b6000604051808303816000865af19150503d80600081146116ac576040519150601f19603f3d011682016040523d82523d6000602084013e6116b1565b606091505b509150915081156116de57805160a0146116c757fe5b808060200190516116db9190810190611c50565b94505b505050509392505050565b60606331360af160e01b826040516024016101729190611e8c565b60008160200183511015611725576117256100906005855185602001610dd6565b50016020015190565b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b8035610664816120d4565b600082601f830112611778578081fd5b813561178b61178682612084565b61205d565b8181529150602080830190840160005b838110156117c8576117b387602084358901016119e1565b8352602092830192919091019060010161179b565b5050505092915050565b600082601f8301126117e2578081fd5b81356117f061178682612084565b818152915060208083019084810160005b8481101561198f57813587016101c0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838c0301121561184157600080fd5b61184a8161205d565b6118568b87850161175d565b81526118658b6040850161175d565b868201526118768b6060850161175d565b60408201526118888b6080850161175d565b606082015260a0830135608082015260c083013560a082015260e083013560c08201526101008084013560e0830152610120808501358284015261014091508185013581840152506101608085013567ffffffffffffffff808211156118ed57600080fd5b6118fb8f8b848a01016119e1565b8486015261018093508387013591508082111561191757600080fd5b6119258f8b848a01016119e1565b838601526101a092508287013591508082111561194157600080fd5b61194f8f8b848a01016119e1565b848601528587013593508084111561196657600080fd5b50506119768d89848801016119e1565b9083015250865250509282019290820190600101611801565b505050505092915050565b60008083601f8401126119ab578182fd5b50813567ffffffffffffffff8111156119c2578182fd5b6020830191508360208285010111156119da57600080fd5b9250929050565b600082601f8301126119f1578081fd5b813567ffffffffffffffff811115611a07578182fd5b611a3860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161205d565b9150808252836020828501011115611a4f57600080fd5b8060208401602084013760009082016020015292915050565b600060208284031215611a79578081fd5b8135610bab816120d4565b600060208284031215611a95578081fd5b8151610bab816120d4565b60008060008060808587031215611ab5578283fd5b843567ffffffffffffffff80821115611acc578485fd5b611ad8888389016117d2565b95506020870135915080821115611aed578485fd5b50611afa87828801611768565b935050604085013591506060850135611b12816120d4565b939692955090935050565b600080600080600060a08688031215611b34578081fd5b853567ffffffffffffffff80821115611b4b578283fd5b611b5789838a016117d2565b9650602088013595506040880135915080821115611b73578283fd5b50611b8088828901611768565b935050606086013591506080860135611b98816120d4565b809150509295509295909350565b600060208284031215611bb7578081fd5b81518015158114610bab578182fd5b60008060208385031215611bd8578182fd5b823567ffffffffffffffff811115611bee578283fd5b611bfa8582860161199a565b90969095509350505050565b600080600060408486031215611c1a578283fd5b833567ffffffffffffffff811115611c30578384fd5b611c3c8682870161199a565b909790965060209590950135949350505050565b600060a0828403128015611c62578182fd5b8015611c6c578182fd5b50611c7760a061205d565b82518152602083015160208201526040830151604082015260608301516060820152608083015160808201528091505092915050565b600060208284031215611cbe578081fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff169052565b60008151808452611cf78160208601602086016120a4565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60008251611d3b8184602087016120a4565b9190910192915050565b7f455243373231546f6b656e28616464726573732c75696e7432353629000000008152601c0190565b7f7472616e7366657228616464726573732c75696e743235362900000000000000815260190190565b7f4552433230546f6b656e28616464726573732900000000000000000000000000815260130190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b600060208252610bab6020830184611cdf565b6060810160048510611ead57fe5b938152602081019290925260409091015290565b6060810160088510611ead57fe5b600060608252611ee3606083018651611cc5565b6020850151611ef56080840182611cc5565b506040850151611f0860a0840182611cc5565b506060850151611f1b60c0840182611cc5565b50608085015160e083015260a0850151610100818185015260c08701519150610120828186015260e0880151925061014083818701528289015193506101609250838387015281890151935061018091508382870152808901519350506101c06101a08181880152611f91610220880186611cdf565b848b015195507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa09450848882030183890152611fcd8187611cdf565b925050828a0151945083878303016101e0880152611feb8286611cdf565b9250808a015194505050818582030161020086015261200a8184611cdf565b91505085602085015283810360408501526120258186611cdf565b979650505050505050565b90815260200190565b918252602082015260400190565b9283526020830191909152604082015260600190565b60405181810167ffffffffffffffff8111828210171561207c57600080fd5b604052919050565b600067ffffffffffffffff82111561209a578081fd5b5060209081020190565b60005b838110156120bf5781810151838201526020016120a7565b838111156120ce576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461061157600080fdfea365627a7a72315820afeb88c9cc19090963cb885eb76d709ca1a151f8f73996031898e2b50578a89b6c6578706572696d656e74616cf564736f6c634300050c0040'; + /** + * @ignore + */ + public static deployedBytecode: string | undefined; /** * Approves the respective proxy for a given asset to transfer tokens on the Forwarder contract's behalf. * This is necessary because an order fee denominated in the maker asset (i.e. a percentage fee) is sent by the @@ -45,7 +53,11 @@ export class ForwarderContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(assetData: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + assetData: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('assetData', assetData); const self = (this as any) as ForwarderContract; const encodedData = self._strictEncodeArguments('approveMakerAssetProxy(bytes)', [assetData]); @@ -61,6 +73,10 @@ export class ForwarderContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.approveMakerAssetProxy.callAsync(assetData, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -75,20 +91,19 @@ export class ForwarderContract extends BaseContract { awaitTransactionSuccessAsync( assetData: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('assetData', assetData); const self = (this as any) as ForwarderContract; - const txHashPromise = self.approveMakerAssetProxy.sendTransactionAsync(assetData, txData); + const txHashPromise = self.approveMakerAssetProxy.sendTransactionAsync(assetData, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -118,14 +133,6 @@ export class ForwarderContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - assetData: string, - txData?: Partial | undefined, - ): Promise { - await (this as any).approveMakerAssetProxy.callAsync(assetData, txData); - const txHash = await (this as any).approveMakerAssetProxy.sendTransactionAsync(assetData, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -182,30 +189,6 @@ export class ForwarderContract extends BaseContract { const abiEncodedTransactionData = self._strictEncodeArguments('approveMakerAssetProxy(bytes)', [assetData]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as ForwarderContract; - const abiEncoder = self._lookupAbiEncoder('approveMakerAssetProxy(bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ForwarderContract; - const abiEncoder = self._lookupAbiEncoder('approveMakerAssetProxy(bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Attempt to buy makerAssetBuyAmount of makerAsset by selling ETH provided with transaction. @@ -249,6 +232,7 @@ export class ForwarderContract extends BaseContract { feePercentage: BigNumber, feeRecipient: string, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isArray('orders', orders); assert.isBigNumber('makerAssetBuyAmount', makerAssetBuyAmount); @@ -272,6 +256,17 @@ export class ForwarderContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.marketBuyOrdersWithEth.callAsync( + orders, + makerAssetBuyAmount, + signatures, + feePercentage, + feeRecipient, + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -311,8 +306,7 @@ export class ForwarderContract extends BaseContract { feePercentage: BigNumber, feeRecipient: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isArray('orders', orders); assert.isBigNumber('makerAssetBuyAmount', makerAssetBuyAmount); @@ -327,6 +321,7 @@ export class ForwarderContract extends BaseContract { feePercentage, feeRecipient.toLowerCase(), txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -334,8 +329,8 @@ export class ForwarderContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -400,47 +395,6 @@ export class ForwarderContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - makerAssetBuyAmount: BigNumber, - signatures: string[], - feePercentage: BigNumber, - feeRecipient: string, - txData?: Partial | undefined, - ): Promise { - await (this as any).marketBuyOrdersWithEth.callAsync( - orders, - makerAssetBuyAmount, - signatures, - feePercentage, - feeRecipient, - txData, - ); - const txHash = await (this as any).marketBuyOrdersWithEth.sendTransactionAsync( - orders, - makerAssetBuyAmount, - signatures, - feePercentage, - feeRecipient, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -570,82 +524,6 @@ export class ForwarderContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): [ - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - BigNumber, - string[], - BigNumber, - string - ] { - const self = (this as any) as ForwarderContract; - const abiEncoder = self._lookupAbiEncoder( - 'marketBuyOrdersWithEth((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256,bytes[],uint256,address)', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - [ - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - BigNumber, - string[], - BigNumber, - string - ] - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [BigNumber, BigNumber, BigNumber] { - const self = (this as any) as ForwarderContract; - const abiEncoder = self._lookupAbiEncoder( - 'marketBuyOrdersWithEth((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],uint256,bytes[],uint256,address)', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[BigNumber, BigNumber, BigNumber]>( - returnData, - ); - return abiDecodedReturnData; - }, }; /** * Purchases as much of orders' makerAssets as possible by selling as much of the ETH value sent @@ -685,6 +563,7 @@ export class ForwarderContract extends BaseContract { feePercentage: BigNumber, feeRecipient: string, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isArray('orders', orders); assert.isArray('signatures', signatures); @@ -707,6 +586,16 @@ export class ForwarderContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.marketSellOrdersWithEth.callAsync( + orders, + signatures, + feePercentage, + feeRecipient, + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -744,8 +633,7 @@ export class ForwarderContract extends BaseContract { feePercentage: BigNumber, feeRecipient: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isArray('orders', orders); assert.isArray('signatures', signatures); @@ -758,6 +646,7 @@ export class ForwarderContract extends BaseContract { feePercentage, feeRecipient.toLowerCase(), txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -765,8 +654,8 @@ export class ForwarderContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -828,44 +717,6 @@ export class ForwarderContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - signatures: string[], - feePercentage: BigNumber, - feeRecipient: string, - txData?: Partial | undefined, - ): Promise { - await (this as any).marketSellOrdersWithEth.callAsync( - orders, - signatures, - feePercentage, - feeRecipient, - txData, - ); - const txHash = await (this as any).marketSellOrdersWithEth.sendTransactionAsync( - orders, - signatures, - feePercentage, - feeRecipient, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -989,80 +840,6 @@ export class ForwarderContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): [ - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - string[], - BigNumber, - string - ] { - const self = (this as any) as ForwarderContract; - const abiEncoder = self._lookupAbiEncoder( - 'marketSellOrdersWithEth((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],uint256,address)', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - [ - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - string[], - BigNumber, - string - ] - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [BigNumber, BigNumber, BigNumber] { - const self = (this as any) as ForwarderContract; - const abiEncoder = self._lookupAbiEncoder( - 'marketSellOrdersWithEth((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],uint256,address)', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[BigNumber, BigNumber, BigNumber]>( - returnData, - ); - return abiDecodedReturnData; - }, }; public owner = { /** @@ -1106,41 +883,6 @@ export class ForwarderContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ForwarderContract; - const abiEncodedTransactionData = self._strictEncodeArguments('owner()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ForwarderContract; - const abiEncoder = self._lookupAbiEncoder('owner()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ForwarderContract; - const abiEncoder = self._lookupAbiEncoder('owner()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public transferOwnership = { /** @@ -1149,7 +891,11 @@ export class ForwarderContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(newOwner: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + newOwner: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('newOwner', newOwner); const self = (this as any) as ForwarderContract; const encodedData = self._strictEncodeArguments('transferOwnership(address)', [newOwner.toLowerCase()]); @@ -1165,6 +911,10 @@ export class ForwarderContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transferOwnership.callAsync(newOwner, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1178,20 +928,19 @@ export class ForwarderContract extends BaseContract { awaitTransactionSuccessAsync( newOwner: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('newOwner', newOwner); const self = (this as any) as ForwarderContract; - const txHashPromise = self.transferOwnership.sendTransactionAsync(newOwner.toLowerCase(), txData); + const txHashPromise = self.transferOwnership.sendTransactionAsync(newOwner.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1220,11 +969,6 @@ export class ForwarderContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(newOwner: string, txData?: Partial | undefined): Promise { - await (this as any).transferOwnership.callAsync(newOwner, txData); - const txHash = await (this as any).transferOwnership.sendTransactionAsync(newOwner, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1281,30 +1025,6 @@ export class ForwarderContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as ForwarderContract; - const abiEncoder = self._lookupAbiEncoder('transferOwnership(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ForwarderContract; - const abiEncoder = self._lookupAbiEncoder('transferOwnership(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Withdraws assets from this contract. The contract formerly required a ZRX balance in order @@ -1324,6 +1044,7 @@ export class ForwarderContract extends BaseContract { assetData: string, amount: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('assetData', assetData); assert.isBigNumber('amount', amount); @@ -1341,6 +1062,10 @@ export class ForwarderContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.withdrawAsset.callAsync(assetData, amount, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1357,21 +1082,20 @@ export class ForwarderContract extends BaseContract { assetData: string, amount: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('assetData', assetData); assert.isBigNumber('amount', amount); const self = (this as any) as ForwarderContract; - const txHashPromise = self.withdrawAsset.sendTransactionAsync(assetData, amount, txData); + const txHashPromise = self.withdrawAsset.sendTransactionAsync(assetData, amount, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1407,15 +1131,6 @@ export class ForwarderContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - assetData: string, - amount: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).withdrawAsset.callAsync(assetData, amount, txData); - const txHash = await (this as any).withdrawAsset.sendTransactionAsync(assetData, amount, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1484,30 +1199,6 @@ export class ForwarderContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, BigNumber] { - const self = (this as any) as ForwarderContract; - const abiEncoder = self._lookupAbiEncoder('withdrawAsset(bytes,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as ForwarderContract; - const abiEncoder = self._lookupAbiEncoder('withdrawAsset(bytes,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public static async deployFrom0xArtifactAsync( artifact: ContractArtifact | SimpleContractArtifact, diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/i_asset_proxy.ts b/packages/abi-gen-wrappers/src/generated-wrappers/i_asset_proxy.ts index 4a91819df5..30aed03216 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/i_asset_proxy.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/i_asset_proxy.ts @@ -18,7 +18,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -28,6 +34,9 @@ import * as ethers from 'ethers'; // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class IAssetProxyContract extends BaseContract { + /** + * @ignore + */ public static deployedBytecode: string | undefined; /** * Transfers assets. Either succeeds or throws. @@ -49,6 +58,7 @@ export class IAssetProxyContract extends BaseContract { to: string, amount: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('assetData', assetData); assert.isString('from', from); @@ -73,6 +83,10 @@ export class IAssetProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transferFrom.callAsync(assetData, from, to, amount, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -93,8 +107,7 @@ export class IAssetProxyContract extends BaseContract { to: string, amount: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('assetData', assetData); assert.isString('from', from); @@ -107,6 +120,7 @@ export class IAssetProxyContract extends BaseContract { to.toLowerCase(), amount, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -114,8 +128,8 @@ export class IAssetProxyContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -162,17 +176,6 @@ export class IAssetProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - assetData: string, - from: string, - to: string, - amount: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).transferFrom.callAsync(assetData, from, to, amount, txData); - const txHash = await (this as any).transferFrom.sendTransactionAsync(assetData, from, to, amount, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -256,30 +259,6 @@ export class IAssetProxyContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, string, string, BigNumber] { - const self = (this as any) as IAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(bytes,address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, string, string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as IAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(bytes,address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Gets the proxy id associated with the proxy address. @@ -306,7 +285,7 @@ export class IAssetProxyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -319,41 +298,6 @@ export class IAssetProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as IAssetProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getProxyId()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as IAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('getProxyId()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as IAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('getProxyId()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public static async deployFrom0xArtifactAsync( artifact: ContractArtifact | SimpleContractArtifact, diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/i_validator.ts b/packages/abi-gen-wrappers/src/generated-wrappers/i_validator.ts index d1cd5b401b..a1a699fde1 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/i_validator.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/i_validator.ts @@ -18,7 +18,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -28,6 +34,9 @@ import * as ethers from 'ethers'; // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class IValidatorContract extends BaseContract { + /** + * @ignore + */ public static deployedBytecode: string | undefined; /** * Verifies that a signature is valid. @@ -91,51 +100,6 @@ export class IValidatorContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param hash Message hash that is signed. - * @param signerAddress Address that should have signed the given hash. - * @param signature Proof of signing. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(hash: string, signerAddress: string, signature: string): string { - assert.isString('hash', hash); - assert.isString('signerAddress', signerAddress); - assert.isString('signature', signature); - const self = (this as any) as IValidatorContract; - const abiEncodedTransactionData = self._strictEncodeArguments('isValidSignature(bytes32,address,bytes)', [ - hash, - signerAddress.toLowerCase(), - signature, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as IValidatorContract; - const abiEncoder = self._lookupAbiEncoder('isValidSignature(bytes32,address,bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as IValidatorContract; - const abiEncoder = self._lookupAbiEncoder('isValidSignature(bytes32,address,bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public static async deployFrom0xArtifactAsync( artifact: ContractArtifact | SimpleContractArtifact, diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/i_wallet.ts b/packages/abi-gen-wrappers/src/generated-wrappers/i_wallet.ts index 9c8399f017..29a1001c9b 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/i_wallet.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/i_wallet.ts @@ -18,7 +18,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -28,6 +34,9 @@ import * as ethers from 'ethers'; // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class IWalletContract extends BaseContract { + /** + * @ignore + */ public static deployedBytecode: string | undefined; /** * Validates a hash with the `Wallet` signature type. @@ -84,48 +93,6 @@ export class IWalletContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param hash Message hash that is signed. - * @param signature Proof of signing. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(hash: string, signature: string): string { - assert.isString('hash', hash); - assert.isString('signature', signature); - const self = (this as any) as IWalletContract; - const abiEncodedTransactionData = self._strictEncodeArguments('isValidSignature(bytes32,bytes)', [ - hash, - signature, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as IWalletContract; - const abiEncoder = self._lookupAbiEncoder('isValidSignature(bytes32,bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as IWalletContract; - const abiEncoder = self._lookupAbiEncoder('isValidSignature(bytes32,bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public static async deployFrom0xArtifactAsync( artifact: ContractArtifact | SimpleContractArtifact, diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/multi_asset_proxy.ts b/packages/abi-gen-wrappers/src/generated-wrappers/multi_asset_proxy.ts index ddac12e1de..33b681ef8b 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/multi_asset_proxy.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/multi_asset_proxy.ts @@ -19,7 +19,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -55,6 +61,9 @@ export interface MultiAssetProxyAssetProxyRegisteredEventArgs extends DecodedLog // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class MultiAssetProxyContract extends BaseContract { + /** + * @ignore + */ public static deployedBytecode = '0x608060405234801561001057600080fd5b50600436106100d45760003560e01c80639ad2674411610081578063c585bb931161005b578063c585bb9314610789578063d39de6e9146107bc578063f2fde38b14610814576100d4565b80639ad26744146106cc578063ae25532e14610705578063b918161114610742576100d4565b806360704108116100b2578063607041081461065257806370712939146106915780638da5cb5b146106c4576100d4565b80633fd3c9971461059857806342f1181e14610600578063494503d414610635575b7fffffffff00000000000000000000000000000000000000000000000000000000600035167fa85e59e400000000000000000000000000000000000000000000000000000000811415610592573360005260026020526040600020546101a5577f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c1553454e4445525f4e4f545f415554484f52495a454400000000000000604052600060605260646000fd5b600480350180356020600482030660448210171561022e577f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c19494e56414c49445f41535345545f444154415f4c454e475448000000604052600060605260646000fd5b602081018201368111156102ad577f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c16494e56414c49445f41535345545f444154415f454e44000000000000604052600060605260646000fd5b5050602481013560448201356044820183016020810335925060448201840160208103358085031561034a577f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c0f4c454e4754485f4d49534d4154434800000000000000000000000000604052600060605260646000fd5b5060646000803760806004526000936064359060200285805b82811015610587578086013584810281868204148615176103ef577f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c1055494e543235365f4f564552464c4f57000000000000000000000000604052600060605260646000fd5b60649081528287013589018b01604481019250018135600481101561049e577f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c1e4c454e4754485f475245415445525f5448414e5f335f5245515549526040527f454400000000000000000000000000000000000000000000000000000000000060605260646000fd5b7fffffffff000000000000000000000000000000000000000000000000000000008235168b8103156104df57809b508b608452600160a45260406084205495505b5084610556577f08c379a0000000000000000000000000000000000000000000000000000000006000527c20000000000000000000000000000000000000000000000000000000006020527c1a41535345545f50524f58595f444f45535f4e4f545f45584953540000604052600060605260646000fd5b60208101836084376000808260a401600080895af1925050508061057e573d6000803e3d6000fd5b50602001610363565b505050505050505050005b50600080fd5b6105d7600480360360208110156105ae57600080fd5b50357fffffffff0000000000000000000000000000000000000000000000000000000016610847565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6106336004803603602081101561061657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661086f565b005b6105d76004803603602081101561064b57600080fd5b5035610a5b565b6105d76004803603602081101561066857600080fd5b50357fffffffff0000000000000000000000000000000000000000000000000000000016610a8f565b610633600480360360208110156106a757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610ad9565b6105d7610dcc565b610633600480360360408110156106e257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610de8565b61070d611199565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b6107756004803603602081101561075857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166111cf565b604080519115158252519081900360200190f35b6106336004803603602081101561079f57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166111e4565b6107c4611446565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156108005781810151838201526020016107e8565b505050509050019250505060405180910390f35b6106336004803603602081101561082a57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166114b5565b60016020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff1633146108f557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526002602052604090205460ff161561098a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f5441524745545f414c52454144595f415554484f52495a454400000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811660008181526002602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915560038054918201815583527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180547fffffffffffffffffffffffff00000000000000000000000000000000000000001684179055513392917f3147867c59d17e8fa9d522465651d44aae0a9e38f902f3475b97e58072f0ed4c91a350565b60038181548110610a6857fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b7fffffffff000000000000000000000000000000000000000000000000000000001660009081526001602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b5f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526002602052604090205460ff16610bf357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5441524745545f4e4f545f415554484f52495a45440000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116600090815260026020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b600354811015610d85578173ffffffffffffffffffffffffffffffffffffffff1660038281548110610c6d57fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff161415610d7d57600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101908110610cc557fe5b6000918252602090912001546003805473ffffffffffffffffffffffffffffffffffffffff9092169183908110610cf857fe5b600091825260209091200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190610d77908261159b565b50610d85565b600101610c3f565b50604051339073ffffffffffffffffffffffffffffffffffffffff8316907f1f32c1b084e2de0713b8fb16bd46bb9df710a3dbeae2f3ca93af46e016dcc6b090600090a350565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e6e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090205460ff16610f0257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5441524745545f4e4f545f415554484f52495a45440000000000000000000000604482015290519081900360640190fd5b6003548110610f7257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e4445585f4f55545f4f465f424f554e445300000000000000000000000000604482015290519081900360640190fd5b8173ffffffffffffffffffffffffffffffffffffffff1660038281548110610f9657fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff161461102457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f415554484f52495a45445f414444524553535f4d49534d415443480000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815260026020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190811061109f57fe5b6000918252602090912001546003805473ffffffffffffffffffffffffffffffffffffffff90921691839081106110d257fe5b600091825260209091200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190611151908261159b565b50604051339073ffffffffffffffffffffffffffffffffffffffff8416907f1f32c1b084e2de0713b8fb16bd46bb9df710a3dbeae2f3ca93af46e016dcc6b090600090a35050565b604080517f4d756c746941737365742875696e743235365b5d2c62797465735b5d290000008152905190819003601d0190205b90565b60026020526000908152604090205460ff1681565b60005473ffffffffffffffffffffffffffffffffffffffff16331461126a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000604482015290519081900360640190fd5b60008173ffffffffffffffffffffffffffffffffffffffff1663ae25532e6040518163ffffffff1660e01b815260040160206040518083038186803b1580156112b257600080fd5b505afa1580156112c6573d6000803e3d6000fd5b505050506040513d60208110156112dc57600080fd5b50517fffffffff00000000000000000000000000000000000000000000000000000000811660009081526001602052604090205490915073ffffffffffffffffffffffffffffffffffffffff16801561139657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f41535345545f50524f58595f414c52454144595f455849535453000000000000604482015290519081900360640190fd5b7fffffffff00000000000000000000000000000000000000000000000000000000821660008181526001602090815260409182902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff881690811790915582519384529083015280517fd2c6b762299c609bdb96520b58a49bfb80186934d4f71a86a367571a15c031949281900390910190a1505050565b606060038054806020026020016040519081016040528092919081815260200182805480156114ab57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311611480575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff16331461153b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4f4e4c595f434f4e54524143545f4f574e455200000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81161561159857600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83161790555b50565b8154818355818111156115bf576000838152602090206115bf9181019083016115c4565b505050565b6111cc91905b808211156115de57600081556001016115ca565b509056fea265627a7a72315820ff218c9e47c47135d1028b03281d63826ba3569217fc501ee67c0661fa98fc5164736f6c634300050b0032'; public assetProxies = { @@ -100,42 +109,6 @@ export class MultiAssetProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: string): string { - assert.isString('index_0', index_0); - const self = (this as any) as MultiAssetProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('assetProxies(bytes4)', [index_0]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('assetProxies(bytes4)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('assetProxies(bytes4)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Authorizes an address. @@ -148,7 +121,11 @@ export class MultiAssetProxyContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(target: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + target: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('target', target); const self = (this as any) as MultiAssetProxyContract; const encodedData = self._strictEncodeArguments('addAuthorizedAddress(address)', [target.toLowerCase()]); @@ -164,6 +141,10 @@ export class MultiAssetProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.addAuthorizedAddress.callAsync(target, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -178,20 +159,19 @@ export class MultiAssetProxyContract extends BaseContract { awaitTransactionSuccessAsync( target: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('target', target); const self = (this as any) as MultiAssetProxyContract; - const txHashPromise = self.addAuthorizedAddress.sendTransactionAsync(target.toLowerCase(), txData); + const txHashPromise = self.addAuthorizedAddress.sendTransactionAsync(target.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -221,11 +201,6 @@ export class MultiAssetProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(target: string, txData?: Partial | undefined): Promise { - await (this as any).addAuthorizedAddress.callAsync(target, txData); - const txHash = await (this as any).addAuthorizedAddress.sendTransactionAsync(target, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -284,30 +259,6 @@ export class MultiAssetProxyContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('addAuthorizedAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('addAuthorizedAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public authorities = { /** @@ -356,42 +307,6 @@ export class MultiAssetProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: BigNumber): string { - assert.isBigNumber('index_0', index_0); - const self = (this as any) as MultiAssetProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('authorities(uint256)', [index_0]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): BigNumber { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('authorities(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('authorities(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Gets an asset proxy. @@ -445,43 +360,6 @@ export class MultiAssetProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param assetProxyId Id of the asset proxy. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(assetProxyId: string): string { - assert.isString('assetProxyId', assetProxyId); - const self = (this as any) as MultiAssetProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getAssetProxy(bytes4)', [assetProxyId]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('getAssetProxy(bytes4)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('getAssetProxy(bytes4)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Removes authorizion of an address. @@ -494,7 +372,11 @@ export class MultiAssetProxyContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(target: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + target: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('target', target); const self = (this as any) as MultiAssetProxyContract; const encodedData = self._strictEncodeArguments('removeAuthorizedAddress(address)', [target.toLowerCase()]); @@ -510,6 +392,10 @@ export class MultiAssetProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.removeAuthorizedAddress.callAsync(target, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -524,20 +410,19 @@ export class MultiAssetProxyContract extends BaseContract { awaitTransactionSuccessAsync( target: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('target', target); const self = (this as any) as MultiAssetProxyContract; - const txHashPromise = self.removeAuthorizedAddress.sendTransactionAsync(target.toLowerCase(), txData); + const txHashPromise = self.removeAuthorizedAddress.sendTransactionAsync(target.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -567,11 +452,6 @@ export class MultiAssetProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(target: string, txData?: Partial | undefined): Promise { - await (this as any).removeAuthorizedAddress.callAsync(target, txData); - const txHash = await (this as any).removeAuthorizedAddress.sendTransactionAsync(target, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -630,30 +510,6 @@ export class MultiAssetProxyContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddress(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public owner = { /** @@ -697,41 +553,6 @@ export class MultiAssetProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as MultiAssetProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('owner()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('owner()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('owner()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Removes authorizion of an address. @@ -749,6 +570,7 @@ export class MultiAssetProxyContract extends BaseContract { target: string, index: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('target', target); assert.isBigNumber('index', index); @@ -769,6 +591,10 @@ export class MultiAssetProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.removeAuthorizedAddressAtIndex.callAsync(target, index, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -785,8 +611,7 @@ export class MultiAssetProxyContract extends BaseContract { target: string, index: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('target', target); assert.isBigNumber('index', index); @@ -795,6 +620,7 @@ export class MultiAssetProxyContract extends BaseContract { target.toLowerCase(), index, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -802,8 +628,8 @@ export class MultiAssetProxyContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -842,19 +668,6 @@ export class MultiAssetProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - target: string, - index: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).removeAuthorizedAddressAtIndex.callAsync(target, index, txData); - const txHash = await (this as any).removeAuthorizedAddressAtIndex.sendTransactionAsync( - target, - index, - txData, - ); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -926,30 +739,6 @@ export class MultiAssetProxyContract extends BaseContract { ); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, BigNumber] { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddressAtIndex(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('removeAuthorizedAddressAtIndex(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Gets the proxy id associated with the proxy address. @@ -976,7 +765,7 @@ export class MultiAssetProxyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -989,41 +778,6 @@ export class MultiAssetProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as MultiAssetProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getProxyId()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('getProxyId()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('getProxyId()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public authorized = { /** @@ -1072,44 +826,6 @@ export class MultiAssetProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: string): string { - assert.isString('index_0', index_0); - const self = (this as any) as MultiAssetProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('authorized(address)', [ - index_0.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('authorized(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('authorized(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Registers an asset proxy to its asset proxy id. @@ -1123,7 +839,11 @@ export class MultiAssetProxyContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(assetProxy: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + assetProxy: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('assetProxy', assetProxy); const self = (this as any) as MultiAssetProxyContract; const encodedData = self._strictEncodeArguments('registerAssetProxy(address)', [assetProxy.toLowerCase()]); @@ -1139,6 +859,10 @@ export class MultiAssetProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.registerAssetProxy.callAsync(assetProxy, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1153,20 +877,19 @@ export class MultiAssetProxyContract extends BaseContract { awaitTransactionSuccessAsync( assetProxy: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('assetProxy', assetProxy); const self = (this as any) as MultiAssetProxyContract; - const txHashPromise = self.registerAssetProxy.sendTransactionAsync(assetProxy.toLowerCase(), txData); + const txHashPromise = self.registerAssetProxy.sendTransactionAsync(assetProxy.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1196,14 +919,6 @@ export class MultiAssetProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - assetProxy: string, - txData?: Partial | undefined, - ): Promise { - await (this as any).registerAssetProxy.callAsync(assetProxy, txData); - const txHash = await (this as any).registerAssetProxy.sendTransactionAsync(assetProxy, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1266,30 +981,6 @@ export class MultiAssetProxyContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('registerAssetProxy(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('registerAssetProxy(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Gets all authorized addresses. @@ -1337,41 +1028,6 @@ export class MultiAssetProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as MultiAssetProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getAuthorizedAddresses()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('getAuthorizedAddresses()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string[] { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('getAuthorizedAddresses()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public transferOwnership = { /** @@ -1380,7 +1036,11 @@ export class MultiAssetProxyContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(newOwner: string, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + newOwner: string, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('newOwner', newOwner); const self = (this as any) as MultiAssetProxyContract; const encodedData = self._strictEncodeArguments('transferOwnership(address)', [newOwner.toLowerCase()]); @@ -1396,6 +1056,10 @@ export class MultiAssetProxyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transferOwnership.callAsync(newOwner, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1409,20 +1073,19 @@ export class MultiAssetProxyContract extends BaseContract { awaitTransactionSuccessAsync( newOwner: string, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('newOwner', newOwner); const self = (this as any) as MultiAssetProxyContract; - const txHashPromise = self.transferOwnership.sendTransactionAsync(newOwner.toLowerCase(), txData); + const txHashPromise = self.transferOwnership.sendTransactionAsync(newOwner.toLowerCase(), txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1451,11 +1114,6 @@ export class MultiAssetProxyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(newOwner: string, txData?: Partial | undefined): Promise { - await (this as any).transferOwnership.callAsync(newOwner, txData); - const txHash = await (this as any).transferOwnership.sendTransactionAsync(newOwner, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1512,30 +1170,6 @@ export class MultiAssetProxyContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string] { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('transferOwnership(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as MultiAssetProxyContract; - const abiEncoder = self._lookupAbiEncoder('transferOwnership(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; private readonly _subscriptionManager: SubscriptionManager; public static async deployFrom0xArtifactAsync( diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/order_validator.ts b/packages/abi-gen-wrappers/src/generated-wrappers/order_validator.ts index de5099cd21..9b3d0f6b4e 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/order_validator.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/order_validator.ts @@ -18,7 +18,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -28,6 +34,9 @@ import * as ethers from 'ethers'; // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class OrderValidatorContract extends BaseContract { + /** + * @ignore + */ public static deployedBytecode: string | undefined; public getOrderAndTraderInfo = { /** @@ -123,129 +132,6 @@ export class OrderValidatorContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData( - order: { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }, - takerAddress: string, - ): string { - assert.isString('takerAddress', takerAddress); - const self = (this as any) as OrderValidatorContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'getOrderAndTraderInfo((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address)', - [order, takerAddress.toLowerCase()], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): [ - { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }, - string - ] { - const self = (this as any) as OrderValidatorContract; - const abiEncoder = self._lookupAbiEncoder( - 'getOrderAndTraderInfo((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address)', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - [ - { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }, - string - ] - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): [ - { orderStatus: number; orderHash: string; orderTakerAssetFilledAmount: BigNumber }, - { - makerBalance: BigNumber; - makerAllowance: BigNumber; - takerBalance: BigNumber; - takerAllowance: BigNumber; - makerZrxBalance: BigNumber; - makerZrxAllowance: BigNumber; - takerZrxBalance: BigNumber; - takerZrxAllowance: BigNumber; - } - ] { - const self = (this as any) as OrderValidatorContract; - const abiEncoder = self._lookupAbiEncoder( - 'getOrderAndTraderInfo((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address)', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue< - [ - { orderStatus: number; orderHash: string; orderTakerAssetFilledAmount: BigNumber }, - { - makerBalance: BigNumber; - makerAllowance: BigNumber; - takerBalance: BigNumber; - takerAllowance: BigNumber; - makerZrxBalance: BigNumber; - makerZrxAllowance: BigNumber; - takerZrxBalance: BigNumber; - takerZrxAllowance: BigNumber; - } - ] - >(returnData); - return abiDecodedReturnData; - }, }; public getBalanceAndAllowance = { /** @@ -299,46 +185,6 @@ export class OrderValidatorContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(target: string, assetData: string): string { - assert.isString('target', target); - assert.isString('assetData', assetData); - const self = (this as any) as OrderValidatorContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getBalanceAndAllowance(address,bytes)', [ - target.toLowerCase(), - assetData, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, string] { - const self = (this as any) as OrderValidatorContract; - const abiEncoder = self._lookupAbiEncoder('getBalanceAndAllowance(address,bytes)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, string]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [BigNumber, BigNumber] { - const self = (this as any) as OrderValidatorContract; - const abiEncoder = self._lookupAbiEncoder('getBalanceAndAllowance(address,bytes)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[BigNumber, BigNumber]>(returnData); - return abiDecodedReturnData; - }, }; public getOrdersAndTradersInfo = { /** @@ -435,130 +281,6 @@ export class OrderValidatorContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }>, - takerAddresses: string[], - ): string { - assert.isArray('orders', orders); - assert.isArray('takerAddresses', takerAddresses); - const self = (this as any) as OrderValidatorContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'getOrdersAndTradersInfo((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address[])', - [orders, takerAddresses], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): [ - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }>, - string[] - ] { - const self = (this as any) as OrderValidatorContract; - const abiEncoder = self._lookupAbiEncoder( - 'getOrdersAndTradersInfo((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - [ - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }>, - string[] - ] - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): [ - Array<{ orderStatus: number; orderHash: string; orderTakerAssetFilledAmount: BigNumber }>, - Array<{ - makerBalance: BigNumber; - makerAllowance: BigNumber; - takerBalance: BigNumber; - takerAllowance: BigNumber; - makerZrxBalance: BigNumber; - makerZrxAllowance: BigNumber; - takerZrxBalance: BigNumber; - takerZrxAllowance: BigNumber; - }> - ] { - const self = (this as any) as OrderValidatorContract; - const abiEncoder = self._lookupAbiEncoder( - 'getOrdersAndTradersInfo((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue< - [ - Array<{ orderStatus: number; orderHash: string; orderTakerAssetFilledAmount: BigNumber }>, - Array<{ - makerBalance: BigNumber; - makerAllowance: BigNumber; - takerBalance: BigNumber; - takerAllowance: BigNumber; - makerZrxBalance: BigNumber; - makerZrxAllowance: BigNumber; - takerZrxBalance: BigNumber; - takerZrxAllowance: BigNumber; - }> - ] - >(returnData); - return abiDecodedReturnData; - }, }; public getTradersInfo = { /** @@ -649,118 +371,6 @@ export class OrderValidatorContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }>, - takerAddresses: string[], - ): string { - assert.isArray('orders', orders); - assert.isArray('takerAddresses', takerAddresses); - const self = (this as any) as OrderValidatorContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'getTradersInfo((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address[])', - [orders, takerAddresses], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }> { - const self = (this as any) as OrderValidatorContract; - const abiEncoder = self._lookupAbiEncoder( - 'getTradersInfo((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address[])', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode< - Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }> - >(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): Array<{ - makerBalance: BigNumber; - makerAllowance: BigNumber; - takerBalance: BigNumber; - takerAllowance: BigNumber; - makerZrxBalance: BigNumber; - makerZrxAllowance: BigNumber; - takerZrxBalance: BigNumber; - takerZrxAllowance: BigNumber; - }> { - const self = (this as any) as OrderValidatorContract; - const abiEncoder = self._lookupAbiEncoder( - 'getTradersInfo((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address[])', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue< - Array<{ - makerBalance: BigNumber; - makerAllowance: BigNumber; - takerBalance: BigNumber; - takerAllowance: BigNumber; - makerZrxBalance: BigNumber; - makerZrxAllowance: BigNumber; - takerZrxBalance: BigNumber; - takerZrxAllowance: BigNumber; - }> - >(returnData); - return abiDecodedReturnData; - }, }; public getERC721TokenOwner = { /** @@ -814,46 +424,6 @@ export class OrderValidatorContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(token: string, tokenId: BigNumber): string { - assert.isString('token', token); - assert.isBigNumber('tokenId', tokenId); - const self = (this as any) as OrderValidatorContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getERC721TokenOwner(address,uint256)', [ - token.toLowerCase(), - tokenId, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as OrderValidatorContract; - const abiEncoder = self._lookupAbiEncoder('getERC721TokenOwner(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as OrderValidatorContract; - const abiEncoder = self._lookupAbiEncoder('getERC721TokenOwner(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public getBalancesAndAllowances = { /** @@ -907,46 +477,6 @@ export class OrderValidatorContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(target: string, assetData: string[]): string { - assert.isString('target', target); - assert.isArray('assetData', assetData); - const self = (this as any) as OrderValidatorContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getBalancesAndAllowances(address,bytes[])', [ - target.toLowerCase(), - assetData, - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, string[]] { - const self = (this as any) as OrderValidatorContract; - const abiEncoder = self._lookupAbiEncoder('getBalancesAndAllowances(address,bytes[])'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, string[]]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): [BigNumber[], BigNumber[]] { - const self = (this as any) as OrderValidatorContract; - const abiEncoder = self._lookupAbiEncoder('getBalancesAndAllowances(address,bytes[])'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<[BigNumber[], BigNumber[]]>(returnData); - return abiDecodedReturnData; - }, }; public getTraderInfo = { /** @@ -1032,113 +562,6 @@ export class OrderValidatorContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData( - order: { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }, - takerAddress: string, - ): string { - assert.isString('takerAddress', takerAddress); - const self = (this as any) as OrderValidatorContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'getTraderInfo((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address)', - [order, takerAddress.toLowerCase()], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData( - callData: string, - ): { - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - } { - const self = (this as any) as OrderValidatorContract; - const abiEncoder = self._lookupAbiEncoder( - 'getTraderInfo((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address)', - ); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - }>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData( - returnData: string, - ): { - makerBalance: BigNumber; - makerAllowance: BigNumber; - takerBalance: BigNumber; - takerAllowance: BigNumber; - makerZrxBalance: BigNumber; - makerZrxAllowance: BigNumber; - takerZrxBalance: BigNumber; - takerZrxAllowance: BigNumber; - } { - const self = (this as any) as OrderValidatorContract; - const abiEncoder = self._lookupAbiEncoder( - 'getTraderInfo((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address)', - ); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<{ - makerBalance: BigNumber; - makerAllowance: BigNumber; - takerBalance: BigNumber; - takerAllowance: BigNumber; - makerZrxBalance: BigNumber; - makerZrxAllowance: BigNumber; - takerZrxBalance: BigNumber; - takerZrxAllowance: BigNumber; - }>(returnData); - return abiDecodedReturnData; - }, }; public static async deployFrom0xArtifactAsync( artifact: ContractArtifact | SimpleContractArtifact, diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/static_call_proxy.ts b/packages/abi-gen-wrappers/src/generated-wrappers/static_call_proxy.ts index 954be6b254..e1298600cb 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/static_call_proxy.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/static_call_proxy.ts @@ -18,7 +18,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -28,6 +34,9 @@ import * as ethers from 'ethers'; // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class StaticCallProxyContract extends BaseContract { + /** + * @ignore + */ public static deployedBytecode = '0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063a85e59e41461003b578063ae25532e146100d3575b600080fd5b6100d16004803603608081101561005157600080fd5b81019060208101813564010000000081111561006c57600080fd5b82018360208201111561007e57600080fd5b803590602001918460018302840111640100000000831117156100a057600080fd5b919350915073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610110565b005b6100db6103a5565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b6000606060006101656004898990508a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092949392505063ffffffff6103c5169050565b806020019051606081101561017957600080fd5b8151602083018051604051929492938301929190846401000000008211156101a057600080fd5b9083019060208201858111156101b557600080fd5b82516401000000008111828201881017156101cf57600080fd5b82525081516020918201929091019080838360005b838110156101fc5781810151838201526020016101e4565b50505050905090810190601f1680156102295780820380516001836020036101000a031916815260200191505b5060405260200180519060200190929190505050925092509250600060608473ffffffffffffffffffffffffffffffffffffffff16846040518082805190602001908083835b602083106102ac57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161026f565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461030c576040519150601f19603f3d011682016040523d82523d6000602084013e610311565b606091505b50915091508161032357805160208201fd5b8051602082012083811461039857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f554e45585045435445445f5354415449435f43414c4c5f524553554c54000000604482015290519081900360640190fd5b5050505050505050505050565b600060405180806104b06021913960210190506040518091039020905090565b6060818311156103e3576103e36103de60008585610408565b6104a7565b83518211156103fc576103fc6103de6001848751610408565b50819003910190815290565b6060632800659560e01b8484846040516024018084600781111561042857fe5b60ff1681526020018381526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090509392505050565b805160208201fdfe53746174696343616c6c28616464726573732c62797465732c6279746573333229a265627a7a72315820c55cf13cfcaaf322238d786911313ce7d45854692241ae9b56709bdbfed4f54c64736f6c634300050b0032'; /** @@ -96,53 +105,6 @@ export class StaticCallProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @param assetData Byte array encoded with staticCallTarget, staticCallData, - * and expectedCallResultHash - * @param from This value is ignored. - * @param to This value is ignored. - * @param amount This value is ignored. - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(assetData: string, from: string, to: string, amount: BigNumber): string { - assert.isString('assetData', assetData); - assert.isString('from', from); - assert.isString('to', to); - assert.isBigNumber('amount', amount); - const self = (this as any) as StaticCallProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments( - 'transferFrom(bytes,address,address,uint256)', - [assetData, from.toLowerCase(), to.toLowerCase(), amount], - ); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [string, string, string, BigNumber] { - const self = (this as any) as StaticCallProxyContract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(bytes,address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[string, string, string, BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as StaticCallProxyContract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(bytes,address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * Gets the proxy id associated with the proxy address. @@ -169,7 +131,7 @@ export class StaticCallProxyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -182,41 +144,6 @@ export class StaticCallProxyContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as StaticCallProxyContract; - const abiEncodedTransactionData = self._strictEncodeArguments('getProxyId()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as StaticCallProxyContract; - const abiEncoder = self._lookupAbiEncoder('getProxyId()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as StaticCallProxyContract; - const abiEncoder = self._lookupAbiEncoder('getProxyId()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public static async deployFrom0xArtifactAsync( artifact: ContractArtifact | SimpleContractArtifact, diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/weth9.ts b/packages/abi-gen-wrappers/src/generated-wrappers/weth9.ts index 699f18d94c..8b9f28a6b3 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/weth9.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/weth9.ts @@ -19,7 +19,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -64,8 +70,10 @@ export interface WETH9WithdrawalEventArgs extends DecodedLogArgs { // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class WETH9Contract extends BaseContract { - public static deployedBytecode = - '0x6080604052600436106100925760003560e01c63ffffffff16806306fdde031461009c578063095ea7b31461012657806318160ddd1461016b57806323b872dd146101925780632e1a7d4d146101c9578063313ce567146101e157806370a082311461020c57806395d89b411461023a578063a9059cbb1461024f578063d0e30db014610092578063dd62ed3e14610280575b61009a6102b4565b005b3480156100a857600080fd5b506100b1610303565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100eb5781810151838201526020016100d3565b50505050905090810190601f1680156101185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561013257600080fd5b5061015773ffffffffffffffffffffffffffffffffffffffff600435166024356103af565b604080519115158252519081900360200190f35b34801561017757600080fd5b50610180610422565b60408051918252519081900360200190f35b34801561019e57600080fd5b5061015773ffffffffffffffffffffffffffffffffffffffff60043581169060243516604435610427565b3480156101d557600080fd5b5061009a6004356105c7565b3480156101ed57600080fd5b506101f661065c565b6040805160ff9092168252519081900360200190f35b34801561021857600080fd5b5061018073ffffffffffffffffffffffffffffffffffffffff60043516610665565b34801561024657600080fd5b506100b1610677565b34801561025b57600080fd5b5061015773ffffffffffffffffffffffffffffffffffffffff600435166024356106ef565b34801561028c57600080fd5b5061018073ffffffffffffffffffffffffffffffffffffffff60043581169060243516610703565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156103a75780601f1061037c576101008083540402835291602001916103a7565b820191906000526020600020905b81548152906001019060200180831161038a57829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b303190565b73ffffffffffffffffffffffffffffffffffffffff831660009081526003602052604081205482111561045957600080fd5b73ffffffffffffffffffffffffffffffffffffffff841633148015906104cf575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105495773ffffffffffffffffffffffffffffffffffffffff8416600090815260046020908152604080832033845290915290205482111561051157600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020805483900390555b73ffffffffffffffffffffffffffffffffffffffff808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b336000908152600360205260409020548111156105e357600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f19350505050158015610622573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156103a75780601f1061037c576101008083540402835291602001916103a7565b60006106fc338484610427565b9392505050565b6004602090815260009283526040808420909152908252902054815600a165627a7a723058201ebe888a6b56dd871f599adbe0f19ec3c29c28aec0685788dfac9b37a99fc9d20029'; + /** + * @ignore + */ + public static deployedBytecode: string | undefined; public name = { /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an @@ -108,41 +116,6 @@ export class WETH9Contract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as WETH9Contract; - const abiEncodedTransactionData = self._strictEncodeArguments('name()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('name()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('name()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public approve = { /** @@ -151,7 +124,12 @@ export class WETH9Contract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(guy: string, wad: BigNumber, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + guy: string, + wad: BigNumber, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('guy', guy); assert.isBigNumber('wad', wad); const self = (this as any) as WETH9Contract; @@ -168,6 +146,10 @@ export class WETH9Contract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.approve.callAsync(guy, wad, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -182,21 +164,20 @@ export class WETH9Contract extends BaseContract { guy: string, wad: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('guy', guy); assert.isBigNumber('wad', wad); const self = (this as any) as WETH9Contract; - const txHashPromise = self.approve.sendTransactionAsync(guy.toLowerCase(), wad, txData); + const txHashPromise = self.approve.sendTransactionAsync(guy.toLowerCase(), wad, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -226,15 +207,6 @@ export class WETH9Contract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - guy: string, - wad: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).approve.callAsync(guy, wad, txData); - const txHash = await (this as any).approve.sendTransactionAsync(guy, wad, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -299,30 +271,6 @@ export class WETH9Contract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('approve(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('approve(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public totalSupply = { /** @@ -366,41 +314,6 @@ export class WETH9Contract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as WETH9Contract; - const abiEncodedTransactionData = self._strictEncodeArguments('totalSupply()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('totalSupply()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('totalSupply()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public transferFrom = { /** @@ -414,6 +327,7 @@ export class WETH9Contract extends BaseContract { dst: string, wad: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('src', src); assert.isString('dst', dst); @@ -436,6 +350,10 @@ export class WETH9Contract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transferFrom.callAsync(src, dst, wad, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -451,8 +369,7 @@ export class WETH9Contract extends BaseContract { dst: string, wad: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('src', src); assert.isString('dst', dst); @@ -463,6 +380,7 @@ export class WETH9Contract extends BaseContract { dst.toLowerCase(), wad, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -470,8 +388,8 @@ export class WETH9Contract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -511,16 +429,6 @@ export class WETH9Contract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - src: string, - dst: string, - wad: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).transferFrom.callAsync(src, dst, wad, txData); - const txHash = await (this as any).transferFrom.sendTransactionAsync(src, dst, wad, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -593,30 +501,6 @@ export class WETH9Contract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public withdraw = { /** @@ -625,7 +509,11 @@ export class WETH9Contract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(wad: BigNumber, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + wad: BigNumber, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isBigNumber('wad', wad); const self = (this as any) as WETH9Contract; const encodedData = self._strictEncodeArguments('withdraw(uint256)', [wad]); @@ -641,6 +529,10 @@ export class WETH9Contract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.withdraw.callAsync(wad, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -654,20 +546,19 @@ export class WETH9Contract extends BaseContract { awaitTransactionSuccessAsync( wad: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isBigNumber('wad', wad); const self = (this as any) as WETH9Contract; - const txHashPromise = self.withdraw.sendTransactionAsync(wad, txData); + const txHashPromise = self.withdraw.sendTransactionAsync(wad, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -696,11 +587,6 @@ export class WETH9Contract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(wad: BigNumber, txData?: Partial | undefined): Promise { - await (this as any).withdraw.callAsync(wad, txData); - const txHash = await (this as any).withdraw.sendTransactionAsync(wad, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -755,30 +641,6 @@ export class WETH9Contract extends BaseContract { const abiEncodedTransactionData = self._strictEncodeArguments('withdraw(uint256)', [wad]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): [BigNumber] { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('withdraw(uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode<[BigNumber]>(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('withdraw(uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public decimals = { /** @@ -822,41 +684,6 @@ export class WETH9Contract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as WETH9Contract; - const abiEncodedTransactionData = self._strictEncodeArguments('decimals()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('decimals()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): number { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('decimals()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public balanceOf = { /** @@ -905,44 +732,6 @@ export class WETH9Contract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: string): string { - assert.isString('index_0', index_0); - const self = (this as any) as WETH9Contract; - const abiEncodedTransactionData = self._strictEncodeArguments('balanceOf(address)', [ - index_0.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('balanceOf(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('balanceOf(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public symbol = { /** @@ -986,41 +775,6 @@ export class WETH9Contract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as WETH9Contract; - const abiEncodedTransactionData = self._strictEncodeArguments('symbol()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('symbol()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('symbol()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public transfer = { /** @@ -1029,7 +783,12 @@ export class WETH9Contract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(dst: string, wad: BigNumber, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + dst: string, + wad: BigNumber, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isString('dst', dst); assert.isBigNumber('wad', wad); const self = (this as any) as WETH9Contract; @@ -1046,6 +805,10 @@ export class WETH9Contract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transfer.callAsync(dst, wad, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1060,21 +823,20 @@ export class WETH9Contract extends BaseContract { dst: string, wad: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('dst', dst); assert.isBigNumber('wad', wad); const self = (this as any) as WETH9Contract; - const txHashPromise = self.transfer.sendTransactionAsync(dst.toLowerCase(), wad, txData); + const txHashPromise = self.transfer.sendTransactionAsync(dst.toLowerCase(), wad, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1104,15 +866,6 @@ export class WETH9Contract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - dst: string, - wad: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).transfer.callAsync(dst, wad, txData); - const txHash = await (this as any).transfer.sendTransactionAsync(dst, wad, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1177,30 +930,6 @@ export class WETH9Contract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('transfer(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('transfer(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public deposit = { /** @@ -1209,7 +938,10 @@ export class WETH9Contract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(txData?: Partial | undefined): Promise { + async sendTransactionAsync( + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { const self = (this as any) as WETH9Contract; const encodedData = self._strictEncodeArguments('deposit()', []); const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( @@ -1224,6 +956,10 @@ export class WETH9Contract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.deposit.callAsync(txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1236,19 +972,18 @@ export class WETH9Contract extends BaseContract { */ awaitTransactionSuccessAsync( txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { const self = (this as any) as WETH9Contract; - const txHashPromise = self.deposit.sendTransactionAsync(txData); + const txHashPromise = self.deposit.sendTransactionAsync(txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1276,11 +1011,6 @@ export class WETH9Contract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(txData?: Partial | undefined): Promise { - await (this as any).deposit.callAsync(txData); - const txHash = await (this as any).deposit.sendTransactionAsync(txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1333,30 +1063,6 @@ export class WETH9Contract extends BaseContract { const abiEncodedTransactionData = self._strictEncodeArguments('deposit()', []); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('deposit()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): void { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('deposit()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public allowance = { /** @@ -1410,46 +1116,6 @@ export class WETH9Contract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(index_0: string, index_1: string): string { - assert.isString('index_0', index_0); - assert.isString('index_1', index_1); - const self = (this as any) as WETH9Contract; - const abiEncodedTransactionData = self._strictEncodeArguments('allowance(address,address)', [ - index_0.toLowerCase(), - index_1.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('allowance(address,address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as WETH9Contract; - const abiEncoder = self._lookupAbiEncoder('allowance(address,address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; private readonly _subscriptionManager: SubscriptionManager; public static async deployFrom0xArtifactAsync( diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/zrx_token.ts b/packages/abi-gen-wrappers/src/generated-wrappers/zrx_token.ts index 6f60e3abab..0eb90329e6 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/zrx_token.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/zrx_token.ts @@ -19,7 +19,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -48,8 +54,10 @@ export interface ZRXTokenApprovalEventArgs extends DecodedLogArgs { // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class ZRXTokenContract extends BaseContract { - public static deployedBytecode = - '0x606060405236156100965763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde038114610098578063095ea7b31461014657806318160ddd1461018657806323b872dd146101a8578063313ce567146101ee57806370a082311461021457806395d89b411461024f578063a9059cbb146102fd578063dd62ed3e1461033d575bfe5b34156100a057fe5b6100a861037e565b60408051602080825283518183015283519192839290830191850190808383821561010c575b80518252602083111561010c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016100ce565b505050905090810190601f1680156101385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561014e57fe5b61017273ffffffffffffffffffffffffffffffffffffffff600435166024356103b5565b604080519115158252519081900360200190f35b341561018e57fe5b61019661042d565b60408051918252519081900360200190f35b34156101b057fe5b61017273ffffffffffffffffffffffffffffffffffffffff60043581169060243516604435610433565b604080519115158252519081900360200190f35b34156101f657fe5b6101fe6105d4565b6040805160ff9092168252519081900360200190f35b341561021c57fe5b61019673ffffffffffffffffffffffffffffffffffffffff600435166105d9565b60408051918252519081900360200190f35b341561025757fe5b6100a8610605565b60408051602080825283518183015283519192839290830191850190808383821561010c575b80518252602083111561010c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016100ce565b505050905090810190601f1680156101385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561030557fe5b61017273ffffffffffffffffffffffffffffffffffffffff6004351660243561063c565b604080519115158252519081900360200190f35b341561034557fe5b61019673ffffffffffffffffffffffffffffffffffffffff60043581169060243516610727565b60408051918252519081900360200190f35b60408051808201909152601181527f30782050726f746f636f6c20546f6b656e000000000000000000000000000000602082015281565b73ffffffffffffffffffffffffffffffffffffffff338116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60035481565b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832033909516835293815283822054928252819052918220548390108015906104835750828110155b80156104b6575073ffffffffffffffffffffffffffffffffffffffff841660009081526020819052604090205483810110155b156105c65773ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220805487019055918716815220805484900390557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156105585773ffffffffffffffffffffffffffffffffffffffff808616600090815260016020908152604080832033909416835292905220805484900390555b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a3600191506105cb565b600091505b5b509392505050565b601281565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602081905260409020545b919050565b60408051808201909152600381527f5a52580000000000000000000000000000000000000000000000000000000000602082015281565b73ffffffffffffffffffffffffffffffffffffffff3316600090815260208190526040812054829010801590610699575073ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205482810110155b156107185773ffffffffffffffffffffffffffffffffffffffff33811660008181526020818152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a3506001610427565b506000610427565b5b92915050565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600160209081526040808320938516835292905220545b929150505600a165627a7a72305820d984298155c708a8164f1cbf83c7275bcc6851dd082c0404013c1f4463b238fa0029'; + /** + * @ignore + */ + public static deployedBytecode: string | undefined; public name = { /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an @@ -92,41 +100,6 @@ export class ZRXTokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ZRXTokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('name()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('name()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('name()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public approve = { /** @@ -139,6 +112,7 @@ export class ZRXTokenContract extends BaseContract { _spender: string, _value: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_spender', _spender); assert.isBigNumber('_value', _value); @@ -159,6 +133,10 @@ export class ZRXTokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.approve.callAsync(_spender, _value, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -173,21 +151,20 @@ export class ZRXTokenContract extends BaseContract { _spender: string, _value: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_spender', _spender); assert.isBigNumber('_value', _value); const self = (this as any) as ZRXTokenContract; - const txHashPromise = self.approve.sendTransactionAsync(_spender.toLowerCase(), _value, txData); + const txHashPromise = self.approve.sendTransactionAsync(_spender.toLowerCase(), _value, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -224,15 +201,6 @@ export class ZRXTokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _spender: string, - _value: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).approve.callAsync(_spender, _value, txData); - const txHash = await (this as any).approve.sendTransactionAsync(_spender, _value, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -300,30 +268,6 @@ export class ZRXTokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('approve(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('approve(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public totalSupply = { /** @@ -367,41 +311,6 @@ export class ZRXTokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ZRXTokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('totalSupply()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('totalSupply()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('totalSupply()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; /** * ERC20 transferFrom, modified such that an allowance of MAX_UINT represents an unlimited allowance. @@ -421,6 +330,7 @@ export class ZRXTokenContract extends BaseContract { _to: string, _value: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_from', _from); assert.isString('_to', _to); @@ -443,6 +353,10 @@ export class ZRXTokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transferFrom.callAsync(_from, _to, _value, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -461,8 +375,7 @@ export class ZRXTokenContract extends BaseContract { _to: string, _value: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_from', _from); assert.isString('_to', _to); @@ -473,6 +386,7 @@ export class ZRXTokenContract extends BaseContract { _to.toLowerCase(), _value, txData, + opts, ); return new PromiseWithTransactionHash( txHashPromise, @@ -480,8 +394,8 @@ export class ZRXTokenContract extends BaseContract { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -524,16 +438,6 @@ export class ZRXTokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _from: string, - _to: string, - _value: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).transferFrom.callAsync(_from, _to, _value, txData); - const txHash = await (this as any).transferFrom.sendTransactionAsync(_from, _to, _value, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -613,30 +517,6 @@ export class ZRXTokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('transferFrom(address,address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public decimals = { /** @@ -680,41 +560,6 @@ export class ZRXTokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ZRXTokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('decimals()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('decimals()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): number { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('decimals()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public balanceOf = { /** @@ -763,42 +608,6 @@ export class ZRXTokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(_owner: string): string { - assert.isString('_owner', _owner); - const self = (this as any) as ZRXTokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('balanceOf(address)', [_owner.toLowerCase()]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('balanceOf(address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('balanceOf(address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public symbol = { /** @@ -842,41 +651,6 @@ export class ZRXTokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(): string { - const self = (this as any) as ZRXTokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('symbol()', []); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): void { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('symbol()'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): string { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('symbol()'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public transfer = { /** @@ -889,6 +663,7 @@ export class ZRXTokenContract extends BaseContract { _to: string, _value: BigNumber, txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { assert.isString('_to', _to); assert.isBigNumber('_value', _value); @@ -906,6 +681,10 @@ export class ZRXTokenContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.transfer.callAsync(_to, _value, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -920,21 +699,20 @@ export class ZRXTokenContract extends BaseContract { _to: string, _value: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isString('_to', _to); assert.isBigNumber('_value', _value); const self = (this as any) as ZRXTokenContract; - const txHashPromise = self.transfer.sendTransactionAsync(_to.toLowerCase(), _value, txData); + const txHashPromise = self.transfer.sendTransactionAsync(_to.toLowerCase(), _value, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -964,15 +742,6 @@ export class ZRXTokenContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync( - _to: string, - _value: BigNumber, - txData?: Partial | undefined, - ): Promise { - await (this as any).transfer.callAsync(_to, _value, txData); - const txHash = await (this as any).transfer.sendTransactionAsync(_to, _value, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1037,30 +806,6 @@ export class ZRXTokenContract extends BaseContract { ]); return abiEncodedTransactionData; }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('transfer(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): boolean { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('transfer(address,uint256)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; public allowance = { /** @@ -1114,46 +859,6 @@ export class ZRXTokenContract extends BaseContract { // tslint:enable boolean-naming return result; }, - /** - * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before - * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used - * to create a 0x transaction (see protocol spec for more details). - * @returns The ABI encoded transaction data as a string - */ - getABIEncodedTransactionData(_owner: string, _spender: string): string { - assert.isString('_owner', _owner); - assert.isString('_spender', _spender); - const self = (this as any) as ZRXTokenContract; - const abiEncodedTransactionData = self._strictEncodeArguments('allowance(address,address)', [ - _owner.toLowerCase(), - _spender.toLowerCase(), - ]); - return abiEncodedTransactionData; - }, - /** - * Decode the ABI-encoded transaction data into its input arguments - * @param callData The ABI-encoded transaction data - * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. - */ - getABIDecodedTransactionData(callData: string): string { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('allowance(address,address)'); - // tslint:disable boolean-naming - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - }, - /** - * Decode the ABI-encoded return data from a transaction - * @param returnData the data returned after transaction execution - * @returns An array representing the output results in order. Keynames of nested structs are preserved. - */ - getABIDecodedReturnData(returnData: string): BigNumber { - const self = (this as any) as ZRXTokenContract; - const abiEncoder = self._lookupAbiEncoder('allowance(address,address)'); - // tslint:disable boolean-naming - const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); - return abiDecodedReturnData; - }, }; private readonly _subscriptionManager: SubscriptionManager; public static async deployFrom0xArtifactAsync( diff --git a/packages/abi-gen/package.json b/packages/abi-gen/package.json index 79d7557875..b1cbfed930 100644 --- a/packages/abi-gen/package.json +++ b/packages/abi-gen/package.json @@ -36,7 +36,7 @@ "watch:sol": "sol-compiler -w", "prettier_contract_wrappers": "prettier --write ./test-cli/output/typescript/* --config ../../.prettierrc", "generate_contract_wrappers": "run-p gen_typescript gen_python", - "gen_typescript": "abi-gen --abis ${npm_package_config_abis} --output ./test-cli/output/typescript --backend ethers", + "gen_typescript": "abi-gen --abis ${npm_package_config_abis} --debug --output ./test-cli/output/typescript --backend ethers", "gen_python": "pip install black && abi-gen --abis ${npm_package_config_abis} --output ./test-cli/output/python --language Python", "diff_contract_wrappers": "git diff --exit-code ./test-cli/output", "coverage:report:text": "istanbul report text", @@ -79,9 +79,11 @@ "yargs": "^10.0.3" }, "devDependencies": { + "@0x/assert": "^2.2.0-beta.0", "@0x/base-contract": "^5.5.0-beta.0", "@0x/contracts-gen": "^1.1.0-beta.0", "@0x/dev-utils": "^2.4.0-beta.0", + "@0x/json-schemas": "^4.1.0-beta.0", "@0x/sol-compiler": "^3.2.0-beta.0", "@0x/subproviders": "^5.1.0-beta.0", "@0x/tslint-config": "^3.0.1", @@ -96,6 +98,7 @@ "chai-as-promised": "^7.1.0", "chai-bignumber": "^3.0.0", "dirty-chai": "^2.0.1", + "ethers": "~4.0.4", "make-promises-safe": "^1.1.0", "mocha": "^6.2.0", "npm-run-all": "^4.1.2", diff --git a/packages/abi-gen/src/index.ts b/packages/abi-gen/src/index.ts index c7b243e97b..f9793aa5d6 100644 --- a/packages/abi-gen/src/index.ts +++ b/packages/abi-gen/src/index.ts @@ -44,6 +44,10 @@ const args = yargs normalize: true, demandOption: true, }) + .option('debug', { + describe: 'Includes debug functions in the wrappers such as `getABIDecodedTransactionData`', + type: 'boolean', + }) .option('partials', { describe: 'Glob pattern for the partial template files', type: 'string', @@ -73,12 +77,11 @@ const args = yargs default: 'TypeScript', }) .example( - "$0 --abis 'src/artifacts/**/*.json' --out 'src/contracts/generated/' --partials 'src/templates/partials/**/*.handlebars' --template 'src/templates/contract.handlebars'", + "$0 --abis 'src/artifacts/**/*.json' --out 'src/contracts/generated/' --debug --partials 'src/templates/partials/**/*.handlebars' --template 'src/templates/contract.handlebars'", 'Full usage example', ).argv; const templateFilename = args.template || `${__dirname}/../../templates/${args.language}/contract.handlebars`; - const mainTemplate = utils.getNamedContent(templateFilename); const template = Handlebars.compile(mainTemplate.content); const abiFileNames = globSync(args.abis); @@ -417,14 +420,17 @@ for (const abiFileName of abiFileNames) { return eventData; }); + const shouldIncludeBytecode = methodsData.find(methodData => methodData.stateMutability === 'pure') !== undefined; + const contextData = { contractName: namedContent.name, ctor, - deployedBytecode, + deployedBytecode: shouldIncludeBytecode ? deployedBytecode : undefined, ABI: ABI as ContractAbi, ABIString: JSON.stringify(ABI), methods: methodsData, events: eventsData, + debug: args.debug, }; const renderedCode = template(contextData); utils.writeOutputFile(outFilePath, renderedCode); diff --git a/packages/abi-gen/templates/TypeScript/contract.handlebars b/packages/abi-gen/templates/TypeScript/contract.handlebars index d7dd089680..2c84f35692 100644 --- a/packages/abi-gen/templates/TypeScript/contract.handlebars +++ b/packages/abi-gen/templates/TypeScript/contract.handlebars @@ -20,7 +20,7 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { AwaitTransactionSuccessOpts, EventCallback, IndexedFilterValues, SendTransactionOpts, SimpleContractArtifact } from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -48,6 +48,9 @@ export enum {{contractName}}Events { // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class {{contractName}}Contract extends BaseContract { + /** + * @ignore + */ {{#ifEquals this.deployedBytecode undefined~}} public static deployedBytecode: string | undefined; {{else~}} @@ -69,7 +72,7 @@ export class {{contractName}}Contract extends BaseContract { {{else}} {{> method_call contractName=../contractName}} {{/ifEquals}} - {{> method_abi_helper contractName=../contractName}} + {{> method_abi_helper contractName=../contractName debug=../debug}} }; {{/each}} {{#if events}}private readonly _subscriptionManager: SubscriptionManager<{{contractName}}EventArgs, {{contractName}}Events>; diff --git a/packages/abi-gen/templates/TypeScript/partials/method_abi_helper.handlebars b/packages/abi-gen/templates/TypeScript/partials/method_abi_helper.handlebars index 0c8f1893af..9fee7996f7 100644 --- a/packages/abi-gen/templates/TypeScript/partials/method_abi_helper.handlebars +++ b/packages/abi-gen/templates/TypeScript/partials/method_abi_helper.handlebars @@ -1,3 +1,27 @@ +{{!-- if ((NOT constant) AND (NOT debug)), to avoid repetition bbecause we use all 3 functions if (debug) --}} +{{^if constant~}} +{{^if debug~}} +/** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). +{{> params_docstring inputs=inputs docstrings=devdoc.params}} + * @returns The ABI encoded transaction data as a string + */ +getABIEncodedTransactionData( + {{> typed_params inputs=inputs}} + ): string { + {{#each inputs}} + {{#assertionType name type}}{{/assertionType}} + {{/each}} + const self = this as any as {{contractName}}Contract; + const abiEncodedTransactionData = self._strictEncodeArguments('{{this.functionSignature}}', [{{> normalized_params inputs=inputs}}]); + return abiEncodedTransactionData; +}, +{{/if~}} +{{/if~}} + +{{#if debug~}} /** * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used @@ -43,3 +67,4 @@ getABIDecodedReturnData( const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue<{{> return_type outputs=outputs}}>(returnData); return abiDecodedReturnData; }, +{{/if}} diff --git a/packages/abi-gen/templates/TypeScript/partials/method_call_pure.handlebars b/packages/abi-gen/templates/TypeScript/partials/method_call_pure.handlebars index 3b7e1ab82c..2ec68190f9 100644 --- a/packages/abi-gen/templates/TypeScript/partials/method_call_pure.handlebars +++ b/packages/abi-gen/templates/TypeScript/partials/method_call_pure.handlebars @@ -29,7 +29,7 @@ async callAsync( let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; diff --git a/packages/abi-gen/templates/TypeScript/partials/method_tx.handlebars b/packages/abi-gen/templates/TypeScript/partials/method_tx.handlebars index d4bbdc9d75..de4e7eb324 100644 --- a/packages/abi-gen/templates/TypeScript/partials/method_tx.handlebars +++ b/packages/abi-gen/templates/TypeScript/partials/method_tx.handlebars @@ -8,6 +8,7 @@ async sendTransactionAsync( {{> typed_params inputs=inputs}} txData?: Partial | undefined, +opts: SendTransactionOpts = { shouldValidate: true }, ): Promise { {{#each inputs}} {{#assertionType name type}}{{/assertionType}} @@ -26,6 +27,15 @@ txData?: Partial | undefined, txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.{{languageSpecificName}}.callAsync( + {{#each inputs~}} + {{name}}, + {{/each~}} + txDataWithDefaults, + ); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -40,17 +50,16 @@ txData?: Partial | undefined, awaitTransactionSuccessAsync( {{> typed_params inputs=inputs}} txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { {{#each inputs}} {{#assertionType name type}}{{/assertionType}} {{/each}} const self = this as any as {{contractName}}Contract; {{#if inputs}} - const txHashPromise = self.{{languageSpecificName}}.sendTransactionAsync({{> normalized_params input=inputs}}, txData); + const txHashPromise = self.{{languageSpecificName}}.sendTransactionAsync({{> normalized_params input=inputs}}, txData, opts); {{else}} - const txHashPromise = self.{{languageSpecificName}}.sendTransactionAsync(txData); + const txHashPromise = self.{{languageSpecificName}}.sendTransactionAsync(txData, opts); {{/if}} return new PromiseWithTransactionHash( txHashPromise, @@ -58,8 +67,8 @@ awaitTransactionSuccessAsync( // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -94,21 +103,3 @@ async estimateGasAsync( const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, -async validateAndSendTransactionAsync( - {{> typed_params inputs=inputs}} - txData?: Partial | undefined, - ): Promise { - await (this as any).{{languageSpecificName}}.callAsync( - {{#each inputs~}} - {{name}}, - {{/each~}} - txData, - ); - const txHash = await (this as any).{{languageSpecificName}}.sendTransactionAsync( - {{#each inputs~}} - {{name}}, - {{/each~}} - txData, - ); - return txHash; -}, diff --git a/packages/abi-gen/test-cli/output/typescript/abi_gen_dummy.ts b/packages/abi-gen/test-cli/output/typescript/abi_gen_dummy.ts index 5b149586fb..8b626041d0 100644 --- a/packages/abi-gen/test-cli/output/typescript/abi_gen_dummy.ts +++ b/packages/abi-gen/test-cli/output/typescript/abi_gen_dummy.ts @@ -19,7 +19,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { EventCallback, IndexedFilterValues, SimpleContractArtifact } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -46,6 +52,9 @@ export interface AbiGenDummySimpleEventEventArgs extends DecodedLogArgs { // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class AbiGenDummyContract extends BaseContract { + /** + * @ignore + */ public static deployedBytecode = '0x608060405234801561001057600080fd5b50600436106101d95760003560e01c806376f15d5b11610104578063bb607362116100a2578063d88be12f11610071578063d88be12f1461039b578063ee8b86fb146103a3578063f408fb3114610279578063fa315f9d146103b6576101d9565b8063bb60736214610353578063bdab168814610369578063cd3c0b971461037e578063d6d7618c14610386576101d9565b80638ee52b4e116100de5780638ee52b4e146103225780639a3b618514610335578063a3c2f6b61461033d578063ae2dae1714610345576101d9565b806376f15d5b146102f25780637833bec0146102fa5780637a791e6e1461031a576101d9565b80634303a5421161017c57806359c28add1161014b57806359c28add146102b45780635ba3c7c0146102c957806363d69c88146102d1578063647341eb146102e4576101d9565b80634303a542146102875780634582eab21461028f57806345fdbdb714610297578063586f84b21461029f576101d9565b80632e1a7d4d116101b85780632e1a7d4d146102245780633687617d1461023757806336b32396146102595780633e9ef66a14610279576101d9565b806209e437146101de5780630527c28f146101e85780631310e444146101fb575b600080fd5b6101e66103c4565b005b6101e66101f6366004610c7f565b610401565b61020e610209366004610d34565b610404565b60405161021b919061139a565b60405180910390f35b6101e6610232366004610d34565b61040b565b61024a610245366004610eac565b61045c565b60405161021b93929190611103565b61026c610267366004610cbc565b6104fc565b60405161021b9190611045565b6101e66101f6366004610cff565b61020e6105de565b6101e66105e5565b6101e661064a565b6102a761067c565b60405161021b9190611325565b6102bc610684565b60405161021b9190611330565b6101e661068c565b61026c6102df366004610c2d565b6106f1565b6101e66101f6366004610e77565b61020e6106fa565b61030d610308366004610d4d565b610708565b60405161021b9190611239565b6101e66107c5565b61020e610330366004610d34565b6107ca565b6101e66107d0565b61020e6107db565b6101e66101f6366004610de7565b61035b6107e0565b60405161021b9291906113a3565b610371610819565b60405161021b9190611066565b6101e661081e565b61038e610855565b60405161021b9190611387565b61020e6109ae565b6101e66103b1366004610d34565b6101f6565b6101e66101f6366004610d34565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f690611202565b60405180910390fd5b565b50565b506107c790565b3373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b6582604051610451919061139a565b60405180910390a250565b505060408051808201825260048082527f1234567800000000000000000000000000000000000000000000000000000000602080840191909152835180850185528281527f87654321000000000000000000000000000000000000000000000000000000008183015284518086019095529184527f616d657400000000000000000000000000000000000000000000000000000000908401529093909250565b600060606040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525090506000818760405160200161054d929190611023565b6040516020818303038152906040528051906020012090506001818787876040516000815260200160405260405161058894939291906110e5565b6020604051602081039080840390855afa1580156105aa573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015198975050505050505050565b6107c75b90565b604080518082018252601481527f5245564552545f574954485f434f4e5354414e54000000000000000000000000602082015290517f08c379a00000000000000000000000000000000000000000000000000000000081526103f69190600401611145565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f6906111cb565b6105e26109b4565b6105e26109cc565b604080518082018252601581527f524551554952455f574954485f434f4e5354414e540000000000000000000000602082015290517f08c379a00000000000000000000000000000000000000000000000000000000081526103f69190600401611145565b50929392505050565b600080546001019081905590565b6107106109ec565b50604080516080810182529182528051808201825260048082527f123456780000000000000000000000000000000000000000000000000000000060208381019190915280850192909252825180840184528181527f87654321000000000000000000000000000000000000000000000000000000008184015284840152825180840190935282527f616d65740000000000000000000000000000000000000000000000000000000090820152606082015290565b6103ff565b60010190565b600080546001019055565b600190565b60408051808201909152600581527f68656c6c6f0000000000000000000000000000000000000000000000000000006020820152600191565b606090565b7f61a6029a4c7ddee5824d171331eecbd015d26a271310a223718b837facb5b77160405161084b9061115f565b60405180910390a1565b61085d610a1a565b6040805160028082526060828101909352816020015b60608152602001906001900390816108735790505090506040518060400160405280600581526020017f3078313233000000000000000000000000000000000000000000000000000000815250816000815181106108cd57fe5b60200260200101819052506040518060400160405280600581526020017f30783332310000000000000000000000000000000000000000000000000000008152508160018151811061091b57fe5b6020908102919091018101919091526040805160c0810182526005608082018181527f307831323300000000000000000000000000000000000000000000000000000060a0840152825281840152808201939093528051808201909152600381527f6162630000000000000000000000000000000000000000000000000000000000918101919091526060820152905090565b6104d290565b60405180602001604052806109c7610a48565b905290565b60405180604001604052806109df610a1a565b8152602001606081525090565b60405180608001604052806109ff610a5b565b81526020016060815260200160608152602001606081525090565b604051806080016040528060608152602001600063ffffffff16815260200160608152602001606081525090565b6040518060200160405280600081525090565b60405180606001604052806000815260200160608152602001606081525090565b600082601f830112610a8c578081fd5b813567ffffffffffffffff811115610aa2578182fd5b6020610ab181828402016113bc565b828152925080830184820160005b84811015610ae857610ad6888584358a0101610af3565b83529183019190830190600101610abf565b505050505092915050565b600082601f830112610b03578081fd5b813567ffffffffffffffff811115610b19578182fd5b610b4a60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016113bc565b9150808252836020828501011115610b6157600080fd5b8060208401602084013760009082016020015292915050565b600060808284031215610b8b578081fd5b610b9560806113bc565b90506000823567ffffffffffffffff80821115610bb0578283fd5b610bbc86838701610af3565b84526020850135915063ffffffff82168214610bd6578283fd5b8160208501526040850135915080821115610bef578283fd5b610bfb86838701610a7c565b60408501526060850135915080821115610c13578283fd5b50610c2085828601610af3565b6060840152505092915050565b600080600080600060a08688031215610c4557600080fd5b8535610c5081611413565b945060208601359350604086013592506060860135610c6e81611413565b949793965091946080013592915050565b600060208284031215610c9157600080fd5b813567ffffffffffffffff811115610ca857600080fd5b610cb484828501610a7c565b949350505050565b60008060008060808587031215610cd257600080fd5b84359350602085013560ff81168114610cea57600080fd5b93969395505050506040820135916060013590565b600060208284031215610d1157600080fd5b813567ffffffffffffffff811115610d2857600080fd5b610cb484828501610af3565b600060208284031215610d4657600080fd5b5035919050565b600060208284031215610d5e578081fd5b813567ffffffffffffffff80821115610d75578283fd5b81840160608187031215610d87578384fd5b610d9160606113bc565b925080358352602081013582811115610da8578485fd5b610db487828401610af3565b602085015250604081013582811115610dcb578485fd5b610dd787828401610af3565b6040850152509195945050505050565b600060208284031215610df8578081fd5b813567ffffffffffffffff80821115610e0f578283fd5b81840160408187031215610e21578384fd5b610e2b60406113bc565b9250803582811115610e3b578485fd5b610e4787828401610b7a565b845250602081013582811115610e5b578485fd5b610e6787828401610af3565b6020850152509195945050505050565b600060208284031215610e8957600080fd5b813567ffffffffffffffff811115610ea057600080fd5b610cb484828501610b7a565b600080600060608486031215610ec0578081fd5b83359250602084013567ffffffffffffffff80821115610ede578283fd5b610eea87838801610af3565b93506040860135915080821115610eff578283fd5b50610f0c86828701610af3565b9150509250925092565b60008151808452610f2e8160208601602086016113e3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000815160808452610f756080850182610f16565b6020915063ffffffff82850151168286015260408401518582036040870152818151808452848401915084858202850101858401600094505b82851015610ffc577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868303018452610fe8828251610f16565b600195909501949387019391508601610fae565b506060880151955088810360608a01526110168187610f16565b9998505050505050505050565b600083516110358184602088016113e3565b9190910191825250602001919050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600060208083018184528085518083526040860191506040848202870101925083870160005b828110156110d8577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526110c6858351610f60565b9450928501929085019060010161108c565b5092979650505050505050565b93845260ff9290921660208401526040830152606082015260800190565b6000606082526111166060830186610f16565b82810360208401526111288186610f16565b838103604085015261113a8186610f16565b979650505050505050565b6000602082526111586020830184610f16565b9392505050565b60408082526004908201527f123456780000000000000000000000000000000000000000000000000000000060608201526080602082018190526005908201527f6c6f72656d00000000000000000000000000000000000000000000000000000060a082015260c00190565b6020808252600d908201527f53494d504c455f52455645525400000000000000000000000000000000000000604082015260600190565b6020808252600e908201527f53494d504c455f52455155495245000000000000000000000000000000000000604082015260600190565b600060208252825160806020840152805160a08401526020810151606060c0850152611269610100850182610f16565b604083015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff608582030160e08601526112a48183610f16565b9250505060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808584030160408601526112e28383610f16565b60408701519350818682030160608701526112fd8185610f16565b92505060608601519250808583030160808601525061131c8183610f16565b95945050505050565b905151815260200190565b60006020825282516040602084015261134c6060840182610f60565b602085015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084820301604085015261131c8183610f16565b6000602082526111586020830184610f60565b90815260200190565b600083825260406020830152610cb46040830184610f16565b60405181810167ffffffffffffffff811182821017156113db57600080fd5b604052919050565b60005b838110156113fe5781810151838201526020016113e6565b8381111561140d576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461040157600080fdfea365627a7a723158207f0854b76fc684de0be1f1a5db2d486bc187ff28d1e99d27ca0f61b452a1942f6c6578706572696d656e74616cf564736f6c634300050b0040'; public simpleRequire = { @@ -69,7 +78,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -144,7 +153,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -224,7 +233,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -283,7 +292,11 @@ export class AbiGenDummyContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(wad: BigNumber, txData?: Partial | undefined): Promise { + async sendTransactionAsync( + wad: BigNumber, + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { assert.isBigNumber('wad', wad); const self = (this as any) as AbiGenDummyContract; const encodedData = self._strictEncodeArguments('withdraw(uint256)', [wad]); @@ -299,6 +312,10 @@ export class AbiGenDummyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.withdraw.callAsync(wad, txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -312,20 +329,19 @@ export class AbiGenDummyContract extends BaseContract { awaitTransactionSuccessAsync( wad: BigNumber, txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { assert.isBigNumber('wad', wad); const self = (this as any) as AbiGenDummyContract; - const txHashPromise = self.withdraw.sendTransactionAsync(wad, txData); + const txHashPromise = self.withdraw.sendTransactionAsync(wad, txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -354,11 +370,6 @@ export class AbiGenDummyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(wad: BigNumber, txData?: Partial | undefined): Promise { - await (this as any).withdraw.callAsync(wad, txData); - const txHash = await (this as any).withdraw.sendTransactionAsync(wad, txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -475,7 +486,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -578,7 +589,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -662,7 +673,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -736,7 +747,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -806,7 +817,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -876,7 +887,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -952,7 +963,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1033,7 +1044,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1114,7 +1125,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1200,7 +1211,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1282,7 +1293,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1350,7 +1361,10 @@ export class AbiGenDummyContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(txData?: Partial | undefined): Promise { + async sendTransactionAsync( + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { const self = (this as any) as AbiGenDummyContract; const encodedData = self._strictEncodeArguments('nonPureMethod()', []); const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( @@ -1365,6 +1379,10 @@ export class AbiGenDummyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.nonPureMethod.callAsync(txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1377,19 +1395,18 @@ export class AbiGenDummyContract extends BaseContract { */ awaitTransactionSuccessAsync( txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { const self = (this as any) as AbiGenDummyContract; - const txHashPromise = self.nonPureMethod.sendTransactionAsync(txData); + const txHashPromise = self.nonPureMethod.sendTransactionAsync(txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1417,11 +1434,6 @@ export class AbiGenDummyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(txData?: Partial | undefined): Promise { - await (this as any).nonPureMethod.callAsync(txData); - const txHash = await (this as any).nonPureMethod.sendTransactionAsync(txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1534,7 +1546,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1622,7 +1634,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1693,7 +1705,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -1750,7 +1762,10 @@ export class AbiGenDummyContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(txData?: Partial | undefined): Promise { + async sendTransactionAsync( + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { const self = (this as any) as AbiGenDummyContract; const encodedData = self._strictEncodeArguments('nonPureMethodThatReturnsNothing()', []); const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( @@ -1765,6 +1780,10 @@ export class AbiGenDummyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.nonPureMethodThatReturnsNothing.callAsync(txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -1777,19 +1796,18 @@ export class AbiGenDummyContract extends BaseContract { */ awaitTransactionSuccessAsync( txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { const self = (this as any) as AbiGenDummyContract; - const txHashPromise = self.nonPureMethodThatReturnsNothing.sendTransactionAsync(txData); + const txHashPromise = self.nonPureMethodThatReturnsNothing.sendTransactionAsync(txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -1817,11 +1835,6 @@ export class AbiGenDummyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(txData?: Partial | undefined): Promise { - await (this as any).nonPureMethodThatReturnsNothing.callAsync(txData); - const txHash = await (this as any).nonPureMethodThatReturnsNothing.sendTransactionAsync(txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -1920,7 +1933,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -2005,7 +2018,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -2105,7 +2118,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -2178,7 +2191,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -2240,7 +2253,10 @@ export class AbiGenDummyContract extends BaseContract { * @param txData Additional data for transaction * @returns The hash of the transaction */ - async sendTransactionAsync(txData?: Partial | undefined): Promise { + async sendTransactionAsync( + txData?: Partial | undefined, + opts: SendTransactionOpts = { shouldValidate: true }, + ): Promise { const self = (this as any) as AbiGenDummyContract; const encodedData = self._strictEncodeArguments('emitSimpleEvent()', []); const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( @@ -2255,6 +2271,10 @@ export class AbiGenDummyContract extends BaseContract { txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); } + if (opts.shouldValidate !== false) { + await self.emitSimpleEvent.callAsync(txDataWithDefaults); + } + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); return txHash; }, @@ -2267,19 +2287,18 @@ export class AbiGenDummyContract extends BaseContract { */ awaitTransactionSuccessAsync( txData?: Partial, - pollingIntervalMs?: number, - timeoutMs?: number, + opts: AwaitTransactionSuccessOpts = { shouldValidate: true }, ): PromiseWithTransactionHash { const self = (this as any) as AbiGenDummyContract; - const txHashPromise = self.emitSimpleEvent.sendTransactionAsync(txData); + const txHashPromise = self.emitSimpleEvent.sendTransactionAsync(txData, opts); return new PromiseWithTransactionHash( txHashPromise, (async (): Promise => { // When the transaction hash resolves, wait for it to be mined. return self._web3Wrapper.awaitTransactionSuccessAsync( await txHashPromise, - pollingIntervalMs, - timeoutMs, + opts.pollingIntervalMs, + opts.timeoutMs, ); })(), ); @@ -2307,11 +2326,6 @@ export class AbiGenDummyContract extends BaseContract { const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); return gas; }, - async validateAndSendTransactionAsync(txData?: Partial | undefined): Promise { - await (this as any).emitSimpleEvent.callAsync(txData); - const txHash = await (this as any).emitSimpleEvent.sendTransactionAsync(txData); - return txHash; - }, /** * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas @@ -2417,7 +2431,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -2499,7 +2513,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -2577,7 +2591,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -2649,7 +2663,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -2721,7 +2735,7 @@ export class AbiGenDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; diff --git a/packages/abi-gen/test-cli/output/typescript/lib_dummy.ts b/packages/abi-gen/test-cli/output/typescript/lib_dummy.ts index 2d71295e25..bc01ce2d03 100644 --- a/packages/abi-gen/test-cli/output/typescript/lib_dummy.ts +++ b/packages/abi-gen/test-cli/output/typescript/lib_dummy.ts @@ -18,7 +18,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -28,8 +34,10 @@ import * as ethers from 'ethers'; // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class LibDummyContract extends BaseContract { - public static deployedBytecode = - '0x73000000000000000000000000000000000000000030146080604052600080fdfea265627a7a72305820b14322cd05aa1dcae66812e472d3ab85cced78118ea7f9a5098d073b2accc45964736f6c634300050a0032'; + /** + * @ignore + */ + public static deployedBytecode: string | undefined; public static async deployFrom0xArtifactAsync( artifact: ContractArtifact | SimpleContractArtifact, supportedProvider: SupportedProvider, diff --git a/packages/abi-gen/test-cli/output/typescript/test_lib_dummy.ts b/packages/abi-gen/test-cli/output/typescript/test_lib_dummy.ts index 275781c69c..edc8830abc 100644 --- a/packages/abi-gen/test-cli/output/typescript/test_lib_dummy.ts +++ b/packages/abi-gen/test-cli/output/typescript/test_lib_dummy.ts @@ -18,7 +18,13 @@ import { SupportedProvider, } from 'ethereum-types'; import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; -import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { + AwaitTransactionSuccessOpts, + EventCallback, + IndexedFilterValues, + SendTransactionOpts, + SimpleContractArtifact, +} from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { assert } from '@0x/assert'; import * as ethers from 'ethers'; @@ -28,6 +34,9 @@ import * as ethers from 'ethers'; // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class TestLibDummyContract extends BaseContract { + /** + * @ignore + */ public static deployedBytecode = '0x6080604052348015600f57600080fd5b506004361060325760003560e01c806322935e921460375780632b82fdf0146063575b600080fd5b605160048036036020811015604b57600080fd5b5035607d565b60408051918252519081900360200190f35b605160048036036020811015607757600080fd5b5035608c565b60006086826095565b92915050565b6000608682609c565b6104d20190565b6001019056fea265627a7a72305820ddb720d14b34694daaefebcbd729af6ae04fa2232481812dd8fde63d6a4c32c164736f6c634300050a0032'; public publicAddConstant = { @@ -52,7 +61,7 @@ export class TestLibDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; @@ -124,7 +133,7 @@ export class TestLibDummyContract extends BaseContract { let rawCallResult; try { - rawCallResult = await self.evmExecAsync(encodedDataBytes); + rawCallResult = await self._evmExecAsync(encodedDataBytes); } catch (err) { BaseContract._throwIfThrownErrorIsRevertError(err); throw err; diff --git a/packages/abi-gen/test-cli/test_typescript/test/abi_gen_dummy_test.ts b/packages/abi-gen/test-cli/test_typescript/test/abi_gen_dummy_test.ts index 80a4281061..948f909c7a 100644 --- a/packages/abi-gen/test-cli/test_typescript/test/abi_gen_dummy_test.ts +++ b/packages/abi-gen/test-cli/test_typescript/test/abi_gen_dummy_test.ts @@ -138,14 +138,6 @@ describe('AbiGenDummy Contract', () => { }); }); - describe('validate and send transaction', () => { - it('should call validateAndSendTransactionAsync', async () => { - const txHash = await abiGenDummy.nonPureMethod.validateAndSendTransactionAsync(); - const hexRegex = /^0x[a-fA-F0-9]+$/; - expect(txHash.match(hexRegex)).to.deep.equal([txHash]); - }); - }); - describe('event subscription', () => { const indexFilterValues = {}; const emptyCallback = () => {}; // tslint:disable-line:no-empty @@ -284,6 +276,13 @@ describe('AbiGenDummy Contract', () => { expect(decodedOutput, 'decoded output').to.be.deep.equal(output); }); }); + describe('awaitTransactionSuccessAsync', async () => { + it('should successfully call the non pure function', async () => { + expect( + abiGenDummy.nonPureMethod.awaitTransactionSuccessAsync({}, { pollingIntervalMs: 10, timeoutMs: 100 }), + ).to.be.fulfilled(''); + }); + }); }); describe('Lib dummy contract', () => { diff --git a/packages/asset-buyer/src/asset_buyer.ts b/packages/asset-buyer/src/asset_buyer.ts index 3dc0b96ea1..fd30833756 100644 --- a/packages/asset-buyer/src/asset_buyer.ts +++ b/packages/asset-buyer/src/asset_buyer.ts @@ -267,7 +267,7 @@ export class AssetBuyer { // if no ethAmount is provided, default to the worst ethAmount from buyQuote const value = ethAmount || worstCaseQuoteInfo.totalEthAmount; - const txHash = await this._contractWrappers.forwarder.marketBuyOrdersWithEth.validateAndSendTransactionAsync( + const txHash = await this._contractWrappers.forwarder.marketBuyOrdersWithEth.sendTransactionAsync( orders, assetBuyAmount, orders.map(o => o.signature), diff --git a/packages/asset-swapper/src/quote_consumers/exchange_swap_quote_consumer.ts b/packages/asset-swapper/src/quote_consumers/exchange_swap_quote_consumer.ts index 981513fcf3..a81c2a2cc5 100644 --- a/packages/asset-swapper/src/quote_consumers/exchange_swap_quote_consumer.ts +++ b/packages/asset-swapper/src/quote_consumers/exchange_swap_quote_consumer.ts @@ -144,7 +144,7 @@ export class ExchangeSwapQuoteConsumer implements SwapQuoteConsumerBase o.signature), @@ -156,7 +156,7 @@ export class ExchangeSwapQuoteConsumer implements SwapQuoteConsumerBase o.signature), diff --git a/packages/asset-swapper/src/quote_consumers/forwarder_swap_quote_consumer.ts b/packages/asset-swapper/src/quote_consumers/forwarder_swap_quote_consumer.ts index f90f30fd0c..f4553572df 100644 --- a/packages/asset-swapper/src/quote_consumers/forwarder_swap_quote_consumer.ts +++ b/packages/asset-swapper/src/quote_consumers/forwarder_swap_quote_consumer.ts @@ -197,7 +197,7 @@ export class ForwarderSwapQuoteConsumer implements SwapQuoteConsumerBase o.signature), @@ -211,7 +211,7 @@ export class ForwarderSwapQuoteConsumer implements SwapQuoteConsumerBase o.signature), formattedFeePercentage, diff --git a/packages/base-contract/CHANGELOG.json b/packages/base-contract/CHANGELOG.json index 1e11866ef6..c691b66589 100644 --- a/packages/base-contract/CHANGELOG.json +++ b/packages/base-contract/CHANGELOG.json @@ -1,4 +1,17 @@ [ + { + "version": "5.5.0-beta.1", + "changes": [ + { + "note": "Make `evmExecAsync` protected and rename to `_evmExecAsync`", + "pr": 2243 + }, + { + "note": "Remove duplicate types `IndexedFilterValues`, `DecodedLogEvent`, `EventCallback`", + "pr": 2243 + } + ] + }, { "version": "5.5.0-beta.0", "changes": [ diff --git a/packages/base-contract/src/index.ts b/packages/base-contract/src/index.ts index 2dc978569f..74b9f22c52 100644 --- a/packages/base-contract/src/index.ts +++ b/packages/base-contract/src/index.ts @@ -184,7 +184,7 @@ export class BaseContract { } return rawEncoded; } - public async evmExecAsync(input: Buffer): Promise { + protected async _evmExecAsync(input: Buffer): Promise { const addressBuf = Buffer.from(this.address.substr(2), 'hex'); // should only run once, the first time it is called if (this._evmIfExists === undefined) { diff --git a/packages/base-contract/src/subscription_manager.ts b/packages/base-contract/src/subscription_manager.ts index f6949d4f47..9f0bdd6cc2 100644 --- a/packages/base-contract/src/subscription_manager.ts +++ b/packages/base-contract/src/subscription_manager.ts @@ -13,7 +13,9 @@ import { import { Block, BlockAndLogStreamer, Log } from 'ethereumjs-blockstream'; import * as _ from 'lodash'; -import { EventCallback, IndexedFilterValues, SubscriptionErrors } from './types'; +import { EventCallback, IndexedFilterValues } from '@0x/types'; + +import { SubscriptionErrors } from './types'; import { filterUtils } from './utils/filter_utils'; const DEFAULT_BLOCK_POLLING_INTERVAL = 1000; @@ -80,7 +82,7 @@ export class SubscriptionManager; + this._filterCallbacks[filterToken] = callback as EventCallback; // tslint:disable-line:no-unnecessary-type-assertion return filterToken; } public async getLogsAsync( diff --git a/packages/base-contract/src/types.ts b/packages/base-contract/src/types.ts index 28048b7af1..5414dd2090 100644 --- a/packages/base-contract/src/types.ts +++ b/packages/base-contract/src/types.ts @@ -1,15 +1,6 @@ -import { ContractEventArg, DecodedLogArgs, LogEntryEvent, LogWithDecodedArgs } from 'ethereum-types'; +import { LogEntryEvent } from 'ethereum-types'; export type LogEvent = LogEntryEvent; -export interface DecodedLogEvent { - isRemoved: boolean; - log: LogWithDecodedArgs; -} - -export type EventCallback = ( - err: null | Error, - log?: DecodedLogEvent, -) => void; export interface ContractEvent { logIndex: number; @@ -27,7 +18,3 @@ export enum SubscriptionErrors { SubscriptionNotFound = 'SUBSCRIPTION_NOT_FOUND', SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT', } - -export interface IndexedFilterValues { - [index: string]: ContractEventArg; -} diff --git a/packages/contract-wrappers/src/index.ts b/packages/contract-wrappers/src/index.ts index 9da6d1ace8..96d46327cd 100644 --- a/packages/contract-wrappers/src/index.ts +++ b/packages/contract-wrappers/src/index.ts @@ -154,6 +154,8 @@ export { SignedZeroExTransaction, SimpleEvmOutput, SimpleEvmBytecodeOutput, + AwaitTransactionSuccessOpts, + SendTransactionOpts, EIP712DomainWithDefaultSchema, EventCallback, DecodedLogEvent, diff --git a/packages/contract-wrappers/src/types.ts b/packages/contract-wrappers/src/types.ts index 048e08981d..5ac052858c 100644 --- a/packages/contract-wrappers/src/types.ts +++ b/packages/contract-wrappers/src/types.ts @@ -40,6 +40,7 @@ export interface ContractWrappersConfig { blockPollingIntervalMs?: number; } +// TODO(xianny): remove after refactoring coordinator wrapper /** * gasPrice: Gas price in Wei to use for a transaction * gasLimit: The amount of gas to send with a transaction (in Gwei) @@ -51,6 +52,7 @@ export interface TransactionOpts { nonce?: number; } +// TODO(xianny): remove after refactoring coordinator wrapper /** * shouldValidate: Flag indicating whether the library should make attempts to validate a transaction before * broadcasting it. For example, order has a valid signature, maker has sufficient funds, etc. Default=true. diff --git a/packages/types/CHANGELOG.json b/packages/types/CHANGELOG.json index b6aca3e427..5c9a0722f3 100644 --- a/packages/types/CHANGELOG.json +++ b/packages/types/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "2.5.0-beta.1", + "changes": [ + { + "note": "Add `SendTransactionOpts` and `AwaitTransactionSuccessOpts` types for contract wrappers", + "pr": 2243 + } + ] + }, { "version": "2.5.0-beta.0", "changes": [ diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 64fa91da2f..ceac35918c 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -670,6 +670,18 @@ export interface Type { tupleElements?: Type[]; } +/** + * * shouldValidate: Flag indicating whether the library should make attempts to validate a transaction before + * broadcasting it. For example, order has a valid signature, maker has sufficient funds, etc. Default=true. + * * pollingIntervalMs: Used with `awaitTransactionSuccessAsync` to determine polling interval in milliseconds + * * timeoutMs: Used with `awaitTransactionSuccessAsync` to determine timeout in milliseconds + */ +export interface SendTransactionOpts { + shouldValidate?: boolean; + pollingIntervalMs?: number; + timeoutMs?: number; +} + export interface ElementType { name: string; typeDocType: TypeDocTypes; @@ -742,27 +754,6 @@ export interface Stats { orderCount: number; } -export interface SimpleContractArtifact { - schemaVersion: string; - contractName: string; - compilerOutput: SimpleStandardContractOutput; - networks: ContractNetworks; -} - -export interface SimpleStandardContractOutput { - abi: ContractAbi; - evm: SimpleEvmOutput; - devdoc?: DevdocOutput; -} - -export interface SimpleEvmOutput { - bytecode: SimpleEvmBytecodeOutput; -} - -export interface SimpleEvmBytecodeOutput { - object: string; -} - export interface DutchAuctionDetails { beginTimeSeconds: BigNumber; endTimeSeconds: BigNumber; @@ -862,3 +853,48 @@ export type EventCallback = ( export interface IndexedFilterValues { [index: string]: ContractEventArg; } + +/* Begin types for @0x/abi-gen-wrappers + * Allow these types to be imported when needed instead of having to import + * the whole package, which is large + */ + +/** + * Used with `sendTransactionAsync` + * * shouldValidate: Flag indicating whether the library should make attempts to validate a transaction before + * broadcasting it. For example, order has a valid signature, maker has sufficient funds, etc. Default=true. + */ +export interface SendTransactionOpts { + shouldValidate?: boolean; +} + +/** + * Used with `awaitTransactionSuccessAsync` + * * pollingIntervalMs: Determine polling intervals in milliseconds + * * timeoutMs: Determines timeout in milliseconds + */ +export interface AwaitTransactionSuccessOpts extends SendTransactionOpts { + pollingIntervalMs?: number; + timeoutMs?: number; +} + +export interface SimpleContractArtifact { + schemaVersion: string; + contractName: string; + compilerOutput: SimpleStandardContractOutput; + networks: ContractNetworks; +} + +export interface SimpleStandardContractOutput { + abi: ContractAbi; + evm: SimpleEvmOutput; + devdoc?: DevdocOutput; +} + +export interface SimpleEvmOutput { + bytecode: SimpleEvmBytecodeOutput; +} + +export interface SimpleEvmBytecodeOutput { + object: string; +} From e43f2d39bf7c22aad02544b87ea7ee78ed44682e Mon Sep 17 00:00:00 2001 From: fabioberger Date: Wed, 16 Oct 2019 22:39:09 +0900 Subject: [PATCH 83/87] Add ERC1155Mintable to artifacts and abi-gen-wrappers packages --- packages/abi-gen-wrappers/package.json | 2 +- .../generated-wrappers/erc1155_mintable.ts | 3508 +++++++++++++++++ .../artifacts/ERC1155Mintable.json | 384 ++ packages/contract-artifacts/src/index.ts | 2 + packages/contract-artifacts/tsconfig.json | 1 + 5 files changed, 3896 insertions(+), 1 deletion(-) create mode 100644 packages/abi-gen-wrappers/src/generated-wrappers/erc1155_mintable.ts create mode 100644 packages/contract-artifacts/artifacts/ERC1155Mintable.json diff --git a/packages/abi-gen-wrappers/package.json b/packages/abi-gen-wrappers/package.json index 74d41fee72..7c543f252e 100644 --- a/packages/abi-gen-wrappers/package.json +++ b/packages/abi-gen-wrappers/package.json @@ -21,7 +21,7 @@ "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --output src/generated-wrappers --backend ethers" }, "config": { - "abis": "../contract-artifacts/artifacts/@(AssetProxyOwner|DevUtils|DutchAuction|DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC20Token|ERC721Proxy|ERC721Token|Exchange|Forwarder|IAssetProxy|IValidator|IWallet|MultiAssetProxy|OrderValidator|WETH9|ZRXToken|Coordinator|CoordinatorRegistry|EthBalanceChecker|ERC1155Proxy|StaticCallProxy).json" + "abis": "../contract-artifacts/artifacts/@(AssetProxyOwner|DevUtils|DutchAuction|DummyERC20Token|DummyERC721Token|ERC1155Mintable|ERC20Proxy|ERC20Token|ERC721Proxy|ERC721Token|Exchange|Forwarder|IAssetProxy|IValidator|IWallet|MultiAssetProxy|OrderValidator|WETH9|ZRXToken|Coordinator|CoordinatorRegistry|EthBalanceChecker|ERC1155Proxy|StaticCallProxy).json" }, "repository": { "type": "git", diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/erc1155_mintable.ts b/packages/abi-gen-wrappers/src/generated-wrappers/erc1155_mintable.ts new file mode 100644 index 0000000000..54410c2387 --- /dev/null +++ b/packages/abi-gen-wrappers/src/generated-wrappers/erc1155_mintable.ts @@ -0,0 +1,3508 @@ +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:whitespace no-unbound-method no-trailing-whitespace +// tslint:disable:no-unused-variable +import { BaseContract, SubscriptionManager, PromiseWithTransactionHash } from '@0x/base-contract'; +import { schemas } from '@0x/json-schemas'; +import { + BlockParam, + BlockParamLiteral, + BlockRange, + CallData, + ContractAbi, + ContractArtifact, + DecodedLogArgs, + LogWithDecodedArgs, + MethodAbi, + TransactionReceiptWithDecodedLogs, + TxData, + TxDataPayable, + SupportedProvider, +} from 'ethereum-types'; +import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; +import { SimpleContractArtifact, EventCallback, IndexedFilterValues } from '@0x/types'; +import { Web3Wrapper } from '@0x/web3-wrapper'; +import { assert } from '@0x/assert'; +import * as ethers from 'ethers'; +// tslint:enable:no-unused-variable + +export type ERC1155MintableEventArgs = + | ERC1155MintableApprovalForAllEventArgs + | ERC1155MintableTransferBatchEventArgs + | ERC1155MintableTransferSingleEventArgs + | ERC1155MintableURIEventArgs; + +export enum ERC1155MintableEvents { + ApprovalForAll = 'ApprovalForAll', + TransferBatch = 'TransferBatch', + TransferSingle = 'TransferSingle', + URI = 'URI', +} + +export interface ERC1155MintableApprovalForAllEventArgs extends DecodedLogArgs { + owner: string; + operator: string; + approved: boolean; +} + +export interface ERC1155MintableTransferBatchEventArgs extends DecodedLogArgs { + operator: string; + from: string; + to: string; + ids: BigNumber[]; + values: BigNumber[]; +} + +export interface ERC1155MintableTransferSingleEventArgs extends DecodedLogArgs { + operator: string; + from: string; + to: string; + id: BigNumber; + value: BigNumber; +} + +export interface ERC1155MintableURIEventArgs extends DecodedLogArgs { + value: string; + id: BigNumber; +} + +/* istanbul ignore next */ +// tslint:disable:no-parameter-reassignment +// tslint:disable-next-line:class-name +export class ERC1155MintableContract extends BaseContract { + public static deployedBytecode = + '0x608060405234801561001057600080fd5b50600436106101765760003560e01c80639f4b286a116100d8578063e0a5c9491161008c578063f242432a11610066578063f242432a146107bb578063f94190881461085d578063fc67bf1c146108d457610176565b8063e0a5c94914610726578063e44591f014610763578063e985e9c51461078057610176565b8063adebf6f2116100bd578063adebf6f21461067a578063cc10e40114610697578063cd53d08e1461070957610176565b80639f4b286a146105c8578063a22cb4651461063f57610176565b80636352211e1161012f5780637269a327116101145780637269a327146104c557806378b27221146104e25780639cca1c64146105ab57610176565b80636352211e146104625780636f969c2d146104a857610176565b80632eb2c2d6116101605780632eb2c2d6146101e35780634e1273f41461031f5780635e81b9581461043157610176565b8062fdd58e1461017b57806308d7d469146101c6575b600080fd5b6101b46004803603604081101561019157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356108dc565b60408051918252519081900360200190f35b6101b4600480360360208110156101dc57600080fd5b5035610966565b61031d600480360360a08110156101f957600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169181019060608101604082013564010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184602083028401116401000000008311171561026e57600080fd5b91939092909160208101903564010000000081111561028c57600080fd5b82018360208201111561029e57600080fd5b803590602001918460208302840111640100000000831117156102c057600080fd5b9193909290916020810190356401000000008111156102de57600080fd5b8201836020820111156102f057600080fd5b8035906020019184600183028401116401000000008311171561031257600080fd5b509092509050610978565b005b6103e16004803603604081101561033557600080fd5b81019060208101813564010000000081111561035057600080fd5b82018360208201111561036257600080fd5b8035906020019184602083028401116401000000008311171561038457600080fd5b9193909290916020810190356401000000008111156103a257600080fd5b8201836020820111156103b457600080fd5b803590602001918460208302840111640100000000831117156103d657600080fd5b509092509050611192565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561041d578181015183820152602001610405565b505050509050019250505060405180910390f35b61044e6004803603602081101561044757600080fd5b5035611357565b604080519115158252519081900360200190f35b61047f6004803603602081101561047857600080fd5b503561139d565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6101b4600480360360208110156104be57600080fd5b50356113c5565b61044e600480360360208110156104db57600080fd5b50356113ea565b61031d600480360360608110156104f857600080fd5b8135919081019060408101602082013564010000000081111561051a57600080fd5b82018360208201111561052c57600080fd5b8035906020019184602083028401116401000000008311171561054e57600080fd5b91939092909160208101903564010000000081111561056c57600080fd5b82018360208201111561057e57600080fd5b803590602001918460208302840111640100000000831117156105a057600080fd5b50909250905061142f565b6101b4600480360360208110156105c157600080fd5b5035611760565b61031d600480360360408110156105de57600080fd5b8135919081019060408101602082013564010000000081111561060057600080fd5b82018360208201111561061257600080fd5b8035906020019184600183028401116401000000008311171561063457600080fd5b509092509050611775565b61031d6004803603604081101561065557600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001351515611875565b61044e6004803603602081101561069057600080fd5b503561190e565b6101b4600480360360408110156106ad57600080fd5b8101906020810181356401000000008111156106c857600080fd5b8201836020820111156106da57600080fd5b803590602001918460018302840111640100000000831117156106fc57600080fd5b9193509150351515611934565b61047f6004803603602081101561071f57600080fd5b5035611a6d565b61072e611a95565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b61044e6004803603602081101561077957600080fd5b5035611ab9565b61044e6004803603604081101561079657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516611ae1565b61031d600480360360a08110156107d157600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359181019060a08101608082013564010000000081111561081e57600080fd5b82018360208201111561083057600080fd5b8035906020019184600183028401116401000000008311171561085257600080fd5b509092509050611b1c565b61031d6004803603604081101561087357600080fd5b8135919081019060408101602082013564010000000081111561089557600080fd5b8201836020820111156108a757600080fd5b803590602001918460208302840111640100000000831117156108c957600080fd5b5090925090506120fb565b61072e61242b565b60006108e782611357565b1561092e5760008281526020819052604090205473ffffffffffffffffffffffffffffffffffffffff848116911614610921576000610924565b60015b60ff169050610960565b50600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020545b92915050565b60056020526000908152604090205481565b73ffffffffffffffffffffffffffffffffffffffff87166109fa57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f43414e4e4f545f5452414e534645525f544f5f414444524553535f5a45524f00604482015290519081900360640190fd5b848314610a6857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f544f4b454e5f414e445f56414c5545535f4c454e4754485f4d49534d41544348604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8816331480610ac1575073ffffffffffffffffffffffffffffffffffffffff8816600090815260026020908152604080832033845290915290205460ff1615156001145b610b2c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f494e53554646494349454e545f414c4c4f57414e434500000000000000000000604482015290519081900360640190fd5b60005b85811015610deb576000878783818110610b4557fe5b9050602002013590506000868684818110610b5c57fe5b905060200201359050610b6e82611ab9565b15610cc85780600114610be257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f414d4f554e545f455155414c5f544f5f4f4e455f524551554952454400000000604482015290519081900360640190fd5b60008281526020819052604090205473ffffffffffffffffffffffffffffffffffffffff8c8116911614610c7757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4e46545f4e4f545f4f574e45445f42595f46524f4d5f41444452455353000000604482015290519081900360640190fd5b600082815260208190526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8c16179055610de1565b600082815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8f168452909152902054610d02908261244f565b6001600084815260200190815260200160002060008d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610db06001600084815260200190815260200160002060008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482612473565b600083815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8f1684529091529020555b5050600101610b2f565b508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb898989896040518080602001806020018381038352878782818152602001925060200280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169091018481038352858152602090810191508690860280828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039850909650505050505050a4610f1f8773ffffffffffffffffffffffffffffffffffffffff1661248f565b156111885760008773ffffffffffffffffffffffffffffffffffffffff1663bc197c81338b8a8a8a8a8a8a6040518963ffffffff1660e01b8152600401808973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018060200184810384528a8a82818152602001925060200280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169091018581038452888152602090810191508990890280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910185810383528681526020019050868680828437600081840152601f19601f8201169050808301925050509b505050505050505050505050602060405180830381600087803b1580156110a857600080fd5b505af11580156110bc573d6000803e3d6000fd5b505050506040513d60208110156110d257600080fd5b505190507fffffffff0000000000000000000000000000000000000000000000000000000081167fbc197c81000000000000000000000000000000000000000000000000000000001461118657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4241445f52454345495645525f52455455524e5f56414c554500000000000000604482015290519081900360640190fd5b505b5050505050505050565b60608382146111ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061256a6024913960400191505060405180910390fd5b604080518581526020808702820101909152848015611215578160200160208202803883390190505b50905060005b8481101561134e57600084848381811061123157fe5b90506020020135905061124381611357565b156112b95786868381811061125457fe5b600084815260208181526040909120549102929092013573ffffffffffffffffffffffffffffffffffffffff9081169216919091149050611296576000611299565b60015b60ff168383815181106112a857fe5b602002602001018181525050611345565b6000818152600160205260408120908888858181106112d457fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205483838151811061133857fe5b6020026020010181815250505b5060010161121b565b50949350505050565b60007f80000000000000000000000000000000000000000000000000000000000000008083161480156109605750506fffffffffffffffffffffffffffffffff16151590565b60009081526020819052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000001690565b60007f80000000000000000000000000000000000000000000000000000000000000008083161480156109605750506fffffffffffffffffffffffffffffffff161590565b600085815260046020526040902054859073ffffffffffffffffffffffffffffffffffffffff16331461146157600080fd5b61146a8661190e565b6114bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d81526020018061258e602d913960400191505060405180910390fd5b60005b848110156117575760008686838181106114d857fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff169050600085858481811061150557fe5b60008c815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8916845282529091205491029290920135925061154a91839150612473565b60008a815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083528184209490945580518d8152918201859052805133927fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6292908290030190a46115d68273ffffffffffffffffffffffffffffffffffffffff1661248f565b1561174d57604080517ff23a6e6100000000000000000000000000000000000000000000000000000000815233600482018190526024820152604481018b90526064810183905260a06084820152600060a48201819052915173ffffffffffffffffffffffffffffffffffffffff85169163f23a6e619160e480830192602092919082900301818787803b15801561166d57600080fd5b505af1158015611681573d6000803e3d6000fd5b505050506040513d602081101561169757600080fd5b505190507fffffffff0000000000000000000000000000000000000000000000000000000081167ff23a6e61000000000000000000000000000000000000000000000000000000001461174b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4241445f52454345495645525f52455455524e5f56414c554500000000000000604482015290519081900360640190fd5b505b50506001016114c2565b50505050505050565b6fffffffffffffffffffffffffffffffff1690565b600083815260046020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163390811790915581518781529283018490528151849391927fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62928290030190a4801561187057827f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b838360405180806020018281038252848482818152602001925080828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039550909350505050a25b505050565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b7f8000000000000000000000000000000000000000000000000000000000000000161590565b600380546001019081905560801b811561196b577f8000000000000000000000000000000000000000000000000000000000000000175b600081815260046020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163390811790915581518581529283018490528151849391927fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62928290030190a48215611a6657807f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b858560405180806020018281038252848482818152602001925080828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039550909350505050a25b9392505050565b60046020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b7ff23a6e610000000000000000000000000000000000000000000000000000000081565b7f80000000000000000000000000000000000000000000000000000000000000009081161490565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260026020908152604080832093909416825291909152205460ff1690565b73ffffffffffffffffffffffffffffffffffffffff8516611b9e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f43414e4e4f545f5452414e534645525f544f5f414444524553535f5a45524f00604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8616331480611bf7575073ffffffffffffffffffffffffffffffffffffffff8616600090815260026020908152604080832033845290915290205460ff1615156001145b611c6257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f494e53554646494349454e545f414c4c4f57414e434500000000000000000000604482015290519081900360640190fd5b611c6b84611ab9565b15611dc55782600114611cdf57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f414d4f554e545f455155414c5f544f5f4f4e455f524551554952454400000000604482015290519081900360640190fd5b60008481526020819052604090205473ffffffffffffffffffffffffffffffffffffffff878116911614611d7457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4e46545f4e4f545f4f574e45445f42595f46524f4d5f41444452455353000000604482015290519081900360640190fd5b600084815260208190526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8716179055611e74565b600084815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8a168452909152902054611dff908461244f565b600085815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8b81168552925280832093909355871681522054611e439084612473565b600085815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8a1684529091529020555b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628787604051808381526020018281526020019250505060405180910390a4611f178573ffffffffffffffffffffffffffffffffffffffff1661248f565b156120f35760008573ffffffffffffffffffffffffffffffffffffffff1663f23a6e613389888888886040518763ffffffff1660e01b8152600401808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050975050505050505050602060405180830381600087803b15801561201557600080fd5b505af1158015612029573d6000803e3d6000fd5b505050506040513d602081101561203f57600080fd5b505190507fffffffff0000000000000000000000000000000000000000000000000000000081167ff23a6e61000000000000000000000000000000000000000000000000000000001461175757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4241445f52454345495645525f52455455524e5f56414c554500000000000000604482015290519081900360640190fd5b505050505050565b600083815260046020526040902054839073ffffffffffffffffffffffffffffffffffffffff16331461212d57600080fd5b61213684611ab9565b61218b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d81526020018061253d602d913960400191505060405180910390fd5b600084815260056020526040812054600101905b838110156123f75760008585838181106121b557fe5b8486018a176000818152602081815260408083208054958302979097013573ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffff00000000000000000000000000000000000000009095168517909655855183815260019181019190915285519396509194869450909233927fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6292908290030190a46122768273ffffffffffffffffffffffffffffffffffffffff1661248f565b156123ed57604080517ff23a6e6100000000000000000000000000000000000000000000000000000000815233600482018190526024820152604481018390526001606482015260a06084820152600060a48201819052915173ffffffffffffffffffffffffffffffffffffffff85169163f23a6e619160e480830192602092919082900301818787803b15801561230d57600080fd5b505af1158015612321573d6000803e3d6000fd5b505050506040513d602081101561233757600080fd5b505190507fffffffff0000000000000000000000000000000000000000000000000000000081167ff23a6e6100000000000000000000000000000000000000000000000000000000146123eb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4241445f52454345495645525f52455455524e5f56414c554500000000000000604482015290519081900360640190fd5b505b505060010161219f565b50600085815260056020526040902054612412908490612473565b6000958652600560205260409095209490945550505050565b7fbc197c810000000000000000000000000000000000000000000000000000000081565b60008282111561246d5761246d61246860028585612495565b612534565b50900390565b600082820183811015611a6657611a6661246860008686612495565b3b151590565b606063e946c1bb60e01b848484604051602401808460038111156124b557fe5b60ff1681526020018381526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090509392505050565b805160208201fdfe54524945445f544f5f4d494e545f4e4f4e5f46554e4749424c455f464f525f46554e4749424c455f544f4b454e4f574e4552535f414e445f4944535f4d5553545f484156455f53414d455f4c454e47544854524945445f544f5f4d494e545f46554e4749424c455f464f525f4e4f4e5f46554e4749424c455f544f4b454ea265627a7a723158205af7d187cbffb255b374d24e5838a04f6b3a3245622025907396b2a61f9d93da64736f6c634300050c0032'; + public ERC1155_BATCH_RECEIVED = { + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + */ + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('ERC1155_BATCH_RECEIVED()', []); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + let rawCallResult; + try { + rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('ERC1155_BATCH_RECEIVED()'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(): string { + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('ERC1155_BATCH_RECEIVED()', []); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): void { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('ERC1155_BATCH_RECEIVED()'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): string { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('ERC1155_BATCH_RECEIVED()'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + public ERC1155_RECEIVED = { + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + */ + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('ERC1155_RECEIVED()', []); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + let rawCallResult; + try { + rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('ERC1155_RECEIVED()'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(): string { + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('ERC1155_RECEIVED()', []); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): void { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('ERC1155_RECEIVED()'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): string { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('ERC1155_RECEIVED()'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + public balanceOf = { + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + * @param owner The address of the token holder + * @param id ID of the Token + * @returns The _owner's balance of the Token type requested + */ + async callAsync( + owner: string, + id: BigNumber, + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise { + assert.isString('owner', owner); + assert.isBigNumber('id', id); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('balanceOf(address,uint256)', [owner.toLowerCase(), id]); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + let rawCallResult; + try { + rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('balanceOf(address,uint256)'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @param owner The address of the token holder + * @param id ID of the Token + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(owner: string, id: BigNumber): string { + assert.isString('owner', owner); + assert.isBigNumber('id', id); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('balanceOf(address,uint256)', [ + owner.toLowerCase(), + id, + ]); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): string { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('balanceOf(address,uint256)'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): BigNumber { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('balanceOf(address,uint256)'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + public balanceOfBatch = { + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + * @param owners The addresses of the token holders + * @param ids ID of the Tokens + * @returns The _owner's balance of the Token types requested + */ + async callAsync( + owners: string[], + ids: BigNumber[], + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise { + assert.isArray('owners', owners); + assert.isArray('ids', ids); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('balanceOfBatch(address[],uint256[])', [owners, ids]); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + let rawCallResult; + try { + rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('balanceOfBatch(address[],uint256[])'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @param owners The addresses of the token holders + * @param ids ID of the Tokens + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(owners: string[], ids: BigNumber[]): string { + assert.isArray('owners', owners); + assert.isArray('ids', ids); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('balanceOfBatch(address[],uint256[])', [ + owners, + ids, + ]); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): string[] { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('balanceOfBatch(address[],uint256[])'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): BigNumber[] { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('balanceOfBatch(address[],uint256[])'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + /** + * creates a new token + */ + public create = { + /** + * Sends an Ethereum transaction executing this method with the supplied parameters. This is a read/write + * Ethereum operation and will cost gas. + * @param uri URI of token + * @param isNF is non-fungible token + * @param txData Additional data for transaction + * @returns The hash of the transaction + */ + async sendTransactionAsync(uri: string, isNF: boolean, txData?: Partial | undefined): Promise { + assert.isString('uri', uri); + assert.isBoolean('isNF', isNF); + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('create(string,bool)', [uri, isNF]); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); + return txHash; + }, + /** + * Sends an Ethereum transaction and waits until the transaction has been successfully mined without reverting. + * If the transaction was mined, but reverted, an error is thrown. + * @param uri URI of token + * @param isNF is non-fungible token + * @param txData Additional data for transaction + * @param pollingIntervalMs Interval at which to poll for success + * @returns A promise that resolves when the transaction is successful + */ + awaitTransactionSuccessAsync( + uri: string, + isNF: boolean, + txData?: Partial, + pollingIntervalMs?: number, + timeoutMs?: number, + ): PromiseWithTransactionHash { + assert.isString('uri', uri); + assert.isBoolean('isNF', isNF); + const self = (this as any) as ERC1155MintableContract; + const txHashPromise = self.create.sendTransactionAsync(uri, isNF, txData); + return new PromiseWithTransactionHash( + txHashPromise, + (async (): Promise => { + // When the transaction hash resolves, wait for it to be mined. + return self._web3Wrapper.awaitTransactionSuccessAsync( + await txHashPromise, + pollingIntervalMs, + timeoutMs, + ); + })(), + ); + }, + /** + * Estimates the gas cost of sending an Ethereum transaction calling this method with these arguments. + * @param uri URI of token + * @param isNF is non-fungible token + * @param txData Additional data for transaction + * @returns The hash of the transaction + */ + async estimateGasAsync(uri: string, isNF: boolean, txData?: Partial | undefined): Promise { + assert.isString('uri', uri); + assert.isBoolean('isNF', isNF); + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('create(string,bool)', [uri, isNF]); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); + return gas; + }, + async validateAndSendTransactionAsync( + uri: string, + isNF: boolean, + txData?: Partial | undefined, + ): Promise { + await (this as any).create.callAsync(uri, isNF, txData); + const txHash = await (this as any).create.sendTransactionAsync(uri, isNF, txData); + return txHash; + }, + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + * @param uri URI of token + * @param isNF is non-fungible token + * @returns type_ of token (a unique identifier) + */ + async callAsync( + uri: string, + isNF: boolean, + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise { + assert.isString('uri', uri); + assert.isBoolean('isNF', isNF); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('create(string,bool)', [uri, isNF]); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + let rawCallResult; + try { + rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('create(string,bool)'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @param uri URI of token + * @param isNF is non-fungible token + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(uri: string, isNF: boolean): string { + assert.isString('uri', uri); + assert.isBoolean('isNF', isNF); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('create(string,bool)', [uri, isNF]); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): string { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('create(string,bool)'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): BigNumber { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('create(string,bool)'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + /** + * creates a new token + */ + public createWithType = { + /** + * Sends an Ethereum transaction executing this method with the supplied parameters. This is a read/write + * Ethereum operation and will cost gas. + * @param type_ of token + * @param uri URI of token + * @param txData Additional data for transaction + * @returns The hash of the transaction + */ + async sendTransactionAsync( + type_: BigNumber, + uri: string, + txData?: Partial | undefined, + ): Promise { + assert.isBigNumber('type_', type_); + assert.isString('uri', uri); + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('createWithType(uint256,string)', [type_, uri]); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); + return txHash; + }, + /** + * Sends an Ethereum transaction and waits until the transaction has been successfully mined without reverting. + * If the transaction was mined, but reverted, an error is thrown. + * @param type_ of token + * @param uri URI of token + * @param txData Additional data for transaction + * @param pollingIntervalMs Interval at which to poll for success + * @returns A promise that resolves when the transaction is successful + */ + awaitTransactionSuccessAsync( + type_: BigNumber, + uri: string, + txData?: Partial, + pollingIntervalMs?: number, + timeoutMs?: number, + ): PromiseWithTransactionHash { + assert.isBigNumber('type_', type_); + assert.isString('uri', uri); + const self = (this as any) as ERC1155MintableContract; + const txHashPromise = self.createWithType.sendTransactionAsync(type_, uri, txData); + return new PromiseWithTransactionHash( + txHashPromise, + (async (): Promise => { + // When the transaction hash resolves, wait for it to be mined. + return self._web3Wrapper.awaitTransactionSuccessAsync( + await txHashPromise, + pollingIntervalMs, + timeoutMs, + ); + })(), + ); + }, + /** + * Estimates the gas cost of sending an Ethereum transaction calling this method with these arguments. + * @param type_ of token + * @param uri URI of token + * @param txData Additional data for transaction + * @returns The hash of the transaction + */ + async estimateGasAsync(type_: BigNumber, uri: string, txData?: Partial | undefined): Promise { + assert.isBigNumber('type_', type_); + assert.isString('uri', uri); + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('createWithType(uint256,string)', [type_, uri]); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); + return gas; + }, + async validateAndSendTransactionAsync( + type_: BigNumber, + uri: string, + txData?: Partial | undefined, + ): Promise { + await (this as any).createWithType.callAsync(type_, uri, txData); + const txHash = await (this as any).createWithType.sendTransactionAsync(type_, uri, txData); + return txHash; + }, + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + * @param type_ of token + * @param uri URI of token + */ + async callAsync( + type_: BigNumber, + uri: string, + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise { + assert.isBigNumber('type_', type_); + assert.isString('uri', uri); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('createWithType(uint256,string)', [type_, uri]); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + let rawCallResult; + try { + rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('createWithType(uint256,string)'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @param type_ of token + * @param uri URI of token + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(type_: BigNumber, uri: string): string { + assert.isBigNumber('type_', type_); + assert.isString('uri', uri); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('createWithType(uint256,string)', [ + type_, + uri, + ]); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): [BigNumber, string] { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('createWithType(uint256,string)'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode<[BigNumber, string]>(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): void { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('createWithType(uint256,string)'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + public creators = { + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + */ + async callAsync( + index_0: BigNumber, + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise { + assert.isBigNumber('index_0', index_0); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('creators(uint256)', [index_0]); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + let rawCallResult; + try { + rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('creators(uint256)'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(index_0: BigNumber): string { + assert.isBigNumber('index_0', index_0); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('creators(uint256)', [index_0]); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): BigNumber { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('creators(uint256)'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): string { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('creators(uint256)'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + /** + * Returns base type of non-fungible token + */ + public getNonFungibleBaseType = { + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + */ + async callAsync( + id: BigNumber, + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise { + assert.isBigNumber('id', id); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('getNonFungibleBaseType(uint256)', [id]); + const encodedDataBytes = Buffer.from(encodedData.substr(2), 'hex'); + + let rawCallResult; + try { + rawCallResult = await self.evmExecAsync(encodedDataBytes); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + + const abiEncoder = self._lookupAbiEncoder('getNonFungibleBaseType(uint256)'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(id: BigNumber): string { + assert.isBigNumber('id', id); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('getNonFungibleBaseType(uint256)', [id]); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): BigNumber { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('getNonFungibleBaseType(uint256)'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): BigNumber { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('getNonFungibleBaseType(uint256)'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + /** + * Returns index of non-fungible token + */ + public getNonFungibleIndex = { + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + */ + async callAsync( + id: BigNumber, + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise { + assert.isBigNumber('id', id); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('getNonFungibleIndex(uint256)', [id]); + const encodedDataBytes = Buffer.from(encodedData.substr(2), 'hex'); + + let rawCallResult; + try { + rawCallResult = await self.evmExecAsync(encodedDataBytes); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + + const abiEncoder = self._lookupAbiEncoder('getNonFungibleIndex(uint256)'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(id: BigNumber): string { + assert.isBigNumber('id', id); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('getNonFungibleIndex(uint256)', [id]); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): BigNumber { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('getNonFungibleIndex(uint256)'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): BigNumber { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('getNonFungibleIndex(uint256)'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + public isApprovedForAll = { + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + * @param owner The owner of the Tokens + * @param operator Address of authorized operator + * @returns True if the operator is approved, false if not + */ + async callAsync( + owner: string, + operator: string, + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise { + assert.isString('owner', owner); + assert.isString('operator', operator); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('isApprovedForAll(address,address)', [ + owner.toLowerCase(), + operator.toLowerCase(), + ]); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + let rawCallResult; + try { + rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('isApprovedForAll(address,address)'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @param owner The owner of the Tokens + * @param operator Address of authorized operator + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(owner: string, operator: string): string { + assert.isString('owner', owner); + assert.isString('operator', operator); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('isApprovedForAll(address,address)', [ + owner.toLowerCase(), + operator.toLowerCase(), + ]); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): string { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('isApprovedForAll(address,address)'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): boolean { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('isApprovedForAll(address,address)'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + /** + * Returns true if token is fungible + */ + public isFungible = { + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + */ + async callAsync(id: BigNumber, callData: Partial = {}, defaultBlock?: BlockParam): Promise { + assert.isBigNumber('id', id); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('isFungible(uint256)', [id]); + const encodedDataBytes = Buffer.from(encodedData.substr(2), 'hex'); + + let rawCallResult; + try { + rawCallResult = await self.evmExecAsync(encodedDataBytes); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + + const abiEncoder = self._lookupAbiEncoder('isFungible(uint256)'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(id: BigNumber): string { + assert.isBigNumber('id', id); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('isFungible(uint256)', [id]); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): BigNumber { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('isFungible(uint256)'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): boolean { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('isFungible(uint256)'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + /** + * Returns true if token is non-fungible + */ + public isNonFungible = { + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + */ + async callAsync(id: BigNumber, callData: Partial = {}, defaultBlock?: BlockParam): Promise { + assert.isBigNumber('id', id); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('isNonFungible(uint256)', [id]); + const encodedDataBytes = Buffer.from(encodedData.substr(2), 'hex'); + + let rawCallResult; + try { + rawCallResult = await self.evmExecAsync(encodedDataBytes); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + + const abiEncoder = self._lookupAbiEncoder('isNonFungible(uint256)'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(id: BigNumber): string { + assert.isBigNumber('id', id); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('isNonFungible(uint256)', [id]); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): BigNumber { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('isNonFungible(uint256)'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): boolean { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('isNonFungible(uint256)'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + /** + * Returns true if input is base-type of a non-fungible token + */ + public isNonFungibleBaseType = { + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + */ + async callAsync(id: BigNumber, callData: Partial = {}, defaultBlock?: BlockParam): Promise { + assert.isBigNumber('id', id); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('isNonFungibleBaseType(uint256)', [id]); + const encodedDataBytes = Buffer.from(encodedData.substr(2), 'hex'); + + let rawCallResult; + try { + rawCallResult = await self.evmExecAsync(encodedDataBytes); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + + const abiEncoder = self._lookupAbiEncoder('isNonFungibleBaseType(uint256)'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(id: BigNumber): string { + assert.isBigNumber('id', id); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('isNonFungibleBaseType(uint256)', [id]); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): BigNumber { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('isNonFungibleBaseType(uint256)'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): boolean { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('isNonFungibleBaseType(uint256)'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + /** + * Returns true if input is a non-fungible token + */ + public isNonFungibleItem = { + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + */ + async callAsync(id: BigNumber, callData: Partial = {}, defaultBlock?: BlockParam): Promise { + assert.isBigNumber('id', id); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('isNonFungibleItem(uint256)', [id]); + const encodedDataBytes = Buffer.from(encodedData.substr(2), 'hex'); + + let rawCallResult; + try { + rawCallResult = await self.evmExecAsync(encodedDataBytes); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + + const abiEncoder = self._lookupAbiEncoder('isNonFungibleItem(uint256)'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(id: BigNumber): string { + assert.isBigNumber('id', id); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('isNonFungibleItem(uint256)', [id]); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): BigNumber { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('isNonFungibleItem(uint256)'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): boolean { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('isNonFungibleItem(uint256)'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + public maxIndex = { + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + */ + async callAsync( + index_0: BigNumber, + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise { + assert.isBigNumber('index_0', index_0); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('maxIndex(uint256)', [index_0]); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + let rawCallResult; + try { + rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('maxIndex(uint256)'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(index_0: BigNumber): string { + assert.isBigNumber('index_0', index_0); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('maxIndex(uint256)', [index_0]); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): BigNumber { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('maxIndex(uint256)'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): BigNumber { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('maxIndex(uint256)'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + /** + * mints fungible tokens + */ + public mintFungible = { + /** + * Sends an Ethereum transaction executing this method with the supplied parameters. This is a read/write + * Ethereum operation and will cost gas. + * @param id token type + * @param to beneficiaries of minted tokens + * @param quantities amounts of minted tokens + * @param txData Additional data for transaction + * @returns The hash of the transaction + */ + async sendTransactionAsync( + id: BigNumber, + to: string[], + quantities: BigNumber[], + txData?: Partial | undefined, + ): Promise { + assert.isBigNumber('id', id); + assert.isArray('to', to); + assert.isArray('quantities', quantities); + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('mintFungible(uint256,address[],uint256[])', [ + id, + to, + quantities, + ]); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); + return txHash; + }, + /** + * Sends an Ethereum transaction and waits until the transaction has been successfully mined without reverting. + * If the transaction was mined, but reverted, an error is thrown. + * @param id token type + * @param to beneficiaries of minted tokens + * @param quantities amounts of minted tokens + * @param txData Additional data for transaction + * @param pollingIntervalMs Interval at which to poll for success + * @returns A promise that resolves when the transaction is successful + */ + awaitTransactionSuccessAsync( + id: BigNumber, + to: string[], + quantities: BigNumber[], + txData?: Partial, + pollingIntervalMs?: number, + timeoutMs?: number, + ): PromiseWithTransactionHash { + assert.isBigNumber('id', id); + assert.isArray('to', to); + assert.isArray('quantities', quantities); + const self = (this as any) as ERC1155MintableContract; + const txHashPromise = self.mintFungible.sendTransactionAsync(id, to, quantities, txData); + return new PromiseWithTransactionHash( + txHashPromise, + (async (): Promise => { + // When the transaction hash resolves, wait for it to be mined. + return self._web3Wrapper.awaitTransactionSuccessAsync( + await txHashPromise, + pollingIntervalMs, + timeoutMs, + ); + })(), + ); + }, + /** + * Estimates the gas cost of sending an Ethereum transaction calling this method with these arguments. + * @param id token type + * @param to beneficiaries of minted tokens + * @param quantities amounts of minted tokens + * @param txData Additional data for transaction + * @returns The hash of the transaction + */ + async estimateGasAsync( + id: BigNumber, + to: string[], + quantities: BigNumber[], + txData?: Partial | undefined, + ): Promise { + assert.isBigNumber('id', id); + assert.isArray('to', to); + assert.isArray('quantities', quantities); + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('mintFungible(uint256,address[],uint256[])', [ + id, + to, + quantities, + ]); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); + return gas; + }, + async validateAndSendTransactionAsync( + id: BigNumber, + to: string[], + quantities: BigNumber[], + txData?: Partial | undefined, + ): Promise { + await (this as any).mintFungible.callAsync(id, to, quantities, txData); + const txHash = await (this as any).mintFungible.sendTransactionAsync(id, to, quantities, txData); + return txHash; + }, + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + * @param id token type + * @param to beneficiaries of minted tokens + * @param quantities amounts of minted tokens + */ + async callAsync( + id: BigNumber, + to: string[], + quantities: BigNumber[], + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise { + assert.isBigNumber('id', id); + assert.isArray('to', to); + assert.isArray('quantities', quantities); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('mintFungible(uint256,address[],uint256[])', [ + id, + to, + quantities, + ]); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + let rawCallResult; + try { + rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('mintFungible(uint256,address[],uint256[])'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @param id token type + * @param to beneficiaries of minted tokens + * @param quantities amounts of minted tokens + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(id: BigNumber, to: string[], quantities: BigNumber[]): string { + assert.isBigNumber('id', id); + assert.isArray('to', to); + assert.isArray('quantities', quantities); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('mintFungible(uint256,address[],uint256[])', [ + id, + to, + quantities, + ]); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): [BigNumber, string[], BigNumber[]] { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('mintFungible(uint256,address[],uint256[])'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode<[BigNumber, string[], BigNumber[]]>(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): void { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('mintFungible(uint256,address[],uint256[])'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + /** + * mints a non-fungible token + */ + public mintNonFungible = { + /** + * Sends an Ethereum transaction executing this method with the supplied parameters. This is a read/write + * Ethereum operation and will cost gas. + * @param type_ token type + * @param to beneficiaries of minted tokens + * @param txData Additional data for transaction + * @returns The hash of the transaction + */ + async sendTransactionAsync( + type_: BigNumber, + to: string[], + txData?: Partial | undefined, + ): Promise { + assert.isBigNumber('type_', type_); + assert.isArray('to', to); + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('mintNonFungible(uint256,address[])', [type_, to]); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); + return txHash; + }, + /** + * Sends an Ethereum transaction and waits until the transaction has been successfully mined without reverting. + * If the transaction was mined, but reverted, an error is thrown. + * @param type_ token type + * @param to beneficiaries of minted tokens + * @param txData Additional data for transaction + * @param pollingIntervalMs Interval at which to poll for success + * @returns A promise that resolves when the transaction is successful + */ + awaitTransactionSuccessAsync( + type_: BigNumber, + to: string[], + txData?: Partial, + pollingIntervalMs?: number, + timeoutMs?: number, + ): PromiseWithTransactionHash { + assert.isBigNumber('type_', type_); + assert.isArray('to', to); + const self = (this as any) as ERC1155MintableContract; + const txHashPromise = self.mintNonFungible.sendTransactionAsync(type_, to, txData); + return new PromiseWithTransactionHash( + txHashPromise, + (async (): Promise => { + // When the transaction hash resolves, wait for it to be mined. + return self._web3Wrapper.awaitTransactionSuccessAsync( + await txHashPromise, + pollingIntervalMs, + timeoutMs, + ); + })(), + ); + }, + /** + * Estimates the gas cost of sending an Ethereum transaction calling this method with these arguments. + * @param type_ token type + * @param to beneficiaries of minted tokens + * @param txData Additional data for transaction + * @returns The hash of the transaction + */ + async estimateGasAsync(type_: BigNumber, to: string[], txData?: Partial | undefined): Promise { + assert.isBigNumber('type_', type_); + assert.isArray('to', to); + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('mintNonFungible(uint256,address[])', [type_, to]); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); + return gas; + }, + async validateAndSendTransactionAsync( + type_: BigNumber, + to: string[], + txData?: Partial | undefined, + ): Promise { + await (this as any).mintNonFungible.callAsync(type_, to, txData); + const txHash = await (this as any).mintNonFungible.sendTransactionAsync(type_, to, txData); + return txHash; + }, + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + * @param type_ token type + * @param to beneficiaries of minted tokens + */ + async callAsync( + type_: BigNumber, + to: string[], + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise { + assert.isBigNumber('type_', type_); + assert.isArray('to', to); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('mintNonFungible(uint256,address[])', [type_, to]); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + let rawCallResult; + try { + rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('mintNonFungible(uint256,address[])'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @param type_ token type + * @param to beneficiaries of minted tokens + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(type_: BigNumber, to: string[]): string { + assert.isBigNumber('type_', type_); + assert.isArray('to', to); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('mintNonFungible(uint256,address[])', [ + type_, + to, + ]); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): [BigNumber, string[]] { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('mintNonFungible(uint256,address[])'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode<[BigNumber, string[]]>(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): void { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('mintNonFungible(uint256,address[])'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + /** + * returns owner of a non-fungible token + */ + public ownerOf = { + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + */ + async callAsync(id: BigNumber, callData: Partial = {}, defaultBlock?: BlockParam): Promise { + assert.isBigNumber('id', id); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('ownerOf(uint256)', [id]); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + let rawCallResult; + try { + rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('ownerOf(uint256)'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(id: BigNumber): string { + assert.isBigNumber('id', id); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('ownerOf(uint256)', [id]); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): BigNumber { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('ownerOf(uint256)'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): string { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('ownerOf(uint256)'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + /** + * MUST emit TransferBatch event on success. Caller must be approved to manage the _from account's tokens (see isApprovedForAll). MUST throw if `_to` is the zero address. MUST throw if length of `_ids` is not the same as length of `_values`. MUST throw if any of the balance of sender for token `_ids` is lower than the respective `_values` sent. MUST throw on any other error. When transfer is complete, this function MUST check if `_to` is a smart contract (code size > 0). If so, it MUST call `onERC1155BatchReceived` on `_to` and revert if the return value is not `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`. + */ + public safeBatchTransferFrom = { + /** + * Sends an Ethereum transaction executing this method with the supplied parameters. This is a read/write + * Ethereum operation and will cost gas. + * @param from Source addresses + * @param to Target addresses + * @param ids IDs of each token type + * @param values Transfer amounts per token type + * @param data Additional data with no specified format, sent in call to `_to` + * @param txData Additional data for transaction + * @returns The hash of the transaction + */ + async sendTransactionAsync( + from: string, + to: string, + ids: BigNumber[], + values: BigNumber[], + data: string, + txData?: Partial | undefined, + ): Promise { + assert.isString('from', from); + assert.isString('to', to); + assert.isArray('ids', ids); + assert.isArray('values', values); + assert.isString('data', data); + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments( + 'safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)', + [from.toLowerCase(), to.toLowerCase(), ids, values, data], + ); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); + return txHash; + }, + /** + * Sends an Ethereum transaction and waits until the transaction has been successfully mined without reverting. + * If the transaction was mined, but reverted, an error is thrown. + * @param from Source addresses + * @param to Target addresses + * @param ids IDs of each token type + * @param values Transfer amounts per token type + * @param data Additional data with no specified format, sent in call to `_to` + * @param txData Additional data for transaction + * @param pollingIntervalMs Interval at which to poll for success + * @returns A promise that resolves when the transaction is successful + */ + awaitTransactionSuccessAsync( + from: string, + to: string, + ids: BigNumber[], + values: BigNumber[], + data: string, + txData?: Partial, + pollingIntervalMs?: number, + timeoutMs?: number, + ): PromiseWithTransactionHash { + assert.isString('from', from); + assert.isString('to', to); + assert.isArray('ids', ids); + assert.isArray('values', values); + assert.isString('data', data); + const self = (this as any) as ERC1155MintableContract; + const txHashPromise = self.safeBatchTransferFrom.sendTransactionAsync( + from.toLowerCase(), + to.toLowerCase(), + ids, + values, + data, + txData, + ); + return new PromiseWithTransactionHash( + txHashPromise, + (async (): Promise => { + // When the transaction hash resolves, wait for it to be mined. + return self._web3Wrapper.awaitTransactionSuccessAsync( + await txHashPromise, + pollingIntervalMs, + timeoutMs, + ); + })(), + ); + }, + /** + * Estimates the gas cost of sending an Ethereum transaction calling this method with these arguments. + * @param from Source addresses + * @param to Target addresses + * @param ids IDs of each token type + * @param values Transfer amounts per token type + * @param data Additional data with no specified format, sent in call to `_to` + * @param txData Additional data for transaction + * @returns The hash of the transaction + */ + async estimateGasAsync( + from: string, + to: string, + ids: BigNumber[], + values: BigNumber[], + data: string, + txData?: Partial | undefined, + ): Promise { + assert.isString('from', from); + assert.isString('to', to); + assert.isArray('ids', ids); + assert.isArray('values', values); + assert.isString('data', data); + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments( + 'safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)', + [from.toLowerCase(), to.toLowerCase(), ids, values, data], + ); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); + return gas; + }, + async validateAndSendTransactionAsync( + from: string, + to: string, + ids: BigNumber[], + values: BigNumber[], + data: string, + txData?: Partial | undefined, + ): Promise { + await (this as any).safeBatchTransferFrom.callAsync(from, to, ids, values, data, txData); + const txHash = await (this as any).safeBatchTransferFrom.sendTransactionAsync( + from, + to, + ids, + values, + data, + txData, + ); + return txHash; + }, + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + * @param from Source addresses + * @param to Target addresses + * @param ids IDs of each token type + * @param values Transfer amounts per token type + * @param data Additional data with no specified format, sent in call to `_to` + */ + async callAsync( + from: string, + to: string, + ids: BigNumber[], + values: BigNumber[], + data: string, + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise { + assert.isString('from', from); + assert.isString('to', to); + assert.isArray('ids', ids); + assert.isArray('values', values); + assert.isString('data', data); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments( + 'safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)', + [from.toLowerCase(), to.toLowerCase(), ids, values, data], + ); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + let rawCallResult; + try { + rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + const abiEncoder = self._lookupAbiEncoder( + 'safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)', + ); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @param from Source addresses + * @param to Target addresses + * @param ids IDs of each token type + * @param values Transfer amounts per token type + * @param data Additional data with no specified format, sent in call to `_to` + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData( + from: string, + to: string, + ids: BigNumber[], + values: BigNumber[], + data: string, + ): string { + assert.isString('from', from); + assert.isString('to', to); + assert.isArray('ids', ids); + assert.isArray('values', values); + assert.isString('data', data); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments( + 'safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)', + [from.toLowerCase(), to.toLowerCase(), ids, values, data], + ); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): [string, string, BigNumber[], BigNumber[], string] { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder( + 'safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)', + ); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode<[string, string, BigNumber[], BigNumber[], string]>( + callData, + ); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): void { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder( + 'safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)', + ); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + /** + * MUST emit TransferSingle event on success. Caller must be approved to manage the _from account's tokens (see isApprovedForAll). MUST throw if `_to` is the zero address. MUST throw if balance of sender for token `_id` is lower than the `_value` sent. MUST throw on any other error. When transfer is complete, this function MUST check if `_to` is a smart contract (code size > 0). If so, it MUST call `onERC1155Received` on `_to` and revert if the return value is not `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`. + */ + public safeTransferFrom = { + /** + * Sends an Ethereum transaction executing this method with the supplied parameters. This is a read/write + * Ethereum operation and will cost gas. + * @param from Source address + * @param to Target address + * @param id ID of the token type + * @param value Transfer amount + * @param data Additional data with no specified format, sent in call to `_to` + * @param txData Additional data for transaction + * @returns The hash of the transaction + */ + async sendTransactionAsync( + from: string, + to: string, + id: BigNumber, + value: BigNumber, + data: string, + txData?: Partial | undefined, + ): Promise { + assert.isString('from', from); + assert.isString('to', to); + assert.isBigNumber('id', id); + assert.isBigNumber('value', value); + assert.isString('data', data); + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('safeTransferFrom(address,address,uint256,uint256,bytes)', [ + from.toLowerCase(), + to.toLowerCase(), + id, + value, + data, + ]); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); + return txHash; + }, + /** + * Sends an Ethereum transaction and waits until the transaction has been successfully mined without reverting. + * If the transaction was mined, but reverted, an error is thrown. + * @param from Source address + * @param to Target address + * @param id ID of the token type + * @param value Transfer amount + * @param data Additional data with no specified format, sent in call to `_to` + * @param txData Additional data for transaction + * @param pollingIntervalMs Interval at which to poll for success + * @returns A promise that resolves when the transaction is successful + */ + awaitTransactionSuccessAsync( + from: string, + to: string, + id: BigNumber, + value: BigNumber, + data: string, + txData?: Partial, + pollingIntervalMs?: number, + timeoutMs?: number, + ): PromiseWithTransactionHash { + assert.isString('from', from); + assert.isString('to', to); + assert.isBigNumber('id', id); + assert.isBigNumber('value', value); + assert.isString('data', data); + const self = (this as any) as ERC1155MintableContract; + const txHashPromise = self.safeTransferFrom.sendTransactionAsync( + from.toLowerCase(), + to.toLowerCase(), + id, + value, + data, + txData, + ); + return new PromiseWithTransactionHash( + txHashPromise, + (async (): Promise => { + // When the transaction hash resolves, wait for it to be mined. + return self._web3Wrapper.awaitTransactionSuccessAsync( + await txHashPromise, + pollingIntervalMs, + timeoutMs, + ); + })(), + ); + }, + /** + * Estimates the gas cost of sending an Ethereum transaction calling this method with these arguments. + * @param from Source address + * @param to Target address + * @param id ID of the token type + * @param value Transfer amount + * @param data Additional data with no specified format, sent in call to `_to` + * @param txData Additional data for transaction + * @returns The hash of the transaction + */ + async estimateGasAsync( + from: string, + to: string, + id: BigNumber, + value: BigNumber, + data: string, + txData?: Partial | undefined, + ): Promise { + assert.isString('from', from); + assert.isString('to', to); + assert.isBigNumber('id', id); + assert.isBigNumber('value', value); + assert.isString('data', data); + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('safeTransferFrom(address,address,uint256,uint256,bytes)', [ + from.toLowerCase(), + to.toLowerCase(), + id, + value, + data, + ]); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); + return gas; + }, + async validateAndSendTransactionAsync( + from: string, + to: string, + id: BigNumber, + value: BigNumber, + data: string, + txData?: Partial | undefined, + ): Promise { + await (this as any).safeTransferFrom.callAsync(from, to, id, value, data, txData); + const txHash = await (this as any).safeTransferFrom.sendTransactionAsync(from, to, id, value, data, txData); + return txHash; + }, + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + * @param from Source address + * @param to Target address + * @param id ID of the token type + * @param value Transfer amount + * @param data Additional data with no specified format, sent in call to `_to` + */ + async callAsync( + from: string, + to: string, + id: BigNumber, + value: BigNumber, + data: string, + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise { + assert.isString('from', from); + assert.isString('to', to); + assert.isBigNumber('id', id); + assert.isBigNumber('value', value); + assert.isString('data', data); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('safeTransferFrom(address,address,uint256,uint256,bytes)', [ + from.toLowerCase(), + to.toLowerCase(), + id, + value, + data, + ]); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + let rawCallResult; + try { + rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('safeTransferFrom(address,address,uint256,uint256,bytes)'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @param from Source address + * @param to Target address + * @param id ID of the token type + * @param value Transfer amount + * @param data Additional data with no specified format, sent in call to `_to` + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(from: string, to: string, id: BigNumber, value: BigNumber, data: string): string { + assert.isString('from', from); + assert.isString('to', to); + assert.isBigNumber('id', id); + assert.isBigNumber('value', value); + assert.isString('data', data); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments( + 'safeTransferFrom(address,address,uint256,uint256,bytes)', + [from.toLowerCase(), to.toLowerCase(), id, value, data], + ); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): [string, string, BigNumber, BigNumber, string] { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('safeTransferFrom(address,address,uint256,uint256,bytes)'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode<[string, string, BigNumber, BigNumber, string]>( + callData, + ); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): void { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('safeTransferFrom(address,address,uint256,uint256,bytes)'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + /** + * MUST emit the ApprovalForAll event on success. + */ + public setApprovalForAll = { + /** + * Sends an Ethereum transaction executing this method with the supplied parameters. This is a read/write + * Ethereum operation and will cost gas. + * @param operator Address to add to the set of authorized operators + * @param approved True if the operator is approved, false to revoke approval + * @param txData Additional data for transaction + * @returns The hash of the transaction + */ + async sendTransactionAsync( + operator: string, + approved: boolean, + txData?: Partial | undefined, + ): Promise { + assert.isString('operator', operator); + assert.isBoolean('approved', approved); + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('setApprovalForAll(address,bool)', [ + operator.toLowerCase(), + approved, + ]); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); + return txHash; + }, + /** + * Sends an Ethereum transaction and waits until the transaction has been successfully mined without reverting. + * If the transaction was mined, but reverted, an error is thrown. + * @param operator Address to add to the set of authorized operators + * @param approved True if the operator is approved, false to revoke approval + * @param txData Additional data for transaction + * @param pollingIntervalMs Interval at which to poll for success + * @returns A promise that resolves when the transaction is successful + */ + awaitTransactionSuccessAsync( + operator: string, + approved: boolean, + txData?: Partial, + pollingIntervalMs?: number, + timeoutMs?: number, + ): PromiseWithTransactionHash { + assert.isString('operator', operator); + assert.isBoolean('approved', approved); + const self = (this as any) as ERC1155MintableContract; + const txHashPromise = self.setApprovalForAll.sendTransactionAsync(operator.toLowerCase(), approved, txData); + return new PromiseWithTransactionHash( + txHashPromise, + (async (): Promise => { + // When the transaction hash resolves, wait for it to be mined. + return self._web3Wrapper.awaitTransactionSuccessAsync( + await txHashPromise, + pollingIntervalMs, + timeoutMs, + ); + })(), + ); + }, + /** + * Estimates the gas cost of sending an Ethereum transaction calling this method with these arguments. + * @param operator Address to add to the set of authorized operators + * @param approved True if the operator is approved, false to revoke approval + * @param txData Additional data for transaction + * @returns The hash of the transaction + */ + async estimateGasAsync( + operator: string, + approved: boolean, + txData?: Partial | undefined, + ): Promise { + assert.isString('operator', operator); + assert.isBoolean('approved', approved); + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('setApprovalForAll(address,bool)', [ + operator.toLowerCase(), + approved, + ]); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + if (txDataWithDefaults.from !== undefined) { + txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase(); + } + + const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); + return gas; + }, + async validateAndSendTransactionAsync( + operator: string, + approved: boolean, + txData?: Partial | undefined, + ): Promise { + await (this as any).setApprovalForAll.callAsync(operator, approved, txData); + const txHash = await (this as any).setApprovalForAll.sendTransactionAsync(operator, approved, txData); + return txHash; + }, + /** + * Sends a read-only call to the contract method. Returns the result that would happen if one were to send an + * Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas + * since they don't modify state. + * @param operator Address to add to the set of authorized operators + * @param approved True if the operator is approved, false to revoke approval + */ + async callAsync( + operator: string, + approved: boolean, + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise { + assert.isString('operator', operator); + assert.isBoolean('approved', approved); + assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (defaultBlock !== undefined) { + assert.isBlockParam('defaultBlock', defaultBlock); + } + const self = (this as any) as ERC1155MintableContract; + const encodedData = self._strictEncodeArguments('setApprovalForAll(address,bool)', [ + operator.toLowerCase(), + approved, + ]); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + callDataWithDefaults.from = callDataWithDefaults.from + ? callDataWithDefaults.from.toLowerCase() + : callDataWithDefaults.from; + let rawCallResult; + try { + rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + } catch (err) { + BaseContract._throwIfThrownErrorIsRevertError(err); + throw err; + } + BaseContract._throwIfCallResultIsRevertError(rawCallResult); + const abiEncoder = self._lookupAbiEncoder('setApprovalForAll(address,bool)'); + // tslint:disable boolean-naming + const result = abiEncoder.strictDecodeReturnValue(rawCallResult); + // tslint:enable boolean-naming + return result; + }, + /** + * Returns the ABI encoded transaction data needed to send an Ethereum transaction calling this method. Before + * sending the Ethereum tx, this encoded tx data can first be sent to a separate signing service or can be used + * to create a 0x transaction (see protocol spec for more details). + * @param operator Address to add to the set of authorized operators + * @param approved True if the operator is approved, false to revoke approval + * @returns The ABI encoded transaction data as a string + */ + getABIEncodedTransactionData(operator: string, approved: boolean): string { + assert.isString('operator', operator); + assert.isBoolean('approved', approved); + const self = (this as any) as ERC1155MintableContract; + const abiEncodedTransactionData = self._strictEncodeArguments('setApprovalForAll(address,bool)', [ + operator.toLowerCase(), + approved, + ]); + return abiEncodedTransactionData; + }, + /** + * Decode the ABI-encoded transaction data into its input arguments + * @param callData The ABI-encoded transaction data + * @returns An array representing the input arguments in order. Keynames of nested structs are preserved. + */ + getABIDecodedTransactionData(callData: string): [string, boolean] { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('setApprovalForAll(address,bool)'); + // tslint:disable boolean-naming + const abiDecodedCallData = abiEncoder.strictDecode<[string, boolean]>(callData); + return abiDecodedCallData; + }, + /** + * Decode the ABI-encoded return data from a transaction + * @param returnData the data returned after transaction execution + * @returns An array representing the output results in order. Keynames of nested structs are preserved. + */ + getABIDecodedReturnData(returnData: string): void { + const self = (this as any) as ERC1155MintableContract; + const abiEncoder = self._lookupAbiEncoder('setApprovalForAll(address,bool)'); + // tslint:disable boolean-naming + const abiDecodedReturnData = abiEncoder.strictDecodeReturnValue(returnData); + return abiDecodedReturnData; + }, + }; + private readonly _subscriptionManager: SubscriptionManager; + public static async deployFrom0xArtifactAsync( + artifact: ContractArtifact | SimpleContractArtifact, + supportedProvider: SupportedProvider, + txDefaults: Partial, + logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact }, + ): Promise { + assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + if (artifact.compilerOutput === undefined) { + throw new Error('Compiler output not found in the artifact file'); + } + const provider = providerUtils.standardizeOrThrow(supportedProvider); + const bytecode = artifact.compilerOutput.evm.bytecode.object; + const abi = artifact.compilerOutput.abi; + const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {}; + if (Object.keys(logDecodeDependencies) !== undefined) { + for (const key of Object.keys(logDecodeDependencies)) { + logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi; + } + } + return ERC1155MintableContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly); + } + public static async deployAsync( + bytecode: string, + abi: ContractAbi, + supportedProvider: SupportedProvider, + txDefaults: Partial, + logDecodeDependencies: { [contractName: string]: ContractAbi }, + ): Promise { + assert.isHexString('bytecode', bytecode); + assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [ + schemas.addressSchema, + schemas.numberSchema, + schemas.jsNumber, + ]); + const provider = providerUtils.standardizeOrThrow(supportedProvider); + const constructorAbi = BaseContract._lookupConstructorAbi(abi); + [] = BaseContract._formatABIDataItemList(constructorAbi.inputs, [], BaseContract._bigNumberToString); + const iface = new ethers.utils.Interface(abi); + const deployInfo = iface.deployFunction; + const txData = deployInfo.encode(bytecode, []); + const web3Wrapper = new Web3Wrapper(provider); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { data: txData }, + txDefaults, + web3Wrapper.estimateGasAsync.bind(web3Wrapper), + ); + const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults); + logUtils.log(`transactionHash: ${txHash}`); + const txReceipt = await web3Wrapper.awaitTransactionSuccessAsync(txHash); + logUtils.log(`ERC1155Mintable successfully deployed at ${txReceipt.contractAddress}`); + const contractInstance = new ERC1155MintableContract( + txReceipt.contractAddress as string, + provider, + txDefaults, + logDecodeDependencies, + ); + contractInstance.constructorArgs = []; + return contractInstance; + } + + /** + * @returns The contract ABI + */ + public static ABI(): ContractAbi { + const abi = [ + { + anonymous: false, + inputs: [ + { + name: 'owner', + type: 'address', + indexed: true, + }, + { + name: 'operator', + type: 'address', + indexed: true, + }, + { + name: 'approved', + type: 'bool', + indexed: false, + }, + ], + name: 'ApprovalForAll', + outputs: [], + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + name: 'operator', + type: 'address', + indexed: true, + }, + { + name: 'from', + type: 'address', + indexed: true, + }, + { + name: 'to', + type: 'address', + indexed: true, + }, + { + name: 'ids', + type: 'uint256[]', + indexed: false, + }, + { + name: 'values', + type: 'uint256[]', + indexed: false, + }, + ], + name: 'TransferBatch', + outputs: [], + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + name: 'operator', + type: 'address', + indexed: true, + }, + { + name: 'from', + type: 'address', + indexed: true, + }, + { + name: 'to', + type: 'address', + indexed: true, + }, + { + name: 'id', + type: 'uint256', + indexed: false, + }, + { + name: 'value', + type: 'uint256', + indexed: false, + }, + ], + name: 'TransferSingle', + outputs: [], + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + name: 'value', + type: 'string', + indexed: false, + }, + { + name: 'id', + type: 'uint256', + indexed: true, + }, + ], + name: 'URI', + outputs: [], + type: 'event', + }, + { + constant: true, + inputs: [], + name: 'ERC1155_BATCH_RECEIVED', + outputs: [ + { + name: '', + type: 'bytes4', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, + { + constant: true, + inputs: [], + name: 'ERC1155_RECEIVED', + outputs: [ + { + name: '', + type: 'bytes4', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, + { + constant: true, + inputs: [ + { + name: 'owner', + type: 'address', + }, + { + name: 'id', + type: 'uint256', + }, + ], + name: 'balanceOf', + outputs: [ + { + name: '', + type: 'uint256', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, + { + constant: true, + inputs: [ + { + name: 'owners', + type: 'address[]', + }, + { + name: 'ids', + type: 'uint256[]', + }, + ], + name: 'balanceOfBatch', + outputs: [ + { + name: 'balances_', + type: 'uint256[]', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, + { + constant: false, + inputs: [ + { + name: 'uri', + type: 'string', + }, + { + name: 'isNF', + type: 'bool', + }, + ], + name: 'create', + outputs: [ + { + name: 'type_', + type: 'uint256', + }, + ], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, + { + constant: false, + inputs: [ + { + name: 'type_', + type: 'uint256', + }, + { + name: 'uri', + type: 'string', + }, + ], + name: 'createWithType', + outputs: [], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, + { + constant: true, + inputs: [ + { + name: 'index_0', + type: 'uint256', + }, + ], + name: 'creators', + outputs: [ + { + name: '', + type: 'address', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, + { + constant: true, + inputs: [ + { + name: 'id', + type: 'uint256', + }, + ], + name: 'getNonFungibleBaseType', + outputs: [ + { + name: '', + type: 'uint256', + }, + ], + payable: false, + stateMutability: 'pure', + type: 'function', + }, + { + constant: true, + inputs: [ + { + name: 'id', + type: 'uint256', + }, + ], + name: 'getNonFungibleIndex', + outputs: [ + { + name: '', + type: 'uint256', + }, + ], + payable: false, + stateMutability: 'pure', + type: 'function', + }, + { + constant: true, + inputs: [ + { + name: 'owner', + type: 'address', + }, + { + name: 'operator', + type: 'address', + }, + ], + name: 'isApprovedForAll', + outputs: [ + { + name: '', + type: 'bool', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, + { + constant: true, + inputs: [ + { + name: 'id', + type: 'uint256', + }, + ], + name: 'isFungible', + outputs: [ + { + name: '', + type: 'bool', + }, + ], + payable: false, + stateMutability: 'pure', + type: 'function', + }, + { + constant: true, + inputs: [ + { + name: 'id', + type: 'uint256', + }, + ], + name: 'isNonFungible', + outputs: [ + { + name: '', + type: 'bool', + }, + ], + payable: false, + stateMutability: 'pure', + type: 'function', + }, + { + constant: true, + inputs: [ + { + name: 'id', + type: 'uint256', + }, + ], + name: 'isNonFungibleBaseType', + outputs: [ + { + name: '', + type: 'bool', + }, + ], + payable: false, + stateMutability: 'pure', + type: 'function', + }, + { + constant: true, + inputs: [ + { + name: 'id', + type: 'uint256', + }, + ], + name: 'isNonFungibleItem', + outputs: [ + { + name: '', + type: 'bool', + }, + ], + payable: false, + stateMutability: 'pure', + type: 'function', + }, + { + constant: true, + inputs: [ + { + name: 'index_0', + type: 'uint256', + }, + ], + name: 'maxIndex', + outputs: [ + { + name: '', + type: 'uint256', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, + { + constant: false, + inputs: [ + { + name: 'id', + type: 'uint256', + }, + { + name: 'to', + type: 'address[]', + }, + { + name: 'quantities', + type: 'uint256[]', + }, + ], + name: 'mintFungible', + outputs: [], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, + { + constant: false, + inputs: [ + { + name: 'type_', + type: 'uint256', + }, + { + name: 'to', + type: 'address[]', + }, + ], + name: 'mintNonFungible', + outputs: [], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, + { + constant: true, + inputs: [ + { + name: 'id', + type: 'uint256', + }, + ], + name: 'ownerOf', + outputs: [ + { + name: '', + type: 'address', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, + { + constant: false, + inputs: [ + { + name: 'from', + type: 'address', + }, + { + name: 'to', + type: 'address', + }, + { + name: 'ids', + type: 'uint256[]', + }, + { + name: 'values', + type: 'uint256[]', + }, + { + name: 'data', + type: 'bytes', + }, + ], + name: 'safeBatchTransferFrom', + outputs: [], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, + { + constant: false, + inputs: [ + { + name: 'from', + type: 'address', + }, + { + name: 'to', + type: 'address', + }, + { + name: 'id', + type: 'uint256', + }, + { + name: 'value', + type: 'uint256', + }, + { + name: 'data', + type: 'bytes', + }, + ], + name: 'safeTransferFrom', + outputs: [], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, + { + constant: false, + inputs: [ + { + name: 'operator', + type: 'address', + }, + { + name: 'approved', + type: 'bool', + }, + ], + name: 'setApprovalForAll', + outputs: [], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, + ] as ContractAbi; + return abi; + } + /** + * Subscribe to an event type emitted by the ERC1155Mintable contract. + * @param eventName The ERC1155Mintable contract event you would like to subscribe to. + * @param indexFilterValues An object where the keys are indexed args returned by the event and + * the value is the value you are interested in. E.g `{maker: aUserAddressHex}` + * @param callback Callback that gets called when a log is added/removed + * @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered) + * @return Subscription token used later to unsubscribe + */ + public subscribe( + eventName: ERC1155MintableEvents, + indexFilterValues: IndexedFilterValues, + callback: EventCallback, + isVerbose: boolean = false, + blockPollingIntervalMs?: number, + ): string { + assert.doesBelongToStringEnum('eventName', eventName, ERC1155MintableEvents); + assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); + assert.isFunction('callback', callback); + const subscriptionToken = this._subscriptionManager.subscribe( + this.address, + eventName, + indexFilterValues, + ERC1155MintableContract.ABI(), + callback, + isVerbose, + blockPollingIntervalMs, + ); + return subscriptionToken; + } + /** + * Cancel a subscription + * @param subscriptionToken Subscription token returned by `subscribe()` + */ + public unsubscribe(subscriptionToken: string): void { + this._subscriptionManager.unsubscribe(subscriptionToken); + } + /** + * Cancels all existing subscriptions + */ + public unsubscribeAll(): void { + this._subscriptionManager.unsubscribeAll(); + } + /** + * Gets historical logs without creating a subscription + * @param eventName The ERC1155Mintable contract event you would like to subscribe to. + * @param blockRange Block range to get logs from. + * @param indexFilterValues An object where the keys are indexed args returned by the event and + * the value is the value you are interested in. E.g `{_from: aUserAddressHex}` + * @return Array of logs that match the parameters + */ + public async getLogsAsync( + eventName: ERC1155MintableEvents, + blockRange: BlockRange, + indexFilterValues: IndexedFilterValues, + ): Promise>> { + assert.doesBelongToStringEnum('eventName', eventName, ERC1155MintableEvents); + assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema); + assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); + const logs = await this._subscriptionManager.getLogsAsync( + this.address, + eventName, + blockRange, + indexFilterValues, + ERC1155MintableContract.ABI(), + ); + return logs; + } + constructor( + address: string, + supportedProvider: SupportedProvider, + txDefaults?: Partial, + logDecodeDependencies?: { [contractName: string]: ContractAbi }, + deployedBytecode: string | undefined = ERC1155MintableContract.deployedBytecode, + ) { + super( + 'ERC1155Mintable', + ERC1155MintableContract.ABI(), + address, + supportedProvider, + txDefaults, + logDecodeDependencies, + deployedBytecode, + ); + classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); + this._subscriptionManager = new SubscriptionManager( + ERC1155MintableContract.ABI(), + this._web3Wrapper, + ); + } +} + +// tslint:disable:max-file-line-count +// tslint:enable:no-unbound-method no-parameter-reassignment no-consecutive-blank-lines ordered-imports align +// tslint:enable:trailing-comma whitespace no-trailing-whitespace diff --git a/packages/contract-artifacts/artifacts/ERC1155Mintable.json b/packages/contract-artifacts/artifacts/ERC1155Mintable.json new file mode 100644 index 0000000000..c406fbe89b --- /dev/null +++ b/packages/contract-artifacts/artifacts/ERC1155Mintable.json @@ -0,0 +1,384 @@ +{ + "schemaVersion": "2.0.0", + "contractName": "ERC1155Mintable", + "compilerOutput": { + "abi": [ + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "owner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "operator", "type": "address" }, + { "indexed": false, "internalType": "bool", "name": "approved", "type": "bool" } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "operator", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, + { "indexed": false, "internalType": "uint256[]", "name": "ids", "type": "uint256[]" }, + { "indexed": false, "internalType": "uint256[]", "name": "values", "type": "uint256[]" } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "operator", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "id", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "string", "name": "value", "type": "string" }, + { "indexed": true, "internalType": "uint256", "name": "id", "type": "uint256" } + ], + "name": "URI", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "ERC1155_BATCH_RECEIVED", + "outputs": [{ "internalType": "bytes4", "name": "", "type": "bytes4" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "ERC1155_RECEIVED", + "outputs": [{ "internalType": "bytes4", "name": "", "type": "bytes4" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "uint256", "name": "id", "type": "uint256" } + ], + "name": "balanceOf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "address[]", "name": "owners", "type": "address[]" }, + { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" } + ], + "name": "balanceOfBatch", + "outputs": [{ "internalType": "uint256[]", "name": "balances_", "type": "uint256[]" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "string", "name": "uri", "type": "string" }, + { "internalType": "bool", "name": "isNF", "type": "bool" } + ], + "name": "create", + "outputs": [{ "internalType": "uint256", "name": "type_", "type": "uint256" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "uint256", "name": "type_", "type": "uint256" }, + { "internalType": "string", "name": "uri", "type": "string" } + ], + "name": "createWithType", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "creators", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "uint256", "name": "id", "type": "uint256" }], + "name": "getNonFungibleBaseType", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "uint256", "name": "id", "type": "uint256" }], + "name": "getNonFungibleIndex", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "operator", "type": "address" } + ], + "name": "isApprovedForAll", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "uint256", "name": "id", "type": "uint256" }], + "name": "isFungible", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "uint256", "name": "id", "type": "uint256" }], + "name": "isNonFungible", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "uint256", "name": "id", "type": "uint256" }], + "name": "isNonFungibleBaseType", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "uint256", "name": "id", "type": "uint256" }], + "name": "isNonFungibleItem", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "maxIndex", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "uint256", "name": "id", "type": "uint256" }, + { "internalType": "address[]", "name": "to", "type": "address[]" }, + { "internalType": "uint256[]", "name": "quantities", "type": "uint256[]" } + ], + "name": "mintFungible", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "uint256", "name": "type_", "type": "uint256" }, + { "internalType": "address[]", "name": "to", "type": "address[]" } + ], + "name": "mintNonFungible", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "uint256", "name": "id", "type": "uint256" }], + "name": "ownerOf", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" }, + { "internalType": "uint256[]", "name": "values", "type": "uint256[]" }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "id", "type": "uint256" }, + { "internalType": "uint256", "name": "value", "type": "uint256" }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "safeTransferFrom", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "operator", "type": "address" }, + { "internalType": "bool", "name": "approved", "type": "bool" } + ], + "name": "setApprovalForAll", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ], + "devdoc": { + "details": "Mintable form of ERC1155 Shows how easy it is to mint new items", + "methods": { + "balanceOf(address,uint256)": { + "params": { "id": "ID of the Token", "owner": "The address of the token holder" }, + "return": "The _owner's balance of the Token type requested" + }, + "balanceOfBatch(address[],uint256[])": { + "params": { "ids": "ID of the Tokens", "owners": "The addresses of the token holders" }, + "return": "The _owner's balance of the Token types requested" + }, + "create(string,bool)": { + "details": "creates a new token", + "params": { "isNF": "is non-fungible token", "uri": "URI of token" }, + "return": "type_ of token (a unique identifier)" + }, + "createWithType(uint256,string)": { + "details": "creates a new token", + "params": { "type_": "of token", "uri": "URI of token" } + }, + "getNonFungibleBaseType(uint256)": { "details": "Returns base type of non-fungible token" }, + "getNonFungibleIndex(uint256)": { "details": "Returns index of non-fungible token" }, + "isApprovedForAll(address,address)": { + "params": { "operator": "Address of authorized operator", "owner": "The owner of the Tokens" }, + "return": "True if the operator is approved, false if not" + }, + "isFungible(uint256)": { "details": "Returns true if token is fungible" }, + "isNonFungible(uint256)": { "details": "Returns true if token is non-fungible" }, + "isNonFungibleBaseType(uint256)": { + "details": "Returns true if input is base-type of a non-fungible token" + }, + "isNonFungibleItem(uint256)": { "details": "Returns true if input is a non-fungible token" }, + "mintFungible(uint256,address[],uint256[])": { + "details": "mints fungible tokens", + "params": { + "id": "token type", + "quantities": "amounts of minted tokens", + "to": "beneficiaries of minted tokens" + } + }, + "mintNonFungible(uint256,address[])": { + "details": "mints a non-fungible token", + "params": { "to": "beneficiaries of minted tokens", "type_": "token type" } + }, + "ownerOf(uint256)": { "details": "returns owner of a non-fungible token" }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "details": "MUST emit TransferBatch event on success. Caller must be approved to manage the _from account's tokens (see isApprovedForAll). MUST throw if `_to` is the zero address. MUST throw if length of `_ids` is not the same as length of `_values`. MUST throw if any of the balance of sender for token `_ids` is lower than the respective `_values` sent. MUST throw on any other error. When transfer is complete, this function MUST check if `_to` is a smart contract (code size > 0). If so, it MUST call `onERC1155BatchReceived` on `_to` and revert if the return value is not `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`.", + "params": { + "data": "Additional data with no specified format, sent in call to `_to`", + "from": "Source addresses", + "ids": "IDs of each token type", + "to": "Target addresses", + "values": "Transfer amounts per token type" + } + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "details": "MUST emit TransferSingle event on success. Caller must be approved to manage the _from account's tokens (see isApprovedForAll). MUST throw if `_to` is the zero address. MUST throw if balance of sender for token `_id` is lower than the `_value` sent. MUST throw on any other error. When transfer is complete, this function MUST check if `_to` is a smart contract (code size > 0). If so, it MUST call `onERC1155Received` on `_to` and revert if the return value is not `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`.", + "params": { + "data": "Additional data with no specified format, sent in call to `_to`", + "from": "Source address", + "id": "ID of the token type", + "to": "Target address", + "value": "Transfer amount" + } + }, + "setApprovalForAll(address,bool)": { + "details": "MUST emit the ApprovalForAll event on success.", + "params": { + "approved": "True if the operator is approved, false to revoke approval", + "operator": "Address to add to the set of authorized operators" + } + } + } + }, + "evm": { + "bytecode": { + "object": "0x608060405234801561001057600080fd5b506125ef806100206000396000f3fe608060405234801561001057600080fd5b50600436106101765760003560e01c80639f4b286a116100d8578063e0a5c9491161008c578063f242432a11610066578063f242432a146107bb578063f94190881461085d578063fc67bf1c146108d457610176565b8063e0a5c94914610726578063e44591f014610763578063e985e9c51461078057610176565b8063adebf6f2116100bd578063adebf6f21461067a578063cc10e40114610697578063cd53d08e1461070957610176565b80639f4b286a146105c8578063a22cb4651461063f57610176565b80636352211e1161012f5780637269a327116101145780637269a327146104c557806378b27221146104e25780639cca1c64146105ab57610176565b80636352211e146104625780636f969c2d146104a857610176565b80632eb2c2d6116101605780632eb2c2d6146101e35780634e1273f41461031f5780635e81b9581461043157610176565b8062fdd58e1461017b57806308d7d469146101c6575b600080fd5b6101b46004803603604081101561019157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356108dc565b60408051918252519081900360200190f35b6101b4600480360360208110156101dc57600080fd5b5035610966565b61031d600480360360a08110156101f957600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169181019060608101604082013564010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184602083028401116401000000008311171561026e57600080fd5b91939092909160208101903564010000000081111561028c57600080fd5b82018360208201111561029e57600080fd5b803590602001918460208302840111640100000000831117156102c057600080fd5b9193909290916020810190356401000000008111156102de57600080fd5b8201836020820111156102f057600080fd5b8035906020019184600183028401116401000000008311171561031257600080fd5b509092509050610978565b005b6103e16004803603604081101561033557600080fd5b81019060208101813564010000000081111561035057600080fd5b82018360208201111561036257600080fd5b8035906020019184602083028401116401000000008311171561038457600080fd5b9193909290916020810190356401000000008111156103a257600080fd5b8201836020820111156103b457600080fd5b803590602001918460208302840111640100000000831117156103d657600080fd5b509092509050611192565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561041d578181015183820152602001610405565b505050509050019250505060405180910390f35b61044e6004803603602081101561044757600080fd5b5035611357565b604080519115158252519081900360200190f35b61047f6004803603602081101561047857600080fd5b503561139d565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6101b4600480360360208110156104be57600080fd5b50356113c5565b61044e600480360360208110156104db57600080fd5b50356113ea565b61031d600480360360608110156104f857600080fd5b8135919081019060408101602082013564010000000081111561051a57600080fd5b82018360208201111561052c57600080fd5b8035906020019184602083028401116401000000008311171561054e57600080fd5b91939092909160208101903564010000000081111561056c57600080fd5b82018360208201111561057e57600080fd5b803590602001918460208302840111640100000000831117156105a057600080fd5b50909250905061142f565b6101b4600480360360208110156105c157600080fd5b5035611760565b61031d600480360360408110156105de57600080fd5b8135919081019060408101602082013564010000000081111561060057600080fd5b82018360208201111561061257600080fd5b8035906020019184600183028401116401000000008311171561063457600080fd5b509092509050611775565b61031d6004803603604081101561065557600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001351515611875565b61044e6004803603602081101561069057600080fd5b503561190e565b6101b4600480360360408110156106ad57600080fd5b8101906020810181356401000000008111156106c857600080fd5b8201836020820111156106da57600080fd5b803590602001918460018302840111640100000000831117156106fc57600080fd5b9193509150351515611934565b61047f6004803603602081101561071f57600080fd5b5035611a6d565b61072e611a95565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b61044e6004803603602081101561077957600080fd5b5035611ab9565b61044e6004803603604081101561079657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516611ae1565b61031d600480360360a08110156107d157600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359181019060a08101608082013564010000000081111561081e57600080fd5b82018360208201111561083057600080fd5b8035906020019184600183028401116401000000008311171561085257600080fd5b509092509050611b1c565b61031d6004803603604081101561087357600080fd5b8135919081019060408101602082013564010000000081111561089557600080fd5b8201836020820111156108a757600080fd5b803590602001918460208302840111640100000000831117156108c957600080fd5b5090925090506120fb565b61072e61242b565b60006108e782611357565b1561092e5760008281526020819052604090205473ffffffffffffffffffffffffffffffffffffffff848116911614610921576000610924565b60015b60ff169050610960565b50600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020545b92915050565b60056020526000908152604090205481565b73ffffffffffffffffffffffffffffffffffffffff87166109fa57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f43414e4e4f545f5452414e534645525f544f5f414444524553535f5a45524f00604482015290519081900360640190fd5b848314610a6857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f544f4b454e5f414e445f56414c5545535f4c454e4754485f4d49534d41544348604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8816331480610ac1575073ffffffffffffffffffffffffffffffffffffffff8816600090815260026020908152604080832033845290915290205460ff1615156001145b610b2c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f494e53554646494349454e545f414c4c4f57414e434500000000000000000000604482015290519081900360640190fd5b60005b85811015610deb576000878783818110610b4557fe5b9050602002013590506000868684818110610b5c57fe5b905060200201359050610b6e82611ab9565b15610cc85780600114610be257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f414d4f554e545f455155414c5f544f5f4f4e455f524551554952454400000000604482015290519081900360640190fd5b60008281526020819052604090205473ffffffffffffffffffffffffffffffffffffffff8c8116911614610c7757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4e46545f4e4f545f4f574e45445f42595f46524f4d5f41444452455353000000604482015290519081900360640190fd5b600082815260208190526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8c16179055610de1565b600082815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8f168452909152902054610d02908261244f565b6001600084815260200190815260200160002060008d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610db06001600084815260200190815260200160002060008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482612473565b600083815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8f1684529091529020555b5050600101610b2f565b508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb898989896040518080602001806020018381038352878782818152602001925060200280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169091018481038352858152602090810191508690860280828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039850909650505050505050a4610f1f8773ffffffffffffffffffffffffffffffffffffffff1661248f565b156111885760008773ffffffffffffffffffffffffffffffffffffffff1663bc197c81338b8a8a8a8a8a8a6040518963ffffffff1660e01b8152600401808973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018060200184810384528a8a82818152602001925060200280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169091018581038452888152602090810191508990890280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910185810383528681526020019050868680828437600081840152601f19601f8201169050808301925050509b505050505050505050505050602060405180830381600087803b1580156110a857600080fd5b505af11580156110bc573d6000803e3d6000fd5b505050506040513d60208110156110d257600080fd5b505190507fffffffff0000000000000000000000000000000000000000000000000000000081167fbc197c81000000000000000000000000000000000000000000000000000000001461118657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4241445f52454345495645525f52455455524e5f56414c554500000000000000604482015290519081900360640190fd5b505b5050505050505050565b60608382146111ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061256a6024913960400191505060405180910390fd5b604080518581526020808702820101909152848015611215578160200160208202803883390190505b50905060005b8481101561134e57600084848381811061123157fe5b90506020020135905061124381611357565b156112b95786868381811061125457fe5b600084815260208181526040909120549102929092013573ffffffffffffffffffffffffffffffffffffffff9081169216919091149050611296576000611299565b60015b60ff168383815181106112a857fe5b602002602001018181525050611345565b6000818152600160205260408120908888858181106112d457fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205483838151811061133857fe5b6020026020010181815250505b5060010161121b565b50949350505050565b60007f80000000000000000000000000000000000000000000000000000000000000008083161480156109605750506fffffffffffffffffffffffffffffffff16151590565b60009081526020819052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000001690565b60007f80000000000000000000000000000000000000000000000000000000000000008083161480156109605750506fffffffffffffffffffffffffffffffff161590565b600085815260046020526040902054859073ffffffffffffffffffffffffffffffffffffffff16331461146157600080fd5b61146a8661190e565b6114bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d81526020018061258e602d913960400191505060405180910390fd5b60005b848110156117575760008686838181106114d857fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff169050600085858481811061150557fe5b60008c815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8916845282529091205491029290920135925061154a91839150612473565b60008a815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083528184209490945580518d8152918201859052805133927fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6292908290030190a46115d68273ffffffffffffffffffffffffffffffffffffffff1661248f565b1561174d57604080517ff23a6e6100000000000000000000000000000000000000000000000000000000815233600482018190526024820152604481018b90526064810183905260a06084820152600060a48201819052915173ffffffffffffffffffffffffffffffffffffffff85169163f23a6e619160e480830192602092919082900301818787803b15801561166d57600080fd5b505af1158015611681573d6000803e3d6000fd5b505050506040513d602081101561169757600080fd5b505190507fffffffff0000000000000000000000000000000000000000000000000000000081167ff23a6e61000000000000000000000000000000000000000000000000000000001461174b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4241445f52454345495645525f52455455524e5f56414c554500000000000000604482015290519081900360640190fd5b505b50506001016114c2565b50505050505050565b6fffffffffffffffffffffffffffffffff1690565b600083815260046020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163390811790915581518781529283018490528151849391927fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62928290030190a4801561187057827f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b838360405180806020018281038252848482818152602001925080828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039550909350505050a25b505050565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b7f8000000000000000000000000000000000000000000000000000000000000000161590565b600380546001019081905560801b811561196b577f8000000000000000000000000000000000000000000000000000000000000000175b600081815260046020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163390811790915581518581529283018490528151849391927fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62928290030190a48215611a6657807f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b858560405180806020018281038252848482818152602001925080828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039550909350505050a25b9392505050565b60046020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b7ff23a6e610000000000000000000000000000000000000000000000000000000081565b7f80000000000000000000000000000000000000000000000000000000000000009081161490565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260026020908152604080832093909416825291909152205460ff1690565b73ffffffffffffffffffffffffffffffffffffffff8516611b9e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f43414e4e4f545f5452414e534645525f544f5f414444524553535f5a45524f00604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8616331480611bf7575073ffffffffffffffffffffffffffffffffffffffff8616600090815260026020908152604080832033845290915290205460ff1615156001145b611c6257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f494e53554646494349454e545f414c4c4f57414e434500000000000000000000604482015290519081900360640190fd5b611c6b84611ab9565b15611dc55782600114611cdf57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f414d4f554e545f455155414c5f544f5f4f4e455f524551554952454400000000604482015290519081900360640190fd5b60008481526020819052604090205473ffffffffffffffffffffffffffffffffffffffff878116911614611d7457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4e46545f4e4f545f4f574e45445f42595f46524f4d5f41444452455353000000604482015290519081900360640190fd5b600084815260208190526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8716179055611e74565b600084815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8a168452909152902054611dff908461244f565b600085815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8b81168552925280832093909355871681522054611e439084612473565b600085815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8a1684529091529020555b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628787604051808381526020018281526020019250505060405180910390a4611f178573ffffffffffffffffffffffffffffffffffffffff1661248f565b156120f35760008573ffffffffffffffffffffffffffffffffffffffff1663f23a6e613389888888886040518763ffffffff1660e01b8152600401808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050975050505050505050602060405180830381600087803b15801561201557600080fd5b505af1158015612029573d6000803e3d6000fd5b505050506040513d602081101561203f57600080fd5b505190507fffffffff0000000000000000000000000000000000000000000000000000000081167ff23a6e61000000000000000000000000000000000000000000000000000000001461175757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4241445f52454345495645525f52455455524e5f56414c554500000000000000604482015290519081900360640190fd5b505050505050565b600083815260046020526040902054839073ffffffffffffffffffffffffffffffffffffffff16331461212d57600080fd5b61213684611ab9565b61218b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d81526020018061253d602d913960400191505060405180910390fd5b600084815260056020526040812054600101905b838110156123f75760008585838181106121b557fe5b8486018a176000818152602081815260408083208054958302979097013573ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffff00000000000000000000000000000000000000009095168517909655855183815260019181019190915285519396509194869450909233927fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6292908290030190a46122768273ffffffffffffffffffffffffffffffffffffffff1661248f565b156123ed57604080517ff23a6e6100000000000000000000000000000000000000000000000000000000815233600482018190526024820152604481018390526001606482015260a06084820152600060a48201819052915173ffffffffffffffffffffffffffffffffffffffff85169163f23a6e619160e480830192602092919082900301818787803b15801561230d57600080fd5b505af1158015612321573d6000803e3d6000fd5b505050506040513d602081101561233757600080fd5b505190507fffffffff0000000000000000000000000000000000000000000000000000000081167ff23a6e6100000000000000000000000000000000000000000000000000000000146123eb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4241445f52454345495645525f52455455524e5f56414c554500000000000000604482015290519081900360640190fd5b505b505060010161219f565b50600085815260056020526040902054612412908490612473565b6000958652600560205260409095209490945550505050565b7fbc197c810000000000000000000000000000000000000000000000000000000081565b60008282111561246d5761246d61246860028585612495565b612534565b50900390565b600082820183811015611a6657611a6661246860008686612495565b3b151590565b606063e946c1bb60e01b848484604051602401808460038111156124b557fe5b60ff1681526020018381526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090509392505050565b805160208201fdfe54524945445f544f5f4d494e545f4e4f4e5f46554e4749424c455f464f525f46554e4749424c455f544f4b454e4f574e4552535f414e445f4944535f4d5553545f484156455f53414d455f4c454e47544854524945445f544f5f4d494e545f46554e4749424c455f464f525f4e4f4e5f46554e4749424c455f544f4b454ea265627a7a723158205af7d187cbffb255b374d24e5838a04f6b3a3245622025907396b2a61f9d93da64736f6c634300050c0032" + }, + "deployedBytecode": { + "object": "0x608060405234801561001057600080fd5b50600436106101765760003560e01c80639f4b286a116100d8578063e0a5c9491161008c578063f242432a11610066578063f242432a146107bb578063f94190881461085d578063fc67bf1c146108d457610176565b8063e0a5c94914610726578063e44591f014610763578063e985e9c51461078057610176565b8063adebf6f2116100bd578063adebf6f21461067a578063cc10e40114610697578063cd53d08e1461070957610176565b80639f4b286a146105c8578063a22cb4651461063f57610176565b80636352211e1161012f5780637269a327116101145780637269a327146104c557806378b27221146104e25780639cca1c64146105ab57610176565b80636352211e146104625780636f969c2d146104a857610176565b80632eb2c2d6116101605780632eb2c2d6146101e35780634e1273f41461031f5780635e81b9581461043157610176565b8062fdd58e1461017b57806308d7d469146101c6575b600080fd5b6101b46004803603604081101561019157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356108dc565b60408051918252519081900360200190f35b6101b4600480360360208110156101dc57600080fd5b5035610966565b61031d600480360360a08110156101f957600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169181019060608101604082013564010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184602083028401116401000000008311171561026e57600080fd5b91939092909160208101903564010000000081111561028c57600080fd5b82018360208201111561029e57600080fd5b803590602001918460208302840111640100000000831117156102c057600080fd5b9193909290916020810190356401000000008111156102de57600080fd5b8201836020820111156102f057600080fd5b8035906020019184600183028401116401000000008311171561031257600080fd5b509092509050610978565b005b6103e16004803603604081101561033557600080fd5b81019060208101813564010000000081111561035057600080fd5b82018360208201111561036257600080fd5b8035906020019184602083028401116401000000008311171561038457600080fd5b9193909290916020810190356401000000008111156103a257600080fd5b8201836020820111156103b457600080fd5b803590602001918460208302840111640100000000831117156103d657600080fd5b509092509050611192565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561041d578181015183820152602001610405565b505050509050019250505060405180910390f35b61044e6004803603602081101561044757600080fd5b5035611357565b604080519115158252519081900360200190f35b61047f6004803603602081101561047857600080fd5b503561139d565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6101b4600480360360208110156104be57600080fd5b50356113c5565b61044e600480360360208110156104db57600080fd5b50356113ea565b61031d600480360360608110156104f857600080fd5b8135919081019060408101602082013564010000000081111561051a57600080fd5b82018360208201111561052c57600080fd5b8035906020019184602083028401116401000000008311171561054e57600080fd5b91939092909160208101903564010000000081111561056c57600080fd5b82018360208201111561057e57600080fd5b803590602001918460208302840111640100000000831117156105a057600080fd5b50909250905061142f565b6101b4600480360360208110156105c157600080fd5b5035611760565b61031d600480360360408110156105de57600080fd5b8135919081019060408101602082013564010000000081111561060057600080fd5b82018360208201111561061257600080fd5b8035906020019184600183028401116401000000008311171561063457600080fd5b509092509050611775565b61031d6004803603604081101561065557600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001351515611875565b61044e6004803603602081101561069057600080fd5b503561190e565b6101b4600480360360408110156106ad57600080fd5b8101906020810181356401000000008111156106c857600080fd5b8201836020820111156106da57600080fd5b803590602001918460018302840111640100000000831117156106fc57600080fd5b9193509150351515611934565b61047f6004803603602081101561071f57600080fd5b5035611a6d565b61072e611a95565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b61044e6004803603602081101561077957600080fd5b5035611ab9565b61044e6004803603604081101561079657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516611ae1565b61031d600480360360a08110156107d157600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359181019060a08101608082013564010000000081111561081e57600080fd5b82018360208201111561083057600080fd5b8035906020019184600183028401116401000000008311171561085257600080fd5b509092509050611b1c565b61031d6004803603604081101561087357600080fd5b8135919081019060408101602082013564010000000081111561089557600080fd5b8201836020820111156108a757600080fd5b803590602001918460208302840111640100000000831117156108c957600080fd5b5090925090506120fb565b61072e61242b565b60006108e782611357565b1561092e5760008281526020819052604090205473ffffffffffffffffffffffffffffffffffffffff848116911614610921576000610924565b60015b60ff169050610960565b50600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020545b92915050565b60056020526000908152604090205481565b73ffffffffffffffffffffffffffffffffffffffff87166109fa57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f43414e4e4f545f5452414e534645525f544f5f414444524553535f5a45524f00604482015290519081900360640190fd5b848314610a6857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f544f4b454e5f414e445f56414c5545535f4c454e4754485f4d49534d41544348604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8816331480610ac1575073ffffffffffffffffffffffffffffffffffffffff8816600090815260026020908152604080832033845290915290205460ff1615156001145b610b2c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f494e53554646494349454e545f414c4c4f57414e434500000000000000000000604482015290519081900360640190fd5b60005b85811015610deb576000878783818110610b4557fe5b9050602002013590506000868684818110610b5c57fe5b905060200201359050610b6e82611ab9565b15610cc85780600114610be257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f414d4f554e545f455155414c5f544f5f4f4e455f524551554952454400000000604482015290519081900360640190fd5b60008281526020819052604090205473ffffffffffffffffffffffffffffffffffffffff8c8116911614610c7757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4e46545f4e4f545f4f574e45445f42595f46524f4d5f41444452455353000000604482015290519081900360640190fd5b600082815260208190526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8c16179055610de1565b600082815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8f168452909152902054610d02908261244f565b6001600084815260200190815260200160002060008d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610db06001600084815260200190815260200160002060008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482612473565b600083815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8f1684529091529020555b5050600101610b2f565b508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb898989896040518080602001806020018381038352878782818152602001925060200280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169091018481038352858152602090810191508690860280828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039850909650505050505050a4610f1f8773ffffffffffffffffffffffffffffffffffffffff1661248f565b156111885760008773ffffffffffffffffffffffffffffffffffffffff1663bc197c81338b8a8a8a8a8a8a6040518963ffffffff1660e01b8152600401808973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018060200184810384528a8a82818152602001925060200280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169091018581038452888152602090810191508990890280828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910185810383528681526020019050868680828437600081840152601f19601f8201169050808301925050509b505050505050505050505050602060405180830381600087803b1580156110a857600080fd5b505af11580156110bc573d6000803e3d6000fd5b505050506040513d60208110156110d257600080fd5b505190507fffffffff0000000000000000000000000000000000000000000000000000000081167fbc197c81000000000000000000000000000000000000000000000000000000001461118657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4241445f52454345495645525f52455455524e5f56414c554500000000000000604482015290519081900360640190fd5b505b5050505050505050565b60608382146111ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061256a6024913960400191505060405180910390fd5b604080518581526020808702820101909152848015611215578160200160208202803883390190505b50905060005b8481101561134e57600084848381811061123157fe5b90506020020135905061124381611357565b156112b95786868381811061125457fe5b600084815260208181526040909120549102929092013573ffffffffffffffffffffffffffffffffffffffff9081169216919091149050611296576000611299565b60015b60ff168383815181106112a857fe5b602002602001018181525050611345565b6000818152600160205260408120908888858181106112d457fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205483838151811061133857fe5b6020026020010181815250505b5060010161121b565b50949350505050565b60007f80000000000000000000000000000000000000000000000000000000000000008083161480156109605750506fffffffffffffffffffffffffffffffff16151590565b60009081526020819052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000001690565b60007f80000000000000000000000000000000000000000000000000000000000000008083161480156109605750506fffffffffffffffffffffffffffffffff161590565b600085815260046020526040902054859073ffffffffffffffffffffffffffffffffffffffff16331461146157600080fd5b61146a8661190e565b6114bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d81526020018061258e602d913960400191505060405180910390fd5b60005b848110156117575760008686838181106114d857fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff169050600085858481811061150557fe5b60008c815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8916845282529091205491029290920135925061154a91839150612473565b60008a815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083528184209490945580518d8152918201859052805133927fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6292908290030190a46115d68273ffffffffffffffffffffffffffffffffffffffff1661248f565b1561174d57604080517ff23a6e6100000000000000000000000000000000000000000000000000000000815233600482018190526024820152604481018b90526064810183905260a06084820152600060a48201819052915173ffffffffffffffffffffffffffffffffffffffff85169163f23a6e619160e480830192602092919082900301818787803b15801561166d57600080fd5b505af1158015611681573d6000803e3d6000fd5b505050506040513d602081101561169757600080fd5b505190507fffffffff0000000000000000000000000000000000000000000000000000000081167ff23a6e61000000000000000000000000000000000000000000000000000000001461174b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4241445f52454345495645525f52455455524e5f56414c554500000000000000604482015290519081900360640190fd5b505b50506001016114c2565b50505050505050565b6fffffffffffffffffffffffffffffffff1690565b600083815260046020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163390811790915581518781529283018490528151849391927fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62928290030190a4801561187057827f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b838360405180806020018281038252848482818152602001925080828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039550909350505050a25b505050565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b7f8000000000000000000000000000000000000000000000000000000000000000161590565b600380546001019081905560801b811561196b577f8000000000000000000000000000000000000000000000000000000000000000175b600081815260046020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163390811790915581518581529283018490528151849391927fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62928290030190a48215611a6657807f6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b858560405180806020018281038252848482818152602001925080828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039550909350505050a25b9392505050565b60046020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b7ff23a6e610000000000000000000000000000000000000000000000000000000081565b7f80000000000000000000000000000000000000000000000000000000000000009081161490565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260026020908152604080832093909416825291909152205460ff1690565b73ffffffffffffffffffffffffffffffffffffffff8516611b9e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f43414e4e4f545f5452414e534645525f544f5f414444524553535f5a45524f00604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8616331480611bf7575073ffffffffffffffffffffffffffffffffffffffff8616600090815260026020908152604080832033845290915290205460ff1615156001145b611c6257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f494e53554646494349454e545f414c4c4f57414e434500000000000000000000604482015290519081900360640190fd5b611c6b84611ab9565b15611dc55782600114611cdf57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f414d4f554e545f455155414c5f544f5f4f4e455f524551554952454400000000604482015290519081900360640190fd5b60008481526020819052604090205473ffffffffffffffffffffffffffffffffffffffff878116911614611d7457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4e46545f4e4f545f4f574e45445f42595f46524f4d5f41444452455353000000604482015290519081900360640190fd5b600084815260208190526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8716179055611e74565b600084815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8a168452909152902054611dff908461244f565b600085815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8b81168552925280832093909355871681522054611e439084612473565b600085815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8a1684529091529020555b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628787604051808381526020018281526020019250505060405180910390a4611f178573ffffffffffffffffffffffffffffffffffffffff1661248f565b156120f35760008573ffffffffffffffffffffffffffffffffffffffff1663f23a6e613389888888886040518763ffffffff1660e01b8152600401808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050975050505050505050602060405180830381600087803b15801561201557600080fd5b505af1158015612029573d6000803e3d6000fd5b505050506040513d602081101561203f57600080fd5b505190507fffffffff0000000000000000000000000000000000000000000000000000000081167ff23a6e61000000000000000000000000000000000000000000000000000000001461175757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4241445f52454345495645525f52455455524e5f56414c554500000000000000604482015290519081900360640190fd5b505050505050565b600083815260046020526040902054839073ffffffffffffffffffffffffffffffffffffffff16331461212d57600080fd5b61213684611ab9565b61218b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d81526020018061253d602d913960400191505060405180910390fd5b600084815260056020526040812054600101905b838110156123f75760008585838181106121b557fe5b8486018a176000818152602081815260408083208054958302979097013573ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffff00000000000000000000000000000000000000009095168517909655855183815260019181019190915285519396509194869450909233927fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6292908290030190a46122768273ffffffffffffffffffffffffffffffffffffffff1661248f565b156123ed57604080517ff23a6e6100000000000000000000000000000000000000000000000000000000815233600482018190526024820152604481018390526001606482015260a06084820152600060a48201819052915173ffffffffffffffffffffffffffffffffffffffff85169163f23a6e619160e480830192602092919082900301818787803b15801561230d57600080fd5b505af1158015612321573d6000803e3d6000fd5b505050506040513d602081101561233757600080fd5b505190507fffffffff0000000000000000000000000000000000000000000000000000000081167ff23a6e6100000000000000000000000000000000000000000000000000000000146123eb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4241445f52454345495645525f52455455524e5f56414c554500000000000000604482015290519081900360640190fd5b505b505060010161219f565b50600085815260056020526040902054612412908490612473565b6000958652600560205260409095209490945550505050565b7fbc197c810000000000000000000000000000000000000000000000000000000081565b60008282111561246d5761246d61246860028585612495565b612534565b50900390565b600082820183811015611a6657611a6661246860008686612495565b3b151590565b606063e946c1bb60e01b848484604051602401808460038111156124b557fe5b60ff1681526020018381526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090509392505050565b805160208201fdfe54524945445f544f5f4d494e545f4e4f4e5f46554e4749424c455f464f525f46554e4749424c455f544f4b454e4f574e4552535f414e445f4944535f4d5553545f484156455f53414d455f4c454e47544854524945445f544f5f4d494e545f46554e4749424c455f464f525f4e4f4e5f46554e4749424c455f544f4b454ea265627a7a723158205af7d187cbffb255b374d24e5838a04f6b3a3245622025907396b2a61f9d93da64736f6c634300050c0032" + } + } + }, + "compiler": { + "name": "solc", + "version": "soljson-v0.5.12+commit.7709ece9.js", + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000000, + "details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true } + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "devdoc", + "evm.bytecode.object", + "evm.bytecode.sourceMap", + "evm.deployedBytecode.object", + "evm.deployedBytecode.sourceMap" + ] + } + }, + "evmVersion": "constantinople" + } + }, + "networks": {} +} diff --git a/packages/contract-artifacts/src/index.ts b/packages/contract-artifacts/src/index.ts index a1a5db3b8d..7917b556b7 100644 --- a/packages/contract-artifacts/src/index.ts +++ b/packages/contract-artifacts/src/index.ts @@ -5,6 +5,7 @@ import * as DevUtils from '../artifacts/DevUtils.json'; import * as DummyERC20Token from '../artifacts/DummyERC20Token.json'; import * as DummyERC721Token from '../artifacts/DummyERC721Token.json'; import * as DutchAuction from '../artifacts/DutchAuction.json'; +import * as ERC1155Mintable from '../artifacts/ERC1155Mintable.json'; import * as ERC1155Proxy from '../artifacts/ERC1155Proxy.json'; import * as ERC20Proxy from '../artifacts/ERC20Proxy.json'; import * as ERC20Token from '../artifacts/ERC20Token.json'; @@ -28,6 +29,7 @@ export { DevUtils, DummyERC20Token, DummyERC721Token, + ERC1155Mintable, ERC1155Proxy, ERC20Proxy, ERC20Token, diff --git a/packages/contract-artifacts/tsconfig.json b/packages/contract-artifacts/tsconfig.json index 7d339682c3..6dcc87100e 100644 --- a/packages/contract-artifacts/tsconfig.json +++ b/packages/contract-artifacts/tsconfig.json @@ -12,6 +12,7 @@ "./artifacts/DutchAuction.json", "./artifacts/DummyERC20Token.json", "./artifacts/DummyERC721Token.json", + "./artifacts/ERC1155Mintable.json", "./artifacts/ERC20Proxy.json", "./artifacts/ERC20Token.json", "./artifacts/ERC721Proxy.json", From 727d0498b6f9db7aba0e402040c733c94c0b450d Mon Sep 17 00:00:00 2001 From: fabioberger Date: Wed, 16 Oct 2019 22:52:47 +0900 Subject: [PATCH 84/87] Export ERC1155Mintable from abi-gen-wrapper --- packages/abi-gen-wrappers/src/index.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/abi-gen-wrappers/src/index.ts b/packages/abi-gen-wrappers/src/index.ts index 31a9875352..d0c5f1f991 100644 --- a/packages/abi-gen-wrappers/src/index.ts +++ b/packages/abi-gen-wrappers/src/index.ts @@ -30,6 +30,13 @@ export { DummyERC721TokenApprovalForAllEventArgs, DummyERC721TokenContract, } from './generated-wrappers/dummy_erc721_token'; +export { + ERC1155MintableContract, + ERC1155MintableApprovalForAllEventArgs, + ERC1155MintableTransferBatchEventArgs, + ERC1155MintableTransferSingleEventArgs, + ERC1155MintableURIEventArgs, +} from './generated-wrappers/erc1155_mintable'; export { DutchAuctionContract } from './generated-wrappers/dutch_auction'; export { ERC1155ProxyEventArgs, From eae40016226ab70585e9fdcf061158eb607a05fb Mon Sep 17 00:00:00 2001 From: fabioberger Date: Wed, 16 Oct 2019 22:53:12 +0900 Subject: [PATCH 85/87] Update ganache-cli version in migration dockerfile --- packages/migrations/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/migrations/Dockerfile b/packages/migrations/Dockerfile index 80586edabf..05f8cca30f 100644 --- a/packages/migrations/Dockerfile +++ b/packages/migrations/Dockerfile @@ -2,7 +2,7 @@ FROM mhart/alpine-node:10 WORKDIR /usr/src/app -RUN npm install -g ganache-cli@6.4.1 +RUN npm install -g ganache-cli@6.7.0 ENV MNEMONIC "concert load couple harbor equip island argue ramp clarify fence smart topic" ENV NETWORK_ID 50 From 2dbda6fc42dfc70cb28603b0c04c5f2a0862a3fd Mon Sep 17 00:00:00 2001 From: fabioberger Date: Wed, 16 Oct 2019 22:53:25 +0900 Subject: [PATCH 86/87] Deploy ERC1155Mintable in migration --- packages/migrations/src/migration.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/migrations/src/migration.ts b/packages/migrations/src/migration.ts index db3a1a7239..1b36128f20 100644 --- a/packages/migrations/src/migration.ts +++ b/packages/migrations/src/migration.ts @@ -300,6 +300,14 @@ export async function runMigrationsAsync( exchange.address, ); + // tslint:disable-next-line:no-unused-variable + const erc1155DummyToken = await wrappers.ERC1155MintableContract.deployFrom0xArtifactAsync( + artifacts.ERC1155Mintable, + provider, + txDefaults, + artifacts, + ); + const contractAddresses = { erc20Proxy: erc20Proxy.address, erc721Proxy: erc721Proxy.address, From 9114510c00dc5cf5def44edd6cdee12722370c4e Mon Sep 17 00:00:00 2001 From: fabioberger Date: Thu, 17 Oct 2019 11:29:36 +0900 Subject: [PATCH 87/87] Add enum-naming linter ignore to wrappers to fix linter issue with `URL` in ERC1155Mintable --- .../src/generated-wrappers/asset_proxy_owner.ts | 2 +- packages/abi-gen-wrappers/src/generated-wrappers/coordinator.ts | 2 +- .../src/generated-wrappers/coordinator_registry.ts | 2 +- packages/abi-gen-wrappers/src/generated-wrappers/dev_utils.ts | 2 +- .../src/generated-wrappers/dummy_erc20_token.ts | 2 +- .../src/generated-wrappers/dummy_erc721_token.ts | 2 +- .../abi-gen-wrappers/src/generated-wrappers/dutch_auction.ts | 2 +- .../abi-gen-wrappers/src/generated-wrappers/erc1155_mintable.ts | 2 +- .../abi-gen-wrappers/src/generated-wrappers/erc1155_proxy.ts | 2 +- packages/abi-gen-wrappers/src/generated-wrappers/erc20_proxy.ts | 2 +- packages/abi-gen-wrappers/src/generated-wrappers/erc20_token.ts | 2 +- .../abi-gen-wrappers/src/generated-wrappers/erc721_proxy.ts | 2 +- .../abi-gen-wrappers/src/generated-wrappers/erc721_token.ts | 2 +- .../src/generated-wrappers/eth_balance_checker.ts | 2 +- packages/abi-gen-wrappers/src/generated-wrappers/exchange.ts | 2 +- packages/abi-gen-wrappers/src/generated-wrappers/forwarder.ts | 2 +- .../abi-gen-wrappers/src/generated-wrappers/i_asset_proxy.ts | 2 +- packages/abi-gen-wrappers/src/generated-wrappers/i_validator.ts | 2 +- packages/abi-gen-wrappers/src/generated-wrappers/i_wallet.ts | 2 +- .../src/generated-wrappers/multi_asset_proxy.ts | 2 +- .../abi-gen-wrappers/src/generated-wrappers/order_validator.ts | 2 +- .../src/generated-wrappers/static_call_proxy.ts | 2 +- packages/abi-gen-wrappers/src/generated-wrappers/weth9.ts | 2 +- packages/abi-gen-wrappers/src/generated-wrappers/zrx_token.ts | 2 +- packages/abi-gen/templates/TypeScript/contract.handlebars | 2 +- packages/abi-gen/test-cli/output/typescript/abi_gen_dummy.ts | 2 +- packages/abi-gen/test-cli/output/typescript/lib_dummy.ts | 2 +- packages/abi-gen/test-cli/output/typescript/test_lib_dummy.ts | 2 +- 28 files changed, 28 insertions(+), 28 deletions(-) diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/asset_proxy_owner.ts b/packages/abi-gen-wrappers/src/generated-wrappers/asset_proxy_owner.ts index 1e6aee0d1a..9252949b94 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/asset_proxy_owner.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/asset_proxy_owner.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, SubscriptionManager, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/coordinator.ts b/packages/abi-gen-wrappers/src/generated-wrappers/coordinator.ts index 56348dfb51..ff71948443 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/coordinator.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/coordinator.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/coordinator_registry.ts b/packages/abi-gen-wrappers/src/generated-wrappers/coordinator_registry.ts index f76b2ed8a3..103645e98f 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/coordinator_registry.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/coordinator_registry.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, SubscriptionManager, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/dev_utils.ts b/packages/abi-gen-wrappers/src/generated-wrappers/dev_utils.ts index 0f25b73cce..6420fa4849 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/dev_utils.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/dev_utils.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/dummy_erc20_token.ts b/packages/abi-gen-wrappers/src/generated-wrappers/dummy_erc20_token.ts index 6821ab56f8..311a30e135 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/dummy_erc20_token.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/dummy_erc20_token.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, SubscriptionManager, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/dummy_erc721_token.ts b/packages/abi-gen-wrappers/src/generated-wrappers/dummy_erc721_token.ts index 8e78e37b76..bbc525276d 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/dummy_erc721_token.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/dummy_erc721_token.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, SubscriptionManager, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/dutch_auction.ts b/packages/abi-gen-wrappers/src/generated-wrappers/dutch_auction.ts index 7111992209..9489d74f25 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/dutch_auction.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/dutch_auction.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/erc1155_mintable.ts b/packages/abi-gen-wrappers/src/generated-wrappers/erc1155_mintable.ts index 54410c2387..e28018bbac 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/erc1155_mintable.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/erc1155_mintable.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, SubscriptionManager, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/erc1155_proxy.ts b/packages/abi-gen-wrappers/src/generated-wrappers/erc1155_proxy.ts index 8fe2202022..a3a2bf881e 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/erc1155_proxy.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/erc1155_proxy.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, SubscriptionManager, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/erc20_proxy.ts b/packages/abi-gen-wrappers/src/generated-wrappers/erc20_proxy.ts index 59ae25dd46..95cd7444b4 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/erc20_proxy.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/erc20_proxy.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, SubscriptionManager, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/erc20_token.ts b/packages/abi-gen-wrappers/src/generated-wrappers/erc20_token.ts index 1cc9c8e0d0..f8b8109085 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/erc20_token.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/erc20_token.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, SubscriptionManager, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/erc721_proxy.ts b/packages/abi-gen-wrappers/src/generated-wrappers/erc721_proxy.ts index 9f3d13bc8a..d80cd4dd1e 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/erc721_proxy.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/erc721_proxy.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, SubscriptionManager, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/erc721_token.ts b/packages/abi-gen-wrappers/src/generated-wrappers/erc721_token.ts index 883ba300c3..dcb5db41f3 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/erc721_token.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/erc721_token.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, SubscriptionManager, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/eth_balance_checker.ts b/packages/abi-gen-wrappers/src/generated-wrappers/eth_balance_checker.ts index ef8097adfd..4fac46c6b4 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/eth_balance_checker.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/eth_balance_checker.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/exchange.ts b/packages/abi-gen-wrappers/src/generated-wrappers/exchange.ts index 64458c76b3..a168c3df1e 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/exchange.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/exchange.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, SubscriptionManager, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/forwarder.ts b/packages/abi-gen-wrappers/src/generated-wrappers/forwarder.ts index 33a486db3b..ed11ba7808 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/forwarder.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/forwarder.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/i_asset_proxy.ts b/packages/abi-gen-wrappers/src/generated-wrappers/i_asset_proxy.ts index 30aed03216..0383c018a4 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/i_asset_proxy.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/i_asset_proxy.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/i_validator.ts b/packages/abi-gen-wrappers/src/generated-wrappers/i_validator.ts index a1a699fde1..1f97f3f316 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/i_validator.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/i_validator.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/i_wallet.ts b/packages/abi-gen-wrappers/src/generated-wrappers/i_wallet.ts index 29a1001c9b..000d0798b6 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/i_wallet.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/i_wallet.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/multi_asset_proxy.ts b/packages/abi-gen-wrappers/src/generated-wrappers/multi_asset_proxy.ts index 33b681ef8b..857ddaecc9 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/multi_asset_proxy.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/multi_asset_proxy.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, SubscriptionManager, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/order_validator.ts b/packages/abi-gen-wrappers/src/generated-wrappers/order_validator.ts index 9b3d0f6b4e..aadf482932 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/order_validator.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/order_validator.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/static_call_proxy.ts b/packages/abi-gen-wrappers/src/generated-wrappers/static_call_proxy.ts index e1298600cb..c75c4d2457 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/static_call_proxy.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/static_call_proxy.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/weth9.ts b/packages/abi-gen-wrappers/src/generated-wrappers/weth9.ts index 8b9f28a6b3..3d5c5cbf14 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/weth9.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/weth9.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, SubscriptionManager, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/zrx_token.ts b/packages/abi-gen-wrappers/src/generated-wrappers/zrx_token.ts index 0eb90329e6..3586560204 100644 --- a/packages/abi-gen-wrappers/src/generated-wrappers/zrx_token.ts +++ b/packages/abi-gen-wrappers/src/generated-wrappers/zrx_token.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, SubscriptionManager, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen/templates/TypeScript/contract.handlebars b/packages/abi-gen/templates/TypeScript/contract.handlebars index 2c84f35692..2a2d56f845 100644 --- a/packages/abi-gen/templates/TypeScript/contract.handlebars +++ b/packages/abi-gen/templates/TypeScript/contract.handlebars @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract{{#if events}}, diff --git a/packages/abi-gen/test-cli/output/typescript/abi_gen_dummy.ts b/packages/abi-gen/test-cli/output/typescript/abi_gen_dummy.ts index 8b626041d0..702c55dec0 100644 --- a/packages/abi-gen/test-cli/output/typescript/abi_gen_dummy.ts +++ b/packages/abi-gen/test-cli/output/typescript/abi_gen_dummy.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, SubscriptionManager, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen/test-cli/output/typescript/lib_dummy.ts b/packages/abi-gen/test-cli/output/typescript/lib_dummy.ts index bc01ce2d03..39d6a9f45e 100644 --- a/packages/abi-gen/test-cli/output/typescript/lib_dummy.ts +++ b/packages/abi-gen/test-cli/output/typescript/lib_dummy.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; diff --git a/packages/abi-gen/test-cli/output/typescript/test_lib_dummy.ts b/packages/abi-gen/test-cli/output/typescript/test_lib_dummy.ts index edc8830abc..61e5cbe2ef 100644 --- a/packages/abi-gen/test-cli/output/typescript/test_lib_dummy.ts +++ b/packages/abi-gen/test-cli/output/typescript/test_lib_dummy.ts @@ -1,4 +1,4 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming // tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:no-unused-variable import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract';