Merge branch 'development' into refactor/reduceContractPkgBundle

This commit is contained in:
fabioberger 2019-11-11 21:00:36 +00:00
commit 67e7b5c124
56 changed files with 263 additions and 13708 deletions

View File

@ -219,7 +219,7 @@ jobs:
- image: 0xorg/launch-kit-backend:v3
environment:
RPC_URL: 'http://localhost:8545'
NETWORK_ID: 50
CHAIN_ID: 1337
WHITELIST_ALL_TOKENS: True
FEE_RECIPIENT: '0x0000000000000000000000000000000000000001'
MAKER_FEE_UNIT_AMOUNT: 0

1
.gitignore vendored
View File

@ -172,7 +172,6 @@ python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc1155_proxy/__
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_proxy/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc721_proxy/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc721_token/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/eth_balance_checker/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/forwarder/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/i_asset_proxy/__init__.py
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/i_validator/__init__.py

View File

@ -16,11 +16,7 @@ import * as _ from 'lodash';
import { artifacts } from './artifacts';
import {
ERC20BridgeProxyContract,
TestERC20BridgeBridgeWithdrawToEventArgs,
TestERC20BridgeContract,
} from './wrappers';
import { ERC20BridgeProxyContract, TestERC20BridgeContract } from './wrappers';
blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
const PROXY_ID = AssetProxyId.ERC20Bridge;
@ -165,7 +161,7 @@ blockchainTests.resets('ERC20BridgeProxy unit tests', env => {
const opts = createTransferFromOpts();
const logs = await transferFromAsync(opts);
expect(logs.length).to.eq(1);
const args = logs[0].args as TestERC20BridgeBridgeWithdrawToEventArgs;
const args = logs[0].args;
expect(args.tokenAddress).to.eq(opts.assetData.tokenAddress);
expect(args.from).to.eq(opts.from);
expect(args.to).to.eq(opts.to);

View File

@ -1,29 +1,22 @@
import {
DevUtilsContract,
DummyERC20TokenContract,
ERC20ProxyContract,
ERC20TokenContract,
} from '@0x/abi-gen-wrappers';
import * as artifacts from '@0x/contract-artifacts';
import { BlockchainLifecycle, devConstants } from '@0x/dev-utils';
import { artifacts as assetProxyArtifacts, ERC20ProxyContract } from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { artifacts as erc20Artifacts, DummyERC20TokenContract, ERC20TokenContract } from '@0x/contracts-erc20';
import { blockchainTests, chaiSetup, constants } from '@0x/contracts-test-utils';
import { ExchangeContractErrs } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import { constants } from '../src/constants';
import { ExchangeTransferSimulator } from '../src/exchange_transfer_simulator';
import { BalanceAndProxyAllowanceLazyStore } from '../src/store/balance_and_proxy_allowance_lazy_store';
import { TradeSide, TransferType } from '../src/types';
import { chaiSetup } from './utils/chai_setup';
import { ExchangeTransferSimulator } from './utils/exchange_transfer_simulator';
import { SimpleERC20BalanceAndProxyAllowanceFetcher } from './utils/simple_erc20_balance_and_proxy_allowance_fetcher';
import { provider, web3Wrapper } from './utils/web3_wrapper';
import { BalanceAndProxyAllowanceLazyStore } from './utils/store/balance_and_proxy_allowance_lazy_store';
import { TradeSide, TransferType } from './utils/types';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('ExchangeTransferSimulator', async () => {
const GAS_LIMIT = 9e6;
blockchainTests('ExchangeTransferSimulator', env => {
const transferAmount = new BigNumber(5);
let userAddresses: string[];
let dummyERC20Token: DummyERC20TokenContract;
@ -34,25 +27,25 @@ describe('ExchangeTransferSimulator', async () => {
let exchangeTransferSimulator: ExchangeTransferSimulator;
let txHash: string;
let erc20ProxyAddress: string;
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, env.provider);
before(async function(): Promise<void> {
const mochaTestTimeoutMs = 20000;
this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
userAddresses = await env.web3Wrapper.getAvailableAddressesAsync();
[coinbase, sender, recipient] = userAddresses;
const txDefaults = {
gas: devConstants.GAS_LIMIT,
from: devConstants.TESTRPC_FIRST_ADDRESS,
gas: GAS_LIMIT,
from: userAddresses[0],
};
await blockchainLifecycle.startAsync();
await env.blockchainLifecycle.startAsync();
const erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync(
artifacts.ERC20Proxy,
provider,
assetProxyArtifacts.ERC20Proxy,
env.provider,
txDefaults,
artifacts,
assetProxyArtifacts,
);
erc20ProxyAddress = erc20Proxy.address;
@ -62,10 +55,10 @@ describe('ExchangeTransferSimulator', async () => {
const decimals = new BigNumber(18);
// tslint:disable-next-line:no-unused-variable
dummyERC20Token = await DummyERC20TokenContract.deployFrom0xArtifactAsync(
artifacts.DummyERC20Token,
provider,
erc20Artifacts.DummyERC20Token,
env.provider,
txDefaults,
artifacts,
erc20Artifacts,
name,
symbol,
decimals,
@ -75,13 +68,13 @@ describe('ExchangeTransferSimulator', async () => {
exampleAssetData = await devUtils.encodeERC20AssetData.callAsync(dummyERC20Token.address);
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
await env.blockchainLifecycle.startAsync();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
await env.blockchainLifecycle.revertAsync();
});
after(async () => {
await blockchainLifecycle.revertAsync();
await env.blockchainLifecycle.revertAsync();
});
describe('#transferFromAsync', function(): void {
// HACK: For some reason these tests need a slightly longer timeout
@ -95,7 +88,7 @@ describe('ExchangeTransferSimulator', async () => {
const balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore(
simpleERC20BalanceAndProxyAllowanceFetcher,
);
exchangeTransferSimulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore);
exchangeTransferSimulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore, devUtils);
});
it("throws if the user doesn't have enough allowance", async () => {
return expect(
@ -113,7 +106,7 @@ describe('ExchangeTransferSimulator', async () => {
txHash = await dummyERC20Token.approve.sendTransactionAsync(erc20ProxyAddress, transferAmount, {
from: sender,
});
await web3Wrapper.awaitTransactionSuccessAsync(txHash);
await env.web3Wrapper.awaitTransactionSuccessAsync(txHash);
return expect(
exchangeTransferSimulator.transferFromAsync(
exampleAssetData,
@ -129,12 +122,12 @@ describe('ExchangeTransferSimulator', async () => {
txHash = await dummyERC20Token.transfer.sendTransactionAsync(sender, transferAmount, {
from: coinbase,
});
await web3Wrapper.awaitTransactionSuccessAsync(txHash);
await env.web3Wrapper.awaitTransactionSuccessAsync(txHash);
txHash = await dummyERC20Token.approve.sendTransactionAsync(erc20ProxyAddress, transferAmount, {
from: sender,
});
await web3Wrapper.awaitTransactionSuccessAsync(txHash);
await env.web3Wrapper.awaitTransactionSuccessAsync(txHash);
await exchangeTransferSimulator.transferFromAsync(
exampleAssetData,
@ -156,7 +149,7 @@ describe('ExchangeTransferSimulator', async () => {
txHash = await dummyERC20Token.transfer.sendTransactionAsync(sender, transferAmount, {
from: coinbase,
});
await web3Wrapper.awaitTransactionSuccessAsync(txHash);
await env.web3Wrapper.awaitTransactionSuccessAsync(txHash);
txHash = await dummyERC20Token.approve.sendTransactionAsync(
erc20ProxyAddress,
constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
@ -164,7 +157,7 @@ describe('ExchangeTransferSimulator', async () => {
from: sender,
},
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash);
await env.web3Wrapper.awaitTransactionSuccessAsync(txHash);
await exchangeTransferSimulator.transferFromAsync(
exampleAssetData,
sender,

View File

@ -1,6 +1,11 @@
import { blockchainTests, describe } from '@0x/contracts-test-utils';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { blockchainTests, constants, describe, provider } from '@0x/contracts-test-utils';
import * as _ from 'lodash';
import {
FillOrderCombinatorialUtils,
fillOrderCombinatorialUtilsFactoryAsync,
} from './utils/fill_order_combinatorial_utils';
import {
AllowanceAmountScenario,
AssetDataScenario,
@ -13,11 +18,6 @@ import {
TakerScenario,
} from './utils/fill_order_scenarios';
import {
FillOrderCombinatorialUtils,
fillOrderCombinatorialUtilsFactoryAsync,
} from './utils/fill_order_combinatorial_utils';
const defaultFillScenario = {
orderScenario: {
takerScenario: TakerScenario.Unspecified,
@ -49,8 +49,10 @@ const defaultFillScenario = {
blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
let fillOrderCombinatorialUtils: FillOrderCombinatorialUtils;
let devUtils: DevUtilsContract;
before(async () => {
devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
fillOrderCombinatorialUtils = await fillOrderCombinatorialUtilsFactoryAsync(web3Wrapper, txDefaults);
});
@ -63,7 +65,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
takerAssetAmountScenario: OrderAssetAmountScenario.Small,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should transfer the correct amounts when makerAssetAmount < takerAssetAmount', async () => {
@ -74,7 +76,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
makerAssetAmountScenario: OrderAssetAmountScenario.Small,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should transfer the correct amounts when makerAssetAmount < takerAssetAmount with zero decimals', async () => {
@ -86,7 +88,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
makerAssetDataScenario: AssetDataScenario.ERC20ZeroDecimals,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should transfer the correct amounts when taker is specified and order is claimed by taker', async () => {
@ -97,7 +99,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
takerScenario: TakerScenario.CorrectlySpecified,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should transfer the correct amounts maker == feeRecipient', async () => {
@ -108,7 +110,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeRecipientScenario: FeeRecipientAddressScenario.MakerAddress,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should transfer the correct amounts maker == feeRecipient and makerFeeAsset == takerAsset', async () => {
@ -120,7 +122,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
makerFeeAssetDataScenario: FeeAssetDataScenario.TakerToken,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should transfer the correct amounts taker == feeRecipient', async () => {
@ -131,7 +133,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeRecipientScenario: FeeRecipientAddressScenario.TakerAddress,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should transfer the correct amounts taker == feeRecipient and takerFeeAsset == makerAsset', async () => {
@ -143,7 +145,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
takerFeeAssetDataScenario: FeeAssetDataScenario.MakerToken,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should fill remaining value if takerAssetFillAmount > remaining takerAssetAmount', async () => {
@ -151,7 +153,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
...defaultFillScenario,
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.GreaterThanTakerAssetAmount,
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should revert when taker is specified and order is claimed by other', async () => {
@ -162,7 +164,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
takerScenario: TakerScenario.IncorrectlySpecified,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
it('should revert if makerAssetAmount is 0', async () => {
@ -174,7 +176,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
},
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.GreaterThanTakerAssetAmount,
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
it('should revert if takerAssetAmount is 0', async () => {
@ -186,7 +188,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
},
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.GreaterThanTakerAssetAmount,
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
it('should revert if an order is expired', async () => {
@ -197,7 +199,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
expirationTimeSecondsScenario: ExpirationTimeSecondsScenario.InPast,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
});
@ -217,7 +219,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
takerAssetDataScenario: takerAsset,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
}
it('should be able to pay maker fee with taker asset', async () => {
@ -233,7 +235,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should be able to pay taker fee with maker asset', async () => {
@ -249,7 +251,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should not be able to pay maker fee with maker asset if none is left over (double-spend)', async () => {
@ -266,7 +268,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
it('should not be able to pay taker fee with taker asset if none is left over (double-spend)', async () => {
@ -283,7 +285,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
it('should be able to pay taker fee with maker asset', async () => {
@ -299,7 +301,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should revert if maker balance is too low to fill order', async () => {
@ -310,7 +312,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
traderAssetBalance: BalanceAmountScenario.TooLow,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
it('should revert if taker balance is too low to fill order', async () => {
@ -321,7 +323,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
traderAssetBalance: BalanceAmountScenario.TooLow,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
it('should revert if maker allowances are too low to fill order', async () => {
@ -332,7 +334,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
traderAssetAllowance: AllowanceAmountScenario.TooLow,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
it('should revert if taker allowances are too low to fill order', async () => {
@ -343,7 +345,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
traderAssetAllowance: AllowanceAmountScenario.TooLow,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
it('should revert if maker fee balance is too low to fill order', async () => {
@ -354,7 +356,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.TooLow,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
it('should revert if taker fee balance is too low to fill order', async () => {
@ -365,7 +367,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.TooLow,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
it('should revert if maker fee allowances are too low to fill order', async () => {
@ -376,7 +378,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeAllowance: AllowanceAmountScenario.TooLow,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
it('should revert if taker fee allowances are too low to fill order', async () => {
@ -387,7 +389,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeAllowance: AllowanceAmountScenario.TooLow,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
});
@ -406,7 +408,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should be able to pay taker fee with maker ERC721', async () => {
@ -423,7 +425,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should not be able to pay maker fee with maker ERC721 (double-spend)', async () => {
@ -440,7 +442,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
it('should be able to pay taker fee with taker ERC721 (double-spend)', async () => {
@ -457,7 +459,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
});
@ -479,7 +481,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should be able to pay taker fee with maker asset', async () => {
@ -496,7 +498,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should not be able to pay maker fee with maker asset if not enough left (double-spend)', async () => {
@ -514,7 +516,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
it('should be able to pay taker fee with taker asset if not enough left (double-spend)', async () => {
@ -532,7 +534,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
});
}
@ -553,7 +555,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should be able to pay taker fee with maker MAP', async () => {
@ -570,7 +572,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
it('should not be able to pay maker fee with maker MAP (double-spend)', async () => {
@ -587,7 +589,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
it('should be able to pay taker fee with taker MAP (double-spend)', async () => {
@ -604,7 +606,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
});
});
@ -627,7 +629,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
},
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
}
});
@ -651,7 +653,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
},
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
});
}
});
@ -661,7 +663,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
for (const fillScenario of allFillScenarios) {
const description = `Combinatorial OrderFill: ${JSON.stringify(fillScenario)}`;
it(description, async () => {
await fillOrderCombinatorialUtils.testFillOrderScenarioAsync(fillScenario);
await fillOrderCombinatorialUtils.testFillOrderScenarioAsync(fillScenario, devUtils);
});
}
});

View File

@ -1,4 +1,3 @@
import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
/**
@ -13,10 +12,4 @@ export abstract class AbstractOrderFilledCancelledFetcher {
* @return FilledTakerAmount
*/
public abstract async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber>;
/**
* Whether an order is cancelled
* @param orderHash OrderHash of order we are interested in
* @return Whether or not the order is cancelled
*/
public abstract async isOrderCancelledAsync(signedOrder: SignedOrder): Promise<boolean>;
}

View File

@ -1,9 +1,7 @@
import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
export abstract class AbstractOrderFilledCancelledLazyStore {
public abstract async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber>;
public abstract async getIsCancelledAsync(signedOrder: SignedOrder): Promise<boolean>;
public abstract setFilledTakerAmount(orderHash: string, balance: BigNumber): void;
public abstract deleteFilledTakerAmount(orderHash: string): void;
public abstract setIsCancelled(orderHash: string, isCancelled: boolean): void;

View File

@ -1,4 +1,4 @@
import { DevUtilsContract } from '@0x/abi-gen-wrappers';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';

View File

@ -1,9 +1,9 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { constants } from '@0x/contracts-test-utils';
import { AssetProxyId, ExchangeContractErrs } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { AbstractBalanceAndProxyAllowanceLazyStore } from './abstract/abstract_balance_and_proxy_allowance_lazy_store';
import { assetDataUtils } from './asset_data_utils';
import { constants } from './constants';
import { TradeSide, TransferType } from './types';
enum FailureReason {
@ -40,6 +40,7 @@ const ERR_MSG_MAPPING = {
*/
export class ExchangeTransferSimulator {
private readonly _store: AbstractBalanceAndProxyAllowanceLazyStore;
private readonly _devUtils: DevUtilsContract;
private static _throwValidationError(
failureReason: FailureReason,
tradeSide: TradeSide,
@ -53,8 +54,9 @@ export class ExchangeTransferSimulator {
* @param store A class that implements AbstractBalanceAndProxyAllowanceLazyStore
* @return an instance of ExchangeTransferSimulator
*/
constructor(store: AbstractBalanceAndProxyAllowanceLazyStore) {
constructor(store: AbstractBalanceAndProxyAllowanceLazyStore, devUtilsContract: DevUtilsContract) {
this._store = store;
this._devUtils = devUtilsContract;
}
/**
* Simulates transferFrom call performed by a proxy
@ -75,7 +77,7 @@ export class ExchangeTransferSimulator {
tradeSide: TradeSide,
transferType: TransferType,
): Promise<void> {
const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData);
const assetProxyId = await this._devUtils.decodeAssetProxyId.callAsync(assetData);
switch (assetProxyId) {
case AssetProxyId.ERC1155:
case AssetProxyId.ERC20:
@ -108,11 +110,11 @@ export class ExchangeTransferSimulator {
break;
}
case AssetProxyId.MultiAsset: {
const decodedAssetData = assetDataUtils.decodeMultiAssetData(assetData);
const decodedAssetData = await this._devUtils.decodeMultiAssetData.callAsync(assetData);
await this._decreaseBalanceAsync(assetData, from, amountInBaseUnits);
await this._increaseBalanceAsync(assetData, to, amountInBaseUnits);
for (const [index, nestedAssetDataElement] of decodedAssetData.nestedAssetData.entries()) {
const amountsElement = decodedAssetData.amounts[index];
for (const [index, nestedAssetDataElement] of decodedAssetData[2].entries()) {
const amountsElement = decodedAssetData[1][index];
const totalAmount = amountInBaseUnits.times(amountsElement);
await this.transferFromAsync(
nestedAssetDataElement,

View File

@ -7,7 +7,7 @@ import {
} from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { constants, expect, LogDecoder, orderUtils, signingUtils } from '@0x/contracts-test-utils';
import { BalanceAndProxyAllowanceLazyStore, ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils';
import { ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils';
import { FillResults, Order, SignatureType, SignedOrder } from '@0x/types';
import { BigNumber, errorUtils, providerUtils, RevertError, StringRevertError } from '@0x/utils';
import { SupportedProvider, Web3Wrapper } from '@0x/web3-wrapper';
@ -37,6 +37,7 @@ import {
import { FillOrderError, FillOrderSimulator } from './fill_order_simulator';
import { OrderFactoryFromScenario } from './order_factory_from_scenario';
import { SimpleAssetBalanceAndProxyAllowanceFetcher } from './simple_asset_balance_and_proxy_allowance_fetcher';
import { BalanceAndProxyAllowanceLazyStore } from './store/balance_and_proxy_allowance_lazy_store';
const EMPTY_FILL_RESULTS = {
takerAssetFilledAmount: constants.ZERO_AMOUNT,
@ -441,24 +442,29 @@ export class FillOrderCombinatorialUtils {
this.balanceAndProxyAllowanceFetcher = new SimpleAssetBalanceAndProxyAllowanceFetcher(assetWrapper);
}
public async testFillOrderScenarioAsync(fillScenario: FillScenario): Promise<void> {
return this._testFillOrderScenarioAsync(fillScenario);
public async testFillOrderScenarioAsync(fillScenario: FillScenario, devUtils: DevUtilsContract): Promise<void> {
return this._testFillOrderScenarioAsync(fillScenario, TestOutlook.Any, devUtils);
}
public async testFillOrderScenarioSuccessAsync(fillScenario: FillScenario): Promise<void> {
return this._testFillOrderScenarioAsync(fillScenario, TestOutlook.Success);
public async testFillOrderScenarioSuccessAsync(
fillScenario: FillScenario,
devUtils: DevUtilsContract,
): Promise<void> {
return this._testFillOrderScenarioAsync(fillScenario, TestOutlook.Success, devUtils);
}
public async testFillOrderScenarioFailureAsync(
fillScenario: FillScenario,
devUtils: DevUtilsContract,
fillErrorIfExists?: FillOrderError,
): Promise<void> {
return this._testFillOrderScenarioAsync(fillScenario, TestOutlook.Failure, fillErrorIfExists);
return this._testFillOrderScenarioAsync(fillScenario, TestOutlook.Failure, devUtils, fillErrorIfExists);
}
private async _testFillOrderScenarioAsync(
fillScenario: FillScenario,
expectedTestResult: TestOutlook = TestOutlook.Any,
devUtils: DevUtilsContract,
fillErrorIfExists?: FillOrderError,
): Promise<void> {
const lazyStore = new BalanceAndProxyAllowanceLazyStore(this.balanceAndProxyAllowanceFetcher);
@ -471,7 +477,12 @@ export class FillOrderCombinatorialUtils {
let _fillErrorIfExists = fillErrorIfExists;
if (expectedTestResult !== TestOutlook.Failure || fillErrorIfExists === undefined) {
try {
expectedFillResults = await this._simulateFillOrderAsync(signedOrder, takerAssetFillAmount, lazyStore);
expectedFillResults = await this._simulateFillOrderAsync(
signedOrder,
takerAssetFillAmount,
lazyStore,
devUtils,
);
} catch (err) {
_fillErrorIfExists = err.message;
if (expectedTestResult === TestOutlook.Success) {
@ -504,8 +515,9 @@ export class FillOrderCombinatorialUtils {
signedOrder: SignedOrder,
takerAssetFillAmount: BigNumber,
lazyStore: BalanceAndProxyAllowanceLazyStore,
devUtils: DevUtilsContract,
): Promise<FillResults> {
const simulator = new FillOrderSimulator(lazyStore);
const simulator = new FillOrderSimulator(lazyStore, devUtils);
return simulator.simulateFillOrderAsync(signedOrder, this.takerAddress, takerAssetFillAmount);
}

View File

@ -1,15 +1,14 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { constants, orderUtils } from '@0x/contracts-test-utils';
import {
AbstractBalanceAndProxyAllowanceLazyStore as LazyStore,
ExchangeTransferSimulator,
Order,
TradeSide,
TransferType,
} from '@0x/order-utils';
import { Order } from '@0x/order-utils';
import { FillResults } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
import { AbstractBalanceAndProxyAllowanceLazyStore as LazyStore } from './abstract/abstract_balance_and_proxy_allowance_lazy_store';
import { ExchangeTransferSimulator } from './exchange_transfer_simulator';
import { TradeSide, TransferType } from './types';
export enum FillOrderError {
OrderUnfillable = 'ORDER_UNFILLABLE',
InvalidSender = 'INVALID_SENDER',
@ -27,9 +26,9 @@ export class FillOrderSimulator {
public readonly lazyStore: LazyStore;
private readonly _transferSimulator: ExchangeTransferSimulator;
constructor(lazyStore: LazyStore) {
constructor(lazyStore: LazyStore, devUtilsContract: DevUtilsContract) {
this.lazyStore = lazyStore;
this._transferSimulator = new ExchangeTransferSimulator(lazyStore);
this._transferSimulator = new ExchangeTransferSimulator(lazyStore, devUtilsContract);
}
public async simulateFillOrderAsync(

View File

@ -1,6 +1,6 @@
import { AbstractBalanceAndProxyAllowanceFetcher } from '@0x/order-utils';
import { BigNumber } from '@0x/utils';
import { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher';
import { AssetWrapper } from './asset_wrapper';
export class SimpleAssetBalanceAndProxyAllowanceFetcher implements AbstractBalanceAndProxyAllowanceFetcher {

View File

@ -1,7 +1,7 @@
import { ERC20TokenContract } from '@0x/abi-gen-wrappers';
import { ERC20TokenContract } from '@0x/contracts-erc20';
import { BigNumber } from '@0x/utils';
import { AbstractBalanceAndProxyAllowanceFetcher } from '../../src/abstract/abstract_balance_and_proxy_allowance_fetcher';
import { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher';
export class SimpleERC20BalanceAndProxyAllowanceFetcher implements AbstractBalanceAndProxyAllowanceFetcher {
private readonly _erc20TokenContract: ERC20TokenContract;

View File

@ -1,10 +1,8 @@
import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
import { AbstractOrderFilledCancelledFetcher } from '../abstract/abstract_order_filled_cancelled_fetcher';
import { AbstractOrderFilledCancelledLazyStore } from '../abstract/abstract_order_filled_cancelled_lazy_store';
import { orderHashUtils } from '../order_hash';
/**
* Copy on read store for balances/proxyAllowances of tokens/accounts
@ -55,20 +53,6 @@ export class OrderFilledCancelledLazyStore implements AbstractOrderFilledCancell
public deleteFilledTakerAmount(orderHash: string): void {
delete this._filledTakerAmount[orderHash];
}
/**
* Check if an order has been cancelled
* @param orderHash OrderHash from order of interest
* @return Whether the order has been cancelled
*/
public async getIsCancelledAsync(signedOrder: SignedOrder): Promise<boolean> {
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
if (this._isCancelled[orderHash] === undefined) {
const isCancelled = await this._orderFilledCancelledFetcher.isOrderCancelledAsync(signedOrder);
this.setIsCancelled(orderHash, isCancelled);
}
const cachedIsCancelled = this._isCancelled[orderHash]; // tslint:disable-line:boolean-naming
return cachedIsCancelled;
}
/**
* Set whether an order has been cancelled or not
* @param orderHash OrderHash from order of interest

View File

@ -1,4 +1,17 @@
[
{
"version": "8.0.0-beta.1",
"changes": [
{
"note": "Remove ZRXToken contract wrapper",
"pr": 2324
},
{
"note": "ContractWrappers no longer exposes `erc20Proxy`, `erc721Proxy` and `dutchAuction` wrappers",
"pr": 2324
}
]
},
{
"version": "8.0.0-beta.0",
"changes": [

View File

@ -38,11 +38,6 @@ export {
ERC721TokenApprovalEventArgs,
ERC721TokenApprovalForAllEventArgs,
ERC721TokenContract,
ZRXTokenEventArgs,
ZRXTokenEvents,
ZRXTokenTransferEventArgs,
ZRXTokenApprovalEventArgs,
ZRXTokenContract,
ExchangeProtocolFeeCollectorAddressEventArgs,
ExchangeProtocolFeeMultiplierEventArgs,
ExchangeTransactionExecutionEventArgs,

View File

@ -1,4 +1,13 @@
[
{
"version": "5.4.0-beta.2",
"changes": [
{
"note": "[Breaking] Remove `erc20Proxy`, `multiAssetProxy`, `erc1155Proxy`, `staticCallProxy`, `erc721Proxy`, `assetProxyOwner`, `ZRXToken` and `dutchAuction` wrappers",
"pr": 2324
}
]
},
{
"version": "5.4.0-beta.1",
"changes": [

View File

@ -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|ERC1155Mintable|ERC20Proxy|ERC20Token|ERC721Proxy|ERC721Token|Exchange|Forwarder|IAssetProxy|IValidator|IWallet|MultiAssetProxy|OrderValidator|WETH9|ZRXToken|Coordinator|CoordinatorRegistry|EthBalanceChecker|ERC1155Proxy|StaticCallProxy|Staking|StakingProxy).json"
"abis": "../contract-artifacts/artifacts/@(DevUtils|DummyERC20Token|DummyERC721Token|ERC1155Mintable|ERC20Token|ERC721Token|Exchange|Forwarder|IValidator|IWallet|OrderValidator|WETH9|Coordinator|CoordinatorRegistry|Staking|StakingProxy).json"
},
"repository": {
"type": "git",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,444 +0,0 @@
// 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';
import { schemas } from '@0x/json-schemas';
import {
BlockParam,
BlockParamLiteral,
BlockRange,
CallData,
ContractAbi,
ContractArtifact,
DecodedLogArgs,
MethodAbi,
TransactionReceiptWithDecodedLogs,
TxData,
TxDataPayable,
SupportedProvider,
} from 'ethereum-types';
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
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';
// tslint:enable:no-unused-variable
/* istanbul ignore next */
// 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.
*/
public transferFrom = {
/**
* Sends an Ethereum transaction executing this method with the supplied parameters. This is a read/write
* Ethereum operation and will cost gas.
* @param assetData Byte array encoded for the respective asset proxy.
* @param from Address to transfer asset from.
* @param to Address to transfer asset to.
* @param amount Amount of asset to transfer.
* @param txData Additional data for transaction
* @returns The hash of the transaction
*/
async sendTransactionAsync(
assetData: string,
from: string,
to: string,
amount: BigNumber,
txData?: Partial<TxData> | undefined,
opts: SendTransactionOpts = { shouldValidate: true },
): Promise<string> {
assert.isString('assetData', assetData);
assert.isString('from', from);
assert.isString('to', to);
assert.isBigNumber('amount', amount);
const self = (this as any) as IAssetProxyContract;
const encodedData = self._strictEncodeArguments('transferFrom(bytes,address,address,uint256)', [
assetData,
from.toLowerCase(),
to.toLowerCase(),
amount,
]);
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
{
to: self.address,
...txData,
data: encodedData,
},
self._web3Wrapper.getContractDefaults(),
);
if (txDataWithDefaults.from !== undefined) {
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;
},
/**
* 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 assetData Byte array encoded for the respective asset proxy.
* @param from Address to transfer asset from.
* @param to Address to transfer asset to.
* @param amount Amount of asset to transfer.
* @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(
assetData: string,
from: string,
to: string,
amount: BigNumber,
txData?: Partial<TxData>,
opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
assert.isString('assetData', assetData);
assert.isString('from', from);
assert.isString('to', to);
assert.isBigNumber('amount', amount);
const self = (this as any) as IAssetProxyContract;
const txHashPromise = self.transferFrom.sendTransactionAsync(
assetData,
from.toLowerCase(),
to.toLowerCase(),
amount,
txData,
opts,
);
return new PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs>(
txHashPromise,
(async (): Promise<TransactionReceiptWithDecodedLogs> => {
// When the transaction hash resolves, wait for it to be mined.
return self._web3Wrapper.awaitTransactionSuccessAsync(
await txHashPromise,
opts.pollingIntervalMs,
opts.timeoutMs,
);
})(),
);
},
/**
* Estimates the gas cost of sending an Ethereum transaction calling this method with these arguments.
* @param assetData Byte array encoded for the respective asset proxy.
* @param from Address to transfer asset from.
* @param to Address to transfer asset to.
* @param amount Amount of asset to transfer.
* @param txData Additional data for transaction
* @returns The hash of the transaction
*/
async estimateGasAsync(
assetData: string,
from: string,
to: string,
amount: BigNumber,
txData?: Partial<TxData> | undefined,
): Promise<number> {
assert.isString('assetData', assetData);
assert.isString('from', from);
assert.isString('to', to);
assert.isBigNumber('amount', amount);
const self = (this as any) as IAssetProxyContract;
const encodedData = self._strictEncodeArguments('transferFrom(bytes,address,address,uint256)', [
assetData,
from.toLowerCase(),
to.toLowerCase(),
amount,
]);
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
* Ethereum transaction to this method, given the current state of the blockchain. Calls do not cost gas
* since they don't modify state.
* @param assetData Byte array encoded for the respective asset proxy.
* @param from Address to transfer asset from.
* @param to Address to transfer asset to.
* @param amount Amount of asset to transfer.
*/
async callAsync(
assetData: string,
from: string,
to: string,
amount: BigNumber,
callData: Partial<CallData> = {},
defaultBlock?: BlockParam,
): Promise<void> {
assert.isString('assetData', assetData);
assert.isString('from', from);
assert.isString('to', to);
assert.isBigNumber('amount', amount);
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 IAssetProxyContract;
const encodedData = self._strictEncodeArguments('transferFrom(bytes,address,address,uint256)', [
assetData,
from.toLowerCase(),
to.toLowerCase(),
amount,
]);
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('transferFrom(bytes,address,address,uint256)');
// tslint:disable boolean-naming
const result = abiEncoder.strictDecodeReturnValue<void>(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 assetData Byte array encoded for the respective asset proxy.
* @param from Address to transfer asset from.
* @param to Address to transfer asset to.
* @param amount Amount of asset to transfer.
* @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 IAssetProxyContract;
const abiEncodedTransactionData = self._strictEncodeArguments(
'transferFrom(bytes,address,address,uint256)',
[assetData, from.toLowerCase(), to.toLowerCase(), amount],
);
return abiEncodedTransactionData;
},
/**
* Returns the 4 byte function selector as a hex string.
*/
getSelector(): string {
const self = (this as any) as IAssetProxyContract;
const abiEncoder = self._lookupAbiEncoder('transferFrom(bytes,address,address,uint256)');
return abiEncoder.getSelector();
},
};
/**
* Gets the proxy id associated with the proxy address.
*/
public getProxyId = {
/**
* 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.
* @returns Proxy id.
*/
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
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 IAssetProxyContract;
const encodedData = self._strictEncodeArguments('getProxyId()', []);
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('getProxyId()');
// tslint:disable boolean-naming
const result = abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
// tslint:enable boolean-naming
return result;
},
};
public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
): Promise<IAssetProxyContract> {
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 IAssetProxyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
}
public static async deployAsync(
bytecode: string,
abi: ContractAbi,
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractAbi },
): Promise<IAssetProxyContract> {
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(`IAssetProxy successfully deployed at ${txReceipt.contractAddress}`);
const contractInstance = new IAssetProxyContract(
txReceipt.contractAddress as string,
provider,
txDefaults,
logDecodeDependencies,
);
contractInstance.constructorArgs = [];
return contractInstance;
}
/**
* @returns The contract ABI
*/
public static ABI(): ContractAbi {
const abi = [
{
constant: false,
inputs: [
{
name: 'assetData',
type: 'bytes',
},
{
name: 'from',
type: 'address',
},
{
name: 'to',
type: 'address',
},
{
name: 'amount',
type: 'uint256',
},
],
name: 'transferFrom',
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'function',
},
{
constant: true,
inputs: [],
name: 'getProxyId',
outputs: [
{
name: '',
type: 'bytes4',
},
],
payable: false,
stateMutability: 'pure',
type: 'function',
},
] as ContractAbi;
return abi;
}
constructor(
address: string,
supportedProvider: SupportedProvider,
txDefaults?: Partial<TxData>,
logDecodeDependencies?: { [contractName: string]: ContractAbi },
deployedBytecode: string | undefined = IAssetProxyContract.deployedBytecode,
) {
super(
'IAssetProxy',
IAssetProxyContract.ABI(),
address,
supportedProvider,
txDefaults,
logDecodeDependencies,
deployedBytecode,
);
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_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

File diff suppressed because one or more lines are too long

View File

@ -1,282 +0,0 @@
// 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';
import { schemas } from '@0x/json-schemas';
import {
BlockParam,
BlockParamLiteral,
BlockRange,
CallData,
ContractAbi,
ContractArtifact,
DecodedLogArgs,
MethodAbi,
TransactionReceiptWithDecodedLogs,
TxData,
TxDataPayable,
SupportedProvider,
} from 'ethereum-types';
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
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';
// tslint:enable:no-unused-variable
/* istanbul ignore next */
// tslint:disable:no-parameter-reassignment
// tslint:disable-next-line:class-name
export class StaticCallProxyContract extends BaseContract {
/**
* @ignore
*/
public static deployedBytecode =
'0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063a85e59e41461003b578063ae25532e146100d3575b600080fd5b6100d16004803603608081101561005157600080fd5b81019060208101813564010000000081111561006c57600080fd5b82018360208201111561007e57600080fd5b803590602001918460018302840111640100000000831117156100a057600080fd5b919350915073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610110565b005b6100db6103a5565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b6000606060006101656004898990508a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092949392505063ffffffff6103c5169050565b806020019051606081101561017957600080fd5b8151602083018051604051929492938301929190846401000000008211156101a057600080fd5b9083019060208201858111156101b557600080fd5b82516401000000008111828201881017156101cf57600080fd5b82525081516020918201929091019080838360005b838110156101fc5781810151838201526020016101e4565b50505050905090810190601f1680156102295780820380516001836020036101000a031916815260200191505b5060405260200180519060200190929190505050925092509250600060608473ffffffffffffffffffffffffffffffffffffffff16846040518082805190602001908083835b602083106102ac57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161026f565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461030c576040519150601f19603f3d011682016040523d82523d6000602084013e610311565b606091505b50915091508161032357805160208201fd5b8051602082012083811461039857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f554e45585045435445445f5354415449435f43414c4c5f524553554c54000000604482015290519081900360640190fd5b5050505050505050505050565b600060405180806104b06021913960210190506040518091039020905090565b6060818311156103e3576103e36103de60008585610408565b6104a7565b83518211156103fc576103fc6103de6001848751610408565b50819003910190815290565b6060632800659560e01b8484846040516024018084600781111561042857fe5b60ff1681526020018381526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090509392505050565b805160208201fdfe53746174696343616c6c28616464726573732c62797465732c6279746573333229a265627a7a72315820c55cf13cfcaaf322238d786911313ce7d45854692241ae9b56709bdbfed4f54c64736f6c634300050b0032';
/**
* Makes a staticcall to a target address and verifies that the data returned matches the expected return data.
*/
public transferFrom = {
/**
* 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 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.
*/
async callAsync(
assetData: string,
from: string,
to: string,
amount: BigNumber,
callData: Partial<CallData> = {},
defaultBlock?: BlockParam,
): Promise<void> {
assert.isString('assetData', assetData);
assert.isString('from', from);
assert.isString('to', to);
assert.isBigNumber('amount', amount);
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 StaticCallProxyContract;
const encodedData = self._strictEncodeArguments('transferFrom(bytes,address,address,uint256)', [
assetData,
from.toLowerCase(),
to.toLowerCase(),
amount,
]);
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('transferFrom(bytes,address,address,uint256)');
// tslint:disable boolean-naming
const result = abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
// tslint:enable boolean-naming
return result;
},
};
/**
* Gets the proxy id associated with the proxy address.
*/
public getProxyId = {
/**
* 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.
* @returns Proxy id.
*/
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
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 StaticCallProxyContract;
const encodedData = self._strictEncodeArguments('getProxyId()', []);
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('getProxyId()');
// tslint:disable boolean-naming
const result = abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
// tslint:enable boolean-naming
return result;
},
};
public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
): Promise<StaticCallProxyContract> {
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 StaticCallProxyContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly);
}
public static async deployAsync(
bytecode: string,
abi: ContractAbi,
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
logDecodeDependencies: { [contractName: string]: ContractAbi },
): Promise<StaticCallProxyContract> {
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(`StaticCallProxy successfully deployed at ${txReceipt.contractAddress}`);
const contractInstance = new StaticCallProxyContract(
txReceipt.contractAddress as string,
provider,
txDefaults,
logDecodeDependencies,
);
contractInstance.constructorArgs = [];
return contractInstance;
}
/**
* @returns The contract ABI
*/
public static ABI(): ContractAbi {
const abi = [
{
constant: true,
inputs: [
{
name: 'assetData',
type: 'bytes',
},
{
name: 'from',
type: 'address',
},
{
name: 'to',
type: 'address',
},
{
name: 'amount',
type: 'uint256',
},
],
name: 'transferFrom',
outputs: [],
payable: false,
stateMutability: 'view',
type: 'function',
},
{
constant: true,
inputs: [],
name: 'getProxyId',
outputs: [
{
name: '',
type: 'bytes4',
},
],
payable: false,
stateMutability: 'pure',
type: 'function',
},
] as ContractAbi;
return abi;
}
constructor(
address: string,
supportedProvider: SupportedProvider,
txDefaults?: Partial<TxData>,
logDecodeDependencies?: { [contractName: string]: ContractAbi },
deployedBytecode: string | undefined = StaticCallProxyContract.deployedBytecode,
) {
super(
'StaticCallProxy',
StaticCallProxyContract.ABI(),
address,
supportedProvider,
txDefaults,
logDecodeDependencies,
deployedBytecode,
);
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_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

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,3 @@
export {
AssetProxyOwnerEventArgs,
AssetProxyOwnerEvents,
AssetProxyOwnerConfirmationTimeSetEventArgs,
AssetProxyOwnerTimeLockChangeEventArgs,
AssetProxyOwnerConfirmationEventArgs,
AssetProxyOwnerRevocationEventArgs,
AssetProxyOwnerSubmissionEventArgs,
AssetProxyOwnerExecutionEventArgs,
AssetProxyOwnerExecutionFailureEventArgs,
AssetProxyOwnerDepositEventArgs,
AssetProxyOwnerOwnerAdditionEventArgs,
AssetProxyOwnerOwnerRemovalEventArgs,
AssetProxyOwnerRequirementChangeEventArgs,
AssetProxyOwnerContract,
} from './generated-wrappers/asset_proxy_owner';
export { DevUtilsContract } from './generated-wrappers/dev_utils';
export {
DummyERC20TokenEventArgs,
@ -37,21 +21,6 @@ export {
ERC1155MintableTransferSingleEventArgs,
ERC1155MintableURIEventArgs,
} from './generated-wrappers/erc1155_mintable';
export { DutchAuctionContract } from './generated-wrappers/dutch_auction';
export {
ERC1155ProxyEventArgs,
ERC1155ProxyEvents,
ERC1155ProxyAuthorizedAddressAddedEventArgs,
ERC1155ProxyAuthorizedAddressRemovedEventArgs,
ERC1155ProxyContract,
} from './generated-wrappers/erc1155_proxy';
export {
ERC20ProxyEventArgs,
ERC20ProxyEvents,
ERC20ProxyAuthorizedAddressAddedEventArgs,
ERC20ProxyAuthorizedAddressRemovedEventArgs,
ERC20ProxyContract,
} from './generated-wrappers/erc20_proxy';
export {
ERC20TokenEventArgs,
ERC20TokenEvents,
@ -59,13 +28,6 @@ export {
ERC20TokenApprovalEventArgs,
ERC20TokenContract,
} from './generated-wrappers/erc20_token';
export {
ERC721ProxyEventArgs,
ERC721ProxyEvents,
ERC721ProxyAuthorizedAddressAddedEventArgs,
ERC721ProxyAuthorizedAddressRemovedEventArgs,
ERC721ProxyContract,
} from './generated-wrappers/erc721_proxy';
export {
ERC721TokenEventArgs,
ERC721TokenEvents,
@ -88,19 +50,9 @@ export {
ExchangeTransactionExecutionEventArgs,
} from './generated-wrappers/exchange';
export { ForwarderContract } from './generated-wrappers/forwarder';
export { IAssetProxyContract } from './generated-wrappers/i_asset_proxy';
export { IValidatorContract } from './generated-wrappers/i_validator';
export { IWalletContract } from './generated-wrappers/i_wallet';
export {
MultiAssetProxyEventArgs,
MultiAssetProxyEvents,
MultiAssetProxyAuthorizedAddressAddedEventArgs,
MultiAssetProxyAuthorizedAddressRemovedEventArgs,
MultiAssetProxyAssetProxyRegisteredEventArgs,
MultiAssetProxyContract,
} from './generated-wrappers/multi_asset_proxy';
export { OrderValidatorContract } from './generated-wrappers/order_validator';
export { StaticCallProxyContract } from './generated-wrappers/static_call_proxy';
export {
StakingAuthorizedAddressAddedEventArgs,
StakingAuthorizedAddressRemovedEventArgs,
@ -141,13 +93,6 @@ export {
WETH9WithdrawalEventArgs,
WETH9Contract,
} from './generated-wrappers/weth9';
export {
ZRXTokenEventArgs,
ZRXTokenEvents,
ZRXTokenTransferEventArgs,
ZRXTokenApprovalEventArgs,
ZRXTokenContract,
} from './generated-wrappers/zrx_token';
export { CoordinatorContract } from './generated-wrappers/coordinator';
export {
CoordinatorRegistryEventArgs,
@ -155,6 +100,5 @@ export {
CoordinatorRegistryCoordinatorEndpointSetEventArgs,
CoordinatorRegistryContract,
} from './generated-wrappers/coordinator_registry';
export { EthBalanceCheckerContract } from './generated-wrappers/eth_balance_checker';
export * from '@0x/contract-addresses';

View File

@ -77,7 +77,7 @@ describe('ForwarderSwapQuoteConsumer', () => {
beforeEach(async () => {
await blockchainLifecycle.startAsync();
const UNLIMITED_ALLOWANCE = UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
erc20ProxyAddress = contractWrappers.erc20Proxy.address;
erc20ProxyAddress = contractAddresses.erc20Proxy;
const totalFillableAmount = FILLABLE_AMOUNTS.reduce(
(a: BigNumber, c: BigNumber) => a.plus(c),

View File

@ -71,7 +71,7 @@ describe('SwapQuoteConsumer', () => {
beforeEach(async () => {
await blockchainLifecycle.startAsync();
const UNLIMITED_ALLOWANCE = UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
erc20ProxyAddress = contractWrappers.erc20Proxy.address;
erc20ProxyAddress = contractAddresses.erc20Proxy;
const totalFillableAmount = FILLABLE_AMOUNTS.reduce(
(a: BigNumber, c: BigNumber) => a.plus(c),

View File

@ -1,59 +0,0 @@
{
"schemaVersion": "2.0.0",
"contractName": "EthBalanceChecker",
"compilerOutput": {
"abi": [
{
"constant": true,
"inputs": [{ "internalType": "address[]", "name": "addresses", "type": "address[]" }],
"name": "getEthBalances",
"outputs": [{ "internalType": "uint256[]", "name": "", "type": "uint256[]" }],
"payable": false,
"stateMutability": "view",
"type": "function"
}
],
"devdoc": {
"methods": {
"getEthBalances(address[])": {
"details": "Batch fetches ETH balances",
"params": { "addresses": "Array of addresses." },
"return": "Array of ETH balances."
}
}
},
"evm": {
"bytecode": {
"object": "0x608060405234801561001057600080fd5b506101e5806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a0901e5114610030575b600080fd5b6100d36004803603602081101561004657600080fd5b81019060208101813564010000000081111561006157600080fd5b82018360208201111561007357600080fd5b8035906020019184602083028401116401000000008311171561009557600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610123945050505050565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561010f5781810151838201526020016100f7565b505050509050019250505060405180910390f35b6060808251604051908082528060200260200182016040528015610151578160200160208202803883390190505b50905060005b835181146101a95783818151811061016b57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff163182828151811061019657fe5b6020908102919091010152600101610157565b509291505056fea265627a7a7231582094309783f0b63086d85d9cb4f6e5be253699056ac1580a863367c5076ecb5c1864736f6c634300050b0032"
},
"deployedBytecode": {
"object": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a0901e5114610030575b600080fd5b6100d36004803603602081101561004657600080fd5b81019060208101813564010000000081111561006157600080fd5b82018360208201111561007357600080fd5b8035906020019184602083028401116401000000008311171561009557600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610123945050505050565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561010f5781810151838201526020016100f7565b505050509050019250505060405180910390f35b6060808251604051908082528060200260200182016040528015610151578160200160208202803883390190505b50905060005b835181146101a95783818151811061016b57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff163182828151811061019657fe5b6020908102919091010152600101610157565b509291505056fea265627a7a7231582094309783f0b63086d85d9cb4f6e5be253699056ac1580a863367c5076ecb5c1864736f6c634300050b0032"
}
}
},
"compiler": {
"name": "solc",
"version": "soljson-v0.5.11+commit.c082d0b4.js",
"settings": {
"optimizer": {
"enabled": true,
"runs": 10000,
"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": {}
}

View File

@ -11,7 +11,6 @@ import * as ERC20Proxy from '../artifacts/ERC20Proxy.json';
import * as ERC20Token from '../artifacts/ERC20Token.json';
import * as ERC721Proxy from '../artifacts/ERC721Proxy.json';
import * as ERC721Token from '../artifacts/ERC721Token.json';
import * as EthBalanceChecker from '../artifacts/EthBalanceChecker.json';
import * as Exchange from '../artifacts/Exchange.json';
import * as Forwarder from '../artifacts/Forwarder.json';
import * as IAssetProxy from '../artifacts/IAssetProxy.json';
@ -49,7 +48,6 @@ export {
ZRXToken,
Coordinator,
CoordinatorRegistry,
EthBalanceChecker,
Staking,
StakingProxy,
};

View File

@ -28,7 +28,6 @@
"./artifacts/ZRXToken.json",
"./artifacts/CoordinatorRegistry.json",
"./artifacts/Coordinator.json",
"./artifacts/EthBalanceChecker.json",
"./artifacts/ERC1155Proxy.json",
"./artifacts/StaticCallProxy.json",
"./artifacts/Staking.json",

View File

@ -1,4 +1,13 @@
[
{
"version": "12.2.0-beta.2",
"changes": [
{
"note": "[Breaking] Remove `erc20Proxy`, `erc721Proxy` and `dutchAuction` wrappers",
"pr": 2324
}
]
},
{
"version": "12.2.0-beta.1",
"changes": [

View File

@ -34,9 +34,6 @@
"docs:md": "ts-doc-gen --sourceDir='$PROJECT_FILES' --output=$MD_FILE_DIR --fileExtension=mdx --tsconfig=./typedoc-tsconfig.json",
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
},
"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).json"
},
"repository": {
"type": "git",
"url": "https://github.com/0xProject/0x-monorepo.git"

View File

@ -1,8 +1,5 @@
import {
DevUtilsContract,
DutchAuctionContract,
ERC20ProxyContract,
ERC721ProxyContract,
ExchangeContract,
ForwarderContract,
OrderValidatorContract,
@ -13,9 +10,7 @@ import {
Coordinator,
DevUtils,
DutchAuction,
ERC20Proxy,
ERC20Token,
ERC721Proxy,
ERC721Token,
Exchange,
Forwarder,
@ -45,16 +40,6 @@ export class ContractWrappers {
* An instance of the ExchangeContract class containing methods for interacting with the 0x Exchange smart contract.
*/
public exchange: ExchangeContract;
/**
* An instance of the ERC20ProxyContract class containing methods for interacting with the
* erc20Proxy smart contract.
*/
public erc20Proxy: ERC20ProxyContract;
/**
* An instance of the ERC721ProxyContract class containing methods for interacting with the
* erc721Proxy smart contract.
*/
public erc721Proxy: ERC721ProxyContract;
/**
* An instance of the WETH9Contract class containing methods for interacting with the
* WETH9 smart contract.
@ -64,14 +49,11 @@ export class ContractWrappers {
* An instance of the ForwarderContract class containing methods for interacting with any Forwarder smart contract.
*/
public forwarder: ForwarderContract;
// TODO(fabio): Remove orderValidator after @0x/asset-buyer is deleted
/**
* An instance of the OrderValidatorContract class containing methods for interacting with any OrderValidator smart contract.
*/
public orderValidator: OrderValidatorContract;
/**
* An instance of the DutchAuctionContract class containing methods for interacting with any DutchAuction smart contract.
*/
public dutchAuction: DutchAuctionContract;
/**
* An instance of the DevUtilsContract class containing methods for interacting with the DevUtils smart contract.
*/
@ -99,9 +81,7 @@ export class ContractWrappers {
Coordinator,
DevUtils,
DutchAuction,
ERC20Proxy,
ERC20Token,
ERC721Proxy,
ERC721Token,
Exchange,
Forwarder,
@ -115,13 +95,10 @@ export class ContractWrappers {
config.contractAddresses === undefined
? _getDefaultContractAddresses(config.chainId)
: config.contractAddresses;
this.erc20Proxy = new ERC20ProxyContract(contractAddresses.erc20Proxy, this.getProvider());
this.erc721Proxy = new ERC721ProxyContract(contractAddresses.erc721Proxy, this.getProvider());
this.weth9 = new WETH9Contract(contractAddresses.etherToken, this.getProvider());
this.exchange = new ExchangeContract(contractAddresses.exchange, this.getProvider());
this.forwarder = new ForwarderContract(contractAddresses.forwarder, this.getProvider());
this.orderValidator = new OrderValidatorContract(contractAddresses.orderValidator, this.getProvider());
this.dutchAuction = new DutchAuctionContract(contractAddresses.dutchAuction, this.getProvider());
this.devUtils = new DevUtilsContract(contractAddresses.devUtils, this.getProvider());
this.coordinator = new CoordinatorWrapper(
this.getProvider(),
@ -137,8 +114,6 @@ export class ContractWrappers {
*/
public unsubscribeAll(): void {
this.exchange.unsubscribeAll();
this.erc20Proxy.unsubscribeAll();
this.erc721Proxy.unsubscribeAll();
this.weth9.unsubscribeAll();
}
/**

View File

@ -14,7 +14,6 @@ export {
ExchangeContract,
DevUtilsContract,
ForwarderContract,
DutchAuctionContract,
CoordinatorContract,
CoordinatorRegistryEventArgs,
CoordinatorRegistryEvents,
@ -40,16 +39,6 @@ export {
ERC721TokenApprovalEventArgs,
ERC721TokenApprovalForAllEventArgs,
ERC721TokenContract,
ERC1155ProxyEventArgs,
ERC1155ProxyEvents,
ERC1155ProxyAuthorizedAddressAddedEventArgs,
ERC1155ProxyAuthorizedAddressRemovedEventArgs,
ERC1155ProxyContract,
ZRXTokenEventArgs,
ZRXTokenEvents,
ZRXTokenTransferEventArgs,
ZRXTokenApprovalEventArgs,
ZRXTokenContract,
DummyERC20TokenEventArgs,
DummyERC20TokenEvents,
DummyERC20TokenTransferEventArgs,
@ -61,16 +50,6 @@ export {
DummyERC721TokenApprovalEventArgs,
DummyERC721TokenApprovalForAllEventArgs,
DummyERC721TokenContract,
ERC20ProxyEventArgs,
ERC20ProxyEvents,
ERC20ProxyContract,
ERC20ProxyAuthorizedAddressAddedEventArgs,
ERC20ProxyAuthorizedAddressRemovedEventArgs,
ERC721ProxyEventArgs,
ERC721ProxyEvents,
ERC721ProxyAuthorizedAddressAddedEventArgs,
ERC721ProxyAuthorizedAddressRemovedEventArgs,
ERC721ProxyContract,
OrderValidatorContract,
ExchangeProtocolFeeCollectorAddressEventArgs,
ExchangeProtocolFeeMultiplierEventArgs,

View File

@ -1,4 +1,13 @@
[
{
"version": "4.4.0-beta.2",
"changes": [
{
"note": "Migrations script no longer deploys DutchAuction since it is not yet upgraded for V3 of the protocol",
"pr": 2324
}
]
},
{
"version": "4.4.0-beta.1",
"changes": [

View File

@ -59,14 +59,18 @@
"@0x/base-contract": "^5.5.0-beta.1",
"@0x/contract-addresses": "^3.3.0-beta.2",
"@0x/contract-artifacts": "^2.3.0-beta.2",
"@0x/contracts-asset-proxy": "^2.3.0-beta.1",
"@0x/contracts-coordinator": "^2.1.0-beta.1",
"@0x/contracts-asset-proxy": "2.3.0-beta.1",
"@0x/contracts-exchange-forwarder": "3.1.0-beta.1",
"@0x/contracts-dev-utils": "^0.1.0-beta.1",
"@0x/contracts-exchange": "^2.2.0-beta.1",
"@0x/contracts-exchange-forwarder": "^3.1.0-beta.1",
"@0x/contracts-coordinator": "2.1.0-beta.1",
"@0x/contracts-multisig": "^3.2.0-beta.1",
"@0x/contracts-staking": "^1.1.0-beta.1",
"@0x/contracts-exchange": "^2.2.0-beta.1",
"@0x/contracts-extensions": "^4.1.0-beta.1",
"@0x/contracts-utils": "^3.3.0-beta.1",
"@0x/contracts-erc20": "^2.3.0-beta.1",
"@0x/contracts-erc721": "^2.2.0-beta.1",
"@0x/contracts-erc1155": "^1.2.0-beta.1",
"@0x/sol-compiler": "^3.2.0-beta.1",
"@0x/subproviders": "^5.1.0-beta.1",
"@0x/typescript-typings": "^4.4.0-beta.1",

View File

@ -1,6 +1,20 @@
import * as wrappers from '@0x/abi-gen-wrappers';
import { CoordinatorContract, OrderValidatorContract } from '@0x/abi-gen-wrappers';
import { ContractAddresses } from '@0x/contract-addresses';
import * as artifacts from '@0x/contract-artifacts';
import {
ERC1155ProxyContract,
ERC20ProxyContract,
ERC721ProxyContract,
MultiAssetProxyContract,
StaticCallProxyContract,
} from '@0x/contracts-asset-proxy';
import { CoordinatorRegistryContract } from '@0x/contracts-coordinator';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { ERC1155MintableContract } from '@0x/contracts-erc1155';
import { DummyERC20TokenContract, WETH9Contract, ZRXTokenContract } from '@0x/contracts-erc20';
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
import { ExchangeContract } from '@0x/contracts-exchange';
import { ForwarderContract } from '@0x/contracts-exchange-forwarder';
import { Web3ProviderEngine } from '@0x/subproviders';
import { AbiEncoder, BigNumber, providerUtils } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
@ -55,13 +69,13 @@ export async function runMigrationsAsync(
const chainId = new BigNumber(await providerUtils.getChainIdAsync(provider));
// Proxies
const erc20Proxy = await wrappers.ERC20ProxyContract.deployFrom0xArtifactAsync(
const erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync(
artifacts.ERC20Proxy,
provider,
txDefaults,
artifacts,
);
const erc721Proxy = await wrappers.ERC721ProxyContract.deployFrom0xArtifactAsync(
const erc721Proxy = await ERC721ProxyContract.deployFrom0xArtifactAsync(
artifacts.ERC721Proxy,
provider,
txDefaults,
@ -69,7 +83,7 @@ export async function runMigrationsAsync(
);
// ZRX
const zrxToken = await wrappers.ZRXTokenContract.deployFrom0xArtifactAsync(
const zrxToken = await ZRXTokenContract.deployFrom0xArtifactAsync(
artifacts.ZRXToken,
provider,
txDefaults,
@ -77,16 +91,12 @@ export async function runMigrationsAsync(
);
// Ether token
const etherToken = await wrappers.WETH9Contract.deployFrom0xArtifactAsync(
artifacts.WETH9,
provider,
txDefaults,
artifacts,
);
const etherToken = await WETH9Contract.deployFrom0xArtifactAsync(artifacts.WETH9, provider, txDefaults, artifacts);
// Exchange
// tslint:disable-next-line:no-unused-variable
const zrxAssetData = encodeERC20AssetData(zrxToken.address);
const exchange = await wrappers.ExchangeContract.deployFrom0xArtifactAsync(
const exchange = await ExchangeContract.deployFrom0xArtifactAsync(
artifacts.Exchange,
provider,
txDefaults,
@ -98,7 +108,7 @@ export async function runMigrationsAsync(
for (const token of erc20TokenInfo) {
const totalSupply = new BigNumber(1000000000000000000000000000);
// tslint:disable-next-line:no-unused-variable
const dummyErc20Token = await wrappers.DummyERC20TokenContract.deployFrom0xArtifactAsync(
const dummyErc20Token = await DummyERC20TokenContract.deployFrom0xArtifactAsync(
artifacts.DummyERC20Token,
provider,
txDefaults,
@ -112,7 +122,7 @@ export async function runMigrationsAsync(
// ERC721
// tslint:disable-next-line:no-unused-variable
const cryptoKittieToken = await wrappers.DummyERC721TokenContract.deployFrom0xArtifactAsync(
const cryptoKittieToken = await DummyERC721TokenContract.deployFrom0xArtifactAsync(
artifacts.DummyERC721Token,
provider,
txDefaults,
@ -122,21 +132,21 @@ export async function runMigrationsAsync(
);
// 1155 Asset Proxy
const erc1155Proxy = await wrappers.ERC1155ProxyContract.deployFrom0xArtifactAsync(
const erc1155Proxy = await ERC1155ProxyContract.deployFrom0xArtifactAsync(
artifacts.ERC1155Proxy,
provider,
txDefaults,
artifacts,
);
const staticCallProxy = await wrappers.StaticCallProxyContract.deployFrom0xArtifactAsync(
const staticCallProxy = await StaticCallProxyContract.deployFrom0xArtifactAsync(
artifacts.StaticCallProxy,
provider,
txDefaults,
artifacts,
);
const multiAssetProxy = await wrappers.MultiAssetProxyContract.deployFrom0xArtifactAsync(
const multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
artifacts.MultiAssetProxy,
provider,
txDefaults,
@ -165,7 +175,7 @@ export async function runMigrationsAsync(
await exchange.registerAssetProxy.awaitTransactionSuccessAsync(staticCallProxy.address, txDefaults);
// Forwarder
const forwarder = await wrappers.ForwarderContract.deployFrom0xArtifactAsync(
const forwarder = await ForwarderContract.deployFrom0xArtifactAsync(
artifacts.Forwarder,
provider,
txDefaults,
@ -174,8 +184,9 @@ export async function runMigrationsAsync(
encodeERC20AssetData(etherToken.address),
);
// TODO(fabio): Remove orderValidator after @0x/asset-buyer is deleted
// OrderValidator
const orderValidator = await wrappers.OrderValidatorContract.deployFrom0xArtifactAsync(
const orderValidator = await OrderValidatorContract.deployFrom0xArtifactAsync(
artifacts.OrderValidator,
provider,
txDefaults,
@ -184,14 +195,16 @@ export async function runMigrationsAsync(
zrxAssetData,
);
// DutchAuction
const dutchAuction = await wrappers.DutchAuctionContract.deployFrom0xArtifactAsync(
artifacts.DutchAuction,
provider,
txDefaults,
artifacts,
exchange.address,
);
// TODO(fabio): Uncomment dutchAuction once the @0x/contracts-extensions is refactored
// for V3
// // DutchAuction
// const dutchAuction = await DutchAuctionContract.deployFrom0xArtifactAsync(
// artifacts.DutchAuction,
// provider,
// txDefaults,
// artifacts,
// exchange.address,
// );
// TODO (xianny): figure out how to deploy AssetProxyOwnerContract properly
// // Multisigs
@ -202,7 +215,7 @@ export async function runMigrationsAsync(
// // AssetProxyOwner
// const assetProxyOwner = await wrappers.AssetProxyOwnerContract.deployFrom0xArtifactAsync(
// const assetProxyOwner = await AssetProxyOwnerContract.deployFrom0xArtifactAsync(
// artifacts.AssetProxyOwner,
// provider,
// txDefaults,
@ -231,7 +244,7 @@ export async function runMigrationsAsync(
// Fake the above transactions so our nonce increases and we result with the same addresses
// while AssetProxyOwner is disabled (TODO: @dekz remove)
const dummyTransactionCount = 5;
const dummyTransactionCount = 6;
for (let index = 0; index < dummyTransactionCount; index++) {
await web3Wrapper.sendTransactionAsync({ to: txDefaults.from, from: txDefaults.from, value: new BigNumber(0) });
}
@ -242,7 +255,7 @@ export async function runMigrationsAsync(
await zrxToken.transfer.awaitTransactionSuccessAsync(forwarder.address, zrxForwarderAmount, txDefaults);
// CoordinatorRegistry
const coordinatorRegistry = await wrappers.CoordinatorRegistryContract.deployFrom0xArtifactAsync(
const coordinatorRegistry = await CoordinatorRegistryContract.deployFrom0xArtifactAsync(
artifacts.CoordinatorRegistry,
provider,
txDefaults,
@ -250,7 +263,7 @@ export async function runMigrationsAsync(
);
// Coordinator
const coordinator = await wrappers.CoordinatorContract.deployFrom0xArtifactAsync(
const coordinator = await CoordinatorContract.deployFrom0xArtifactAsync(
artifacts.Coordinator,
provider,
txDefaults,
@ -259,7 +272,7 @@ export async function runMigrationsAsync(
);
// Dev Utils
const devUtils = await wrappers.DevUtilsContract.deployFrom0xArtifactAsync(
const devUtils = await DevUtilsContract.deployFrom0xArtifactAsync(
artifacts.DevUtils,
provider,
txDefaults,
@ -268,7 +281,7 @@ export async function runMigrationsAsync(
);
// tslint:disable-next-line:no-unused-variable
const erc1155DummyToken = await wrappers.ERC1155MintableContract.deployFrom0xArtifactAsync(
const erc1155DummyToken = await ERC1155MintableContract.deployFrom0xArtifactAsync(
artifacts.ERC1155Mintable,
provider,
txDefaults,
@ -288,7 +301,7 @@ export async function runMigrationsAsync(
zeroExGovernor: constants.NULL_ADDRESS,
forwarder: forwarder.address,
orderValidator: orderValidator.address,
dutchAuction: dutchAuction.address,
dutchAuction: constants.NULL_ADDRESS,
coordinatorRegistry: coordinatorRegistry.address,
coordinator: coordinator.address,
multiAssetProxy: multiAssetProxy.address,

View File

@ -1,6 +1,11 @@
#!/usr/bin/env node
import * as wrappers from '@0x/abi-gen-wrappers';
import { getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
import {
ERC1155ProxyContract,
ERC20ProxyContract,
ERC721ProxyContract,
MultiAssetProxyContract,
} from '@0x/contracts-asset-proxy';
import { ExchangeContract } from '@0x/contracts-exchange';
import { ZeroExGovernorContract } from '@0x/contracts-multisig';
import { StakingContract, StakingProxyContract, ZrxVaultContract } from '@0x/contracts-staking';
@ -34,11 +39,11 @@ async function testContractConfigsAsync(provider: SupportedProvider): Promise<vo
const exchange = new ExchangeContract(addresses.exchange, provider);
const exchangeV2 = new ExchangeContract(addresses.exchangeV2, provider);
const erc20Proxy = new wrappers.ERC20ProxyContract(addresses.erc20Proxy, provider);
const erc721Proxy = new wrappers.ERC721ProxyContract(addresses.erc721Proxy, provider);
const erc1155Proxy = new wrappers.ERC1155ProxyContract(addresses.erc1155Proxy, provider);
const multiAssetProxy = new wrappers.MultiAssetProxyContract(addresses.multiAssetProxy, provider);
const erc20BridgeProxy = new wrappers.ERC20ProxyContract(addresses.erc20BridgeProxy, provider);
const erc20Proxy = new ERC20ProxyContract(addresses.erc20Proxy, provider);
const erc721Proxy = new ERC721ProxyContract(addresses.erc721Proxy, provider);
const erc1155Proxy = new ERC1155ProxyContract(addresses.erc1155Proxy, provider);
const multiAssetProxy = new MultiAssetProxyContract(addresses.multiAssetProxy, provider);
const erc20BridgeProxy = new ERC20ProxyContract(addresses.erc20BridgeProxy, provider);
const governor = new ZeroExGovernorContract(addresses.zeroExGovernor, provider);
const stakingProxy = new StakingProxyContract(addresses.stakingProxy, provider);
const stakingContract = new StakingContract(addresses.stakingProxy, provider);

View File

@ -1,4 +1,13 @@
[
{
"version": "8.5.0-beta.2",
"changes": [
{
"note": "[Breaking] Removed `OrderStateUtils`, `OrderValidationUtils`, `ExchangeTransferSimulator` and all abstract and store classes. For order validation, please use the `DevUtils` contract wrapper method `getOrderRelevantState`|`getOrderRelevantStates`",
"pr": 2324
}
]
},
{
"version": "8.5.0-beta.1",
"changes": [

View File

@ -15,17 +15,6 @@ export { sortingUtils } from './sorting_utils';
export { orderParsingUtils } from './parsing_utils';
export { orderCalculationUtils } from './order_calculation_utils';
export { OrderStateUtils } from './order_state_utils';
export { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher';
export { AbstractBalanceAndProxyAllowanceLazyStore } from './abstract/abstract_balance_and_proxy_allowance_lazy_store';
export { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher';
export { AbstractOrderFilledCancelledLazyStore } from './abstract/abstract_order_filled_cancelled_lazy_store';
export { OrderValidationUtils } from './order_validation_utils';
export { ExchangeTransferSimulator } from './exchange_transfer_simulator';
export { BalanceAndProxyAllowanceLazyStore } from './store/balance_and_proxy_allowance_lazy_store';
export { OrderFilledCancelledLazyStore } from './store/order_filled_cancelled_lazy_store';
export { eip712Utils } from './eip712_utils';
export {
@ -47,8 +36,6 @@ export {
export {
SignedOrder,
Order,
OrderRelevantState,
OrderState,
ECSignature,
AssetData,
SingleAssetData,
@ -61,10 +48,6 @@ export {
MultiAssetDataWithRecursiveDecoding,
AssetProxyId,
SignatureType,
ObjectMap,
OrderStateValid,
OrderStateInvalid,
ExchangeContractErrs,
EIP712Parameter,
EIP712TypedData,
EIP712Types,
@ -78,8 +61,6 @@ export {
export {
TypedDataError,
TradeSide,
TransferType,
FindFeeOrdersThatCoverFeesForTargetOrdersOpts,
FindOrdersThatCoverMakerAssetFillAmountOpts,
FindOrdersThatCoverTakerAssetFillAmountOpts,

View File

@ -1,363 +0,0 @@
import {
AssetProxyId,
ERC20AssetData,
ERC721AssetData,
ExchangeContractErrs,
MultiAssetData,
ObjectMap,
OrderRelevantState,
OrderState,
OrderStateInvalid,
OrderStateValid,
SignedOrder,
SingleAssetData,
} from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
import { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher';
import { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher';
import { assetDataUtils } from './asset_data_utils';
import { orderHashUtils } from './order_hash';
import { OrderValidationUtils } from './order_validation_utils';
import { RemainingFillableCalculator } from './remaining_fillable_calculator';
import { utils } from './utils';
interface SidedOrderRelevantState {
isMakerSide: boolean;
traderBalance: BigNumber;
traderIndividualBalances: ObjectMap<BigNumber>;
traderProxyAllowance: BigNumber;
traderIndividualProxyAllowances: ObjectMap<BigNumber>;
traderFeeBalance: BigNumber;
traderFeeProxyAllowance: BigNumber;
filledTakerAssetAmount: BigNumber;
remainingFillableAssetAmount: BigNumber;
isOrderCancelled: boolean;
}
interface OrderValidResult {
isValid: true;
}
interface OrderInvalidResult {
isValid: false;
error: ExchangeContractErrs;
}
type OrderValidationResult = OrderValidResult | OrderInvalidResult;
export class OrderStateUtils {
private readonly _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher;
private readonly _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher;
private static _validateIfOrderIsValid(
signedOrder: SignedOrder,
sidedOrderRelevantState: SidedOrderRelevantState,
): OrderValidationResult {
const isMakerSide = sidedOrderRelevantState.isMakerSide;
if (sidedOrderRelevantState.isOrderCancelled) {
return { isValid: false, error: ExchangeContractErrs.OrderCancelled };
}
const availableTakerAssetAmount = signedOrder.takerAssetAmount.minus(
sidedOrderRelevantState.filledTakerAssetAmount,
);
if (availableTakerAssetAmount.eq(0)) {
return { isValid: false, error: ExchangeContractErrs.OrderRemainingFillAmountZero };
}
if (sidedOrderRelevantState.traderBalance.eq(0)) {
const error = isMakerSide
? ExchangeContractErrs.InsufficientMakerBalance
: ExchangeContractErrs.InsufficientTakerBalance;
return { isValid: false, error };
}
if (sidedOrderRelevantState.traderProxyAllowance.eq(0)) {
const error = isMakerSide
? ExchangeContractErrs.InsufficientMakerAllowance
: ExchangeContractErrs.InsufficientTakerAllowance;
return { isValid: false, error };
}
if (!signedOrder.makerFee.eq(0)) {
if (sidedOrderRelevantState.traderFeeBalance.eq(0)) {
const error = isMakerSide
? ExchangeContractErrs.InsufficientMakerFeeBalance
: ExchangeContractErrs.InsufficientTakerFeeBalance;
return { isValid: false, error };
}
if (sidedOrderRelevantState.traderFeeProxyAllowance.eq(0)) {
const error = isMakerSide
? ExchangeContractErrs.InsufficientMakerFeeAllowance
: ExchangeContractErrs.InsufficientTakerFeeAllowance;
return { isValid: false, error };
}
}
const remainingTakerAssetAmount = signedOrder.takerAssetAmount.minus(
sidedOrderRelevantState.filledTakerAssetAmount,
);
const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(
remainingTakerAssetAmount,
signedOrder.takerAssetAmount,
signedOrder.makerAssetAmount,
);
if (isRoundingError) {
return { isValid: false, error: ExchangeContractErrs.OrderFillRoundingError };
}
return { isValid: true };
}
/**
* Instantiate OrderStateUtils
* @param balanceAndProxyAllowanceFetcher A class that is capable of fetching balances
* and proxyAllowances for Ethereum addresses. It must implement AbstractBalanceAndProxyAllowanceFetcher
* @param orderFilledCancelledFetcher A class that is capable of fetching whether an order
* is cancelled and how much of it has been filled. It must implement AbstractOrderFilledCancelledFetcher
* @return Instance of OrderStateUtils
*/
constructor(
balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher,
orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher,
) {
this._balanceAndProxyAllowanceFetcher = balanceAndProxyAllowanceFetcher;
this._orderFilledCancelledFetcher = orderFilledCancelledFetcher;
}
/**
* Get the orderState for an "open" order (i.e where takerAddress=NULL_ADDRESS)
* This method will only check the maker's balance/allowance to calculate the
* OrderState.
* @param signedOrder The order of interest
* @return State relevant to the signedOrder, as well as whether the signedOrder is "valid".
* Validity is defined as a non-zero amount of the order can still be filled.
*/
public async getOpenOrderStateAsync(signedOrder: SignedOrder, transactionHash?: string): Promise<OrderState> {
const orderRelevantState = await this.getOpenOrderRelevantStateAsync(signedOrder);
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
const isOrderCancelled = await this._orderFilledCancelledFetcher.isOrderCancelledAsync(signedOrder);
const sidedOrderRelevantState = {
isMakerSide: true,
traderBalance: orderRelevantState.makerBalance,
traderIndividualBalances: orderRelevantState.makerIndividualBalances,
traderProxyAllowance: orderRelevantState.makerProxyAllowance,
traderIndividualProxyAllowances: orderRelevantState.makerIndividualProxyAllowances,
traderFeeBalance: orderRelevantState.makerFeeBalance,
traderFeeProxyAllowance: orderRelevantState.makerFeeProxyAllowance,
filledTakerAssetAmount: orderRelevantState.filledTakerAssetAmount,
remainingFillableAssetAmount: orderRelevantState.remainingFillableMakerAssetAmount,
isOrderCancelled,
};
const orderValidationResult = OrderStateUtils._validateIfOrderIsValid(signedOrder, sidedOrderRelevantState);
if (orderValidationResult.isValid) {
const orderState: OrderStateValid = {
isValid: true,
orderHash,
orderRelevantState,
transactionHash,
};
return orderState;
} else {
const orderState: OrderStateInvalid = {
isValid: false,
orderHash,
error: orderValidationResult.error,
transactionHash,
};
return orderState;
}
}
/**
* Get state relevant to an order (i.e makerBalance, makerAllowance, filledTakerAssetAmount, etc...
* @param signedOrder Order of interest
* @return An instance of OrderRelevantState
*/
public async getOpenOrderRelevantStateAsync(signedOrder: SignedOrder): Promise<OrderRelevantState> {
const isMaker = true;
const sidedOrderRelevantState = await this._getSidedOrderRelevantStateAsync(
isMaker,
signedOrder,
signedOrder.takerAddress,
);
const remainingFillableTakerAssetAmount = sidedOrderRelevantState.remainingFillableAssetAmount
.times(signedOrder.takerAssetAmount)
.dividedToIntegerBy(signedOrder.makerAssetAmount);
const orderRelevantState = {
makerBalance: sidedOrderRelevantState.traderBalance,
makerIndividualBalances: sidedOrderRelevantState.traderIndividualBalances,
makerProxyAllowance: sidedOrderRelevantState.traderProxyAllowance,
makerIndividualProxyAllowances: sidedOrderRelevantState.traderIndividualProxyAllowances,
makerFeeBalance: sidedOrderRelevantState.traderFeeBalance,
makerFeeProxyAllowance: sidedOrderRelevantState.traderFeeProxyAllowance,
filledTakerAssetAmount: sidedOrderRelevantState.filledTakerAssetAmount,
remainingFillableMakerAssetAmount: sidedOrderRelevantState.remainingFillableAssetAmount,
remainingFillableTakerAssetAmount,
};
return orderRelevantState;
}
/**
* Get the max amount of the supplied order's takerAmount that could still be filled
* @param signedOrder Order of interest
* @param takerAddress Hypothetical taker of the order
* @return fillableTakerAssetAmount
*/
public async getMaxFillableTakerAssetAmountAsync(
signedOrder: SignedOrder,
takerAddress: string,
): Promise<BigNumber> {
// Get max fillable amount for an order, considering the makers ability to fill
let isMaker = true;
const orderRelevantMakerState = await this._getSidedOrderRelevantStateAsync(
isMaker,
signedOrder,
signedOrder.takerAddress,
);
const remainingFillableTakerAssetAmountGivenMakersStatus = signedOrder.makerAssetAmount.eq(0)
? new BigNumber(0)
: utils.getPartialAmountFloor(
orderRelevantMakerState.remainingFillableAssetAmount,
signedOrder.makerAssetAmount,
signedOrder.takerAssetAmount,
);
// Get max fillable amount for an order, considering the takers ability to fill
isMaker = false;
const orderRelevantTakerState = await this._getSidedOrderRelevantStateAsync(isMaker, signedOrder, takerAddress);
const remainingFillableTakerAssetAmountGivenTakersStatus = orderRelevantTakerState.remainingFillableAssetAmount;
// The min of these two in the actualy max fillable by either party
const fillableTakerAssetAmount = BigNumber.min(
remainingFillableTakerAssetAmountGivenMakersStatus,
remainingFillableTakerAssetAmountGivenTakersStatus,
);
return fillableTakerAssetAmount;
}
private async _getSidedOrderRelevantStateAsync(
isMakerSide: boolean,
signedOrder: SignedOrder,
takerAddress: string,
): Promise<SidedOrderRelevantState> {
let traderAddress;
let assetData;
let assetAmount;
let feeAssetData;
let feeAmount;
if (isMakerSide) {
traderAddress = signedOrder.makerAddress;
assetData = signedOrder.makerAssetData;
assetAmount = signedOrder.makerAssetAmount;
feeAssetData = signedOrder.makerFeeAssetData;
feeAmount = signedOrder.makerFee;
} else {
traderAddress = takerAddress;
assetData = signedOrder.takerAssetData;
assetAmount = signedOrder.takerAssetAmount;
feeAssetData = signedOrder.takerFeeAssetData;
feeAmount = signedOrder.takerFee;
}
const isPercentageFee = assetData === feeAssetData;
const traderBalance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync(assetData, traderAddress);
const traderIndividualBalances = await this._getAssetBalancesAsync(assetData, traderAddress);
const traderProxyAllowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync(
assetData,
traderAddress,
);
const traderIndividualProxyAllowances = await this._getAssetProxyAllowancesAsync(assetData, traderAddress);
const traderFeeBalance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync(
feeAssetData,
traderAddress,
);
const traderFeeProxyAllowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync(
feeAssetData,
traderAddress,
);
const transferrableTraderAssetAmount = BigNumber.min(traderProxyAllowance, traderBalance);
const transferrableFeeAssetAmount = BigNumber.min(traderFeeProxyAllowance, traderFeeBalance);
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
const filledTakerAssetAmount = await this._orderFilledCancelledFetcher.getFilledTakerAmountAsync(orderHash);
const totalMakerAssetAmount = signedOrder.makerAssetAmount;
const totalTakerAssetAmount = signedOrder.takerAssetAmount;
const isOrderCancelled = await this._orderFilledCancelledFetcher.isOrderCancelledAsync(signedOrder);
const remainingTakerAssetAmount = isOrderCancelled
? new BigNumber(0)
: totalTakerAssetAmount.minus(filledTakerAssetAmount);
const remainingMakerAssetAmount = remainingTakerAssetAmount.eq(0)
? new BigNumber(0)
: remainingTakerAssetAmount.times(totalMakerAssetAmount).dividedToIntegerBy(totalTakerAssetAmount);
const remainingAssetAmount = isMakerSide ? remainingMakerAssetAmount : remainingTakerAssetAmount;
const remainingFillableCalculator = new RemainingFillableCalculator(
feeAmount,
assetAmount,
isPercentageFee,
transferrableTraderAssetAmount,
transferrableFeeAssetAmount,
remainingAssetAmount,
);
const remainingFillableAssetAmount = remainingFillableCalculator.computeRemainingFillable();
const sidedOrderRelevantState = {
isMakerSide,
traderBalance,
traderIndividualBalances,
traderProxyAllowance,
traderIndividualProxyAllowances,
traderFeeBalance,
traderFeeProxyAllowance,
filledTakerAssetAmount,
remainingFillableAssetAmount,
isOrderCancelled,
};
return sidedOrderRelevantState;
}
private async _getAssetBalancesAsync(
assetData: string,
traderAddress: string,
initialBalances: ObjectMap<BigNumber> = {},
): Promise<ObjectMap<BigNumber>> {
const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
let balances: ObjectMap<BigNumber> = { ...initialBalances };
if (isERC20AssetData(decodedAssetData) || isERC721AssetData(decodedAssetData)) {
const balance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync(assetData, traderAddress);
// tslint:disable-next-line:no-unnecessary-type-assertion
const tokenAddress = (decodedAssetData as ERC20AssetData | ERC721AssetData).tokenAddress;
balances[tokenAddress] =
initialBalances[tokenAddress] === undefined ? balance : balances[tokenAddress].plus(balance);
} else if (isMultiAssetData(decodedAssetData)) {
for (const assetDataElement of (decodedAssetData as MultiAssetData).nestedAssetData) {
balances = await this._getAssetBalancesAsync(assetDataElement, traderAddress, balances);
}
}
return balances;
}
private async _getAssetProxyAllowancesAsync(
assetData: string,
traderAddress: string,
initialAllowances: ObjectMap<BigNumber> = {},
): Promise<ObjectMap<BigNumber>> {
const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
let allowances: ObjectMap<BigNumber> = { ...initialAllowances };
if (isERC20AssetData(decodedAssetData) || isERC721AssetData(decodedAssetData)) {
const allowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync(
assetData,
traderAddress,
);
// tslint:disable-next-line:no-unnecessary-type-assertion
const tokenAddress = (decodedAssetData as ERC20AssetData | ERC721AssetData).tokenAddress;
allowances[tokenAddress] =
initialAllowances[tokenAddress] === undefined ? allowance : allowances[tokenAddress].plus(allowance);
} else if (isMultiAssetData(decodedAssetData)) {
for (const assetDataElement of (decodedAssetData as MultiAssetData).nestedAssetData) {
allowances = await this._getAssetBalancesAsync(assetDataElement, traderAddress, allowances);
}
}
return allowances;
}
}
function isERC20AssetData(decodedAssetData: SingleAssetData | MultiAssetData): boolean {
return decodedAssetData.assetProxyId === AssetProxyId.ERC20;
}
function isERC721AssetData(decodedAssetData: SingleAssetData | MultiAssetData): boolean {
return decodedAssetData.assetProxyId === AssetProxyId.ERC721;
}
function isMultiAssetData(decodedAssetData: SingleAssetData | MultiAssetData): boolean {
return decodedAssetData.assetProxyId === AssetProxyId.MultiAsset;
}

View File

@ -1,204 +0,0 @@
import { ExchangeContractErrs, RevertReason, SignedOrder } from '@0x/types';
import { BigNumber, providerUtils } from '@0x/utils';
import { SupportedProvider, ZeroExProvider } from 'ethereum-types';
import * as _ from 'lodash';
import { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher';
import { constants } from './constants';
import { ExchangeTransferSimulator } from './exchange_transfer_simulator';
import { orderHashUtils } from './order_hash';
import { signatureUtils } from './signature_utils';
import { TradeSide, TransferType, TypedDataError } from './types';
import { utils } from './utils';
/**
* A utility class for validating orders
*/
export class OrderValidationUtils {
private readonly _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher;
private readonly _provider: ZeroExProvider;
/**
* A TypeScript implementation mirroring the implementation of isRoundingError in the
* Exchange smart contract
* @param numerator Numerator value. When used to check an order, pass in `takerAssetFilledAmount`
* @param denominator Denominator value. When used to check an order, pass in `order.takerAssetAmount`
* @param target Target value. When used to check an order, pass in `order.makerAssetAmount`
*/
public static isRoundingErrorFloor(numerator: BigNumber, denominator: BigNumber, target: BigNumber): boolean {
// Solidity's mulmod() in JS
// Source: https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#mathematical-and-cryptographic-functions
if (denominator.eq(0)) {
throw new Error('denominator cannot be 0');
}
const remainder = target.multipliedBy(numerator).mod(denominator);
if (remainder.eq(0)) {
return false; // no rounding error
}
// tslint:disable-next-line:custom-no-magic-numbers
const errPercentageTimes1000000 = remainder.multipliedBy(1000000).div(numerator.multipliedBy(target));
// tslint:disable-next-line:custom-no-magic-numbers
const isError = errPercentageTimes1000000.gt(1000);
return isError;
}
/**
* Validate that the maker & taker have sufficient balances/allowances
* to fill the supplied order to the fillTakerAssetAmount amount
* @param exchangeTradeEmulator ExchangeTradeEmulator to use
* @param signedOrder SignedOrder to test
* @param fillTakerAssetAmount Amount of takerAsset to fill the signedOrder
* @param senderAddress Sender of the fillOrder tx
*/
public static async validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
exchangeTradeEmulator: ExchangeTransferSimulator,
signedOrder: SignedOrder,
fillTakerAssetAmount: BigNumber,
senderAddress: string,
): Promise<void> {
const fillMakerTokenAmount = utils.getPartialAmountFloor(
fillTakerAssetAmount,
signedOrder.takerAssetAmount,
signedOrder.makerAssetAmount,
);
const makerFeeAmount = utils.getPartialAmountFloor(
fillTakerAssetAmount,
signedOrder.takerAssetAmount,
signedOrder.makerFee,
);
const takerFeeAmount = utils.getPartialAmountFloor(
fillTakerAssetAmount,
signedOrder.takerAssetAmount,
signedOrder.takerFee,
);
await exchangeTradeEmulator.transferFromAsync(
signedOrder.makerAssetData,
signedOrder.makerAddress,
senderAddress,
fillMakerTokenAmount,
TradeSide.Maker,
TransferType.Trade,
);
await exchangeTradeEmulator.transferFromAsync(
signedOrder.takerAssetData,
senderAddress,
signedOrder.makerAddress,
fillTakerAssetAmount,
TradeSide.Taker,
TransferType.Trade,
);
await exchangeTradeEmulator.transferFromAsync(
signedOrder.makerFeeAssetData,
signedOrder.makerAddress,
signedOrder.feeRecipientAddress,
makerFeeAmount,
TradeSide.Maker,
TransferType.Fee,
);
await exchangeTradeEmulator.transferFromAsync(
signedOrder.takerFeeAssetData,
senderAddress,
signedOrder.feeRecipientAddress,
takerFeeAmount,
TradeSide.Taker,
TransferType.Fee,
);
}
private static _validateOrderNotExpiredOrThrow(expirationTimeSeconds: BigNumber): void {
const currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
if (expirationTimeSeconds.isLessThan(currentUnixTimestampSec)) {
throw new Error(RevertReason.OrderUnfillable);
}
}
/**
* Instantiate OrderValidationUtils
* @param orderFilledCancelledFetcher A module that implements the AbstractOrderFilledCancelledFetcher
* @param supportedProvider Web3 provider to use for JSON RPC calls
* @return An instance of OrderValidationUtils
*/
constructor(
orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher,
supportedProvider: SupportedProvider,
) {
this._orderFilledCancelledFetcher = orderFilledCancelledFetcher;
this._provider = providerUtils.standardizeOrThrow(supportedProvider);
}
/**
* Validate a call to FillOrder and throw if it wouldn't succeed
* @param exchangeTradeEmulator ExchangeTradeEmulator to use
* @param signedOrder SignedOrder of interest
* @param fillTakerAssetAmount Amount we'd like to fill the order for
* @param takerAddress The taker of the order
*/
public async validateFillOrderThrowIfInvalidAsync(
exchangeTradeEmulator: ExchangeTransferSimulator,
signedOrder: SignedOrder,
fillTakerAssetAmount: BigNumber,
takerAddress: string,
): Promise<BigNumber> {
OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationTimeSeconds);
if (signedOrder.makerAssetAmount.eq(0) || signedOrder.takerAssetAmount.eq(0)) {
throw new Error(RevertReason.OrderUnfillable);
}
if (fillTakerAssetAmount.eq(0)) {
throw new Error(RevertReason.InvalidTakerAmount);
}
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
const isValid = await signatureUtils.isValidSignatureAsync(
this._provider,
orderHash,
signedOrder.signature,
signedOrder.makerAddress,
);
if (!isValid) {
throw new Error(TypedDataError.InvalidSignature);
}
const filledTakerTokenAmount = await this._orderFilledCancelledFetcher.getFilledTakerAmountAsync(orderHash);
if (signedOrder.takerAssetAmount.eq(filledTakerTokenAmount)) {
throw new Error(RevertReason.OrderUnfillable);
}
if (signedOrder.takerAddress !== constants.NULL_ADDRESS && signedOrder.takerAddress !== takerAddress) {
throw new Error(RevertReason.InvalidTaker);
}
const remainingTakerTokenAmount = signedOrder.takerAssetAmount.minus(filledTakerTokenAmount);
const desiredFillTakerTokenAmount = remainingTakerTokenAmount.isLessThan(fillTakerAssetAmount)
? remainingTakerTokenAmount
: fillTakerAssetAmount;
try {
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
exchangeTradeEmulator,
signedOrder,
desiredFillTakerTokenAmount,
takerAddress,
);
} catch (err) {
const transferFailedErrorMessages = [
ExchangeContractErrs.InsufficientMakerBalance,
ExchangeContractErrs.InsufficientMakerFeeBalance,
ExchangeContractErrs.InsufficientTakerBalance,
ExchangeContractErrs.InsufficientTakerFeeBalance,
ExchangeContractErrs.InsufficientMakerAllowance,
ExchangeContractErrs.InsufficientMakerFeeAllowance,
ExchangeContractErrs.InsufficientTakerAllowance,
ExchangeContractErrs.InsufficientTakerFeeAllowance,
];
if (_.includes(transferFailedErrorMessages, err.message)) {
throw new Error(RevertReason.TransferFailed);
}
throw err;
}
const wouldRoundingErrorOccur = OrderValidationUtils.isRoundingErrorFloor(
desiredFillTakerTokenAmount,
signedOrder.takerAssetAmount,
signedOrder.makerAssetAmount,
);
if (wouldRoundingErrorOccur) {
throw new Error(RevertReason.RoundingError);
}
return filledTakerTokenAmount;
}
}

View File

@ -5,16 +5,6 @@ export enum TypedDataError {
InvalidMetamaskSigner = "MetaMask provider must be wrapped in a MetamaskSubprovider (from the '@0x/subproviders' package) in order to work with this method.",
}
export enum TradeSide {
Maker = 'maker',
Taker = 'taker',
}
export enum TransferType {
Trade = 'trade',
Fee = 'fee',
}
export interface CreateOrderOpts {
takerAddress?: string;
senderAddress?: string;

View File

@ -1,142 +0,0 @@
import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import 'mocha';
import { AbstractBalanceAndProxyAllowanceFetcher } from '../src/abstract/abstract_balance_and_proxy_allowance_fetcher';
import { AbstractOrderFilledCancelledFetcher } from '../src/abstract/abstract_order_filled_cancelled_fetcher';
import { OrderStateUtils } from '../src/order_state_utils';
import { chaiSetup } from './utils/chai_setup';
import { testOrderFactory } from './utils/test_order_factory';
chaiSetup.configure();
const expect = chai.expect;
describe('OrderStateUtils', () => {
describe('#getOpenOrderStateAsync', () => {
const buildMockBalanceFetcher = (takerBalance: BigNumber): AbstractBalanceAndProxyAllowanceFetcher => {
const balanceFetcher = {
async getBalanceAsync(_assetData: string, _userAddress: string): Promise<BigNumber> {
return takerBalance;
},
async getProxyAllowanceAsync(_assetData: string, _userAddress: string): Promise<BigNumber> {
return takerBalance;
},
};
return balanceFetcher;
};
const buildMockOrderFilledFetcher = (
filledAmount: BigNumber = new BigNumber(0),
cancelled: boolean = false,
): AbstractOrderFilledCancelledFetcher => {
const orderFetcher = {
async getFilledTakerAmountAsync(_orderHash: string): Promise<BigNumber> {
return filledAmount;
},
async isOrderCancelledAsync(_signedOrder: SignedOrder): Promise<boolean> {
return cancelled;
},
};
return orderFetcher;
};
it('should have valid order state if order can be fully filled with small maker amount', async () => {
const makerAssetAmount = new BigNumber(10);
const takerAssetAmount = new BigNumber(10000000000000000);
const takerBalance = takerAssetAmount;
const orderFilledAmount = new BigNumber(0);
const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance);
const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount);
const [signedOrder] = testOrderFactory.generateTestSignedOrders(
{
makerAssetAmount,
takerAssetAmount,
},
1,
);
const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher);
const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder);
expect(orderState.isValid).to.eq(true);
});
it('should be invalid when an order is partially filled where only a rounding error remains', async () => {
const makerAssetAmount = new BigNumber(1001);
const takerAssetAmount = new BigNumber(3);
const takerBalance = takerAssetAmount;
const orderFilledAmount = new BigNumber(2);
const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance);
const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount);
const [signedOrder] = testOrderFactory.generateTestSignedOrders(
{
makerAssetAmount,
takerAssetAmount,
},
1,
);
const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher);
const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder);
expect(orderState.isValid).to.eq(false);
});
it('should be invalid when an order is cancelled', async () => {
const makerAssetAmount = new BigNumber(1000);
const takerAssetAmount = new BigNumber(2);
const takerBalance = takerAssetAmount;
const orderFilledAmount = new BigNumber(0);
const isCancelled = true;
const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance);
const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount, isCancelled);
const [signedOrder] = testOrderFactory.generateTestSignedOrders(
{
makerAssetAmount,
takerAssetAmount,
},
1,
);
const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher);
const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder);
expect(orderState.isValid).to.eq(false);
});
it('should be invalid when an order is fully filled', async () => {
const makerAssetAmount = new BigNumber(1000);
const takerAssetAmount = new BigNumber(2);
const takerBalance = takerAssetAmount;
const orderFilledAmount = takerAssetAmount;
const isCancelled = false;
const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance);
const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount, isCancelled);
const [signedOrder] = testOrderFactory.generateTestSignedOrders(
{
makerAssetAmount,
takerAssetAmount,
},
1,
);
const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher);
const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder);
expect(orderState.isValid).to.eq(false);
});
it('should include the transactionHash in orderState if supplied in method invocation', async () => {
const makerAssetAmount = new BigNumber(10);
const takerAssetAmount = new BigNumber(10000000000000000);
const takerBalance = takerAssetAmount;
const orderFilledAmount = new BigNumber(0);
const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance);
const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount);
const [signedOrder] = testOrderFactory.generateTestSignedOrders(
{
makerAssetAmount,
takerAssetAmount,
},
1,
);
const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher);
const transactionHash = '0xdeadbeef';
const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder, transactionHash);
expect(orderState.transactionHash).to.eq(transactionHash);
});
});
});

View File

@ -1,70 +0,0 @@
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import 'mocha';
import { OrderValidationUtils } from '../src/order_validation_utils';
import { chaiSetup } from './utils/chai_setup';
chaiSetup.configure();
const expect = chai.expect;
describe('OrderValidationUtils', () => {
describe('#isRoundingError', () => {
it('should return false if there is a rounding error of 0.1%', async () => {
const numerator = new BigNumber(20);
const denominator = new BigNumber(999);
const target = new BigNumber(50);
// rounding error = ((20*50/999) - floor(20*50/999)) / (20*50/999) = 0.1%
const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target);
expect(isRoundingError).to.be.false();
});
it('should return false if there is a rounding of 0.09%', async () => {
const numerator = new BigNumber(20);
const denominator = new BigNumber(9991);
const target = new BigNumber(500);
// rounding error = ((20*500/9991) - floor(20*500/9991)) / (20*500/9991) = 0.09%
const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target);
expect(isRoundingError).to.be.false();
});
it('should return true if there is a rounding error of 0.11%', async () => {
const numerator = new BigNumber(20);
const denominator = new BigNumber(9989);
const target = new BigNumber(500);
// rounding error = ((20*500/9989) - floor(20*500/9989)) / (20*500/9989) = 0.011%
const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target);
expect(isRoundingError).to.be.true();
});
it('should return true if there is a rounding error > 0.1%', async () => {
const numerator = new BigNumber(3);
const denominator = new BigNumber(7);
const target = new BigNumber(10);
// rounding error = ((3*10/7) - floor(3*10/7)) / (3*10/7) = 6.67%
const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target);
expect(isRoundingError).to.be.true();
});
it('should return false when there is no rounding error', async () => {
const numerator = new BigNumber(1);
const denominator = new BigNumber(2);
const target = new BigNumber(10);
const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target);
expect(isRoundingError).to.be.false();
});
it('should return false when there is rounding error <= 0.1%', async () => {
// randomly generated numbers
const numerator = new BigNumber(76564);
const denominator = new BigNumber(676373677);
const target = new BigNumber(105762562);
// rounding error = ((76564*105762562/676373677) - floor(76564*105762562/676373677)) /
// (76564*105762562/676373677) = 0.0007%
const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target);
expect(isRoundingError).to.be.false();
});
});
});

View File

@ -30,7 +30,6 @@ CONTRACTS_TO_BE_WRAPPED = [
"erc20_token",
"erc721_proxy",
"erc721_token",
"eth_balance_checker",
"exchange",
"forwarder",
"i_asset_proxy",

View File

@ -97,14 +97,6 @@ zero_ex.contract_wrappers.erc721_token
:special-members:
zero_ex.contract_wrappers.eth_balance_checker
=============================================
.. automodule:: zero_ex.contract_wrappers.eth_balance_checker
:members:
:special-members:
zero_ex.contract_wrappers.exchange
==================================

View File

@ -38,9 +38,24 @@ To replicate this setup, one could run the following commands:
docker run -d -p 8545:8545 0xorg/ganache-cli
docker run -d -p 60557:60557 --network host \
-e ETHEREUM_RPC_URL=http://localhost:8545 \
-e ETHEREUM_NETWORK_ID=50 \
-e ETHEREUM_CHAIN_ID=1337 \
-e USE_BOOTSTRAP_LIST=false \
-e VERBOSITY=3 \
-e PRIVATE_KEY_PATH= \
-e BLOCK_POLLING_INTERVAL=5s \
-e P2P_LISTEN_PORT=60557
0xorg/mesh:6.0.0-beta-0xv3
docker run -d --network host \
-e RPC_URL=http://localhost:8545 \
-e NETWORK_ID=50 \
-e CHAIN_ID=1337 \
-e FEE_RECIPIENT=0x0000000000000000000000000000000000000001 \
-e MAKER_FEE_UNIT_AMOUNT=0 \
-e TAKER_FEE_UNIT_AMOUNT=0
-e MESH_ENDPOINT=ws://localhost:60557
-e WHITELIST_ALL_TOKENS=True \
0xorg/launch-kit-ci
@ -168,7 +183,7 @@ Retrieve the order we just posted:
>>> relayer.get_order("0x" + order_hash_hex)
{'meta_data': {'orderHash': '0x...',
'remainingFillableTakerAssetAmount': '2'},
'order': {'chainId': 50,
'order': {'chainId': 1337,
'exchangeAddress': '0x...',
'expirationTimeSeconds': '...',
'feeRecipientAddress': '0x0000000000000000000000000000000000000000',
@ -195,7 +210,7 @@ of the one we just posted:
>>> relayer.get_orders()
{'records': [{'meta_data': {'orderHash': '0x...',
'remainingFillableTakerAssetAmount': '2'},
'order': {'chainId': 50,
'order': {'chainId': 1337,
'exchangeAddress': '0x...',
'expirationTimeSeconds': '...',
'feeRecipientAddress': '0x0000000000000000000000000000000000000000',
@ -255,7 +270,7 @@ consists just of our order):
{'asks': {'records': [...]},
'bids': {'records': [{'meta_data': {'orderHash': '0x...',
'remainingFillableTakerAssetAmount': '2'},
'order': {'chainId': 50,
'order': {'chainId': 1337,
'exchangeAddress': '0x...',
'expirationTimeSeconds': '...',
'feeRecipientAddress': '0x0000000000000000000000000000000000000000',
@ -280,7 +295,7 @@ Select an order from the orderbook
>>> order = jsdict_to_order(orderbook.bids.records[0].order)
>>> from pprint import pprint
>>> pprint(order)
{'chainId': 50,
{'chainId': 1337,
'expirationTimeSeconds': ...,
'feeRecipientAddress': '0x0000000000000000000000000000000000000000',
'makerAddress': '0x...',

View File

@ -35,7 +35,7 @@ services:
- "3000:3000"
network_mode: "host" # to connect to ganache
environment:
- NETWORK_ID=50
- CHAIN_ID=1337
- RPC_URL=http://localhost:8545
- WHITELIST_ALL_TOKENS=True
- FEE_RECIPIENT=0x0000000000000000000000000000000000000001