diff options
author | Greg Hysen <greg.hysen@gmail.com> | 2018-12-21 07:39:19 +0800 |
---|---|---|
committer | Greg Hysen <greg.hysen@gmail.com> | 2019-01-08 07:50:48 +0800 |
commit | 43b648e7dc1ea49aff3ab1e6883aa6e069fae72f (patch) | |
tree | 7db4b13135cc91a1c217c78766667e85cfc62e14 | |
parent | 89fcbec43b04a49c45786067f61c539128e1c507 (diff) | |
download | dexon-sol-tools-43b648e7dc1ea49aff3ab1e6883aa6e069fae72f.tar.gz dexon-sol-tools-43b648e7dc1ea49aff3ab1e6883aa6e069fae72f.tar.zst dexon-sol-tools-43b648e7dc1ea49aff3ab1e6883aa6e069fae72f.zip |
Dutch wrapper
-rw-r--r-- | contracts/extensions/test/extensions/dutch_auction.ts | 50 | ||||
-rw-r--r-- | contracts/extensions/test/utils/dutch_auction_test_wrapper.ts (renamed from contracts/extensions/test/utils/dutch_auction_wrapper.ts) | 16 | ||||
-rw-r--r-- | packages/abi-gen-wrappers/package.json | 2 | ||||
-rw-r--r-- | packages/abi-gen-wrappers/src/generated-wrappers/dutch_auction.ts | 322 | ||||
-rw-r--r-- | packages/abi-gen-wrappers/src/index.ts | 1 | ||||
-rw-r--r-- | packages/contract-addresses/src/index.ts | 6 | ||||
-rw-r--r-- | packages/contract-artifacts/artifacts/DutchAuction.json | 392 | ||||
-rw-r--r-- | packages/contract-artifacts/src/index.ts | 2 | ||||
-rw-r--r-- | packages/contract-artifacts/tsconfig.json | 1 | ||||
-rw-r--r-- | packages/contract-wrappers/src/contract_wrappers.ts | 10 | ||||
-rw-r--r-- | packages/contract-wrappers/src/contract_wrappers/dutch_auction_wrapper.ts | 151 | ||||
-rw-r--r-- | packages/contract-wrappers/src/index.ts | 1 | ||||
-rw-r--r-- | packages/contract-wrappers/test/dutch_auction_wrapper_test.ts | 156 | ||||
-rw-r--r-- | packages/migrations/src/migration.ts | 9 | ||||
-rw-r--r-- | packages/order-utils/src/asset_data_utils.ts | 20 |
15 files changed, 1092 insertions, 47 deletions
diff --git a/contracts/extensions/test/extensions/dutch_auction.ts b/contracts/extensions/test/extensions/dutch_auction.ts index 5e1534594..cd5816810 100644 --- a/contracts/extensions/test/extensions/dutch_auction.ts +++ b/contracts/extensions/test/extensions/dutch_auction.ts @@ -34,7 +34,7 @@ import * as _ from 'lodash'; import { DutchAuctionContract } from '../../generated-wrappers/dutch_auction'; import { artifacts } from '../../src/artifacts'; -import { DutchAuctionWrapper } from '../utils/dutch_auction_wrapper'; +import { DutchAuctionTestWrapper } from '../utils/dutch_auction_test_wrapper'; chaiSetup.configure(); const expect = chai.expect; @@ -68,7 +68,7 @@ describe(ContractName.DutchAuction, () => { let erc721MakerAssetIds: BigNumber[]; const tenMinutesInSeconds = 10 * 60; - let dutchAuctionWrapper: DutchAuctionWrapper; + let dutchAuctionTestWrapper: DutchAuctionTestWrapper; let defaultERC20MakerAssetData: string; before(async () => { @@ -125,7 +125,7 @@ describe(ContractName.DutchAuction, () => { dutchAuctionInstance.address, provider, ); - dutchAuctionWrapper = new DutchAuctionWrapper(dutchAuctionInstance, provider); + dutchAuctionTestWrapper = new DutchAuctionTestWrapper(dutchAuctionInstance, provider); defaultMakerAssetAddress = erc20TokenA.address; const defaultTakerAssetAddress = wethContract.address; @@ -164,7 +164,7 @@ describe(ContractName.DutchAuction, () => { feeRecipientAddress, // taker address or sender address should be set to the ducth auction contract takerAddress: dutchAuctionContract.address, - makerAssetData: assetDataUtils.encodeDutchAuctionAssetData( + makerAssetData: DutchAuctionTestWrapper.encodeDutchAuctionAssetData( assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress), auctionBeginTimeSeconds, auctionBeginAmount, @@ -206,13 +206,13 @@ describe(ContractName.DutchAuction, () => { describe('matchOrders', () => { it('should be worth the begin price at the begining of the auction', async () => { auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp + 2); - const makerAssetData = assetDataUtils.encodeDutchAuctionAssetData( + const makerAssetData = DutchAuctionTestWrapper.encodeDutchAuctionAssetData( defaultERC20MakerAssetData, auctionBeginTimeSeconds, auctionBeginAmount, ); sellOrder = await sellerOrderFactory.newSignedOrderAsync({ makerAssetData }); - const auctionDetails = await dutchAuctionWrapper.getAuctionDetailsAsync(sellOrder); + const auctionDetails = await dutchAuctionTestWrapper.getAuctionDetailsAsync(sellOrder); expect(auctionDetails.currentTimeSeconds).to.be.bignumber.lte(auctionBeginTimeSeconds); expect(auctionDetails.currentAmount).to.be.bignumber.equal(auctionBeginAmount); expect(auctionDetails.beginAmount).to.be.bignumber.equal(auctionBeginAmount); @@ -220,7 +220,7 @@ describe(ContractName.DutchAuction, () => { it('should be be worth the end price at the end of the auction', async () => { auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds * 2); auctionEndTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds); - const makerAssetData = assetDataUtils.encodeDutchAuctionAssetData( + const makerAssetData = DutchAuctionTestWrapper.encodeDutchAuctionAssetData( defaultERC20MakerAssetData, auctionBeginTimeSeconds, auctionBeginAmount, @@ -229,18 +229,18 @@ describe(ContractName.DutchAuction, () => { makerAssetData, expirationTimeSeconds: auctionEndTimeSeconds, }); - const auctionDetails = await dutchAuctionWrapper.getAuctionDetailsAsync(sellOrder); + const auctionDetails = await dutchAuctionTestWrapper.getAuctionDetailsAsync(sellOrder); expect(auctionDetails.currentTimeSeconds).to.be.bignumber.gte(auctionEndTimeSeconds); expect(auctionDetails.currentAmount).to.be.bignumber.equal(auctionEndAmount); expect(auctionDetails.beginAmount).to.be.bignumber.equal(auctionBeginAmount); }); it('should match orders at current amount and send excess to buyer', async () => { - const beforeAuctionDetails = await dutchAuctionWrapper.getAuctionDetailsAsync(sellOrder); + const beforeAuctionDetails = await dutchAuctionTestWrapper.getAuctionDetailsAsync(sellOrder); buyOrder = await buyerOrderFactory.newSignedOrderAsync({ makerAssetAmount: beforeAuctionDetails.currentAmount.times(2), }); - await dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress); - const afterAuctionDetails = await dutchAuctionWrapper.getAuctionDetailsAsync(sellOrder); + await dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress); + const afterAuctionDetails = await dutchAuctionTestWrapper.getAuctionDetailsAsync(sellOrder); const newBalances = await erc20Wrapper.getBalancesAsync(); expect(newBalances[dutchAuctionContract.address][wethContract.address]).to.be.bignumber.equal( constants.ZERO_AMOUNT, @@ -259,8 +259,8 @@ describe(ContractName.DutchAuction, () => { sellOrder = await sellerOrderFactory.newSignedOrderAsync({ makerFee: new BigNumber(1), }); - await dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress); - const afterAuctionDetails = await dutchAuctionWrapper.getAuctionDetailsAsync(sellOrder); + await dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress); + const afterAuctionDetails = await dutchAuctionTestWrapper.getAuctionDetailsAsync(sellOrder); const newBalances = await erc20Wrapper.getBalancesAsync(); expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte( erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount), @@ -273,9 +273,9 @@ describe(ContractName.DutchAuction, () => { buyOrder = await buyerOrderFactory.newSignedOrderAsync({ makerFee: new BigNumber(1), }); - await dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress); + await dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress); const newBalances = await erc20Wrapper.getBalancesAsync(); - const afterAuctionDetails = await dutchAuctionWrapper.getAuctionDetailsAsync(sellOrder); + const afterAuctionDetails = await dutchAuctionTestWrapper.getAuctionDetailsAsync(sellOrder); expect(newBalances[makerAddress][wethContract.address]).to.be.bignumber.gte( erc20Balances[makerAddress][wethContract.address].plus(afterAuctionDetails.currentAmount), ); @@ -286,7 +286,7 @@ describe(ContractName.DutchAuction, () => { it('should revert when auction expires', async () => { auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds * 2); auctionEndTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds); - const makerAssetData = assetDataUtils.encodeDutchAuctionAssetData( + const makerAssetData = DutchAuctionTestWrapper.encodeDutchAuctionAssetData( defaultERC20MakerAssetData, auctionBeginTimeSeconds, auctionBeginAmount, @@ -296,7 +296,7 @@ describe(ContractName.DutchAuction, () => { makerAssetData, }); return expectTransactionFailedAsync( - dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress), + dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress), RevertReason.AuctionExpired, ); }); @@ -305,7 +305,7 @@ describe(ContractName.DutchAuction, () => { makerAssetAmount: sellOrder.takerAssetAmount, }); return expectTransactionFailedAsync( - dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress), + dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress), RevertReason.AuctionInvalidAmount, ); }); @@ -314,13 +314,13 @@ describe(ContractName.DutchAuction, () => { takerAssetAmount: auctionBeginAmount.plus(1), }); return expectTransactionFailedAsync( - dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress), + dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress), RevertReason.AuctionInvalidAmount, ); }); it('begin time is less than end time', async () => { auctionBeginTimeSeconds = new BigNumber(auctionEndTimeSeconds).plus(tenMinutesInSeconds); - const makerAssetData = assetDataUtils.encodeDutchAuctionAssetData( + const makerAssetData = DutchAuctionTestWrapper.encodeDutchAuctionAssetData( defaultERC20MakerAssetData, auctionBeginTimeSeconds, auctionBeginAmount, @@ -330,7 +330,7 @@ describe(ContractName.DutchAuction, () => { makerAssetData, }); return expectTransactionFailedAsync( - dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress), + dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress), RevertReason.AuctionInvalidBeginTime, ); }); @@ -339,7 +339,7 @@ describe(ContractName.DutchAuction, () => { makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress), }); return expectTransactionFailedAsync( - dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress), + dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress), RevertReason.InvalidAssetData, ); }); @@ -348,7 +348,7 @@ describe(ContractName.DutchAuction, () => { it('should match orders when ERC721', async () => { const makerAssetId = erc721MakerAssetIds[0]; const erc721MakerAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId); - const makerAssetData = assetDataUtils.encodeDutchAuctionAssetData( + const makerAssetData = DutchAuctionTestWrapper.encodeDutchAuctionAssetData( erc721MakerAssetData, auctionBeginTimeSeconds, auctionBeginAmount, @@ -361,8 +361,8 @@ describe(ContractName.DutchAuction, () => { takerAssetAmount: new BigNumber(1), takerAssetData: sellOrder.makerAssetData, }); - await dutchAuctionWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress); - const afterAuctionDetails = await dutchAuctionWrapper.getAuctionDetailsAsync(sellOrder); + await dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress); + const afterAuctionDetails = await dutchAuctionTestWrapper.getAuctionDetailsAsync(sellOrder); const newBalances = await erc20Wrapper.getBalancesAsync(); // HACK gte used here due to a bug in ganache where the timestamp can change // between multiple calls to the same block. Which can move the amount in our case diff --git a/contracts/extensions/test/utils/dutch_auction_wrapper.ts b/contracts/extensions/test/utils/dutch_auction_test_wrapper.ts index 138b40ca9..653b9136c 100644 --- a/contracts/extensions/test/utils/dutch_auction_wrapper.ts +++ b/contracts/extensions/test/utils/dutch_auction_test_wrapper.ts @@ -5,11 +5,13 @@ import { DutchAuctionDetails, SignedOrder } from '@0x/types'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import * as _ from 'lodash'; +import { BigNumber } from '@0x/utils'; import { DutchAuctionContract } from '../../generated-wrappers/dutch_auction'; import { artifacts } from '../../src/artifacts'; +import { DutchAuctionWrapper } from '@0x/contract-wrappers'; -export class DutchAuctionWrapper { +export class DutchAuctionTestWrapper { private readonly _dutchAuctionContract: DutchAuctionContract; private readonly _web3Wrapper: Web3Wrapper; private readonly _logDecoder: LogDecoder; @@ -59,4 +61,16 @@ export class DutchAuctionWrapper { const afterAuctionDetails = await this._dutchAuctionContract.getAuctionDetails.callAsync(sellOrder); return afterAuctionDetails; } + /** + * Dutch auction details are encoded with the asset data for a 0x order. This function produces a hex + * encoded assetData string, containing information both about the asset being traded and the + * dutch auction; which is usable in the makerAssetData or takerAssetData fields in a 0x order. + * @param assetData Hex encoded assetData string for the asset being auctioned. + * @param beginTimeSeconds Begin time of the dutch auction. + * @param beginAmount Starting amount being sold in the dutch auction. + * @return The hex encoded assetData string. + */ + public static encodeDutchAuctionAssetData(assetData: string, beginTimeSeconds: BigNumber, beginAmount: BigNumber): string { + return DutchAuctionWrapper.encodeDutchAuctionAssetData(assetData, beginTimeSeconds, beginAmount); + }; } diff --git a/packages/abi-gen-wrappers/package.json b/packages/abi-gen-wrappers/package.json index 25ba3a6e0..38b5e9a9b 100644 --- a/packages/abi-gen-wrappers/package.json +++ b/packages/abi-gen-wrappers/package.json @@ -18,7 +18,7 @@ "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output src/generated-wrappers --backend ethers" }, "config": { - "abis": "../contract-artifacts/artifacts/@(AssetProxyOwner|DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC20Token|ERC721Proxy|ERC721Token|Exchange|Forwarder|IValidator|IWallet|OrderValidator|WETH9|ZRXToken).json" + "abis": "../contract-artifacts/artifacts/@(AssetProxyOwner|DutchAuction|DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC20Token|ERC721Proxy|ERC721Token|Exchange|Forwarder|IValidator|IWallet|OrderValidator|WETH9|ZRXToken).json" }, "repository": { "type": "git", diff --git a/packages/abi-gen-wrappers/src/generated-wrappers/dutch_auction.ts b/packages/abi-gen-wrappers/src/generated-wrappers/dutch_auction.ts new file mode 100644 index 000000000..90e233756 --- /dev/null +++ b/packages/abi-gen-wrappers/src/generated-wrappers/dutch_auction.ts @@ -0,0 +1,322 @@ +// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma whitespace class-name +// tslint:disable:no-unused-variable +// tslint:disable:no-unbound-method +import { BaseContract } from '@0x/base-contract'; +import { BlockParam, BlockParamLiteral, CallData, ContractAbi, ContractArtifact, DecodedLogArgs, MethodAbi, Provider, TxData, TxDataPayable } from 'ethereum-types'; +import { BigNumber, classUtils, logUtils } from '@0x/utils'; +import { SimpleContractArtifact } from '@0x/types'; +import { Web3Wrapper } from '@0x/web3-wrapper'; +import * as ethers from 'ethers'; +import * as _ from 'lodash'; +// tslint:enable:no-unused-variable + + +/* istanbul ignore next */ +// tslint:disable:no-parameter-reassignment +// tslint:disable-next-line:class-name +export class DutchAuctionContract extends BaseContract { + public getAuctionDetails = { + async sendTransactionAsync( + order: {makerAddress: string;takerAddress: string;feeRecipientAddress: string;senderAddress: string;makerAssetAmount: BigNumber;takerAssetAmount: BigNumber;makerFee: BigNumber;takerFee: BigNumber;expirationTimeSeconds: BigNumber;salt: BigNumber;makerAssetData: string;takerAssetData: string}, + txData: Partial<TxData> = {}, + ): Promise<string> { + const self = this as any as DutchAuctionContract; + const inputAbi = self._lookupAbi('getAuctionDetails({address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes})').inputs; + [order + ] = BaseContract._formatABIDataItemList(inputAbi, [order + ], BaseContract._bigNumberToString.bind(self)); + BaseContract.strictArgumentEncodingCheck(inputAbi, [order + ]); + const encodedData = self._lookupEthersInterface('getAuctionDetails({address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes})').functions.getAuctionDetails.encode([order + ]); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + self.getAuctionDetails.estimateGasAsync.bind( + self, + order + ), + ); + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); + return txHash; + }, + async estimateGasAsync( + order: {makerAddress: string;takerAddress: string;feeRecipientAddress: string;senderAddress: string;makerAssetAmount: BigNumber;takerAssetAmount: BigNumber;makerFee: BigNumber;takerFee: BigNumber;expirationTimeSeconds: BigNumber;salt: BigNumber;makerAssetData: string;takerAssetData: string}, + txData: Partial<TxData> = {}, + ): Promise<number> { + const self = this as any as DutchAuctionContract; + const inputAbi = self._lookupAbi('getAuctionDetails({address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes})').inputs; + [order + ] = BaseContract._formatABIDataItemList(inputAbi, [order + ], BaseContract._bigNumberToString); + const encodedData = self._lookupEthersInterface('getAuctionDetails({address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes})').functions.getAuctionDetails.encode([order + ]); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); + return gas; + }, + getABIEncodedTransactionData( + order: {makerAddress: string;takerAddress: string;feeRecipientAddress: string;senderAddress: string;makerAssetAmount: BigNumber;takerAssetAmount: BigNumber;makerFee: BigNumber;takerFee: BigNumber;expirationTimeSeconds: BigNumber;salt: BigNumber;makerAssetData: string;takerAssetData: string}, + ): string { + const self = this as any as DutchAuctionContract; + const inputAbi = self._lookupAbi('getAuctionDetails({address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes})').inputs; + [order + ] = BaseContract._formatABIDataItemList(inputAbi, [order + ], BaseContract._bigNumberToString); + const abiEncodedTransactionData = self._lookupEthersInterface('getAuctionDetails({address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes})').functions.getAuctionDetails.encode([order + ]); + return abiEncodedTransactionData; + }, + async callAsync( + order: {makerAddress: string;takerAddress: string;feeRecipientAddress: string;senderAddress: string;makerAssetAmount: BigNumber;takerAssetAmount: BigNumber;makerFee: BigNumber;takerFee: BigNumber;expirationTimeSeconds: BigNumber;salt: BigNumber;makerAssetData: string;takerAssetData: string}, + callData: Partial<CallData> = {}, + defaultBlock?: BlockParam, + ): Promise<{beginTimeSeconds: BigNumber;endTimeSeconds: BigNumber;beginAmount: BigNumber;endAmount: BigNumber;currentAmount: BigNumber;currentTimeSeconds: BigNumber} + > { + const self = this as any as DutchAuctionContract; + const functionSignature = 'getAuctionDetails({address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes})'; + const inputAbi = self._lookupAbi(functionSignature).inputs; + [order + ] = BaseContract._formatABIDataItemList(inputAbi, [order + ], BaseContract._bigNumberToString.bind(self)); + BaseContract.strictArgumentEncodingCheck(inputAbi, [order + ]); + const ethersFunction = self._lookupEthersInterface(functionSignature).functions.getAuctionDetails; + const encodedData = ethersFunction.encode([order + ]); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + BaseContract._throwIfRevertWithReasonCallResult(rawCallResult); + let resultArray = ethersFunction.decode(rawCallResult); + const outputAbi = (_.find(self.abi, {name: 'getAuctionDetails'}) as MethodAbi).outputs; + resultArray = BaseContract._formatABIDataItemList(outputAbi, resultArray, BaseContract._lowercaseAddress.bind(this)); + resultArray = BaseContract._formatABIDataItemList(outputAbi, resultArray, BaseContract._bnToBigNumber.bind(this)); + return resultArray[0]; + }, + }; + public matchOrders = { + async sendTransactionAsync( + buyOrder: {makerAddress: string;takerAddress: string;feeRecipientAddress: string;senderAddress: string;makerAssetAmount: BigNumber;takerAssetAmount: BigNumber;makerFee: BigNumber;takerFee: BigNumber;expirationTimeSeconds: BigNumber;salt: BigNumber;makerAssetData: string;takerAssetData: string}, + sellOrder: {makerAddress: string;takerAddress: string;feeRecipientAddress: string;senderAddress: string;makerAssetAmount: BigNumber;takerAssetAmount: BigNumber;makerFee: BigNumber;takerFee: BigNumber;expirationTimeSeconds: BigNumber;salt: BigNumber;makerAssetData: string;takerAssetData: string}, + buySignature: string, + sellSignature: string, + txData: Partial<TxData> = {}, + ): Promise<string> { + const self = this as any as DutchAuctionContract; + const inputAbi = self._lookupAbi('matchOrders({address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes},{address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes},bytes,bytes)').inputs; + [buyOrder, + sellOrder, + buySignature, + sellSignature + ] = BaseContract._formatABIDataItemList(inputAbi, [buyOrder, + sellOrder, + buySignature, + sellSignature + ], BaseContract._bigNumberToString.bind(self)); + BaseContract.strictArgumentEncodingCheck(inputAbi, [buyOrder, + sellOrder, + buySignature, + sellSignature + ]); + const encodedData = self._lookupEthersInterface('matchOrders({address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes},{address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes},bytes,bytes)').functions.matchOrders.encode([buyOrder, + sellOrder, + buySignature, + sellSignature + ]); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + self.matchOrders.estimateGasAsync.bind( + self, + buyOrder, + sellOrder, + buySignature, + sellSignature + ), + ); + const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults); + return txHash; + }, + async estimateGasAsync( + buyOrder: {makerAddress: string;takerAddress: string;feeRecipientAddress: string;senderAddress: string;makerAssetAmount: BigNumber;takerAssetAmount: BigNumber;makerFee: BigNumber;takerFee: BigNumber;expirationTimeSeconds: BigNumber;salt: BigNumber;makerAssetData: string;takerAssetData: string}, + sellOrder: {makerAddress: string;takerAddress: string;feeRecipientAddress: string;senderAddress: string;makerAssetAmount: BigNumber;takerAssetAmount: BigNumber;makerFee: BigNumber;takerFee: BigNumber;expirationTimeSeconds: BigNumber;salt: BigNumber;makerAssetData: string;takerAssetData: string}, + buySignature: string, + sellSignature: string, + txData: Partial<TxData> = {}, + ): Promise<number> { + const self = this as any as DutchAuctionContract; + const inputAbi = self._lookupAbi('matchOrders({address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes},{address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes},bytes,bytes)').inputs; + [buyOrder, + sellOrder, + buySignature, + sellSignature + ] = BaseContract._formatABIDataItemList(inputAbi, [buyOrder, + sellOrder, + buySignature, + sellSignature + ], BaseContract._bigNumberToString); + const encodedData = self._lookupEthersInterface('matchOrders({address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes},{address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes},bytes,bytes)').functions.matchOrders.encode([buyOrder, + sellOrder, + buySignature, + sellSignature + ]); + const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...txData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults); + return gas; + }, + getABIEncodedTransactionData( + buyOrder: {makerAddress: string;takerAddress: string;feeRecipientAddress: string;senderAddress: string;makerAssetAmount: BigNumber;takerAssetAmount: BigNumber;makerFee: BigNumber;takerFee: BigNumber;expirationTimeSeconds: BigNumber;salt: BigNumber;makerAssetData: string;takerAssetData: string}, + sellOrder: {makerAddress: string;takerAddress: string;feeRecipientAddress: string;senderAddress: string;makerAssetAmount: BigNumber;takerAssetAmount: BigNumber;makerFee: BigNumber;takerFee: BigNumber;expirationTimeSeconds: BigNumber;salt: BigNumber;makerAssetData: string;takerAssetData: string}, + buySignature: string, + sellSignature: string, + ): string { + const self = this as any as DutchAuctionContract; + const inputAbi = self._lookupAbi('matchOrders({address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes},{address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes},bytes,bytes)').inputs; + [buyOrder, + sellOrder, + buySignature, + sellSignature + ] = BaseContract._formatABIDataItemList(inputAbi, [buyOrder, + sellOrder, + buySignature, + sellSignature + ], BaseContract._bigNumberToString); + const abiEncodedTransactionData = self._lookupEthersInterface('matchOrders({address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes},{address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes},bytes,bytes)').functions.matchOrders.encode([buyOrder, + sellOrder, + buySignature, + sellSignature + ]); + return abiEncodedTransactionData; + }, + async callAsync( + buyOrder: {makerAddress: string;takerAddress: string;feeRecipientAddress: string;senderAddress: string;makerAssetAmount: BigNumber;takerAssetAmount: BigNumber;makerFee: BigNumber;takerFee: BigNumber;expirationTimeSeconds: BigNumber;salt: BigNumber;makerAssetData: string;takerAssetData: string}, + sellOrder: {makerAddress: string;takerAddress: string;feeRecipientAddress: string;senderAddress: string;makerAssetAmount: BigNumber;takerAssetAmount: BigNumber;makerFee: BigNumber;takerFee: BigNumber;expirationTimeSeconds: BigNumber;salt: BigNumber;makerAssetData: string;takerAssetData: string}, + buySignature: string, + sellSignature: string, + callData: Partial<CallData> = {}, + defaultBlock?: BlockParam, + ): Promise<{left: {makerAssetFilledAmount: BigNumber;takerAssetFilledAmount: BigNumber;makerFeePaid: BigNumber;takerFeePaid: BigNumber};right: {makerAssetFilledAmount: BigNumber;takerAssetFilledAmount: BigNumber;makerFeePaid: BigNumber;takerFeePaid: BigNumber};leftMakerAssetSpreadAmount: BigNumber} + > { + const self = this as any as DutchAuctionContract; + const functionSignature = 'matchOrders({address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes},{address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes},bytes,bytes)'; + const inputAbi = self._lookupAbi(functionSignature).inputs; + [buyOrder, + sellOrder, + buySignature, + sellSignature + ] = BaseContract._formatABIDataItemList(inputAbi, [buyOrder, + sellOrder, + buySignature, + sellSignature + ], BaseContract._bigNumberToString.bind(self)); + BaseContract.strictArgumentEncodingCheck(inputAbi, [buyOrder, + sellOrder, + buySignature, + sellSignature + ]); + const ethersFunction = self._lookupEthersInterface(functionSignature).functions.matchOrders; + const encodedData = ethersFunction.encode([buyOrder, + sellOrder, + buySignature, + sellSignature + ]); + const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync( + { + to: self.address, + ...callData, + data: encodedData, + }, + self._web3Wrapper.getContractDefaults(), + ); + const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); + BaseContract._throwIfRevertWithReasonCallResult(rawCallResult); + let resultArray = ethersFunction.decode(rawCallResult); + const outputAbi = (_.find(self.abi, {name: 'matchOrders'}) as MethodAbi).outputs; + resultArray = BaseContract._formatABIDataItemList(outputAbi, resultArray, BaseContract._lowercaseAddress.bind(this)); + resultArray = BaseContract._formatABIDataItemList(outputAbi, resultArray, BaseContract._bnToBigNumber.bind(this)); + return resultArray[0]; + }, + }; + public static async deployFrom0xArtifactAsync( + artifact: ContractArtifact | SimpleContractArtifact, + provider: Provider, + txDefaults: Partial<TxData>, + _exchange: string, + ): Promise<DutchAuctionContract> { + if (_.isUndefined(artifact.compilerOutput)) { + throw new Error('Compiler output not found in the artifact file'); + } + const bytecode = artifact.compilerOutput.evm.bytecode.object; + const abi = artifact.compilerOutput.abi; + return DutchAuctionContract.deployAsync(bytecode, abi, provider, txDefaults, _exchange +); + } + public static async deployAsync( + bytecode: string, + abi: ContractAbi, + provider: Provider, + txDefaults: Partial<TxData>, + _exchange: string, + ): Promise<DutchAuctionContract> { + const constructorAbi = BaseContract._lookupConstructorAbi(abi); + [_exchange +] = BaseContract._formatABIDataItemList( + constructorAbi.inputs, + [_exchange +], + BaseContract._bigNumberToString, + ); + const iface = new ethers.utils.Interface(abi); + const deployInfo = iface.deployFunction; + const txData = deployInfo.encode(bytecode, [_exchange +]); + 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(`DutchAuction successfully deployed at ${txReceipt.contractAddress}`); + const contractInstance = new DutchAuctionContract(abi, txReceipt.contractAddress as string, provider, txDefaults); + contractInstance.constructorArgs = [_exchange +]; + return contractInstance; + } + constructor(abi: ContractAbi, address: string, provider: Provider, txDefaults?: Partial<TxData>) { + super('DutchAuction', abi, address, provider, txDefaults); + classUtils.bindAll(this, ['_ethersInterfacesByFunctionSignature', 'address', 'abi', '_web3Wrapper']); + } +} // tslint:disable:max-file-line-count +// tslint:enable:no-unbound-method diff --git a/packages/abi-gen-wrappers/src/index.ts b/packages/abi-gen-wrappers/src/index.ts index de418214b..b5a7d0cfe 100644 --- a/packages/abi-gen-wrappers/src/index.ts +++ b/packages/abi-gen-wrappers/src/index.ts @@ -1,6 +1,7 @@ export * from './generated-wrappers/asset_proxy_owner'; export * from './generated-wrappers/dummy_erc20_token'; export * from './generated-wrappers/dummy_erc721_token'; +export * from './generated-wrappers/dutch_auction'; export * from './generated-wrappers/erc20_proxy'; export * from './generated-wrappers/erc20_token'; export * from './generated-wrappers/erc721_proxy'; diff --git a/packages/contract-addresses/src/index.ts b/packages/contract-addresses/src/index.ts index 7989631e3..5b8e95174 100644 --- a/packages/contract-addresses/src/index.ts +++ b/packages/contract-addresses/src/index.ts @@ -9,6 +9,7 @@ export interface ContractAddresses { assetProxyOwner: string; forwarder: string; orderValidator: string; + dutchAuction: string; } export enum NetworkId { @@ -29,6 +30,7 @@ const networkToAddresses: { [networkId: number]: ContractAddresses } = { assetProxyOwner: '0x17992e4ffb22730138e4b62aaa6367fa9d3699a6', forwarder: '0x5468a1dc173652ee28d249c271fa9933144746b1', orderValidator: '0x9463e518dea6810309563c81d5266c1b1d149138', + dutchAuction: '0x', }, 3: { erc20Proxy: '0xb1408f4c245a23c31b98d2c626777d4c0d766caa', @@ -39,6 +41,7 @@ const networkToAddresses: { [networkId: number]: ContractAddresses } = { assetProxyOwner: '0xf5fa5b5fed2727a0e44ac67f6772e97977aa358b', forwarder: '0x2240dab907db71e64d3e0dba4800c83b5c502d4e', orderValidator: '0x90431a90516ab49af23a0530e04e8c7836e7122f', + dutchAuction: '0x', }, 4: { exchange: '0xbce0b5f6eb618c565c3e5f5cd69652bbc279f44e', @@ -49,6 +52,7 @@ const networkToAddresses: { [networkId: number]: ContractAddresses } = { assetProxyOwner: '0xe1703da878afcebff5b7624a826902af475b9c03', forwarder: '0x2d40589abbdee84961f3a7656b9af7adb0ee5ab4', orderValidator: '0x0c5173a51e26b29d6126c686756fb9fbef71f762', + dutchAuction: '0x', }, 42: { erc20Proxy: '0xf1ec01d6236d3cd881a0bf0130ea25fe4234003e', @@ -59,6 +63,7 @@ const networkToAddresses: { [networkId: number]: ContractAddresses } = { assetProxyOwner: '0x2c824d2882baa668e0d5202b1e7f2922278703f8', forwarder: '0x17992e4ffb22730138e4b62aaa6367fa9d3699a6', orderValidator: '0xb389da3d204b412df2f75c6afb3d0a7ce0bc283d', + dutchAuction: '0x', }, // NetworkId 50 represents our Ganache snapshot generated from migrations. 50: { @@ -70,6 +75,7 @@ const networkToAddresses: { [networkId: number]: ContractAddresses } = { assetProxyOwner: '0x34d402f14d58e001d8efbe6585051bf9706aa064', forwarder: '0xb69e673309512a9d726f87304c6984054f87a93b', orderValidator: '0xe86bb98fcf9bff3512c74589b78fb168200cc546', + dutchAuction: '0x', }, }; diff --git a/packages/contract-artifacts/artifacts/DutchAuction.json b/packages/contract-artifacts/artifacts/DutchAuction.json new file mode 100644 index 000000000..2c1998034 --- /dev/null +++ b/packages/contract-artifacts/artifacts/DutchAuction.json @@ -0,0 +1,392 @@ +{ + "schemaVersion": "2.0.0", + "contractName": "DutchAuction", + "compilerOutput": { + "abi": [ + { + "constant": false, + "inputs": [ + { + "components": [ + { + "name": "makerAddress", + "type": "address" + }, + { + "name": "takerAddress", + "type": "address" + }, + { + "name": "feeRecipientAddress", + "type": "address" + }, + { + "name": "senderAddress", + "type": "address" + }, + { + "name": "makerAssetAmount", + "type": "uint256" + }, + { + "name": "takerAssetAmount", + "type": "uint256" + }, + { + "name": "makerFee", + "type": "uint256" + }, + { + "name": "takerFee", + "type": "uint256" + }, + { + "name": "expirationTimeSeconds", + "type": "uint256" + }, + { + "name": "salt", + "type": "uint256" + }, + { + "name": "makerAssetData", + "type": "bytes" + }, + { + "name": "takerAssetData", + "type": "bytes" + } + ], + "name": "order", + "type": "tuple" + } + ], + "name": "getAuctionDetails", + "outputs": [ + { + "components": [ + { + "name": "beginTimeSeconds", + "type": "uint256" + }, + { + "name": "endTimeSeconds", + "type": "uint256" + }, + { + "name": "beginAmount", + "type": "uint256" + }, + { + "name": "endAmount", + "type": "uint256" + }, + { + "name": "currentAmount", + "type": "uint256" + }, + { + "name": "currentTimeSeconds", + "type": "uint256" + } + ], + "name": "auctionDetails", + "type": "tuple" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "components": [ + { + "name": "makerAddress", + "type": "address" + }, + { + "name": "takerAddress", + "type": "address" + }, + { + "name": "feeRecipientAddress", + "type": "address" + }, + { + "name": "senderAddress", + "type": "address" + }, + { + "name": "makerAssetAmount", + "type": "uint256" + }, + { + "name": "takerAssetAmount", + "type": "uint256" + }, + { + "name": "makerFee", + "type": "uint256" + }, + { + "name": "takerFee", + "type": "uint256" + }, + { + "name": "expirationTimeSeconds", + "type": "uint256" + }, + { + "name": "salt", + "type": "uint256" + }, + { + "name": "makerAssetData", + "type": "bytes" + }, + { + "name": "takerAssetData", + "type": "bytes" + } + ], + "name": "buyOrder", + "type": "tuple" + }, + { + "components": [ + { + "name": "makerAddress", + "type": "address" + }, + { + "name": "takerAddress", + "type": "address" + }, + { + "name": "feeRecipientAddress", + "type": "address" + }, + { + "name": "senderAddress", + "type": "address" + }, + { + "name": "makerAssetAmount", + "type": "uint256" + }, + { + "name": "takerAssetAmount", + "type": "uint256" + }, + { + "name": "makerFee", + "type": "uint256" + }, + { + "name": "takerFee", + "type": "uint256" + }, + { + "name": "expirationTimeSeconds", + "type": "uint256" + }, + { + "name": "salt", + "type": "uint256" + }, + { + "name": "makerAssetData", + "type": "bytes" + }, + { + "name": "takerAssetData", + "type": "bytes" + } + ], + "name": "sellOrder", + "type": "tuple" + }, + { + "name": "buySignature", + "type": "bytes" + }, + { + "name": "sellSignature", + "type": "bytes" + } + ], + "name": "matchOrders", + "outputs": [ + { + "components": [ + { + "components": [ + { + "name": "makerAssetFilledAmount", + "type": "uint256" + }, + { + "name": "takerAssetFilledAmount", + "type": "uint256" + }, + { + "name": "makerFeePaid", + "type": "uint256" + }, + { + "name": "takerFeePaid", + "type": "uint256" + } + ], + "name": "left", + "type": "tuple" + }, + { + "components": [ + { + "name": "makerAssetFilledAmount", + "type": "uint256" + }, + { + "name": "takerAssetFilledAmount", + "type": "uint256" + }, + { + "name": "makerFeePaid", + "type": "uint256" + }, + { + "name": "takerFeePaid", + "type": "uint256" + } + ], + "name": "right", + "type": "tuple" + }, + { + "name": "leftMakerAssetSpreadAmount", + "type": "uint256" + } + ], + "name": "matchedFillResults", + "type": "tuple" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "name": "_exchange", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + } + ], + "evm": { + "bytecode": { + "linkReferences": {}, + "object": "0x608060405234801561001057600080fd5b50604051602080611352833981018060405261002f9190810190610067565b60008054600160a060020a031916600160a060020a0392909216919091179055610099565b6000610060825161008d565b9392505050565b60006020828403121561007957600080fd5b60006100858484610054565b949350505050565b600160a060020a031690565b6112aa806100a86000396000f30060806040526004361061004b5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632e9cd03381146100505780633c28d86114610086575b600080fd5b34801561005c57600080fd5b5061007061006b366004610b25565b6100b3565b60405161007d919061110a565b60405180910390f35b34801561009257600080fd5b506100a66100a1366004610b5a565b61029c565b60405161007d9190611118565b6100bb6107b1565b610140820151516000808080808080606488101561010e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610105906110aa565b60405180910390fd5b6101408a0151610146907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08a0163ffffffff6105f216565b6101408b0151909750610181907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08a0163ffffffff6105f216565b9550868a61010001511115156101c3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610105906110ba565b868a61010001510394508960a001519350838611151561020f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610105906110fa565b50505083865261010087018051602088015260408701849052606087018290524260a088018190529051828503919081900386821015610255576080890186905261028f565b6101008a0151821061026d576080890184905261028f565b6102898461028461027e8487610607565b8861066d565b610684565b60808a01525b5050505050505050919050565b6102a46107e8565b6102ac6107b1565b6000606060008060006102be8a6100b3565b805160a08201519197501115610300576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610105906110ea565b60a08601516101008b015111610342576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610105906110ca565b608080870151908c01511015610384576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610105906110fa565b6000546040517f3c28d86100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690633c28d861906103e0908e908e908e908e90600401611127565b61012060405180830381600087803b1580156103fb57600080fd5b505af115801561040f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506104339190810190610b06565b96508660400151945060008511156105e4576101608a0151935061045e84601063ffffffff6106c316565b92506104728b608001518760800151610724565b915061047e8583610724565b905060008111156105325789516040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169163a9059cbb916104de9190859060040161105f565b602060405180830381600087803b1580156104f857600080fd5b505af115801561050c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506105309190810190610ae0565b505b60008211156105e4578a516040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169163a9059cbb916105909190869060040161105f565b602060405180830381600087803b1580156105aa57600080fd5b505af11580156105be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506105e29190810190610ae0565b505b505050505050949350505050565b60006105fe8383610766565b90505b92915050565b60008083151561061a5760009150610666565b5082820282848281151561062a57fe5b0414610662576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101059061109a565b8091505b5092915050565b600080828481151561067b57fe5b04949350505050565b600082820183811015610662576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101059061109a565b600081601401835110151515610705576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610105906110da565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b600082821115610760576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101059061107a565b50900390565b6000816020018351101515156107a8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101059061108a565b50016020015190565b60c0604051908101604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b610120604051908101604052806107fd610817565b815260200161080a610817565b8152602001600081525090565b608060405190810160405280600081526020016000815260200160008152602001600081525090565b600061084c82356111ef565b9392505050565b600061084c825161120b565b6000601f8201831361087057600080fd5b813561088361087e826111a5565b61117e565b9150808252602083016020830185838301111561089f57600080fd5b6108aa838284611210565b50505092915050565b6000608082840312156108c557600080fd5b6108cf608061117e565b905060006108dd8484610ad4565b82525060206108ee84848301610ad4565b602083015250604061090284828501610ad4565b604083015250606061091684828501610ad4565b60608301525092915050565b6000610120828403121561093557600080fd5b61093f606061117e565b9050600061094d84846108b3565b825250608061095e848483016108b3565b60208301525061010061097384828501610ad4565b60408301525092915050565b6000610180828403121561099257600080fd5b61099d61018061117e565b905060006109ab8484610840565b82525060206109bc84848301610840565b60208301525060406109d084828501610840565b60408301525060606109e484828501610840565b60608301525060806109f884828501610ac8565b60808301525060a0610a0c84828501610ac8565b60a08301525060c0610a2084828501610ac8565b60c08301525060e0610a3484828501610ac8565b60e083015250610100610a4984828501610ac8565b61010083015250610120610a5f84828501610ac8565b6101208301525061014082013567ffffffffffffffff811115610a8157600080fd5b610a8d8482850161085f565b6101408301525061016082013567ffffffffffffffff811115610aaf57600080fd5b610abb8482850161085f565b6101608301525092915050565b600061084c8235611208565b600061084c8251611208565b600060208284031215610af257600080fd5b6000610afe8484610853565b949350505050565b60006101208284031215610b1957600080fd5b6000610afe8484610922565b600060208284031215610b3757600080fd5b813567ffffffffffffffff811115610b4e57600080fd5b610afe8482850161097f565b60008060008060808587031215610b7057600080fd5b843567ffffffffffffffff811115610b8757600080fd5b610b938782880161097f565b945050602085013567ffffffffffffffff811115610bb057600080fd5b610bbc8782880161097f565b935050604085013567ffffffffffffffff811115610bd957600080fd5b610be58782880161085f565b925050606085013567ffffffffffffffff811115610c0257600080fd5b610c0e8782880161085f565b91505092959194509250565b610c23816111ef565b82525050565b6000610c34826111eb565b808452610c4881602086016020860161121c565b610c5181611248565b9093016020019392505050565b601181527f55494e543235365f554e444552464c4f57000000000000000000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f33325f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601081527f55494e543235365f4f564552464c4f5700000000000000000000000000000000602082015260400190565b601281527f494e56414c49445f41535345545f444154410000000000000000000000000000602082015260400190565b601281527f494e56414c49445f424547494e5f54494d450000000000000000000000000000602082015260400190565b600f81527f41554354494f4e5f455850495245440000000000000000000000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601381527f41554354494f4e5f4e4f545f5354415254454400000000000000000000000000602082015260400190565b600e81527f494e56414c49445f414d4f554e54000000000000000000000000000000000000602082015260400190565b805160c0830190610e6b8482611056565b506020820151610e7e6020850182611056565b506040820151610e916040850182611056565b506060820151610ea46060850182611056565b506080820151610eb76080850182611056565b5060a0820151610eca60a0850182611056565b50505050565b80516080830190610ee18482611056565b506020820151610ef46020850182611056565b506040820151610f076040850182611056565b506060820151610eca6060850182611056565b8051610120830190610f2c8482610ed0565b506020820151610f3f6080850182610ed0565b506040820151610eca610100850182611056565b8051600090610180840190610f688582610c1a565b506020830151610f7b6020860182610c1a565b506040830151610f8e6040860182610c1a565b506060830151610fa16060860182610c1a565b506080830151610fb46080860182611056565b5060a0830151610fc760a0860182611056565b5060c0830151610fda60c0860182611056565b5060e0830151610fed60e0860182611056565b50610100830151611002610100860182611056565b50610120830151611017610120860182611056565b506101408301518482036101408601526110318282610c29565b91505061016083015184820361016086015261104d8282610c29565b95945050505050565b610c2381611208565b6040810161106d8285610c1a565b61084c6020830184611056565b6020808252810161060181610c5e565b6020808252810161060181610c8e565b6020808252810161060181610ce4565b6020808252810161060181610d14565b6020808252810161060181610d44565b6020808252810161060181610d74565b6020808252810161060181610da4565b6020808252810161060181610dfa565b6020808252810161060181610e2a565b60c081016106018284610e5a565b61012081016106018284610f1a565b608080825281016111388187610f53565b9050818103602083015261114c8186610f53565b905081810360408301526111608185610c29565b905081810360608301526111748184610c29565b9695505050505050565b60405181810167ffffffffffffffff8111828210171561119d57600080fd5b604052919050565b600067ffffffffffffffff8211156111bc57600080fd5b506020601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b5190565b73ffffffffffffffffffffffffffffffffffffffff1690565b90565b151590565b82818337506000910152565b60005b8381101561123757818101518382015260200161121f565b83811115610eca5750506000910152565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016905600a265627a7a723058209cf70b04b75fc23e6762ae4c6c8f25ccad25dfcb39cf1dd3966eb27ce513de036c6578706572696d656e74616cf50037", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH1 0x20 DUP1 PUSH2 0x1352 DUP4 CODECOPY DUP2 ADD DUP1 PUSH1 0x40 MSTORE PUSH2 0x2F SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x67 JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT AND PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB SWAP3 SWAP1 SWAP3 AND SWAP2 SWAP1 SWAP2 OR SWAP1 SSTORE PUSH2 0x99 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x60 DUP3 MLOAD PUSH2 0x8D JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x79 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x85 DUP5 DUP5 PUSH2 0x54 JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 JUMP JUMPDEST PUSH2 0x12AA DUP1 PUSH2 0xA8 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x4B JUMPI PUSH4 0xFFFFFFFF PUSH29 0x100000000000000000000000000000000000000000000000000000000 PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0x2E9CD033 DUP2 EQ PUSH2 0x50 JUMPI DUP1 PUSH4 0x3C28D861 EQ PUSH2 0x86 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x5C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x70 PUSH2 0x6B CALLDATASIZE PUSH1 0x4 PUSH2 0xB25 JUMP JUMPDEST PUSH2 0xB3 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x7D SWAP2 SWAP1 PUSH2 0x110A JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x92 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xA6 PUSH2 0xA1 CALLDATASIZE PUSH1 0x4 PUSH2 0xB5A JUMP JUMPDEST PUSH2 0x29C JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x7D SWAP2 SWAP1 PUSH2 0x1118 JUMP JUMPDEST PUSH2 0xBB PUSH2 0x7B1 JUMP JUMPDEST PUSH2 0x140 DUP3 ADD MLOAD MLOAD PUSH1 0x0 DUP1 DUP1 DUP1 DUP1 DUP1 DUP1 PUSH1 0x64 DUP9 LT ISZERO PUSH2 0x10E JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x10AA JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0x140 DUP11 ADD MLOAD PUSH2 0x146 SWAP1 PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 DUP11 ADD PUSH4 0xFFFFFFFF PUSH2 0x5F2 AND JUMP JUMPDEST PUSH2 0x140 DUP12 ADD MLOAD SWAP1 SWAP8 POP PUSH2 0x181 SWAP1 PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP11 ADD PUSH4 0xFFFFFFFF PUSH2 0x5F2 AND JUMP JUMPDEST SWAP6 POP DUP7 DUP11 PUSH2 0x100 ADD MLOAD GT ISZERO ISZERO PUSH2 0x1C3 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x10BA JUMP JUMPDEST DUP7 DUP11 PUSH2 0x100 ADD MLOAD SUB SWAP5 POP DUP10 PUSH1 0xA0 ADD MLOAD SWAP4 POP DUP4 DUP7 GT ISZERO ISZERO PUSH2 0x20F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x10FA JUMP JUMPDEST POP POP POP DUP4 DUP7 MSTORE PUSH2 0x100 DUP8 ADD DUP1 MLOAD PUSH1 0x20 DUP9 ADD MSTORE PUSH1 0x40 DUP8 ADD DUP5 SWAP1 MSTORE PUSH1 0x60 DUP8 ADD DUP3 SWAP1 MSTORE TIMESTAMP PUSH1 0xA0 DUP9 ADD DUP2 SWAP1 MSTORE SWAP1 MLOAD DUP3 DUP6 SUB SWAP2 SWAP1 DUP2 SWAP1 SUB DUP7 DUP3 LT ISZERO PUSH2 0x255 JUMPI PUSH1 0x80 DUP10 ADD DUP7 SWAP1 MSTORE PUSH2 0x28F JUMP JUMPDEST PUSH2 0x100 DUP11 ADD MLOAD DUP3 LT PUSH2 0x26D JUMPI PUSH1 0x80 DUP10 ADD DUP5 SWAP1 MSTORE PUSH2 0x28F JUMP JUMPDEST PUSH2 0x289 DUP5 PUSH2 0x284 PUSH2 0x27E DUP5 DUP8 PUSH2 0x607 JUMP JUMPDEST DUP9 PUSH2 0x66D JUMP JUMPDEST PUSH2 0x684 JUMP JUMPDEST PUSH1 0x80 DUP11 ADD MSTORE JUMPDEST POP POP POP POP POP POP POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH2 0x2A4 PUSH2 0x7E8 JUMP JUMPDEST PUSH2 0x2AC PUSH2 0x7B1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 PUSH1 0x0 DUP1 PUSH1 0x0 PUSH2 0x2BE DUP11 PUSH2 0xB3 JUMP JUMPDEST DUP1 MLOAD PUSH1 0xA0 DUP3 ADD MLOAD SWAP2 SWAP8 POP GT ISZERO PUSH2 0x300 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x10EA JUMP JUMPDEST PUSH1 0xA0 DUP7 ADD MLOAD PUSH2 0x100 DUP12 ADD MLOAD GT PUSH2 0x342 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x10CA JUMP JUMPDEST PUSH1 0x80 DUP1 DUP8 ADD MLOAD SWAP1 DUP13 ADD MLOAD LT ISZERO PUSH2 0x384 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x10FA JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH1 0x40 MLOAD PUSH32 0x3C28D86100000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP2 AND SWAP1 PUSH4 0x3C28D861 SWAP1 PUSH2 0x3E0 SWAP1 DUP15 SWAP1 DUP15 SWAP1 DUP15 SWAP1 DUP15 SWAP1 PUSH1 0x4 ADD PUSH2 0x1127 JUMP JUMPDEST PUSH2 0x120 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x3FB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x40F JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP PUSH1 0x40 MLOAD RETURNDATASIZE PUSH1 0x1F NOT PUSH1 0x1F DUP3 ADD AND DUP3 ADD DUP1 PUSH1 0x40 MSTORE POP PUSH2 0x433 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0xB06 JUMP JUMPDEST SWAP7 POP DUP7 PUSH1 0x40 ADD MLOAD SWAP5 POP PUSH1 0x0 DUP6 GT ISZERO PUSH2 0x5E4 JUMPI PUSH2 0x160 DUP11 ADD MLOAD SWAP4 POP PUSH2 0x45E DUP5 PUSH1 0x10 PUSH4 0xFFFFFFFF PUSH2 0x6C3 AND JUMP JUMPDEST SWAP3 POP PUSH2 0x472 DUP12 PUSH1 0x80 ADD MLOAD DUP8 PUSH1 0x80 ADD MLOAD PUSH2 0x724 JUMP JUMPDEST SWAP2 POP PUSH2 0x47E DUP6 DUP4 PUSH2 0x724 JUMP JUMPDEST SWAP1 POP PUSH1 0x0 DUP2 GT ISZERO PUSH2 0x532 JUMPI DUP10 MLOAD PUSH1 0x40 MLOAD PUSH32 0xA9059CBB00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP6 AND SWAP2 PUSH4 0xA9059CBB SWAP2 PUSH2 0x4DE SWAP2 SWAP1 DUP6 SWAP1 PUSH1 0x4 ADD PUSH2 0x105F JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x4F8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x50C JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP PUSH1 0x40 MLOAD RETURNDATASIZE PUSH1 0x1F NOT PUSH1 0x1F DUP3 ADD AND DUP3 ADD DUP1 PUSH1 0x40 MSTORE POP PUSH2 0x530 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0xAE0 JUMP JUMPDEST POP JUMPDEST PUSH1 0x0 DUP3 GT ISZERO PUSH2 0x5E4 JUMPI DUP11 MLOAD PUSH1 0x40 MLOAD PUSH32 0xA9059CBB00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP6 AND SWAP2 PUSH4 0xA9059CBB SWAP2 PUSH2 0x590 SWAP2 SWAP1 DUP7 SWAP1 PUSH1 0x4 ADD PUSH2 0x105F JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x5AA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x5BE JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP PUSH1 0x40 MLOAD RETURNDATASIZE PUSH1 0x1F NOT PUSH1 0x1F DUP3 ADD AND DUP3 ADD DUP1 PUSH1 0x40 MSTORE POP PUSH2 0x5E2 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0xAE0 JUMP JUMPDEST POP JUMPDEST POP POP POP POP POP POP SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5FE DUP4 DUP4 PUSH2 0x766 JUMP JUMPDEST SWAP1 POP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP4 ISZERO ISZERO PUSH2 0x61A JUMPI PUSH1 0x0 SWAP2 POP PUSH2 0x666 JUMP JUMPDEST POP DUP3 DUP3 MUL DUP3 DUP5 DUP3 DUP2 ISZERO ISZERO PUSH2 0x62A JUMPI INVALID JUMPDEST DIV EQ PUSH2 0x662 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x109A JUMP JUMPDEST DUP1 SWAP2 POP JUMPDEST POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 DUP2 ISZERO ISZERO PUSH2 0x67B JUMPI INVALID JUMPDEST DIV SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 DUP3 ADD DUP4 DUP2 LT ISZERO PUSH2 0x662 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x109A JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x14 ADD DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0x705 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x10DA JUMP JUMPDEST POP ADD PUSH1 0x14 ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP3 DUP3 GT ISZERO PUSH2 0x760 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x107A JUMP JUMPDEST POP SWAP1 SUB SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x20 ADD DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0x7A8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x108A JUMP JUMPDEST POP ADD PUSH1 0x20 ADD MLOAD SWAP1 JUMP JUMPDEST PUSH1 0xC0 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH2 0x120 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH2 0x7FD PUSH2 0x817 JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x80A PUSH2 0x817 JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x80 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x84C DUP3 CALLDATALOAD PUSH2 0x11EF JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x84C DUP3 MLOAD PUSH2 0x120B JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0x870 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0x883 PUSH2 0x87E DUP3 PUSH2 0x11A5 JUMP JUMPDEST PUSH2 0x117E JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE PUSH1 0x20 DUP4 ADD PUSH1 0x20 DUP4 ADD DUP6 DUP4 DUP4 ADD GT ISZERO PUSH2 0x89F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x8AA DUP4 DUP3 DUP5 PUSH2 0x1210 JUMP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x80 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x8C5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x8CF PUSH1 0x80 PUSH2 0x117E JUMP JUMPDEST SWAP1 POP PUSH1 0x0 PUSH2 0x8DD DUP5 DUP5 PUSH2 0xAD4 JUMP JUMPDEST DUP3 MSTORE POP PUSH1 0x20 PUSH2 0x8EE DUP5 DUP5 DUP4 ADD PUSH2 0xAD4 JUMP JUMPDEST PUSH1 0x20 DUP4 ADD MSTORE POP PUSH1 0x40 PUSH2 0x902 DUP5 DUP3 DUP6 ADD PUSH2 0xAD4 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MSTORE POP PUSH1 0x60 PUSH2 0x916 DUP5 DUP3 DUP6 ADD PUSH2 0xAD4 JUMP JUMPDEST PUSH1 0x60 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x120 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x935 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x93F PUSH1 0x60 PUSH2 0x117E JUMP JUMPDEST SWAP1 POP PUSH1 0x0 PUSH2 0x94D DUP5 DUP5 PUSH2 0x8B3 JUMP JUMPDEST DUP3 MSTORE POP PUSH1 0x80 PUSH2 0x95E DUP5 DUP5 DUP4 ADD PUSH2 0x8B3 JUMP JUMPDEST PUSH1 0x20 DUP4 ADD MSTORE POP PUSH2 0x100 PUSH2 0x973 DUP5 DUP3 DUP6 ADD PUSH2 0xAD4 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x180 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x992 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x99D PUSH2 0x180 PUSH2 0x117E JUMP JUMPDEST SWAP1 POP PUSH1 0x0 PUSH2 0x9AB DUP5 DUP5 PUSH2 0x840 JUMP JUMPDEST DUP3 MSTORE POP PUSH1 0x20 PUSH2 0x9BC DUP5 DUP5 DUP4 ADD PUSH2 0x840 JUMP JUMPDEST PUSH1 0x20 DUP4 ADD MSTORE POP PUSH1 0x40 PUSH2 0x9D0 DUP5 DUP3 DUP6 ADD PUSH2 0x840 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MSTORE POP PUSH1 0x60 PUSH2 0x9E4 DUP5 DUP3 DUP6 ADD PUSH2 0x840 JUMP JUMPDEST PUSH1 0x60 DUP4 ADD MSTORE POP PUSH1 0x80 PUSH2 0x9F8 DUP5 DUP3 DUP6 ADD PUSH2 0xAC8 JUMP JUMPDEST PUSH1 0x80 DUP4 ADD MSTORE POP PUSH1 0xA0 PUSH2 0xA0C DUP5 DUP3 DUP6 ADD PUSH2 0xAC8 JUMP JUMPDEST PUSH1 0xA0 DUP4 ADD MSTORE POP PUSH1 0xC0 PUSH2 0xA20 DUP5 DUP3 DUP6 ADD PUSH2 0xAC8 JUMP JUMPDEST PUSH1 0xC0 DUP4 ADD MSTORE POP PUSH1 0xE0 PUSH2 0xA34 DUP5 DUP3 DUP6 ADD PUSH2 0xAC8 JUMP JUMPDEST PUSH1 0xE0 DUP4 ADD MSTORE POP PUSH2 0x100 PUSH2 0xA49 DUP5 DUP3 DUP6 ADD PUSH2 0xAC8 JUMP JUMPDEST PUSH2 0x100 DUP4 ADD MSTORE POP PUSH2 0x120 PUSH2 0xA5F DUP5 DUP3 DUP6 ADD PUSH2 0xAC8 JUMP JUMPDEST PUSH2 0x120 DUP4 ADD MSTORE POP PUSH2 0x140 DUP3 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xA81 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xA8D DUP5 DUP3 DUP6 ADD PUSH2 0x85F JUMP JUMPDEST PUSH2 0x140 DUP4 ADD MSTORE POP PUSH2 0x160 DUP3 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xAAF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xABB DUP5 DUP3 DUP6 ADD PUSH2 0x85F JUMP JUMPDEST PUSH2 0x160 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x84C DUP3 CALLDATALOAD PUSH2 0x1208 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x84C DUP3 MLOAD PUSH2 0x1208 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xAF2 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0xAFE DUP5 DUP5 PUSH2 0x853 JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x120 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xB19 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0xAFE DUP5 DUP5 PUSH2 0x922 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xB37 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xB4E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xAFE DUP5 DUP3 DUP6 ADD PUSH2 0x97F JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP1 PUSH1 0x80 DUP6 DUP8 SUB SLT ISZERO PUSH2 0xB70 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP5 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xB87 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB93 DUP8 DUP3 DUP9 ADD PUSH2 0x97F JUMP JUMPDEST SWAP5 POP POP PUSH1 0x20 DUP6 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xBB0 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xBBC DUP8 DUP3 DUP9 ADD PUSH2 0x97F JUMP JUMPDEST SWAP4 POP POP PUSH1 0x40 DUP6 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xBD9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xBE5 DUP8 DUP3 DUP9 ADD PUSH2 0x85F JUMP JUMPDEST SWAP3 POP POP PUSH1 0x60 DUP6 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xC02 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xC0E DUP8 DUP3 DUP9 ADD PUSH2 0x85F JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP6 SWAP2 SWAP5 POP SWAP3 POP JUMP JUMPDEST PUSH2 0xC23 DUP2 PUSH2 0x11EF JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0xC34 DUP3 PUSH2 0x11EB JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH2 0xC48 DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x121C JUMP JUMPDEST PUSH2 0xC51 DUP2 PUSH2 0x1248 JUMP JUMPDEST SWAP1 SWAP4 ADD PUSH1 0x20 ADD SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x11 DUP2 MSTORE PUSH32 0x55494E543235365F554E444552464C4F57000000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST PUSH1 0x26 DUP2 MSTORE PUSH32 0x475245415445525F4F525F455155414C5F544F5F33325F4C454E4754485F5245 PUSH1 0x20 DUP3 ADD MSTORE PUSH32 0x5155495245440000000000000000000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST PUSH1 0x10 DUP2 MSTORE PUSH32 0x55494E543235365F4F564552464C4F5700000000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST PUSH1 0x12 DUP2 MSTORE PUSH32 0x494E56414C49445F41535345545F444154410000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST PUSH1 0x12 DUP2 MSTORE PUSH32 0x494E56414C49445F424547494E5F54494D450000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST PUSH1 0xF DUP2 MSTORE PUSH32 0x41554354494F4E5F455850495245440000000000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST PUSH1 0x26 DUP2 MSTORE PUSH32 0x475245415445525F4F525F455155414C5F544F5F32305F4C454E4754485F5245 PUSH1 0x20 DUP3 ADD MSTORE PUSH32 0x5155495245440000000000000000000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST PUSH1 0x13 DUP2 MSTORE PUSH32 0x41554354494F4E5F4E4F545F5354415254454400000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST PUSH1 0xE DUP2 MSTORE PUSH32 0x494E56414C49445F414D4F554E54000000000000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST DUP1 MLOAD PUSH1 0xC0 DUP4 ADD SWAP1 PUSH2 0xE6B DUP5 DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0x20 DUP3 ADD MLOAD PUSH2 0xE7E PUSH1 0x20 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0x40 DUP3 ADD MLOAD PUSH2 0xE91 PUSH1 0x40 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0x60 DUP3 ADD MLOAD PUSH2 0xEA4 PUSH1 0x60 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0x80 DUP3 ADD MLOAD PUSH2 0xEB7 PUSH1 0x80 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0xA0 DUP3 ADD MLOAD PUSH2 0xECA PUSH1 0xA0 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP POP POP POP JUMP JUMPDEST DUP1 MLOAD PUSH1 0x80 DUP4 ADD SWAP1 PUSH2 0xEE1 DUP5 DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0x20 DUP3 ADD MLOAD PUSH2 0xEF4 PUSH1 0x20 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0x40 DUP3 ADD MLOAD PUSH2 0xF07 PUSH1 0x40 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0x60 DUP3 ADD MLOAD PUSH2 0xECA PUSH1 0x60 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST DUP1 MLOAD PUSH2 0x120 DUP4 ADD SWAP1 PUSH2 0xF2C DUP5 DUP3 PUSH2 0xED0 JUMP JUMPDEST POP PUSH1 0x20 DUP3 ADD MLOAD PUSH2 0xF3F PUSH1 0x80 DUP6 ADD DUP3 PUSH2 0xED0 JUMP JUMPDEST POP PUSH1 0x40 DUP3 ADD MLOAD PUSH2 0xECA PUSH2 0x100 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST DUP1 MLOAD PUSH1 0x0 SWAP1 PUSH2 0x180 DUP5 ADD SWAP1 PUSH2 0xF68 DUP6 DUP3 PUSH2 0xC1A JUMP JUMPDEST POP PUSH1 0x20 DUP4 ADD MLOAD PUSH2 0xF7B PUSH1 0x20 DUP7 ADD DUP3 PUSH2 0xC1A JUMP JUMPDEST POP PUSH1 0x40 DUP4 ADD MLOAD PUSH2 0xF8E PUSH1 0x40 DUP7 ADD DUP3 PUSH2 0xC1A JUMP JUMPDEST POP PUSH1 0x60 DUP4 ADD MLOAD PUSH2 0xFA1 PUSH1 0x60 DUP7 ADD DUP3 PUSH2 0xC1A JUMP JUMPDEST POP PUSH1 0x80 DUP4 ADD MLOAD PUSH2 0xFB4 PUSH1 0x80 DUP7 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0xA0 DUP4 ADD MLOAD PUSH2 0xFC7 PUSH1 0xA0 DUP7 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0xC0 DUP4 ADD MLOAD PUSH2 0xFDA PUSH1 0xC0 DUP7 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0xE0 DUP4 ADD MLOAD PUSH2 0xFED PUSH1 0xE0 DUP7 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH2 0x100 DUP4 ADD MLOAD PUSH2 0x1002 PUSH2 0x100 DUP7 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH2 0x120 DUP4 ADD MLOAD PUSH2 0x1017 PUSH2 0x120 DUP7 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH2 0x140 DUP4 ADD MLOAD DUP5 DUP3 SUB PUSH2 0x140 DUP7 ADD MSTORE PUSH2 0x1031 DUP3 DUP3 PUSH2 0xC29 JUMP JUMPDEST SWAP2 POP POP PUSH2 0x160 DUP4 ADD MLOAD DUP5 DUP3 SUB PUSH2 0x160 DUP7 ADD MSTORE PUSH2 0x104D DUP3 DUP3 PUSH2 0xC29 JUMP JUMPDEST SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST PUSH2 0xC23 DUP2 PUSH2 0x1208 JUMP JUMPDEST PUSH1 0x40 DUP2 ADD PUSH2 0x106D DUP3 DUP6 PUSH2 0xC1A JUMP JUMPDEST PUSH2 0x84C PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x1056 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xC5E JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xC8E JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xCE4 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xD14 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xD44 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xD74 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xDA4 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xDFA JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xE2A JUMP JUMPDEST PUSH1 0xC0 DUP2 ADD PUSH2 0x601 DUP3 DUP5 PUSH2 0xE5A JUMP JUMPDEST PUSH2 0x120 DUP2 ADD PUSH2 0x601 DUP3 DUP5 PUSH2 0xF1A JUMP JUMPDEST PUSH1 0x80 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x1138 DUP2 DUP8 PUSH2 0xF53 JUMP JUMPDEST SWAP1 POP DUP2 DUP2 SUB PUSH1 0x20 DUP4 ADD MSTORE PUSH2 0x114C DUP2 DUP7 PUSH2 0xF53 JUMP JUMPDEST SWAP1 POP DUP2 DUP2 SUB PUSH1 0x40 DUP4 ADD MSTORE PUSH2 0x1160 DUP2 DUP6 PUSH2 0xC29 JUMP JUMPDEST SWAP1 POP DUP2 DUP2 SUB PUSH1 0x60 DUP4 ADD MSTORE PUSH2 0x1174 DUP2 DUP5 PUSH2 0xC29 JUMP JUMPDEST SWAP7 SWAP6 POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x119D JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT ISZERO PUSH2 0x11BC JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 PUSH1 0x1F SWAP2 SWAP1 SWAP2 ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND ADD SWAP1 JUMP JUMPDEST MLOAD SWAP1 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST ISZERO ISZERO SWAP1 JUMP JUMPDEST DUP3 DUP2 DUP4 CALLDATACOPY POP PUSH1 0x0 SWAP2 ADD MSTORE JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x1237 JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x121F JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0xECA JUMPI POP POP PUSH1 0x0 SWAP2 ADD MSTORE JUMP JUMPDEST PUSH1 0x1F ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND SWAP1 JUMP STOP LOG2 PUSH6 0x627A7A723058 KECCAK256 SWAP13 0xf7 SIGNEXTEND DIV 0xb7 0x5f 0xc2 RETURNDATACOPY PUSH8 0x62AE4C6C8F25CCAD 0x25 0xdf 0xcb CODECOPY 0xcf SAR 0xd3 SWAP7 PUSH15 0xB27CE513DE036C6578706572696D65 PUSH15 0x74616CF50037000000000000000000 ", + "sourceMap": "986:9378:28:-;;;1673:99;8:9:-1;5:2;;;30:1;27;20:12;5:2;1673:99:28;;;;;;;;;;;;;;;;;;;;;;1734:8;:31;;-1:-1:-1;;;;;;1734:31:28;-1:-1:-1;;;;;1734:31:28;;;;;;;;;;986:9378;;5:122:-1;;83:39;114:6;108:13;83:39;;;74:48;68:59;-1:-1;;;68:59;134:263;;249:2;237:9;228:7;224:23;220:32;217:2;;;265:1;262;255:12;217:2;300:1;317:64;373:7;353:9;317:64;;;307:74;211:186;-1:-1;;;;211:186;404:128;-1:-1;;;;;473:54;;456:76;;986:9378:28;;;;;;" + }, + "deployedBytecode": { + "linkReferences": {}, + "object": "0x60806040526004361061004b5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632e9cd03381146100505780633c28d86114610086575b600080fd5b34801561005c57600080fd5b5061007061006b366004610b25565b6100b3565b60405161007d919061110a565b60405180910390f35b34801561009257600080fd5b506100a66100a1366004610b5a565b61029c565b60405161007d9190611118565b6100bb6107b1565b610140820151516000808080808080606488101561010e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610105906110aa565b60405180910390fd5b6101408a0151610146907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08a0163ffffffff6105f216565b6101408b0151909750610181907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08a0163ffffffff6105f216565b9550868a61010001511115156101c3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610105906110ba565b868a61010001510394508960a001519350838611151561020f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610105906110fa565b50505083865261010087018051602088015260408701849052606087018290524260a088018190529051828503919081900386821015610255576080890186905261028f565b6101008a0151821061026d576080890184905261028f565b6102898461028461027e8487610607565b8861066d565b610684565b60808a01525b5050505050505050919050565b6102a46107e8565b6102ac6107b1565b6000606060008060006102be8a6100b3565b805160a08201519197501115610300576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610105906110ea565b60a08601516101008b015111610342576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610105906110ca565b608080870151908c01511015610384576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610105906110fa565b6000546040517f3c28d86100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690633c28d861906103e0908e908e908e908e90600401611127565b61012060405180830381600087803b1580156103fb57600080fd5b505af115801561040f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506104339190810190610b06565b96508660400151945060008511156105e4576101608a0151935061045e84601063ffffffff6106c316565b92506104728b608001518760800151610724565b915061047e8583610724565b905060008111156105325789516040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169163a9059cbb916104de9190859060040161105f565b602060405180830381600087803b1580156104f857600080fd5b505af115801561050c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506105309190810190610ae0565b505b60008211156105e4578a516040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169163a9059cbb916105909190869060040161105f565b602060405180830381600087803b1580156105aa57600080fd5b505af11580156105be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506105e29190810190610ae0565b505b505050505050949350505050565b60006105fe8383610766565b90505b92915050565b60008083151561061a5760009150610666565b5082820282848281151561062a57fe5b0414610662576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101059061109a565b8091505b5092915050565b600080828481151561067b57fe5b04949350505050565b600082820183811015610662576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101059061109a565b600081601401835110151515610705576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610105906110da565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b600082821115610760576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101059061107a565b50900390565b6000816020018351101515156107a8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101059061108a565b50016020015190565b60c0604051908101604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b610120604051908101604052806107fd610817565b815260200161080a610817565b8152602001600081525090565b608060405190810160405280600081526020016000815260200160008152602001600081525090565b600061084c82356111ef565b9392505050565b600061084c825161120b565b6000601f8201831361087057600080fd5b813561088361087e826111a5565b61117e565b9150808252602083016020830185838301111561089f57600080fd5b6108aa838284611210565b50505092915050565b6000608082840312156108c557600080fd5b6108cf608061117e565b905060006108dd8484610ad4565b82525060206108ee84848301610ad4565b602083015250604061090284828501610ad4565b604083015250606061091684828501610ad4565b60608301525092915050565b6000610120828403121561093557600080fd5b61093f606061117e565b9050600061094d84846108b3565b825250608061095e848483016108b3565b60208301525061010061097384828501610ad4565b60408301525092915050565b6000610180828403121561099257600080fd5b61099d61018061117e565b905060006109ab8484610840565b82525060206109bc84848301610840565b60208301525060406109d084828501610840565b60408301525060606109e484828501610840565b60608301525060806109f884828501610ac8565b60808301525060a0610a0c84828501610ac8565b60a08301525060c0610a2084828501610ac8565b60c08301525060e0610a3484828501610ac8565b60e083015250610100610a4984828501610ac8565b61010083015250610120610a5f84828501610ac8565b6101208301525061014082013567ffffffffffffffff811115610a8157600080fd5b610a8d8482850161085f565b6101408301525061016082013567ffffffffffffffff811115610aaf57600080fd5b610abb8482850161085f565b6101608301525092915050565b600061084c8235611208565b600061084c8251611208565b600060208284031215610af257600080fd5b6000610afe8484610853565b949350505050565b60006101208284031215610b1957600080fd5b6000610afe8484610922565b600060208284031215610b3757600080fd5b813567ffffffffffffffff811115610b4e57600080fd5b610afe8482850161097f565b60008060008060808587031215610b7057600080fd5b843567ffffffffffffffff811115610b8757600080fd5b610b938782880161097f565b945050602085013567ffffffffffffffff811115610bb057600080fd5b610bbc8782880161097f565b935050604085013567ffffffffffffffff811115610bd957600080fd5b610be58782880161085f565b925050606085013567ffffffffffffffff811115610c0257600080fd5b610c0e8782880161085f565b91505092959194509250565b610c23816111ef565b82525050565b6000610c34826111eb565b808452610c4881602086016020860161121c565b610c5181611248565b9093016020019392505050565b601181527f55494e543235365f554e444552464c4f57000000000000000000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f33325f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601081527f55494e543235365f4f564552464c4f5700000000000000000000000000000000602082015260400190565b601281527f494e56414c49445f41535345545f444154410000000000000000000000000000602082015260400190565b601281527f494e56414c49445f424547494e5f54494d450000000000000000000000000000602082015260400190565b600f81527f41554354494f4e5f455850495245440000000000000000000000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601381527f41554354494f4e5f4e4f545f5354415254454400000000000000000000000000602082015260400190565b600e81527f494e56414c49445f414d4f554e54000000000000000000000000000000000000602082015260400190565b805160c0830190610e6b8482611056565b506020820151610e7e6020850182611056565b506040820151610e916040850182611056565b506060820151610ea46060850182611056565b506080820151610eb76080850182611056565b5060a0820151610eca60a0850182611056565b50505050565b80516080830190610ee18482611056565b506020820151610ef46020850182611056565b506040820151610f076040850182611056565b506060820151610eca6060850182611056565b8051610120830190610f2c8482610ed0565b506020820151610f3f6080850182610ed0565b506040820151610eca610100850182611056565b8051600090610180840190610f688582610c1a565b506020830151610f7b6020860182610c1a565b506040830151610f8e6040860182610c1a565b506060830151610fa16060860182610c1a565b506080830151610fb46080860182611056565b5060a0830151610fc760a0860182611056565b5060c0830151610fda60c0860182611056565b5060e0830151610fed60e0860182611056565b50610100830151611002610100860182611056565b50610120830151611017610120860182611056565b506101408301518482036101408601526110318282610c29565b91505061016083015184820361016086015261104d8282610c29565b95945050505050565b610c2381611208565b6040810161106d8285610c1a565b61084c6020830184611056565b6020808252810161060181610c5e565b6020808252810161060181610c8e565b6020808252810161060181610ce4565b6020808252810161060181610d14565b6020808252810161060181610d44565b6020808252810161060181610d74565b6020808252810161060181610da4565b6020808252810161060181610dfa565b6020808252810161060181610e2a565b60c081016106018284610e5a565b61012081016106018284610f1a565b608080825281016111388187610f53565b9050818103602083015261114c8186610f53565b905081810360408301526111608185610c29565b905081810360608301526111748184610c29565b9695505050505050565b60405181810167ffffffffffffffff8111828210171561119d57600080fd5b604052919050565b600067ffffffffffffffff8211156111bc57600080fd5b506020601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b5190565b73ffffffffffffffffffffffffffffffffffffffff1690565b90565b151590565b82818337506000910152565b60005b8381101561123757818101518382015260200161121f565b83811115610eca5750506000910152565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016905600a265627a7a723058209cf70b04b75fc23e6762ae4c6c8f25ccad25dfcb39cf1dd3966eb27ce513de036c6578706572696d656e74616cf50037", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x4B JUMPI PUSH4 0xFFFFFFFF PUSH29 0x100000000000000000000000000000000000000000000000000000000 PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0x2E9CD033 DUP2 EQ PUSH2 0x50 JUMPI DUP1 PUSH4 0x3C28D861 EQ PUSH2 0x86 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x5C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x70 PUSH2 0x6B CALLDATASIZE PUSH1 0x4 PUSH2 0xB25 JUMP JUMPDEST PUSH2 0xB3 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x7D SWAP2 SWAP1 PUSH2 0x110A JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x92 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xA6 PUSH2 0xA1 CALLDATASIZE PUSH1 0x4 PUSH2 0xB5A JUMP JUMPDEST PUSH2 0x29C JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x7D SWAP2 SWAP1 PUSH2 0x1118 JUMP JUMPDEST PUSH2 0xBB PUSH2 0x7B1 JUMP JUMPDEST PUSH2 0x140 DUP3 ADD MLOAD MLOAD PUSH1 0x0 DUP1 DUP1 DUP1 DUP1 DUP1 DUP1 PUSH1 0x64 DUP9 LT ISZERO PUSH2 0x10E JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x10AA JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0x140 DUP11 ADD MLOAD PUSH2 0x146 SWAP1 PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 DUP11 ADD PUSH4 0xFFFFFFFF PUSH2 0x5F2 AND JUMP JUMPDEST PUSH2 0x140 DUP12 ADD MLOAD SWAP1 SWAP8 POP PUSH2 0x181 SWAP1 PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP11 ADD PUSH4 0xFFFFFFFF PUSH2 0x5F2 AND JUMP JUMPDEST SWAP6 POP DUP7 DUP11 PUSH2 0x100 ADD MLOAD GT ISZERO ISZERO PUSH2 0x1C3 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x10BA JUMP JUMPDEST DUP7 DUP11 PUSH2 0x100 ADD MLOAD SUB SWAP5 POP DUP10 PUSH1 0xA0 ADD MLOAD SWAP4 POP DUP4 DUP7 GT ISZERO ISZERO PUSH2 0x20F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x10FA JUMP JUMPDEST POP POP POP DUP4 DUP7 MSTORE PUSH2 0x100 DUP8 ADD DUP1 MLOAD PUSH1 0x20 DUP9 ADD MSTORE PUSH1 0x40 DUP8 ADD DUP5 SWAP1 MSTORE PUSH1 0x60 DUP8 ADD DUP3 SWAP1 MSTORE TIMESTAMP PUSH1 0xA0 DUP9 ADD DUP2 SWAP1 MSTORE SWAP1 MLOAD DUP3 DUP6 SUB SWAP2 SWAP1 DUP2 SWAP1 SUB DUP7 DUP3 LT ISZERO PUSH2 0x255 JUMPI PUSH1 0x80 DUP10 ADD DUP7 SWAP1 MSTORE PUSH2 0x28F JUMP JUMPDEST PUSH2 0x100 DUP11 ADD MLOAD DUP3 LT PUSH2 0x26D JUMPI PUSH1 0x80 DUP10 ADD DUP5 SWAP1 MSTORE PUSH2 0x28F JUMP JUMPDEST PUSH2 0x289 DUP5 PUSH2 0x284 PUSH2 0x27E DUP5 DUP8 PUSH2 0x607 JUMP JUMPDEST DUP9 PUSH2 0x66D JUMP JUMPDEST PUSH2 0x684 JUMP JUMPDEST PUSH1 0x80 DUP11 ADD MSTORE JUMPDEST POP POP POP POP POP POP POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH2 0x2A4 PUSH2 0x7E8 JUMP JUMPDEST PUSH2 0x2AC PUSH2 0x7B1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 PUSH1 0x0 DUP1 PUSH1 0x0 PUSH2 0x2BE DUP11 PUSH2 0xB3 JUMP JUMPDEST DUP1 MLOAD PUSH1 0xA0 DUP3 ADD MLOAD SWAP2 SWAP8 POP GT ISZERO PUSH2 0x300 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x10EA JUMP JUMPDEST PUSH1 0xA0 DUP7 ADD MLOAD PUSH2 0x100 DUP12 ADD MLOAD GT PUSH2 0x342 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x10CA JUMP JUMPDEST PUSH1 0x80 DUP1 DUP8 ADD MLOAD SWAP1 DUP13 ADD MLOAD LT ISZERO PUSH2 0x384 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x10FA JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH1 0x40 MLOAD PUSH32 0x3C28D86100000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP2 AND SWAP1 PUSH4 0x3C28D861 SWAP1 PUSH2 0x3E0 SWAP1 DUP15 SWAP1 DUP15 SWAP1 DUP15 SWAP1 DUP15 SWAP1 PUSH1 0x4 ADD PUSH2 0x1127 JUMP JUMPDEST PUSH2 0x120 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x3FB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x40F JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP PUSH1 0x40 MLOAD RETURNDATASIZE PUSH1 0x1F NOT PUSH1 0x1F DUP3 ADD AND DUP3 ADD DUP1 PUSH1 0x40 MSTORE POP PUSH2 0x433 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0xB06 JUMP JUMPDEST SWAP7 POP DUP7 PUSH1 0x40 ADD MLOAD SWAP5 POP PUSH1 0x0 DUP6 GT ISZERO PUSH2 0x5E4 JUMPI PUSH2 0x160 DUP11 ADD MLOAD SWAP4 POP PUSH2 0x45E DUP5 PUSH1 0x10 PUSH4 0xFFFFFFFF PUSH2 0x6C3 AND JUMP JUMPDEST SWAP3 POP PUSH2 0x472 DUP12 PUSH1 0x80 ADD MLOAD DUP8 PUSH1 0x80 ADD MLOAD PUSH2 0x724 JUMP JUMPDEST SWAP2 POP PUSH2 0x47E DUP6 DUP4 PUSH2 0x724 JUMP JUMPDEST SWAP1 POP PUSH1 0x0 DUP2 GT ISZERO PUSH2 0x532 JUMPI DUP10 MLOAD PUSH1 0x40 MLOAD PUSH32 0xA9059CBB00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP6 AND SWAP2 PUSH4 0xA9059CBB SWAP2 PUSH2 0x4DE SWAP2 SWAP1 DUP6 SWAP1 PUSH1 0x4 ADD PUSH2 0x105F JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x4F8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x50C JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP PUSH1 0x40 MLOAD RETURNDATASIZE PUSH1 0x1F NOT PUSH1 0x1F DUP3 ADD AND DUP3 ADD DUP1 PUSH1 0x40 MSTORE POP PUSH2 0x530 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0xAE0 JUMP JUMPDEST POP JUMPDEST PUSH1 0x0 DUP3 GT ISZERO PUSH2 0x5E4 JUMPI DUP11 MLOAD PUSH1 0x40 MLOAD PUSH32 0xA9059CBB00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP6 AND SWAP2 PUSH4 0xA9059CBB SWAP2 PUSH2 0x590 SWAP2 SWAP1 DUP7 SWAP1 PUSH1 0x4 ADD PUSH2 0x105F JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x5AA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x5BE JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP PUSH1 0x40 MLOAD RETURNDATASIZE PUSH1 0x1F NOT PUSH1 0x1F DUP3 ADD AND DUP3 ADD DUP1 PUSH1 0x40 MSTORE POP PUSH2 0x5E2 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0xAE0 JUMP JUMPDEST POP JUMPDEST POP POP POP POP POP POP SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5FE DUP4 DUP4 PUSH2 0x766 JUMP JUMPDEST SWAP1 POP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP4 ISZERO ISZERO PUSH2 0x61A JUMPI PUSH1 0x0 SWAP2 POP PUSH2 0x666 JUMP JUMPDEST POP DUP3 DUP3 MUL DUP3 DUP5 DUP3 DUP2 ISZERO ISZERO PUSH2 0x62A JUMPI INVALID JUMPDEST DIV EQ PUSH2 0x662 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x109A JUMP JUMPDEST DUP1 SWAP2 POP JUMPDEST POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 DUP2 ISZERO ISZERO PUSH2 0x67B JUMPI INVALID JUMPDEST DIV SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 DUP3 ADD DUP4 DUP2 LT ISZERO PUSH2 0x662 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x109A JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x14 ADD DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0x705 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x10DA JUMP JUMPDEST POP ADD PUSH1 0x14 ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP3 DUP3 GT ISZERO PUSH2 0x760 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x107A JUMP JUMPDEST POP SWAP1 SUB SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x20 ADD DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0x7A8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x105 SWAP1 PUSH2 0x108A JUMP JUMPDEST POP ADD PUSH1 0x20 ADD MLOAD SWAP1 JUMP JUMPDEST PUSH1 0xC0 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH2 0x120 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH2 0x7FD PUSH2 0x817 JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x80A PUSH2 0x817 JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x80 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x84C DUP3 CALLDATALOAD PUSH2 0x11EF JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x84C DUP3 MLOAD PUSH2 0x120B JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0x870 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0x883 PUSH2 0x87E DUP3 PUSH2 0x11A5 JUMP JUMPDEST PUSH2 0x117E JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE PUSH1 0x20 DUP4 ADD PUSH1 0x20 DUP4 ADD DUP6 DUP4 DUP4 ADD GT ISZERO PUSH2 0x89F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x8AA DUP4 DUP3 DUP5 PUSH2 0x1210 JUMP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x80 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x8C5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x8CF PUSH1 0x80 PUSH2 0x117E JUMP JUMPDEST SWAP1 POP PUSH1 0x0 PUSH2 0x8DD DUP5 DUP5 PUSH2 0xAD4 JUMP JUMPDEST DUP3 MSTORE POP PUSH1 0x20 PUSH2 0x8EE DUP5 DUP5 DUP4 ADD PUSH2 0xAD4 JUMP JUMPDEST PUSH1 0x20 DUP4 ADD MSTORE POP PUSH1 0x40 PUSH2 0x902 DUP5 DUP3 DUP6 ADD PUSH2 0xAD4 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MSTORE POP PUSH1 0x60 PUSH2 0x916 DUP5 DUP3 DUP6 ADD PUSH2 0xAD4 JUMP JUMPDEST PUSH1 0x60 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x120 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x935 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x93F PUSH1 0x60 PUSH2 0x117E JUMP JUMPDEST SWAP1 POP PUSH1 0x0 PUSH2 0x94D DUP5 DUP5 PUSH2 0x8B3 JUMP JUMPDEST DUP3 MSTORE POP PUSH1 0x80 PUSH2 0x95E DUP5 DUP5 DUP4 ADD PUSH2 0x8B3 JUMP JUMPDEST PUSH1 0x20 DUP4 ADD MSTORE POP PUSH2 0x100 PUSH2 0x973 DUP5 DUP3 DUP6 ADD PUSH2 0xAD4 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x180 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x992 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x99D PUSH2 0x180 PUSH2 0x117E JUMP JUMPDEST SWAP1 POP PUSH1 0x0 PUSH2 0x9AB DUP5 DUP5 PUSH2 0x840 JUMP JUMPDEST DUP3 MSTORE POP PUSH1 0x20 PUSH2 0x9BC DUP5 DUP5 DUP4 ADD PUSH2 0x840 JUMP JUMPDEST PUSH1 0x20 DUP4 ADD MSTORE POP PUSH1 0x40 PUSH2 0x9D0 DUP5 DUP3 DUP6 ADD PUSH2 0x840 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MSTORE POP PUSH1 0x60 PUSH2 0x9E4 DUP5 DUP3 DUP6 ADD PUSH2 0x840 JUMP JUMPDEST PUSH1 0x60 DUP4 ADD MSTORE POP PUSH1 0x80 PUSH2 0x9F8 DUP5 DUP3 DUP6 ADD PUSH2 0xAC8 JUMP JUMPDEST PUSH1 0x80 DUP4 ADD MSTORE POP PUSH1 0xA0 PUSH2 0xA0C DUP5 DUP3 DUP6 ADD PUSH2 0xAC8 JUMP JUMPDEST PUSH1 0xA0 DUP4 ADD MSTORE POP PUSH1 0xC0 PUSH2 0xA20 DUP5 DUP3 DUP6 ADD PUSH2 0xAC8 JUMP JUMPDEST PUSH1 0xC0 DUP4 ADD MSTORE POP PUSH1 0xE0 PUSH2 0xA34 DUP5 DUP3 DUP6 ADD PUSH2 0xAC8 JUMP JUMPDEST PUSH1 0xE0 DUP4 ADD MSTORE POP PUSH2 0x100 PUSH2 0xA49 DUP5 DUP3 DUP6 ADD PUSH2 0xAC8 JUMP JUMPDEST PUSH2 0x100 DUP4 ADD MSTORE POP PUSH2 0x120 PUSH2 0xA5F DUP5 DUP3 DUP6 ADD PUSH2 0xAC8 JUMP JUMPDEST PUSH2 0x120 DUP4 ADD MSTORE POP PUSH2 0x140 DUP3 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xA81 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xA8D DUP5 DUP3 DUP6 ADD PUSH2 0x85F JUMP JUMPDEST PUSH2 0x140 DUP4 ADD MSTORE POP PUSH2 0x160 DUP3 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xAAF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xABB DUP5 DUP3 DUP6 ADD PUSH2 0x85F JUMP JUMPDEST PUSH2 0x160 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x84C DUP3 CALLDATALOAD PUSH2 0x1208 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x84C DUP3 MLOAD PUSH2 0x1208 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xAF2 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0xAFE DUP5 DUP5 PUSH2 0x853 JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x120 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xB19 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0xAFE DUP5 DUP5 PUSH2 0x922 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xB37 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xB4E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xAFE DUP5 DUP3 DUP6 ADD PUSH2 0x97F JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP1 PUSH1 0x80 DUP6 DUP8 SUB SLT ISZERO PUSH2 0xB70 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP5 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xB87 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB93 DUP8 DUP3 DUP9 ADD PUSH2 0x97F JUMP JUMPDEST SWAP5 POP POP PUSH1 0x20 DUP6 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xBB0 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xBBC DUP8 DUP3 DUP9 ADD PUSH2 0x97F JUMP JUMPDEST SWAP4 POP POP PUSH1 0x40 DUP6 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xBD9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xBE5 DUP8 DUP3 DUP9 ADD PUSH2 0x85F JUMP JUMPDEST SWAP3 POP POP PUSH1 0x60 DUP6 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xC02 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xC0E DUP8 DUP3 DUP9 ADD PUSH2 0x85F JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP6 SWAP2 SWAP5 POP SWAP3 POP JUMP JUMPDEST PUSH2 0xC23 DUP2 PUSH2 0x11EF JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0xC34 DUP3 PUSH2 0x11EB JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH2 0xC48 DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x121C JUMP JUMPDEST PUSH2 0xC51 DUP2 PUSH2 0x1248 JUMP JUMPDEST SWAP1 SWAP4 ADD PUSH1 0x20 ADD SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x11 DUP2 MSTORE PUSH32 0x55494E543235365F554E444552464C4F57000000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST PUSH1 0x26 DUP2 MSTORE PUSH32 0x475245415445525F4F525F455155414C5F544F5F33325F4C454E4754485F5245 PUSH1 0x20 DUP3 ADD MSTORE PUSH32 0x5155495245440000000000000000000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST PUSH1 0x10 DUP2 MSTORE PUSH32 0x55494E543235365F4F564552464C4F5700000000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST PUSH1 0x12 DUP2 MSTORE PUSH32 0x494E56414C49445F41535345545F444154410000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST PUSH1 0x12 DUP2 MSTORE PUSH32 0x494E56414C49445F424547494E5F54494D450000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST PUSH1 0xF DUP2 MSTORE PUSH32 0x41554354494F4E5F455850495245440000000000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST PUSH1 0x26 DUP2 MSTORE PUSH32 0x475245415445525F4F525F455155414C5F544F5F32305F4C454E4754485F5245 PUSH1 0x20 DUP3 ADD MSTORE PUSH32 0x5155495245440000000000000000000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST PUSH1 0x13 DUP2 MSTORE PUSH32 0x41554354494F4E5F4E4F545F5354415254454400000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST PUSH1 0xE DUP2 MSTORE PUSH32 0x494E56414C49445F414D4F554E54000000000000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST DUP1 MLOAD PUSH1 0xC0 DUP4 ADD SWAP1 PUSH2 0xE6B DUP5 DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0x20 DUP3 ADD MLOAD PUSH2 0xE7E PUSH1 0x20 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0x40 DUP3 ADD MLOAD PUSH2 0xE91 PUSH1 0x40 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0x60 DUP3 ADD MLOAD PUSH2 0xEA4 PUSH1 0x60 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0x80 DUP3 ADD MLOAD PUSH2 0xEB7 PUSH1 0x80 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0xA0 DUP3 ADD MLOAD PUSH2 0xECA PUSH1 0xA0 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP POP POP POP JUMP JUMPDEST DUP1 MLOAD PUSH1 0x80 DUP4 ADD SWAP1 PUSH2 0xEE1 DUP5 DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0x20 DUP3 ADD MLOAD PUSH2 0xEF4 PUSH1 0x20 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0x40 DUP3 ADD MLOAD PUSH2 0xF07 PUSH1 0x40 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0x60 DUP3 ADD MLOAD PUSH2 0xECA PUSH1 0x60 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST DUP1 MLOAD PUSH2 0x120 DUP4 ADD SWAP1 PUSH2 0xF2C DUP5 DUP3 PUSH2 0xED0 JUMP JUMPDEST POP PUSH1 0x20 DUP3 ADD MLOAD PUSH2 0xF3F PUSH1 0x80 DUP6 ADD DUP3 PUSH2 0xED0 JUMP JUMPDEST POP PUSH1 0x40 DUP3 ADD MLOAD PUSH2 0xECA PUSH2 0x100 DUP6 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST DUP1 MLOAD PUSH1 0x0 SWAP1 PUSH2 0x180 DUP5 ADD SWAP1 PUSH2 0xF68 DUP6 DUP3 PUSH2 0xC1A JUMP JUMPDEST POP PUSH1 0x20 DUP4 ADD MLOAD PUSH2 0xF7B PUSH1 0x20 DUP7 ADD DUP3 PUSH2 0xC1A JUMP JUMPDEST POP PUSH1 0x40 DUP4 ADD MLOAD PUSH2 0xF8E PUSH1 0x40 DUP7 ADD DUP3 PUSH2 0xC1A JUMP JUMPDEST POP PUSH1 0x60 DUP4 ADD MLOAD PUSH2 0xFA1 PUSH1 0x60 DUP7 ADD DUP3 PUSH2 0xC1A JUMP JUMPDEST POP PUSH1 0x80 DUP4 ADD MLOAD PUSH2 0xFB4 PUSH1 0x80 DUP7 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0xA0 DUP4 ADD MLOAD PUSH2 0xFC7 PUSH1 0xA0 DUP7 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0xC0 DUP4 ADD MLOAD PUSH2 0xFDA PUSH1 0xC0 DUP7 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH1 0xE0 DUP4 ADD MLOAD PUSH2 0xFED PUSH1 0xE0 DUP7 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH2 0x100 DUP4 ADD MLOAD PUSH2 0x1002 PUSH2 0x100 DUP7 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH2 0x120 DUP4 ADD MLOAD PUSH2 0x1017 PUSH2 0x120 DUP7 ADD DUP3 PUSH2 0x1056 JUMP JUMPDEST POP PUSH2 0x140 DUP4 ADD MLOAD DUP5 DUP3 SUB PUSH2 0x140 DUP7 ADD MSTORE PUSH2 0x1031 DUP3 DUP3 PUSH2 0xC29 JUMP JUMPDEST SWAP2 POP POP PUSH2 0x160 DUP4 ADD MLOAD DUP5 DUP3 SUB PUSH2 0x160 DUP7 ADD MSTORE PUSH2 0x104D DUP3 DUP3 PUSH2 0xC29 JUMP JUMPDEST SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST PUSH2 0xC23 DUP2 PUSH2 0x1208 JUMP JUMPDEST PUSH1 0x40 DUP2 ADD PUSH2 0x106D DUP3 DUP6 PUSH2 0xC1A JUMP JUMPDEST PUSH2 0x84C PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x1056 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xC5E JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xC8E JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xCE4 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xD14 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xD44 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xD74 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xDA4 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xDFA JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x601 DUP2 PUSH2 0xE2A JUMP JUMPDEST PUSH1 0xC0 DUP2 ADD PUSH2 0x601 DUP3 DUP5 PUSH2 0xE5A JUMP JUMPDEST PUSH2 0x120 DUP2 ADD PUSH2 0x601 DUP3 DUP5 PUSH2 0xF1A JUMP JUMPDEST PUSH1 0x80 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x1138 DUP2 DUP8 PUSH2 0xF53 JUMP JUMPDEST SWAP1 POP DUP2 DUP2 SUB PUSH1 0x20 DUP4 ADD MSTORE PUSH2 0x114C DUP2 DUP7 PUSH2 0xF53 JUMP JUMPDEST SWAP1 POP DUP2 DUP2 SUB PUSH1 0x40 DUP4 ADD MSTORE PUSH2 0x1160 DUP2 DUP6 PUSH2 0xC29 JUMP JUMPDEST SWAP1 POP DUP2 DUP2 SUB PUSH1 0x60 DUP4 ADD MSTORE PUSH2 0x1174 DUP2 DUP5 PUSH2 0xC29 JUMP JUMPDEST SWAP7 SWAP6 POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x119D JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT ISZERO PUSH2 0x11BC JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 PUSH1 0x1F SWAP2 SWAP1 SWAP2 ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND ADD SWAP1 JUMP JUMPDEST MLOAD SWAP1 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST ISZERO ISZERO SWAP1 JUMP JUMPDEST DUP3 DUP2 DUP4 CALLDATACOPY POP PUSH1 0x0 SWAP2 ADD MSTORE JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x1237 JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x121F JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0xECA JUMPI POP POP PUSH1 0x0 SWAP2 ADD MSTORE JUMP JUMPDEST PUSH1 0x1F ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND SWAP1 JUMP STOP LOG2 PUSH6 0x627A7A723058 KECCAK256 SWAP13 0xf7 SIGNEXTEND DIV 0xb7 0x5f 0xc2 RETURNDATACOPY PUSH8 0x62AE4C6C8F25CCAD 0x25 0xdf 0xcb CODECOPY 0xcf SAR 0xd3 SWAP7 PUSH15 0xB27CE513DE036C6578706572696D65 PUSH15 0x74616CF50037000000000000000000 ", + "sourceMap": "986:9378:28:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;7335:3027;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;7335:3027:28;;;;;;;;;;;;;;;;;;;;;;;;;3690:3508;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;3690:3508:28;;;;;;;;;;;;;;;;;7335:3027;7437:36;;:::i;:::-;7520:20;;;;:27;7489:28;;;;;;;8295:3;8271:27;;;8250:92;;;;;;;;;;;;;;;;;;;;;;8386:20;;;;:59;;8419:25;;;8386:59;:32;:59;:::i;:::-;8484:20;;;;8352:93;;-1:-1:-1;8484:59:28;;8517:25;;;8484:59;:32;:59;:::i;:::-;8455:88;;8657:23;8627:5;:27;;;:53;8606:118;;;;;;;;;;;;;;;;8795:23;8767:5;:27;;;:51;8734:84;;8900:5;:22;;;8880:42;;8974:9;8953:18;:30;8932:91;;;;;;;;;;;;;;;;-1:-1:-1;;;9192:57:28;;;9291:27;;;;;9259:29;;;:59;9328:26;;;:47;;;9385:24;;;:36;;;9167:15;9431:33;;;:45;;;9522:27;;9055:28;;;;9167:15;9522:37;;;9573:35;;;9569:756;;;9717:28;;;:49;;;9569:756;;;9800:27;;;;9787:40;;9783:542;;10009:28;;;:40;;;9783:542;;;10111:203;10136:9;10163:137;10192:46;10200:24;10226:11;10192:7;:46::i;:::-;10260:22;10163:7;:137::i;:::-;10111:7;:203::i;:::-;10080:28;;;:234;9783:542;7335:3027;;;;;;;;;;;:::o;3690:3508::-;3901:59;;:::i;:::-;3976:36;;:::i;:::-;5398:34;6127:22;6190:13;6404:25;6510:26;4015:28;4033:9;4015:17;:28::i;:::-;4161:31;;4124:33;;;;3976:67;;-1:-1:-1;;4124:68:28;4103:134;;;;;;;;;;;;;;4413:33;;;;4379:31;;;;:67;4358:129;;;;;;;;;;;;;;4627:28;;;;;4598:25;;;;:57;;4577:118;;;;;;;;;;;;;;4780:8;;:128;;;;;:8;;;;;:20;;:128;;4814:8;;4836:9;;4859:12;;4885:13;;4780:128;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4780:128:28;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;4780:128:28;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;4780:128:28;;;;;;;;;4759:149;;5435:18;:45;;;5398:82;;5523:1;5494:26;:30;5490:1667;;;6152:24;;;;;-1:-1:-1;6206:25:28;6152:24;6228:2;6206:25;:21;:25;:::i;:::-;6190:41;;6432:64;6440:8;:25;;;6467:14;:28;;;6432:7;:64::i;:::-;6404:92;;6539:54;6547:26;6575:17;6539:7;:54::i;:::-;6510:83;;6766:1;6745:18;:22;6741:132;;;6815:22;;6787:71;;;;;:27;;;;;;:71;;6815:22;6839:18;;6787:71;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;6787:71:28;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6787:71:28;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;6787:71:28;;;;;;;;;;6741:132;7042:1;7022:17;:21;7018:129;;;7091:21;;7063:69;;;;;:27;;;;;;:69;;7091:21;7114:17;;7063:69;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;7063:69:28;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;7063:69:28;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;7063:69:28;;;;;;;;;;7018:129;3690:3508;;;;;;;;;;;;:::o;14708:220:17:-;14829:14;14876:21;14888:1;14891:5;14876:11;:21::i;:::-;14868:30;-1:-1:-1;14708:220:17;;;;;:::o;51:288:20:-;137:7;;164:6;;160:45;;;193:1;186:8;;;;160:45;-1:-1:-1;226:5:20;;;230:1;226;:5;262;;;;;;;;:10;241:73;;;;;;;;;;;;;;331:1;324:8;;51:288;;;;;;:::o;345:151::-;431:7;454:9;470:1;466;:5;;;;;;;;;345:151;-1:-1:-1;;;;345:151:20:o;716:230::-;802:7;837:5;;;873:6;;;;852:69;;;;;;;;;;;;;10268:886:17;10389:14;10452:5;10460:2;10452:10;10440:1;:8;:22;;10419:135;;;;;;;;;;;;;;;;-1:-1:-1;11056:13:17;10801:2;11056:13;11050:20;11072:42;11046:69;;10268:886::o;502:208:20:-;588:7;632:6;;;;611:70;;;;;;;;;;;;;;-1:-1:-1;698:5:20;;;502:208::o;13290:490:17:-;13411:14;13474:5;13482:2;13474:10;13462:1;:8;:22;;13441:107;;;;;;;;;;;;;;;;-1:-1:-1;13727:13:17;13629:2;13727:13;13721:20;;13290:490::o;986:9378:28:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;5:118:-1:-;;72:46;110:6;97:20;72:46;;;63:55;57:66;-1:-1;;;57:66;130:116;;205:36;233:6;227:13;205:36;;254:432;;344:4;332:17;;328:27;-1:-1;318:2;;369:1;366;359:12;318:2;406:6;393:20;428:60;443:44;480:6;443:44;;;428:60;;;419:69;;508:6;501:5;494:21;544:4;536:6;532:17;577:4;570:5;566:16;612:3;603:6;598:3;594:16;591:25;588:2;;;629:1;626;619:12;588:2;639:41;673:6;668:3;663;639:41;;;311:375;;;;;;;;1183:861;;1308:4;1296:9;1291:3;1287:19;1283:30;1280:2;;;1326:1;1323;1316:12;1280:2;1344:20;1359:4;1344:20;;;1335:29;-1:-1;1432:1;1463:60;1519:3;1499:9;1463:60;;;1439:85;;-1:-1;1603:2;1636:60;1692:3;1668:22;;;1636:60;;;1629:4;1622:5;1618:16;1611:86;1545:163;1766:2;1799:60;1855:3;1846:6;1835:9;1831:22;1799:60;;;1792:4;1785:5;1781:16;1774:86;1718:153;1929:2;1962:60;2018:3;2009:6;1998:9;1994:22;1962:60;;;1955:4;1948:5;1944:16;1937:86;1881:153;1274:770;;;;;2098:741;;2234:5;2222:9;2217:3;2213:19;2209:31;2206:2;;;2253:1;2250;2243:12;2206:2;2271:20;2286:4;2271:20;;;2262:29;-1:-1;2341:1;2372:85;2453:3;2433:9;2372:85;;;2348:110;;-1:-1;2520:3;2554:85;2635:3;2611:22;;;2554:85;;;2547:4;2540:5;2536:16;2529:111;2479:172;2723:3;2757:60;2813:3;2804:6;2793:9;2789:22;2757:60;;;2750:4;2743:5;2739:16;2732:86;2661:168;2200:639;;;;;2874:2208;;2985:5;2973:9;2968:3;2964:19;2960:31;2957:2;;;3004:1;3001;2994:12;2957:2;3022:21;3037:5;3022:21;;;3013:30;-1:-1;3101:1;3132:49;3177:3;3157:9;3132:49;;;3108:74;;-1:-1;3251:2;3284:49;3329:3;3305:22;;;3284:49;;;3277:4;3270:5;3266:16;3259:75;3203:142;3410:2;3443:49;3488:3;3479:6;3468:9;3464:22;3443:49;;;3436:4;3429:5;3425:16;3418:75;3355:149;3563:2;3596:49;3641:3;3632:6;3621:9;3617:22;3596:49;;;3589:4;3582:5;3578:16;3571:75;3514:143;3719:3;3753:49;3798:3;3789:6;3778:9;3774:22;3753:49;;;3746:4;3739:5;3735:16;3728:75;3667:147;3876:3;3910:49;3955:3;3946:6;3935:9;3931:22;3910:49;;;3903:4;3896:5;3892:16;3885:75;3824:147;4025:3;4059:49;4104:3;4095:6;4084:9;4080:22;4059:49;;;4052:4;4045:5;4041:16;4034:75;3981:139;4174:3;4208:49;4253:3;4244:6;4233:9;4229:22;4208:49;;;4201:4;4194:5;4190:16;4183:75;4130:139;4336:3;4371:49;4416:3;4407:6;4396:9;4392:22;4371:49;;;4363:5;4356;4352:17;4345:76;4279:153;4482:3;4517:49;4562:3;4553:6;4542:9;4538:22;4517:49;;;4509:5;4502;4498:17;4491:76;4442:136;4666:3;4655:9;4651:19;4638:33;4691:18;4683:6;4680:30;4677:2;;;4723:1;4720;4713:12;4677:2;4759:54;4809:3;4800:6;4789:9;4785:22;4759:54;;;4751:5;4744;4740:17;4733:81;4588:237;4913:3;4902:9;4898:19;4885:33;4938:18;4930:6;4927:30;4924:2;;;4970:1;4967;4960:12;4924:2;5006:54;5056:3;5047:6;5036:9;5032:22;5006:54;;;4998:5;4991;4987:17;4980:81;4835:237;2951:2131;;;;;5089:118;;5156:46;5194:6;5181:20;5156:46;;5214:122;;5292:39;5323:6;5317:13;5292:39;;5343:257;;5455:2;5443:9;5434:7;5430:23;5426:32;5423:2;;;5471:1;5468;5461:12;5423:2;5506:1;5523:61;5576:7;5556:9;5523:61;;;5513:71;5417:183;-1:-1;;;;5417:183;5607:336;;5758:3;5746:9;5737:7;5733:23;5729:33;5726:2;;;5775:1;5772;5765:12;5726:2;5810:1;5827:100;5919:7;5899:9;5827:100;;5950:371;;6076:2;6064:9;6055:7;6051:23;6047:32;6044:2;;;6092:1;6089;6082:12;6044:2;6127:31;;6178:18;6167:30;;6164:2;;;6210:1;6207;6200:12;6164:2;6230:75;6297:7;6288:6;6277:9;6273:22;6230:75;;6328:1085;;;;;6545:3;6533:9;6524:7;6520:23;6516:33;6513:2;;;6562:1;6559;6552:12;6513:2;6597:31;;6648:18;6637:30;;6634:2;;;6680:1;6677;6670:12;6634:2;6700:75;6767:7;6758:6;6747:9;6743:22;6700:75;;;6690:85;;6576:205;6840:2;6829:9;6825:18;6812:32;6864:18;6856:6;6853:30;6850:2;;;6896:1;6893;6886:12;6850:2;6916:75;6983:7;6974:6;6963:9;6959:22;6916:75;;;6906:85;;6791:206;7056:2;7045:9;7041:18;7028:32;7080:18;7072:6;7069:30;7066:2;;;7112:1;7109;7102:12;7066:2;7132:62;7186:7;7177:6;7166:9;7162:22;7132:62;;;7122:72;;7007:193;7259:2;7248:9;7244:18;7231:32;7283:18;7275:6;7272:30;7269:2;;;7315:1;7312;7305:12;7269:2;7335:62;7389:7;7380:6;7369:9;7365:22;7335:62;;;7325:72;;7210:193;6507:906;;;;;;;;7420:110;7493:31;7518:5;7493:31;;;7488:3;7481:44;7475:55;;;7537:297;;7637:38;7669:5;7637:38;;;7692:6;7687:3;7680:19;7704:63;7760:6;7753:4;7748:3;7744:14;7737:4;7730:5;7726:16;7704:63;;;7799:29;7821:6;7799:29;;;7779:50;;;7792:4;7779:50;;7617:217;-1:-1;;;7617:217;8138:296;8293:2;8281:15;;8330:66;8325:2;8316:12;;8309:88;8425:2;8416:12;;8274:160;8443:397;8598:2;8586:15;;8635:66;8630:2;8621:12;;8614:88;8736:66;8731:2;8722:12;;8715:88;8831:2;8822:12;;8579:261;8849:296;9004:2;8992:15;;9041:66;9036:2;9027:12;;9020:88;9136:2;9127:12;;8985:160;9154:296;9309:2;9297:15;;9346:66;9341:2;9332:12;;9325:88;9441:2;9432:12;;9290:160;9459:296;9614:2;9602:15;;9651:66;9646:2;9637:12;;9630:88;9746:2;9737:12;;9595:160;9764:296;9919:2;9907:15;;9956:66;9951:2;9942:12;;9935:88;10051:2;10042:12;;9900:160;10069:397;10224:2;10212:15;;10261:66;10256:2;10247:12;;10240:88;10362:66;10357:2;10348:12;;10341:88;10457:2;10448:12;;10205:261;10475:296;10630:2;10618:15;;10667:66;10662:2;10653:12;;10646:88;10762:2;10753:12;;10611:160;10780:296;10935:2;10923:15;;10972:66;10967:2;10958:12;;10951:88;11067:2;11058:12;;10916:160;11163:1231;11387:22;;11306:4;11297:14;;;11421:61;11301:3;11387:22;11421:61;;;11326:168;11580:4;11573:5;11569:16;11563:23;11598:62;11654:4;11649:3;11645:14;11632:11;11598:62;;;11504:168;11755:4;11748:5;11744:16;11738:23;11773:62;11829:4;11824:3;11820:14;11807:11;11773:62;;;11682:165;11928:4;11921:5;11917:16;11911:23;11946:62;12002:4;11997:3;11993:14;11980:11;11946:62;;;11857:163;12105:4;12098:5;12094:16;12088:23;12123:62;12179:4;12174:3;12170:14;12157:11;12123:62;;;12030:167;12287:4;12280:5;12276:16;12270:23;12305:62;12361:4;12356:3;12352:14;12339:11;12305:62;;;12207:172;11279:1115;;;;12478:884;12702:22;;12615:4;12606:14;;;12736:61;12610:3;12702:22;12736:61;;;12635:174;12903:4;12896:5;12892:16;12886:23;12921:62;12977:4;12972:3;12968:14;12955:11;12921:62;;;12819:176;13079:4;13072:5;13068:16;13062:23;13097:62;13153:4;13148:3;13144:14;13131:11;13097:62;;;13005:166;13255:4;13248:5;13244:16;13238:23;13273:62;13329:4;13324:3;13320:14;13307:11;13273:62;;13460:815;13685:22;;13615:5;13606:15;;;13719:115;13610:3;13685:22;13719:115;;;13636:210;13923:4;13916:5;13912:16;13906:23;13941:116;14051:4;14046:3;14042:14;14029:11;13941:116;;;13856:213;14167:4;14160:5;14156:16;14150:23;14185:63;14241:5;14236:3;14232:15;14219:11;14185:63;;14335:2417;14548:22;;14335:2417;;14470:5;14461:15;;;14582:61;14465:3;14548:22;14582:61;;;14491:164;14739:4;14732:5;14728:16;14722:23;14757:62;14813:4;14808:3;14804:14;14791:11;14757:62;;;14665:166;14922:4;14915:5;14911:16;14905:23;14940:62;14996:4;14991:3;14987:14;14974:11;14940:62;;;14841:173;15099:4;15092:5;15088:16;15082:23;15117:62;15173:4;15168:3;15164:14;15151:11;15117:62;;;15024:167;15279:4;15272:5;15268:16;15262:23;15297:62;15353:4;15348:3;15344:14;15331:11;15297:62;;;15201:170;15459:4;15452:5;15448:16;15442:23;15477:62;15533:4;15528:3;15524:14;15511:11;15477:62;;;15381:170;15631:4;15624:5;15620:16;15614:23;15649:62;15705:4;15700:3;15696:14;15683:11;15649:62;;;15561:162;15803:4;15796:5;15792:16;15786:23;15821:62;15877:4;15872:3;15868:14;15855:11;15821:62;;;15733:162;15988:5;15981;15977:17;15971:24;16007:63;16063:5;16058:3;16054:15;16041:11;16007:63;;;15905:177;16158:5;16151;16147:17;16141:24;16177:63;16233:5;16228:3;16224:15;16211:11;16177:63;;;16092:160;16338:5;16331;16327:17;16321:24;16391:3;16385:4;16381:14;16373:5;16368:3;16364:15;16357:39;16411:66;16472:4;16459:11;16411:66;;;16403:74;;16262:227;16575:5;16568;16564:17;16558:24;16628:3;16622:4;16618:14;16610:5;16605:3;16601:15;16594:39;16648:66;16709:4;16696:11;16648:66;;;16640:74;14443:2309;-1:-1;;;;;14443:2309;16759:110;16832:31;16857:5;16832:31;;16876:294;17012:2;16997:18;;17026:61;17001:9;17060:6;17026:61;;;17098:62;17156:2;17145:9;17141:18;17132:6;17098:62;;17177:387;17358:2;17372:47;;;17343:18;;17433:121;17343:18;17433:121;;17571:387;17752:2;17766:47;;;17737:18;;17827:121;17737:18;17827:121;;17965:387;18146:2;18160:47;;;18131:18;;18221:121;18131:18;18221:121;;18359:387;18540:2;18554:47;;;18525:18;;18615:121;18525:18;18615:121;;18753:387;18934:2;18948:47;;;18919:18;;19009:121;18919:18;19009:121;;19147:387;19328:2;19342:47;;;19313:18;;19403:121;19313:18;19403:121;;19541:387;19722:2;19736:47;;;19707:18;;19797:121;19707:18;19797:121;;19935:387;20116:2;20130:47;;;20101:18;;20191:121;20101:18;20191:121;;20329:387;20510:2;20524:47;;;20495:18;;20585:121;20495:18;20585:121;;20723:314;20891:3;20876:19;;20906:121;20880:9;21000:6;20906:121;;21044:338;21224:3;21209:19;;21239:133;21213:9;21345:6;21239:133;;21389:937;21705:3;21720:47;;;21690:19;;21781:92;21690:19;21859:6;21781:92;;;21773:100;;21921:9;21915:4;21911:20;21906:2;21895:9;21891:18;21884:48;21946:92;22033:4;22024:6;21946:92;;;21938:100;;22086:9;22080:4;22076:20;22071:2;22060:9;22056:18;22049:48;22111:66;22172:4;22163:6;22111:66;;;22103:74;;22225:9;22219:4;22215:20;22210:2;22199:9;22195:18;22188:48;22250:66;22311:4;22302:6;22250:66;;;22242:74;21676:650;-1:-1;;;;;;21676:650;22333:256;22395:2;22389:9;22421:17;;;22496:18;22481:34;;22517:22;;;22478:62;22475:2;;;22553:1;22550;22543:12;22475:2;22569;22562:22;22373:216;;-1:-1;22373:216;22596:254;;22735:18;22727:6;22724:30;22721:2;;;22767:1;22764;22757:12;22721:2;-1:-1;22840:4;22811;22788:17;;;;22807:9;22784:33;22830:15;;22658:192;23122:87;23192:12;;23176:33;23314:128;23394:42;23383:54;;23366:76;23449:79;23518:5;23501:27;23670:92;23743:13;23736:21;;23719:43;23856:145;23937:6;23932:3;23927;23914:30;-1:-1;23993:1;23975:16;;23968:27;23907:94;24010:268;24075:1;24082:101;24096:6;24093:1;24090:13;24082:101;;;24163:11;;;24157:18;24144:11;;;24137:39;24118:2;24111:10;24082:101;;;24198:6;24195:1;24192:13;24189:2;;;-1:-1;;24263:1;24245:16;;24238:27;24059:219;24286:97;24374:2;24354:14;24370:7;24350:28;;24334:49" + } + } + }, + "sources": { + "DutchAuction/DutchAuction.sol": { + "id": 28 + }, + "@0x/contracts-interfaces/contracts/protocol/Exchange/IExchange.sol": { + "id": 1 + }, + "@0x/contracts-interfaces/contracts/protocol/Exchange/IExchangeCore.sol": { + "id": 2 + }, + "@0x/contracts-libs/contracts/libs/LibOrder.sol": { + "id": 13 + }, + "@0x/contracts-libs/contracts/libs/LibEIP712.sol": { + "id": 9 + }, + "@0x/contracts-libs/contracts/libs/LibFillResults.sol": { + "id": 11 + }, + "@0x/contracts-utils/contracts/utils/SafeMath/SafeMath.sol": { + "id": 20 + }, + "@0x/contracts-interfaces/contracts/protocol/Exchange/IMatchOrders.sol": { + "id": 3 + }, + "@0x/contracts-interfaces/contracts/protocol/Exchange/ISignatureValidator.sol": { + "id": 4 + }, + "@0x/contracts-interfaces/contracts/protocol/Exchange/ITransactions.sol": { + "id": 5 + }, + "@0x/contracts-interfaces/contracts/protocol/Exchange/IAssetProxyDispatcher.sol": { + "id": 0 + }, + "@0x/contracts-interfaces/contracts/protocol/Exchange/IWrapperFunctions.sol": { + "id": 6 + }, + "@0x/contracts-tokens/contracts/tokens/ERC20Token/IERC20Token.sol": { + "id": 14 + }, + "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol": { + "id": 17 + } + }, + "sourceCodes": { + "DutchAuction/DutchAuction.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity 0.4.24;\npragma experimental ABIEncoderV2;\n\nimport \"@0x/contracts-interfaces/contracts/protocol/Exchange/IExchange.sol\";\nimport \"@0x/contracts-libs/contracts/libs/LibOrder.sol\";\nimport \"@0x/contracts-tokens/contracts/tokens/ERC20Token/IERC20Token.sol\";\nimport \"@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol\";\nimport \"@0x/contracts-utils/contracts/utils/SafeMath/SafeMath.sol\";\n\n\ncontract DutchAuction is\n SafeMath\n{\n using LibBytes for bytes;\n\n // solhint-disable var-name-mixedcase\n IExchange internal EXCHANGE;\n\n struct AuctionDetails {\n uint256 beginTimeSeconds; // Auction begin unix timestamp: sellOrder.makerAssetData\n uint256 endTimeSeconds; // Auction end unix timestamp: sellOrder.expiryTimeSeconds\n uint256 beginAmount; // Auction begin amount: sellOrder.makerAssetData\n uint256 endAmount; // Auction end amount: sellOrder.takerAssetAmount\n uint256 currentAmount; // Calculated amount given block.timestamp\n uint256 currentTimeSeconds; // block.timestamp\n }\n\n constructor (address _exchange)\n public\n {\n EXCHANGE = IExchange(_exchange);\n }\n\n /// @dev Matches the buy and sell orders at an amount given the following: the current block time, the auction\n /// start time and the auction begin amount. The sell order is a an order at the lowest amount\n /// at the end of the auction. Excess from the match is transferred to the seller.\n /// Over time the price moves from beginAmount to endAmount given the current block.timestamp.\n /// sellOrder.expiryTimeSeconds is the end time of the auction.\n /// sellOrder.takerAssetAmount is the end amount of the auction (lowest possible amount).\n /// sellOrder.makerAssetData is the ABI encoded Asset Proxy data with the following data appended\n /// buyOrder.makerAssetData is the buyers bid on the auction, must meet the amount for the current block timestamp\n /// (uint256 beginTimeSeconds, uint256 beginAmount).\n /// This function reverts in the following scenarios:\n /// * Auction has not started (auctionDetails.currentTimeSeconds < auctionDetails.beginTimeSeconds)\n /// * Auction has expired (auctionDetails.endTimeSeconds < auctionDetails.currentTimeSeconds)\n /// * Amount is invalid: Buy order amount is too low (buyOrder.makerAssetAmount < auctionDetails.currentAmount)\n /// * Amount is invalid: Invalid begin amount (auctionDetails.beginAmount > auctionDetails.endAmount)\n /// * Any failure in the 0x Match Orders\n /// @param buyOrder The Buyer's order. This order is for the current expected price of the auction.\n /// @param sellOrder The Seller's order. This order is for the lowest amount (at the end of the auction).\n /// @param buySignature Proof that order was created by the buyer.\n /// @param sellSignature Proof that order was created by the seller.\n /// @return matchedFillResults amounts filled and fees paid by maker and taker of matched orders.\n function matchOrders(\n LibOrder.Order memory buyOrder,\n LibOrder.Order memory sellOrder,\n bytes memory buySignature,\n bytes memory sellSignature\n )\n public\n returns (LibFillResults.MatchedFillResults memory matchedFillResults)\n {\n AuctionDetails memory auctionDetails = getAuctionDetails(sellOrder);\n // Ensure the auction has not yet started\n require(\n auctionDetails.currentTimeSeconds >= auctionDetails.beginTimeSeconds,\n \"AUCTION_NOT_STARTED\"\n );\n // Ensure the auction has not expired. This will fail later in 0x but we can save gas by failing early\n require(\n sellOrder.expirationTimeSeconds > auctionDetails.currentTimeSeconds,\n \"AUCTION_EXPIRED\"\n );\n // Validate the buyer amount is greater than the current auction amount\n require(\n buyOrder.makerAssetAmount >= auctionDetails.currentAmount,\n \"INVALID_AMOUNT\"\n );\n // Match orders, maximally filling `buyOrder`\n matchedFillResults = EXCHANGE.matchOrders(\n buyOrder,\n sellOrder,\n buySignature,\n sellSignature\n );\n // The difference in sellOrder.takerAssetAmount and current amount is given as spread to the matcher\n // This may include additional spread from the buyOrder.makerAssetAmount and the currentAmount.\n // e.g currentAmount is 30, sellOrder.takerAssetAmount is 10 and buyOrder.makerAssetamount is 40.\n // 10 (40-30) is returned to the buyer, 20 (30-10) sent to the seller and 10 has previously\n // been transferred to the seller during matchOrders\n uint256 leftMakerAssetSpreadAmount = matchedFillResults.leftMakerAssetSpreadAmount;\n if (leftMakerAssetSpreadAmount > 0) {\n // ERC20 Asset data itself is encoded as follows:\n //\n // | Area | Offset | Length | Contents |\n // |----------|--------|---------|-------------------------------------|\n // | Header | 0 | 4 | function selector |\n // | Params | | 1 * 32 | function parameters: |\n // | | 4 | 12 | 1. token address padding |\n // | | 16 | 20 | 2. token address |\n bytes memory assetData = sellOrder.takerAssetData;\n address token = assetData.readAddress(16);\n // Calculate the excess from the buy order. This can occur if the buyer sends in a higher\n // amount than the calculated current amount\n uint256 buyerExcessAmount = safeSub(buyOrder.makerAssetAmount, auctionDetails.currentAmount);\n uint256 sellerExcessAmount = safeSub(leftMakerAssetSpreadAmount, buyerExcessAmount);\n // Return the difference between auctionDetails.currentAmount and sellOrder.takerAssetAmount\n // to the seller\n if (sellerExcessAmount > 0) {\n IERC20Token(token).transfer(sellOrder.makerAddress, sellerExcessAmount);\n }\n // Return the difference between buyOrder.makerAssetAmount and auctionDetails.currentAmount\n // to the buyer\n if (buyerExcessAmount > 0) {\n IERC20Token(token).transfer(buyOrder.makerAddress, buyerExcessAmount);\n }\n }\n return matchedFillResults;\n }\n\n /// @dev Calculates the Auction Details for the given order\n /// @param order The sell order\n /// @return AuctionDetails\n function getAuctionDetails(\n LibOrder.Order memory order\n )\n public\n returns (AuctionDetails memory auctionDetails)\n {\n uint256 makerAssetDataLength = order.makerAssetData.length;\n // It is unknown the encoded data of makerAssetData, we assume the last 64 bytes\n // are the Auction Details encoding.\n // Auction Details is encoded as follows:\n //\n // | Area | Offset | Length | Contents |\n // |----------|--------|---------|-------------------------------------|\n // | Params | | 2 * 32 | parameters: |\n // | | -64 | 32 | 1. auction begin unix timestamp |\n // | | -32 | 32 | 2. auction begin begin amount |\n // ERC20 asset data length is 4+32, 64 for auction details results in min length 100\n require(\n makerAssetDataLength >= 100,\n \"INVALID_ASSET_DATA\"\n );\n uint256 auctionBeginTimeSeconds = order.makerAssetData.readUint256(makerAssetDataLength - 64);\n uint256 auctionBeginAmount = order.makerAssetData.readUint256(makerAssetDataLength - 32);\n // Ensure the auction has a valid begin time\n require(\n order.expirationTimeSeconds > auctionBeginTimeSeconds,\n \"INVALID_BEGIN_TIME\"\n );\n uint256 auctionDurationSeconds = order.expirationTimeSeconds-auctionBeginTimeSeconds;\n // Ensure the auction goes from high to low\n uint256 minAmount = order.takerAssetAmount;\n require(\n auctionBeginAmount > minAmount,\n \"INVALID_AMOUNT\"\n );\n uint256 amountDelta = auctionBeginAmount-minAmount;\n // solhint-disable-next-line not-rely-on-time\n uint256 timestamp = block.timestamp;\n auctionDetails.beginTimeSeconds = auctionBeginTimeSeconds;\n auctionDetails.endTimeSeconds = order.expirationTimeSeconds;\n auctionDetails.beginAmount = auctionBeginAmount;\n auctionDetails.endAmount = minAmount;\n auctionDetails.currentTimeSeconds = timestamp;\n\n uint256 remainingDurationSeconds = order.expirationTimeSeconds-timestamp;\n if (timestamp < auctionBeginTimeSeconds) {\n // If the auction has not yet begun the current amount is the auctionBeginAmount\n auctionDetails.currentAmount = auctionBeginAmount;\n } else if (timestamp >= order.expirationTimeSeconds) {\n // If the auction has ended the current amount is the minAmount.\n // Auction end time is guaranteed by 0x Exchange due to the order expiration\n auctionDetails.currentAmount = minAmount;\n } else {\n auctionDetails.currentAmount = safeAdd(\n minAmount,\n safeDiv(\n safeMul(remainingDurationSeconds, amountDelta),\n auctionDurationSeconds\n )\n );\n }\n return auctionDetails;\n }\n}\n", + "@0x/contracts-interfaces/contracts/protocol/Exchange/IExchange.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity 0.4.24;\npragma experimental ABIEncoderV2;\n\nimport \"./IExchangeCore.sol\";\nimport \"./IMatchOrders.sol\";\nimport \"./ISignatureValidator.sol\";\nimport \"./ITransactions.sol\";\nimport \"./IAssetProxyDispatcher.sol\";\nimport \"./IWrapperFunctions.sol\";\n\n\n// solhint-disable no-empty-blocks\ncontract IExchange is\n IExchangeCore,\n IMatchOrders,\n ISignatureValidator,\n ITransactions,\n IAssetProxyDispatcher,\n IWrapperFunctions\n{}\n", + "@0x/contracts-interfaces/contracts/protocol/Exchange/IExchangeCore.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity 0.4.24;\npragma experimental ABIEncoderV2;\n\nimport \"@0x/contracts-libs/contracts/libs/LibOrder.sol\";\nimport \"@0x/contracts-libs/contracts/libs/LibFillResults.sol\";\n\n\ncontract IExchangeCore {\n\n /// @dev Cancels all orders created by makerAddress with a salt less than or equal to the targetOrderEpoch\n /// and senderAddress equal to msg.sender (or null address if msg.sender == makerAddress).\n /// @param targetOrderEpoch Orders created with a salt less or equal to this value will be cancelled.\n function cancelOrdersUpTo(uint256 targetOrderEpoch)\n external;\n\n /// @dev Fills the input order.\n /// @param order Order struct containing order specifications.\n /// @param takerAssetFillAmount Desired amount of takerAsset to sell.\n /// @param signature Proof that order has been created by maker.\n /// @return Amounts filled and fees paid by maker and taker.\n function fillOrder(\n LibOrder.Order memory order,\n uint256 takerAssetFillAmount,\n bytes memory signature\n )\n public\n returns (LibFillResults.FillResults memory fillResults);\n\n /// @dev After calling, the order can not be filled anymore.\n /// @param order Order struct containing order specifications.\n function cancelOrder(LibOrder.Order memory order)\n public;\n\n /// @dev Gets information about an order: status, hash, and amount filled.\n /// @param order Order to gather information on.\n /// @return OrderInfo Information about the order and its state.\n /// See LibOrder.OrderInfo for a complete description.\n function getOrderInfo(LibOrder.Order memory order)\n public\n view\n returns (LibOrder.OrderInfo memory orderInfo);\n}\n", + "@0x/contracts-libs/contracts/libs/LibOrder.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity 0.4.24;\n\nimport \"./LibEIP712.sol\";\n\n\ncontract LibOrder is\n LibEIP712\n{\n // Hash for the EIP712 Order Schema\n bytes32 constant internal EIP712_ORDER_SCHEMA_HASH = keccak256(abi.encodePacked(\n \"Order(\",\n \"address makerAddress,\",\n \"address takerAddress,\",\n \"address feeRecipientAddress,\",\n \"address senderAddress,\",\n \"uint256 makerAssetAmount,\",\n \"uint256 takerAssetAmount,\",\n \"uint256 makerFee,\",\n \"uint256 takerFee,\",\n \"uint256 expirationTimeSeconds,\",\n \"uint256 salt,\",\n \"bytes makerAssetData,\",\n \"bytes takerAssetData\",\n \")\"\n ));\n\n // A valid order remains fillable until it is expired, fully filled, or cancelled.\n // An order's state is unaffected by external factors, like account balances.\n enum OrderStatus {\n INVALID, // Default value\n INVALID_MAKER_ASSET_AMOUNT, // Order does not have a valid maker asset amount\n INVALID_TAKER_ASSET_AMOUNT, // Order does not have a valid taker asset amount\n FILLABLE, // Order is fillable\n EXPIRED, // Order has already expired\n FULLY_FILLED, // Order is fully filled\n CANCELLED // Order has been cancelled\n }\n\n // solhint-disable max-line-length\n struct Order {\n address makerAddress; // Address that created the order. \n address takerAddress; // Address that is allowed to fill the order. If set to 0, any address is allowed to fill the order. \n address feeRecipientAddress; // Address that will recieve fees when order is filled. \n address senderAddress; // Address that is allowed to call Exchange contract methods that affect this order. If set to 0, any address is allowed to call these methods.\n uint256 makerAssetAmount; // Amount of makerAsset being offered by maker. Must be greater than 0. \n uint256 takerAssetAmount; // Amount of takerAsset being bid on by maker. Must be greater than 0. \n uint256 makerFee; // Amount of ZRX paid to feeRecipient by maker when order is filled. If set to 0, no transfer of ZRX from maker to feeRecipient will be attempted.\n uint256 takerFee; // Amount of ZRX paid to feeRecipient by taker when order is filled. If set to 0, no transfer of ZRX from taker to feeRecipient will be attempted.\n uint256 expirationTimeSeconds; // Timestamp in seconds at which order expires. \n uint256 salt; // Arbitrary number to facilitate uniqueness of the order's hash. \n bytes makerAssetData; // Encoded data that can be decoded by a specified proxy contract when transferring makerAsset. The last byte references the id of this proxy.\n bytes takerAssetData; // Encoded data that can be decoded by a specified proxy contract when transferring takerAsset. The last byte references the id of this proxy.\n }\n // solhint-enable max-line-length\n\n struct OrderInfo {\n uint8 orderStatus; // Status that describes order's validity and fillability.\n bytes32 orderHash; // EIP712 hash of the order (see LibOrder.getOrderHash).\n uint256 orderTakerAssetFilledAmount; // Amount of order that has already been filled.\n }\n\n /// @dev Calculates Keccak-256 hash of the order.\n /// @param order The order structure.\n /// @return Keccak-256 EIP712 hash of the order.\n function getOrderHash(Order memory order)\n internal\n view\n returns (bytes32 orderHash)\n {\n orderHash = hashEIP712Message(hashOrder(order));\n return orderHash;\n }\n\n /// @dev Calculates EIP712 hash of the order.\n /// @param order The order structure.\n /// @return EIP712 hash of the order.\n function hashOrder(Order memory order)\n internal\n pure\n returns (bytes32 result)\n {\n bytes32 schemaHash = EIP712_ORDER_SCHEMA_HASH;\n bytes32 makerAssetDataHash = keccak256(order.makerAssetData);\n bytes32 takerAssetDataHash = keccak256(order.takerAssetData);\n\n // Assembly for more efficiently computing:\n // keccak256(abi.encodePacked(\n // EIP712_ORDER_SCHEMA_HASH,\n // bytes32(order.makerAddress),\n // bytes32(order.takerAddress),\n // bytes32(order.feeRecipientAddress),\n // bytes32(order.senderAddress),\n // order.makerAssetAmount,\n // order.takerAssetAmount,\n // order.makerFee,\n // order.takerFee,\n // order.expirationTimeSeconds,\n // order.salt,\n // keccak256(order.makerAssetData),\n // keccak256(order.takerAssetData)\n // ));\n\n assembly {\n // Calculate memory addresses that will be swapped out before hashing\n let pos1 := sub(order, 32)\n let pos2 := add(order, 320)\n let pos3 := add(order, 352)\n\n // Backup\n let temp1 := mload(pos1)\n let temp2 := mload(pos2)\n let temp3 := mload(pos3)\n \n // Hash in place\n mstore(pos1, schemaHash)\n mstore(pos2, makerAssetDataHash)\n mstore(pos3, takerAssetDataHash)\n result := keccak256(pos1, 416)\n \n // Restore\n mstore(pos1, temp1)\n mstore(pos2, temp2)\n mstore(pos3, temp3)\n }\n return result;\n }\n}\n", + "@0x/contracts-libs/contracts/libs/LibEIP712.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity 0.4.24;\n\n\ncontract LibEIP712 {\n\n // EIP191 header for EIP712 prefix\n string constant internal EIP191_HEADER = \"\\x19\\x01\";\n\n // EIP712 Domain Name value\n string constant internal EIP712_DOMAIN_NAME = \"0x Protocol\";\n\n // EIP712 Domain Version value\n string constant internal EIP712_DOMAIN_VERSION = \"2\";\n\n // Hash of the EIP712 Domain Separator Schema\n bytes32 constant internal EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256(abi.encodePacked(\n \"EIP712Domain(\",\n \"string name,\",\n \"string version,\",\n \"address verifyingContract\",\n \")\"\n ));\n\n // Hash of the EIP712 Domain Separator data\n // solhint-disable-next-line var-name-mixedcase\n bytes32 public EIP712_DOMAIN_HASH;\n\n constructor ()\n public\n {\n EIP712_DOMAIN_HASH = keccak256(abi.encodePacked(\n EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH,\n keccak256(bytes(EIP712_DOMAIN_NAME)),\n keccak256(bytes(EIP712_DOMAIN_VERSION)),\n bytes32(address(this))\n ));\n }\n\n /// @dev Calculates EIP712 encoding for a hash struct in this EIP712 Domain.\n /// @param hashStruct The EIP712 hash struct.\n /// @return EIP712 hash applied to this EIP712 Domain.\n function hashEIP712Message(bytes32 hashStruct)\n internal\n view\n returns (bytes32 result)\n {\n bytes32 eip712DomainHash = EIP712_DOMAIN_HASH;\n\n // Assembly for more efficient computing:\n // keccak256(abi.encodePacked(\n // EIP191_HEADER,\n // EIP712_DOMAIN_HASH,\n // hashStruct \n // ));\n\n assembly {\n // Load free memory pointer\n let memPtr := mload(64)\n\n mstore(memPtr, 0x1901000000000000000000000000000000000000000000000000000000000000) // EIP191 header\n mstore(add(memPtr, 2), eip712DomainHash) // EIP712 domain hash\n mstore(add(memPtr, 34), hashStruct) // Hash of struct\n\n // Compute hash\n result := keccak256(memPtr, 66)\n }\n return result;\n }\n}\n", + "@0x/contracts-libs/contracts/libs/LibFillResults.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity 0.4.24;\n\nimport \"@0x/contracts-utils/contracts/utils/SafeMath/SafeMath.sol\";\n\n\ncontract LibFillResults is\n SafeMath\n{\n struct FillResults {\n uint256 makerAssetFilledAmount; // Total amount of makerAsset(s) filled.\n uint256 takerAssetFilledAmount; // Total amount of takerAsset(s) filled.\n uint256 makerFeePaid; // Total amount of ZRX paid by maker(s) to feeRecipient(s).\n uint256 takerFeePaid; // Total amount of ZRX paid by taker to feeRecipients(s).\n }\n\n struct MatchedFillResults {\n FillResults left; // Amounts filled and fees paid of left order.\n FillResults right; // Amounts filled and fees paid of right order.\n uint256 leftMakerAssetSpreadAmount; // Spread between price of left and right order, denominated in the left order's makerAsset, paid to taker.\n }\n\n /// @dev Adds properties of both FillResults instances.\n /// Modifies the first FillResults instance specified.\n /// @param totalFillResults Fill results instance that will be added onto.\n /// @param singleFillResults Fill results instance that will be added to totalFillResults.\n function addFillResults(FillResults memory totalFillResults, FillResults memory singleFillResults)\n internal\n pure\n {\n totalFillResults.makerAssetFilledAmount = safeAdd(totalFillResults.makerAssetFilledAmount, singleFillResults.makerAssetFilledAmount);\n totalFillResults.takerAssetFilledAmount = safeAdd(totalFillResults.takerAssetFilledAmount, singleFillResults.takerAssetFilledAmount);\n totalFillResults.makerFeePaid = safeAdd(totalFillResults.makerFeePaid, singleFillResults.makerFeePaid);\n totalFillResults.takerFeePaid = safeAdd(totalFillResults.takerFeePaid, singleFillResults.takerFeePaid);\n }\n}\n", + "@0x/contracts-utils/contracts/utils/SafeMath/SafeMath.sol": "pragma solidity 0.4.24;\n\n\ncontract SafeMath {\n\n function safeMul(uint256 a, uint256 b)\n internal\n pure\n returns (uint256)\n {\n if (a == 0) {\n return 0;\n }\n uint256 c = a * b;\n require(\n c / a == b,\n \"UINT256_OVERFLOW\"\n );\n return c;\n }\n\n function safeDiv(uint256 a, uint256 b)\n internal\n pure\n returns (uint256)\n {\n uint256 c = a / b;\n return c;\n }\n\n function safeSub(uint256 a, uint256 b)\n internal\n pure\n returns (uint256)\n {\n require(\n b <= a,\n \"UINT256_UNDERFLOW\"\n );\n return a - b;\n }\n\n function safeAdd(uint256 a, uint256 b)\n internal\n pure\n returns (uint256)\n {\n uint256 c = a + b;\n require(\n c >= a,\n \"UINT256_OVERFLOW\"\n );\n return c;\n }\n\n function max64(uint64 a, uint64 b)\n internal\n pure\n returns (uint256)\n {\n return a >= b ? a : b;\n }\n\n function min64(uint64 a, uint64 b)\n internal\n pure\n returns (uint256)\n {\n return a < b ? a : b;\n }\n\n function max256(uint256 a, uint256 b)\n internal\n pure\n returns (uint256)\n {\n return a >= b ? a : b;\n }\n\n function min256(uint256 a, uint256 b)\n internal\n pure\n returns (uint256)\n {\n return a < b ? a : b;\n }\n}\n", + "@0x/contracts-interfaces/contracts/protocol/Exchange/IMatchOrders.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\npragma solidity 0.4.24;\npragma experimental ABIEncoderV2;\n\nimport \"@0x/contracts-libs/contracts/libs/LibOrder.sol\";\nimport \"@0x/contracts-libs/contracts/libs/LibFillResults.sol\";\n\n\ncontract IMatchOrders {\n\n /// @dev Match two complementary orders that have a profitable spread.\n /// Each order is filled at their respective price point. However, the calculations are\n /// carried out as though the orders are both being filled at the right order's price point.\n /// The profit made by the left order goes to the taker (who matched the two orders).\n /// @param leftOrder First order to match.\n /// @param rightOrder Second order to match.\n /// @param leftSignature Proof that order was created by the left maker.\n /// @param rightSignature Proof that order was created by the right maker.\n /// @return matchedFillResults Amounts filled and fees paid by maker and taker of matched orders.\n function matchOrders(\n LibOrder.Order memory leftOrder,\n LibOrder.Order memory rightOrder,\n bytes memory leftSignature,\n bytes memory rightSignature\n )\n public\n returns (LibFillResults.MatchedFillResults memory matchedFillResults);\n}\n", + "@0x/contracts-interfaces/contracts/protocol/Exchange/ISignatureValidator.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity 0.4.24;\n\n\ncontract ISignatureValidator {\n\n /// @dev Approves a hash on-chain using any valid signature type.\n /// After presigning a hash, the preSign signature type will become valid for that hash and signer.\n /// @param signerAddress Address that should have signed the given hash.\n /// @param signature Proof that the hash has been signed by signer.\n function preSign(\n bytes32 hash,\n address signerAddress,\n bytes signature\n )\n external;\n \n /// @dev Approves/unnapproves a Validator contract to verify signatures on signer's behalf.\n /// @param validatorAddress Address of Validator contract.\n /// @param approval Approval or disapproval of Validator contract.\n function setSignatureValidatorApproval(\n address validatorAddress,\n bool approval\n )\n external;\n\n /// @dev Verifies that a signature is valid.\n /// @param hash Message hash that is signed.\n /// @param signerAddress Address of signer.\n /// @param signature Proof of signing.\n /// @return Validity of order signature.\n function isValidSignature(\n bytes32 hash,\n address signerAddress,\n bytes memory signature\n )\n public\n view\n returns (bool isValid);\n}\n", + "@0x/contracts-interfaces/contracts/protocol/Exchange/ITransactions.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\npragma solidity 0.4.24;\n\n\ncontract ITransactions {\n\n /// @dev Executes an exchange method call in the context of signer.\n /// @param salt Arbitrary number to ensure uniqueness of transaction hash.\n /// @param signerAddress Address of transaction signer.\n /// @param data AbiV2 encoded calldata.\n /// @param signature Proof of signer transaction by signer.\n function executeTransaction(\n uint256 salt,\n address signerAddress,\n bytes data,\n bytes signature\n )\n external;\n}\n", + "@0x/contracts-interfaces/contracts/protocol/Exchange/IAssetProxyDispatcher.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity 0.4.24;\n\n\ncontract IAssetProxyDispatcher {\n\n /// @dev Registers an asset proxy to its asset proxy id.\n /// Once an asset proxy is registered, it cannot be unregistered.\n /// @param assetProxy Address of new asset proxy to register.\n function registerAssetProxy(address assetProxy)\n external;\n\n /// @dev Gets an asset proxy.\n /// @param assetProxyId Id of the asset proxy.\n /// @return The asset proxy registered to assetProxyId. Returns 0x0 if no proxy is registered.\n function getAssetProxy(bytes4 assetProxyId)\n external\n view\n returns (address);\n}\n", + "@0x/contracts-interfaces/contracts/protocol/Exchange/IWrapperFunctions.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity 0.4.24;\npragma experimental ABIEncoderV2;\n\nimport \"@0x/contracts-libs/contracts/libs/LibOrder.sol\";\nimport \"@0x/contracts-libs/contracts/libs/LibFillResults.sol\";\n\n\ncontract IWrapperFunctions {\n\n /// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled.\n /// @param order LibOrder.Order struct containing order specifications.\n /// @param takerAssetFillAmount Desired amount of takerAsset to sell.\n /// @param signature Proof that order has been created by maker.\n function fillOrKillOrder(\n LibOrder.Order memory order,\n uint256 takerAssetFillAmount,\n bytes memory signature\n )\n public\n returns (LibFillResults.FillResults memory fillResults);\n\n /// @dev Fills an order with specified parameters and ECDSA signature.\n /// Returns false if the transaction would otherwise revert.\n /// @param order LibOrder.Order struct containing order specifications.\n /// @param takerAssetFillAmount Desired amount of takerAsset to sell.\n /// @param signature Proof that order has been created by maker.\n /// @return Amounts filled and fees paid by maker and taker.\n function fillOrderNoThrow(\n LibOrder.Order memory order,\n uint256 takerAssetFillAmount,\n bytes memory signature\n )\n public\n returns (LibFillResults.FillResults memory fillResults);\n\n /// @dev Synchronously executes multiple calls of fillOrder.\n /// @param orders Array of order specifications.\n /// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders.\n /// @param signatures Proofs that orders have been created by makers.\n /// @return Amounts filled and fees paid by makers and taker.\n function batchFillOrders(\n LibOrder.Order[] memory orders,\n uint256[] memory takerAssetFillAmounts,\n bytes[] memory signatures\n )\n public\n returns (LibFillResults.FillResults memory totalFillResults);\n\n /// @dev Synchronously executes multiple calls of fillOrKill.\n /// @param orders Array of order specifications.\n /// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders.\n /// @param signatures Proofs that orders have been created by makers.\n /// @return Amounts filled and fees paid by makers and taker.\n function batchFillOrKillOrders(\n LibOrder.Order[] memory orders,\n uint256[] memory takerAssetFillAmounts,\n bytes[] memory signatures\n )\n public\n returns (LibFillResults.FillResults memory totalFillResults);\n\n /// @dev Fills an order with specified parameters and ECDSA signature.\n /// Returns false if the transaction would otherwise revert.\n /// @param orders Array of order specifications.\n /// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders.\n /// @param signatures Proofs that orders have been created by makers.\n /// @return Amounts filled and fees paid by makers and taker.\n function batchFillOrdersNoThrow(\n LibOrder.Order[] memory orders,\n uint256[] memory takerAssetFillAmounts,\n bytes[] memory signatures\n )\n public\n returns (LibFillResults.FillResults memory totalFillResults);\n\n /// @dev Synchronously executes multiple calls of fillOrder until total amount of takerAsset is sold by taker.\n /// @param orders Array of order specifications.\n /// @param takerAssetFillAmount Desired amount of takerAsset to sell.\n /// @param signatures Proofs that orders have been created by makers.\n /// @return Amounts filled and fees paid by makers and taker.\n function marketSellOrders(\n LibOrder.Order[] memory orders,\n uint256 takerAssetFillAmount,\n bytes[] memory signatures\n )\n public\n returns (LibFillResults.FillResults memory totalFillResults);\n\n /// @dev Synchronously executes multiple calls of fillOrder until total amount of takerAsset is sold by taker.\n /// Returns false if the transaction would otherwise revert.\n /// @param orders Array of order specifications.\n /// @param takerAssetFillAmount Desired amount of takerAsset to sell.\n /// @param signatures Proofs that orders have been signed by makers.\n /// @return Amounts filled and fees paid by makers and taker.\n function marketSellOrdersNoThrow(\n LibOrder.Order[] memory orders,\n uint256 takerAssetFillAmount,\n bytes[] memory signatures\n )\n public\n returns (LibFillResults.FillResults memory totalFillResults);\n\n /// @dev Synchronously executes multiple calls of fillOrder until total amount of makerAsset is bought by taker.\n /// @param orders Array of order specifications.\n /// @param makerAssetFillAmount Desired amount of makerAsset to buy.\n /// @param signatures Proofs that orders have been signed by makers.\n /// @return Amounts filled and fees paid by makers and taker.\n function marketBuyOrders(\n LibOrder.Order[] memory orders,\n uint256 makerAssetFillAmount,\n bytes[] memory signatures\n )\n public\n returns (LibFillResults.FillResults memory totalFillResults);\n\n /// @dev Synchronously executes multiple fill orders in a single transaction until total amount is bought by taker.\n /// Returns false if the transaction would otherwise revert.\n /// @param orders Array of order specifications.\n /// @param makerAssetFillAmount Desired amount of makerAsset to buy.\n /// @param signatures Proofs that orders have been signed by makers.\n /// @return Amounts filled and fees paid by makers and taker.\n function marketBuyOrdersNoThrow(\n LibOrder.Order[] memory orders,\n uint256 makerAssetFillAmount,\n bytes[] memory signatures\n )\n public\n returns (LibFillResults.FillResults memory totalFillResults);\n\n /// @dev Synchronously cancels multiple orders in a single transaction.\n /// @param orders Array of order specifications.\n function batchCancelOrders(LibOrder.Order[] memory orders)\n public;\n\n /// @dev Fetches information for all passed in orders\n /// @param orders Array of order specifications.\n /// @return Array of OrderInfo instances that correspond to each order.\n function getOrdersInfo(LibOrder.Order[] memory orders)\n public\n view\n returns (LibOrder.OrderInfo[] memory);\n}\n", + "@0x/contracts-tokens/contracts/tokens/ERC20Token/IERC20Token.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity 0.4.24;\n\n\ncontract IERC20Token {\n\n // solhint-disable no-simple-event-func-name\n event Transfer(\n address indexed _from,\n address indexed _to,\n uint256 _value\n );\n\n event Approval(\n address indexed _owner,\n address indexed _spender,\n uint256 _value\n );\n\n /// @dev send `value` token to `to` from `msg.sender`\n /// @param _to The address of the recipient\n /// @param _value The amount of token to be transferred\n /// @return True if transfer was successful\n function transfer(address _to, uint256 _value)\n external\n returns (bool);\n\n /// @dev send `value` token to `to` from `from` on the condition it is approved by `from`\n /// @param _from The address of the sender\n /// @param _to The address of the recipient\n /// @param _value The amount of token to be transferred\n /// @return True if transfer was successful\n function transferFrom(\n address _from,\n address _to,\n uint256 _value\n )\n external\n returns (bool);\n \n /// @dev `msg.sender` approves `_spender` to spend `_value` tokens\n /// @param _spender The address of the account able to transfer the tokens\n /// @param _value The amount of wei to be approved for transfer\n /// @return Always true if the call has enough gas to complete execution\n function approve(address _spender, uint256 _value)\n external\n returns (bool);\n\n /// @dev Query total supply of token\n /// @return Total supply of token\n function totalSupply()\n external\n view\n returns (uint256);\n \n /// @param _owner The address from which the balance will be retrieved\n /// @return Balance of owner\n function balanceOf(address _owner)\n external\n view\n returns (uint256);\n\n /// @param _owner The address of the account owning tokens\n /// @param _spender The address of the account able to transfer the tokens\n /// @return Amount of remaining tokens allowed to spent\n function allowance(address _owner, address _spender)\n external\n view\n returns (uint256);\n}\n", + "@0x/contracts-utils/contracts/utils/LibBytes/LibBytes.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity 0.4.24;\n\n\nlibrary LibBytes {\n\n using LibBytes for bytes;\n\n /// @dev Gets the memory address for a byte array.\n /// @param input Byte array to lookup.\n /// @return memoryAddress Memory address of byte array. This\n /// points to the header of the byte array which contains\n /// the length.\n function rawAddress(bytes memory input)\n internal\n pure\n returns (uint256 memoryAddress)\n {\n assembly {\n memoryAddress := input\n }\n return memoryAddress;\n }\n \n /// @dev Gets the memory address for the contents of a byte array.\n /// @param input Byte array to lookup.\n /// @return memoryAddress Memory address of the contents of the byte array.\n function contentAddress(bytes memory input)\n internal\n pure\n returns (uint256 memoryAddress)\n {\n assembly {\n memoryAddress := add(input, 32)\n }\n return memoryAddress;\n }\n\n /// @dev Copies `length` bytes from memory location `source` to `dest`.\n /// @param dest memory address to copy bytes to.\n /// @param source memory address to copy bytes from.\n /// @param length number of bytes to copy.\n function memCopy(\n uint256 dest,\n uint256 source,\n uint256 length\n )\n internal\n pure\n {\n if (length < 32) {\n // Handle a partial word by reading destination and masking\n // off the bits we are interested in.\n // This correctly handles overlap, zero lengths and source == dest\n assembly {\n let mask := sub(exp(256, sub(32, length)), 1)\n let s := and(mload(source), not(mask))\n let d := and(mload(dest), mask)\n mstore(dest, or(s, d))\n }\n } else {\n // Skip the O(length) loop when source == dest.\n if (source == dest) {\n return;\n }\n\n // For large copies we copy whole words at a time. The final\n // word is aligned to the end of the range (instead of after the\n // previous) to handle partial words. So a copy will look like this:\n //\n // ####\n // ####\n // ####\n // ####\n //\n // We handle overlap in the source and destination range by\n // changing the copying direction. This prevents us from\n // overwriting parts of source that we still need to copy.\n //\n // This correctly handles source == dest\n //\n if (source > dest) {\n assembly {\n // We subtract 32 from `sEnd` and `dEnd` because it\n // is easier to compare with in the loop, and these\n // are also the addresses we need for copying the\n // last bytes.\n length := sub(length, 32)\n let sEnd := add(source, length)\n let dEnd := add(dest, length)\n\n // Remember the last 32 bytes of source\n // This needs to be done here and not after the loop\n // because we may have overwritten the last bytes in\n // source already due to overlap.\n let last := mload(sEnd)\n\n // Copy whole words front to back\n // Note: the first check is always true,\n // this could have been a do-while loop.\n // solhint-disable-next-line no-empty-blocks\n for {} lt(source, sEnd) {} {\n mstore(dest, mload(source))\n source := add(source, 32)\n dest := add(dest, 32)\n }\n \n // Write the last 32 bytes\n mstore(dEnd, last)\n }\n } else {\n assembly {\n // We subtract 32 from `sEnd` and `dEnd` because those\n // are the starting points when copying a word at the end.\n length := sub(length, 32)\n let sEnd := add(source, length)\n let dEnd := add(dest, length)\n\n // Remember the first 32 bytes of source\n // This needs to be done here and not after the loop\n // because we may have overwritten the first bytes in\n // source already due to overlap.\n let first := mload(source)\n\n // Copy whole words back to front\n // We use a signed comparisson here to allow dEnd to become\n // negative (happens when source and dest < 32). Valid\n // addresses in local memory will never be larger than\n // 2**255, so they can be safely re-interpreted as signed.\n // Note: the first check is always true,\n // this could have been a do-while loop.\n // solhint-disable-next-line no-empty-blocks\n for {} slt(dest, dEnd) {} {\n mstore(dEnd, mload(sEnd))\n sEnd := sub(sEnd, 32)\n dEnd := sub(dEnd, 32)\n }\n \n // Write the first 32 bytes\n mstore(dest, first)\n }\n }\n }\n }\n\n /// @dev Returns a slices from a byte array.\n /// @param b The byte array to take a slice from.\n /// @param from The starting index for the slice (inclusive).\n /// @param to The final index for the slice (exclusive).\n /// @return result The slice containing bytes at indices [from, to)\n function slice(\n bytes memory b,\n uint256 from,\n uint256 to\n )\n internal\n pure\n returns (bytes memory result)\n {\n require(\n from <= to,\n \"FROM_LESS_THAN_TO_REQUIRED\"\n );\n require(\n to < b.length,\n \"TO_LESS_THAN_LENGTH_REQUIRED\"\n );\n \n // Create a new bytes structure and copy contents\n result = new bytes(to - from);\n memCopy(\n result.contentAddress(),\n b.contentAddress() + from,\n result.length\n );\n return result;\n }\n \n /// @dev Returns a slice from a byte array without preserving the input.\n /// @param b The byte array to take a slice from. Will be destroyed in the process.\n /// @param from The starting index for the slice (inclusive).\n /// @param to The final index for the slice (exclusive).\n /// @return result The slice containing bytes at indices [from, to)\n /// @dev When `from == 0`, the original array will match the slice. In other cases its state will be corrupted.\n function sliceDestructive(\n bytes memory b,\n uint256 from,\n uint256 to\n )\n internal\n pure\n returns (bytes memory result)\n {\n require(\n from <= to,\n \"FROM_LESS_THAN_TO_REQUIRED\"\n );\n require(\n to < b.length,\n \"TO_LESS_THAN_LENGTH_REQUIRED\"\n );\n \n // Create a new bytes structure around [from, to) in-place.\n assembly {\n result := add(b, from)\n mstore(result, sub(to, from))\n }\n return result;\n }\n\n /// @dev Pops the last byte off of a byte array by modifying its length.\n /// @param b Byte array that will be modified.\n /// @return The byte that was popped off.\n function popLastByte(bytes memory b)\n internal\n pure\n returns (bytes1 result)\n {\n require(\n b.length > 0,\n \"GREATER_THAN_ZERO_LENGTH_REQUIRED\"\n );\n\n // Store last byte.\n result = b[b.length - 1];\n\n assembly {\n // Decrement length of byte array.\n let newLen := sub(mload(b), 1)\n mstore(b, newLen)\n }\n return result;\n }\n\n /// @dev Pops the last 20 bytes off of a byte array by modifying its length.\n /// @param b Byte array that will be modified.\n /// @return The 20 byte address that was popped off.\n function popLast20Bytes(bytes memory b)\n internal\n pure\n returns (address result)\n {\n require(\n b.length >= 20,\n \"GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED\"\n );\n\n // Store last 20 bytes.\n result = readAddress(b, b.length - 20);\n\n assembly {\n // Subtract 20 from byte array length.\n let newLen := sub(mload(b), 20)\n mstore(b, newLen)\n }\n return result;\n }\n\n /// @dev Tests equality of two byte arrays.\n /// @param lhs First byte array to compare.\n /// @param rhs Second byte array to compare.\n /// @return True if arrays are the same. False otherwise.\n function equals(\n bytes memory lhs,\n bytes memory rhs\n )\n internal\n pure\n returns (bool equal)\n {\n // Keccak gas cost is 30 + numWords * 6. This is a cheap way to compare.\n // We early exit on unequal lengths, but keccak would also correctly\n // handle this.\n return lhs.length == rhs.length && keccak256(lhs) == keccak256(rhs);\n }\n\n /// @dev Reads an address from a position in a byte array.\n /// @param b Byte array containing an address.\n /// @param index Index in byte array of address.\n /// @return address from byte array.\n function readAddress(\n bytes memory b,\n uint256 index\n )\n internal\n pure\n returns (address result)\n {\n require(\n b.length >= index + 20, // 20 is length of address\n \"GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED\"\n );\n\n // Add offset to index:\n // 1. Arrays are prefixed by 32-byte length parameter (add 32 to index)\n // 2. Account for size difference between address length and 32-byte storage word (subtract 12 from index)\n index += 20;\n\n // Read address from array memory\n assembly {\n // 1. Add index to address of bytes array\n // 2. Load 32-byte word from memory\n // 3. Apply 20-byte mask to obtain address\n result := and(mload(add(b, index)), 0xffffffffffffffffffffffffffffffffffffffff)\n }\n return result;\n }\n\n /// @dev Writes an address into a specific position in a byte array.\n /// @param b Byte array to insert address into.\n /// @param index Index in byte array of address.\n /// @param input Address to put into byte array.\n function writeAddress(\n bytes memory b,\n uint256 index,\n address input\n )\n internal\n pure\n {\n require(\n b.length >= index + 20, // 20 is length of address\n \"GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED\"\n );\n\n // Add offset to index:\n // 1. Arrays are prefixed by 32-byte length parameter (add 32 to index)\n // 2. Account for size difference between address length and 32-byte storage word (subtract 12 from index)\n index += 20;\n\n // Store address into array memory\n assembly {\n // The address occupies 20 bytes and mstore stores 32 bytes.\n // First fetch the 32-byte word where we'll be storing the address, then\n // apply a mask so we have only the bytes in the word that the address will not occupy.\n // Then combine these bytes with the address and store the 32 bytes back to memory with mstore.\n\n // 1. Add index to address of bytes array\n // 2. Load 32-byte word from memory\n // 3. Apply 12-byte mask to obtain extra bytes occupying word of memory where we'll store the address\n let neighbors := and(\n mload(add(b, index)),\n 0xffffffffffffffffffffffff0000000000000000000000000000000000000000\n )\n \n // Make sure input address is clean.\n // (Solidity does not guarantee this)\n input := and(input, 0xffffffffffffffffffffffffffffffffffffffff)\n\n // Store the neighbors and address into memory\n mstore(add(b, index), xor(input, neighbors))\n }\n }\n\n /// @dev Reads a bytes32 value from a position in a byte array.\n /// @param b Byte array containing a bytes32 value.\n /// @param index Index in byte array of bytes32 value.\n /// @return bytes32 value from byte array.\n function readBytes32(\n bytes memory b,\n uint256 index\n )\n internal\n pure\n returns (bytes32 result)\n {\n require(\n b.length >= index + 32,\n \"GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED\"\n );\n\n // Arrays are prefixed by a 256 bit length parameter\n index += 32;\n\n // Read the bytes32 from array memory\n assembly {\n result := mload(add(b, index))\n }\n return result;\n }\n\n /// @dev Writes a bytes32 into a specific position in a byte array.\n /// @param b Byte array to insert <input> into.\n /// @param index Index in byte array of <input>.\n /// @param input bytes32 to put into byte array.\n function writeBytes32(\n bytes memory b,\n uint256 index,\n bytes32 input\n )\n internal\n pure\n {\n require(\n b.length >= index + 32,\n \"GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED\"\n );\n\n // Arrays are prefixed by a 256 bit length parameter\n index += 32;\n\n // Read the bytes32 from array memory\n assembly {\n mstore(add(b, index), input)\n }\n }\n\n /// @dev Reads a uint256 value from a position in a byte array.\n /// @param b Byte array containing a uint256 value.\n /// @param index Index in byte array of uint256 value.\n /// @return uint256 value from byte array.\n function readUint256(\n bytes memory b,\n uint256 index\n )\n internal\n pure\n returns (uint256 result)\n {\n result = uint256(readBytes32(b, index));\n return result;\n }\n\n /// @dev Writes a uint256 into a specific position in a byte array.\n /// @param b Byte array to insert <input> into.\n /// @param index Index in byte array of <input>.\n /// @param input uint256 to put into byte array.\n function writeUint256(\n bytes memory b,\n uint256 index,\n uint256 input\n )\n internal\n pure\n {\n writeBytes32(b, index, bytes32(input));\n }\n\n /// @dev Reads an unpadded bytes4 value from a position in a byte array.\n /// @param b Byte array containing a bytes4 value.\n /// @param index Index in byte array of bytes4 value.\n /// @return bytes4 value from byte array.\n function readBytes4(\n bytes memory b,\n uint256 index\n )\n internal\n pure\n returns (bytes4 result)\n {\n require(\n b.length >= index + 4,\n \"GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED\"\n );\n\n // Arrays are prefixed by a 32 byte length field\n index += 32;\n\n // Read the bytes4 from array memory\n assembly {\n result := mload(add(b, index))\n // Solidity does not require us to clean the trailing bytes.\n // We do it anyway\n result := and(result, 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000)\n }\n return result;\n }\n\n /// @dev Reads nested bytes from a specific position.\n /// @dev NOTE: the returned value overlaps with the input value.\n /// Both should be treated as immutable.\n /// @param b Byte array containing nested bytes.\n /// @param index Index of nested bytes.\n /// @return result Nested bytes.\n function readBytesWithLength(\n bytes memory b,\n uint256 index\n )\n internal\n pure\n returns (bytes memory result)\n {\n // Read length of nested bytes\n uint256 nestedBytesLength = readUint256(b, index);\n index += 32;\n\n // Assert length of <b> is valid, given\n // length of nested bytes\n require(\n b.length >= index + nestedBytesLength,\n \"GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED\"\n );\n \n // Return a pointer to the byte array as it exists inside `b`\n assembly {\n result := add(b, index)\n }\n return result;\n }\n\n /// @dev Inserts bytes at a specific position in a byte array.\n /// @param b Byte array to insert <input> into.\n /// @param index Index in byte array of <input>.\n /// @param input bytes to insert.\n function writeBytesWithLength(\n bytes memory b,\n uint256 index,\n bytes memory input\n )\n internal\n pure\n {\n // Assert length of <b> is valid, given\n // length of input\n require(\n b.length >= index + 32 + input.length, // 32 bytes to store length\n \"GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED\"\n );\n\n // Copy <input> into <b>\n memCopy(\n b.contentAddress() + index,\n input.rawAddress(), // includes length of <input>\n input.length + 32 // +32 bytes to store <input> length\n );\n }\n\n /// @dev Performs a deep copy of a byte array onto another byte array of greater than or equal length.\n /// @param dest Byte array that will be overwritten with source bytes.\n /// @param source Byte array to copy onto dest bytes.\n function deepCopyBytes(\n bytes memory dest,\n bytes memory source\n )\n internal\n pure\n {\n uint256 sourceLen = source.length;\n // Dest length must be >= source length, or some bytes would not be copied.\n require(\n dest.length >= sourceLen,\n \"GREATER_OR_EQUAL_TO_SOURCE_BYTES_LENGTH_REQUIRED\"\n );\n memCopy(\n dest.contentAddress(),\n source.contentAddress(),\n sourceLen\n );\n }\n}\n" + }, + "sourceTreeHashHex": "0x4be45134ccdebcf000c4e09f6aed69041411babf993cfba6871e9ad73369122f", + "compiler": { + "name": "solc", + "version": "soljson-v0.4.24+commit.e67f0147.js", + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode.object", + "evm.bytecode.sourceMap", + "evm.deployedBytecode.object", + "evm.deployedBytecode.sourceMap" + ] + } + } + } + }, + "networks": {} +}
\ No newline at end of file diff --git a/packages/contract-artifacts/src/index.ts b/packages/contract-artifacts/src/index.ts index f30276dd9..bd5f8fee3 100644 --- a/packages/contract-artifacts/src/index.ts +++ b/packages/contract-artifacts/src/index.ts @@ -1,4 +1,5 @@ import * as AssetProxyOwner from '../artifacts/AssetProxyOwner.json'; +import * as DutchAuction from '../artifacts/DutchAuction.json'; import * as DummyERC20Token from '../artifacts/DummyERC20Token.json'; import * as DummyERC721Token from '../artifacts/DummyERC721Token.json'; import * as ERC20Proxy from '../artifacts/ERC20Proxy.json'; @@ -15,6 +16,7 @@ import * as ZRXToken from '../artifacts/ZRXToken.json'; export { AssetProxyOwner, + DutchAuction, DummyERC20Token, DummyERC721Token, ERC20Proxy, diff --git a/packages/contract-artifacts/tsconfig.json b/packages/contract-artifacts/tsconfig.json index cce086209..59169fceb 100644 --- a/packages/contract-artifacts/tsconfig.json +++ b/packages/contract-artifacts/tsconfig.json @@ -8,6 +8,7 @@ "include": ["./src/**/*"], "files": [ "./artifacts/AssetProxyOwner.json", + "./artifacts/DutchAuction.json", "./artifacts/DummyERC20Token.json", "./artifacts/DummyERC721Token.json", "./artifacts/ERC20Proxy.json", diff --git a/packages/contract-wrappers/src/contract_wrappers.ts b/packages/contract-wrappers/src/contract_wrappers.ts index 0c535bd5c..396505866 100644 --- a/packages/contract-wrappers/src/contract_wrappers.ts +++ b/packages/contract-wrappers/src/contract_wrappers.ts @@ -20,6 +20,7 @@ import { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper'; import { ExchangeWrapper } from './contract_wrappers/exchange_wrapper'; import { ForwarderWrapper } from './contract_wrappers/forwarder_wrapper'; import { OrderValidatorWrapper } from './contract_wrappers/order_validator_wrapper'; +import { DutchAuctionWrapper } from './contract_wrappers/dutch_auction_wrapper'; import { ContractWrappersConfigSchema } from './schemas/contract_wrappers_config_schema'; import { ContractWrappersConfig } from './types'; import { assert } from './utils/assert'; @@ -65,6 +66,10 @@ export class ContractWrappers { * An instance of the OrderValidatorWrapper class containing methods for interacting with any OrderValidator smart contract. */ public orderValidator: OrderValidatorWrapper; + /** + * An instance of the DutchAuctionWrapper class containing methods for interacting with any DutchAuction smart contract. + */ + public dutchAuction: DutchAuctionWrapper; private readonly _web3Wrapper: Web3Wrapper; /** @@ -141,6 +146,11 @@ export class ContractWrappers { config.networkId, contractAddresses.orderValidator, ); + this.dutchAuction = new DutchAuctionWrapper( + this._web3Wrapper, + config.networkId, + contractAddresses.orderValidator, + ); } /** * Unsubscribes from all subscriptions for all contracts. diff --git a/packages/contract-wrappers/src/contract_wrappers/dutch_auction_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/dutch_auction_wrapper.ts new file mode 100644 index 000000000..500e7a63d --- /dev/null +++ b/packages/contract-wrappers/src/contract_wrappers/dutch_auction_wrapper.ts @@ -0,0 +1,151 @@ +import { artifacts as protocolArtifacts } from '@0x/contracts-protocol'; +import { DutchAuctionContract } from '@0x/abi-gen-wrappers'; +import { DutchAuction } from '@0x/contract-artifacts'; +import { LogDecoder } from '@0x/contracts-test-utils'; +import { artifacts as tokensArtifacts } from '@0x/contracts-tokens'; +import { _getDefaultContractAddresses } from '../utils/contract_addresses'; +import { DutchAuctionDetails, SignedOrder } from '@0x/types'; +import { ContractAbi } from 'ethereum-types'; +import { Web3Wrapper } from '@0x/web3-wrapper'; +import { BigNumber } from '@0x/utils'; +import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types'; +import * as _ from 'lodash'; +import ethAbi = require('ethereumjs-abi'); +import { schemas } from '@0x/json-schemas'; +import { assert } from '../utils/assert'; +import ethUtil = require('ethereumjs-util'); + +import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema'; +import { txOptsSchema } from '../schemas/tx_opts_schema'; +import { OrderTransactionOpts } from '../types'; +import { ContractWrapper } from './contract_wrapper'; +import { ExchangeWrapperError } from '../types'; + +export class DutchAuctionWrapper extends ContractWrapper { + public abi: ContractAbi = DutchAuction.compilerOutput.abi; + public address: string; + private _dutchAuctionContractIfExists?: DutchAuctionContract; + /** + * Instantiate DutchAuctionWrapper + * @param web3Wrapper Web3Wrapper instance to use. + * @param networkId Desired networkId. + * @param address The address of the Dutch Auction contract. If undefined, will + * default to the known address corresponding to the networkId. + */ + constructor( + web3Wrapper: Web3Wrapper, + networkId: number, + address: string, + ) { + super(web3Wrapper, networkId); + this.address = address; + } + /** + * Matches the buy and sell orders at an amount given the following: the current block time, the auction + * start time and the auction begin amount. The sell order is a an order at the lowest amount + * at the end of the auction. Excess from the match is transferred to the seller. + * Over time the price moves from beginAmount to endAmount given the current block.timestamp. + * @param buyOrder The Buyer's order. This order is for the current expected price of the auction. + * @param sellOrder The Seller's order. This order is for the lowest amount (at the end of the auction). + * @param from Address the transaction is being sent from. + * @return Transaction receipt with decoded logs. + */ + public async matchOrdersAsync( + buyOrder: SignedOrder, + sellOrder: SignedOrder, + takerAddress: string, + orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, + ): Promise<string> { + // type assertions + assert.doesConformToSchema('buyOrder', buyOrder, schemas.signedOrderSchema); + assert.doesConformToSchema('sellOrder', sellOrder, schemas.signedOrderSchema); + await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); + assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); + const normalizedTakerAddress = takerAddress.toLowerCase(); + // other assertions + if ( + sellOrder.makerAssetData !== buyOrder.takerAssetData || + sellOrder.takerAssetData !== buyOrder.makerAssetData + ) { + throw new Error(ExchangeWrapperError.AssetDataMismatch); + } + // get contract + const dutchAuctionInstance = await this._getDutchAuctionContractAsync(); + // validate transaction + if (orderTransactionOpts.shouldValidate) { + await dutchAuctionInstance.matchOrders.callAsync( + buyOrder, + sellOrder, + buyOrder.signature, + sellOrder.signature, + { + from: normalizedTakerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + nonce: orderTransactionOpts.nonce, + }, + ); + } + // send transaction + const txHash = await dutchAuctionInstance.matchOrders.sendTransactionAsync( + buyOrder, + sellOrder, + buyOrder.signature, + sellOrder.signature, + { + from: normalizedTakerAddress, + gas: orderTransactionOpts.gasLimit, + gasPrice: orderTransactionOpts.gasPrice, + nonce: orderTransactionOpts.nonce, + }, + ); + return txHash; + } + /** + * Calculates the Auction Details for the given order + * @param sellOrder The Seller's order. This order is for the lowest amount (at the end of the auction). + * @return The dutch auction details. + */ + public async getAuctionDetailsAsync(sellOrder: SignedOrder): Promise<DutchAuctionDetails> { + // type assertions + assert.doesConformToSchema('sellOrder', sellOrder, schemas.signedOrderSchema); + // get contract + const dutchAuctionInstance = await this._getDutchAuctionContractAsync(); + // call contract + const afterAuctionDetails = await dutchAuctionInstance.getAuctionDetails.callAsync(sellOrder); + return afterAuctionDetails; + } + private async _getDutchAuctionContractAsync(): Promise<DutchAuctionContract> { + if (!_.isUndefined(this._dutchAuctionContractIfExists)) { + return this._dutchAuctionContractIfExists; + } + const contractInstance = new DutchAuctionContract( + this.abi, + this.address, + this._web3Wrapper.getProvider(), + this._web3Wrapper.getContractDefaults(), + ); + this._dutchAuctionContractIfExists = contractInstance; + return this._dutchAuctionContractIfExists; + } + /** + * Dutch auction details are encoded with the asset data for a 0x order. This function produces a hex + * encoded assetData string, containing information both about the asset being traded and the + * dutch auction; which is usable in the makerAssetData or takerAssetData fields in a 0x order. + * @param assetData Hex encoded assetData string for the asset being auctioned. + * @param beginTimeSeconds Begin time of the dutch auction. + * @param beginAmount Starting amount being sold in the dutch auction. + * @return The hex encoded assetData string. + */ + public static encodeDutchAuctionAssetData(assetData: string, beginTimeSeconds: BigNumber, beginAmount: BigNumber): string { + const assetDataBuffer = ethUtil.toBuffer(assetData); + const abiEncodedAuctionData = (ethAbi as any).rawEncode( + ['uint256', 'uint256'], + [beginTimeSeconds.toString(), beginAmount.toString()], + ); + const abiEncodedAuctionDataBuffer = ethUtil.toBuffer(abiEncodedAuctionData); + const dutchAuctionDataBuffer = Buffer.concat([assetDataBuffer, abiEncodedAuctionDataBuffer]); + const dutchAuctionData = ethUtil.bufferToHex(dutchAuctionDataBuffer); + return dutchAuctionData; + }; +} diff --git a/packages/contract-wrappers/src/index.ts b/packages/contract-wrappers/src/index.ts index d66ff5c9c..5c64dbbc6 100644 --- a/packages/contract-wrappers/src/index.ts +++ b/packages/contract-wrappers/src/index.ts @@ -34,6 +34,7 @@ export { ERC20ProxyWrapper } from './contract_wrappers/erc20_proxy_wrapper'; export { ERC721ProxyWrapper } from './contract_wrappers/erc721_proxy_wrapper'; export { ForwarderWrapper } from './contract_wrappers/forwarder_wrapper'; export { OrderValidatorWrapper } from './contract_wrappers/order_validator_wrapper'; +export { DutchAuctionWrapper } from './contract_wrappers/dutch_auction_wrapper'; export { TransactionEncoder } from './utils/transaction_encoder'; diff --git a/packages/contract-wrappers/test/dutch_auction_wrapper_test.ts b/packages/contract-wrappers/test/dutch_auction_wrapper_test.ts new file mode 100644 index 000000000..ad8b3bd31 --- /dev/null +++ b/packages/contract-wrappers/test/dutch_auction_wrapper_test.ts @@ -0,0 +1,156 @@ +import { BlockchainLifecycle } from '@0x/dev-utils'; +import { FillScenarios } from '@0x/fill-scenarios'; +import { assetDataUtils } from '@0x/order-utils'; +import { SignedOrder } from '@0x/types'; +import { BigNumber } from '@0x/utils'; +import * as chai from 'chai'; +import 'mocha'; + +import { ContractWrappers, OrderStatus } from '../src'; + +import { chaiSetup } from './utils/chai_setup'; +import { constants } from './utils/constants'; +import { migrateOnceAsync } from './utils/migrate'; +import { tokenUtils } from './utils/token_utils'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; +import { getLatestBlockTimestampAsync } from '@0x/contracts-test-utils'; +import { DutchAuction } from '@0x/contract-artifacts'; +import { DutchAuctionWrapper } from '../src/contract_wrappers/dutch_auction_wrapper'; + +chaiSetup.configure(); +const expect = chai.expect; +const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); + +// tslint:disable:custom-no-magic-numbers +describe.only('DutchAuctionWrapper', () => { + const fillableAmount = new BigNumber(5); + const tenMinutesInSeconds = 10 * 60; + let contractWrappers: ContractWrappers; + let fillScenarios: FillScenarios; + let exchangeContractAddress: string; + let zrxTokenAddress: string; + let userAddresses: string[]; + let makerAddress: string; + let takerAddress: string; + let makerTokenAddress: string; + let takerTokenAddress: string; + let makerAssetData: string; + let takerAssetData: string; + let buyOrder: SignedOrder; + let sellOrder: SignedOrder; + let makerTokenAssetData: string; + let takerTokenAssetData: string; + before(async () => { + console.log(`BEOGIN DEPLOYINH`); + const contractAddresses = await migrateOnceAsync(); + await blockchainLifecycle.startAsync(); + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + blockPollingIntervalMs: 10, + }; + + contractWrappers = new ContractWrappers(provider, config); + console.log(`DEPLOYINH`); + exchangeContractAddress = contractWrappers.exchange.address; + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); + zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress; + fillScenarios = new FillScenarios( + provider, + userAddresses, + zrxTokenAddress, + exchangeContractAddress, + contractWrappers.erc20Proxy.address, + contractWrappers.erc721Proxy.address, + ); + [, makerAddress, takerAddress] = userAddresses; + [makerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); + takerTokenAddress = contractWrappers.forwarder.etherTokenAddress; + // construct asset data for tokens being swapped + [makerTokenAssetData, takerTokenAssetData] = [ + assetDataUtils.encodeERC20AssetData(makerTokenAddress), + assetDataUtils.encodeERC20AssetData(takerTokenAddress), + ]; + // encode auction details in maker asset data + const auctionBeginAmount = fillableAmount; + const currentBlockTimestamp = await getLatestBlockTimestampAsync(); + const auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds); + makerAssetData = DutchAuctionWrapper.encodeDutchAuctionAssetData( + makerTokenAssetData, + auctionBeginTimeSeconds, + auctionBeginAmount + ); + takerAssetData = takerTokenAssetData; + // create sell / buy orders for auction + // note that the maker/taker asset datas are swapped in the `buyOrder` + sellOrder = await fillScenarios.createFillableSignedOrderAsync( + makerAssetData, + takerAssetData, + makerAddress, + constants.NULL_ADDRESS, + fillableAmount, + ); + buyOrder = await fillScenarios.createFillableSignedOrderAsync( + takerAssetData, + makerAssetData, + makerAddress, + constants.NULL_ADDRESS, + fillableAmount, + ); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); + beforeEach(async () => { + await blockchainLifecycle.startAsync(); + }); + afterEach(async () => { + await blockchainLifecycle.revertAsync(); + }); + describe('#matchOrdersAsync', () => { + it('should match two orders', async () => { + const txHash = await contractWrappers.dutchAuction.matchOrdersAsync(buyOrder, sellOrder, takerAddress); + await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); + }); + it('should throw when invalid transaction and shouldValidate is true', async () => { + // request match with bad buy/sell orders + const badSellOrder = buyOrder; + const badBuyOrder = sellOrder; + return expect( + await contractWrappers.dutchAuction.matchOrdersAsync( + badBuyOrder, + badSellOrder, + takerAddress, + { + shouldValidate: true, + }, + ), + ).to.be.rejectedWith('COMPLETE_FILL_FAILED'); + }); + }); + + describe('#getAuctionDetailsAsync', () => { + it('should be worth the begin price at the begining of the auction', async () => { + // setup auction details + const auctionBeginAmount = fillableAmount; + const currentBlockTimestamp = await getLatestBlockTimestampAsync(); + const auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp + tenMinutesInSeconds); + const makerAssetData = DutchAuctionWrapper.encodeDutchAuctionAssetData( + makerTokenAssetData, + auctionBeginTimeSeconds, + auctionBeginAmount + ); + const order = await fillScenarios.createFillableSignedOrderAsync( + makerAssetData, + takerAssetData, + makerAddress, + constants.NULL_ADDRESS, + fillableAmount, + ); + const auctionDetails = await contractWrappers.dutchAuction.getAuctionDetailsAsync(order); + expect(auctionDetails.currentTimeSeconds).to.be.bignumber.lte(auctionBeginTimeSeconds); + expect(auctionDetails.currentAmount).to.be.bignumber.equal(auctionBeginAmount); + expect(auctionDetails.beginAmount).to.be.bignumber.equal(auctionBeginAmount); + }); + }); +}); diff --git a/packages/migrations/src/migration.ts b/packages/migrations/src/migration.ts index c684c4970..99d1719f1 100644 --- a/packages/migrations/src/migration.ts +++ b/packages/migrations/src/migration.ts @@ -141,6 +141,14 @@ export async function runMigrationsAsync(provider: Provider, txDefaults: Partial zrxAssetData, ); + // DutchAuction + const dutchAuction = await wrappers.DutchAuctionContract.deployFrom0xArtifactAsync( + artifacts.DutchAuction, + provider, + txDefaults, + exchange.address, + ); + // Fund the Forwarder with ZRX const zrxDecimals = await zrxToken.decimals.callAsync(); const zrxForwarderAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(5000), zrxDecimals); @@ -157,6 +165,7 @@ export async function runMigrationsAsync(provider: Provider, txDefaults: Partial assetProxyOwner: assetProxyOwner.address, forwarder: forwarder.address, orderValidator: orderValidator.address, + dutchAuction: dutchAuction.address, }; } diff --git a/packages/order-utils/src/asset_data_utils.ts b/packages/order-utils/src/asset_data_utils.ts index 0fc166969..f314891e2 100644 --- a/packages/order-utils/src/asset_data_utils.ts +++ b/packages/order-utils/src/asset_data_utils.ts @@ -305,24 +305,4 @@ export const assetDataUtils = { throw new Error(`Unrecognized asset proxy id: ${assetProxyId}`); } }, - /** - * Dutch auction details are encoded with the asset data for a 0x order. This function produces a hex - * encoded assetData string, containing information both about the asset being traded and the - * dutch auction; which is usable in the makerAssetData or takerAssetData fields in a 0x order. - * @param assetData Hex encoded assetData string for the asset being auctioned. - * @param beginTimeSeconds Begin time of the dutch auction. - * @param beginAmount Starting amount being sold in the dutch auction. - * @return The hex encoded assetData string. - */ - encodeDutchAuctionAssetData(assetData: string, beginTimeSeconds: BigNumber, beginAmount: BigNumber): string { - const assetDataBuffer = ethUtil.toBuffer(assetData); - const abiEncodedAuctionData = (ethAbi as any).rawEncode( - ['uint256', 'uint256'], - [beginTimeSeconds.toString(), beginAmount.toString()], - ); - const abiEncodedAuctionDataBuffer = ethUtil.toBuffer(abiEncodedAuctionData); - const dutchAuctionDataBuffer = Buffer.concat([assetDataBuffer, abiEncodedAuctionDataBuffer]); - const dutchAuctionData = ethUtil.bufferToHex(dutchAuctionDataBuffer); - return dutchAuctionData; - }, }; |