diff options
Diffstat (limited to 'packages')
157 files changed, 2645 insertions, 874 deletions
diff --git a/packages/0x.js/package.json b/packages/0x.js/package.json index c3adb496e..db6e2363e 100644 --- a/packages/0x.js/package.json +++ b/packages/0x.js/package.json @@ -15,7 +15,6 @@ "main": "lib/index.js", "types": "lib/index.d.ts", "scripts": { - "watch_without_deps": "tsc -w", "build": "yarn build:all", "build:all": "run-p build:umd:prod build:commonjs", "lint": "tslint --project . --exclude **/src/generated_contract_wrappers/**/*", @@ -25,8 +24,8 @@ "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "clean": "shx rm -rf _bundles lib test_temp src/generated_contract_wrappers generated_docs", "build:umd:prod": "NODE_ENV=production webpack", - "build:commonjs": "tsc", - "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES" + "build:commonjs": "tsc -b", + "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" }, "config": { "postpublish": { diff --git a/packages/0x.js/src/index.ts b/packages/0x.js/src/index.ts index 7058a898f..17511f468 100644 --- a/packages/0x.js/src/index.ts +++ b/packages/0x.js/src/index.ts @@ -9,6 +9,7 @@ export { ERC20ProxyWrapper, ERC721ProxyWrapper, ForwarderWrapper, + OrderValidatorWrapper, IndexedFilterValues, BlockRange, ContractWrappersConfig, @@ -42,6 +43,9 @@ export { DecodedLogEvent, ExchangeEventArgs, TransactionEncoder, + BalanceAndAllowance, + OrderAndTraderInfo, + TraderInfo, } from '@0xproject/contract-wrappers'; export { OrderWatcher, OnOrderStateChangeCallback, OrderWatcherConfig } from '@0xproject/order-watcher'; diff --git a/packages/0x.js/tsconfig.json b/packages/0x.js/tsconfig.json index e35816553..a96536716 100644 --- a/packages/0x.js/tsconfig.json +++ b/packages/0x.js/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "src" }, - "include": ["./src/**/*", "./test/**/*"] + "include": ["./src/**/*"] } diff --git a/packages/0x.js/typedoc-tsconfig.json b/packages/0x.js/typedoc-tsconfig.json new file mode 100644 index 000000000..c9b0af1ae --- /dev/null +++ b/packages/0x.js/typedoc-tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../typedoc-tsconfig", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["./src/**/*", "./test/**/*"] +} diff --git a/packages/0x.js/webpack.config.js b/packages/0x.js/webpack.config.js index 982e076ee..1ad0a79ec 100644 --- a/packages/0x.js/webpack.config.js +++ b/packages/0x.js/webpack.config.js @@ -47,8 +47,13 @@ module.exports = { use: [ { loader: 'awesome-typescript-loader', + // tsconfig.json contains some options required for + // project references which do not work with webback. + // We override those options here. query: { declaration: false, + declarationMap: false, + composite: false, }, }, ], diff --git a/packages/abi-gen/package.json b/packages/abi-gen/package.json index 000e8cee0..5b4a2b7fc 100644 --- a/packages/abi-gen/package.json +++ b/packages/abi-gen/package.json @@ -8,10 +8,9 @@ "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { - "watch_without_deps": "tsc -w", "lint": "tslint --project .", "clean": "shx rm -rf lib", - "build": "tsc", + "build": "tsc -b", "test": "yarn run_mocha", "run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --bail --exit", "test:circleci": "yarn test:coverage", diff --git a/packages/abi-gen/tsconfig.json b/packages/abi-gen/tsconfig.json index e35816553..2ee711adc 100644 --- a/packages/abi-gen/tsconfig.json +++ b/packages/abi-gen/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "." }, "include": ["./src/**/*", "./test/**/*"] } diff --git a/packages/assert/package.json b/packages/assert/package.json index 2dea4b616..29ddb6002 100644 --- a/packages/assert/package.json +++ b/packages/assert/package.json @@ -8,8 +8,7 @@ "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { - "watch_without_deps": "tsc -w", - "build": "tsc", + "build": "tsc -b", "clean": "shx rm -rf lib test_temp", "lint": "tslint --project .", "run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --exit", diff --git a/packages/assert/tsconfig.json b/packages/assert/tsconfig.json index e35816553..2ee711adc 100644 --- a/packages/assert/tsconfig.json +++ b/packages/assert/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "." }, "include": ["./src/**/*", "./test/**/*"] } diff --git a/packages/base-contract/package.json b/packages/base-contract/package.json index 33a66c97a..08f8766b5 100644 --- a/packages/base-contract/package.json +++ b/packages/base-contract/package.json @@ -8,8 +8,7 @@ "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { - "watch_without_deps": "tsc -w", - "build": "tsc", + "build": "tsc -b", "clean": "shx rm -rf lib", "test": "yarn run_mocha", "rebuild_and_test": "run-s clean build test", diff --git a/packages/base-contract/tsconfig.json b/packages/base-contract/tsconfig.json index 8b4cd47a2..718e623c7 100644 --- a/packages/base-contract/tsconfig.json +++ b/packages/base-contract/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "." }, "include": ["src/**/*", "test/**/*"] } diff --git a/packages/connect/package.json b/packages/connect/package.json index 15f537c7d..543852350 100644 --- a/packages/connect/package.json +++ b/packages/connect/package.json @@ -15,8 +15,7 @@ "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { - "watch_without_deps": "tsc -w", - "build": "tsc", + "build": "tsc -b", "clean": "shx rm -rf lib test_temp generated_docs", "copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures", "lint": "tslint --project .", @@ -26,7 +25,7 @@ "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "test:circleci": "yarn test:coverage", - "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES" + "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" }, "config": { "postpublish": { diff --git a/packages/connect/tsconfig.json b/packages/connect/tsconfig.json index e35816553..2ee711adc 100644 --- a/packages/connect/tsconfig.json +++ b/packages/connect/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "." }, "include": ["./src/**/*", "./test/**/*"] } diff --git a/packages/connect/typedoc-tsconfig.json b/packages/connect/typedoc-tsconfig.json new file mode 100644 index 000000000..c9b0af1ae --- /dev/null +++ b/packages/connect/typedoc-tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../typedoc-tsconfig", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["./src/**/*", "./test/**/*"] +} diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json index b3c9b0fb3..b7c89a325 100644 --- a/packages/contract-wrappers/CHANGELOG.json +++ b/packages/contract-wrappers/CHANGELOG.json @@ -1,5 +1,13 @@ [ { + "version": "1.0.1-rc.6", + "changes": [ + { + "note": "Add `OrderValidatorWrapper`" + } + ] + }, + { "version": "1.0.1-rc.5", "changes": [ { diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json index 7d9417d65..7da839a00 100644 --- a/packages/contract-wrappers/package.json +++ b/packages/contract-wrappers/package.json @@ -11,10 +11,9 @@ "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { - "watch_without_deps": "yarn pre_build && tsc -w", - "build": "yarn pre_build && tsc", + "build": "yarn pre_build && tsc -b", "pre_build": "run-s update_artifacts_v2_beta update_artifacts_v2 generate_contract_wrappers copy_artifacts", - "generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token|ZRXToken|ERC20Token|ERC721Token|WETH9|ERC20Proxy|ERC721Proxy|Forwarder).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers", + "generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token|ZRXToken|ERC20Token|ERC721Token|WETH9|ERC20Proxy|ERC721Proxy|Forwarder|OrderValidator).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers", "lint": "tslint --project . --exclude **/src/contract_wrappers/**/* --exclude **/lib/**/*", "test:circleci": "run-s test:coverage", "test": "yarn run_mocha", @@ -26,7 +25,7 @@ "copy_artifacts": "copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts", "clean": "shx rm -rf _bundles lib test_temp test/artifacts src/contract_wrappers/generated src/artifacts generated_docs", "run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit", - "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES" + "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" }, "config": { "contracts_v2_beta": "AssetProxyOwner Exchange ERC20Proxy ERC20Token ERC721Proxy ERC721Token WETH9 ZRXToken Forwarder OrderValidator", diff --git a/packages/contract-wrappers/src/artifacts.ts b/packages/contract-wrappers/src/artifacts.ts index 7e67544d2..925f34162 100644 --- a/packages/contract-wrappers/src/artifacts.ts +++ b/packages/contract-wrappers/src/artifacts.ts @@ -8,6 +8,7 @@ import * as ERC721Proxy from './artifacts/ERC721Proxy.json'; import * as ERC721Token from './artifacts/ERC721Token.json'; import * as Exchange from './artifacts/Exchange.json'; import * as Forwarder from './artifacts/Forwarder.json'; +import * as OrderValidator from './artifacts/OrderValidator.json'; import * as EtherToken from './artifacts/WETH9.json'; import * as ZRXToken from './artifacts/ZRXToken.json'; @@ -22,4 +23,5 @@ export const artifacts = { ERC20Proxy: (ERC20Proxy as any) as ContractArtifact, ERC721Proxy: (ERC721Proxy as any) as ContractArtifact, Forwarder: (Forwarder as any) as ContractArtifact, + OrderValidator: (OrderValidator as any) as ContractArtifact, }; diff --git a/packages/contract-wrappers/src/contract_wrappers.ts b/packages/contract-wrappers/src/contract_wrappers.ts index 4277a0746..8ca0fc93c 100644 --- a/packages/contract-wrappers/src/contract_wrappers.ts +++ b/packages/contract-wrappers/src/contract_wrappers.ts @@ -12,6 +12,7 @@ import { ERC721TokenWrapper } from './contract_wrappers/erc721_token_wrapper'; 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 { ContractWrappersConfigSchema } from './schemas/contract_wrappers_config_schema'; import { contractWrappersPrivateNetworkConfigSchema } from './schemas/contract_wrappers_private_network_config_schema'; import { contractWrappersPublicNetworkConfigSchema } from './schemas/contract_wrappers_public_network_config_schema'; @@ -52,6 +53,10 @@ export class ContractWrappers { * An instance of the ForwarderWrapper class containing methods for interacting with any Forwarder smart contract. */ public forwarder: ForwarderWrapper; + /** + * An instance of the OrderValidatorWrapper class containing methods for interacting with any OrderValidator smart contract. + */ + public orderValidator: OrderValidatorWrapper; private _web3Wrapper: Web3Wrapper; /** @@ -116,6 +121,7 @@ export class ContractWrappers { config.forwarderContractAddress, config.zrxContractAddress, ); + this.orderValidator = new OrderValidatorWrapper(this._web3Wrapper, config.networkId); } /** * Sets a new web3 provider for 0x.js. Updating the provider will stop all diff --git a/packages/contract-wrappers/src/contract_wrappers/order_validator_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/order_validator_wrapper.ts new file mode 100644 index 000000000..1da88f624 --- /dev/null +++ b/packages/contract-wrappers/src/contract_wrappers/order_validator_wrapper.ts @@ -0,0 +1,187 @@ +import { schemas } from '@0xproject/json-schemas'; +import { SignedOrder } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import { ContractAbi } from 'ethereum-types'; +import * as _ from 'lodash'; + +import { artifacts } from '../artifacts'; +import { BalanceAndAllowance, OrderAndTraderInfo, TraderInfo } from '../types'; +import { assert } from '../utils/assert'; + +import { ContractWrapper } from './contract_wrapper'; +import { OrderValidatorContract } from './generated/order_validator'; + +/** + * This class includes the functionality related to interacting with the OrderValidator contract. + */ +export class OrderValidatorWrapper extends ContractWrapper { + public abi: ContractAbi = artifacts.OrderValidator.compilerOutput.abi; + private _orderValidatorContractIfExists?: OrderValidatorContract; + /** + * Instantiate OrderValidatorWrapper + * @param web3Wrapper Web3Wrapper instance to use + * @param networkId Desired networkId + */ + constructor(web3Wrapper: Web3Wrapper, networkId: number) { + super(web3Wrapper, networkId); + } + /** + * Get an object conforming to OrderAndTraderInfo containing on-chain information of the provided order and address + * @param order An object conforming to SignedOrder + * @param takerAddress An ethereum address + * @return OrderAndTraderInfo + */ + public async getOrderAndTraderInfoAsync(order: SignedOrder, takerAddress: string): Promise<OrderAndTraderInfo> { + assert.doesConformToSchema('order', order, schemas.signedOrderSchema); + assert.isETHAddressHex('takerAddress', takerAddress); + const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); + const orderAndTraderInfo = await OrderValidatorContractInstance.getOrderAndTraderInfo.callAsync( + order, + takerAddress, + ); + const result = { + orderInfo: orderAndTraderInfo[0], + traderInfo: orderAndTraderInfo[1], + }; + return result; + } + /** + * Get an array of objects conforming to OrderAndTraderInfo containing on-chain information of the provided orders and addresses + * @param orders An array of objects conforming to SignedOrder + * @param takerAddresses An array of ethereum addresses + * @return array of OrderAndTraderInfo + */ + public async getOrdersAndTradersInfoAsync( + orders: SignedOrder[], + takerAddresses: string[], + ): Promise<OrderAndTraderInfo[]> { + assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema); + _.forEach(takerAddresses, (takerAddress, index) => + assert.isETHAddressHex(`takerAddresses[${index}]`, takerAddress), + ); + assert.assert(orders.length === takerAddresses.length, 'Expected orders.length to equal takerAddresses.length'); + const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); + const ordersAndTradersInfo = await OrderValidatorContractInstance.getOrdersAndTradersInfo.callAsync( + orders, + takerAddresses, + ); + const orderInfos = ordersAndTradersInfo[0]; + const traderInfos = ordersAndTradersInfo[1]; + const result = _.map(orderInfos, (orderInfo, index) => { + const traderInfo = traderInfos[index]; + return { + orderInfo, + traderInfo, + }; + }); + return result; + } + /** + * Get an object conforming to TraderInfo containing on-chain balance and allowances for maker and taker of order + * @param order An object conforming to SignedOrder + * @param takerAddress An ethereum address + * @return TraderInfo + */ + public async getTraderInfoAsync(order: SignedOrder, takerAddress: string): Promise<TraderInfo> { + assert.doesConformToSchema('order', order, schemas.signedOrderSchema); + assert.isETHAddressHex('takerAddress', takerAddress); + const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); + const result = await OrderValidatorContractInstance.getTraderInfo.callAsync(order, takerAddress); + return result; + } + /** + * Get an array of objects conforming to TraderInfo containing on-chain balance and allowances for maker and taker of order + * @param orders An array of objects conforming to SignedOrder + * @param takerAddresses An array of ethereum addresses + * @return array of TraderInfo + */ + public async getTradersInfoAsync(orders: SignedOrder[], takerAddresses: string[]): Promise<TraderInfo[]> { + assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema); + _.forEach(takerAddresses, (takerAddress, index) => + assert.isETHAddressHex(`takerAddresses[${index}]`, takerAddress), + ); + assert.assert(orders.length === takerAddresses.length, 'Expected orders.length to equal takerAddresses.length'); + const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); + const result = await OrderValidatorContractInstance.getTradersInfo.callAsync(orders, takerAddresses); + return result; + } + /** + * Get an object conforming to BalanceAndAllowance containing on-chain balance and allowance for some address and assetData + * @param address An ethereum address + * @param assetData An encoded string that can be decoded by a specified proxy contract + * @return BalanceAndAllowance + */ + public async getBalanceAndAllowanceAsync(address: string, assetData: string): Promise<BalanceAndAllowance> { + assert.isETHAddressHex('address', address); + assert.isHexString('assetData', assetData); + const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); + const balanceAndAllowance = await OrderValidatorContractInstance.getBalanceAndAllowance.callAsync( + address, + assetData, + ); + const result = { + balance: balanceAndAllowance[0], + allowance: balanceAndAllowance[1], + }; + return result; + } + /** + * Get an array of objects conforming to BalanceAndAllowance containing on-chain balance and allowance for some address and array of assetDatas + * @param address An ethereum address + * @param assetDatas An array of encoded strings that can be decoded by a specified proxy contract + * @return BalanceAndAllowance + */ + public async getBalancesAndAllowancesAsync(address: string, assetDatas: string[]): Promise<BalanceAndAllowance[]> { + assert.isETHAddressHex('address', address); + _.forEach(assetDatas, (assetData, index) => assert.isHexString(`assetDatas[${index}]`, assetData)); + const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); + const balancesAndAllowances = await OrderValidatorContractInstance.getBalancesAndAllowances.callAsync( + address, + assetDatas, + ); + const balances = balancesAndAllowances[0]; + const allowances = balancesAndAllowances[1]; + const result = _.map(balances, (balance, index) => { + const allowance = allowances[index]; + return { + balance, + allowance, + }; + }); + return result; + } + /** + * Get owner address of tokenId by calling `token.ownerOf(tokenId)`, but returns a null owner instead of reverting on an unowned token. + * @param tokenAddress An ethereum address + * @param tokenId An ERC721 tokenId + * @return Owner of tokenId or null address if unowned + */ + public async getERC721TokenOwnerAsync(tokenAddress: string, tokenId: BigNumber): Promise<string | undefined> { + assert.isETHAddressHex('tokenAddress', tokenAddress); + assert.isBigNumber('tokenId', tokenId); + const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); + const result = await OrderValidatorContractInstance.getERC721TokenOwner.callAsync(tokenAddress, tokenId); + return result; + } + // HACK: We don't want this method to be visible to the other units within that package but not to the end user. + // TS doesn't give that possibility and therefore we make it private and access it over an any cast. Because of that tslint sees it as unused. + // tslint:disable-next-line:no-unused-variable + private _invalidateContractInstance(): void { + delete this._orderValidatorContractIfExists; + } + private async _getOrderValidatorContractAsync(): Promise<OrderValidatorContract> { + if (!_.isUndefined(this._orderValidatorContractIfExists)) { + return this._orderValidatorContractIfExists; + } + const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(artifacts.OrderValidator); + const contractInstance = new OrderValidatorContract( + abi, + address, + this._web3Wrapper.getProvider(), + this._web3Wrapper.getContractDefaults(), + ); + this._orderValidatorContractIfExists = contractInstance; + return this._orderValidatorContractIfExists; + } +} diff --git a/packages/contract-wrappers/src/index.ts b/packages/contract-wrappers/src/index.ts index 5e691fc21..b66d8460e 100644 --- a/packages/contract-wrappers/src/index.ts +++ b/packages/contract-wrappers/src/index.ts @@ -6,6 +6,7 @@ export { ExchangeWrapper } from './contract_wrappers/exchange_wrapper'; 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 { TransactionEncoder } from './utils/transaction_encoder'; @@ -21,6 +22,9 @@ export { OrderInfo, EventCallback, DecodedLogEvent, + BalanceAndAllowance, + OrderAndTraderInfo, + TraderInfo, } from './types'; export { Order, SignedOrder, AssetProxyId } from '@0xproject/types'; diff --git a/packages/contract-wrappers/src/types.ts b/packages/contract-wrappers/src/types.ts index 2b3cdc591..e0b12b7c9 100644 --- a/packages/contract-wrappers/src/types.ts +++ b/packages/contract-wrappers/src/types.ts @@ -188,3 +188,24 @@ export enum OrderStatus { FULLY_FILLED, CANCELLED, } + +export interface TraderInfo { + makerBalance: BigNumber; + makerAllowance: BigNumber; + takerBalance: BigNumber; + takerAllowance: BigNumber; + makerZrxBalance: BigNumber; + makerZrxAllowance: BigNumber; + takerZrxBalance: BigNumber; + takerZrxAllowance: BigNumber; +} + +export interface OrderAndTraderInfo { + orderInfo: OrderInfo; + traderInfo: TraderInfo; +} + +export interface BalanceAndAllowance { + balance: BigNumber; + allowance: BigNumber; +} diff --git a/packages/contract-wrappers/test/forwarder_wrapper_test.ts b/packages/contract-wrappers/test/forwarder_wrapper_test.ts index d0b21225c..a969807b2 100644 --- a/packages/contract-wrappers/test/forwarder_wrapper_test.ts +++ b/packages/contract-wrappers/test/forwarder_wrapper_test.ts @@ -25,10 +25,8 @@ describe('ForwarderWrapper', () => { blockPollingIntervalMs: 0, }; const fillableAmount = new BigNumber(5); - const takerTokenFillAmount = new BigNumber(5); let contractWrappers: ContractWrappers; let fillScenarios: FillScenarios; - let forwarderContractAddress: string; let exchangeContractAddress: string; let zrxTokenAddress: string; let userAddresses: string[]; @@ -46,7 +44,6 @@ describe('ForwarderWrapper', () => { before(async () => { await blockchainLifecycle.startAsync(); contractWrappers = new ContractWrappers(provider, contractWrappersConfig); - forwarderContractAddress = contractWrappers.forwarder.getContractAddress(); exchangeContractAddress = contractWrappers.exchange.getContractAddress(); userAddresses = await web3Wrapper.getAvailableAddressesAsync(); zrxTokenAddress = tokenUtils.getProtocolTokenAddress(); diff --git a/packages/contract-wrappers/test/order_validator_wrapper_test.ts b/packages/contract-wrappers/test/order_validator_wrapper_test.ts new file mode 100644 index 000000000..2fdb00a71 --- /dev/null +++ b/packages/contract-wrappers/test/order_validator_wrapper_test.ts @@ -0,0 +1,142 @@ +import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils'; +import { FillScenarios } from '@0xproject/fill-scenarios'; +import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils'; +import { DoneCallback, SignedOrder } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import * as chai from 'chai'; +import { BlockParamLiteral } from 'ethereum-types'; +import * as _ from 'lodash'; +import 'mocha'; + +import { ContractWrappers, ExchangeCancelEventArgs, ExchangeEvents, ExchangeFillEventArgs, OrderStatus } from '../src'; +import { DecodedLogEvent, OrderInfo, TraderInfo } from '../src/types'; + +import { chaiSetup } from './utils/chai_setup'; +import { constants } from './utils/constants'; +import { tokenUtils } from './utils/token_utils'; +import { provider, web3Wrapper } from './utils/web3_wrapper'; + +chaiSetup.configure(); +const expect = chai.expect; +const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); + +describe('OrderValidator', () => { + const contractWrappersConfig = { + networkId: constants.TESTRPC_NETWORK_ID, + blockPollingIntervalMs: 0, + }; + const fillableAmount = new BigNumber(5); + const partialFillAmount = new BigNumber(2); + let contractWrappers: ContractWrappers; + let fillScenarios: FillScenarios; + let exchangeContractAddress: string; + let zrxTokenAddress: string; + let zrxTokenAssetData: string; + let userAddresses: string[]; + let coinbase: string; + let makerAddress: string; + let takerAddress: string; + let feeRecipient: string; + let anotherMakerAddress: string; + let makerTokenAddress: string; + let takerTokenAddress: string; + let makerAssetData: string; + let takerAssetData: string; + let signedOrder: SignedOrder; + let anotherSignedOrder: SignedOrder; + before(async () => { + await blockchainLifecycle.startAsync(); + contractWrappers = new ContractWrappers(provider, contractWrappersConfig); + exchangeContractAddress = contractWrappers.exchange.getContractAddress(); + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); + zrxTokenAddress = tokenUtils.getProtocolTokenAddress(); + zrxTokenAssetData = assetDataUtils.encodeERC20AssetData(zrxTokenAddress); + fillScenarios = new FillScenarios( + provider, + userAddresses, + zrxTokenAddress, + exchangeContractAddress, + contractWrappers.erc20Proxy.getContractAddress(), + contractWrappers.erc721Proxy.getContractAddress(), + ); + [coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses; + [makerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); + takerTokenAddress = tokenUtils.getWethTokenAddress(); + [makerAssetData, takerAssetData] = [ + assetDataUtils.encodeERC20AssetData(makerTokenAddress), + assetDataUtils.encodeERC20AssetData(takerTokenAddress), + ]; + + signedOrder = await fillScenarios.createFillableSignedOrderAsync( + makerAssetData, + takerAssetData, + makerAddress, + constants.NULL_ADDRESS, + fillableAmount, + ); + anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync( + zrxTokenAssetData, + takerAssetData, + makerAddress, + constants.NULL_ADDRESS, + fillableAmount, + ); + }); + after(async () => { + await blockchainLifecycle.revertAsync(); + }); + beforeEach(async () => { + await blockchainLifecycle.startAsync(); + }); + afterEach(async () => { + await blockchainLifecycle.revertAsync(); + }); + describe('#getOrdersAndTradersInfoAsync', () => { + let signedOrders: SignedOrder[]; + let takerAddresses: string[]; + let ordersInfo: OrderInfo[]; + let tradersInfo: TraderInfo[]; + beforeEach(async () => { + signedOrders = [signedOrder, anotherSignedOrder]; + takerAddresses = [takerAddress, takerAddress]; + const ordersAndTradersInfo = await contractWrappers.orderValidator.getOrdersAndTradersInfoAsync( + signedOrders, + takerAddresses, + ); + ordersInfo = _.map(ordersAndTradersInfo, orderAndTraderInfo => orderAndTraderInfo.orderInfo); + tradersInfo = _.map(ordersAndTradersInfo, orderAndTraderInfo => orderAndTraderInfo.traderInfo); + }); + it('should return the same number of order infos and trader infos as input orders', async () => { + expect(ordersInfo.length).to.be.equal(signedOrders.length); + expect(tradersInfo.length).to.be.equal(takerAddresses.length); + }); + it('should return correct on-chain order info for input orders', async () => { + const firstOrderInfo = ordersInfo[0]; + const secondOrderInfo = ordersInfo[1]; + expect(firstOrderInfo.orderStatus).to.be.equal(OrderStatus.FILLABLE); + expect(firstOrderInfo.orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT); + expect(secondOrderInfo.orderStatus).to.be.equal(OrderStatus.FILLABLE); + expect(secondOrderInfo.orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT); + }); + it('should return correct on-chain trader info for input takers', async () => { + const firstTraderInfo = tradersInfo[0]; + const secondTraderInfo = tradersInfo[1]; + expect(firstTraderInfo.makerBalance).to.bignumber.equal(new BigNumber(5)); + expect(firstTraderInfo.makerAllowance).to.bignumber.equal(new BigNumber(5)); + expect(firstTraderInfo.takerBalance).to.bignumber.equal(new BigNumber(0)); + expect(firstTraderInfo.takerAllowance).to.bignumber.equal(new BigNumber(0)); + expect(firstTraderInfo.makerZrxBalance).to.bignumber.equal(new BigNumber(5)); + expect(firstTraderInfo.makerZrxAllowance).to.bignumber.equal(new BigNumber(5)); + expect(firstTraderInfo.takerZrxBalance).to.bignumber.equal(new BigNumber(0)); + expect(firstTraderInfo.takerZrxAllowance).to.bignumber.equal(new BigNumber(0)); + expect(secondTraderInfo.makerBalance).to.bignumber.equal(new BigNumber(5)); + expect(secondTraderInfo.makerAllowance).to.bignumber.equal(new BigNumber(5)); + expect(secondTraderInfo.takerBalance).to.bignumber.equal(new BigNumber(0)); + expect(secondTraderInfo.takerAllowance).to.bignumber.equal(new BigNumber(0)); + expect(secondTraderInfo.makerZrxBalance).to.bignumber.equal(new BigNumber(5)); + expect(secondTraderInfo.makerZrxAllowance).to.bignumber.equal(new BigNumber(5)); + expect(secondTraderInfo.takerZrxBalance).to.bignumber.equal(new BigNumber(0)); + expect(secondTraderInfo.takerZrxAllowance).to.bignumber.equal(new BigNumber(0)); + }); + }); +}); diff --git a/packages/contract-wrappers/test/utils/constants.ts b/packages/contract-wrappers/test/utils/constants.ts index 60c3370a2..f38728b77 100644 --- a/packages/contract-wrappers/test/utils/constants.ts +++ b/packages/contract-wrappers/test/utils/constants.ts @@ -15,4 +15,5 @@ export const constants = { DUMMY_TOKEN_TOTAL_SUPPLY: new BigNumber(10 ** 27), // tslint:disable-line:custom-no-magic-numbers NUM_DUMMY_ERC20_TO_DEPLOY: 3, NUM_DUMMY_ERC721_TO_DEPLOY: 1, + ZERO_AMOUNT: new BigNumber(0), }; diff --git a/packages/contract-wrappers/tsconfig.json b/packages/contract-wrappers/tsconfig.json index e35816553..2ee711adc 100644 --- a/packages/contract-wrappers/tsconfig.json +++ b/packages/contract-wrappers/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "." }, "include": ["./src/**/*", "./test/**/*"] } diff --git a/packages/contract-wrappers/typedoc-tsconfig.json b/packages/contract-wrappers/typedoc-tsconfig.json new file mode 100644 index 000000000..c9b0af1ae --- /dev/null +++ b/packages/contract-wrappers/typedoc-tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../typedoc-tsconfig", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["./src/**/*", "./test/**/*"] +} diff --git a/packages/contracts/compiler.json b/packages/contracts/compiler.json index f66114e87..cdf49dcf6 100644 --- a/packages/contracts/compiler.json +++ b/packages/contracts/compiler.json @@ -23,6 +23,7 @@ "DummyERC20Token", "DummyERC721Receiver", "DummyERC721Token", + "DummyMultipleReturnERC20Token", "DummyNoReturnERC20Token", "ERC20Proxy", "ERC20Token", diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 5d2f290ac..283991cee 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -11,8 +11,7 @@ "test": "test" }, "scripts": { - "watch_without_deps": "yarn pre_build && tsc -w", - "build": "yarn pre_build && tsc", + "build": "yarn pre_build && tsc -b", "pre_build": "run-s compile copy_artifacts generate_contract_wrappers", "copy_artifacts": "copyfiles -u 4 '../migrations/artifacts/2.0.0/**/*' ./lib/artifacts;", "test": "yarn run_mocha", @@ -20,11 +19,14 @@ "test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov", "test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html", "test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha", - "run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit", + "run_mocha": + "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit", "compile": "sol-compiler --contracts-dir src", "clean": "shx rm -rf lib generated_contract_wrappers", - "generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output generated_contract_wrappers --backend ethers", - "lint": "tslint --project . --exclude **/src/generated_contract_wrappers/**/* --exclude **/lib/**/* && yarn lint-contracts", + "generate_contract_wrappers": + "abi-gen --abis ${npm_package_config_abis} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output generated_contract_wrappers --backend ethers", + "lint": + "tslint --project . --exclude **/src/generated_contract_wrappers/**/* --exclude **/lib/**/* && yarn lint-contracts", "coverage:report:text": "istanbul report text", "coverage:report:html": "istanbul report html && open coverage/index.html", "profiler:report:html": "istanbul report html && open coverage/index.html", @@ -33,7 +35,8 @@ "lint-contracts": "solhint src/2.0.0/**/**/**/**/*.sol" }, "config": { - "abis": "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Receiver|DummyERC721Token|DummyNoReturnERC20Token|ERC20Proxy|ERC721Proxy|Forwarder|Exchange|ExchangeWrapper|IAssetData|IAssetProxy|InvalidERC721Receiver|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|OrderValidator|ReentrantERC20Token|TestAssetProxyOwner|TestAssetProxyDispatcher|TestConstants|TestExchangeInternals|TestLibBytes|TestLibs|TestSignatureValidator|TestStaticCallReceiver|Validator|Wallet|TokenRegistry|Whitelist|WETH9|ZRXToken).json" + "abis": + "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Receiver|DummyERC721Token|DummyMultipleReturnERC20Token|DummyNoReturnERC20Token|ERC20Proxy|ERC721Proxy|Forwarder|Exchange|ExchangeWrapper|IAssetData|IAssetProxy|InvalidERC721Receiver|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|OrderValidator|ReentrantERC20Token|TestAssetProxyOwner|TestAssetProxyDispatcher|TestConstants|TestExchangeInternals|TestLibBytes|TestLibs|TestSignatureValidator|TestStaticCallReceiver|Validator|Wallet|TokenRegistry|Whitelist|WETH9|ZRXToken).json" }, "repository": { "type": "git", diff --git a/packages/contracts/src/2.0.0/protocol/AssetProxy/ERC20Proxy.sol b/packages/contracts/src/2.0.0/protocol/AssetProxy/ERC20Proxy.sol index 004c3892d..258443bca 100644 --- a/packages/contracts/src/2.0.0/protocol/AssetProxy/ERC20Proxy.sol +++ b/packages/contracts/src/2.0.0/protocol/AssetProxy/ERC20Proxy.sol @@ -18,7 +18,6 @@ pragma solidity 0.4.24; -import "../../utils/LibBytes/LibBytes.sol"; import "./MixinAuthorizable.sol"; @@ -59,15 +58,64 @@ contract ERC20Proxy is mstore(96, 0) revert(0, 100) } - - /////// Token contract address /////// - // The token address is found as follows: - // * It is stored at offset 4 in `assetData` contents. - // * This is stored at offset 32 from `assetData`. - // * The offset to `assetData` from Params is stored at offset - // 4 in calldata. - // * The offset of Params in calldata is 4. - // So we read location 4 and add 32 + 4 + 4 to it. + + // `transferFrom`. + // The function is marked `external`, so no abi decodeding is done for + // us. Instead, we expect the `calldata` memory to contain the + // following: + // + // | Area | Offset | Length | Contents | + // |----------|--------|---------|-------------------------------------| + // | Header | 0 | 4 | function selector | + // | Params | | 4 * 32 | function parameters: | + // | | 4 | | 1. offset to assetData (*) | + // | | 36 | | 2. from | + // | | 68 | | 3. to | + // | | 100 | | 4. amount | + // | Data | | | assetData: | + // | | 132 | 32 | assetData Length | + // | | 164 | ** | assetData Contents | + // + // (*): offset is computed from start of function parameters, so offset + // by an additional 4 bytes in the calldata. + // + // (**): see table below to compute length of assetData Contents + // + // WARNING: The ABIv2 specification allows additional padding between + // the Params and Data section. This will result in a larger + // offset to assetData. + + // Asset data itself is encoded as follows: + // + // | Area | Offset | Length | Contents | + // |----------|--------|---------|-------------------------------------| + // | Header | 0 | 4 | function selector | + // | Params | | 1 * 32 | function parameters: | + // | | 4 | 12 + 20 | 1. token address | + + // We construct calldata for the `token.transferFrom` ABI. + // The layout of this calldata is in the table below. + // + // | Area | Offset | Length | Contents | + // |----------|--------|---------|-------------------------------------| + // | Header | 0 | 4 | function selector | + // | Params | | 3 * 32 | function parameters: | + // | | 4 | | 1. from | + // | | 36 | | 2. to | + // | | 68 | | 3. amount | + + /////// Read token address from calldata /////// + // * The token address is stored in `assetData`. + // + // * The "offset to assetData" is stored at offset 4 in the calldata (table 1). + // [assetDataOffsetFromParams = calldataload(4)] + // + // * Notes that the "offset to assetData" is relative to the "Params" area of calldata; + // add 4 bytes to account for the length of the "Header" area (table 1). + // [assetDataOffsetFromHeader = assetDataOffsetFromParams + 4] + // + // * The "token address" is offset 32+4=36 bytes into "assetData" (tables 1 & 2). + // [tokenOffset = assetDataOffsetFromHeader + 36 = calldataload(4) + 4 + 36] let token := calldataload(add(calldataload(4), 40)) /////// Setup Header Area /////// diff --git a/packages/contracts/src/2.0.0/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/2.0.0/protocol/AssetProxy/ERC721Proxy.sol index 9d0bc0f74..65b664b8b 100644 --- a/packages/contracts/src/2.0.0/protocol/AssetProxy/ERC721Proxy.sol +++ b/packages/contracts/src/2.0.0/protocol/AssetProxy/ERC721Proxy.sol @@ -18,7 +18,6 @@ pragma solidity 0.4.24; -import "../../utils/LibBytes/LibBytes.sol"; import "./MixinAuthorizable.sol"; @@ -80,6 +79,8 @@ contract ERC721Proxy is // (*): offset is computed from start of function parameters, so offset // by an additional 4 bytes in the calldata. // + // (**): see table below to compute length of assetData Contents + // // WARNING: The ABIv2 specification allows additional padding between // the Params and Data section. This will result in a larger // offset to assetData. diff --git a/packages/contracts/src/2.0.0/protocol/AssetProxyOwner/AssetProxyOwner.sol b/packages/contracts/src/2.0.0/protocol/AssetProxyOwner/AssetProxyOwner.sol index 8b7333646..4d00e92d3 100644 --- a/packages/contracts/src/2.0.0/protocol/AssetProxyOwner/AssetProxyOwner.sol +++ b/packages/contracts/src/2.0.0/protocol/AssetProxyOwner/AssetProxyOwner.sol @@ -16,15 +16,18 @@ */ -pragma solidity 0.4.10; +pragma solidity 0.4.24; import "../../multisig/MultiSigWalletWithTimeLock.sol"; +import "../../utils/LibBytes/LibBytes.sol"; contract AssetProxyOwner is MultiSigWalletWithTimeLock { + using LibBytes for bytes; + event AssetProxyRegistration(address assetProxyContract, bool isRegistered); // Mapping of AssetProxy contract address => @@ -37,8 +40,14 @@ contract AssetProxyOwner is /// on an approved AssetProxy contract. modifier validRemoveAuthorizedAddressAtIndexTx(uint256 transactionId) { Transaction storage tx = transactions[transactionId]; - require(isAssetProxyRegistered[tx.destination]); - require(readBytes4(tx.data, 0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR); + require( + isAssetProxyRegistered[tx.destination], + "UNREGISTERED_ASSET_PROXY" + ); + require( + tx.data.readBytes4(0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR, + "INVALID_FUNCTION_SELECTOR" + ); _; } @@ -48,7 +57,7 @@ contract AssetProxyOwner is /// @param _assetProxyContracts Array of AssetProxy contract addresses. /// @param _required Number of required confirmations. /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds. - function AssetProxyOwner( + constructor ( address[] memory _owners, address[] memory _assetProxyContracts, uint256 _required, @@ -59,7 +68,10 @@ contract AssetProxyOwner is { for (uint256 i = 0; i < _assetProxyContracts.length; i++) { address assetProxy = _assetProxyContracts[i]; - require(assetProxy != address(0)); + require( + assetProxy != address(0), + "INVALID_ASSET_PROXY" + ); isAssetProxyRegistered[assetProxy] = true; } } @@ -74,7 +86,7 @@ contract AssetProxyOwner is notNull(assetProxyContract) { isAssetProxyRegistered[assetProxyContract] = isRegistered; - AssetProxyRegistration(assetProxyContract, isRegistered); + emit AssetProxyRegistration(assetProxyContract, isRegistered); } /// @dev Allows execution of `removeAuthorizedAddressAtIndex` without time lock. @@ -89,31 +101,10 @@ contract AssetProxyOwner is tx.executed = true; // solhint-disable-next-line avoid-call-value if (tx.destination.call.value(tx.value)(tx.data)) - Execution(transactionId); + emit Execution(transactionId); else { - ExecutionFailure(transactionId); + emit ExecutionFailure(transactionId); tx.executed = false; } } - - /// @dev Reads an unpadded bytes4 value from a position in a byte array. - /// @param b Byte array containing a bytes4 value. - /// @param index Index in byte array of bytes4 value. - /// @return bytes4 value from byte array. - function readBytes4( - bytes memory b, - uint256 index - ) - internal - returns (bytes4 result) - { - require(b.length >= index + 4); - assembly { - result := mload(add(b, 32)) - // Solidity does not require us to clean the trailing bytes. - // We do it anyway - result := and(result, 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000) - } - return result; - } } diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinAssetProxyDispatcher.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinAssetProxyDispatcher.sol index 80475e6e3..e90b62f19 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinAssetProxyDispatcher.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinAssetProxyDispatcher.sol @@ -19,7 +19,6 @@ pragma solidity 0.4.24; import "../../utils/Ownable/Ownable.sol"; -import "../../utils/LibBytes/LibBytes.sol"; import "./mixins/MAssetProxyDispatcher.sol"; import "../AssetProxy/interfaces/IAssetProxy.sol"; @@ -28,7 +27,6 @@ contract MixinAssetProxyDispatcher is Ownable, MAssetProxyDispatcher { - using LibBytes for bytes; // Mapping from Asset Proxy Id's to their respective Asset Proxy mapping (bytes4 => IAssetProxy) public assetProxies; @@ -90,7 +88,7 @@ contract MixinAssetProxyDispatcher is "LENGTH_GREATER_THAN_3_REQUIRED" ); - // Lookup assetProxy + // Lookup assetProxy. We do not use `LibBytes.readBytes4` for gas efficiency reasons. bytes4 assetProxyId; assembly { assetProxyId := and(mload( diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinExchangeCore.sol index be163ec97..11bbe40fb 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinExchangeCore.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinExchangeCore.sol @@ -107,14 +107,7 @@ contract MixinExchangeCore is public nonReentrant { - // Fetch current order status - OrderInfo memory orderInfo = getOrderInfo(order); - - // Validate context - assertValidCancel(order, orderInfo); - - // Perform cancel - updateCancelledState(order, orderInfo.orderHash); + cancelOrderInternal(order); } /// @dev Gets information about an order: status, hash, and amount filled. @@ -236,6 +229,22 @@ contract MixinExchangeCore is return fillResults; } + /// @dev After calling, the order can not be filled anymore. + /// Throws if order is invalid or sender does not have permission to cancel. + /// @param order Order to cancel. Order must be OrderStatus.FILLABLE. + function cancelOrderInternal(Order memory order) + internal + { + // Fetch current order status + OrderInfo memory orderInfo = getOrderInfo(order); + + // Validate context + assertValidCancel(order, orderInfo); + + // Perform cancel + updateCancelledState(order, orderInfo.orderHash); + } + /// @dev Updates state with results of a fill order. /// @param order that was filled. /// @param takerAddress Address of taker who filled the order. @@ -404,16 +413,6 @@ contract MixinExchangeCore is safeMul(order.makerAssetAmount, takerAssetFilledAmount), "INVALID_FILL_PRICE" ); - - // Validate fill order rounding - require( - !isRoundingErrorFloor( - takerAssetFilledAmount, - order.takerAssetAmount, - order.makerAssetAmount - ), - "ROUNDING_ERROR" - ); } /// @dev Validates context for cancelOrder. Succeeds or throws. @@ -463,17 +462,17 @@ contract MixinExchangeCore is { // Compute proportional transfer amounts fillResults.takerAssetFilledAmount = takerAssetFilledAmount; - fillResults.makerAssetFilledAmount = getPartialAmountFloor( + fillResults.makerAssetFilledAmount = safeGetPartialAmountFloor( takerAssetFilledAmount, order.takerAssetAmount, order.makerAssetAmount ); - fillResults.makerFeePaid = getPartialAmountFloor( - takerAssetFilledAmount, - order.takerAssetAmount, + fillResults.makerFeePaid = safeGetPartialAmountFloor( + fillResults.makerAssetFilledAmount, + order.makerAssetAmount, order.makerFee ); - fillResults.takerFeePaid = getPartialAmountFloor( + fillResults.takerFeePaid = safeGetPartialAmountFloor( takerAssetFilledAmount, order.takerAssetAmount, order.takerFee diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinMatchOrders.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinMatchOrders.sol index 075a610b5..b4f6bdb26 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinMatchOrders.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinMatchOrders.sol @@ -177,13 +177,13 @@ contract MixinMatchOrders is { // Derive maker asset amounts for left & right orders, given store taker assert amounts uint256 leftTakerAssetAmountRemaining = safeSub(leftOrder.takerAssetAmount, leftOrderTakerAssetFilledAmount); - uint256 leftMakerAssetAmountRemaining = getPartialAmountFloor( + uint256 leftMakerAssetAmountRemaining = safeGetPartialAmountFloor( leftOrder.makerAssetAmount, leftOrder.takerAssetAmount, leftTakerAssetAmountRemaining ); uint256 rightTakerAssetAmountRemaining = safeSub(rightOrder.takerAssetAmount, rightOrderTakerAssetFilledAmount); - uint256 rightMakerAssetAmountRemaining = getPartialAmountFloor( + uint256 rightMakerAssetAmountRemaining = safeGetPartialAmountFloor( rightOrder.makerAssetAmount, rightOrder.takerAssetAmount, rightTakerAssetAmountRemaining @@ -205,7 +205,7 @@ contract MixinMatchOrders is matchedFillResults.left.takerAssetFilledAmount = matchedFillResults.right.makerAssetFilledAmount; // Round down to ensure the maker's exchange rate does not exceed the price specified by the order. // We favor the maker when the exchange rate must be rounded. - matchedFillResults.left.makerAssetFilledAmount = getPartialAmountFloor( + matchedFillResults.left.makerAssetFilledAmount = safeGetPartialAmountFloor( leftOrder.makerAssetAmount, leftOrder.takerAssetAmount, matchedFillResults.left.takerAssetFilledAmount @@ -217,7 +217,7 @@ contract MixinMatchOrders is matchedFillResults.right.makerAssetFilledAmount = matchedFillResults.left.takerAssetFilledAmount; // Round up to ensure the maker's exchange rate does not exceed the price specified by the order. // We favor the maker when the exchange rate must be rounded. - matchedFillResults.right.takerAssetFilledAmount = getPartialAmountCeil( + matchedFillResults.right.takerAssetFilledAmount = safeGetPartialAmountCeil( rightOrder.takerAssetAmount, rightOrder.makerAssetAmount, matchedFillResults.right.makerAssetFilledAmount @@ -231,24 +231,24 @@ contract MixinMatchOrders is ); // Compute fees for left order - matchedFillResults.left.makerFeePaid = getPartialAmountFloor( + matchedFillResults.left.makerFeePaid = safeGetPartialAmountFloor( matchedFillResults.left.makerAssetFilledAmount, leftOrder.makerAssetAmount, leftOrder.makerFee ); - matchedFillResults.left.takerFeePaid = getPartialAmountFloor( + matchedFillResults.left.takerFeePaid = safeGetPartialAmountFloor( matchedFillResults.left.takerAssetFilledAmount, leftOrder.takerAssetAmount, leftOrder.takerFee ); // Compute fees for right order - matchedFillResults.right.makerFeePaid = getPartialAmountFloor( + matchedFillResults.right.makerFeePaid = safeGetPartialAmountFloor( matchedFillResults.right.makerAssetFilledAmount, rightOrder.makerAssetAmount, rightOrder.makerFee ); - matchedFillResults.right.takerFeePaid = getPartialAmountFloor( + matchedFillResults.right.takerFeePaid = safeGetPartialAmountFloor( matchedFillResults.right.takerAssetFilledAmount, rightOrder.takerAssetAmount, rightOrder.takerFee diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol index a5459a21e..a149f95c9 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol @@ -377,10 +377,11 @@ contract MixinWrapperFunctions is /// @param orders Array of order specifications. function batchCancelOrders(LibOrder.Order[] memory orders) public + nonReentrant { uint256 ordersLength = orders.length; for (uint256 i = 0; i != ordersLength; i++) { - cancelOrder(orders[i]); + cancelOrderInternal(orders[i]); } } diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibMath.sol b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibMath.sol index 0e0fba5d2..57fd53f29 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibMath.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/libs/LibMath.sol @@ -26,11 +26,48 @@ contract LibMath is { /// @dev Calculates partial value given a numerator and denominator rounded down. + /// Reverts if rounding error is >= 0.1% /// @param numerator Numerator. /// @param denominator Denominator. /// @param target Value to calculate partial of. /// @return Partial value of target rounded down. - function getPartialAmountFloor( + function safeGetPartialAmountFloor( + uint256 numerator, + uint256 denominator, + uint256 target + ) + internal + pure + returns (uint256 partialAmount) + { + require( + denominator > 0, + "DIVISION_BY_ZERO" + ); + + require( + !isRoundingErrorFloor( + numerator, + denominator, + target + ), + "ROUNDING_ERROR" + ); + + partialAmount = safeDiv( + safeMul(numerator, target), + denominator + ); + return partialAmount; + } + + /// @dev Calculates partial value given a numerator and denominator rounded down. + /// Reverts if rounding error is >= 0.1% + /// @param numerator Numerator. + /// @param denominator Denominator. + /// @param target Value to calculate partial of. + /// @return Partial value of target rounded up. + function safeGetPartialAmountCeil( uint256 numerator, uint256 denominator, uint256 target @@ -43,7 +80,48 @@ contract LibMath is denominator > 0, "DIVISION_BY_ZERO" ); + + require( + !isRoundingErrorCeil( + numerator, + denominator, + target + ), + "ROUNDING_ERROR" + ); + // safeDiv computes `floor(a / b)`. We use the identity (a, b integer): + // ceil(a / b) = floor((a + b - 1) / b) + // To implement `ceil(a / b)` using safeDiv. + partialAmount = safeDiv( + safeAdd( + safeMul(numerator, target), + safeSub(denominator, 1) + ), + denominator + ); + return partialAmount; + } + + /// @dev Calculates partial value given a numerator and denominator rounded down. + /// @param numerator Numerator. + /// @param denominator Denominator. + /// @param target Value to calculate partial of. + /// @return Partial value of target rounded down. + function getPartialAmountFloor( + uint256 numerator, + uint256 denominator, + uint256 target + ) + internal + pure + returns (uint256 partialAmount) + { + require( + denominator > 0, + "DIVISION_BY_ZERO" + ); + partialAmount = safeDiv( safeMul(numerator, target), denominator @@ -69,7 +147,7 @@ contract LibMath is denominator > 0, "DIVISION_BY_ZERO" ); - + // safeDiv computes `floor(a / b)`. We use the identity (a, b integer): // ceil(a / b) = floor((a + b - 1) / b) // To implement `ceil(a / b)` using safeDiv. diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MExchangeCore.sol b/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MExchangeCore.sol index d85913e0f..742499568 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MExchangeCore.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/mixins/MExchangeCore.sol @@ -72,6 +72,11 @@ contract MExchangeCore is internal returns (LibFillResults.FillResults memory fillResults); + /// @dev After calling, the order can not be filled anymore. + /// @param order Order struct containing order specifications. + function cancelOrderInternal(LibOrder.Order memory order) + internal; + /// @dev Updates state with results of a fill order. /// @param order that was filled. /// @param takerAddress Address of taker who filled the order. diff --git a/packages/contracts/src/2.0.0/test/DummyERC20Token/DummyMultipleReturnERC20Token.sol b/packages/contracts/src/2.0.0/test/DummyERC20Token/DummyMultipleReturnERC20Token.sol new file mode 100644 index 000000000..8a8aecae8 --- /dev/null +++ b/packages/contracts/src/2.0.0/test/DummyERC20Token/DummyMultipleReturnERC20Token.sol @@ -0,0 +1,70 @@ +/* + + Copyright 2018 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity 0.4.24; + +import "./DummyERC20Token.sol"; + + +// solhint-disable no-empty-blocks +contract DummyMultipleReturnERC20Token is + DummyERC20Token +{ + + constructor ( + string _name, + string _symbol, + uint256 _decimals, + uint256 _totalSupply + ) + public + DummyERC20Token( + _name, + _symbol, + _decimals, + _totalSupply + ) + {} + + /// @dev send `value` token to `to` from `from` on the condition it is approved by `from` + /// @param _from The address of the sender + /// @param _to The address of the recipient + /// @param _value The amount of token to be transferred + function transferFrom( + address _from, + address _to, + uint256 _value + ) + external + returns (bool) + { + emit Transfer( + _from, + _to, + _value + ); + + // HACK: This contract will not compile if we remove `returns (bool)`, so we manually return 64 bytes (equiavalent to true, true) + assembly { + mstore(0, 1) + mstore(32, 1) + return(0, 64) + } + } +} + diff --git a/packages/contracts/src/2.0.0/test/ReentrantERC20Token/ReentrantERC20Token.sol b/packages/contracts/src/2.0.0/test/ReentrantERC20Token/ReentrantERC20Token.sol index 8bfdd2e66..e3311c703 100644 --- a/packages/contracts/src/2.0.0/test/ReentrantERC20Token/ReentrantERC20Token.sol +++ b/packages/contracts/src/2.0.0/test/ReentrantERC20Token/ReentrantERC20Token.sol @@ -25,6 +25,7 @@ import "../../protocol/Exchange/interfaces/IExchange.sol"; import "../../protocol/Exchange/libs/LibOrder.sol"; +// solhint-disable no-unused-vars contract ReentrantERC20Token is ERC20Token { @@ -50,6 +51,7 @@ contract ReentrantERC20Token is MARKET_SELL_ORDERS, MATCH_ORDERS, CANCEL_ORDER, + BATCH_CANCEL_ORDERS, CANCEL_ORDERS_UP_TO, SET_SIGNATURE_VALIDATOR_APPROVAL } @@ -149,6 +151,11 @@ contract ReentrantERC20Token is EXCHANGE.cancelOrder.selector, order ); + } else if (currentFunctionId == uint8(ExchangeFunction.BATCH_CANCEL_ORDERS)) { + calldata = abi.encodeWithSelector( + EXCHANGE.batchCancelOrders.selector, + orders + ); } else if (currentFunctionId == uint8(ExchangeFunction.CANCEL_ORDERS_UP_TO)) { calldata = abi.encodeWithSelector( EXCHANGE.cancelOrdersUpTo.selector, diff --git a/packages/contracts/src/2.0.0/test/TestAssetProxyOwner/TestAssetProxyOwner.sol b/packages/contracts/src/2.0.0/test/TestAssetProxyOwner/TestAssetProxyOwner.sol index 75e782d43..38ec42a72 100644 --- a/packages/contracts/src/2.0.0/test/TestAssetProxyOwner/TestAssetProxyOwner.sol +++ b/packages/contracts/src/2.0.0/test/TestAssetProxyOwner/TestAssetProxyOwner.sol @@ -16,7 +16,7 @@ */ -pragma solidity 0.4.10; +pragma solidity 0.4.24; import "../../protocol/AssetProxyOwner/AssetProxyOwner.sol"; @@ -26,7 +26,7 @@ contract TestAssetProxyOwner is AssetProxyOwner { - function TestAssetProxyOwner( + constructor ( address[] memory _owners, address[] memory _assetProxyContracts, uint256 _required, @@ -38,6 +38,7 @@ contract TestAssetProxyOwner is function testValidRemoveAuthorizedAddressAtIndexTx(uint256 id) public + view validRemoveAuthorizedAddressAtIndexTx(id) returns (bool) { @@ -50,23 +51,9 @@ contract TestAssetProxyOwner is /// @return Successful if data is a call to `removeAuthorizedAddressAtIndex`. function isFunctionRemoveAuthorizedAddressAtIndex(bytes memory data) public + pure returns (bool) { - return readBytes4(data, 0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR; - } - - /// @dev Reads an unpadded bytes4 value from a position in a byte array. - /// @param b Byte array containing a bytes4 value. - /// @param index Index in byte array of bytes4 value. - /// @return bytes4 value from byte array. - function publicReadBytes4( - bytes memory b, - uint256 index - ) - public - returns (bytes4 result) - { - result = readBytes4(b, index); - return result; + return data.readBytes4(0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR; } } diff --git a/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol b/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol index da9313e02..27187f8f8 100644 --- a/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol +++ b/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol @@ -63,6 +63,42 @@ contract TestExchangeInternals is } /// @dev Calculates partial value given a numerator and denominator. + /// Reverts if rounding error is >= 0.1% + /// @param numerator Numerator. + /// @param denominator Denominator. + /// @param target Value to calculate partial of. + /// @return Partial value of target. + function publicSafeGetPartialAmountFloor( + uint256 numerator, + uint256 denominator, + uint256 target + ) + public + pure + returns (uint256 partialAmount) + { + return safeGetPartialAmountFloor(numerator, denominator, target); + } + + /// @dev Calculates partial value given a numerator and denominator. + /// Reverts if rounding error is >= 0.1% + /// @param numerator Numerator. + /// @param denominator Denominator. + /// @param target Value to calculate partial of. + /// @return Partial value of target. + function publicSafeGetPartialAmountCeil( + uint256 numerator, + uint256 denominator, + uint256 target + ) + public + pure + returns (uint256 partialAmount) + { + return safeGetPartialAmountCeil(numerator, denominator, target); + } + + /// @dev Calculates partial value given a numerator and denominator. /// @param numerator Numerator. /// @param denominator Denominator. /// @param target Value to calculate partial of. diff --git a/packages/contracts/src/2.0.0/utils/LibBytes/LibBytes.sol b/packages/contracts/src/2.0.0/utils/LibBytes/LibBytes.sol index 504e950a8..93873cbcc 100644 --- a/packages/contracts/src/2.0.0/utils/LibBytes/LibBytes.sol +++ b/packages/contracts/src/2.0.0/utils/LibBytes/LibBytes.sol @@ -467,8 +467,13 @@ library LibBytes { b.length >= index + 4, "GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED" ); + + // Arrays are prefixed by a 32 byte length field + index += 32; + + // Read the bytes4 from array memory assembly { - result := mload(add(b, 32)) + result := mload(add(b, index)) // Solidity does not require us to clean the trailing bytes. // We do it anyway result := and(result, 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000) diff --git a/packages/contracts/test/asset_proxy/authorizable.ts b/packages/contracts/test/asset_proxy/authorizable.ts index e99c6cee3..0c0da46b3 100644 --- a/packages/contracts/test/asset_proxy/authorizable.ts +++ b/packages/contracts/test/asset_proxy/authorizable.ts @@ -2,6 +2,7 @@ import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { RevertReason } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; +import * as _ from 'lodash'; import { MixinAuthorizableContract } from '../../generated_contract_wrappers/mixin_authorizable'; import { artifacts } from '../utils/artifacts'; @@ -28,8 +29,7 @@ describe('Authorizable', () => { }); before(async () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); - owner = address = accounts[0]; - notOwner = accounts[1]; + [owner, address, notOwner] = _.slice(accounts, 0, 3); authorizable = await MixinAuthorizableContract.deployFrom0xArtifactAsync( artifacts.MixinAuthorizable, provider, diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts index 6031e554d..4d70031d1 100644 --- a/packages/contracts/test/asset_proxy/proxies.ts +++ b/packages/contracts/test/asset_proxy/proxies.ts @@ -8,6 +8,8 @@ import * as _ from 'lodash'; import { DummyERC20TokenContract } from '../../generated_contract_wrappers/dummy_erc20_token'; import { DummyERC721ReceiverContract } from '../../generated_contract_wrappers/dummy_erc721_receiver'; import { DummyERC721TokenContract } from '../../generated_contract_wrappers/dummy_erc721_token'; +import { DummyMultipleReturnERC20TokenContract } from '../../generated_contract_wrappers/dummy_multiple_return_erc20_token'; +import { DummyNoReturnERC20TokenContract } from '../../generated_contract_wrappers/dummy_no_return_erc20_token'; import { ERC20ProxyContract } from '../../generated_contract_wrappers/erc20_proxy'; import { ERC721ProxyContract } from '../../generated_contract_wrappers/erc721_proxy'; import { IAssetProxyContract } from '../../generated_contract_wrappers/i_asset_proxy'; @@ -42,6 +44,8 @@ describe('Asset Transfer Proxies', () => { let erc721Receiver: DummyERC721ReceiverContract; let erc20Proxy: ERC20ProxyContract; let erc721Proxy: ERC721ProxyContract; + let noReturnErc20Token: DummyNoReturnERC20TokenContract; + let multipleReturnErc20Token: DummyMultipleReturnERC20TokenContract; let erc20Wrapper: ERC20Wrapper; let erc721Wrapper: ERC721Wrapper; @@ -91,6 +95,51 @@ describe('Asset Transfer Proxies', () => { provider, txDefaults, ); + noReturnErc20Token = await DummyNoReturnERC20TokenContract.deployFrom0xArtifactAsync( + artifacts.DummyNoReturnERC20Token, + provider, + txDefaults, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + constants.DUMMY_TOKEN_DECIMALS, + constants.DUMMY_TOKEN_TOTAL_SUPPLY, + ); + await web3Wrapper.awaitTransactionSuccessAsync( + await noReturnErc20Token.setBalance.sendTransactionAsync(makerAddress, constants.INITIAL_ERC20_BALANCE), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + await web3Wrapper.awaitTransactionSuccessAsync( + await noReturnErc20Token.approve.sendTransactionAsync( + erc20Proxy.address, + constants.INITIAL_ERC20_ALLOWANCE, + { from: makerAddress }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + multipleReturnErc20Token = await DummyMultipleReturnERC20TokenContract.deployFrom0xArtifactAsync( + artifacts.DummyMultipleReturnERC20Token, + provider, + txDefaults, + constants.DUMMY_TOKEN_NAME, + constants.DUMMY_TOKEN_SYMBOL, + constants.DUMMY_TOKEN_DECIMALS, + constants.DUMMY_TOKEN_TOTAL_SUPPLY, + ); + await web3Wrapper.awaitTransactionSuccessAsync( + await multipleReturnErc20Token.setBalance.sendTransactionAsync( + makerAddress, + constants.INITIAL_ERC20_BALANCE, + ), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + await web3Wrapper.awaitTransactionSuccessAsync( + await multipleReturnErc20Token.approve.sendTransactionAsync( + erc20Proxy.address, + constants.INITIAL_ERC20_ALLOWANCE, + { from: makerAddress }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, + ); }); beforeEach(async () => { await blockchainLifecycle.startAsync(); @@ -141,6 +190,65 @@ describe('Asset Transfer Proxies', () => { ); }); + it('should successfully transfer tokens that do not return a value', async () => { + // Construct ERC20 asset data + const encodedAssetData = assetDataUtils.encodeERC20AssetData(noReturnErc20Token.address); + // Perform a transfer from makerAddress to takerAddress + const initialMakerBalance = await noReturnErc20Token.balanceOf.callAsync(makerAddress); + const initialTakerBalance = await noReturnErc20Token.balanceOf.callAsync(takerAddress); + const amount = new BigNumber(10); + const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( + encodedAssetData, + makerAddress, + takerAddress, + amount, + ); + await web3Wrapper.awaitTransactionSuccessAsync( + await web3Wrapper.sendTransactionAsync({ + to: erc20Proxy.address, + data, + from: exchangeAddress, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + // Verify transfer was successful + const newMakerBalance = await noReturnErc20Token.balanceOf.callAsync(makerAddress); + const newTakerBalance = await noReturnErc20Token.balanceOf.callAsync(takerAddress); + expect(newMakerBalance).to.be.bignumber.equal(initialMakerBalance.minus(amount)); + expect(newTakerBalance).to.be.bignumber.equal(initialTakerBalance.plus(amount)); + }); + + it('should successfully transfer tokens and ignore extra assetData', async () => { + // Construct ERC20 asset data + const extraData = '0102030405060708'; + const encodedAssetData = `${assetDataUtils.encodeERC20AssetData(zrxToken.address)}${extraData}`; + // Perform a transfer from makerAddress to takerAddress + const erc20Balances = await erc20Wrapper.getBalancesAsync(); + const amount = new BigNumber(10); + const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( + encodedAssetData, + makerAddress, + takerAddress, + amount, + ); + await web3Wrapper.awaitTransactionSuccessAsync( + await web3Wrapper.sendTransactionAsync({ + to: erc20Proxy.address, + data, + from: exchangeAddress, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + // Verify transfer was successful + const newBalances = await erc20Wrapper.getBalancesAsync(); + expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[makerAddress][zrxToken.address].minus(amount), + ); + expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[takerAddress][zrxToken.address].add(amount), + ); + }); + it('should do nothing if transferring 0 amount of a token', async () => { // Construct ERC20 asset data const encodedAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address); @@ -189,6 +297,7 @@ describe('Asset Transfer Proxies', () => { }), constants.AWAIT_TRANSACTION_MINED_MS, ); + const erc20Balances = await erc20Wrapper.getBalancesAsync(); // Perform a transfer; expect this to fail. await expectTransactionFailedAsync( web3Wrapper.sendTransactionAsync({ @@ -198,6 +307,43 @@ describe('Asset Transfer Proxies', () => { }), RevertReason.TransferFailed, ); + const newBalances = await erc20Wrapper.getBalancesAsync(); + expect(newBalances).to.deep.equal(erc20Balances); + }); + + it('should throw if allowances are too low and token does not return a value', async () => { + // Construct ERC20 asset data + const encodedAssetData = assetDataUtils.encodeERC20AssetData(noReturnErc20Token.address); + // Create allowance less than transfer amount. Set allowance on proxy. + const allowance = new BigNumber(0); + const amount = new BigNumber(10); + const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( + encodedAssetData, + makerAddress, + takerAddress, + amount, + ); + await web3Wrapper.awaitTransactionSuccessAsync( + await noReturnErc20Token.approve.sendTransactionAsync(erc20Proxy.address, allowance, { + from: makerAddress, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + const initialMakerBalance = await noReturnErc20Token.balanceOf.callAsync(makerAddress); + const initialTakerBalance = await noReturnErc20Token.balanceOf.callAsync(takerAddress); + // Perform a transfer; expect this to fail. + await expectTransactionFailedAsync( + web3Wrapper.sendTransactionAsync({ + to: erc20Proxy.address, + data, + from: exchangeAddress, + }), + RevertReason.TransferFailed, + ); + const newMakerBalance = await noReturnErc20Token.balanceOf.callAsync(makerAddress); + const newTakerBalance = await noReturnErc20Token.balanceOf.callAsync(takerAddress); + expect(newMakerBalance).to.be.bignumber.equal(initialMakerBalance); + expect(newTakerBalance).to.be.bignumber.equal(initialTakerBalance); }); it('should throw if requesting address is not authorized', async () => { @@ -211,6 +357,7 @@ describe('Asset Transfer Proxies', () => { takerAddress, amount, ); + const erc20Balances = await erc20Wrapper.getBalancesAsync(); await expectTransactionFailedAsync( web3Wrapper.sendTransactionAsync({ to: erc20Proxy.address, @@ -219,6 +366,35 @@ describe('Asset Transfer Proxies', () => { }), RevertReason.SenderNotAuthorized, ); + const newBalances = await erc20Wrapper.getBalancesAsync(); + expect(newBalances).to.deep.equal(erc20Balances); + }); + + it('should throw if token returns more than 32 bytes', async () => { + // Construct ERC20 asset data + const encodedAssetData = assetDataUtils.encodeERC20AssetData(multipleReturnErc20Token.address); + const amount = new BigNumber(10); + const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( + encodedAssetData, + makerAddress, + takerAddress, + amount, + ); + const initialMakerBalance = await multipleReturnErc20Token.balanceOf.callAsync(makerAddress); + const initialTakerBalance = await multipleReturnErc20Token.balanceOf.callAsync(takerAddress); + // Perform a transfer; expect this to fail. + await expectTransactionFailedAsync( + web3Wrapper.sendTransactionAsync({ + to: erc20Proxy.address, + data, + from: exchangeAddress, + }), + RevertReason.TransferFailed, + ); + const newMakerBalance = await multipleReturnErc20Token.balanceOf.callAsync(makerAddress); + const newTakerBalance = await multipleReturnErc20Token.balanceOf.callAsync(takerAddress); + expect(newMakerBalance).to.be.bignumber.equal(initialMakerBalance); + expect(newTakerBalance).to.be.bignumber.equal(initialTakerBalance); }); }); @@ -247,7 +423,38 @@ describe('Asset Transfer Proxies', () => { const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Verify pre-condition const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); - expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); + expect(ownerMakerAsset).to.be.equal(makerAddress); + // Perform a transfer from makerAddress to takerAddress + const amount = new BigNumber(1); + const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( + encodedAssetData, + makerAddress, + takerAddress, + amount, + ); + await web3Wrapper.awaitTransactionSuccessAsync( + await web3Wrapper.sendTransactionAsync({ + to: erc721Proxy.address, + data, + from: exchangeAddress, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + // Verify transfer was successful + const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); + expect(newOwnerMakerAsset).to.be.bignumber.equal(takerAddress); + }); + + it('should successfully transfer tokens and ignore extra assetData', async () => { + // Construct ERC721 asset data + const extraData = '0102030405060708'; + const encodedAssetData = `${assetDataUtils.encodeERC721AssetData( + erc721Token.address, + erc721MakerTokenId, + )}${extraData}`; + // Verify pre-condition + const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); + expect(ownerMakerAsset).to.be.equal(makerAddress); // Perform a transfer from makerAddress to takerAddress const amount = new BigNumber(1); const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( @@ -274,7 +481,7 @@ describe('Asset Transfer Proxies', () => { const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Verify pre-condition const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); - expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); + expect(ownerMakerAsset).to.be.equal(makerAddress); // Perform a transfer from makerAddress to takerAddress const amount = new BigNumber(1); const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( @@ -304,7 +511,7 @@ describe('Asset Transfer Proxies', () => { const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Verify pre-condition const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); - expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); + expect(ownerMakerAsset).to.be.equal(makerAddress); // Perform a transfer from makerAddress to takerAddress const amount = new BigNumber(0); const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( @@ -313,7 +520,7 @@ describe('Asset Transfer Proxies', () => { takerAddress, amount, ); - return expectTransactionFailedAsync( + await expectTransactionFailedAsync( web3Wrapper.sendTransactionAsync({ to: erc721Proxy.address, data, @@ -321,6 +528,8 @@ describe('Asset Transfer Proxies', () => { }), RevertReason.InvalidAmount, ); + const newOwner = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); + expect(newOwner).to.be.equal(ownerMakerAsset); }); it('should throw if transferring > 1 amount of a token', async () => { @@ -328,7 +537,7 @@ describe('Asset Transfer Proxies', () => { const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); // Verify pre-condition const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); - expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); + expect(ownerMakerAsset).to.be.equal(makerAddress); // Perform a transfer from makerAddress to takerAddress const amount = new BigNumber(500); const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( @@ -337,7 +546,7 @@ describe('Asset Transfer Proxies', () => { takerAddress, amount, ); - return expectTransactionFailedAsync( + await expectTransactionFailedAsync( web3Wrapper.sendTransactionAsync({ to: erc721Proxy.address, data, @@ -345,11 +554,16 @@ describe('Asset Transfer Proxies', () => { }), RevertReason.InvalidAmount, ); + const newOwner = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); + expect(newOwner).to.be.equal(ownerMakerAsset); }); it('should throw if allowances are too low', async () => { // Construct ERC721 asset data const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); + // Verify pre-condition + const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); + expect(ownerMakerAsset).to.be.equal(makerAddress); // Remove transfer approval for makerAddress. await web3Wrapper.awaitTransactionSuccessAsync( await erc721Token.approve.sendTransactionAsync(constants.NULL_ADDRESS, erc721MakerTokenId, { @@ -365,7 +579,7 @@ describe('Asset Transfer Proxies', () => { takerAddress, amount, ); - return expectTransactionFailedAsync( + await expectTransactionFailedAsync( web3Wrapper.sendTransactionAsync({ to: erc721Proxy.address, data, @@ -373,11 +587,16 @@ describe('Asset Transfer Proxies', () => { }), RevertReason.TransferFailed, ); + const newOwner = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); + expect(newOwner).to.be.equal(ownerMakerAsset); }); it('should throw if requesting address is not authorized', async () => { // Construct ERC721 asset data const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId); + // Verify pre-condition + const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); + expect(ownerMakerAsset).to.be.equal(makerAddress); // Perform a transfer from makerAddress to takerAddress const amount = new BigNumber(1); const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( @@ -386,7 +605,7 @@ describe('Asset Transfer Proxies', () => { takerAddress, amount, ); - return expectTransactionFailedAsync( + await expectTransactionFailedAsync( web3Wrapper.sendTransactionAsync({ to: erc721Proxy.address, data, @@ -394,6 +613,8 @@ describe('Asset Transfer Proxies', () => { }), RevertReason.SenderNotAuthorized, ); + const newOwner = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); + expect(newOwner).to.be.equal(ownerMakerAsset); }); }); diff --git a/packages/contracts/test/exchange/core.ts b/packages/contracts/test/exchange/core.ts index 3bb71b58f..acb99eed1 100644 --- a/packages/contracts/test/exchange/core.ts +++ b/packages/contracts/test/exchange/core.ts @@ -8,7 +8,10 @@ import { LogWithDecodedArgs } from 'ethereum-types'; import ethUtil = require('ethereumjs-util'); import * as _ from 'lodash'; -import { DummyERC20TokenContract } from '../../generated_contract_wrappers/dummy_erc20_token'; +import { + DummyERC20TokenContract, + DummyERC20TokenTransferEventArgs, +} from '../../generated_contract_wrappers/dummy_erc20_token'; import { DummyERC721TokenContract } from '../../generated_contract_wrappers/dummy_erc721_token'; import { DummyNoReturnERC20TokenContract } from '../../generated_contract_wrappers/dummy_no_return_erc20_token'; import { ERC20ProxyContract } from '../../generated_contract_wrappers/erc20_proxy'; @@ -243,6 +246,40 @@ describe('Exchange core', () => { RevertReason.ValidatorError, ); }); + + it('should not emit transfer events for transfers where from == to', async () => { + const txReceipt = await exchangeWrapper.fillOrderAsync(signedOrder, makerAddress); + const logs = txReceipt.logs; + const transferLogs = _.filter( + logs, + log => (log as LogWithDecodedArgs<DummyERC20TokenTransferEventArgs>).event === 'Transfer', + ); + expect(transferLogs.length).to.be.equal(2); + expect((transferLogs[0] as LogWithDecodedArgs<DummyERC20TokenTransferEventArgs>).address).to.be.equal( + zrxToken.address, + ); + expect((transferLogs[0] as LogWithDecodedArgs<DummyERC20TokenTransferEventArgs>).args._from).to.be.equal( + makerAddress, + ); + expect((transferLogs[0] as LogWithDecodedArgs<DummyERC20TokenTransferEventArgs>).args._to).to.be.equal( + feeRecipientAddress, + ); + expect( + (transferLogs[0] as LogWithDecodedArgs<DummyERC20TokenTransferEventArgs>).args._value, + ).to.be.bignumber.equal(signedOrder.makerFee); + expect((transferLogs[1] as LogWithDecodedArgs<DummyERC20TokenTransferEventArgs>).address).to.be.equal( + zrxToken.address, + ); + expect((transferLogs[1] as LogWithDecodedArgs<DummyERC20TokenTransferEventArgs>).args._from).to.be.equal( + makerAddress, + ); + expect((transferLogs[1] as LogWithDecodedArgs<DummyERC20TokenTransferEventArgs>).args._to).to.be.equal( + feeRecipientAddress, + ); + expect( + (transferLogs[1] as LogWithDecodedArgs<DummyERC20TokenTransferEventArgs>).args._value, + ).to.be.bignumber.equal(signedOrder.takerFee); + }); }); describe('Testing exchange of ERC20 tokens with no return values', () => { diff --git a/packages/contracts/test/exchange/dispatcher.ts b/packages/contracts/test/exchange/dispatcher.ts index 81871a680..a8ae897a8 100644 --- a/packages/contracts/test/exchange/dispatcher.ts +++ b/packages/contracts/test/exchange/dispatcher.ts @@ -205,6 +205,60 @@ describe('AssetProxyDispatcher', () => { ); }); + it('should not dispatch a transfer if amount == 0', async () => { + // Register ERC20 proxy + await web3Wrapper.awaitTransactionSuccessAsync( + await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, { from: owner }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + // Construct metadata for ERC20 proxy + const encodedAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address); + + // Perform a transfer from makerAddress to takerAddress + const erc20Balances = await erc20Wrapper.getBalancesAsync(); + const amount = constants.ZERO_AMOUNT; + const txReceipt = await web3Wrapper.awaitTransactionSuccessAsync( + await assetProxyDispatcher.publicDispatchTransferFrom.sendTransactionAsync( + encodedAssetData, + makerAddress, + takerAddress, + amount, + { from: owner }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + expect(txReceipt.logs.length).to.be.equal(0); + const newBalances = await erc20Wrapper.getBalancesAsync(); + expect(newBalances).to.deep.equal(erc20Balances); + }); + + it('should not dispatch a transfer if from == to', async () => { + // Register ERC20 proxy + await web3Wrapper.awaitTransactionSuccessAsync( + await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, { from: owner }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + // Construct metadata for ERC20 proxy + const encodedAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address); + + // Perform a transfer from makerAddress to takerAddress + const erc20Balances = await erc20Wrapper.getBalancesAsync(); + const amount = new BigNumber(10); + const txReceipt = await web3Wrapper.awaitTransactionSuccessAsync( + await assetProxyDispatcher.publicDispatchTransferFrom.sendTransactionAsync( + encodedAssetData, + makerAddress, + makerAddress, + amount, + { from: owner }, + ), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + expect(txReceipt.logs.length).to.be.equal(0); + const newBalances = await erc20Wrapper.getBalancesAsync(); + expect(newBalances).to.deep.equal(erc20Balances); + }); + it('should throw if dispatching to unregistered proxy', async () => { // Construct metadata for ERC20 proxy const encodedAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address); diff --git a/packages/contracts/test/exchange/internal.ts b/packages/contracts/test/exchange/internal.ts index de381fca3..156e086af 100644 --- a/packages/contracts/test/exchange/internal.ts +++ b/packages/contracts/test/exchange/internal.ts @@ -6,10 +6,7 @@ import * as _ from 'lodash'; import { TestExchangeInternalsContract } from '../../generated_contract_wrappers/test_exchange_internals'; import { artifacts } from '../utils/artifacts'; -import { - getInvalidOpcodeErrorMessageForCallAsync, - getRevertReasonOrErrorMessageForSendTransactionAsync, -} from '../utils/assertions'; +import { getRevertReasonOrErrorMessageForSendTransactionAsync } from '../utils/assertions'; import { chaiSetup } from '../utils/chai_setup'; import { bytes32Values, testCombinatoriallyWithReferenceFuncAsync, uint256Values } from '../utils/combinatorial_utils'; import { constants } from '../utils/constants'; @@ -48,9 +45,9 @@ const overflowErrorForCall = new Error(RevertReason.Uint256Overflow); describe('Exchange core internal functions', () => { let testExchange: TestExchangeInternalsContract; - let invalidOpcodeErrorForCall: Error | undefined; let overflowErrorForSendTransaction: Error | undefined; let divisionByZeroErrorForCall: Error | undefined; + let roundingErrorForCall: Error | undefined; before(async () => { await blockchainLifecycle.startAsync(); @@ -68,12 +65,67 @@ describe('Exchange core internal functions', () => { await getRevertReasonOrErrorMessageForSendTransactionAsync(RevertReason.Uint256Overflow), ); divisionByZeroErrorForCall = new Error(RevertReason.DivisionByZero); - invalidOpcodeErrorForCall = new Error(await getInvalidOpcodeErrorMessageForCallAsync()); + roundingErrorForCall = new Error(RevertReason.RoundingError); }); // Note(albrow): Don't forget to add beforeEach and afterEach calls to reset // the blockchain state for any tests which modify it! - async function referenceGetPartialAmountFloorAsync( + async function referenceIsRoundingErrorFloorAsync( + numerator: BigNumber, + denominator: BigNumber, + target: BigNumber, + ): Promise<boolean> { + if (denominator.eq(0)) { + throw divisionByZeroErrorForCall; + } + if (numerator.eq(0)) { + return false; + } + if (target.eq(0)) { + return false; + } + const product = numerator.mul(target); + const remainder = product.mod(denominator); + const remainderTimes1000 = remainder.mul('1000'); + const isError = remainderTimes1000.gte(product); + if (product.greaterThan(MAX_UINT256)) { + throw overflowErrorForCall; + } + if (remainderTimes1000.greaterThan(MAX_UINT256)) { + throw overflowErrorForCall; + } + return isError; + } + + async function referenceIsRoundingErrorCeilAsync( + numerator: BigNumber, + denominator: BigNumber, + target: BigNumber, + ): Promise<boolean> { + if (denominator.eq(0)) { + throw divisionByZeroErrorForCall; + } + if (numerator.eq(0)) { + return false; + } + if (target.eq(0)) { + return false; + } + const product = numerator.mul(target); + const remainder = product.mod(denominator); + const error = denominator.sub(remainder).mod(denominator); + const errorTimes1000 = error.mul('1000'); + const isError = errorTimes1000.gte(product); + if (product.greaterThan(MAX_UINT256)) { + throw overflowErrorForCall; + } + if (errorTimes1000.greaterThan(MAX_UINT256)) { + throw overflowErrorForCall; + } + return isError; + } + + async function referenceSafeGetPartialAmountFloorAsync( numerator: BigNumber, denominator: BigNumber, target: BigNumber, @@ -81,6 +133,10 @@ describe('Exchange core internal functions', () => { if (denominator.eq(0)) { throw divisionByZeroErrorForCall; } + const isRoundingError = await referenceIsRoundingErrorFloorAsync(numerator, denominator, target); + if (isRoundingError) { + throw roundingErrorForCall; + } const product = numerator.mul(target); if (product.greaterThan(MAX_UINT256)) { throw overflowErrorForCall; @@ -162,19 +218,22 @@ describe('Exchange core internal functions', () => { // in any mathematical operation in either the reference TypeScript // implementation or the Solidity implementation of // calculateFillResults. + const makerAssetFilledAmount = await referenceSafeGetPartialAmountFloorAsync( + takerAssetFilledAmount, + orderTakerAssetAmount, + otherAmount, + ); + const order = makeOrder(otherAmount, orderTakerAssetAmount, otherAmount, otherAmount); + const orderMakerAssetAmount = order.makerAssetAmount; return { - makerAssetFilledAmount: await referenceGetPartialAmountFloorAsync( - takerAssetFilledAmount, - orderTakerAssetAmount, - otherAmount, - ), + makerAssetFilledAmount, takerAssetFilledAmount, - makerFeePaid: await referenceGetPartialAmountFloorAsync( - takerAssetFilledAmount, - orderTakerAssetAmount, + makerFeePaid: await referenceSafeGetPartialAmountFloorAsync( + makerAssetFilledAmount, + orderMakerAssetAmount, otherAmount, ), - takerFeePaid: await referenceGetPartialAmountFloorAsync( + takerFeePaid: await referenceSafeGetPartialAmountFloorAsync( takerAssetFilledAmount, orderTakerAssetAmount, otherAmount, @@ -198,6 +257,20 @@ describe('Exchange core internal functions', () => { }); describe('getPartialAmountFloor', async () => { + async function referenceGetPartialAmountFloorAsync( + numerator: BigNumber, + denominator: BigNumber, + target: BigNumber, + ): Promise<BigNumber> { + if (denominator.eq(0)) { + throw divisionByZeroErrorForCall; + } + const product = numerator.mul(target); + if (product.greaterThan(MAX_UINT256)) { + throw overflowErrorForCall; + } + return product.dividedToIntegerBy(denominator); + } async function testGetPartialAmountFloorAsync( numerator: BigNumber, denominator: BigNumber, @@ -206,7 +279,7 @@ describe('Exchange core internal functions', () => { return testExchange.publicGetPartialAmountFloor.callAsync(numerator, denominator, target); } await testCombinatoriallyWithReferenceFuncAsync( - 'getPartialAmount', + 'getPartialAmountFloor', referenceGetPartialAmountFloorAsync, testGetPartialAmountFloorAsync, [uint256Values, uint256Values, uint256Values], @@ -250,76 +323,80 @@ describe('Exchange core internal functions', () => { ); }); - describe('isRoundingError', async () => { - async function referenceIsRoundingErrorAsync( + describe('safeGetPartialAmountFloor', async () => { + async function testSafeGetPartialAmountFloorAsync( numerator: BigNumber, denominator: BigNumber, target: BigNumber, - ): Promise<boolean> { + ): Promise<BigNumber> { + return testExchange.publicSafeGetPartialAmountFloor.callAsync(numerator, denominator, target); + } + await testCombinatoriallyWithReferenceFuncAsync( + 'safeGetPartialAmountFloor', + referenceSafeGetPartialAmountFloorAsync, + testSafeGetPartialAmountFloorAsync, + [uint256Values, uint256Values, uint256Values], + ); + }); + + describe('safeGetPartialAmountCeil', async () => { + async function referenceSafeGetPartialAmountCeilAsync( + numerator: BigNumber, + denominator: BigNumber, + target: BigNumber, + ): Promise<BigNumber> { if (denominator.eq(0)) { throw divisionByZeroErrorForCall; } - if (numerator.eq(0)) { - return false; - } - if (target.eq(0)) { - return false; + const isRoundingError = await referenceIsRoundingErrorCeilAsync(numerator, denominator, target); + if (isRoundingError) { + throw roundingErrorForCall; } const product = numerator.mul(target); - const remainder = product.mod(denominator); - const remainderTimes1000 = remainder.mul('1000'); - const isError = remainderTimes1000.gt(product); - if (product.greaterThan(MAX_UINT256)) { + const offset = product.add(denominator.sub(1)); + if (offset.greaterThan(MAX_UINT256)) { throw overflowErrorForCall; } - if (remainderTimes1000.greaterThan(MAX_UINT256)) { - throw overflowErrorForCall; + const result = offset.dividedToIntegerBy(denominator); + if (product.mod(denominator).eq(0)) { + expect(result.mul(denominator)).to.be.bignumber.eq(product); + } else { + expect(result.mul(denominator)).to.be.bignumber.gt(product); } - return isError; + return result; } - async function testIsRoundingErrorAsync( + async function testSafeGetPartialAmountCeilAsync( numerator: BigNumber, denominator: BigNumber, target: BigNumber, - ): Promise<boolean> { - return testExchange.publicIsRoundingErrorFloor.callAsync(numerator, denominator, target); + ): Promise<BigNumber> { + return testExchange.publicSafeGetPartialAmountCeil.callAsync(numerator, denominator, target); } await testCombinatoriallyWithReferenceFuncAsync( - 'isRoundingError', - referenceIsRoundingErrorAsync, - testIsRoundingErrorAsync, + 'safeGetPartialAmountCeil', + referenceSafeGetPartialAmountCeilAsync, + testSafeGetPartialAmountCeilAsync, [uint256Values, uint256Values, uint256Values], ); }); - describe('isRoundingErrorCeil', async () => { - async function referenceIsRoundingErrorAsync( + describe('isRoundingErrorFloor', async () => { + async function testIsRoundingErrorFloorAsync( numerator: BigNumber, denominator: BigNumber, target: BigNumber, ): Promise<boolean> { - if (denominator.eq(0)) { - throw divisionByZeroErrorForCall; - } - if (numerator.eq(0)) { - return false; - } - if (target.eq(0)) { - return false; - } - const product = numerator.mul(target); - const remainder = product.mod(denominator); - const error = denominator.sub(remainder).mod(denominator); - const errorTimes1000 = error.mul('1000'); - const isError = errorTimes1000.gt(product); - if (product.greaterThan(MAX_UINT256)) { - throw overflowErrorForCall; - } - if (errorTimes1000.greaterThan(MAX_UINT256)) { - throw overflowErrorForCall; - } - return isError; + return testExchange.publicIsRoundingErrorFloor.callAsync(numerator, denominator, target); } + await testCombinatoriallyWithReferenceFuncAsync( + 'isRoundingErrorFloor', + referenceIsRoundingErrorFloorAsync, + testIsRoundingErrorFloorAsync, + [uint256Values, uint256Values, uint256Values], + ); + }); + + describe('isRoundingErrorCeil', async () => { async function testIsRoundingErrorCeilAsync( numerator: BigNumber, denominator: BigNumber, @@ -329,7 +406,7 @@ describe('Exchange core internal functions', () => { } await testCombinatoriallyWithReferenceFuncAsync( 'isRoundingErrorCeil', - referenceIsRoundingErrorAsync, + referenceIsRoundingErrorCeilAsync, testIsRoundingErrorCeilAsync, [uint256Values, uint256Values, uint256Values], ); diff --git a/packages/contracts/test/exchange/match_orders.ts b/packages/contracts/test/exchange/match_orders.ts index 8732e20ba..c6e7b494f 100644 --- a/packages/contracts/test/exchange/match_orders.ts +++ b/packages/contracts/test/exchange/match_orders.ts @@ -3,6 +3,7 @@ import { assetDataUtils } from '@0xproject/order-utils'; import { RevertReason } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import * as chai from 'chai'; import * as _ from 'lodash'; import { DummyERC20TokenContract } from '../../generated_contract_wrappers/dummy_erc20_token'; @@ -11,8 +12,10 @@ import { ERC20ProxyContract } from '../../generated_contract_wrappers/erc20_prox import { ERC721ProxyContract } from '../../generated_contract_wrappers/erc721_proxy'; import { ExchangeContract } from '../../generated_contract_wrappers/exchange'; import { ReentrantERC20TokenContract } from '../../generated_contract_wrappers/reentrant_erc20_token'; +import { TestExchangeInternalsContract } from '../../generated_contract_wrappers/test_exchange_internals'; import { artifacts } from '../utils/artifacts'; import { expectTransactionFailedAsync } from '../utils/assertions'; +import { chaiSetup } from '../utils/chai_setup'; import { constants } from '../utils/constants'; import { ERC20Wrapper } from '../utils/erc20_wrapper'; import { ERC721Wrapper } from '../utils/erc721_wrapper'; @@ -23,6 +26,8 @@ import { ERC20BalancesByOwner, ERC721TokenIdsByOwner } from '../utils/types'; import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); +chaiSetup.configure(); +const expect = chai.expect; describe('matchOrders', () => { let makerAddressLeft: string; @@ -58,6 +63,8 @@ describe('matchOrders', () => { let matchOrderTester: MatchOrderTester; + let testExchange: TestExchangeInternalsContract; + before(async () => { await blockchainLifecycle.startAsync(); }); @@ -160,6 +167,11 @@ describe('matchOrders', () => { orderFactoryRight = new OrderFactory(privateKeyRight, defaultOrderParamsRight); // Set match order tester matchOrderTester = new MatchOrderTester(exchangeWrapper, erc20Wrapper, erc721Wrapper, zrxToken.address); + testExchange = await TestExchangeInternalsContract.deployFrom0xArtifactAsync( + artifacts.TestExchangeInternals, + provider, + txDefaults, + ); }); beforeEach(async () => { await blockchainLifecycle.startAsync(); @@ -173,39 +185,170 @@ describe('matchOrders', () => { erc721TokenIdsByOwner = await erc721Wrapper.getBalancesAsync(); }); - it('Should give right maker a better price when correct price is not integral', async () => { + it('Should transfer correct amounts when right order is fully filled and values pass isRoundingErrorFloor but fail isRoundingErrorCeil', async () => { + // Create orders to match + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + makerAddress: makerAddressLeft, + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(17), 0), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(98), 0), + feeRecipientAddress: feeRecipientAddressLeft, + }); + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + makerAddress: makerAddressRight, + makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(75), 0), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0), + feeRecipientAddress: feeRecipientAddressRight, + }); + // Assert is rounding error ceil & not rounding error floor + // These assertions are taken from MixinMatchOrders::calculateMatchedFillResults + // The rounding error is derived computating how much the left maker will sell. + const numerator = signedOrderLeft.makerAssetAmount; + const denominator = signedOrderLeft.takerAssetAmount; + const target = signedOrderRight.makerAssetAmount; + const isRoundingErrorCeil = await testExchange.publicIsRoundingErrorCeil.callAsync( + numerator, + denominator, + target, + ); + expect(isRoundingErrorCeil).to.be.true(); + const isRoundingErrorFloor = await testExchange.publicIsRoundingErrorFloor.callAsync( + numerator, + denominator, + target, + ); + expect(isRoundingErrorFloor).to.be.false(); + // Match signedOrderLeft with signedOrderRight + // Note that the left maker received a slightly better sell price. + // This is intentional; see note in MixinMatchOrders.calculateMatchedFillResults. + // Because the left maker received a slightly more favorable sell price, the fee + // paid by the left taker is slightly higher than that paid by the left maker. + // Fees can be thought of as a tax paid by the seller, derived from the sale price. + const expectedTransferAmounts = { + // Left Maker + amountSoldByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0), + amountBoughtByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(75), 0), + feePaidByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber('76.4705882352941176'), 16), // 76.47% + // Right Maker + amountSoldByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(75), 0), + amountBoughtByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0), + feePaidByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100% + // Taker + amountReceivedByTaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), 0), + feePaidByTakerLeft: Web3Wrapper.toBaseUnitAmount(new BigNumber('76.5306122448979591'), 16), // 76.53% + feePaidByTakerRight: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100% + }; + await matchOrderTester.matchOrdersAndAssertEffectsAsync( + signedOrderLeft, + signedOrderRight, + takerAddress, + erc20BalancesByOwner, + erc721TokenIdsByOwner, + expectedTransferAmounts, + ); + }); + + it('Should transfer correct amounts when left order is fully filled and values pass isRoundingErrorCeil but fail isRoundingErrorFloor', async () => { // Create orders to match const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2000), 0), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1001), 0), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(15), 0), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(90), 0), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 0), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(3000), 0), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(97), 0), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(14), 0), + feeRecipientAddress: feeRecipientAddressRight, + }); + // Assert is rounding error floor & not rounding error ceil + // These assertions are taken from MixinMatchOrders::calculateMatchedFillResults + // The rounding error is derived computating how much the right maker will buy. + const numerator = signedOrderRight.takerAssetAmount; + const denominator = signedOrderRight.makerAssetAmount; + const target = signedOrderLeft.takerAssetAmount; + const isRoundingErrorFloor = await testExchange.publicIsRoundingErrorFloor.callAsync( + numerator, + denominator, + target, + ); + expect(isRoundingErrorFloor).to.be.true(); + const isRoundingErrorCeil = await testExchange.publicIsRoundingErrorCeil.callAsync( + numerator, + denominator, + target, + ); + expect(isRoundingErrorCeil).to.be.false(); + // Match signedOrderLeft with signedOrderRight + // Note that the right maker received a slightly better purchase price. + // This is intentional; see note in MixinMatchOrders.calculateMatchedFillResults. + // Because the right maker received a slightly more favorable buy price, the fee + // paid by the right taker is slightly higher than that paid by the right maker. + // Fees can be thought of as a tax paid by the seller, derived from the sale price. + const expectedTransferAmounts = { + // Left Maker + amountSoldByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(15), 0), + amountBoughtByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(90), 0), + feePaidByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100% + // Right Maker + amountSoldByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(90), 0), + amountBoughtByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0), + feePaidByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber('92.7835051546391752'), 16), // 92.78% + // Taker + amountReceivedByTaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 0), + feePaidByTakerLeft: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100% + feePaidByTakerRight: Web3Wrapper.toBaseUnitAmount(new BigNumber('92.8571428571428571'), 16), // 92.85% + }; + await matchOrderTester.matchOrdersAndAssertEffectsAsync( + signedOrderLeft, + signedOrderRight, + takerAddress, + erc20BalancesByOwner, + erc721TokenIdsByOwner, + expectedTransferAmounts, + ); + }); + + it('Should give right maker a better buy price when rounding', async () => { + // Create orders to match + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + makerAddress: makerAddressLeft, + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(16), 0), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(22), 0), + feeRecipientAddress: feeRecipientAddressLeft, + }); + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + makerAddress: makerAddressRight, + makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(83), 0), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(49), 0), feeRecipientAddress: feeRecipientAddressRight, }); // Note: + // The correct price buy price for the right maker would yield (49/83) * 22 = 12.988 units + // of the left maker asset. This gets rounded up to 13, giving the right maker a better price. + // Note: // The maker/taker fee percentage paid on the right order differs because - // they received different sale prices. Similarly, the right maker pays a - // slightly higher lower than the right taker. + // they received different sale prices. The right maker pays a + // fee slightly lower than the right taker. const expectedTransferAmounts = { // Left Maker - amountSoldByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(2000), 0), - amountBoughtByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(1001), 0), + amountSoldByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(16), 0), + amountBoughtByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(22), 0), feePaidByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100% // Right Maker - amountSoldByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(1001), 0), - amountBoughtByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(301), 0), - feePaidByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(10.01), 16), // 10.01% + amountSoldByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(22), 0), + amountBoughtByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0), + feePaidByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber('26.5060240963855421'), 16), // 26.506% // Taker - amountReceivedByTaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(1699), 0), + amountReceivedByTaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(3), 0), feePaidByTakerLeft: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100% - feePaidByTakerRight: Web3Wrapper.toBaseUnitAmount(new BigNumber('10.0333333333333333'), 16), // 10.03% + feePaidByTakerRight: Web3Wrapper.toBaseUnitAmount(new BigNumber('26.5306122448979591'), 16), // 26.531% }; // Match signedOrderLeft with signedOrderRight await matchOrderTester.matchOrdersAndAssertEffectsAsync( @@ -218,7 +361,7 @@ describe('matchOrders', () => { ); }); - it('Should give left maker a better price when correct price is not integral', async () => { + it('Should give left maker a better sell price when rounding', async () => { // Create orders to match const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, @@ -236,7 +379,8 @@ describe('matchOrders', () => { }); // Note: // The maker/taker fee percentage paid on the left order differs because - // they received different sale prices. + // they received different sale prices. The left maker pays a fee + // slightly lower than the left taker. const expectedTransferAmounts = { // Left Maker amountSoldByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(11), 0), @@ -262,42 +406,87 @@ describe('matchOrders', () => { ); }); - it('Should transfer correct amounts when right order fill amount deviates from amount derived by `Exchange.fillOrder`', async () => { + it('Should give right maker and right taker a favorable fee price when rounding', async () => { // Create orders to match const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 0), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(3), 0), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(16), 0), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(22), 0), feeRecipientAddress: feeRecipientAddressLeft, }); const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), - makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(4), 0), - takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 0), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(83), 0), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(49), 0), feeRecipientAddress: feeRecipientAddressRight, + makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 0), + takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 0), }); - // TODO: These values will change after implementation of rounding up has been merged + // Note: + // The maker/taker fee percentage paid on the right order differs because + // they received different sale prices. The right maker pays a + // fee slightly lower than the right taker. const expectedTransferAmounts = { // Left Maker - amountSoldByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 0), - amountBoughtByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(3), 0), + amountSoldByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(16), 0), + amountBoughtByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(22), 0), feePaidByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100% // Right Maker - // Note: - // For order [4,2] valid fill amounts through `Exchange.fillOrder` would be [2, 1] or [4, 2] - // In this case we have fill amounts of [3, 1] which is attainable through - // `Exchange.matchOrders` but not `Exchange.fillOrder` - // Note: - // The right maker fee differs from the right taker fee because their exchange rate differs. - // The right maker always receives the better exchange and fee price. - amountSoldByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(3), 0), - amountBoughtByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 0), - feePaidByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(75), 16), // 75% + amountSoldByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(22), 0), + amountBoughtByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0), + feePaidByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(2650), 0), // 2650.6 rounded down tro 2650 // Taker - amountReceivedByTaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(8), 0), + amountReceivedByTaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(3), 0), feePaidByTakerLeft: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100% + feePaidByTakerRight: Web3Wrapper.toBaseUnitAmount(new BigNumber(2653), 0), // 2653.1 rounded down to 2653 + }; + // Match signedOrderLeft with signedOrderRight + await matchOrderTester.matchOrdersAndAssertEffectsAsync( + signedOrderLeft, + signedOrderRight, + takerAddress, + erc20BalancesByOwner, + erc721TokenIdsByOwner, + expectedTransferAmounts, + ); + }); + + it('Should give left maker and left taker a favorable fee price when rounding', async () => { + // Create orders to match + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + makerAddress: makerAddressLeft, + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(12), 0), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(97), 0), + feeRecipientAddress: feeRecipientAddressLeft, + makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 0), + takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 0), + }); + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + makerAddress: makerAddressRight, + makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(89), 0), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 0), + feeRecipientAddress: feeRecipientAddressRight, + }); + // Note: + // The maker/taker fee percentage paid on the left order differs because + // they received different sale prices. The left maker pays a + // fee slightly lower than the left taker. + const expectedTransferAmounts = { + // Left Maker + amountSoldByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(11), 0), + amountBoughtByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(89), 0), + feePaidByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(9166), 0), // 9166.6 rounded down to 9166 + // Right Maker + amountSoldByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(89), 0), + amountBoughtByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 0), + feePaidByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100% + // Taker + amountReceivedByTaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 0), + feePaidByTakerLeft: Web3Wrapper.toBaseUnitAmount(new BigNumber(9175), 0), // 9175.2 rounded down to 9175 feePaidByTakerRight: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100% }; // Match signedOrderLeft with signedOrderRight @@ -311,6 +500,61 @@ describe('matchOrders', () => { ); }); + it('Should transfer correct amounts when right order fill amount deviates from amount derived by `Exchange.fillOrder`', async () => { + // Create orders to match + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ + makerAddress: makerAddressLeft, + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), 0), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1005), 0), + feeRecipientAddress: feeRecipientAddressLeft, + }); + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ + makerAddress: makerAddressRight, + makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), + takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2126), 0), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1063), 0), + feeRecipientAddress: feeRecipientAddressRight, + }); + const expectedTransferAmounts = { + // Left Maker + amountSoldByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), 0), + amountBoughtByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(1005), 0), + feePaidByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100% + // Right Maker + // Notes: + // i. + // The left order is fully filled by the right order, so the right maker must sell 1005 units of their asset to the left maker. + // By selling 1005 units, the right maker should theoretically receive 502.5 units of the left maker's asset. + // Since the transfer amount must be an integer, this value must be rounded down to 502 or up to 503. + // ii. + // If the right order were filled via `Exchange.fillOrder` the respective fill amounts would be [1004, 502] or [1006, 503]. + // It follows that we cannot trigger a sale of 1005 units of the right maker's asset through `Exchange.fillOrder`. + // iii. + // For an optimal match, the algorithm must choose either [1005, 502] or [1005, 503] as fill amounts for the right order. + // The algorithm favors the right maker when the exchange rate must be rounded, so the final fill for the right order is [1005, 503]. + // iv. + // The right maker fee differs from the right taker fee because their exchange rate differs. + // The right maker always receives the better exchange and fee price. + amountSoldByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(1005), 0), + amountBoughtByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(503), 0), + feePaidByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber('47.2718720602069614'), 16), // 47.27% + // Taker + amountReceivedByTaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(497), 0), + feePaidByTakerLeft: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100% + feePaidByTakerRight: Web3Wrapper.toBaseUnitAmount(new BigNumber('47.3189087488240827'), 16), // 47.31% + }; + // Match signedOrderLeft with signedOrderRight + await matchOrderTester.matchOrdersAndAssertEffectsAsync( + signedOrderLeft, + signedOrderRight, + takerAddress, + erc20BalancesByOwner, + erc721TokenIdsByOwner, + expectedTransferAmounts, + ); + }); + const reentrancyTest = (functionNames: string[]) => { _.forEach(functionNames, async (functionName: string, functionId: number) => { const description = `should not allow matchOrders to reenter the Exchange contract via ${functionName}`; diff --git a/packages/contracts/test/exchange/signature_validator.ts b/packages/contracts/test/exchange/signature_validator.ts index da2febfd8..5cc62e777 100644 --- a/packages/contracts/test/exchange/signature_validator.ts +++ b/packages/contracts/test/exchange/signature_validator.ts @@ -14,7 +14,7 @@ import { ValidatorContract } from '../../generated_contract_wrappers/validator'; import { WalletContract } from '../../generated_contract_wrappers/wallet'; import { addressUtils } from '../utils/address_utils'; import { artifacts } from '../utils/artifacts'; -import { expectContractCallFailed, expectContractCallFailedWithoutReasonAsync } from '../utils/assertions'; +import { expectContractCallFailedAsync } from '../utils/assertions'; import { chaiSetup } from '../utils/chai_setup'; import { constants } from '../utils/constants'; import { LogDecoder } from '../utils/log_decoder'; @@ -119,7 +119,7 @@ describe('MixinSignatureValidator', () => { it('should revert when signature is empty', async () => { const emptySignature = '0x'; const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); - return expectContractCallFailed( + return expectContractCallFailedAsync( signatureValidator.publicIsValidSignature.callAsync( orderHashHex, signedOrder.makerAddress, @@ -133,7 +133,7 @@ describe('MixinSignatureValidator', () => { const unsupportedSignatureType = SignatureType.NSignatureTypes; const unsupportedSignatureHex = '0x' + Buffer.from([unsupportedSignatureType]).toString('hex'); const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); - return expectContractCallFailed( + return expectContractCallFailedAsync( signatureValidator.publicIsValidSignature.callAsync( orderHashHex, signedOrder.makerAddress, @@ -146,7 +146,7 @@ describe('MixinSignatureValidator', () => { it('should revert when SignatureType=Illegal', async () => { const unsupportedSignatureHex = '0x' + Buffer.from([SignatureType.Illegal]).toString('hex'); const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); - return expectContractCallFailed( + return expectContractCallFailedAsync( signatureValidator.publicIsValidSignature.callAsync( orderHashHex, signedOrder.makerAddress, @@ -173,7 +173,7 @@ describe('MixinSignatureValidator', () => { const signatureBuffer = Buffer.concat([fillerData, signatureType]); const signatureHex = ethUtil.bufferToHex(signatureBuffer); const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); - return expectContractCallFailed( + return expectContractCallFailedAsync( signatureValidator.publicIsValidSignature.callAsync( orderHashHex, signedOrder.makerAddress, @@ -339,7 +339,7 @@ describe('MixinSignatureValidator', () => { ethUtil.toBuffer(`0x${SignatureType.Wallet}`), ]); const signatureHex = ethUtil.bufferToHex(signature); - await expectContractCallFailed( + await expectContractCallFailedAsync( signatureValidator.publicIsValidSignature.callAsync( orderHashHex, maliciousWallet.address, @@ -385,7 +385,7 @@ describe('MixinSignatureValidator', () => { const signature = Buffer.concat([validatorAddress, signatureType]); const signatureHex = ethUtil.bufferToHex(signature); const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); - await expectContractCallFailed( + await expectContractCallFailedAsync( signatureValidator.publicIsValidSignature.callAsync(orderHashHex, signerAddress, signatureHex), RevertReason.ValidatorError, ); diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts index 1c497a226..13640a761 100644 --- a/packages/contracts/test/libraries/lib_bytes.ts +++ b/packages/contracts/test/libraries/lib_bytes.ts @@ -9,7 +9,7 @@ import * as _ from 'lodash'; import { TestLibBytesContract } from '../../generated_contract_wrappers/test_lib_bytes'; import { artifacts } from '../utils/artifacts'; -import { expectContractCallFailed } from '../utils/assertions'; +import { expectContractCallFailedAsync } from '../utils/assertions'; import { chaiSetup } from '../utils/chai_setup'; import { constants } from '../utils/constants'; import { typeEncodingUtils } from '../utils/type_encoding_utils'; @@ -41,6 +41,8 @@ describe('LibBytes', () => { const testBytes32B = '0x534877abd8443578526845cdfef020047528759477fedef87346527659aced32'; const testUint256 = new BigNumber(testBytes32, 16); const testUint256B = new BigNumber(testBytes32B, 16); + const testBytes4 = '0xabcdef12'; + const testByte = '0xab'; let shortData: string; let shortTestBytes: string; let shortTestBytesAsBuffer: Buffer; @@ -101,34 +103,47 @@ describe('LibBytes', () => { describe('popLastByte', () => { it('should revert if length is 0', async () => { - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicPopLastByte.callAsync(constants.NULL_BYTES), RevertReason.LibBytesGreaterThanZeroLengthRequired, ); }); - it('should pop the last byte from the input and return it', async () => { + it('should pop the last byte from the input and return it when array holds more than 1 byte', async () => { const [newBytes, poppedByte] = await libBytes.publicPopLastByte.callAsync(byteArrayLongerThan32Bytes); const expectedNewBytes = byteArrayLongerThan32Bytes.slice(0, -2); const expectedPoppedByte = `0x${byteArrayLongerThan32Bytes.slice(-2)}`; expect(newBytes).to.equal(expectedNewBytes); expect(poppedByte).to.equal(expectedPoppedByte); }); + it('should pop the last byte from the input and return it when array is exactly 1 byte', async () => { + const [newBytes, poppedByte] = await libBytes.publicPopLastByte.callAsync(testByte); + const expectedNewBytes = '0x'; + expect(newBytes).to.equal(expectedNewBytes); + return expect(poppedByte).to.be.equal(testByte); + }); }); describe('popLast20Bytes', () => { it('should revert if length is less than 20', async () => { - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicPopLast20Bytes.callAsync(byteArrayShorterThan20Bytes), RevertReason.LibBytesGreaterOrEqualTo20LengthRequired, ); }); - it('should pop the last 20 bytes from the input and return it', async () => { + it('should pop the last 20 bytes from the input and return it when array holds more than 20 bytes', async () => { const [newBytes, poppedAddress] = await libBytes.publicPopLast20Bytes.callAsync(byteArrayLongerThan32Bytes); const expectedNewBytes = byteArrayLongerThan32Bytes.slice(0, -40); const expectedPoppedAddress = `0x${byteArrayLongerThan32Bytes.slice(-40)}`; expect(newBytes).to.equal(expectedNewBytes); expect(poppedAddress).to.equal(expectedPoppedAddress); }); + it('should pop the last 20 bytes from the input and return it when array is exactly 20 bytes', async () => { + const [newBytes, poppedAddress] = await libBytes.publicPopLast20Bytes.callAsync(testAddress); + const expectedNewBytes = '0x'; + const expectedPoppedAddress = testAddress; + expect(newBytes).to.equal(expectedNewBytes); + expect(poppedAddress).to.equal(expectedPoppedAddress); + }); }); describe('equals', () => { @@ -185,7 +200,7 @@ describe('LibBytes', () => { describe('deepCopyBytes', () => { it('should revert if dest is shorter than source', async () => { - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicDeepCopyBytes.callAsync(byteArrayShorterThan32Bytes, byteArrayLongerThan32Bytes), RevertReason.LibBytesGreaterOrEqualToSourceBytesLengthRequired, ); @@ -238,7 +253,7 @@ describe('LibBytes', () => { it('should fail if the byte array is too short to hold an address', async () => { const shortByteArray = '0xabcdef'; const offset = new BigNumber(0); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicReadAddress.callAsync(shortByteArray, offset), RevertReason.LibBytesGreaterOrEqualTo20LengthRequired, ); @@ -246,7 +261,7 @@ describe('LibBytes', () => { it('should fail if the length between the offset and end of the byte array is too short to hold an address', async () => { const byteArray = testAddress; const badOffset = new BigNumber(ethUtil.toBuffer(byteArray).byteLength); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicReadAddress.callAsync(byteArray, badOffset), RevertReason.LibBytesGreaterOrEqualTo20LengthRequired, ); @@ -282,7 +297,7 @@ describe('LibBytes', () => { }); it('should fail if the byte array is too short to hold an address', async () => { const offset = new BigNumber(0); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicWriteAddress.callAsync(byteArrayShorterThan20Bytes, offset, testAddress), RevertReason.LibBytesGreaterOrEqualTo20LengthRequired, ); @@ -290,7 +305,7 @@ describe('LibBytes', () => { it('should fail if the length between the offset and end of the byte array is too short to hold an address', async () => { const byteArray = byteArrayLongerThan32Bytes; const badOffset = new BigNumber(ethUtil.toBuffer(byteArray).byteLength); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicWriteAddress.callAsync(byteArray, badOffset, testAddress), RevertReason.LibBytesGreaterOrEqualTo20LengthRequired, ); @@ -303,7 +318,7 @@ describe('LibBytes', () => { const bytes32 = await libBytes.publicReadBytes32.callAsync(testBytes32, testBytes32Offset); return expect(bytes32).to.be.equal(testBytes32); }); - it('should successfully read bytes32 when it is offset in the array)', async () => { + it('should successfully read bytes32 when it is offset in the array', async () => { const bytes32ByteArrayBuffer = ethUtil.toBuffer(testBytes32); const prefixByteArrayBuffer = ethUtil.toBuffer('0xabcdef'); const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, bytes32ByteArrayBuffer]); @@ -314,14 +329,14 @@ describe('LibBytes', () => { }); it('should fail if the byte array is too short to hold a bytes32', async () => { const offset = new BigNumber(0); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicReadBytes32.callAsync(byteArrayShorterThan32Bytes, offset), RevertReason.LibBytesGreaterOrEqualTo32LengthRequired, ); }); it('should fail if the length between the offset and end of the byte array is too short to hold a bytes32', async () => { const badOffset = new BigNumber(ethUtil.toBuffer(testBytes32).byteLength); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicReadBytes32.callAsync(testBytes32, badOffset), RevertReason.LibBytesGreaterOrEqualTo32LengthRequired, ); @@ -357,7 +372,7 @@ describe('LibBytes', () => { }); it('should fail if the byte array is too short to hold a bytes32', async () => { const offset = new BigNumber(0); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicWriteBytes32.callAsync(byteArrayShorterThan32Bytes, offset, testBytes32), RevertReason.LibBytesGreaterOrEqualTo32LengthRequired, ); @@ -365,7 +380,7 @@ describe('LibBytes', () => { it('should fail if the length between the offset and end of the byte array is too short to hold a bytes32', async () => { const byteArray = byteArrayLongerThan32Bytes; const badOffset = new BigNumber(ethUtil.toBuffer(byteArray).byteLength); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicWriteBytes32.callAsync(byteArray, badOffset, testBytes32), RevertReason.LibBytesGreaterOrEqualTo32LengthRequired, ); @@ -393,7 +408,7 @@ describe('LibBytes', () => { }); it('should fail if the byte array is too short to hold a uint256', async () => { const offset = new BigNumber(0); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicReadUint256.callAsync(byteArrayShorterThan32Bytes, offset), RevertReason.LibBytesGreaterOrEqualTo32LengthRequired, ); @@ -403,7 +418,7 @@ describe('LibBytes', () => { const testUint256AsBuffer = ethUtil.toBuffer(formattedTestUint256); const byteArray = ethUtil.bufferToHex(testUint256AsBuffer); const badOffset = new BigNumber(testUint256AsBuffer.byteLength); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicReadUint256.callAsync(byteArray, badOffset), RevertReason.LibBytesGreaterOrEqualTo32LengthRequired, ); @@ -443,7 +458,7 @@ describe('LibBytes', () => { }); it('should fail if the byte array is too short to hold a uint256', async () => { const offset = new BigNumber(0); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicWriteUint256.callAsync(byteArrayShorterThan32Bytes, offset, testUint256), RevertReason.LibBytesGreaterOrEqualTo32LengthRequired, ); @@ -451,7 +466,7 @@ describe('LibBytes', () => { it('should fail if the length between the offset and end of the byte array is too short to hold a uint256', async () => { const byteArray = byteArrayLongerThan32Bytes; const badOffset = new BigNumber(ethUtil.toBuffer(byteArray).byteLength); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicWriteUint256.callAsync(byteArray, badOffset, testUint256), RevertReason.LibBytesGreaterOrEqualTo32LengthRequired, ); @@ -462,8 +477,9 @@ describe('LibBytes', () => { // AssertionError: expected promise to be rejected with an error including 'revert' but it was fulfilled with '0x08c379a0' it('should revert if byte array has a length < 4', async () => { const byteArrayLessThan4Bytes = '0x010101'; - return expectContractCallFailed( - libBytes.publicReadBytes4.callAsync(byteArrayLessThan4Bytes, new BigNumber(0)), + const offset = new BigNumber(0); + return expectContractCallFailedAsync( + libBytes.publicReadBytes4.callAsync(byteArrayLessThan4Bytes, offset), RevertReason.LibBytesGreaterOrEqualTo4LengthRequired, ); }); @@ -472,6 +488,27 @@ describe('LibBytes', () => { const expectedFirst4Bytes = byteArrayLongerThan32Bytes.slice(0, 10); expect(first4Bytes).to.equal(expectedFirst4Bytes); }); + it('should successfully read bytes4 when the bytes4 takes up the whole array', async () => { + const testBytes4Offset = new BigNumber(0); + const bytes4 = await libBytes.publicReadBytes4.callAsync(testBytes4, testBytes4Offset); + return expect(bytes4).to.be.equal(testBytes4); + }); + it('should successfully read bytes4 when it is offset in the array', async () => { + const bytes4ByteArrayBuffer = ethUtil.toBuffer(testBytes4); + const prefixByteArrayBuffer = ethUtil.toBuffer('0xabcdef'); + const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, bytes4ByteArrayBuffer]); + const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer); + const testBytes4Offset = new BigNumber(prefixByteArrayBuffer.byteLength); + const bytes4 = await libBytes.publicReadBytes4.callAsync(combinedByteArray, testBytes4Offset); + return expect(bytes4).to.be.equal(testBytes4); + }); + it('should fail if the length between the offset and end of the byte array is too short to hold a bytes4', async () => { + const badOffset = new BigNumber(ethUtil.toBuffer(testBytes4).byteLength); + return expectContractCallFailedAsync( + libBytes.publicReadBytes4.callAsync(testBytes4, badOffset), + RevertReason.LibBytesGreaterOrEqualTo4LengthRequired, + ); + }); }); describe('readBytesWithLength', () => { @@ -517,28 +554,28 @@ describe('LibBytes', () => { it('should fail if the byte array is too short to hold the length of a nested byte array', async () => { // The length of the nested array is 32 bytes. By storing less than 32 bytes, a length cannot be read. const offset = new BigNumber(0); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicReadBytesWithLength.callAsync(byteArrayShorterThan32Bytes, offset), RevertReason.LibBytesGreaterOrEqualTo32LengthRequired, ); }); it('should fail if we store a nested byte array length, without a nested byte array', async () => { const offset = new BigNumber(0); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicReadBytesWithLength.callAsync(testBytes32, offset), RevertReason.LibBytesGreaterOrEqualToNestedBytesLengthRequired, ); }); it('should fail if the length between the offset and end of the byte array is too short to hold the length of a nested byte array', async () => { const badOffset = new BigNumber(ethUtil.toBuffer(byteArrayShorterThan32Bytes).byteLength); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicReadBytesWithLength.callAsync(byteArrayShorterThan32Bytes, badOffset), RevertReason.LibBytesGreaterOrEqualTo32LengthRequired, ); }); it('should fail if the length between the offset and end of the byte array is too short to hold the nested byte array', async () => { const badOffset = new BigNumber(ethUtil.toBuffer(testBytes32).byteLength); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicReadBytesWithLength.callAsync(testBytes32, badOffset), RevertReason.LibBytesGreaterOrEqualTo32LengthRequired, ); @@ -546,7 +583,7 @@ describe('LibBytes', () => { }); describe('writeBytesWithLength', () => { - it('should successfully write short, nested array of bytes when it takes up the whole array)', async () => { + it('should successfully write short, nested array of bytes when it takes up the whole array', async () => { const testBytesOffset = new BigNumber(0); const emptyByteArray = ethUtil.bufferToHex(new Buffer(shortTestBytesAsBuffer.byteLength)); const bytesWritten = await libBytes.publicWriteBytesWithLength.callAsync( @@ -650,15 +687,15 @@ describe('LibBytes', () => { it('should fail if the byte array is too short to hold the length of a nested byte array', async () => { const offset = new BigNumber(0); const emptyByteArray = ethUtil.bufferToHex(new Buffer(1)); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicWriteBytesWithLength.callAsync(emptyByteArray, offset, longData), RevertReason.LibBytesGreaterOrEqualToNestedBytesLengthRequired, ); }); - it('should fail if the length between the offset and end of the byte array is too short to hold the length of a nested byte array)', async () => { + it('should fail if the length between the offset and end of the byte array is too short to hold the length of a nested byte array', async () => { const emptyByteArray = ethUtil.bufferToHex(new Buffer(shortTestBytesAsBuffer.byteLength)); const badOffset = new BigNumber(ethUtil.toBuffer(shortTestBytesAsBuffer).byteLength); - return expectContractCallFailed( + return expectContractCallFailedAsync( libBytes.publicWriteBytesWithLength.callAsync(emptyByteArray, badOffset, shortData), RevertReason.LibBytesGreaterOrEqualToNestedBytesLengthRequired, ); diff --git a/packages/contracts/test/multisig/asset_proxy_owner.ts b/packages/contracts/test/multisig/asset_proxy_owner.ts index 9515941ff..bb2b3b1a3 100644 --- a/packages/contracts/test/multisig/asset_proxy_owner.ts +++ b/packages/contracts/test/multisig/asset_proxy_owner.ts @@ -1,4 +1,5 @@ import { BlockchainLifecycle } from '@0xproject/dev-utils'; +import { RevertReason } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; import { LogWithDecodedArgs } from 'ethereum-types'; @@ -14,9 +15,11 @@ import { MixinAuthorizableContract } from '../../generated_contract_wrappers/mix import { TestAssetProxyOwnerContract } from '../../generated_contract_wrappers/test_asset_proxy_owner'; import { artifacts } from '../utils/artifacts'; import { - expectContractCallFailedWithoutReasonAsync, - expectContractCreationFailedWithoutReason, + expectContractCallFailedAsync, + expectContractCreationFailedAsync, + expectTransactionFailedAsync, expectTransactionFailedWithoutReasonAsync, + sendTransactionResult, } from '../utils/assertions'; import { increaseTimeAndMineBlockAsync } from '../utils/block_timestamp'; import { chaiSetup } from '../utils/chai_setup'; @@ -109,8 +112,8 @@ describe('AssetProxyOwner', () => { }); it('should throw if a null address is included in assetProxyContracts', async () => { const assetProxyContractAddresses = [erc20Proxy.address, constants.NULL_ADDRESS]; - return expectContractCreationFailedWithoutReason( - AssetProxyOwnerContract.deployFrom0xArtifactAsync( + return expectContractCreationFailedAsync( + (AssetProxyOwnerContract.deployFrom0xArtifactAsync( artifacts.AssetProxyOwner, provider, txDefaults, @@ -118,7 +121,8 @@ describe('AssetProxyOwner', () => { assetProxyContractAddresses, REQUIRED_APPROVALS, SECONDS_TIME_LOCKED, - ), + ) as any) as sendTransactionResult, + RevertReason.InvalidAssetProxy, ); }); }); @@ -148,25 +152,6 @@ describe('AssetProxyOwner', () => { }); }); - describe('readBytes4', () => { - it('should revert if byte array has a length < 4', async () => { - const byteArrayLessThan4Bytes = '0x010101'; - return expectContractCallFailedWithoutReasonAsync( - testAssetProxyOwner.publicReadBytes4.callAsync(byteArrayLessThan4Bytes, new BigNumber(0)), - ); - }); - it('should return the first 4 bytes of a byte array of arbitrary length', async () => { - const byteArrayLongerThan32Bytes = - '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'; - const first4Bytes = await testAssetProxyOwner.publicReadBytes4.callAsync( - byteArrayLongerThan32Bytes, - new BigNumber(0), - ); - const expectedFirst4Bytes = byteArrayLongerThan32Bytes.slice(0, 10); - expect(first4Bytes).to.equal(expectedFirst4Bytes); - }); - }); - describe('registerAssetProxy', () => { it('should throw if not called by multisig', async () => { const isRegistered = true; @@ -300,8 +285,9 @@ describe('AssetProxyOwner', () => { ); const log = submitTxRes.logs[0] as LogWithDecodedArgs<AssetProxyOwnerSubmissionEventArgs>; const txId = log.args.transactionId; - return expectContractCallFailedWithoutReasonAsync( + return expectContractCallFailedAsync( testAssetProxyOwner.testValidRemoveAuthorizedAddressAtIndexTx.callAsync(txId), + RevertReason.InvalidFunctionSelector, ); }); @@ -335,8 +321,9 @@ describe('AssetProxyOwner', () => { ); const log = submitTxRes.logs[0] as LogWithDecodedArgs<AssetProxyOwnerSubmissionEventArgs>; const txId = log.args.transactionId; - return expectContractCallFailedWithoutReasonAsync( + return expectContractCallFailedAsync( testAssetProxyOwner.testValidRemoveAuthorizedAddressAtIndexTx.callAsync(txId), + RevertReason.UnregisteredAssetProxy, ); }); }); @@ -377,10 +364,11 @@ describe('AssetProxyOwner', () => { await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); - return expectTransactionFailedWithoutReasonAsync( + return expectTransactionFailedAsync( testAssetProxyOwner.executeRemoveAuthorizedAddressAtIndex.sendTransactionAsync(txId, { from: owners[1], }), + RevertReason.UnregisteredAssetProxy, ); }); @@ -399,10 +387,11 @@ describe('AssetProxyOwner', () => { await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); - return expectTransactionFailedWithoutReasonAsync( + return expectTransactionFailedAsync( testAssetProxyOwner.executeRemoveAuthorizedAddressAtIndex.sendTransactionAsync(txId, { from: owners[1], }), + RevertReason.InvalidFunctionSelector, ); }); diff --git a/packages/contracts/test/tokens/unlimited_allowance_token.ts b/packages/contracts/test/tokens/unlimited_allowance_token.ts index f2725b408..63680fe9b 100644 --- a/packages/contracts/test/tokens/unlimited_allowance_token.ts +++ b/packages/contracts/test/tokens/unlimited_allowance_token.ts @@ -5,7 +5,7 @@ import * as chai from 'chai'; import { DummyERC20TokenContract } from '../../generated_contract_wrappers/dummy_erc20_token'; import { artifacts } from '../utils/artifacts'; -import { expectContractCallFailed } from '../utils/assertions'; +import { expectContractCallFailedAsync } from '../utils/assertions'; import { chaiSetup } from '../utils/chai_setup'; import { constants } from '../utils/constants'; import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; @@ -54,7 +54,7 @@ describe('UnlimitedAllowanceToken', () => { it('should throw if owner has insufficient balance', async () => { const ownerBalance = await token.balanceOf.callAsync(owner); const amountToTransfer = ownerBalance.plus(1); - return expectContractCallFailed( + return expectContractCallFailedAsync( token.transfer.callAsync(spender, amountToTransfer, { from: owner }), RevertReason.Erc20InsufficientBalance, ); @@ -93,7 +93,7 @@ describe('UnlimitedAllowanceToken', () => { await token.approve.sendTransactionAsync(spender, amountToTransfer, { from: owner }), constants.AWAIT_TRANSACTION_MINED_MS, ); - return expectContractCallFailed( + return expectContractCallFailedAsync( token.transferFrom.callAsync(owner, spender, amountToTransfer, { from: spender, }), @@ -109,7 +109,7 @@ describe('UnlimitedAllowanceToken', () => { const isSpenderAllowanceInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; expect(isSpenderAllowanceInsufficient).to.be.true(); - return expectContractCallFailed( + return expectContractCallFailedAsync( token.transferFrom.callAsync(owner, spender, amountToTransfer, { from: spender, }), diff --git a/packages/contracts/test/utils/artifacts.ts b/packages/contracts/test/utils/artifacts.ts index 5ddb5cc7f..53f2a4e4e 100644 --- a/packages/contracts/test/utils/artifacts.ts +++ b/packages/contracts/test/utils/artifacts.ts @@ -4,6 +4,7 @@ import * as AssetProxyOwner from '../../artifacts/AssetProxyOwner.json'; import * as DummyERC20Token from '../../artifacts/DummyERC20Token.json'; import * as DummyERC721Receiver from '../../artifacts/DummyERC721Receiver.json'; import * as DummyERC721Token from '../../artifacts/DummyERC721Token.json'; +import * as DummyMultipleReturnERC20Token from '../../artifacts/DummyMultipleReturnERC20Token.json'; import * as DummyNoReturnERC20Token from '../../artifacts/DummyNoReturnERC20Token.json'; import * as ERC20Proxy from '../../artifacts/ERC20Proxy.json'; import * as ERC721Proxy from '../../artifacts/ERC721Proxy.json'; @@ -37,6 +38,7 @@ export const artifacts = { DummyERC20Token: (DummyERC20Token as any) as ContractArtifact, DummyERC721Receiver: (DummyERC721Receiver as any) as ContractArtifact, DummyERC721Token: (DummyERC721Token as any) as ContractArtifact, + DummyMultipleReturnERC20Token: (DummyMultipleReturnERC20Token as any) as ContractArtifact, DummyNoReturnERC20Token: (DummyNoReturnERC20Token as any) as ContractArtifact, ERC20Proxy: (ERC20Proxy as any) as ContractArtifact, ERC721Proxy: (ERC721Proxy as any) as ContractArtifact, diff --git a/packages/contracts/test/utils/assertions.ts b/packages/contracts/test/utils/assertions.ts index 61df800c8..3361a751a 100644 --- a/packages/contracts/test/utils/assertions.ts +++ b/packages/contracts/test/utils/assertions.ts @@ -159,7 +159,7 @@ export async function expectTransactionFailedWithoutReasonAsync(p: sendTransacti * @returns a new Promise which will reject if the conditions are not met and * otherwise resolve with no value. */ -export async function expectContractCallFailed<T>(p: Promise<T>, reason: RevertReason): Promise<void> { +export async function expectContractCallFailedAsync<T>(p: Promise<T>, reason: RevertReason): Promise<void> { return expect(p).to.be.rejectedWith(reason); } @@ -180,7 +180,20 @@ export async function expectContractCallFailedWithoutReasonAsync<T>(p: Promise<T * @returns a new Promise which will reject if the conditions are not met and * otherwise resolve with no value. */ -export async function expectContractCreationFailedWithoutReason<T>(p: Promise<T>): Promise<void> { +export async function expectContractCreationFailedAsync<T>( + p: sendTransactionResult, + reason: RevertReason, +): Promise<void> { + return expectTransactionFailedAsync(p, reason); +} + +/** + * Resolves if the contract creation/deployment fails without a revert reason. + * @param p a Promise resulting from a contract creation/deployment + * @returns a new Promise which will reject if the conditions are not met and + * otherwise resolve with no value. + */ +export async function expectContractCreationFailedWithoutReasonAsync<T>(p: Promise<T>): Promise<void> { const errMessage = await _getTransactionFailedErrorMessageAsync(); return expect(p).to.be.rejectedWith(errMessage); } diff --git a/packages/contracts/test/utils/constants.ts b/packages/contracts/test/utils/constants.ts index ee4378d2e..b9ba8ccb9 100644 --- a/packages/contracts/test/utils/constants.ts +++ b/packages/contracts/test/utils/constants.ts @@ -60,6 +60,7 @@ export const constants = { 'MARKET_SELL_ORDERS', 'MATCH_ORDERS', 'CANCEL_ORDER', + 'BATCH_CANCEL_ORDERS', 'CANCEL_ORDERS_UP_TO', 'SET_SIGNATURE_VALIDATOR_APPROVAL', ], diff --git a/packages/contracts/test/utils/web3_wrapper.ts b/packages/contracts/test/utils/web3_wrapper.ts index acb3103b7..d1cd3d387 100644 --- a/packages/contracts/test/utils/web3_wrapper.ts +++ b/packages/contracts/test/utils/web3_wrapper.ts @@ -1,5 +1,5 @@ import { devConstants, env, EnvVars, web3Factory } from '@0xproject/dev-utils'; -import { prependSubprovider } from '@0xproject/subproviders'; +import { prependSubprovider, Web3ProviderEngine } from '@0xproject/subproviders'; import { logUtils } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; @@ -47,7 +47,7 @@ const ganacheConfigs = { }; const providerConfigs = testProvider === ProviderType.Ganache ? ganacheConfigs : gethConfigs; -export const provider = web3Factory.getRpcProvider(providerConfigs); +export const provider: Web3ProviderEngine = web3Factory.getRpcProvider(providerConfigs); const isCoverageEnabled = env.parseBoolean(EnvVars.SolidityCoverage); const isProfilerEnabled = env.parseBoolean(EnvVars.SolidityProfiler); const isRevertTraceEnabled = env.parseBoolean(EnvVars.SolidityRevertTrace); diff --git a/packages/contracts/tsconfig.json b/packages/contracts/tsconfig.json index 86b33ede7..5fd4c5331 100644 --- a/packages/contracts/tsconfig.json +++ b/packages/contracts/tsconfig.json @@ -2,13 +2,11 @@ "extends": "../../tsconfig", "compilerOptions": { "outDir": "lib", - "baseUrl": ".", - "declaration": false, - "allowJs": true + "rootDir": "." }, "include": [ "./globals.d.ts", - "./contract_wrappers", + "./generated_contract_wrappers", "./src/**/*", "./utils/**/*", "./test/**/*", diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index d4740d3bd..afe518d10 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -8,8 +8,7 @@ "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { - "watch_without_deps": "tsc -w", - "build": "tsc", + "build": "tsc -b", "test": "yarn run_mocha", "rebuild_and_test": "run-s clean build test", "test:circleci": "yarn test:coverage", diff --git a/packages/dev-utils/tsconfig.json b/packages/dev-utils/tsconfig.json index e35816553..2ee711adc 100644 --- a/packages/dev-utils/tsconfig.json +++ b/packages/dev-utils/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "." }, "include": ["./src/**/*", "./test/**/*"] } diff --git a/packages/ethereum-types/package.json b/packages/ethereum-types/package.json index 9e4d287a4..007c4cebe 100644 --- a/packages/ethereum-types/package.json +++ b/packages/ethereum-types/package.json @@ -8,11 +8,10 @@ "main": "lib/index.js", "types": "lib/index.d.ts", "scripts": { - "watch_without_deps": "tsc -w", - "build": "tsc", + "build": "tsc -b", "clean": "shx rm -rf lib generated_docs", "lint": "tslint --project .", - "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES" + "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" }, "config": { "postpublish": { diff --git a/packages/ethereum-types/tsconfig.json b/packages/ethereum-types/tsconfig.json index 82a45ea94..9ab22ac8a 100644 --- a/packages/ethereum-types/tsconfig.json +++ b/packages/ethereum-types/tsconfig.json @@ -2,7 +2,8 @@ "extends": "../../tsconfig", "compilerOptions": { "typeRoots": ["../../node_modules/@types"], - "outDir": "lib" + "outDir": "lib", + "rootDir": "src" }, "include": ["src/**/*"] } diff --git a/packages/ethereum-types/typedoc-tsconfig.json b/packages/ethereum-types/typedoc-tsconfig.json new file mode 100644 index 000000000..f71153ec0 --- /dev/null +++ b/packages/ethereum-types/typedoc-tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../typedoc-tsconfig", + "compilerOptions": { + "typeRoots": ["../../node_modules/@types"], + "outDir": "lib" + }, + "include": ["src/**/*"] +} diff --git a/packages/fill-scenarios/package.json b/packages/fill-scenarios/package.json index d0cb29df4..60192d03e 100644 --- a/packages/fill-scenarios/package.json +++ b/packages/fill-scenarios/package.json @@ -5,8 +5,7 @@ "main": "lib/index.js", "types": "lib/index.d.ts", "scripts": { - "watch_without_deps": "yarn pre_build && tsc -w", - "build": "yarn pre_build && tsc", + "build": "yarn pre_build && tsc -b", "pre_build": "run-s update_artifacts generate_contract_wrappers", "update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/artifacts/2.0.0-beta-testnet/$i.json lib/artifacts; done;", "generate_contract_wrappers": "abi-gen --abis 'lib/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers", diff --git a/packages/fill-scenarios/tsconfig.json b/packages/fill-scenarios/tsconfig.json index f5f4b37c2..56689eaa3 100644 --- a/packages/fill-scenarios/tsconfig.json +++ b/packages/fill-scenarios/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "src" }, "include": ["src/**/*"] } diff --git a/packages/forwarder-helper/package.json b/packages/forwarder-helper/package.json index fccd7ccdd..ca2fa96d9 100644 --- a/packages/forwarder-helper/package.json +++ b/packages/forwarder-helper/package.json @@ -20,7 +20,7 @@ "build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", "manual:postpublish": "yarn build; node ./scripts/postpublish.js", "docs:stage": "node scripts/stage_docs.js", - "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES", + "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES", "upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json" }, "config": { @@ -63,7 +63,7 @@ "nyc": "^11.0.1", "shx": "^0.2.2", "tslint": "5.11.0", - "typedoc": "0xProject/typedoc", + "typedoc": "0.12.0", "typescript": "3.0.1" }, "publishConfig": { diff --git a/packages/forwarder-helper/tsconfig.json b/packages/forwarder-helper/tsconfig.json index e35816553..2ee711adc 100644 --- a/packages/forwarder-helper/tsconfig.json +++ b/packages/forwarder-helper/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "." }, "include": ["./src/**/*", "./test/**/*"] } diff --git a/packages/forwarder-helper/typedoc-tsconfig.json b/packages/forwarder-helper/typedoc-tsconfig.json new file mode 100644 index 000000000..c9b0af1ae --- /dev/null +++ b/packages/forwarder-helper/typedoc-tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../typedoc-tsconfig", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["./src/**/*", "./test/**/*"] +} diff --git a/packages/json-schemas/package.json b/packages/json-schemas/package.json index bdd801a19..b0ea37b6e 100644 --- a/packages/json-schemas/package.json +++ b/packages/json-schemas/package.json @@ -8,7 +8,7 @@ "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { - "watch_without_deps": "tsc -w", + "build": "tsc -b", "lint": "tslint --project .", "test": "yarn run_mocha", "rebuild_and_test": "run-s clean build test", @@ -17,8 +17,7 @@ "test:circleci": "yarn test:coverage", "run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --exit", "clean": "shx rm -rf lib test_temp generated_docs", - "build": "tsc", - "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES" + "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" }, "config": { "postpublish": { diff --git a/packages/json-schemas/tsconfig.json b/packages/json-schemas/tsconfig.json index e35816553..96bf8789e 100644 --- a/packages/json-schemas/tsconfig.json +++ b/packages/json-schemas/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "." }, - "include": ["./src/**/*", "./test/**/*"] + "include": ["./src/**/*", "./test/**/*", "./schemas/**/*"] } diff --git a/packages/json-schemas/typedoc-tsconfig.json b/packages/json-schemas/typedoc-tsconfig.json new file mode 100644 index 000000000..c9b0af1ae --- /dev/null +++ b/packages/json-schemas/typedoc-tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../typedoc-tsconfig", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["./src/**/*", "./test/**/*"] +} diff --git a/packages/metacoin/package.json b/packages/metacoin/package.json index ea251e2fe..4b467716d 100644 --- a/packages/metacoin/package.json +++ b/packages/metacoin/package.json @@ -8,8 +8,7 @@ "description": "Example solidity project using 0x dev tools", "scripts": { "lint": "tslint --project . --exclude **/src/contract_wrappers/**/*", - "watch_without_deps": "yarn pre_build && tsc -w", - "build": "yarn pre_build && tsc", + "build": "yarn pre_build && tsc -b", "pre_build": "run-s compile generate_contract_wrappers copy_artifacts", "clean": "shx rm -rf lib artifacts src/contract_wrappers", "copy_artifacts": "copyfiles './artifacts/**/*' './contracts/**/*' ./lib", diff --git a/packages/metacoin/tsconfig.json b/packages/metacoin/tsconfig.json index bc3bd1e94..3065396ff 100644 --- a/packages/metacoin/tsconfig.json +++ b/packages/metacoin/tsconfig.json @@ -1,8 +1,8 @@ { + "extends": "../../tsconfig", "compilerOptions": { "outDir": "lib", - "lib": ["es2017"], - "skipLibCheck": true, + "rootDir": ".", "typeRoots": [ "comment: for building within 0x-monorepo:", "../../node_modules/@0xproject/typescript-typings/types", diff --git a/packages/migrations/artifacts/2.0.0-beta-testnet/OrderValidator.json b/packages/migrations/artifacts/2.0.0-beta-testnet/OrderValidator.json index 99805c766..add00d3ce 100644 --- a/packages/migrations/artifacts/2.0.0-beta-testnet/OrderValidator.json +++ b/packages/migrations/artifacts/2.0.0-beta-testnet/OrderValidator.json @@ -414,6 +414,33 @@ "constant": true, "inputs": [ { + "name": "target", + "type": "address" + }, + { + "name": "assetData", + "type": "bytes[]" + } + ], + "name": "getBalancesAndAllowances", + "outputs": [ + { + "name": "", + "type": "uint256[]" + }, + { + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "components": [ { "name": "makerAddress", @@ -536,15 +563,15 @@ "evm": { "bytecode": { "linkReferences": {}, - "object": "0x60806040523480156200001157600080fd5b5060405162001b0d38038062001b0d833981018060405262000037919081019062000186565b60008054600160a060020a031916600160a060020a03841617905580516200006790600190602084019062000070565b5050506200026b565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620000b357805160ff1916838001178555620000e3565b82800160010185558215620000e3579182015b82811115620000e3578251825591602001919060010190620000c6565b50620000f1929150620000f5565b5090565b6200011291905b80821115620000f15760008155600101620000fc565b90565b60006200012382516200022c565b9392505050565b6000601f820183136200013c57600080fd5b8151620001536200014d8262000204565b620001dd565b915080825260208301602083018583830111156200017057600080fd5b6200017d83828462000238565b50505092915050565b600080604083850312156200019a57600080fd5b6000620001a8858562000115565b92505060208301516001604060020a03811115620001c557600080fd5b620001d3858286016200012a565b9150509250929050565b6040518181016001604060020a0381118282101715620001fc57600080fd5b604052919050565b60006001604060020a038211156200021b57600080fd5b506020601f91909101601f19160190565b600160a060020a031690565b60005b83811015620002555781810151838201526020016200023b565b8381111562000265576000848401525b50505050565b611892806200027b6000396000f3006080604052600436106100775763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166304ad1e53811461007c5780632cd0fc73146100b35780634b95de13146100e1578063690d31141461010f578063b69884631461013c578063f241ffb014610169575b600080fd5b34801561008857600080fd5b5061009c610097366004611118565b610196565b6040516100aa9291906116af565b60405180910390f35b3480156100bf57600080fd5b506100d36100ce366004610fc6565b610263565b6040516100aa9291906116f9565b3480156100ed57600080fd5b506101016100fc36600461107d565b610794565b6040516100aa92919061161a565b34801561011b57600080fd5b5061012f61012a36600461107d565b61086b565b6040516100aa9190611650565b34801561014857600080fd5b5061015c610157366004611018565b610925565b6040516100aa91906115f1565b34801561017557600080fd5b50610189610184366004611118565b610970565b6040516100aa91906116dc565b61019e610bba565b6101a6610bda565b6000546040517fc75e0a8100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063c75e0a81906101fc9087906004016116cb565b606060405180830381600087803b15801561021657600080fd5b505af115801561022a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061024e91908101906110fa565b915061025a8484610970565b90509250929050565b60008080808080808061027c898263ffffffff610a8e16565b955061028f89601063ffffffff610afb16565b6000546040517f6070410800000000000000000000000000000000000000000000000000000000815291965073ffffffffffffffffffffffffffffffffffffffff16906360704108906102e6908990600401611661565b602060405180830381600087803b15801561030057600080fd5b505af1158015610314573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506103389190810190610fa0565b604080517f4552433230546f6b656e28616464726573732900000000000000000000000000815290519081900360130190209094507fffffffff00000000000000000000000000000000000000000000000000000000878116911614156104ed576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8616906370a08231906103eb908d906004016115f1565b602060405180830381600087803b15801561040557600080fd5b505af1158015610419573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061043d919081019061115f565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815290985073ffffffffffffffffffffffffffffffffffffffff86169063dd62ed3e90610494908d9088906004016115ff565b602060405180830381600087803b1580156104ae57600080fd5b505af11580156104c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506104e6919081019061115f565b9650610787565b604080517f455243373231546f6b656e28616464726573732c75696e7432353629000000008152905190819003601c0190207fffffffff000000000000000000000000000000000000000000000000000000008781169116141561074c5761055c89602463ffffffff610b5c16565b92506105688584610925565b91508173ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16146105a45760006105a7565b60015b60ff1697508473ffffffffffffffffffffffffffffffffffffffff1663e985e9c58b866040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016106039291906115ff565b602060405180830381600087803b15801561061d57600080fd5b505af1158015610631573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061065591908101906110dc565b8061073157508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1663081812fc856040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016106c791906116eb565b602060405180830381600087803b1580156106e157600080fd5b505af11580156106f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107199190810190610fa0565b73ffffffffffffffffffffffffffffffffffffffff16145b90508061073f576000610742565b60015b60ff169650610787565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077e9061167f565b60405180910390fd5b5050505050509250929050565b6000546040517f7e9d74dc000000000000000000000000000000000000000000000000000000008152606091829173ffffffffffffffffffffffffffffffffffffffff90911690637e9d74dc906107ef90879060040161163f565b600060405180830381600087803b15801561080957600080fd5b505af115801561081d573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526108639190810190611048565b915061025a84845b606060006060600085519250826040519080825280602002602001820160405280156108b157816020015b61089e610bda565b8152602001906001900390816108965790505b509150600090505b808314610918576108f886828151811015156108d157fe5b9060200190602002015186838151811015156108e957fe5b90602001906020020151610970565b828281518110151561090657fe5b602090810290910101526001016108b9565b8193505b50505092915050565b60006040517f6352211e000000000000000000000000000000000000000000000000000000008152826004820152602081602483875afa801561096757815192505b50505b92915050565b610978610bda565b606061098d8460000151856101400151610263565b602084015282526101608401516109a5908490610263565b60608401526040808401919091526001805482516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101008688161502019094169390930492830181900481028201810190945281815292830182828015610a545780601f10610a2957610100808354040283529160200191610a54565b820191906000526020600020905b815481529060010190602001808311610a3757829003601f168201915b50505050509050610a69846000015182610263565b60a08401526080830152610a7d8382610263565b60e084015260c08301525092915050565b600081600401835110151515610ad0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077e9061169f565b5050602001517fffffffff000000000000000000000000000000000000000000000000000000001690565b600081601401835110151515610b3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077e9061168f565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b6000610b688383610b6f565b9392505050565b600081602001835110151515610bb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077e9061166f565b50016020015190565b604080516060810182526000808252602082018190529181019190915290565b6101006040519081016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000610b6882356117ac565b6000610b6882516117ac565b6000601f82018313610c4957600080fd5b8135610c5c610c578261173b565b611714565b91508181835260208401935060208101905083856020840282011115610c8157600080fd5b60005b83811015610cad5781610c978882610c20565b8452506020928301929190910190600101610c84565b5050505092915050565b6000601f82018313610cc857600080fd5b8151610cd6610c578261173b565b91508181835260208401935060208101905083856060840282011115610cfb57600080fd5b60005b83811015610cad5781610d118882610de4565b84525060209092019160609190910190600101610cfe565b6000601f82018313610d3a57600080fd5b8135610d48610c578261173b565b81815260209384019390925082018360005b83811015610cad5781358601610d708882610e3f565b8452506020928301929190910190600101610d5a565b6000610b6882516117f3565b6000610b6882516117c5565b6000601f82018313610daf57600080fd5b8135610dbd610c578261175c565b91508082526020830160208301858383011115610dd957600080fd5b61091c8382846117f8565b600060608284031215610df657600080fd5b610e006060611714565b90506000610e0e8484610f94565b8252506020610e1f84848301610d92565b6020830152506040610e3384828501610d92565b60408301525092915050565b60006101808284031215610e5257600080fd5b610e5d610180611714565b90506000610e6b8484610c20565b8252506020610e7c84848301610c20565b6020830152506040610e9084828501610c20565b6040830152506060610ea484828501610c20565b6060830152506080610eb884828501610f88565b60808301525060a0610ecc84828501610f88565b60a08301525060c0610ee084828501610f88565b60c08301525060e0610ef484828501610f88565b60e083015250610100610f0984828501610f88565b61010083015250610120610f1f84828501610f88565b6101208301525061014082013567ffffffffffffffff811115610f4157600080fd5b610f4d84828501610d9e565b6101408301525061016082013567ffffffffffffffff811115610f6f57600080fd5b610f7b84828501610d9e565b6101608301525092915050565b6000610b6882356117c5565b6000610b6882516117ed565b600060208284031215610fb257600080fd5b6000610fbe8484610c2c565b949350505050565b60008060408385031215610fd957600080fd5b6000610fe58585610c20565b925050602083013567ffffffffffffffff81111561100257600080fd5b61100e85828601610d9e565b9150509250929050565b6000806040838503121561102b57600080fd5b60006110378585610c20565b925050602061100e85828601610f88565b60006020828403121561105a57600080fd5b815167ffffffffffffffff81111561107157600080fd5b610fbe84828501610cb7565b6000806040838503121561109057600080fd5b823567ffffffffffffffff8111156110a757600080fd5b6110b385828601610d29565b925050602083013567ffffffffffffffff8111156110d057600080fd5b61100e85828601610c38565b6000602082840312156110ee57600080fd5b6000610fbe8484610d86565b60006060828403121561110c57600080fd5b6000610fbe8484610de4565b6000806040838503121561112b57600080fd5b823567ffffffffffffffff81111561114257600080fd5b61114e85828601610e3f565b925050602061100e85828601610c20565b60006020828403121561117157600080fd5b6000610fbe8484610d92565b611186816117ac565b82525050565b6000611197826117a8565b8084526020840193506111a9836117a2565b60005b828110156111d9576111bf868351611411565b6111c8826117a2565b6060969096019591506001016111ac565b5093949350505050565b60006111ee826117a8565b80845260208401935083602082028501611207856117a2565b60005b8481101561123e57838303885261122283835161144e565b925061122d826117a2565b60209890980197915060010161120a565b50909695505050505050565b6000611255826117a8565b808452602084019350611267836117a2565b60005b828110156111d95761127d868351611551565b611286826117a2565b6101009690960195915060010161126a565b611186816117c5565b611186816117c8565b60006112b5826117a8565b8084526112c9816020860160208601611804565b6112d281611830565b9093016020019392505050565b602681527f475245415445525f4f525f455155414c5f544f5f33325f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601781527f554e535550504f525445445f41535345545f50524f5859000000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b602581527f475245415445525f4f525f455155414c5f544f5f345f4c454e4754485f52455160208201527f5549524544000000000000000000000000000000000000000000000000000000604082015260600190565b8051606083019061142284826115e8565b5060208201516114356020850182611298565b5060408201516114486040850182611298565b50505050565b8051600090610180840190611463858261117d565b506020830151611476602086018261117d565b506040830151611489604086018261117d565b50606083015161149c606086018261117d565b5060808301516114af6080860182611298565b5060a08301516114c260a0860182611298565b5060c08301516114d560c0860182611298565b5060e08301516114e860e0860182611298565b506101008301516114fd610100860182611298565b50610120830151611512610120860182611298565b5061014083015184820361014086015261152c82826112aa565b91505061016083015184820361016086015261154882826112aa565b95945050505050565b80516101008301906115638482611298565b5060208201516115766020850182611298565b5060408201516115896040850182611298565b50606082015161159c6060850182611298565b5060808201516115af6080850182611298565b5060a08201516115c260a0850182611298565b5060c08201516115d560c0850182611298565b5060e082015161144860e0850182611298565b611186816117ed565b6020810161096a828461117d565b6040810161160d828561117d565b610b68602083018461117d565b6040808252810161162b818561118c565b90508181036020830152610fbe818461124a565b60208082528101610b6881846111e3565b60208082528101610b68818461124a565b6020810161096a82846112a1565b6020808252810161096a816112df565b6020808252810161096a81611335565b6020808252810161096a81611365565b6020808252810161096a816113bb565b61016081016116be8285611411565b610b686060830184611551565b60208082528101610b68818461144e565b610100810161096a8284611551565b6020810161096a8284611298565b604081016117078285611298565b610b686020830184611298565b60405181810167ffffffffffffffff8111828210171561173357600080fd5b604052919050565b600067ffffffffffffffff82111561175257600080fd5b5060209081020190565b600067ffffffffffffffff82111561177357600080fd5b506020601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b60200190565b5190565b73ffffffffffffffffffffffffffffffffffffffff1690565b90565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b60ff1690565b151590565b82818337506000910152565b60005b8381101561181f578181015183820152602001611807565b838111156114485750506000910152565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016905600a265627a7a723058200742593843de04ccb442f25f2474ff7a322e1281cdb1232118c18b3985166e7f6c6578706572696d656e74616cf50037", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1B0D CODESIZE SUB DUP1 PUSH3 0x1B0D DUP4 CODECOPY DUP2 ADD DUP1 PUSH1 0x40 MSTORE PUSH3 0x37 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH3 0x186 JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT AND PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP5 AND OR SWAP1 SSTORE DUP1 MLOAD PUSH3 0x67 SWAP1 PUSH1 0x1 SWAP1 PUSH1 0x20 DUP5 ADD SWAP1 PUSH3 0x70 JUMP JUMPDEST POP POP POP PUSH3 0x26B JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0xB3 JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0xE3 JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0xE3 JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0xE3 JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0xC6 JUMP JUMPDEST POP PUSH3 0xF1 SWAP3 SWAP2 POP PUSH3 0xF5 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x112 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0xF1 JUMPI PUSH1 0x0 DUP2 SSTORE PUSH1 0x1 ADD PUSH3 0xFC JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH3 0x123 DUP3 MLOAD PUSH3 0x22C JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH3 0x13C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 MLOAD PUSH3 0x153 PUSH3 0x14D DUP3 PUSH3 0x204 JUMP JUMPDEST PUSH3 0x1DD JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE PUSH1 0x20 DUP4 ADD PUSH1 0x20 DUP4 ADD DUP6 DUP4 DUP4 ADD GT ISZERO PUSH3 0x170 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH3 0x17D DUP4 DUP3 DUP5 PUSH3 0x238 JUMP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH3 0x19A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH3 0x1A8 DUP6 DUP6 PUSH3 0x115 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 DUP4 ADD MLOAD PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP2 GT ISZERO PUSH3 0x1C5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH3 0x1D3 DUP6 DUP3 DUP7 ADD PUSH3 0x12A JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH3 0x1FC JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP3 GT ISZERO PUSH3 0x21B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 PUSH1 0x1F SWAP2 SWAP1 SWAP2 ADD PUSH1 0x1F NOT AND ADD SWAP1 JUMP JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH3 0x255 JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH3 0x23B JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH3 0x265 JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH2 0x1892 DUP1 PUSH3 0x27B PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x77 JUMPI PUSH4 0xFFFFFFFF PUSH29 0x100000000000000000000000000000000000000000000000000000000 PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0x4AD1E53 DUP2 EQ PUSH2 0x7C JUMPI DUP1 PUSH4 0x2CD0FC73 EQ PUSH2 0xB3 JUMPI DUP1 PUSH4 0x4B95DE13 EQ PUSH2 0xE1 JUMPI DUP1 PUSH4 0x690D3114 EQ PUSH2 0x10F JUMPI DUP1 PUSH4 0xB6988463 EQ PUSH2 0x13C JUMPI DUP1 PUSH4 0xF241FFB0 EQ PUSH2 0x169 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x88 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x9C PUSH2 0x97 CALLDATASIZE PUSH1 0x4 PUSH2 0x1118 JUMP JUMPDEST PUSH2 0x196 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xAA SWAP3 SWAP2 SWAP1 PUSH2 0x16AF JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0xBF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xD3 PUSH2 0xCE CALLDATASIZE PUSH1 0x4 PUSH2 0xFC6 JUMP JUMPDEST PUSH2 0x263 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xAA SWAP3 SWAP2 SWAP1 PUSH2 0x16F9 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0xED JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x101 PUSH2 0xFC CALLDATASIZE PUSH1 0x4 PUSH2 0x107D JUMP JUMPDEST PUSH2 0x794 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xAA SWAP3 SWAP2 SWAP1 PUSH2 0x161A JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x11B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x12F PUSH2 0x12A CALLDATASIZE PUSH1 0x4 PUSH2 0x107D JUMP JUMPDEST PUSH2 0x86B JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xAA SWAP2 SWAP1 PUSH2 0x1650 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x148 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x15C PUSH2 0x157 CALLDATASIZE PUSH1 0x4 PUSH2 0x1018 JUMP JUMPDEST PUSH2 0x925 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xAA SWAP2 SWAP1 PUSH2 0x15F1 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x175 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x189 PUSH2 0x184 CALLDATASIZE PUSH1 0x4 PUSH2 0x1118 JUMP JUMPDEST PUSH2 0x970 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xAA SWAP2 SWAP1 PUSH2 0x16DC JUMP JUMPDEST PUSH2 0x19E PUSH2 0xBBA JUMP JUMPDEST PUSH2 0x1A6 PUSH2 0xBDA JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH1 0x40 MLOAD PUSH32 0xC75E0A8100000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP2 AND SWAP1 PUSH4 0xC75E0A81 SWAP1 PUSH2 0x1FC SWAP1 DUP8 SWAP1 PUSH1 0x4 ADD PUSH2 0x16CB JUMP JUMPDEST PUSH1 0x60 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x216 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x22A 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 0x24E SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x10FA JUMP JUMPDEST SWAP2 POP PUSH2 0x25A DUP5 DUP5 PUSH2 0x970 JUMP JUMPDEST SWAP1 POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP1 DUP1 DUP1 DUP1 DUP1 DUP1 PUSH2 0x27C DUP10 DUP3 PUSH4 0xFFFFFFFF PUSH2 0xA8E AND JUMP JUMPDEST SWAP6 POP PUSH2 0x28F DUP10 PUSH1 0x10 PUSH4 0xFFFFFFFF PUSH2 0xAFB AND JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH1 0x40 MLOAD PUSH32 0x6070410800000000000000000000000000000000000000000000000000000000 DUP2 MSTORE SWAP2 SWAP7 POP PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH4 0x60704108 SWAP1 PUSH2 0x2E6 SWAP1 DUP10 SWAP1 PUSH1 0x4 ADD PUSH2 0x1661 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x300 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x314 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 0x338 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0xFA0 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0x4552433230546F6B656E28616464726573732900000000000000000000000000 DUP2 MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x13 ADD SWAP1 KECCAK256 SWAP1 SWAP5 POP PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 DUP8 DUP2 AND SWAP2 AND EQ ISZERO PUSH2 0x4ED JUMPI PUSH1 0x40 MLOAD PUSH32 0x70A0823100000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP7 AND SWAP1 PUSH4 0x70A08231 SWAP1 PUSH2 0x3EB SWAP1 DUP14 SWAP1 PUSH1 0x4 ADD PUSH2 0x15F1 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x405 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x419 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 0x43D SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x115F JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0xDD62ED3E00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE SWAP1 SWAP9 POP PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP7 AND SWAP1 PUSH4 0xDD62ED3E SWAP1 PUSH2 0x494 SWAP1 DUP14 SWAP1 DUP9 SWAP1 PUSH1 0x4 ADD PUSH2 0x15FF JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x4AE JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x4C2 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 0x4E6 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x115F JUMP JUMPDEST SWAP7 POP PUSH2 0x787 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0x455243373231546F6B656E28616464726573732C75696E743235362900000000 DUP2 MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x1C ADD SWAP1 KECCAK256 PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 DUP8 DUP2 AND SWAP2 AND EQ ISZERO PUSH2 0x74C JUMPI PUSH2 0x55C DUP10 PUSH1 0x24 PUSH4 0xFFFFFFFF PUSH2 0xB5C AND JUMP JUMPDEST SWAP3 POP PUSH2 0x568 DUP6 DUP5 PUSH2 0x925 JUMP JUMPDEST SWAP2 POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ PUSH2 0x5A4 JUMPI PUSH1 0x0 PUSH2 0x5A7 JUMP JUMPDEST PUSH1 0x1 JUMPDEST PUSH1 0xFF AND SWAP8 POP DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH4 0xE985E9C5 DUP12 DUP7 PUSH1 0x40 MLOAD DUP4 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x603 SWAP3 SWAP2 SWAP1 PUSH2 0x15FF JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x61D JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x631 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 0x655 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x10DC JUMP JUMPDEST DUP1 PUSH2 0x731 JUMPI POP DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH4 0x81812FC DUP6 PUSH1 0x40 MLOAD DUP3 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x6C7 SWAP2 SWAP1 PUSH2 0x16EB JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x6E1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x6F5 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 0x719 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0xFA0 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ JUMPDEST SWAP1 POP DUP1 PUSH2 0x73F JUMPI PUSH1 0x0 PUSH2 0x742 JUMP JUMPDEST PUSH1 0x1 JUMPDEST PUSH1 0xFF AND SWAP7 POP PUSH2 0x787 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x77E SWAP1 PUSH2 0x167F JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP POP POP POP POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH1 0x40 MLOAD PUSH32 0x7E9D74DC00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x60 SWAP2 DUP3 SWAP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP2 AND SWAP1 PUSH4 0x7E9D74DC SWAP1 PUSH2 0x7EF SWAP1 DUP8 SWAP1 PUSH1 0x4 ADD PUSH2 0x163F JUMP JUMPDEST PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x809 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x81D JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP PUSH1 0x40 MLOAD RETURNDATASIZE PUSH1 0x0 DUP3 RETURNDATACOPY PUSH1 0x1F RETURNDATASIZE SWAP1 DUP2 ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND DUP3 ADD PUSH1 0x40 MSTORE PUSH2 0x863 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1048 JUMP JUMPDEST SWAP2 POP PUSH2 0x25A DUP5 DUP5 JUMPDEST PUSH1 0x60 PUSH1 0x0 PUSH1 0x60 PUSH1 0x0 DUP6 MLOAD SWAP3 POP DUP3 PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x8B1 JUMPI DUP2 PUSH1 0x20 ADD JUMPDEST PUSH2 0x89E PUSH2 0xBDA JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD SWAP1 PUSH1 0x1 SWAP1 SUB SWAP1 DUP2 PUSH2 0x896 JUMPI SWAP1 POP JUMPDEST POP SWAP2 POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP1 DUP4 EQ PUSH2 0x918 JUMPI PUSH2 0x8F8 DUP7 DUP3 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x8D1 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD DUP7 DUP4 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x8E9 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH2 0x970 JUMP JUMPDEST DUP3 DUP3 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x906 JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP1 SWAP2 ADD ADD MSTORE PUSH1 0x1 ADD PUSH2 0x8B9 JUMP JUMPDEST DUP2 SWAP4 POP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x40 MLOAD PUSH32 0x6352211E00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE DUP3 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x20 DUP2 PUSH1 0x24 DUP4 DUP8 GAS STATICCALL DUP1 ISZERO PUSH2 0x967 JUMPI DUP2 MLOAD SWAP3 POP JUMPDEST POP POP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH2 0x978 PUSH2 0xBDA JUMP JUMPDEST PUSH1 0x60 PUSH2 0x98D DUP5 PUSH1 0x0 ADD MLOAD DUP6 PUSH2 0x140 ADD MLOAD PUSH2 0x263 JUMP JUMPDEST PUSH1 0x20 DUP5 ADD MSTORE DUP3 MSTORE PUSH2 0x160 DUP5 ADD MLOAD PUSH2 0x9A5 SWAP1 DUP5 SWAP1 PUSH2 0x263 JUMP JUMPDEST PUSH1 0x60 DUP5 ADD MSTORE PUSH1 0x40 DUP1 DUP5 ADD SWAP2 SWAP1 SWAP2 MSTORE PUSH1 0x1 DUP1 SLOAD DUP3 MLOAD PUSH1 0x20 PUSH1 0x1F PUSH1 0x2 PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF PUSH2 0x100 DUP7 DUP9 AND ISZERO MUL ADD SWAP1 SWAP5 AND SWAP4 SWAP1 SWAP4 DIV SWAP3 DUP4 ADD DUP2 SWAP1 DIV DUP2 MUL DUP3 ADD DUP2 ADD SWAP1 SWAP5 MSTORE DUP2 DUP2 MSTORE SWAP3 DUP4 ADD DUP3 DUP3 DUP1 ISZERO PUSH2 0xA54 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xA29 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xA54 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xA37 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP PUSH2 0xA69 DUP5 PUSH1 0x0 ADD MLOAD DUP3 PUSH2 0x263 JUMP JUMPDEST PUSH1 0xA0 DUP5 ADD MSTORE PUSH1 0x80 DUP4 ADD MSTORE PUSH2 0xA7D DUP4 DUP3 PUSH2 0x263 JUMP JUMPDEST PUSH1 0xE0 DUP5 ADD MSTORE PUSH1 0xC0 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x4 ADD DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0xAD0 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x77E SWAP1 PUSH2 0x169F JUMP JUMPDEST POP POP PUSH1 0x20 ADD MLOAD PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 AND SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x14 ADD DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0xB3D JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x77E SWAP1 PUSH2 0x168F JUMP JUMPDEST POP ADD PUSH1 0x14 ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xB68 DUP4 DUP4 PUSH2 0xB6F JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x20 ADD DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0xBB1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x77E SWAP1 PUSH2 0x166F JUMP JUMPDEST POP ADD PUSH1 0x20 ADD MLOAD SWAP1 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x60 DUP2 ADD DUP3 MSTORE PUSH1 0x0 DUP1 DUP3 MSTORE PUSH1 0x20 DUP3 ADD DUP2 SWAP1 MSTORE SWAP2 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE SWAP1 JUMP JUMPDEST PUSH2 0x100 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 PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xB68 DUP3 CALLDATALOAD PUSH2 0x17AC JUMP JUMPDEST PUSH1 0x0 PUSH2 0xB68 DUP3 MLOAD PUSH2 0x17AC JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xC49 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xC5C PUSH2 0xC57 DUP3 PUSH2 0x173B JUMP JUMPDEST PUSH2 0x1714 JUMP JUMPDEST SWAP2 POP DUP2 DUP2 DUP4 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH1 0x20 DUP2 ADD SWAP1 POP DUP4 DUP6 PUSH1 0x20 DUP5 MUL DUP3 ADD GT ISZERO PUSH2 0xC81 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xCAD JUMPI DUP2 PUSH2 0xC97 DUP9 DUP3 PUSH2 0xC20 JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xC84 JUMP JUMPDEST POP POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xCC8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 MLOAD PUSH2 0xCD6 PUSH2 0xC57 DUP3 PUSH2 0x173B JUMP JUMPDEST SWAP2 POP DUP2 DUP2 DUP4 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH1 0x20 DUP2 ADD SWAP1 POP DUP4 DUP6 PUSH1 0x60 DUP5 MUL DUP3 ADD GT ISZERO PUSH2 0xCFB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xCAD JUMPI DUP2 PUSH2 0xD11 DUP9 DUP3 PUSH2 0xDE4 JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 SWAP1 SWAP3 ADD SWAP2 PUSH1 0x60 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xCFE JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xD3A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xD48 PUSH2 0xC57 DUP3 PUSH2 0x173B JUMP JUMPDEST DUP2 DUP2 MSTORE PUSH1 0x20 SWAP4 DUP5 ADD SWAP4 SWAP1 SWAP3 POP DUP3 ADD DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xCAD JUMPI DUP2 CALLDATALOAD DUP7 ADD PUSH2 0xD70 DUP9 DUP3 PUSH2 0xE3F JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xD5A JUMP JUMPDEST PUSH1 0x0 PUSH2 0xB68 DUP3 MLOAD PUSH2 0x17F3 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xB68 DUP3 MLOAD PUSH2 0x17C5 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xDAF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xDBD PUSH2 0xC57 DUP3 PUSH2 0x175C JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE PUSH1 0x20 DUP4 ADD PUSH1 0x20 DUP4 ADD DUP6 DUP4 DUP4 ADD GT ISZERO PUSH2 0xDD9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x91C DUP4 DUP3 DUP5 PUSH2 0x17F8 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xDF6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xE00 PUSH1 0x60 PUSH2 0x1714 JUMP JUMPDEST SWAP1 POP PUSH1 0x0 PUSH2 0xE0E DUP5 DUP5 PUSH2 0xF94 JUMP JUMPDEST DUP3 MSTORE POP PUSH1 0x20 PUSH2 0xE1F DUP5 DUP5 DUP4 ADD PUSH2 0xD92 JUMP JUMPDEST PUSH1 0x20 DUP4 ADD MSTORE POP PUSH1 0x40 PUSH2 0xE33 DUP5 DUP3 DUP6 ADD PUSH2 0xD92 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x180 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xE52 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xE5D PUSH2 0x180 PUSH2 0x1714 JUMP JUMPDEST SWAP1 POP PUSH1 0x0 PUSH2 0xE6B DUP5 DUP5 PUSH2 0xC20 JUMP JUMPDEST DUP3 MSTORE POP PUSH1 0x20 PUSH2 0xE7C DUP5 DUP5 DUP4 ADD PUSH2 0xC20 JUMP JUMPDEST PUSH1 0x20 DUP4 ADD MSTORE POP PUSH1 0x40 PUSH2 0xE90 DUP5 DUP3 DUP6 ADD PUSH2 0xC20 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MSTORE POP PUSH1 0x60 PUSH2 0xEA4 DUP5 DUP3 DUP6 ADD PUSH2 0xC20 JUMP JUMPDEST PUSH1 0x60 DUP4 ADD MSTORE POP PUSH1 0x80 PUSH2 0xEB8 DUP5 DUP3 DUP6 ADD PUSH2 0xF88 JUMP JUMPDEST PUSH1 0x80 DUP4 ADD MSTORE POP PUSH1 0xA0 PUSH2 0xECC DUP5 DUP3 DUP6 ADD PUSH2 0xF88 JUMP JUMPDEST PUSH1 0xA0 DUP4 ADD MSTORE POP PUSH1 0xC0 PUSH2 0xEE0 DUP5 DUP3 DUP6 ADD PUSH2 0xF88 JUMP JUMPDEST PUSH1 0xC0 DUP4 ADD MSTORE POP PUSH1 0xE0 PUSH2 0xEF4 DUP5 DUP3 DUP6 ADD PUSH2 0xF88 JUMP JUMPDEST PUSH1 0xE0 DUP4 ADD MSTORE POP PUSH2 0x100 PUSH2 0xF09 DUP5 DUP3 DUP6 ADD PUSH2 0xF88 JUMP JUMPDEST PUSH2 0x100 DUP4 ADD MSTORE POP PUSH2 0x120 PUSH2 0xF1F DUP5 DUP3 DUP6 ADD PUSH2 0xF88 JUMP JUMPDEST PUSH2 0x120 DUP4 ADD MSTORE POP PUSH2 0x140 DUP3 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xF41 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xF4D DUP5 DUP3 DUP6 ADD PUSH2 0xD9E JUMP JUMPDEST PUSH2 0x140 DUP4 ADD MSTORE POP PUSH2 0x160 DUP3 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xF6F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xF7B DUP5 DUP3 DUP6 ADD PUSH2 0xD9E JUMP JUMPDEST PUSH2 0x160 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0xB68 DUP3 CALLDATALOAD PUSH2 0x17C5 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xB68 DUP3 MLOAD PUSH2 0x17ED JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xFB2 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0xFBE DUP5 DUP5 PUSH2 0xC2C JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0xFD9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0xFE5 DUP6 DUP6 PUSH2 0xC20 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 DUP4 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x1002 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x100E DUP6 DUP3 DUP7 ADD PUSH2 0xD9E JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x102B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1037 DUP6 DUP6 PUSH2 0xC20 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 PUSH2 0x100E DUP6 DUP3 DUP7 ADD PUSH2 0xF88 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x105A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x1071 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xFBE DUP5 DUP3 DUP6 ADD PUSH2 0xCB7 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x1090 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x10A7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x10B3 DUP6 DUP3 DUP7 ADD PUSH2 0xD29 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 DUP4 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x10D0 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x100E DUP6 DUP3 DUP7 ADD PUSH2 0xC38 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x10EE JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0xFBE DUP5 DUP5 PUSH2 0xD86 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x110C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0xFBE DUP5 DUP5 PUSH2 0xDE4 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x112B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x1142 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x114E DUP6 DUP3 DUP7 ADD PUSH2 0xE3F JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 PUSH2 0x100E DUP6 DUP3 DUP7 ADD PUSH2 0xC20 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x1171 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0xFBE DUP5 DUP5 PUSH2 0xD92 JUMP JUMPDEST PUSH2 0x1186 DUP2 PUSH2 0x17AC JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x1197 DUP3 PUSH2 0x17A8 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH2 0x11A9 DUP4 PUSH2 0x17A2 JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x11D9 JUMPI PUSH2 0x11BF DUP7 DUP4 MLOAD PUSH2 0x1411 JUMP JUMPDEST PUSH2 0x11C8 DUP3 PUSH2 0x17A2 JUMP JUMPDEST PUSH1 0x60 SWAP7 SWAP1 SWAP7 ADD SWAP6 SWAP2 POP PUSH1 0x1 ADD PUSH2 0x11AC JUMP JUMPDEST POP SWAP4 SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x11EE DUP3 PUSH2 0x17A8 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP DUP4 PUSH1 0x20 DUP3 MUL DUP6 ADD PUSH2 0x1207 DUP6 PUSH2 0x17A2 JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP5 DUP2 LT ISZERO PUSH2 0x123E JUMPI DUP4 DUP4 SUB DUP9 MSTORE PUSH2 0x1222 DUP4 DUP4 MLOAD PUSH2 0x144E JUMP JUMPDEST SWAP3 POP PUSH2 0x122D DUP3 PUSH2 0x17A2 JUMP JUMPDEST PUSH1 0x20 SWAP9 SWAP1 SWAP9 ADD SWAP8 SWAP2 POP PUSH1 0x1 ADD PUSH2 0x120A JUMP JUMPDEST POP SWAP1 SWAP7 SWAP6 POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x1255 DUP3 PUSH2 0x17A8 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH2 0x1267 DUP4 PUSH2 0x17A2 JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x11D9 JUMPI PUSH2 0x127D DUP7 DUP4 MLOAD PUSH2 0x1551 JUMP JUMPDEST PUSH2 0x1286 DUP3 PUSH2 0x17A2 JUMP JUMPDEST PUSH2 0x100 SWAP7 SWAP1 SWAP7 ADD SWAP6 SWAP2 POP PUSH1 0x1 ADD PUSH2 0x126A JUMP JUMPDEST PUSH2 0x1186 DUP2 PUSH2 0x17C5 JUMP JUMPDEST PUSH2 0x1186 DUP2 PUSH2 0x17C8 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x12B5 DUP3 PUSH2 0x17A8 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH2 0x12C9 DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x1804 JUMP JUMPDEST PUSH2 0x12D2 DUP2 PUSH2 0x1830 JUMP JUMPDEST SWAP1 SWAP4 ADD PUSH1 0x20 ADD SWAP4 SWAP3 POP POP POP 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 0x17 DUP2 MSTORE PUSH32 0x554E535550504F525445445F41535345545F50524F5859000000000000000000 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 0x25 DUP2 MSTORE PUSH32 0x475245415445525F4F525F455155414C5F544F5F345F4C454E4754485F524551 PUSH1 0x20 DUP3 ADD MSTORE PUSH32 0x5549524544000000000000000000000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST DUP1 MLOAD PUSH1 0x60 DUP4 ADD SWAP1 PUSH2 0x1422 DUP5 DUP3 PUSH2 0x15E8 JUMP JUMPDEST POP PUSH1 0x20 DUP3 ADD MLOAD PUSH2 0x1435 PUSH1 0x20 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0x40 DUP3 ADD MLOAD PUSH2 0x1448 PUSH1 0x40 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP POP POP POP JUMP JUMPDEST DUP1 MLOAD PUSH1 0x0 SWAP1 PUSH2 0x180 DUP5 ADD SWAP1 PUSH2 0x1463 DUP6 DUP3 PUSH2 0x117D JUMP JUMPDEST POP PUSH1 0x20 DUP4 ADD MLOAD PUSH2 0x1476 PUSH1 0x20 DUP7 ADD DUP3 PUSH2 0x117D JUMP JUMPDEST POP PUSH1 0x40 DUP4 ADD MLOAD PUSH2 0x1489 PUSH1 0x40 DUP7 ADD DUP3 PUSH2 0x117D JUMP JUMPDEST POP PUSH1 0x60 DUP4 ADD MLOAD PUSH2 0x149C PUSH1 0x60 DUP7 ADD DUP3 PUSH2 0x117D JUMP JUMPDEST POP PUSH1 0x80 DUP4 ADD MLOAD PUSH2 0x14AF PUSH1 0x80 DUP7 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0xA0 DUP4 ADD MLOAD PUSH2 0x14C2 PUSH1 0xA0 DUP7 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0xC0 DUP4 ADD MLOAD PUSH2 0x14D5 PUSH1 0xC0 DUP7 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0xE0 DUP4 ADD MLOAD PUSH2 0x14E8 PUSH1 0xE0 DUP7 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH2 0x100 DUP4 ADD MLOAD PUSH2 0x14FD PUSH2 0x100 DUP7 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH2 0x120 DUP4 ADD MLOAD PUSH2 0x1512 PUSH2 0x120 DUP7 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH2 0x140 DUP4 ADD MLOAD DUP5 DUP3 SUB PUSH2 0x140 DUP7 ADD MSTORE PUSH2 0x152C DUP3 DUP3 PUSH2 0x12AA JUMP JUMPDEST SWAP2 POP POP PUSH2 0x160 DUP4 ADD MLOAD DUP5 DUP3 SUB PUSH2 0x160 DUP7 ADD MSTORE PUSH2 0x1548 DUP3 DUP3 PUSH2 0x12AA JUMP JUMPDEST SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST DUP1 MLOAD PUSH2 0x100 DUP4 ADD SWAP1 PUSH2 0x1563 DUP5 DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0x20 DUP3 ADD MLOAD PUSH2 0x1576 PUSH1 0x20 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0x40 DUP3 ADD MLOAD PUSH2 0x1589 PUSH1 0x40 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0x60 DUP3 ADD MLOAD PUSH2 0x159C PUSH1 0x60 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0x80 DUP3 ADD MLOAD PUSH2 0x15AF PUSH1 0x80 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0xA0 DUP3 ADD MLOAD PUSH2 0x15C2 PUSH1 0xA0 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0xC0 DUP3 ADD MLOAD PUSH2 0x15D5 PUSH1 0xC0 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0xE0 DUP3 ADD MLOAD PUSH2 0x1448 PUSH1 0xE0 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST PUSH2 0x1186 DUP2 PUSH2 0x17ED JUMP JUMPDEST PUSH1 0x20 DUP2 ADD PUSH2 0x96A DUP3 DUP5 PUSH2 0x117D JUMP JUMPDEST PUSH1 0x40 DUP2 ADD PUSH2 0x160D DUP3 DUP6 PUSH2 0x117D JUMP JUMPDEST PUSH2 0xB68 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x117D JUMP JUMPDEST PUSH1 0x40 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x162B DUP2 DUP6 PUSH2 0x118C JUMP JUMPDEST SWAP1 POP DUP2 DUP2 SUB PUSH1 0x20 DUP4 ADD MSTORE PUSH2 0xFBE DUP2 DUP5 PUSH2 0x124A JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0xB68 DUP2 DUP5 PUSH2 0x11E3 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0xB68 DUP2 DUP5 PUSH2 0x124A JUMP JUMPDEST PUSH1 0x20 DUP2 ADD PUSH2 0x96A DUP3 DUP5 PUSH2 0x12A1 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x96A DUP2 PUSH2 0x12DF JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x96A DUP2 PUSH2 0x1335 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x96A DUP2 PUSH2 0x1365 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x96A DUP2 PUSH2 0x13BB JUMP JUMPDEST PUSH2 0x160 DUP2 ADD PUSH2 0x16BE DUP3 DUP6 PUSH2 0x1411 JUMP JUMPDEST PUSH2 0xB68 PUSH1 0x60 DUP4 ADD DUP5 PUSH2 0x1551 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0xB68 DUP2 DUP5 PUSH2 0x144E JUMP JUMPDEST PUSH2 0x100 DUP2 ADD PUSH2 0x96A DUP3 DUP5 PUSH2 0x1551 JUMP JUMPDEST PUSH1 0x20 DUP2 ADD PUSH2 0x96A DUP3 DUP5 PUSH2 0x1298 JUMP JUMPDEST PUSH1 0x40 DUP2 ADD PUSH2 0x1707 DUP3 DUP6 PUSH2 0x1298 JUMP JUMPDEST PUSH2 0xB68 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x1298 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x1733 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT ISZERO PUSH2 0x1752 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 SWAP1 DUP2 MUL ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT ISZERO PUSH2 0x1773 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 PUSH1 0x1F SWAP2 SWAP1 SWAP2 ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND ADD SWAP1 JUMP JUMPDEST PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST MLOAD SWAP1 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 AND SWAP1 JUMP JUMPDEST PUSH1 0xFF AND 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 0x181F JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x1807 JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x1448 JUMPI POP POP PUSH1 0x0 SWAP2 ADD MSTORE JUMP JUMPDEST PUSH1 0x1F ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND SWAP1 JUMP STOP LOG2 PUSH6 0x627A7A723058 KECCAK256 SMOD TIMESTAMP MSIZE CODESIZE NUMBER 0xde DIV 0xcc 0xb4 TIMESTAMP CALLCODE 0x5f 0x24 PUSH21 0xFF7A322E1281CDB1232118C18B3985166E7F6C6578 PUSH17 0x6572696D656E74616CF500370000000000 ", - "sourceMap": "898:7576:11:-;;;1916:167;8:9:-1;5:2;;;30:1;27;20:12;5:2;1916:167:11;;;;;;;;;;;;;;;;;;;;;;;;2005:8;:31;;-1:-1:-1;;;;;;2005:31:11;-1:-1:-1;;;;;2005:31:11;;;;;2046:30;;;;-1:-1:-1;;2046:30:11;;;;;:::i;:::-;;1916:167;;898:7576;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;898:7576:11;;;-1:-1:-1;898:7576:11;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::o;5:122:-1:-;;83:39;114:6;108:13;83:39;;;74:48;68:59;-1:-1;;;68:59;135:442;;240:4;228:17;;224:27;-1:-1;214:2;;265:1;262;255:12;214:2;295:6;289:13;317:64;332:48;373:6;332:48;;;317:64;;;308:73;;401:6;394:5;387:21;437:4;429:6;425:17;470:4;463:5;459:16;505:3;496:6;491:3;487:16;484:25;481:2;;;522:1;519;512:12;481:2;532:39;564:6;559:3;554;532:39;;;207:370;;;;;;;;585:496;;;726:2;714:9;705:7;701:23;697:32;694:2;;;742:1;739;732:12;694:2;777:1;794:64;850:7;830:9;794:64;;;784:74;;756:108;916:2;905:9;901:18;895:25;-1:-1;;;;;932:6;929:30;926:2;;;972:1;969;962:12;926:2;992:73;1057:7;1048:6;1037:9;1033:22;992:73;;;982:83;;874:197;688:393;;;;;;1088:256;1150:2;1144:9;1176:17;;;-1:-1;;;;;1236:34;;1272:22;;;1233:62;1230:2;;;1308:1;1305;1298:12;1230:2;1324;1317:22;1128:216;;-1:-1;1128:216;1351:258;;-1:-1;;;;;1486:6;1483:30;1480:2;;;1526:1;1523;1516:12;1480:2;-1:-1;1599:4;1570;1547:17;;;;-1:-1;;1543:33;1589:15;;1417:192;1616:128;-1:-1;;;;;1685:54;;1668:76;1752:268;1817:1;1824:101;1838:6;1835:1;1832:13;1824:101;;;1905:11;;;1899:18;1886:11;;;1879:39;1860:2;1853:10;1824:101;;;1940:6;1937:1;1934:13;1931:2;;;2005:1;1996:6;1991:3;1987:16;1980:27;1931:2;1801:219;;;;;;898:7576:11;;;;;;" + "object": "0x60806040523480156200001157600080fd5b5060405162001d3a38038062001d3a833981018060405262000037919081019062000186565b60008054600160a060020a031916600160a060020a03841617905580516200006790600190602084019062000070565b5050506200026b565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620000b357805160ff1916838001178555620000e3565b82800160010185558215620000e3579182015b82811115620000e3578251825591602001919060010190620000c6565b50620000f1929150620000f5565b5090565b6200011291905b80821115620000f15760008155600101620000fc565b90565b60006200012382516200022c565b9392505050565b6000601f820183136200013c57600080fd5b8151620001536200014d8262000204565b620001dd565b915080825260208301602083018583830111156200017057600080fd5b6200017d83828462000238565b50505092915050565b600080604083850312156200019a57600080fd5b6000620001a8858562000115565b92505060208301516001604060020a03811115620001c557600080fd5b620001d3858286016200012a565b9150509250929050565b6040518181016001604060020a0381118282101715620001fc57600080fd5b604052919050565b60006001604060020a038211156200021b57600080fd5b506020601f91909101601f19160190565b600160a060020a031690565b60005b83811015620002555781810151838201526020016200023b565b8381111562000265576000848401525b50505050565b611abf806200027b6000396000f3006080604052600436106100825763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166304ad1e5381146100875780632cd0fc73146100be5780634b95de13146100ec578063690d31141461011a578063b698846314610147578063c6b7f4ee14610174578063f241ffb0146101a2575b600080fd5b34801561009357600080fd5b506100a76100a23660046112d3565b6101cf565b6040516100b59291906118dc565b60405180910390f35b3480156100ca57600080fd5b506100de6100d936600461118b565b61029c565b6040516100b5929190611926565b3480156100f857600080fd5b5061010c610107366004611238565b6107cd565b6040516100b5929190611822565b34801561012657600080fd5b5061013a610135366004611238565b6108a4565b6040516100b59190611858565b34801561015357600080fd5b506101676101623660046111d3565b61095e565b6040516100b591906117f9565b34801561018057600080fd5b5061019461018f366004611139565b6109a9565b6040516100b5929190611869565b3480156101ae57600080fd5b506101c26101bd3660046112d3565b610a86565b6040516100b59190611909565b6101d7610cd0565b6101df610cf0565b6000546040517fc75e0a8100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063c75e0a81906102359087906004016118f8565b606060405180830381600087803b15801561024f57600080fd5b505af1158015610263573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061028791908101906112b5565b91506102938484610a86565b90509250929050565b6000808080808080806102b5898263ffffffff610ba416565b95506102c889601063ffffffff610c1116565b6000546040517f6070410800000000000000000000000000000000000000000000000000000000815291965073ffffffffffffffffffffffffffffffffffffffff169063607041089061031f90899060040161188e565b602060405180830381600087803b15801561033957600080fd5b505af115801561034d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506103719190810190611113565b604080517f4552433230546f6b656e28616464726573732900000000000000000000000000815290519081900360130190209094507fffffffff0000000000000000000000000000000000000000000000000000000087811691161415610526576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8616906370a0823190610424908d906004016117f9565b602060405180830381600087803b15801561043e57600080fd5b505af1158015610452573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610476919081019061131a565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815290985073ffffffffffffffffffffffffffffffffffffffff86169063dd62ed3e906104cd908d908890600401611807565b602060405180830381600087803b1580156104e757600080fd5b505af11580156104fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061051f919081019061131a565b96506107c0565b604080517f455243373231546f6b656e28616464726573732c75696e7432353629000000008152905190819003601c0190207fffffffff00000000000000000000000000000000000000000000000000000000878116911614156107855761059589602463ffffffff610c7216565b92506105a1858461095e565b91508173ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16146105dd5760006105e0565b60015b60ff1697508473ffffffffffffffffffffffffffffffffffffffff1663e985e9c58b866040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040161063c929190611807565b602060405180830381600087803b15801561065657600080fd5b505af115801561066a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061068e9190810190611297565b8061076a57508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1663081812fc856040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016107009190611918565b602060405180830381600087803b15801561071a57600080fd5b505af115801561072e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107529190810190611113565b73ffffffffffffffffffffffffffffffffffffffff16145b90508061077857600061077b565b60015b60ff1696506107c0565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107b7906118ac565b60405180910390fd5b5050505050509250929050565b6000546040517f7e9d74dc000000000000000000000000000000000000000000000000000000008152606091829173ffffffffffffffffffffffffffffffffffffffff90911690637e9d74dc90610828908790600401611847565b600060405180830381600087803b15801561084257600080fd5b505af1158015610856573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261089c9190810190611203565b915061029384845b606060006060600085519250826040519080825280602002602001820160405280156108ea57816020015b6108d7610cf0565b8152602001906001900390816108cf5790505b509150600090505b80831461095157610931868281518110151561090a57fe5b90602001906020020151868381518110151561092257fe5b90602001906020020151610a86565b828281518110151561093f57fe5b602090810290910101526001016108f2565b8193505b50505092915050565b60006040517f6352211e000000000000000000000000000000000000000000000000000000008152826004820152602081602483875afa80156109a057815192505b50505b92915050565b6060806000606080600086519350836040519080825280602002602001820160405280156109e1578160200160208202803883390190505b50925083604051908082528060200260200182016040528015610a0e578160200160208202803883390190505b509150600090505b808414610a7957610a3e888883815181101515610a2f57fe5b9060200190602002015161029c565b8483815181101515610a4c57fe5b9060200190602002018484815181101515610a6357fe5b6020908102909101019190915252600101610a16565b5090969095509350505050565b610a8e610cf0565b6060610aa3846000015185610140015161029c565b60208401528252610160840151610abb90849061029c565b60608401526040808401919091526001805482516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101008688161502019094169390930492830181900481028201810190945281815292830182828015610b6a5780601f10610b3f57610100808354040283529160200191610b6a565b820191906000526020600020905b815481529060010190602001808311610b4d57829003601f168201915b50505050509050610b7f84600001518261029c565b60a08401526080830152610b93838261029c565b60e084015260c08301525092915050565b600081600401835110151515610be6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107b7906118cc565b5050602001517fffffffff000000000000000000000000000000000000000000000000000000001690565b600081601401835110151515610c53576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107b7906118bc565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b6000610c7e8383610c85565b9392505050565b600081602001835110151515610cc7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107b79061189c565b50016020015190565b604080516060810182526000808252602082018190529181019190915290565b6101006040519081016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000610c7e82356119d9565b6000610c7e82516119d9565b6000601f82018313610d5f57600080fd5b8135610d72610d6d82611968565b611941565b91508181835260208401935060208101905083856020840282011115610d9757600080fd5b60005b83811015610dc35781610dad8882610d36565b8452506020928301929190910190600101610d9a565b5050505092915050565b6000601f82018313610dde57600080fd5b8135610dec610d6d82611968565b81815260209384019390925082018360005b83811015610dc35781358601610e148882610f11565b8452506020928301929190910190600101610dfe565b6000601f82018313610e3b57600080fd5b8151610e49610d6d82611968565b91508181835260208401935060208101905083856060840282011115610e6e57600080fd5b60005b83811015610dc35781610e848882610f57565b84525060209092019160609190910190600101610e71565b6000601f82018313610ead57600080fd5b8135610ebb610d6d82611968565b81815260209384019390925082018360005b83811015610dc35781358601610ee38882610fb2565b8452506020928301929190910190600101610ecd565b6000610c7e8251611a20565b6000610c7e82516119f2565b6000601f82018313610f2257600080fd5b8135610f30610d6d82611989565b91508082526020830160208301858383011115610f4c57600080fd5b610955838284611a25565b600060608284031215610f6957600080fd5b610f736060611941565b90506000610f818484611107565b8252506020610f9284848301610f05565b6020830152506040610fa684828501610f05565b60408301525092915050565b60006101808284031215610fc557600080fd5b610fd0610180611941565b90506000610fde8484610d36565b8252506020610fef84848301610d36565b602083015250604061100384828501610d36565b604083015250606061101784828501610d36565b606083015250608061102b848285016110fb565b60808301525060a061103f848285016110fb565b60a08301525060c0611053848285016110fb565b60c08301525060e0611067848285016110fb565b60e08301525061010061107c848285016110fb565b61010083015250610120611092848285016110fb565b6101208301525061014082013567ffffffffffffffff8111156110b457600080fd5b6110c084828501610f11565b6101408301525061016082013567ffffffffffffffff8111156110e257600080fd5b6110ee84828501610f11565b6101608301525092915050565b6000610c7e82356119f2565b6000610c7e8251611a1a565b60006020828403121561112557600080fd5b60006111318484610d42565b949350505050565b6000806040838503121561114c57600080fd5b60006111588585610d36565b925050602083013567ffffffffffffffff81111561117557600080fd5b61118185828601610dcd565b9150509250929050565b6000806040838503121561119e57600080fd5b60006111aa8585610d36565b925050602083013567ffffffffffffffff8111156111c757600080fd5b61118185828601610f11565b600080604083850312156111e657600080fd5b60006111f28585610d36565b9250506020611181858286016110fb565b60006020828403121561121557600080fd5b815167ffffffffffffffff81111561122c57600080fd5b61113184828501610e2a565b6000806040838503121561124b57600080fd5b823567ffffffffffffffff81111561126257600080fd5b61126e85828601610e9c565b925050602083013567ffffffffffffffff81111561128b57600080fd5b61118185828601610d4e565b6000602082840312156112a957600080fd5b60006111318484610ef9565b6000606082840312156112c757600080fd5b60006111318484610f57565b600080604083850312156112e657600080fd5b823567ffffffffffffffff8111156112fd57600080fd5b61130985828601610fb2565b925050602061118185828601610d36565b60006020828403121561132c57600080fd5b60006111318484610f05565b611341816119d9565b82525050565b6000611352826119d5565b808452602084019350611364836119cf565b60005b828110156113945761137a868351611619565b611383826119cf565b606096909601959150600101611367565b5093949350505050565b60006113a9826119d5565b808452602084019350836020820285016113c2856119cf565b60005b848110156113f95783830388526113dd838351611656565b92506113e8826119cf565b6020989098019791506001016113c5565b50909695505050505050565b6000611410826119d5565b808452602084019350611422836119cf565b60005b8281101561139457611438868351611759565b611441826119cf565b61010096909601959150600101611425565b600061145e826119d5565b808452602084019350611470836119cf565b60005b82811015611394576114868683516114a0565b61148f826119cf565b602096909601959150600101611473565b611341816119f2565b611341816119f5565b60006114bd826119d5565b8084526114d1816020860160208601611a31565b6114da81611a5d565b9093016020019392505050565b602681527f475245415445525f4f525f455155414c5f544f5f33325f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601781527f554e535550504f525445445f41535345545f50524f5859000000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b602581527f475245415445525f4f525f455155414c5f544f5f345f4c454e4754485f52455160208201527f5549524544000000000000000000000000000000000000000000000000000000604082015260600190565b8051606083019061162a84826117f0565b50602082015161163d60208501826114a0565b50604082015161165060408501826114a0565b50505050565b805160009061018084019061166b8582611338565b50602083015161167e6020860182611338565b5060408301516116916040860182611338565b5060608301516116a46060860182611338565b5060808301516116b760808601826114a0565b5060a08301516116ca60a08601826114a0565b5060c08301516116dd60c08601826114a0565b5060e08301516116f060e08601826114a0565b506101008301516117056101008601826114a0565b5061012083015161171a6101208601826114a0565b5061014083015184820361014086015261173482826114b2565b91505061016083015184820361016086015261175082826114b2565b95945050505050565b805161010083019061176b84826114a0565b50602082015161177e60208501826114a0565b50604082015161179160408501826114a0565b5060608201516117a460608501826114a0565b5060808201516117b760808501826114a0565b5060a08201516117ca60a08501826114a0565b5060c08201516117dd60c08501826114a0565b5060e082015161165060e08501826114a0565b61134181611a1a565b602081016109a38284611338565b604081016118158285611338565b610c7e6020830184611338565b604080825281016118338185611347565b905081810360208301526111318184611405565b60208082528101610c7e818461139e565b60208082528101610c7e8184611405565b6040808252810161187a8185611453565b905081810360208301526111318184611453565b602081016109a382846114a9565b602080825281016109a3816114e7565b602080825281016109a38161153d565b602080825281016109a38161156d565b602080825281016109a3816115c3565b61016081016118eb8285611619565b610c7e6060830184611759565b60208082528101610c7e8184611656565b61010081016109a38284611759565b602081016109a382846114a0565b6040810161193482856114a0565b610c7e60208301846114a0565b60405181810167ffffffffffffffff8111828210171561196057600080fd5b604052919050565b600067ffffffffffffffff82111561197f57600080fd5b5060209081020190565b600067ffffffffffffffff8211156119a057600080fd5b506020601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b60200190565b5190565b73ffffffffffffffffffffffffffffffffffffffff1690565b90565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b60ff1690565b151590565b82818337506000910152565b60005b83811015611a4c578181015183820152602001611a34565b838111156116505750506000910152565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016905600a265627a7a72305820d3d495bc287663ed8cb2a513cfad47804ffa6e4ad0cfa6d0d0eadf1f907483586c6578706572696d656e74616cf50037", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1D3A CODESIZE SUB DUP1 PUSH3 0x1D3A DUP4 CODECOPY DUP2 ADD DUP1 PUSH1 0x40 MSTORE PUSH3 0x37 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH3 0x186 JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB NOT AND PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB DUP5 AND OR SWAP1 SSTORE DUP1 MLOAD PUSH3 0x67 SWAP1 PUSH1 0x1 SWAP1 PUSH1 0x20 DUP5 ADD SWAP1 PUSH3 0x70 JUMP JUMPDEST POP POP POP PUSH3 0x26B JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0xB3 JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0xE3 JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0xE3 JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0xE3 JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0xC6 JUMP JUMPDEST POP PUSH3 0xF1 SWAP3 SWAP2 POP PUSH3 0xF5 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x112 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0xF1 JUMPI PUSH1 0x0 DUP2 SSTORE PUSH1 0x1 ADD PUSH3 0xFC JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH3 0x123 DUP3 MLOAD PUSH3 0x22C JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH3 0x13C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 MLOAD PUSH3 0x153 PUSH3 0x14D DUP3 PUSH3 0x204 JUMP JUMPDEST PUSH3 0x1DD JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE PUSH1 0x20 DUP4 ADD PUSH1 0x20 DUP4 ADD DUP6 DUP4 DUP4 ADD GT ISZERO PUSH3 0x170 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH3 0x17D DUP4 DUP3 DUP5 PUSH3 0x238 JUMP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH3 0x19A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH3 0x1A8 DUP6 DUP6 PUSH3 0x115 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 DUP4 ADD MLOAD PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP2 GT ISZERO PUSH3 0x1C5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH3 0x1D3 DUP6 DUP3 DUP7 ADD PUSH3 0x12A JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH3 0x1FC JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x40 PUSH1 0x2 EXP SUB DUP3 GT ISZERO PUSH3 0x21B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 PUSH1 0x1F SWAP2 SWAP1 SWAP2 ADD PUSH1 0x1F NOT AND ADD SWAP1 JUMP JUMPDEST PUSH1 0x1 PUSH1 0xA0 PUSH1 0x2 EXP SUB AND SWAP1 JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH3 0x255 JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH3 0x23B JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH3 0x265 JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH2 0x1ABF DUP1 PUSH3 0x27B PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x82 JUMPI PUSH4 0xFFFFFFFF PUSH29 0x100000000000000000000000000000000000000000000000000000000 PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0x4AD1E53 DUP2 EQ PUSH2 0x87 JUMPI DUP1 PUSH4 0x2CD0FC73 EQ PUSH2 0xBE JUMPI DUP1 PUSH4 0x4B95DE13 EQ PUSH2 0xEC JUMPI DUP1 PUSH4 0x690D3114 EQ PUSH2 0x11A JUMPI DUP1 PUSH4 0xB6988463 EQ PUSH2 0x147 JUMPI DUP1 PUSH4 0xC6B7F4EE EQ PUSH2 0x174 JUMPI DUP1 PUSH4 0xF241FFB0 EQ PUSH2 0x1A2 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x93 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xA7 PUSH2 0xA2 CALLDATASIZE PUSH1 0x4 PUSH2 0x12D3 JUMP JUMPDEST PUSH2 0x1CF JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xB5 SWAP3 SWAP2 SWAP1 PUSH2 0x18DC JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0xCA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xDE PUSH2 0xD9 CALLDATASIZE PUSH1 0x4 PUSH2 0x118B JUMP JUMPDEST PUSH2 0x29C JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xB5 SWAP3 SWAP2 SWAP1 PUSH2 0x1926 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0xF8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x10C PUSH2 0x107 CALLDATASIZE PUSH1 0x4 PUSH2 0x1238 JUMP JUMPDEST PUSH2 0x7CD JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xB5 SWAP3 SWAP2 SWAP1 PUSH2 0x1822 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x126 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x13A PUSH2 0x135 CALLDATASIZE PUSH1 0x4 PUSH2 0x1238 JUMP JUMPDEST PUSH2 0x8A4 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xB5 SWAP2 SWAP1 PUSH2 0x1858 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x153 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x167 PUSH2 0x162 CALLDATASIZE PUSH1 0x4 PUSH2 0x11D3 JUMP JUMPDEST PUSH2 0x95E JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xB5 SWAP2 SWAP1 PUSH2 0x17F9 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x180 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x194 PUSH2 0x18F CALLDATASIZE PUSH1 0x4 PUSH2 0x1139 JUMP JUMPDEST PUSH2 0x9A9 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xB5 SWAP3 SWAP2 SWAP1 PUSH2 0x1869 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1AE JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x1C2 PUSH2 0x1BD CALLDATASIZE PUSH1 0x4 PUSH2 0x12D3 JUMP JUMPDEST PUSH2 0xA86 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xB5 SWAP2 SWAP1 PUSH2 0x1909 JUMP JUMPDEST PUSH2 0x1D7 PUSH2 0xCD0 JUMP JUMPDEST PUSH2 0x1DF PUSH2 0xCF0 JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH1 0x40 MLOAD PUSH32 0xC75E0A8100000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP2 AND SWAP1 PUSH4 0xC75E0A81 SWAP1 PUSH2 0x235 SWAP1 DUP8 SWAP1 PUSH1 0x4 ADD PUSH2 0x18F8 JUMP JUMPDEST PUSH1 0x60 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x24F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x263 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 0x287 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12B5 JUMP JUMPDEST SWAP2 POP PUSH2 0x293 DUP5 DUP5 PUSH2 0xA86 JUMP JUMPDEST SWAP1 POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP1 DUP1 DUP1 DUP1 DUP1 DUP1 PUSH2 0x2B5 DUP10 DUP3 PUSH4 0xFFFFFFFF PUSH2 0xBA4 AND JUMP JUMPDEST SWAP6 POP PUSH2 0x2C8 DUP10 PUSH1 0x10 PUSH4 0xFFFFFFFF PUSH2 0xC11 AND JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH1 0x40 MLOAD PUSH32 0x6070410800000000000000000000000000000000000000000000000000000000 DUP2 MSTORE SWAP2 SWAP7 POP PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH4 0x60704108 SWAP1 PUSH2 0x31F SWAP1 DUP10 SWAP1 PUSH1 0x4 ADD PUSH2 0x188E JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x339 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x34D 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 0x371 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1113 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0x4552433230546F6B656E28616464726573732900000000000000000000000000 DUP2 MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x13 ADD SWAP1 KECCAK256 SWAP1 SWAP5 POP PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 DUP8 DUP2 AND SWAP2 AND EQ ISZERO PUSH2 0x526 JUMPI PUSH1 0x40 MLOAD PUSH32 0x70A0823100000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP7 AND SWAP1 PUSH4 0x70A08231 SWAP1 PUSH2 0x424 SWAP1 DUP14 SWAP1 PUSH1 0x4 ADD PUSH2 0x17F9 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x43E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x452 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 0x476 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x131A JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0xDD62ED3E00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE SWAP1 SWAP9 POP PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP7 AND SWAP1 PUSH4 0xDD62ED3E SWAP1 PUSH2 0x4CD SWAP1 DUP14 SWAP1 DUP9 SWAP1 PUSH1 0x4 ADD PUSH2 0x1807 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x4E7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x4FB 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 0x51F SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x131A JUMP JUMPDEST SWAP7 POP PUSH2 0x7C0 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0x455243373231546F6B656E28616464726573732C75696E743235362900000000 DUP2 MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x1C ADD SWAP1 KECCAK256 PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 DUP8 DUP2 AND SWAP2 AND EQ ISZERO PUSH2 0x785 JUMPI PUSH2 0x595 DUP10 PUSH1 0x24 PUSH4 0xFFFFFFFF PUSH2 0xC72 AND JUMP JUMPDEST SWAP3 POP PUSH2 0x5A1 DUP6 DUP5 PUSH2 0x95E JUMP JUMPDEST SWAP2 POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ PUSH2 0x5DD JUMPI PUSH1 0x0 PUSH2 0x5E0 JUMP JUMPDEST PUSH1 0x1 JUMPDEST PUSH1 0xFF AND SWAP8 POP DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH4 0xE985E9C5 DUP12 DUP7 PUSH1 0x40 MLOAD DUP4 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x63C SWAP3 SWAP2 SWAP1 PUSH2 0x1807 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x656 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x66A 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 0x68E SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1297 JUMP JUMPDEST DUP1 PUSH2 0x76A JUMPI POP DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH4 0x81812FC DUP6 PUSH1 0x40 MLOAD DUP3 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x700 SWAP2 SWAP1 PUSH2 0x1918 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x71A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x72E 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 0x752 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1113 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ JUMPDEST SWAP1 POP DUP1 PUSH2 0x778 JUMPI PUSH1 0x0 PUSH2 0x77B JUMP JUMPDEST PUSH1 0x1 JUMPDEST PUSH1 0xFF AND SWAP7 POP PUSH2 0x7C0 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x7B7 SWAP1 PUSH2 0x18AC JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP POP POP POP POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH1 0x40 MLOAD PUSH32 0x7E9D74DC00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x60 SWAP2 DUP3 SWAP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP2 AND SWAP1 PUSH4 0x7E9D74DC SWAP1 PUSH2 0x828 SWAP1 DUP8 SWAP1 PUSH1 0x4 ADD PUSH2 0x1847 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x842 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x856 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP PUSH1 0x40 MLOAD RETURNDATASIZE PUSH1 0x0 DUP3 RETURNDATACOPY PUSH1 0x1F RETURNDATASIZE SWAP1 DUP2 ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND DUP3 ADD PUSH1 0x40 MSTORE PUSH2 0x89C SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1203 JUMP JUMPDEST SWAP2 POP PUSH2 0x293 DUP5 DUP5 JUMPDEST PUSH1 0x60 PUSH1 0x0 PUSH1 0x60 PUSH1 0x0 DUP6 MLOAD SWAP3 POP DUP3 PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x8EA JUMPI DUP2 PUSH1 0x20 ADD JUMPDEST PUSH2 0x8D7 PUSH2 0xCF0 JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD SWAP1 PUSH1 0x1 SWAP1 SUB SWAP1 DUP2 PUSH2 0x8CF JUMPI SWAP1 POP JUMPDEST POP SWAP2 POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP1 DUP4 EQ PUSH2 0x951 JUMPI PUSH2 0x931 DUP7 DUP3 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x90A JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD DUP7 DUP4 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x922 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH2 0xA86 JUMP JUMPDEST DUP3 DUP3 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x93F JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP1 SWAP2 ADD ADD MSTORE PUSH1 0x1 ADD PUSH2 0x8F2 JUMP JUMPDEST DUP2 SWAP4 POP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x40 MLOAD PUSH32 0x6352211E00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE DUP3 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x20 DUP2 PUSH1 0x24 DUP4 DUP8 GAS STATICCALL DUP1 ISZERO PUSH2 0x9A0 JUMPI DUP2 MLOAD SWAP3 POP JUMPDEST POP POP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x60 DUP1 PUSH1 0x0 PUSH1 0x60 DUP1 PUSH1 0x0 DUP7 MLOAD SWAP4 POP DUP4 PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x9E1 JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP3 POP DUP4 PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0xA0E JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP2 POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP1 DUP5 EQ PUSH2 0xA79 JUMPI PUSH2 0xA3E DUP9 DUP9 DUP4 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0xA2F JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH2 0x29C JUMP JUMPDEST DUP5 DUP4 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0xA4C JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD DUP5 DUP5 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0xA63 JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP1 SWAP2 ADD ADD SWAP2 SWAP1 SWAP2 MSTORE MSTORE PUSH1 0x1 ADD PUSH2 0xA16 JUMP JUMPDEST POP SWAP1 SWAP7 SWAP1 SWAP6 POP SWAP4 POP POP POP POP JUMP JUMPDEST PUSH2 0xA8E PUSH2 0xCF0 JUMP JUMPDEST PUSH1 0x60 PUSH2 0xAA3 DUP5 PUSH1 0x0 ADD MLOAD DUP6 PUSH2 0x140 ADD MLOAD PUSH2 0x29C JUMP JUMPDEST PUSH1 0x20 DUP5 ADD MSTORE DUP3 MSTORE PUSH2 0x160 DUP5 ADD MLOAD PUSH2 0xABB SWAP1 DUP5 SWAP1 PUSH2 0x29C JUMP JUMPDEST PUSH1 0x60 DUP5 ADD MSTORE PUSH1 0x40 DUP1 DUP5 ADD SWAP2 SWAP1 SWAP2 MSTORE PUSH1 0x1 DUP1 SLOAD DUP3 MLOAD PUSH1 0x20 PUSH1 0x1F PUSH1 0x2 PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF PUSH2 0x100 DUP7 DUP9 AND ISZERO MUL ADD SWAP1 SWAP5 AND SWAP4 SWAP1 SWAP4 DIV SWAP3 DUP4 ADD DUP2 SWAP1 DIV DUP2 MUL DUP3 ADD DUP2 ADD SWAP1 SWAP5 MSTORE DUP2 DUP2 MSTORE SWAP3 DUP4 ADD DUP3 DUP3 DUP1 ISZERO PUSH2 0xB6A JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xB3F JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xB6A JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xB4D JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP PUSH2 0xB7F DUP5 PUSH1 0x0 ADD MLOAD DUP3 PUSH2 0x29C JUMP JUMPDEST PUSH1 0xA0 DUP5 ADD MSTORE PUSH1 0x80 DUP4 ADD MSTORE PUSH2 0xB93 DUP4 DUP3 PUSH2 0x29C JUMP JUMPDEST PUSH1 0xE0 DUP5 ADD MSTORE PUSH1 0xC0 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x4 ADD DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0xBE6 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x7B7 SWAP1 PUSH2 0x18CC JUMP JUMPDEST POP POP PUSH1 0x20 ADD MLOAD PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 AND SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x14 ADD DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0xC53 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x7B7 SWAP1 PUSH2 0x18BC JUMP JUMPDEST POP ADD PUSH1 0x14 ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xC7E DUP4 DUP4 PUSH2 0xC85 JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x20 ADD DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0xCC7 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x7B7 SWAP1 PUSH2 0x189C JUMP JUMPDEST POP ADD PUSH1 0x20 ADD MLOAD SWAP1 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x60 DUP2 ADD DUP3 MSTORE PUSH1 0x0 DUP1 DUP3 MSTORE PUSH1 0x20 DUP3 ADD DUP2 SWAP1 MSTORE SWAP2 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE SWAP1 JUMP JUMPDEST PUSH2 0x100 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 PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xC7E DUP3 CALLDATALOAD PUSH2 0x19D9 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xC7E DUP3 MLOAD PUSH2 0x19D9 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xD5F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xD72 PUSH2 0xD6D DUP3 PUSH2 0x1968 JUMP JUMPDEST PUSH2 0x1941 JUMP JUMPDEST SWAP2 POP DUP2 DUP2 DUP4 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH1 0x20 DUP2 ADD SWAP1 POP DUP4 DUP6 PUSH1 0x20 DUP5 MUL DUP3 ADD GT ISZERO PUSH2 0xD97 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xDC3 JUMPI DUP2 PUSH2 0xDAD DUP9 DUP3 PUSH2 0xD36 JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xD9A JUMP JUMPDEST POP POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xDDE JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xDEC PUSH2 0xD6D DUP3 PUSH2 0x1968 JUMP JUMPDEST DUP2 DUP2 MSTORE PUSH1 0x20 SWAP4 DUP5 ADD SWAP4 SWAP1 SWAP3 POP DUP3 ADD DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xDC3 JUMPI DUP2 CALLDATALOAD DUP7 ADD PUSH2 0xE14 DUP9 DUP3 PUSH2 0xF11 JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xDFE JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xE3B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 MLOAD PUSH2 0xE49 PUSH2 0xD6D DUP3 PUSH2 0x1968 JUMP JUMPDEST SWAP2 POP DUP2 DUP2 DUP4 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH1 0x20 DUP2 ADD SWAP1 POP DUP4 DUP6 PUSH1 0x60 DUP5 MUL DUP3 ADD GT ISZERO PUSH2 0xE6E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xDC3 JUMPI DUP2 PUSH2 0xE84 DUP9 DUP3 PUSH2 0xF57 JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 SWAP1 SWAP3 ADD SWAP2 PUSH1 0x60 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xE71 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xEAD JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xEBB PUSH2 0xD6D DUP3 PUSH2 0x1968 JUMP JUMPDEST DUP2 DUP2 MSTORE PUSH1 0x20 SWAP4 DUP5 ADD SWAP4 SWAP1 SWAP3 POP DUP3 ADD DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xDC3 JUMPI DUP2 CALLDATALOAD DUP7 ADD PUSH2 0xEE3 DUP9 DUP3 PUSH2 0xFB2 JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xECD JUMP JUMPDEST PUSH1 0x0 PUSH2 0xC7E DUP3 MLOAD PUSH2 0x1A20 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xC7E DUP3 MLOAD PUSH2 0x19F2 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xF22 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xF30 PUSH2 0xD6D DUP3 PUSH2 0x1989 JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE PUSH1 0x20 DUP4 ADD PUSH1 0x20 DUP4 ADD DUP6 DUP4 DUP4 ADD GT ISZERO PUSH2 0xF4C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x955 DUP4 DUP3 DUP5 PUSH2 0x1A25 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xF69 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xF73 PUSH1 0x60 PUSH2 0x1941 JUMP JUMPDEST SWAP1 POP PUSH1 0x0 PUSH2 0xF81 DUP5 DUP5 PUSH2 0x1107 JUMP JUMPDEST DUP3 MSTORE POP PUSH1 0x20 PUSH2 0xF92 DUP5 DUP5 DUP4 ADD PUSH2 0xF05 JUMP JUMPDEST PUSH1 0x20 DUP4 ADD MSTORE POP PUSH1 0x40 PUSH2 0xFA6 DUP5 DUP3 DUP6 ADD PUSH2 0xF05 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x180 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xFC5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xFD0 PUSH2 0x180 PUSH2 0x1941 JUMP JUMPDEST SWAP1 POP PUSH1 0x0 PUSH2 0xFDE DUP5 DUP5 PUSH2 0xD36 JUMP JUMPDEST DUP3 MSTORE POP PUSH1 0x20 PUSH2 0xFEF DUP5 DUP5 DUP4 ADD PUSH2 0xD36 JUMP JUMPDEST PUSH1 0x20 DUP4 ADD MSTORE POP PUSH1 0x40 PUSH2 0x1003 DUP5 DUP3 DUP6 ADD PUSH2 0xD36 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MSTORE POP PUSH1 0x60 PUSH2 0x1017 DUP5 DUP3 DUP6 ADD PUSH2 0xD36 JUMP JUMPDEST PUSH1 0x60 DUP4 ADD MSTORE POP PUSH1 0x80 PUSH2 0x102B DUP5 DUP3 DUP6 ADD PUSH2 0x10FB JUMP JUMPDEST PUSH1 0x80 DUP4 ADD MSTORE POP PUSH1 0xA0 PUSH2 0x103F DUP5 DUP3 DUP6 ADD PUSH2 0x10FB JUMP JUMPDEST PUSH1 0xA0 DUP4 ADD MSTORE POP PUSH1 0xC0 PUSH2 0x1053 DUP5 DUP3 DUP6 ADD PUSH2 0x10FB JUMP JUMPDEST PUSH1 0xC0 DUP4 ADD MSTORE POP PUSH1 0xE0 PUSH2 0x1067 DUP5 DUP3 DUP6 ADD PUSH2 0x10FB JUMP JUMPDEST PUSH1 0xE0 DUP4 ADD MSTORE POP PUSH2 0x100 PUSH2 0x107C DUP5 DUP3 DUP6 ADD PUSH2 0x10FB JUMP JUMPDEST PUSH2 0x100 DUP4 ADD MSTORE POP PUSH2 0x120 PUSH2 0x1092 DUP5 DUP3 DUP6 ADD PUSH2 0x10FB JUMP JUMPDEST PUSH2 0x120 DUP4 ADD MSTORE POP PUSH2 0x140 DUP3 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x10B4 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x10C0 DUP5 DUP3 DUP6 ADD PUSH2 0xF11 JUMP JUMPDEST PUSH2 0x140 DUP4 ADD MSTORE POP PUSH2 0x160 DUP3 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x10E2 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x10EE DUP5 DUP3 DUP6 ADD PUSH2 0xF11 JUMP JUMPDEST PUSH2 0x160 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0xC7E DUP3 CALLDATALOAD PUSH2 0x19F2 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xC7E DUP3 MLOAD PUSH2 0x1A1A JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x1125 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1131 DUP5 DUP5 PUSH2 0xD42 JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x114C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1158 DUP6 DUP6 PUSH2 0xD36 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 DUP4 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x1175 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1181 DUP6 DUP3 DUP7 ADD PUSH2 0xDCD JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x119E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x11AA DUP6 DUP6 PUSH2 0xD36 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 DUP4 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x11C7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1181 DUP6 DUP3 DUP7 ADD PUSH2 0xF11 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x11E6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x11F2 DUP6 DUP6 PUSH2 0xD36 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 PUSH2 0x1181 DUP6 DUP3 DUP7 ADD PUSH2 0x10FB JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x1215 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x122C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1131 DUP5 DUP3 DUP6 ADD PUSH2 0xE2A JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x124B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x1262 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x126E DUP6 DUP3 DUP7 ADD PUSH2 0xE9C JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 DUP4 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x128B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1181 DUP6 DUP3 DUP7 ADD PUSH2 0xD4E JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x12A9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1131 DUP5 DUP5 PUSH2 0xEF9 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x12C7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1131 DUP5 DUP5 PUSH2 0xF57 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x12E6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x12FD JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1309 DUP6 DUP3 DUP7 ADD PUSH2 0xFB2 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 PUSH2 0x1181 DUP6 DUP3 DUP7 ADD PUSH2 0xD36 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x132C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1131 DUP5 DUP5 PUSH2 0xF05 JUMP JUMPDEST PUSH2 0x1341 DUP2 PUSH2 0x19D9 JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x1352 DUP3 PUSH2 0x19D5 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH2 0x1364 DUP4 PUSH2 0x19CF JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x1394 JUMPI PUSH2 0x137A DUP7 DUP4 MLOAD PUSH2 0x1619 JUMP JUMPDEST PUSH2 0x1383 DUP3 PUSH2 0x19CF JUMP JUMPDEST PUSH1 0x60 SWAP7 SWAP1 SWAP7 ADD SWAP6 SWAP2 POP PUSH1 0x1 ADD PUSH2 0x1367 JUMP JUMPDEST POP SWAP4 SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x13A9 DUP3 PUSH2 0x19D5 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP DUP4 PUSH1 0x20 DUP3 MUL DUP6 ADD PUSH2 0x13C2 DUP6 PUSH2 0x19CF JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP5 DUP2 LT ISZERO PUSH2 0x13F9 JUMPI DUP4 DUP4 SUB DUP9 MSTORE PUSH2 0x13DD DUP4 DUP4 MLOAD PUSH2 0x1656 JUMP JUMPDEST SWAP3 POP PUSH2 0x13E8 DUP3 PUSH2 0x19CF JUMP JUMPDEST PUSH1 0x20 SWAP9 SWAP1 SWAP9 ADD SWAP8 SWAP2 POP PUSH1 0x1 ADD PUSH2 0x13C5 JUMP JUMPDEST POP SWAP1 SWAP7 SWAP6 POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x1410 DUP3 PUSH2 0x19D5 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH2 0x1422 DUP4 PUSH2 0x19CF JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x1394 JUMPI PUSH2 0x1438 DUP7 DUP4 MLOAD PUSH2 0x1759 JUMP JUMPDEST PUSH2 0x1441 DUP3 PUSH2 0x19CF JUMP JUMPDEST PUSH2 0x100 SWAP7 SWAP1 SWAP7 ADD SWAP6 SWAP2 POP PUSH1 0x1 ADD PUSH2 0x1425 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x145E DUP3 PUSH2 0x19D5 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH2 0x1470 DUP4 PUSH2 0x19CF JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x1394 JUMPI PUSH2 0x1486 DUP7 DUP4 MLOAD PUSH2 0x14A0 JUMP JUMPDEST PUSH2 0x148F DUP3 PUSH2 0x19CF JUMP JUMPDEST PUSH1 0x20 SWAP7 SWAP1 SWAP7 ADD SWAP6 SWAP2 POP PUSH1 0x1 ADD PUSH2 0x1473 JUMP JUMPDEST PUSH2 0x1341 DUP2 PUSH2 0x19F2 JUMP JUMPDEST PUSH2 0x1341 DUP2 PUSH2 0x19F5 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x14BD DUP3 PUSH2 0x19D5 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH2 0x14D1 DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x1A31 JUMP JUMPDEST PUSH2 0x14DA DUP2 PUSH2 0x1A5D JUMP JUMPDEST SWAP1 SWAP4 ADD PUSH1 0x20 ADD SWAP4 SWAP3 POP POP POP 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 0x17 DUP2 MSTORE PUSH32 0x554E535550504F525445445F41535345545F50524F5859000000000000000000 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 0x25 DUP2 MSTORE PUSH32 0x475245415445525F4F525F455155414C5F544F5F345F4C454E4754485F524551 PUSH1 0x20 DUP3 ADD MSTORE PUSH32 0x5549524544000000000000000000000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST DUP1 MLOAD PUSH1 0x60 DUP4 ADD SWAP1 PUSH2 0x162A DUP5 DUP3 PUSH2 0x17F0 JUMP JUMPDEST POP PUSH1 0x20 DUP3 ADD MLOAD PUSH2 0x163D PUSH1 0x20 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0x40 DUP3 ADD MLOAD PUSH2 0x1650 PUSH1 0x40 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP POP POP POP JUMP JUMPDEST DUP1 MLOAD PUSH1 0x0 SWAP1 PUSH2 0x180 DUP5 ADD SWAP1 PUSH2 0x166B DUP6 DUP3 PUSH2 0x1338 JUMP JUMPDEST POP PUSH1 0x20 DUP4 ADD MLOAD PUSH2 0x167E PUSH1 0x20 DUP7 ADD DUP3 PUSH2 0x1338 JUMP JUMPDEST POP PUSH1 0x40 DUP4 ADD MLOAD PUSH2 0x1691 PUSH1 0x40 DUP7 ADD DUP3 PUSH2 0x1338 JUMP JUMPDEST POP PUSH1 0x60 DUP4 ADD MLOAD PUSH2 0x16A4 PUSH1 0x60 DUP7 ADD DUP3 PUSH2 0x1338 JUMP JUMPDEST POP PUSH1 0x80 DUP4 ADD MLOAD PUSH2 0x16B7 PUSH1 0x80 DUP7 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0xA0 DUP4 ADD MLOAD PUSH2 0x16CA PUSH1 0xA0 DUP7 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0xC0 DUP4 ADD MLOAD PUSH2 0x16DD PUSH1 0xC0 DUP7 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0xE0 DUP4 ADD MLOAD PUSH2 0x16F0 PUSH1 0xE0 DUP7 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH2 0x100 DUP4 ADD MLOAD PUSH2 0x1705 PUSH2 0x100 DUP7 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH2 0x120 DUP4 ADD MLOAD PUSH2 0x171A PUSH2 0x120 DUP7 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH2 0x140 DUP4 ADD MLOAD DUP5 DUP3 SUB PUSH2 0x140 DUP7 ADD MSTORE PUSH2 0x1734 DUP3 DUP3 PUSH2 0x14B2 JUMP JUMPDEST SWAP2 POP POP PUSH2 0x160 DUP4 ADD MLOAD DUP5 DUP3 SUB PUSH2 0x160 DUP7 ADD MSTORE PUSH2 0x1750 DUP3 DUP3 PUSH2 0x14B2 JUMP JUMPDEST SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST DUP1 MLOAD PUSH2 0x100 DUP4 ADD SWAP1 PUSH2 0x176B DUP5 DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0x20 DUP3 ADD MLOAD PUSH2 0x177E PUSH1 0x20 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0x40 DUP3 ADD MLOAD PUSH2 0x1791 PUSH1 0x40 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0x60 DUP3 ADD MLOAD PUSH2 0x17A4 PUSH1 0x60 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0x80 DUP3 ADD MLOAD PUSH2 0x17B7 PUSH1 0x80 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0xA0 DUP3 ADD MLOAD PUSH2 0x17CA PUSH1 0xA0 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0xC0 DUP3 ADD MLOAD PUSH2 0x17DD PUSH1 0xC0 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0xE0 DUP3 ADD MLOAD PUSH2 0x1650 PUSH1 0xE0 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST PUSH2 0x1341 DUP2 PUSH2 0x1A1A JUMP JUMPDEST PUSH1 0x20 DUP2 ADD PUSH2 0x9A3 DUP3 DUP5 PUSH2 0x1338 JUMP JUMPDEST PUSH1 0x40 DUP2 ADD PUSH2 0x1815 DUP3 DUP6 PUSH2 0x1338 JUMP JUMPDEST PUSH2 0xC7E PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x1338 JUMP JUMPDEST PUSH1 0x40 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x1833 DUP2 DUP6 PUSH2 0x1347 JUMP JUMPDEST SWAP1 POP DUP2 DUP2 SUB PUSH1 0x20 DUP4 ADD MSTORE PUSH2 0x1131 DUP2 DUP5 PUSH2 0x1405 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0xC7E DUP2 DUP5 PUSH2 0x139E JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0xC7E DUP2 DUP5 PUSH2 0x1405 JUMP JUMPDEST PUSH1 0x40 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x187A DUP2 DUP6 PUSH2 0x1453 JUMP JUMPDEST SWAP1 POP DUP2 DUP2 SUB PUSH1 0x20 DUP4 ADD MSTORE PUSH2 0x1131 DUP2 DUP5 PUSH2 0x1453 JUMP JUMPDEST PUSH1 0x20 DUP2 ADD PUSH2 0x9A3 DUP3 DUP5 PUSH2 0x14A9 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x9A3 DUP2 PUSH2 0x14E7 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x9A3 DUP2 PUSH2 0x153D JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x9A3 DUP2 PUSH2 0x156D JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x9A3 DUP2 PUSH2 0x15C3 JUMP JUMPDEST PUSH2 0x160 DUP2 ADD PUSH2 0x18EB DUP3 DUP6 PUSH2 0x1619 JUMP JUMPDEST PUSH2 0xC7E PUSH1 0x60 DUP4 ADD DUP5 PUSH2 0x1759 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0xC7E DUP2 DUP5 PUSH2 0x1656 JUMP JUMPDEST PUSH2 0x100 DUP2 ADD PUSH2 0x9A3 DUP3 DUP5 PUSH2 0x1759 JUMP JUMPDEST PUSH1 0x20 DUP2 ADD PUSH2 0x9A3 DUP3 DUP5 PUSH2 0x14A0 JUMP JUMPDEST PUSH1 0x40 DUP2 ADD PUSH2 0x1934 DUP3 DUP6 PUSH2 0x14A0 JUMP JUMPDEST PUSH2 0xC7E PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x14A0 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x1960 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT ISZERO PUSH2 0x197F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 SWAP1 DUP2 MUL ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT ISZERO PUSH2 0x19A0 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 PUSH1 0x1F SWAP2 SWAP1 SWAP2 ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND ADD SWAP1 JUMP JUMPDEST PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST MLOAD SWAP1 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 AND SWAP1 JUMP JUMPDEST PUSH1 0xFF AND 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 0x1A4C JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x1A34 JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x1650 JUMPI POP POP PUSH1 0x0 SWAP2 ADD MSTORE JUMP JUMPDEST PUSH1 0x1F ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND SWAP1 JUMP STOP LOG2 PUSH6 0x627A7A723058 KECCAK256 0xd3 0xd4 SWAP6 0xbc 0x28 PUSH23 0x63ED8CB2A513CFAD47804FFA6E4AD0CFA6D0D0EADF1F90 PUSH21 0x83586C6578706572696D656E74616CF50037000000 ", + "sourceMap": "898:8536:11:-;;;1916:167;8:9:-1;5:2;;;30:1;27;20:12;5:2;1916:167:11;;;;;;;;;;;;;;;;;;;;;;;;2005:8;:31;;-1:-1:-1;;;;;;2005:31:11;-1:-1:-1;;;;;2005:31:11;;;;;2046:30;;;;-1:-1:-1;;2046:30:11;;;;;:::i;:::-;;1916:167;;898:8536;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;898:8536:11;;;-1:-1:-1;898:8536:11;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::o;5:122:-1:-;;83:39;114:6;108:13;83:39;;;74:48;68:59;-1:-1;;;68:59;135:442;;240:4;228:17;;224:27;-1:-1;214:2;;265:1;262;255:12;214:2;295:6;289:13;317:64;332:48;373:6;332:48;;;317:64;;;308:73;;401:6;394:5;387:21;437:4;429:6;425:17;470:4;463:5;459:16;505:3;496:6;491:3;487:16;484:25;481:2;;;522:1;519;512:12;481:2;532:39;564:6;559:3;554;532:39;;;207:370;;;;;;;;585:496;;;726:2;714:9;705:7;701:23;697:32;694:2;;;742:1;739;732:12;694:2;777:1;794:64;850:7;830:9;794:64;;;784:74;;756:108;916:2;905:9;901:18;895:25;-1:-1;;;;;932:6;929:30;926:2;;;972:1;969;962:12;926:2;992:73;1057:7;1048:6;1037:9;1033:22;992:73;;;982:83;;874:197;688:393;;;;;;1088:256;1150:2;1144:9;1176:17;;;-1:-1;;;;;1236:34;;1272:22;;;1233:62;1230:2;;;1308:1;1305;1298:12;1230:2;1324;1317:22;1128:216;;-1:-1;1128:216;1351:258;;-1:-1;;;;;1486:6;1483:30;1480:2;;;1526:1;1523;1516:12;1480:2;-1:-1;1599:4;1570;1547:17;;;;-1:-1;;1543:33;1589:15;;1417:192;1616:128;-1:-1;;;;;1685:54;;1668:76;1752:268;1817:1;1824:101;1838:6;1835:1;1832:13;1824:101;;;1905:11;;;1899:18;1886:11;;;1879:39;1860:2;1853:10;1824:101;;;1940:6;1937:1;1934:13;1931:2;;;2005:1;1996:6;1991:3;1987:16;1980:27;1931:2;1801:219;;;;;;898:8536:11;;;;;;" }, "deployedBytecode": { "linkReferences": {}, - "object": "0x6080604052600436106100775763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166304ad1e53811461007c5780632cd0fc73146100b35780634b95de13146100e1578063690d31141461010f578063b69884631461013c578063f241ffb014610169575b600080fd5b34801561008857600080fd5b5061009c610097366004611118565b610196565b6040516100aa9291906116af565b60405180910390f35b3480156100bf57600080fd5b506100d36100ce366004610fc6565b610263565b6040516100aa9291906116f9565b3480156100ed57600080fd5b506101016100fc36600461107d565b610794565b6040516100aa92919061161a565b34801561011b57600080fd5b5061012f61012a36600461107d565b61086b565b6040516100aa9190611650565b34801561014857600080fd5b5061015c610157366004611018565b610925565b6040516100aa91906115f1565b34801561017557600080fd5b50610189610184366004611118565b610970565b6040516100aa91906116dc565b61019e610bba565b6101a6610bda565b6000546040517fc75e0a8100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063c75e0a81906101fc9087906004016116cb565b606060405180830381600087803b15801561021657600080fd5b505af115801561022a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061024e91908101906110fa565b915061025a8484610970565b90509250929050565b60008080808080808061027c898263ffffffff610a8e16565b955061028f89601063ffffffff610afb16565b6000546040517f6070410800000000000000000000000000000000000000000000000000000000815291965073ffffffffffffffffffffffffffffffffffffffff16906360704108906102e6908990600401611661565b602060405180830381600087803b15801561030057600080fd5b505af1158015610314573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506103389190810190610fa0565b604080517f4552433230546f6b656e28616464726573732900000000000000000000000000815290519081900360130190209094507fffffffff00000000000000000000000000000000000000000000000000000000878116911614156104ed576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8616906370a08231906103eb908d906004016115f1565b602060405180830381600087803b15801561040557600080fd5b505af1158015610419573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061043d919081019061115f565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815290985073ffffffffffffffffffffffffffffffffffffffff86169063dd62ed3e90610494908d9088906004016115ff565b602060405180830381600087803b1580156104ae57600080fd5b505af11580156104c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506104e6919081019061115f565b9650610787565b604080517f455243373231546f6b656e28616464726573732c75696e7432353629000000008152905190819003601c0190207fffffffff000000000000000000000000000000000000000000000000000000008781169116141561074c5761055c89602463ffffffff610b5c16565b92506105688584610925565b91508173ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16146105a45760006105a7565b60015b60ff1697508473ffffffffffffffffffffffffffffffffffffffff1663e985e9c58b866040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016106039291906115ff565b602060405180830381600087803b15801561061d57600080fd5b505af1158015610631573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061065591908101906110dc565b8061073157508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1663081812fc856040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016106c791906116eb565b602060405180830381600087803b1580156106e157600080fd5b505af11580156106f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107199190810190610fa0565b73ffffffffffffffffffffffffffffffffffffffff16145b90508061073f576000610742565b60015b60ff169650610787565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077e9061167f565b60405180910390fd5b5050505050509250929050565b6000546040517f7e9d74dc000000000000000000000000000000000000000000000000000000008152606091829173ffffffffffffffffffffffffffffffffffffffff90911690637e9d74dc906107ef90879060040161163f565b600060405180830381600087803b15801561080957600080fd5b505af115801561081d573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526108639190810190611048565b915061025a84845b606060006060600085519250826040519080825280602002602001820160405280156108b157816020015b61089e610bda565b8152602001906001900390816108965790505b509150600090505b808314610918576108f886828151811015156108d157fe5b9060200190602002015186838151811015156108e957fe5b90602001906020020151610970565b828281518110151561090657fe5b602090810290910101526001016108b9565b8193505b50505092915050565b60006040517f6352211e000000000000000000000000000000000000000000000000000000008152826004820152602081602483875afa801561096757815192505b50505b92915050565b610978610bda565b606061098d8460000151856101400151610263565b602084015282526101608401516109a5908490610263565b60608401526040808401919091526001805482516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101008688161502019094169390930492830181900481028201810190945281815292830182828015610a545780601f10610a2957610100808354040283529160200191610a54565b820191906000526020600020905b815481529060010190602001808311610a3757829003601f168201915b50505050509050610a69846000015182610263565b60a08401526080830152610a7d8382610263565b60e084015260c08301525092915050565b600081600401835110151515610ad0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077e9061169f565b5050602001517fffffffff000000000000000000000000000000000000000000000000000000001690565b600081601401835110151515610b3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077e9061168f565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b6000610b688383610b6f565b9392505050565b600081602001835110151515610bb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077e9061166f565b50016020015190565b604080516060810182526000808252602082018190529181019190915290565b6101006040519081016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000610b6882356117ac565b6000610b6882516117ac565b6000601f82018313610c4957600080fd5b8135610c5c610c578261173b565b611714565b91508181835260208401935060208101905083856020840282011115610c8157600080fd5b60005b83811015610cad5781610c978882610c20565b8452506020928301929190910190600101610c84565b5050505092915050565b6000601f82018313610cc857600080fd5b8151610cd6610c578261173b565b91508181835260208401935060208101905083856060840282011115610cfb57600080fd5b60005b83811015610cad5781610d118882610de4565b84525060209092019160609190910190600101610cfe565b6000601f82018313610d3a57600080fd5b8135610d48610c578261173b565b81815260209384019390925082018360005b83811015610cad5781358601610d708882610e3f565b8452506020928301929190910190600101610d5a565b6000610b6882516117f3565b6000610b6882516117c5565b6000601f82018313610daf57600080fd5b8135610dbd610c578261175c565b91508082526020830160208301858383011115610dd957600080fd5b61091c8382846117f8565b600060608284031215610df657600080fd5b610e006060611714565b90506000610e0e8484610f94565b8252506020610e1f84848301610d92565b6020830152506040610e3384828501610d92565b60408301525092915050565b60006101808284031215610e5257600080fd5b610e5d610180611714565b90506000610e6b8484610c20565b8252506020610e7c84848301610c20565b6020830152506040610e9084828501610c20565b6040830152506060610ea484828501610c20565b6060830152506080610eb884828501610f88565b60808301525060a0610ecc84828501610f88565b60a08301525060c0610ee084828501610f88565b60c08301525060e0610ef484828501610f88565b60e083015250610100610f0984828501610f88565b61010083015250610120610f1f84828501610f88565b6101208301525061014082013567ffffffffffffffff811115610f4157600080fd5b610f4d84828501610d9e565b6101408301525061016082013567ffffffffffffffff811115610f6f57600080fd5b610f7b84828501610d9e565b6101608301525092915050565b6000610b6882356117c5565b6000610b6882516117ed565b600060208284031215610fb257600080fd5b6000610fbe8484610c2c565b949350505050565b60008060408385031215610fd957600080fd5b6000610fe58585610c20565b925050602083013567ffffffffffffffff81111561100257600080fd5b61100e85828601610d9e565b9150509250929050565b6000806040838503121561102b57600080fd5b60006110378585610c20565b925050602061100e85828601610f88565b60006020828403121561105a57600080fd5b815167ffffffffffffffff81111561107157600080fd5b610fbe84828501610cb7565b6000806040838503121561109057600080fd5b823567ffffffffffffffff8111156110a757600080fd5b6110b385828601610d29565b925050602083013567ffffffffffffffff8111156110d057600080fd5b61100e85828601610c38565b6000602082840312156110ee57600080fd5b6000610fbe8484610d86565b60006060828403121561110c57600080fd5b6000610fbe8484610de4565b6000806040838503121561112b57600080fd5b823567ffffffffffffffff81111561114257600080fd5b61114e85828601610e3f565b925050602061100e85828601610c20565b60006020828403121561117157600080fd5b6000610fbe8484610d92565b611186816117ac565b82525050565b6000611197826117a8565b8084526020840193506111a9836117a2565b60005b828110156111d9576111bf868351611411565b6111c8826117a2565b6060969096019591506001016111ac565b5093949350505050565b60006111ee826117a8565b80845260208401935083602082028501611207856117a2565b60005b8481101561123e57838303885261122283835161144e565b925061122d826117a2565b60209890980197915060010161120a565b50909695505050505050565b6000611255826117a8565b808452602084019350611267836117a2565b60005b828110156111d95761127d868351611551565b611286826117a2565b6101009690960195915060010161126a565b611186816117c5565b611186816117c8565b60006112b5826117a8565b8084526112c9816020860160208601611804565b6112d281611830565b9093016020019392505050565b602681527f475245415445525f4f525f455155414c5f544f5f33325f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601781527f554e535550504f525445445f41535345545f50524f5859000000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b602581527f475245415445525f4f525f455155414c5f544f5f345f4c454e4754485f52455160208201527f5549524544000000000000000000000000000000000000000000000000000000604082015260600190565b8051606083019061142284826115e8565b5060208201516114356020850182611298565b5060408201516114486040850182611298565b50505050565b8051600090610180840190611463858261117d565b506020830151611476602086018261117d565b506040830151611489604086018261117d565b50606083015161149c606086018261117d565b5060808301516114af6080860182611298565b5060a08301516114c260a0860182611298565b5060c08301516114d560c0860182611298565b5060e08301516114e860e0860182611298565b506101008301516114fd610100860182611298565b50610120830151611512610120860182611298565b5061014083015184820361014086015261152c82826112aa565b91505061016083015184820361016086015261154882826112aa565b95945050505050565b80516101008301906115638482611298565b5060208201516115766020850182611298565b5060408201516115896040850182611298565b50606082015161159c6060850182611298565b5060808201516115af6080850182611298565b5060a08201516115c260a0850182611298565b5060c08201516115d560c0850182611298565b5060e082015161144860e0850182611298565b611186816117ed565b6020810161096a828461117d565b6040810161160d828561117d565b610b68602083018461117d565b6040808252810161162b818561118c565b90508181036020830152610fbe818461124a565b60208082528101610b6881846111e3565b60208082528101610b68818461124a565b6020810161096a82846112a1565b6020808252810161096a816112df565b6020808252810161096a81611335565b6020808252810161096a81611365565b6020808252810161096a816113bb565b61016081016116be8285611411565b610b686060830184611551565b60208082528101610b68818461144e565b610100810161096a8284611551565b6020810161096a8284611298565b604081016117078285611298565b610b686020830184611298565b60405181810167ffffffffffffffff8111828210171561173357600080fd5b604052919050565b600067ffffffffffffffff82111561175257600080fd5b5060209081020190565b600067ffffffffffffffff82111561177357600080fd5b506020601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b60200190565b5190565b73ffffffffffffffffffffffffffffffffffffffff1690565b90565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b60ff1690565b151590565b82818337506000910152565b60005b8381101561181f578181015183820152602001611807565b838111156114485750506000910152565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016905600a265627a7a723058200742593843de04ccb442f25f2474ff7a322e1281cdb1232118c18b3985166e7f6c6578706572696d656e74616cf50037", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x77 JUMPI PUSH4 0xFFFFFFFF PUSH29 0x100000000000000000000000000000000000000000000000000000000 PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0x4AD1E53 DUP2 EQ PUSH2 0x7C JUMPI DUP1 PUSH4 0x2CD0FC73 EQ PUSH2 0xB3 JUMPI DUP1 PUSH4 0x4B95DE13 EQ PUSH2 0xE1 JUMPI DUP1 PUSH4 0x690D3114 EQ PUSH2 0x10F JUMPI DUP1 PUSH4 0xB6988463 EQ PUSH2 0x13C JUMPI DUP1 PUSH4 0xF241FFB0 EQ PUSH2 0x169 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x88 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x9C PUSH2 0x97 CALLDATASIZE PUSH1 0x4 PUSH2 0x1118 JUMP JUMPDEST PUSH2 0x196 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xAA SWAP3 SWAP2 SWAP1 PUSH2 0x16AF JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0xBF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xD3 PUSH2 0xCE CALLDATASIZE PUSH1 0x4 PUSH2 0xFC6 JUMP JUMPDEST PUSH2 0x263 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xAA SWAP3 SWAP2 SWAP1 PUSH2 0x16F9 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0xED JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x101 PUSH2 0xFC CALLDATASIZE PUSH1 0x4 PUSH2 0x107D JUMP JUMPDEST PUSH2 0x794 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xAA SWAP3 SWAP2 SWAP1 PUSH2 0x161A JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x11B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x12F PUSH2 0x12A CALLDATASIZE PUSH1 0x4 PUSH2 0x107D JUMP JUMPDEST PUSH2 0x86B JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xAA SWAP2 SWAP1 PUSH2 0x1650 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x148 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x15C PUSH2 0x157 CALLDATASIZE PUSH1 0x4 PUSH2 0x1018 JUMP JUMPDEST PUSH2 0x925 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xAA SWAP2 SWAP1 PUSH2 0x15F1 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x175 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x189 PUSH2 0x184 CALLDATASIZE PUSH1 0x4 PUSH2 0x1118 JUMP JUMPDEST PUSH2 0x970 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xAA SWAP2 SWAP1 PUSH2 0x16DC JUMP JUMPDEST PUSH2 0x19E PUSH2 0xBBA JUMP JUMPDEST PUSH2 0x1A6 PUSH2 0xBDA JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH1 0x40 MLOAD PUSH32 0xC75E0A8100000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP2 AND SWAP1 PUSH4 0xC75E0A81 SWAP1 PUSH2 0x1FC SWAP1 DUP8 SWAP1 PUSH1 0x4 ADD PUSH2 0x16CB JUMP JUMPDEST PUSH1 0x60 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x216 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x22A 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 0x24E SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x10FA JUMP JUMPDEST SWAP2 POP PUSH2 0x25A DUP5 DUP5 PUSH2 0x970 JUMP JUMPDEST SWAP1 POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP1 DUP1 DUP1 DUP1 DUP1 DUP1 PUSH2 0x27C DUP10 DUP3 PUSH4 0xFFFFFFFF PUSH2 0xA8E AND JUMP JUMPDEST SWAP6 POP PUSH2 0x28F DUP10 PUSH1 0x10 PUSH4 0xFFFFFFFF PUSH2 0xAFB AND JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH1 0x40 MLOAD PUSH32 0x6070410800000000000000000000000000000000000000000000000000000000 DUP2 MSTORE SWAP2 SWAP7 POP PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH4 0x60704108 SWAP1 PUSH2 0x2E6 SWAP1 DUP10 SWAP1 PUSH1 0x4 ADD PUSH2 0x1661 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x300 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x314 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 0x338 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0xFA0 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0x4552433230546F6B656E28616464726573732900000000000000000000000000 DUP2 MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x13 ADD SWAP1 KECCAK256 SWAP1 SWAP5 POP PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 DUP8 DUP2 AND SWAP2 AND EQ ISZERO PUSH2 0x4ED JUMPI PUSH1 0x40 MLOAD PUSH32 0x70A0823100000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP7 AND SWAP1 PUSH4 0x70A08231 SWAP1 PUSH2 0x3EB SWAP1 DUP14 SWAP1 PUSH1 0x4 ADD PUSH2 0x15F1 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x405 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x419 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 0x43D SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x115F JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0xDD62ED3E00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE SWAP1 SWAP9 POP PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP7 AND SWAP1 PUSH4 0xDD62ED3E SWAP1 PUSH2 0x494 SWAP1 DUP14 SWAP1 DUP9 SWAP1 PUSH1 0x4 ADD PUSH2 0x15FF JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x4AE JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x4C2 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 0x4E6 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x115F JUMP JUMPDEST SWAP7 POP PUSH2 0x787 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0x455243373231546F6B656E28616464726573732C75696E743235362900000000 DUP2 MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x1C ADD SWAP1 KECCAK256 PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 DUP8 DUP2 AND SWAP2 AND EQ ISZERO PUSH2 0x74C JUMPI PUSH2 0x55C DUP10 PUSH1 0x24 PUSH4 0xFFFFFFFF PUSH2 0xB5C AND JUMP JUMPDEST SWAP3 POP PUSH2 0x568 DUP6 DUP5 PUSH2 0x925 JUMP JUMPDEST SWAP2 POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ PUSH2 0x5A4 JUMPI PUSH1 0x0 PUSH2 0x5A7 JUMP JUMPDEST PUSH1 0x1 JUMPDEST PUSH1 0xFF AND SWAP8 POP DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH4 0xE985E9C5 DUP12 DUP7 PUSH1 0x40 MLOAD DUP4 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x603 SWAP3 SWAP2 SWAP1 PUSH2 0x15FF JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x61D JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x631 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 0x655 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x10DC JUMP JUMPDEST DUP1 PUSH2 0x731 JUMPI POP DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH4 0x81812FC DUP6 PUSH1 0x40 MLOAD DUP3 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x6C7 SWAP2 SWAP1 PUSH2 0x16EB JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x6E1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x6F5 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 0x719 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0xFA0 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ JUMPDEST SWAP1 POP DUP1 PUSH2 0x73F JUMPI PUSH1 0x0 PUSH2 0x742 JUMP JUMPDEST PUSH1 0x1 JUMPDEST PUSH1 0xFF AND SWAP7 POP PUSH2 0x787 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x77E SWAP1 PUSH2 0x167F JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP POP POP POP POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH1 0x40 MLOAD PUSH32 0x7E9D74DC00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x60 SWAP2 DUP3 SWAP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP2 AND SWAP1 PUSH4 0x7E9D74DC SWAP1 PUSH2 0x7EF SWAP1 DUP8 SWAP1 PUSH1 0x4 ADD PUSH2 0x163F JUMP JUMPDEST PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x809 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x81D JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP PUSH1 0x40 MLOAD RETURNDATASIZE PUSH1 0x0 DUP3 RETURNDATACOPY PUSH1 0x1F RETURNDATASIZE SWAP1 DUP2 ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND DUP3 ADD PUSH1 0x40 MSTORE PUSH2 0x863 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1048 JUMP JUMPDEST SWAP2 POP PUSH2 0x25A DUP5 DUP5 JUMPDEST PUSH1 0x60 PUSH1 0x0 PUSH1 0x60 PUSH1 0x0 DUP6 MLOAD SWAP3 POP DUP3 PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x8B1 JUMPI DUP2 PUSH1 0x20 ADD JUMPDEST PUSH2 0x89E PUSH2 0xBDA JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD SWAP1 PUSH1 0x1 SWAP1 SUB SWAP1 DUP2 PUSH2 0x896 JUMPI SWAP1 POP JUMPDEST POP SWAP2 POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP1 DUP4 EQ PUSH2 0x918 JUMPI PUSH2 0x8F8 DUP7 DUP3 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x8D1 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD DUP7 DUP4 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x8E9 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH2 0x970 JUMP JUMPDEST DUP3 DUP3 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x906 JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP1 SWAP2 ADD ADD MSTORE PUSH1 0x1 ADD PUSH2 0x8B9 JUMP JUMPDEST DUP2 SWAP4 POP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x40 MLOAD PUSH32 0x6352211E00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE DUP3 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x20 DUP2 PUSH1 0x24 DUP4 DUP8 GAS STATICCALL DUP1 ISZERO PUSH2 0x967 JUMPI DUP2 MLOAD SWAP3 POP JUMPDEST POP POP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH2 0x978 PUSH2 0xBDA JUMP JUMPDEST PUSH1 0x60 PUSH2 0x98D DUP5 PUSH1 0x0 ADD MLOAD DUP6 PUSH2 0x140 ADD MLOAD PUSH2 0x263 JUMP JUMPDEST PUSH1 0x20 DUP5 ADD MSTORE DUP3 MSTORE PUSH2 0x160 DUP5 ADD MLOAD PUSH2 0x9A5 SWAP1 DUP5 SWAP1 PUSH2 0x263 JUMP JUMPDEST PUSH1 0x60 DUP5 ADD MSTORE PUSH1 0x40 DUP1 DUP5 ADD SWAP2 SWAP1 SWAP2 MSTORE PUSH1 0x1 DUP1 SLOAD DUP3 MLOAD PUSH1 0x20 PUSH1 0x1F PUSH1 0x2 PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF PUSH2 0x100 DUP7 DUP9 AND ISZERO MUL ADD SWAP1 SWAP5 AND SWAP4 SWAP1 SWAP4 DIV SWAP3 DUP4 ADD DUP2 SWAP1 DIV DUP2 MUL DUP3 ADD DUP2 ADD SWAP1 SWAP5 MSTORE DUP2 DUP2 MSTORE SWAP3 DUP4 ADD DUP3 DUP3 DUP1 ISZERO PUSH2 0xA54 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xA29 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xA54 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xA37 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP PUSH2 0xA69 DUP5 PUSH1 0x0 ADD MLOAD DUP3 PUSH2 0x263 JUMP JUMPDEST PUSH1 0xA0 DUP5 ADD MSTORE PUSH1 0x80 DUP4 ADD MSTORE PUSH2 0xA7D DUP4 DUP3 PUSH2 0x263 JUMP JUMPDEST PUSH1 0xE0 DUP5 ADD MSTORE PUSH1 0xC0 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x4 ADD DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0xAD0 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x77E SWAP1 PUSH2 0x169F JUMP JUMPDEST POP POP PUSH1 0x20 ADD MLOAD PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 AND SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x14 ADD DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0xB3D JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x77E SWAP1 PUSH2 0x168F JUMP JUMPDEST POP ADD PUSH1 0x14 ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xB68 DUP4 DUP4 PUSH2 0xB6F JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x20 ADD DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0xBB1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x77E SWAP1 PUSH2 0x166F JUMP JUMPDEST POP ADD PUSH1 0x20 ADD MLOAD SWAP1 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x60 DUP2 ADD DUP3 MSTORE PUSH1 0x0 DUP1 DUP3 MSTORE PUSH1 0x20 DUP3 ADD DUP2 SWAP1 MSTORE SWAP2 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE SWAP1 JUMP JUMPDEST PUSH2 0x100 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 PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xB68 DUP3 CALLDATALOAD PUSH2 0x17AC JUMP JUMPDEST PUSH1 0x0 PUSH2 0xB68 DUP3 MLOAD PUSH2 0x17AC JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xC49 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xC5C PUSH2 0xC57 DUP3 PUSH2 0x173B JUMP JUMPDEST PUSH2 0x1714 JUMP JUMPDEST SWAP2 POP DUP2 DUP2 DUP4 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH1 0x20 DUP2 ADD SWAP1 POP DUP4 DUP6 PUSH1 0x20 DUP5 MUL DUP3 ADD GT ISZERO PUSH2 0xC81 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xCAD JUMPI DUP2 PUSH2 0xC97 DUP9 DUP3 PUSH2 0xC20 JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xC84 JUMP JUMPDEST POP POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xCC8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 MLOAD PUSH2 0xCD6 PUSH2 0xC57 DUP3 PUSH2 0x173B JUMP JUMPDEST SWAP2 POP DUP2 DUP2 DUP4 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH1 0x20 DUP2 ADD SWAP1 POP DUP4 DUP6 PUSH1 0x60 DUP5 MUL DUP3 ADD GT ISZERO PUSH2 0xCFB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xCAD JUMPI DUP2 PUSH2 0xD11 DUP9 DUP3 PUSH2 0xDE4 JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 SWAP1 SWAP3 ADD SWAP2 PUSH1 0x60 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xCFE JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xD3A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xD48 PUSH2 0xC57 DUP3 PUSH2 0x173B JUMP JUMPDEST DUP2 DUP2 MSTORE PUSH1 0x20 SWAP4 DUP5 ADD SWAP4 SWAP1 SWAP3 POP DUP3 ADD DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xCAD JUMPI DUP2 CALLDATALOAD DUP7 ADD PUSH2 0xD70 DUP9 DUP3 PUSH2 0xE3F JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xD5A JUMP JUMPDEST PUSH1 0x0 PUSH2 0xB68 DUP3 MLOAD PUSH2 0x17F3 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xB68 DUP3 MLOAD PUSH2 0x17C5 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xDAF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xDBD PUSH2 0xC57 DUP3 PUSH2 0x175C JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE PUSH1 0x20 DUP4 ADD PUSH1 0x20 DUP4 ADD DUP6 DUP4 DUP4 ADD GT ISZERO PUSH2 0xDD9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x91C DUP4 DUP3 DUP5 PUSH2 0x17F8 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xDF6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xE00 PUSH1 0x60 PUSH2 0x1714 JUMP JUMPDEST SWAP1 POP PUSH1 0x0 PUSH2 0xE0E DUP5 DUP5 PUSH2 0xF94 JUMP JUMPDEST DUP3 MSTORE POP PUSH1 0x20 PUSH2 0xE1F DUP5 DUP5 DUP4 ADD PUSH2 0xD92 JUMP JUMPDEST PUSH1 0x20 DUP4 ADD MSTORE POP PUSH1 0x40 PUSH2 0xE33 DUP5 DUP3 DUP6 ADD PUSH2 0xD92 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x180 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xE52 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xE5D PUSH2 0x180 PUSH2 0x1714 JUMP JUMPDEST SWAP1 POP PUSH1 0x0 PUSH2 0xE6B DUP5 DUP5 PUSH2 0xC20 JUMP JUMPDEST DUP3 MSTORE POP PUSH1 0x20 PUSH2 0xE7C DUP5 DUP5 DUP4 ADD PUSH2 0xC20 JUMP JUMPDEST PUSH1 0x20 DUP4 ADD MSTORE POP PUSH1 0x40 PUSH2 0xE90 DUP5 DUP3 DUP6 ADD PUSH2 0xC20 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MSTORE POP PUSH1 0x60 PUSH2 0xEA4 DUP5 DUP3 DUP6 ADD PUSH2 0xC20 JUMP JUMPDEST PUSH1 0x60 DUP4 ADD MSTORE POP PUSH1 0x80 PUSH2 0xEB8 DUP5 DUP3 DUP6 ADD PUSH2 0xF88 JUMP JUMPDEST PUSH1 0x80 DUP4 ADD MSTORE POP PUSH1 0xA0 PUSH2 0xECC DUP5 DUP3 DUP6 ADD PUSH2 0xF88 JUMP JUMPDEST PUSH1 0xA0 DUP4 ADD MSTORE POP PUSH1 0xC0 PUSH2 0xEE0 DUP5 DUP3 DUP6 ADD PUSH2 0xF88 JUMP JUMPDEST PUSH1 0xC0 DUP4 ADD MSTORE POP PUSH1 0xE0 PUSH2 0xEF4 DUP5 DUP3 DUP6 ADD PUSH2 0xF88 JUMP JUMPDEST PUSH1 0xE0 DUP4 ADD MSTORE POP PUSH2 0x100 PUSH2 0xF09 DUP5 DUP3 DUP6 ADD PUSH2 0xF88 JUMP JUMPDEST PUSH2 0x100 DUP4 ADD MSTORE POP PUSH2 0x120 PUSH2 0xF1F DUP5 DUP3 DUP6 ADD PUSH2 0xF88 JUMP JUMPDEST PUSH2 0x120 DUP4 ADD MSTORE POP PUSH2 0x140 DUP3 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xF41 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xF4D DUP5 DUP3 DUP6 ADD PUSH2 0xD9E JUMP JUMPDEST PUSH2 0x140 DUP4 ADD MSTORE POP PUSH2 0x160 DUP3 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xF6F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xF7B DUP5 DUP3 DUP6 ADD PUSH2 0xD9E JUMP JUMPDEST PUSH2 0x160 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0xB68 DUP3 CALLDATALOAD PUSH2 0x17C5 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xB68 DUP3 MLOAD PUSH2 0x17ED JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xFB2 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0xFBE DUP5 DUP5 PUSH2 0xC2C JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0xFD9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0xFE5 DUP6 DUP6 PUSH2 0xC20 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 DUP4 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x1002 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x100E DUP6 DUP3 DUP7 ADD PUSH2 0xD9E JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x102B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1037 DUP6 DUP6 PUSH2 0xC20 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 PUSH2 0x100E DUP6 DUP3 DUP7 ADD PUSH2 0xF88 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x105A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x1071 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xFBE DUP5 DUP3 DUP6 ADD PUSH2 0xCB7 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x1090 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x10A7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x10B3 DUP6 DUP3 DUP7 ADD PUSH2 0xD29 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 DUP4 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x10D0 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x100E DUP6 DUP3 DUP7 ADD PUSH2 0xC38 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x10EE JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0xFBE DUP5 DUP5 PUSH2 0xD86 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x110C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0xFBE DUP5 DUP5 PUSH2 0xDE4 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x112B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x1142 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x114E DUP6 DUP3 DUP7 ADD PUSH2 0xE3F JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 PUSH2 0x100E DUP6 DUP3 DUP7 ADD PUSH2 0xC20 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x1171 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0xFBE DUP5 DUP5 PUSH2 0xD92 JUMP JUMPDEST PUSH2 0x1186 DUP2 PUSH2 0x17AC JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x1197 DUP3 PUSH2 0x17A8 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH2 0x11A9 DUP4 PUSH2 0x17A2 JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x11D9 JUMPI PUSH2 0x11BF DUP7 DUP4 MLOAD PUSH2 0x1411 JUMP JUMPDEST PUSH2 0x11C8 DUP3 PUSH2 0x17A2 JUMP JUMPDEST PUSH1 0x60 SWAP7 SWAP1 SWAP7 ADD SWAP6 SWAP2 POP PUSH1 0x1 ADD PUSH2 0x11AC JUMP JUMPDEST POP SWAP4 SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x11EE DUP3 PUSH2 0x17A8 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP DUP4 PUSH1 0x20 DUP3 MUL DUP6 ADD PUSH2 0x1207 DUP6 PUSH2 0x17A2 JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP5 DUP2 LT ISZERO PUSH2 0x123E JUMPI DUP4 DUP4 SUB DUP9 MSTORE PUSH2 0x1222 DUP4 DUP4 MLOAD PUSH2 0x144E JUMP JUMPDEST SWAP3 POP PUSH2 0x122D DUP3 PUSH2 0x17A2 JUMP JUMPDEST PUSH1 0x20 SWAP9 SWAP1 SWAP9 ADD SWAP8 SWAP2 POP PUSH1 0x1 ADD PUSH2 0x120A JUMP JUMPDEST POP SWAP1 SWAP7 SWAP6 POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x1255 DUP3 PUSH2 0x17A8 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH2 0x1267 DUP4 PUSH2 0x17A2 JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x11D9 JUMPI PUSH2 0x127D DUP7 DUP4 MLOAD PUSH2 0x1551 JUMP JUMPDEST PUSH2 0x1286 DUP3 PUSH2 0x17A2 JUMP JUMPDEST PUSH2 0x100 SWAP7 SWAP1 SWAP7 ADD SWAP6 SWAP2 POP PUSH1 0x1 ADD PUSH2 0x126A JUMP JUMPDEST PUSH2 0x1186 DUP2 PUSH2 0x17C5 JUMP JUMPDEST PUSH2 0x1186 DUP2 PUSH2 0x17C8 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x12B5 DUP3 PUSH2 0x17A8 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH2 0x12C9 DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x1804 JUMP JUMPDEST PUSH2 0x12D2 DUP2 PUSH2 0x1830 JUMP JUMPDEST SWAP1 SWAP4 ADD PUSH1 0x20 ADD SWAP4 SWAP3 POP POP POP 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 0x17 DUP2 MSTORE PUSH32 0x554E535550504F525445445F41535345545F50524F5859000000000000000000 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 0x25 DUP2 MSTORE PUSH32 0x475245415445525F4F525F455155414C5F544F5F345F4C454E4754485F524551 PUSH1 0x20 DUP3 ADD MSTORE PUSH32 0x5549524544000000000000000000000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST DUP1 MLOAD PUSH1 0x60 DUP4 ADD SWAP1 PUSH2 0x1422 DUP5 DUP3 PUSH2 0x15E8 JUMP JUMPDEST POP PUSH1 0x20 DUP3 ADD MLOAD PUSH2 0x1435 PUSH1 0x20 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0x40 DUP3 ADD MLOAD PUSH2 0x1448 PUSH1 0x40 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP POP POP POP JUMP JUMPDEST DUP1 MLOAD PUSH1 0x0 SWAP1 PUSH2 0x180 DUP5 ADD SWAP1 PUSH2 0x1463 DUP6 DUP3 PUSH2 0x117D JUMP JUMPDEST POP PUSH1 0x20 DUP4 ADD MLOAD PUSH2 0x1476 PUSH1 0x20 DUP7 ADD DUP3 PUSH2 0x117D JUMP JUMPDEST POP PUSH1 0x40 DUP4 ADD MLOAD PUSH2 0x1489 PUSH1 0x40 DUP7 ADD DUP3 PUSH2 0x117D JUMP JUMPDEST POP PUSH1 0x60 DUP4 ADD MLOAD PUSH2 0x149C PUSH1 0x60 DUP7 ADD DUP3 PUSH2 0x117D JUMP JUMPDEST POP PUSH1 0x80 DUP4 ADD MLOAD PUSH2 0x14AF PUSH1 0x80 DUP7 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0xA0 DUP4 ADD MLOAD PUSH2 0x14C2 PUSH1 0xA0 DUP7 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0xC0 DUP4 ADD MLOAD PUSH2 0x14D5 PUSH1 0xC0 DUP7 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0xE0 DUP4 ADD MLOAD PUSH2 0x14E8 PUSH1 0xE0 DUP7 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH2 0x100 DUP4 ADD MLOAD PUSH2 0x14FD PUSH2 0x100 DUP7 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH2 0x120 DUP4 ADD MLOAD PUSH2 0x1512 PUSH2 0x120 DUP7 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH2 0x140 DUP4 ADD MLOAD DUP5 DUP3 SUB PUSH2 0x140 DUP7 ADD MSTORE PUSH2 0x152C DUP3 DUP3 PUSH2 0x12AA JUMP JUMPDEST SWAP2 POP POP PUSH2 0x160 DUP4 ADD MLOAD DUP5 DUP3 SUB PUSH2 0x160 DUP7 ADD MSTORE PUSH2 0x1548 DUP3 DUP3 PUSH2 0x12AA JUMP JUMPDEST SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST DUP1 MLOAD PUSH2 0x100 DUP4 ADD SWAP1 PUSH2 0x1563 DUP5 DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0x20 DUP3 ADD MLOAD PUSH2 0x1576 PUSH1 0x20 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0x40 DUP3 ADD MLOAD PUSH2 0x1589 PUSH1 0x40 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0x60 DUP3 ADD MLOAD PUSH2 0x159C PUSH1 0x60 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0x80 DUP3 ADD MLOAD PUSH2 0x15AF PUSH1 0x80 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0xA0 DUP3 ADD MLOAD PUSH2 0x15C2 PUSH1 0xA0 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0xC0 DUP3 ADD MLOAD PUSH2 0x15D5 PUSH1 0xC0 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST POP PUSH1 0xE0 DUP3 ADD MLOAD PUSH2 0x1448 PUSH1 0xE0 DUP6 ADD DUP3 PUSH2 0x1298 JUMP JUMPDEST PUSH2 0x1186 DUP2 PUSH2 0x17ED JUMP JUMPDEST PUSH1 0x20 DUP2 ADD PUSH2 0x96A DUP3 DUP5 PUSH2 0x117D JUMP JUMPDEST PUSH1 0x40 DUP2 ADD PUSH2 0x160D DUP3 DUP6 PUSH2 0x117D JUMP JUMPDEST PUSH2 0xB68 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x117D JUMP JUMPDEST PUSH1 0x40 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x162B DUP2 DUP6 PUSH2 0x118C JUMP JUMPDEST SWAP1 POP DUP2 DUP2 SUB PUSH1 0x20 DUP4 ADD MSTORE PUSH2 0xFBE DUP2 DUP5 PUSH2 0x124A JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0xB68 DUP2 DUP5 PUSH2 0x11E3 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0xB68 DUP2 DUP5 PUSH2 0x124A JUMP JUMPDEST PUSH1 0x20 DUP2 ADD PUSH2 0x96A DUP3 DUP5 PUSH2 0x12A1 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x96A DUP2 PUSH2 0x12DF JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x96A DUP2 PUSH2 0x1335 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x96A DUP2 PUSH2 0x1365 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x96A DUP2 PUSH2 0x13BB JUMP JUMPDEST PUSH2 0x160 DUP2 ADD PUSH2 0x16BE DUP3 DUP6 PUSH2 0x1411 JUMP JUMPDEST PUSH2 0xB68 PUSH1 0x60 DUP4 ADD DUP5 PUSH2 0x1551 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0xB68 DUP2 DUP5 PUSH2 0x144E JUMP JUMPDEST PUSH2 0x100 DUP2 ADD PUSH2 0x96A DUP3 DUP5 PUSH2 0x1551 JUMP JUMPDEST PUSH1 0x20 DUP2 ADD PUSH2 0x96A DUP3 DUP5 PUSH2 0x1298 JUMP JUMPDEST PUSH1 0x40 DUP2 ADD PUSH2 0x1707 DUP3 DUP6 PUSH2 0x1298 JUMP JUMPDEST PUSH2 0xB68 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x1298 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x1733 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT ISZERO PUSH2 0x1752 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 SWAP1 DUP2 MUL ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT ISZERO PUSH2 0x1773 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 PUSH1 0x1F SWAP2 SWAP1 SWAP2 ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND ADD SWAP1 JUMP JUMPDEST PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST MLOAD SWAP1 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 AND SWAP1 JUMP JUMPDEST PUSH1 0xFF AND 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 0x181F JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x1807 JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x1448 JUMPI POP POP PUSH1 0x0 SWAP2 ADD MSTORE JUMP JUMPDEST PUSH1 0x1F ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND SWAP1 JUMP STOP LOG2 PUSH6 0x627A7A723058 KECCAK256 SMOD TIMESTAMP MSIZE CODESIZE NUMBER 0xde DIV 0xcc 0xb4 TIMESTAMP CALLCODE 0x5f 0x24 PUSH21 0xFF7A322E1281CDB1232118C18B3985166E7F6C6578 PUSH17 0x6572696D656E74616CF500370000000000 ", - "sourceMap": "898:7576:11:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2336:352;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;2336:352:11;;;;;;;;;;;;;;;;;;;;;;;;;;5614:1359;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;5614:1359:11;;;;;;;;;;;;;;;;;;3018:384;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;3018:384:11;;;;;;;;;;;;;;;;;;4716:452;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;4716:452:11;;;;;;;;;;;;;;;;;7258:1214;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;7258:1214:11;;;;;;;;;;;;;;;;;3661:739;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;3661:739:11;;;;;;;;;;;;;;;;;2336:352;2463:35;;:::i;:::-;2500:28;;:::i;:::-;2556:8;;:28;;;;;:8;;;;;:21;;:28;;2578:5;;2556:28;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2556:28:11;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2556:28:11;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;2556:28:11;;;;;;;;;2544:40;;2607:34;2621:5;2628:12;2607:13;:34::i;:::-;2594:47;-1:-1:-1;2336:352:11;;;;;:::o;5614:1359::-;5731:15;;;;;;;;5803:23;:9;5731:15;5803:23;:20;:23;:::i;:::-;5781:45;-1:-1:-1;5852:25:11;:9;5874:2;5852:25;:21;:25;:::i;:::-;5908:8;;:36;;;;;5836:41;;-1:-1:-1;5908:8:11;;;:22;;:36;;5931:12;;5908:36;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5908:36:11;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5908:36:11;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;5908:36:11;;;;;;;;;977:32;;;;;;;;;;;;;;;;5887:57;;-1:-1:-1;5959:29:11;;;;;;;5955:975;;;6043:36;;;;;:28;;;;;;:36;;6072:6;;6043:36;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;6043:36:11;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6043:36:11;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;6043:36:11;;;;;;;;;6137:48;;;;;6033:46;;-1:-1:-1;6137:28:11;;;;;;:48;;6166:6;;6174:10;;6137:48;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;6137:48:11;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6137:48:11;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;6137:48:11;;;;;;;;;6125:60;;5955:975;;;1065:41;;;;;;;;;;;;;;;;6206:30;;;;;;;6202:728;;;6270:25;:9;6292:2;6270:25;:21;:25;:::i;:::-;6252:43;;6364:35;6384:5;6391:7;6364:19;:35::i;:::-;6348:51;;6496:5;6486:15;;:6;:15;;;:23;;6508:1;6486:23;;;6504:1;6486:23;6476:33;;;;6620:5;6607:36;;;6644:6;6652:10;6607:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;6607:56:11;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6607:56:11;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;6607:56:11;;;;;;;;;:114;;;;6711:10;6667:54;;6680:5;6667:31;;;6699:7;6667:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;6667:40:11;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6667:40:11;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;6667:40:11;;;;;;;;;:54;;;6607:114;6589:132;;6837:10;:18;;6854:1;6837:18;;;6850:1;6837:18;6825:30;;;;6202:728;;;6886:33;;;;;;;;;;;;;;;;;;;6202:728;5614:1359;;;;;;;;;;;:::o;3018:384::-;3261:8;;:30;;;;;3161:38;;;;3261:8;;;;;:22;;:30;;3284:6;;3261:30;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3261:30:11;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3261:30:11;;;;;;39:16:-1;36:1;17:17;2:54;101:4;3261:30:11;80:15:-1;;;97:9;76:31;65:43;;120:4;113:20;3261:30:11;;;;;;;;;3248:43;;3315:38;3330:6;3338:14;4716:452;4850:12;4885:20;4931:31;5010:9;4908:6;:13;4885:36;;4982:12;4965:30;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;4931:64;;5022:1;5010:13;;5005:129;5025:17;;;5005:129;;5080:43;5094:6;5101:1;5094:9;;;;;;;;;;;;;;;;;;5105:14;5120:1;5105:17;;;;;;;;;;;;;;;;;;5080:13;:43::i;:::-;5063:11;5075:1;5063:14;;;;;;;;;;;;;;;;;;:60;5044:3;;5005:129;;;5150:11;5143:18;;4716:452;;;;;;;;:::o;7258:1214::-;7364:13;7477:2;7471:9;7574:66;7565:7;7558:83;7678:7;7674:1;7665:7;7661:15;7654:32;8100:2;8047:7;7990:2;7943:7;7894:5;7849:3;7821:332;8280:7;8277:2;;;8321:7;8315:14;8306:23;;8277:2;-1:-1:-1;;7258:1214:11;;;;;:::o;3661:739::-;3780:28;;:::i;:::-;4076:25;3879:64;3902:5;:18;;;3922:5;:20;;;3879:22;:64::i;:::-;3850:25;;;3824:119;;;4045:20;;;;4008:58;;4031:12;;4008:22;:58::i;:::-;3979:25;;;3953:113;3954:23;;;;3953:113;;;;4104:14;4076:42;;;;-1:-1:-1;4076:42:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4104:14;4076:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4189:56;4212:5;:18;;;4232:12;4189:22;:56::i;:::-;4157:28;;;4128:117;4129:26;;;4128:117;4316:50;4339:12;4353;4316:22;:50::i;:::-;4284:28;;;4255:111;4256:26;;;4255:111;3661:739;;;;;:::o;15559:559:48:-;15679:13;15741:5;15749:1;15741:9;15729:1;:8;:21;;15708:105;;;;;;;;;;;;;;;;-1:-1:-1;;15869:2:48;15862:10;15856:17;16012:66;16000:79;;15559:559::o;10259:886::-;10380:14;10443:5;10451:2;10443:10;10431:1;:8;:22;;10410:135;;;;;;;;;;;;;;;;-1:-1:-1;11047:13:48;10792:2;11047:13;11041:20;11063:42;11037:69;;10259:886::o;14699:195::-;14820:14;14865:21;14877:1;14880:5;14865:11;:21::i;:::-;14857:30;14699:195;-1:-1:-1;;;14699:195:48:o;13281:490::-;13402:14;13465:5;13473:2;13465:10;13453:1;:8;:22;;13432:107;;;;;;;;;;;;;;;;-1:-1:-1;13718:13:48;13620:2;13718:13;13712:20;;13281:490::o;898:7576:11:-;;;;;;;;;-1:-1:-1;898:7576:11;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;5:118:-1:-;;72:46;110:6;97:20;72:46;;130:122;;208:39;239:6;233:13;208:39;;277:707;;387:4;375:17;;371:27;-1:-1;361:2;;412:1;409;402:12;361:2;449:6;436:20;471:80;486:64;543:6;486:64;;;471:80;;;462:89;;568:5;593:6;586:5;579:21;623:4;615:6;611:17;601:27;;645:4;640:3;636:14;629:21;;698:6;745:3;737:4;729:6;725:17;720:3;716:27;713:36;710:2;;;762:1;759;752:12;710:2;787:1;772:206;797:6;794:1;791:13;772:206;;;855:3;877:37;910:3;898:10;877:37;;;865:50;;-1:-1;938:4;929:14;;;;957;;;;;819:1;812:9;772:206;;;776:14;354:630;;;;;;;;1028:791;;1172:4;1160:17;;1156:27;-1:-1;1146:2;;1197:1;1194;1187:12;1146:2;1227:6;1221:13;1249:103;1264:87;1344:6;1264:87;;1249:103;1240:112;;1369:5;1394:6;1387:5;1380:21;1424:4;1416:6;1412:17;1402:27;;1446:4;1441:3;1437:14;1430:21;;1499:6;1546:3;1538:4;1530:6;1526:17;1521:3;1517:27;1514:36;1511:2;;;1563:1;1560;1553:12;1511:2;1588:1;1573:240;1598:6;1595:1;1592:13;1573:240;;;1656:3;1678:71;1745:3;1733:10;1678:71;;;1666:84;;-1:-1;1773:4;1764:14;;;;1801:4;1792:14;;;;;1620:1;1613:9;1573:240;;1859:735;;1988:4;1976:17;;1972:27;-1:-1;1962:2;;2013:1;2010;2003:12;1962:2;2050:6;2037:20;2072:99;2087:83;2163:6;2087:83;;2072:99;2199:21;;;2243:4;2231:17;;;;2063:108;;-1:-1;2256:14;;2231:17;2351:1;2336:252;2361:6;2358:1;2355:13;2336:252;;;2444:3;2431:17;2423:6;2419:30;2468:56;2520:3;2508:10;2468:56;;;2456:69;;-1:-1;2548:4;2539:14;;;;2567;;;;;2383:1;2376:9;2336:252;;2602:116;;2677:36;2705:6;2699:13;2677:36;;2725:122;;2803:39;2834:6;2828:13;2803:39;;2855:432;;2945:4;2933:17;;2929:27;-1:-1;2919:2;;2970:1;2967;2960:12;2919:2;3007:6;2994:20;3029:60;3044:44;3081:6;3044:44;;3029:60;3020:69;;3109:6;3102:5;3095:21;3145:4;3137:6;3133:17;3178:4;3171:5;3167:16;3213:3;3204:6;3199:3;3195:16;3192:25;3189:2;;;3230:1;3227;3220:12;3189:2;3240:41;3274:6;3269:3;3264;3240:41;;3776:685;;3899:4;3887:9;3882:3;3878:19;3874:30;3871:2;;;3917:1;3914;3907:12;3871:2;3935:20;3950:4;3935:20;;;3926:29;-1:-1;4012:1;4043:58;4097:3;4077:9;4043:58;;;4019:83;;-1:-1;4168:2;4201:60;4257:3;4233:22;;;4201:60;;;4194:4;4187:5;4183:16;4176:86;4123:150;4346:2;4379:60;4435:3;4426:6;4415:9;4411:22;4379:60;;;4372:4;4365:5;4361:16;4354:86;4283:168;3865:596;;;;;5224:2205;;5332:5;5320:9;5315:3;5311:19;5307:31;5304:2;;;5351:1;5348;5341:12;5304:2;5369:21;5384:5;5369:21;;;5360:30;-1:-1;5448:1;5479:49;5524:3;5504:9;5479:49;;;5455:74;;-1:-1;5598:2;5631:49;5676:3;5652:22;;;5631:49;;;5624:4;5617:5;5613:16;5606:75;5550:142;5757:2;5790:49;5835:3;5826:6;5815:9;5811:22;5790:49;;;5783:4;5776:5;5772:16;5765:75;5702:149;5910:2;5943:49;5988:3;5979:6;5968:9;5964:22;5943:49;;;5936:4;5929:5;5925:16;5918:75;5861:143;6066:3;6100:49;6145:3;6136:6;6125:9;6121:22;6100:49;;;6093:4;6086:5;6082:16;6075:75;6014:147;6223:3;6257:49;6302:3;6293:6;6282:9;6278:22;6257:49;;;6250:4;6243:5;6239:16;6232:75;6171:147;6372:3;6406:49;6451:3;6442:6;6431:9;6427:22;6406:49;;;6399:4;6392:5;6388:16;6381:75;6328:139;6521:3;6555:49;6600:3;6591:6;6580:9;6576:22;6555:49;;;6548:4;6541:5;6537:16;6530:75;6477:139;6683:3;6718:49;6763:3;6754:6;6743:9;6739:22;6718:49;;;6710:5;6703;6699:17;6692:76;6626:153;6829:3;6864:49;6909:3;6900:6;6889:9;6885:22;6864:49;;;6856:5;6849;6845:17;6838:76;6789:136;7013:3;7002:9;6998:19;6985:33;7038:18;7030:6;7027:30;7024:2;;;7070:1;7067;7060:12;7024:2;7106:54;7156:3;7147:6;7136:9;7132:22;7106:54;;;7098:5;7091;7087:17;7080:81;6935:237;7260:3;7249:9;7245:19;7232:33;7285:18;7277:6;7274:30;7271:2;;;7317:1;7314;7307:12;7271:2;7353:54;7403:3;7394:6;7383:9;7379:22;7353:54;;;7345:5;7338;7334:17;7327:81;7182:237;5298:2131;;;;;9680:118;;9747:46;9785:6;9772:20;9747:46;;9934:118;;10010:37;10039:6;10033:13;10010:37;;10059:263;;10174:2;10162:9;10153:7;10149:23;10145:32;10142:2;;;10190:1;10187;10180:12;10142:2;10225:1;10242:64;10298:7;10278:9;10242:64;;;10232:74;10136:186;-1:-1;;;;10136:186;10329:470;;;10459:2;10447:9;10438:7;10434:23;10430:32;10427:2;;;10475:1;10472;10465:12;10427:2;10510:1;10527:53;10572:7;10552:9;10527:53;;;10517:63;;10489:97;10645:2;10634:9;10630:18;10617:32;10669:18;10661:6;10658:30;10655:2;;;10701:1;10698;10691:12;10655:2;10721:62;10775:7;10766:6;10755:9;10751:22;10721:62;;;10711:72;;10596:193;10421:378;;;;;;10806:366;;;10927:2;10915:9;10906:7;10902:23;10898:32;10895:2;;;10943:1;10940;10933:12;10895:2;10978:1;10995:53;11040:7;11020:9;10995:53;;;10985:63;;10957:97;11085:2;11103:53;11148:7;11139:6;11128:9;11124:22;11103:53;;11179:438;;11342:2;11330:9;11321:7;11317:23;11313:32;11310:2;;;11358:1;11355;11348:12;11310:2;11393:24;;11437:18;11426:30;;11423:2;;;11469:1;11466;11459:12;11423:2;11489:112;11593:7;11584:6;11573:9;11569:22;11489:112;;11624:676;;;11814:2;11802:9;11793:7;11789:23;11785:32;11782:2;;;11830:1;11827;11820:12;11782:2;11865:31;;11916:18;11905:30;;11902:2;;;11948:1;11945;11938:12;11902:2;11968:97;12057:7;12048:6;12037:9;12033:22;11968:97;;;11958:107;;11844:227;12130:2;12119:9;12115:18;12102:32;12154:18;12146:6;12143:30;12140:2;;;12186:1;12183;12176:12;12140:2;12206:78;12276:7;12267:6;12256:9;12252:22;12206:78;;12307:257;;12419:2;12407:9;12398:7;12394:23;12390:32;12387:2;;;12435:1;12432;12425:12;12387:2;12470:1;12487:61;12540:7;12520:9;12487:61;;12571:317;;12713:2;12701:9;12692:7;12688:23;12684:32;12681:2;;;12729:1;12726;12719:12;12681:2;12764:1;12781:91;12864:7;12844:9;12781:91;;12895:498;;;13039:2;13027:9;13018:7;13014:23;13010:32;13007:2;;;13055:1;13052;13045:12;13007:2;13090:31;;13141:18;13130:30;;13127:2;;;13173:1;13170;13163:12;13127:2;13193:76;13261:7;13252:6;13241:9;13237:22;13193:76;;;13183:86;;13069:206;13306:2;13324:53;13369:7;13360:6;13349:9;13345:22;13324:53;;13400:263;;13515:2;13503:9;13494:7;13490:23;13486:32;13483:2;;;13531:1;13528;13521:12;13483:2;13566:1;13583:64;13639:7;13619:9;13583:64;;13670:110;13743:31;13768:5;13743:31;;;13738:3;13731:44;13725:55;;;13854:755;;14035:77;14106:5;14035:77;;;14130:6;14125:3;14118:19;14154:4;14149:3;14145:14;14138:21;;14199:79;14272:5;14199:79;;;14299:1;14284:303;14309:6;14306:1;14303:13;14284:303;;;14349:103;14448:3;14439:6;14433:13;14349:103;;;14469:83;14545:6;14469:83;;;14575:4;14566:14;;;;;14459:93;-1:-1;14331:1;14324:9;14284:303;;;-1:-1;14600:3;;14014:595;-1:-1;;;;14014:595;14676:864;;14849:73;14916:5;14849:73;;;14940:6;14935:3;14928:19;14964:4;14959:3;14955:14;14948:21;;15012:3;15054:4;15046:6;15042:17;15037:3;15033:27;15080:75;15149:5;15080:75;;;15176:1;15161:340;15186:6;15183:1;15180:13;15161:340;;;15248:9;15242:4;15238:20;15233:3;15226:33;15274:96;15365:4;15356:6;15350:13;15274:96;;;15266:104;;15387:79;15459:6;15387:79;;;15489:4;15480:14;;;;;15377:89;-1:-1;15208:1;15201:9;15161:340;;;-1:-1;15514:4;;14828:712;-1:-1;;;;;;14828:712;15629:749;;15808:76;15878:5;15808:76;;;15902:6;15897:3;15890:19;15926:4;15921:3;15917:14;15910:21;;15971:78;16043:5;15971:78;;;16070:1;16055:301;16080:6;16077:1;16074:13;16055:301;;;16120:101;16217:3;16208:6;16202:13;16120:101;;;16238:82;16313:6;16238:82;;;16343:5;16334:15;;;;;16228:92;-1:-1;16102:1;16095:9;16055:301;;16386:110;16459:31;16484:5;16459:31;;16503:107;16574:30;16598:5;16574:30;;16617:289;;16713:34;16741:5;16713:34;;;16764:6;16759:3;16752:19;16776:63;16832:6;16825:4;16820:3;16816:14;16809:4;16802:5;16798:16;16776:63;;;16871:29;16893:6;16871:29;;;16851:50;;;16864:4;16851:50;;16693:213;-1:-1;;;16693:213;16914:397;17069:2;17057:15;;17106:66;17101:2;17092:12;;17085:88;17207:66;17202:2;17193:12;;17186:88;17302:2;17293:12;;17050:261;17320:296;17475:2;17463:15;;17512:66;17507:2;17498:12;;17491:88;17607:2;17598:12;;17456:160;17625:397;17780:2;17768:15;;17817:66;17812:2;17803:12;;17796:88;17918:66;17913:2;17904:12;;17897:88;18013:2;18004:12;;17761:261;18031:397;18186:2;18174:15;;18223:66;18218:2;18209:12;;18202:88;18324:66;18319:2;18310:12;;18303:88;18419:2;18410:12;;18167:261;18497:695;18710:22;;18634:4;18625:14;;;18744:57;18629:3;18710:22;18744:57;;;18654:159;18894:4;18887:5;18883:16;18877:23;18912:62;18968:4;18963:3;18959:14;18946:11;18912:62;;;18823:163;19085:4;19078:5;19074:16;19068:23;19103:62;19159:4;19154:3;19150:14;19137:11;19103:62;;;18996:181;18607:585;;;;20011:2419;20226:22;;20011:2419;;20148:5;20139:15;;;20260:61;20143:3;20226:22;20260:61;;;20169:164;20417:4;20410:5;20406:16;20400:23;20435:62;20491:4;20486:3;20482:14;20469:11;20435:62;;;20343:166;20600:4;20593:5;20589:16;20583:23;20618:62;20674:4;20669:3;20665:14;20652:11;20618:62;;;20519:173;20777:4;20770:5;20766:16;20760:23;20795:62;20851:4;20846:3;20842:14;20829:11;20795:62;;;20702:167;20957:4;20950:5;20946:16;20940:23;20975:62;21031:4;21026:3;21022:14;21009:11;20975:62;;;20879:170;21137:4;21130:5;21126:16;21120:23;21155:62;21211:4;21206:3;21202:14;21189:11;21155:62;;;21059:170;21309:4;21302:5;21298:16;21292:23;21327:62;21383:4;21378:3;21374:14;21361:11;21327:62;;;21239:162;21481:4;21474:5;21470:16;21464:23;21499:62;21555:4;21550:3;21546:14;21533:11;21499:62;;;21411:162;21666:5;21659;21655:17;21649:24;21685:63;21741:5;21736:3;21732:15;21719:11;21685:63;;;21583:177;21836:5;21829;21825:17;21819:24;21855:63;21911:5;21906:3;21902:15;21889:11;21855:63;;;21770:160;22016:5;22009;22005:17;21999:24;22069:3;22063:4;22059:14;22051:5;22046:3;22042:15;22035:39;22089:66;22150:4;22137:11;22089:66;;;22081:74;;21940:227;22253:5;22246;22242:17;22236:24;22306:3;22300:4;22296:14;22288:5;22283:3;22279:15;22272:39;22326:66;22387:4;22374:11;22326:66;;;22318:74;20121:2309;-1:-1;;;;;20121:2309;24987:1587;25200:22;;25122:5;25113:15;;;25234:61;25117:3;25200:22;25234:61;;;25143:164;25393:4;25386:5;25382:16;25376:23;25411:62;25467:4;25462:3;25458:14;25445:11;25411:62;;;25317:168;25569:4;25562:5;25558:16;25552:23;25587:62;25643:4;25638:3;25634:14;25621:11;25587:62;;;25495:166;25747:4;25740:5;25736:16;25730:23;25765:62;25821:4;25816:3;25812:14;25799:11;25765:62;;;25671:168;25926:4;25919:5;25915:16;25909:23;25944:62;26000:4;25995:3;25991:14;25978:11;25944:62;;;25849:169;26107:4;26100:5;26096:16;26090:23;26125:62;26181:4;26176:3;26172:14;26159:11;26125:62;;;26028:171;26286:4;26279:5;26275:16;26269:23;26304:62;26360:4;26355:3;26351:14;26338:11;26304:62;;;26209:169;26467:4;26460:5;26456:16;26450:23;26485:62;26541:4;26536:3;26532:14;26519:11;26485:62;;28363:104;28432:29;28455:5;28432:29;;28474:193;28582:2;28567:18;;28596:61;28571:9;28630:6;28596:61;;28674:294;28810:2;28795:18;;28824:61;28799:9;28858:6;28824:61;;;28896:62;28954:2;28943:9;28939:18;28930:6;28896:62;;28975:770;29301:2;29315:47;;;29286:18;;29376:144;29286:18;29506:6;29376:144;;;29368:152;;29568:9;29562:4;29558:20;29553:2;29542:9;29538:18;29531:48;29593:142;29730:4;29721:6;29593:142;;29752:417;29948:2;29962:47;;;29933:18;;30023:136;29933:18;30145:6;30023:136;;30176:429;30378:2;30392:47;;;30363:18;;30453:142;30363:18;30581:6;30453:142;;30612:189;30718:2;30703:18;;30732:59;30707:9;30764:6;30732:59;;30808:387;30989:2;31003:47;;;30974:18;;31064:121;30974:18;31064:121;;31202:387;31383:2;31397:47;;;31368:18;;31458:121;31368:18;31458:121;;31596:387;31777:2;31791:47;;;31762:18;;31852:121;31762:18;31852:121;;31990:387;32171:2;32185:47;;;32156:18;;32246:121;32156:18;32246:121;;32384:507;32626:3;32611:19;;32641:115;32615:9;32729:6;32641:115;;;32767:114;32877:2;32866:9;32862:18;32853:6;32767:114;;32898:333;33052:2;33066:47;;;33037:18;;33127:94;33037:18;33207:6;33127:94;;33238:298;33398:3;33383:19;;33413:113;33387:9;33499:6;33413:113;;33543:193;33651:2;33636:18;;33665:61;33640:9;33699:6;33665:61;;33743:294;33879:2;33864:18;;33893:61;33868:9;33927:6;33893:61;;;33965:62;34023:2;34012:9;34008:18;33999:6;33965:62;;34044:256;34106:2;34100:9;34132:17;;;34207:18;34192:34;;34228:22;;;34189:62;34186:2;;;34264:1;34261;34254:12;34186:2;34280;34273:22;34084:216;;-1:-1;34084:216;34307:258;;34466:18;34458:6;34455:30;34452:2;;;34498:1;34495;34488:12;34452:2;-1:-1;34527:4;34515:17;;;34545:15;;34389:176;35144:254;;35283:18;35275:6;35272:30;35269:2;;;35315:1;35312;35305:12;35269:2;-1:-1;35388:4;35359;35336:17;;;;35355:9;35332:33;35378:15;;35206:192;35672:144;35804:4;35792:17;;35773:43;36130:130;36243:12;;36227:33;37087:128;37167:42;37156:54;;37139:76;37222:79;37291:5;37274:27;37308:151;37387:66;37376:78;;37359:100;37552:88;37630:4;37619:16;;37602:38;37782:92;37855:13;37848:21;;37831:43;38149:145;38230:6;38225:3;38220;38207:30;-1:-1;38286:1;38268:16;;38261:27;38200:94;38303:268;38368:1;38375:101;38389:6;38386:1;38383:13;38375:101;;;38456:11;;;38450:18;38437:11;;;38430:39;38411:2;38404:10;38375:101;;;38491:6;38488:1;38485:13;38482:2;;;-1:-1;;38556:1;38538:16;;38531:27;38352:219;38579:97;38667:2;38647:14;38663:7;38643:28;;38627:49" + "object": "0x6080604052600436106100825763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166304ad1e5381146100875780632cd0fc73146100be5780634b95de13146100ec578063690d31141461011a578063b698846314610147578063c6b7f4ee14610174578063f241ffb0146101a2575b600080fd5b34801561009357600080fd5b506100a76100a23660046112d3565b6101cf565b6040516100b59291906118dc565b60405180910390f35b3480156100ca57600080fd5b506100de6100d936600461118b565b61029c565b6040516100b5929190611926565b3480156100f857600080fd5b5061010c610107366004611238565b6107cd565b6040516100b5929190611822565b34801561012657600080fd5b5061013a610135366004611238565b6108a4565b6040516100b59190611858565b34801561015357600080fd5b506101676101623660046111d3565b61095e565b6040516100b591906117f9565b34801561018057600080fd5b5061019461018f366004611139565b6109a9565b6040516100b5929190611869565b3480156101ae57600080fd5b506101c26101bd3660046112d3565b610a86565b6040516100b59190611909565b6101d7610cd0565b6101df610cf0565b6000546040517fc75e0a8100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063c75e0a81906102359087906004016118f8565b606060405180830381600087803b15801561024f57600080fd5b505af1158015610263573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061028791908101906112b5565b91506102938484610a86565b90509250929050565b6000808080808080806102b5898263ffffffff610ba416565b95506102c889601063ffffffff610c1116565b6000546040517f6070410800000000000000000000000000000000000000000000000000000000815291965073ffffffffffffffffffffffffffffffffffffffff169063607041089061031f90899060040161188e565b602060405180830381600087803b15801561033957600080fd5b505af115801561034d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506103719190810190611113565b604080517f4552433230546f6b656e28616464726573732900000000000000000000000000815290519081900360130190209094507fffffffff0000000000000000000000000000000000000000000000000000000087811691161415610526576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8616906370a0823190610424908d906004016117f9565b602060405180830381600087803b15801561043e57600080fd5b505af1158015610452573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610476919081019061131a565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815290985073ffffffffffffffffffffffffffffffffffffffff86169063dd62ed3e906104cd908d908890600401611807565b602060405180830381600087803b1580156104e757600080fd5b505af11580156104fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061051f919081019061131a565b96506107c0565b604080517f455243373231546f6b656e28616464726573732c75696e7432353629000000008152905190819003601c0190207fffffffff00000000000000000000000000000000000000000000000000000000878116911614156107855761059589602463ffffffff610c7216565b92506105a1858461095e565b91508173ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16146105dd5760006105e0565b60015b60ff1697508473ffffffffffffffffffffffffffffffffffffffff1663e985e9c58b866040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040161063c929190611807565b602060405180830381600087803b15801561065657600080fd5b505af115801561066a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061068e9190810190611297565b8061076a57508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1663081812fc856040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016107009190611918565b602060405180830381600087803b15801561071a57600080fd5b505af115801561072e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107529190810190611113565b73ffffffffffffffffffffffffffffffffffffffff16145b90508061077857600061077b565b60015b60ff1696506107c0565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107b7906118ac565b60405180910390fd5b5050505050509250929050565b6000546040517f7e9d74dc000000000000000000000000000000000000000000000000000000008152606091829173ffffffffffffffffffffffffffffffffffffffff90911690637e9d74dc90610828908790600401611847565b600060405180830381600087803b15801561084257600080fd5b505af1158015610856573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261089c9190810190611203565b915061029384845b606060006060600085519250826040519080825280602002602001820160405280156108ea57816020015b6108d7610cf0565b8152602001906001900390816108cf5790505b509150600090505b80831461095157610931868281518110151561090a57fe5b90602001906020020151868381518110151561092257fe5b90602001906020020151610a86565b828281518110151561093f57fe5b602090810290910101526001016108f2565b8193505b50505092915050565b60006040517f6352211e000000000000000000000000000000000000000000000000000000008152826004820152602081602483875afa80156109a057815192505b50505b92915050565b6060806000606080600086519350836040519080825280602002602001820160405280156109e1578160200160208202803883390190505b50925083604051908082528060200260200182016040528015610a0e578160200160208202803883390190505b509150600090505b808414610a7957610a3e888883815181101515610a2f57fe5b9060200190602002015161029c565b8483815181101515610a4c57fe5b9060200190602002018484815181101515610a6357fe5b6020908102909101019190915252600101610a16565b5090969095509350505050565b610a8e610cf0565b6060610aa3846000015185610140015161029c565b60208401528252610160840151610abb90849061029c565b60608401526040808401919091526001805482516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101008688161502019094169390930492830181900481028201810190945281815292830182828015610b6a5780601f10610b3f57610100808354040283529160200191610b6a565b820191906000526020600020905b815481529060010190602001808311610b4d57829003601f168201915b50505050509050610b7f84600001518261029c565b60a08401526080830152610b93838261029c565b60e084015260c08301525092915050565b600081600401835110151515610be6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107b7906118cc565b5050602001517fffffffff000000000000000000000000000000000000000000000000000000001690565b600081601401835110151515610c53576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107b7906118bc565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b6000610c7e8383610c85565b9392505050565b600081602001835110151515610cc7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107b79061189c565b50016020015190565b604080516060810182526000808252602082018190529181019190915290565b6101006040519081016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000610c7e82356119d9565b6000610c7e82516119d9565b6000601f82018313610d5f57600080fd5b8135610d72610d6d82611968565b611941565b91508181835260208401935060208101905083856020840282011115610d9757600080fd5b60005b83811015610dc35781610dad8882610d36565b8452506020928301929190910190600101610d9a565b5050505092915050565b6000601f82018313610dde57600080fd5b8135610dec610d6d82611968565b81815260209384019390925082018360005b83811015610dc35781358601610e148882610f11565b8452506020928301929190910190600101610dfe565b6000601f82018313610e3b57600080fd5b8151610e49610d6d82611968565b91508181835260208401935060208101905083856060840282011115610e6e57600080fd5b60005b83811015610dc35781610e848882610f57565b84525060209092019160609190910190600101610e71565b6000601f82018313610ead57600080fd5b8135610ebb610d6d82611968565b81815260209384019390925082018360005b83811015610dc35781358601610ee38882610fb2565b8452506020928301929190910190600101610ecd565b6000610c7e8251611a20565b6000610c7e82516119f2565b6000601f82018313610f2257600080fd5b8135610f30610d6d82611989565b91508082526020830160208301858383011115610f4c57600080fd5b610955838284611a25565b600060608284031215610f6957600080fd5b610f736060611941565b90506000610f818484611107565b8252506020610f9284848301610f05565b6020830152506040610fa684828501610f05565b60408301525092915050565b60006101808284031215610fc557600080fd5b610fd0610180611941565b90506000610fde8484610d36565b8252506020610fef84848301610d36565b602083015250604061100384828501610d36565b604083015250606061101784828501610d36565b606083015250608061102b848285016110fb565b60808301525060a061103f848285016110fb565b60a08301525060c0611053848285016110fb565b60c08301525060e0611067848285016110fb565b60e08301525061010061107c848285016110fb565b61010083015250610120611092848285016110fb565b6101208301525061014082013567ffffffffffffffff8111156110b457600080fd5b6110c084828501610f11565b6101408301525061016082013567ffffffffffffffff8111156110e257600080fd5b6110ee84828501610f11565b6101608301525092915050565b6000610c7e82356119f2565b6000610c7e8251611a1a565b60006020828403121561112557600080fd5b60006111318484610d42565b949350505050565b6000806040838503121561114c57600080fd5b60006111588585610d36565b925050602083013567ffffffffffffffff81111561117557600080fd5b61118185828601610dcd565b9150509250929050565b6000806040838503121561119e57600080fd5b60006111aa8585610d36565b925050602083013567ffffffffffffffff8111156111c757600080fd5b61118185828601610f11565b600080604083850312156111e657600080fd5b60006111f28585610d36565b9250506020611181858286016110fb565b60006020828403121561121557600080fd5b815167ffffffffffffffff81111561122c57600080fd5b61113184828501610e2a565b6000806040838503121561124b57600080fd5b823567ffffffffffffffff81111561126257600080fd5b61126e85828601610e9c565b925050602083013567ffffffffffffffff81111561128b57600080fd5b61118185828601610d4e565b6000602082840312156112a957600080fd5b60006111318484610ef9565b6000606082840312156112c757600080fd5b60006111318484610f57565b600080604083850312156112e657600080fd5b823567ffffffffffffffff8111156112fd57600080fd5b61130985828601610fb2565b925050602061118185828601610d36565b60006020828403121561132c57600080fd5b60006111318484610f05565b611341816119d9565b82525050565b6000611352826119d5565b808452602084019350611364836119cf565b60005b828110156113945761137a868351611619565b611383826119cf565b606096909601959150600101611367565b5093949350505050565b60006113a9826119d5565b808452602084019350836020820285016113c2856119cf565b60005b848110156113f95783830388526113dd838351611656565b92506113e8826119cf565b6020989098019791506001016113c5565b50909695505050505050565b6000611410826119d5565b808452602084019350611422836119cf565b60005b8281101561139457611438868351611759565b611441826119cf565b61010096909601959150600101611425565b600061145e826119d5565b808452602084019350611470836119cf565b60005b82811015611394576114868683516114a0565b61148f826119cf565b602096909601959150600101611473565b611341816119f2565b611341816119f5565b60006114bd826119d5565b8084526114d1816020860160208601611a31565b6114da81611a5d565b9093016020019392505050565b602681527f475245415445525f4f525f455155414c5f544f5f33325f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b601781527f554e535550504f525445445f41535345545f50524f5859000000000000000000602082015260400190565b602681527f475245415445525f4f525f455155414c5f544f5f32305f4c454e4754485f524560208201527f5155495245440000000000000000000000000000000000000000000000000000604082015260600190565b602581527f475245415445525f4f525f455155414c5f544f5f345f4c454e4754485f52455160208201527f5549524544000000000000000000000000000000000000000000000000000000604082015260600190565b8051606083019061162a84826117f0565b50602082015161163d60208501826114a0565b50604082015161165060408501826114a0565b50505050565b805160009061018084019061166b8582611338565b50602083015161167e6020860182611338565b5060408301516116916040860182611338565b5060608301516116a46060860182611338565b5060808301516116b760808601826114a0565b5060a08301516116ca60a08601826114a0565b5060c08301516116dd60c08601826114a0565b5060e08301516116f060e08601826114a0565b506101008301516117056101008601826114a0565b5061012083015161171a6101208601826114a0565b5061014083015184820361014086015261173482826114b2565b91505061016083015184820361016086015261175082826114b2565b95945050505050565b805161010083019061176b84826114a0565b50602082015161177e60208501826114a0565b50604082015161179160408501826114a0565b5060608201516117a460608501826114a0565b5060808201516117b760808501826114a0565b5060a08201516117ca60a08501826114a0565b5060c08201516117dd60c08501826114a0565b5060e082015161165060e08501826114a0565b61134181611a1a565b602081016109a38284611338565b604081016118158285611338565b610c7e6020830184611338565b604080825281016118338185611347565b905081810360208301526111318184611405565b60208082528101610c7e818461139e565b60208082528101610c7e8184611405565b6040808252810161187a8185611453565b905081810360208301526111318184611453565b602081016109a382846114a9565b602080825281016109a3816114e7565b602080825281016109a38161153d565b602080825281016109a38161156d565b602080825281016109a3816115c3565b61016081016118eb8285611619565b610c7e6060830184611759565b60208082528101610c7e8184611656565b61010081016109a38284611759565b602081016109a382846114a0565b6040810161193482856114a0565b610c7e60208301846114a0565b60405181810167ffffffffffffffff8111828210171561196057600080fd5b604052919050565b600067ffffffffffffffff82111561197f57600080fd5b5060209081020190565b600067ffffffffffffffff8211156119a057600080fd5b506020601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160190565b60200190565b5190565b73ffffffffffffffffffffffffffffffffffffffff1690565b90565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b60ff1690565b151590565b82818337506000910152565b60005b83811015611a4c578181015183820152602001611a34565b838111156116505750506000910152565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016905600a265627a7a72305820d3d495bc287663ed8cb2a513cfad47804ffa6e4ad0cfa6d0d0eadf1f907483586c6578706572696d656e74616cf50037", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x82 JUMPI PUSH4 0xFFFFFFFF PUSH29 0x100000000000000000000000000000000000000000000000000000000 PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0x4AD1E53 DUP2 EQ PUSH2 0x87 JUMPI DUP1 PUSH4 0x2CD0FC73 EQ PUSH2 0xBE JUMPI DUP1 PUSH4 0x4B95DE13 EQ PUSH2 0xEC JUMPI DUP1 PUSH4 0x690D3114 EQ PUSH2 0x11A JUMPI DUP1 PUSH4 0xB6988463 EQ PUSH2 0x147 JUMPI DUP1 PUSH4 0xC6B7F4EE EQ PUSH2 0x174 JUMPI DUP1 PUSH4 0xF241FFB0 EQ PUSH2 0x1A2 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x93 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xA7 PUSH2 0xA2 CALLDATASIZE PUSH1 0x4 PUSH2 0x12D3 JUMP JUMPDEST PUSH2 0x1CF JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xB5 SWAP3 SWAP2 SWAP1 PUSH2 0x18DC JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0xCA JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xDE PUSH2 0xD9 CALLDATASIZE PUSH1 0x4 PUSH2 0x118B JUMP JUMPDEST PUSH2 0x29C JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xB5 SWAP3 SWAP2 SWAP1 PUSH2 0x1926 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0xF8 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x10C PUSH2 0x107 CALLDATASIZE PUSH1 0x4 PUSH2 0x1238 JUMP JUMPDEST PUSH2 0x7CD JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xB5 SWAP3 SWAP2 SWAP1 PUSH2 0x1822 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x126 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x13A PUSH2 0x135 CALLDATASIZE PUSH1 0x4 PUSH2 0x1238 JUMP JUMPDEST PUSH2 0x8A4 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xB5 SWAP2 SWAP1 PUSH2 0x1858 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x153 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x167 PUSH2 0x162 CALLDATASIZE PUSH1 0x4 PUSH2 0x11D3 JUMP JUMPDEST PUSH2 0x95E JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xB5 SWAP2 SWAP1 PUSH2 0x17F9 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x180 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x194 PUSH2 0x18F CALLDATASIZE PUSH1 0x4 PUSH2 0x1139 JUMP JUMPDEST PUSH2 0x9A9 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xB5 SWAP3 SWAP2 SWAP1 PUSH2 0x1869 JUMP JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x1AE JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x1C2 PUSH2 0x1BD CALLDATASIZE PUSH1 0x4 PUSH2 0x12D3 JUMP JUMPDEST PUSH2 0xA86 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0xB5 SWAP2 SWAP1 PUSH2 0x1909 JUMP JUMPDEST PUSH2 0x1D7 PUSH2 0xCD0 JUMP JUMPDEST PUSH2 0x1DF PUSH2 0xCF0 JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH1 0x40 MLOAD PUSH32 0xC75E0A8100000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP2 AND SWAP1 PUSH4 0xC75E0A81 SWAP1 PUSH2 0x235 SWAP1 DUP8 SWAP1 PUSH1 0x4 ADD PUSH2 0x18F8 JUMP JUMPDEST PUSH1 0x60 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x24F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x263 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 0x287 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x12B5 JUMP JUMPDEST SWAP2 POP PUSH2 0x293 DUP5 DUP5 PUSH2 0xA86 JUMP JUMPDEST SWAP1 POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP1 DUP1 DUP1 DUP1 DUP1 DUP1 PUSH2 0x2B5 DUP10 DUP3 PUSH4 0xFFFFFFFF PUSH2 0xBA4 AND JUMP JUMPDEST SWAP6 POP PUSH2 0x2C8 DUP10 PUSH1 0x10 PUSH4 0xFFFFFFFF PUSH2 0xC11 AND JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH1 0x40 MLOAD PUSH32 0x6070410800000000000000000000000000000000000000000000000000000000 DUP2 MSTORE SWAP2 SWAP7 POP PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH4 0x60704108 SWAP1 PUSH2 0x31F SWAP1 DUP10 SWAP1 PUSH1 0x4 ADD PUSH2 0x188E JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x339 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x34D 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 0x371 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1113 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0x4552433230546F6B656E28616464726573732900000000000000000000000000 DUP2 MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x13 ADD SWAP1 KECCAK256 SWAP1 SWAP5 POP PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 DUP8 DUP2 AND SWAP2 AND EQ ISZERO PUSH2 0x526 JUMPI PUSH1 0x40 MLOAD PUSH32 0x70A0823100000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP7 AND SWAP1 PUSH4 0x70A08231 SWAP1 PUSH2 0x424 SWAP1 DUP14 SWAP1 PUSH1 0x4 ADD PUSH2 0x17F9 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x43E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x452 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 0x476 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x131A JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0xDD62ED3E00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE SWAP1 SWAP9 POP PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP7 AND SWAP1 PUSH4 0xDD62ED3E SWAP1 PUSH2 0x4CD SWAP1 DUP14 SWAP1 DUP9 SWAP1 PUSH1 0x4 ADD PUSH2 0x1807 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x4E7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x4FB 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 0x51F SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x131A JUMP JUMPDEST SWAP7 POP PUSH2 0x7C0 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH32 0x455243373231546F6B656E28616464726573732C75696E743235362900000000 DUP2 MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x1C ADD SWAP1 KECCAK256 PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 DUP8 DUP2 AND SWAP2 AND EQ ISZERO PUSH2 0x785 JUMPI PUSH2 0x595 DUP10 PUSH1 0x24 PUSH4 0xFFFFFFFF PUSH2 0xC72 AND JUMP JUMPDEST SWAP3 POP PUSH2 0x5A1 DUP6 DUP5 PUSH2 0x95E JUMP JUMPDEST SWAP2 POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ PUSH2 0x5DD JUMPI PUSH1 0x0 PUSH2 0x5E0 JUMP JUMPDEST PUSH1 0x1 JUMPDEST PUSH1 0xFF AND SWAP8 POP DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH4 0xE985E9C5 DUP12 DUP7 PUSH1 0x40 MLOAD DUP4 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x63C SWAP3 SWAP2 SWAP1 PUSH2 0x1807 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x656 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x66A 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 0x68E SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1297 JUMP JUMPDEST DUP1 PUSH2 0x76A JUMPI POP DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH4 0x81812FC DUP6 PUSH1 0x40 MLOAD DUP3 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x700 SWAP2 SWAP1 PUSH2 0x1918 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x71A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x72E 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 0x752 SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1113 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ JUMPDEST SWAP1 POP DUP1 PUSH2 0x778 JUMPI PUSH1 0x0 PUSH2 0x77B JUMP JUMPDEST PUSH1 0x1 JUMPDEST PUSH1 0xFF AND SWAP7 POP PUSH2 0x7C0 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x7B7 SWAP1 PUSH2 0x18AC JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP POP POP POP POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH1 0x40 MLOAD PUSH32 0x7E9D74DC00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x60 SWAP2 DUP3 SWAP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP2 AND SWAP1 PUSH4 0x7E9D74DC SWAP1 PUSH2 0x828 SWAP1 DUP8 SWAP1 PUSH1 0x4 ADD PUSH2 0x1847 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x842 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0x856 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP PUSH1 0x40 MLOAD RETURNDATASIZE PUSH1 0x0 DUP3 RETURNDATACOPY PUSH1 0x1F RETURNDATASIZE SWAP1 DUP2 ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND DUP3 ADD PUSH1 0x40 MSTORE PUSH2 0x89C SWAP2 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1203 JUMP JUMPDEST SWAP2 POP PUSH2 0x293 DUP5 DUP5 JUMPDEST PUSH1 0x60 PUSH1 0x0 PUSH1 0x60 PUSH1 0x0 DUP6 MLOAD SWAP3 POP DUP3 PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x8EA JUMPI DUP2 PUSH1 0x20 ADD JUMPDEST PUSH2 0x8D7 PUSH2 0xCF0 JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD SWAP1 PUSH1 0x1 SWAP1 SUB SWAP1 DUP2 PUSH2 0x8CF JUMPI SWAP1 POP JUMPDEST POP SWAP2 POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP1 DUP4 EQ PUSH2 0x951 JUMPI PUSH2 0x931 DUP7 DUP3 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x90A JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD DUP7 DUP4 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x922 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH2 0xA86 JUMP JUMPDEST DUP3 DUP3 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x93F JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP1 SWAP2 ADD ADD MSTORE PUSH1 0x1 ADD PUSH2 0x8F2 JUMP JUMPDEST DUP2 SWAP4 POP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x40 MLOAD PUSH32 0x6352211E00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE DUP3 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x20 DUP2 PUSH1 0x24 DUP4 DUP8 GAS STATICCALL DUP1 ISZERO PUSH2 0x9A0 JUMPI DUP2 MLOAD SWAP3 POP JUMPDEST POP POP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x60 DUP1 PUSH1 0x0 PUSH1 0x60 DUP1 PUSH1 0x0 DUP7 MLOAD SWAP4 POP DUP4 PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x9E1 JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP3 POP DUP4 PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0xA0E JUMPI DUP2 PUSH1 0x20 ADD PUSH1 0x20 DUP3 MUL DUP1 CODESIZE DUP4 CODECOPY ADD SWAP1 POP JUMPDEST POP SWAP2 POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP1 DUP5 EQ PUSH2 0xA79 JUMPI PUSH2 0xA3E DUP9 DUP9 DUP4 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0xA2F JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH2 0x29C JUMP JUMPDEST DUP5 DUP4 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0xA4C JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD DUP5 DUP5 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0xA63 JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP1 SWAP2 ADD ADD SWAP2 SWAP1 SWAP2 MSTORE MSTORE PUSH1 0x1 ADD PUSH2 0xA16 JUMP JUMPDEST POP SWAP1 SWAP7 SWAP1 SWAP6 POP SWAP4 POP POP POP POP JUMP JUMPDEST PUSH2 0xA8E PUSH2 0xCF0 JUMP JUMPDEST PUSH1 0x60 PUSH2 0xAA3 DUP5 PUSH1 0x0 ADD MLOAD DUP6 PUSH2 0x140 ADD MLOAD PUSH2 0x29C JUMP JUMPDEST PUSH1 0x20 DUP5 ADD MSTORE DUP3 MSTORE PUSH2 0x160 DUP5 ADD MLOAD PUSH2 0xABB SWAP1 DUP5 SWAP1 PUSH2 0x29C JUMP JUMPDEST PUSH1 0x60 DUP5 ADD MSTORE PUSH1 0x40 DUP1 DUP5 ADD SWAP2 SWAP1 SWAP2 MSTORE PUSH1 0x1 DUP1 SLOAD DUP3 MLOAD PUSH1 0x20 PUSH1 0x1F PUSH1 0x2 PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF PUSH2 0x100 DUP7 DUP9 AND ISZERO MUL ADD SWAP1 SWAP5 AND SWAP4 SWAP1 SWAP4 DIV SWAP3 DUP4 ADD DUP2 SWAP1 DIV DUP2 MUL DUP3 ADD DUP2 ADD SWAP1 SWAP5 MSTORE DUP2 DUP2 MSTORE SWAP3 DUP4 ADD DUP3 DUP3 DUP1 ISZERO PUSH2 0xB6A JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xB3F JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xB6A JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xB4D JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP PUSH2 0xB7F DUP5 PUSH1 0x0 ADD MLOAD DUP3 PUSH2 0x29C JUMP JUMPDEST PUSH1 0xA0 DUP5 ADD MSTORE PUSH1 0x80 DUP4 ADD MSTORE PUSH2 0xB93 DUP4 DUP3 PUSH2 0x29C JUMP JUMPDEST PUSH1 0xE0 DUP5 ADD MSTORE PUSH1 0xC0 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x4 ADD DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0xBE6 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x7B7 SWAP1 PUSH2 0x18CC JUMP JUMPDEST POP POP PUSH1 0x20 ADD MLOAD PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 AND SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x14 ADD DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0xC53 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x7B7 SWAP1 PUSH2 0x18BC JUMP JUMPDEST POP ADD PUSH1 0x14 ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xC7E DUP4 DUP4 PUSH2 0xC85 JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 PUSH1 0x20 ADD DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0xCC7 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x7B7 SWAP1 PUSH2 0x189C JUMP JUMPDEST POP ADD PUSH1 0x20 ADD MLOAD SWAP1 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x60 DUP2 ADD DUP3 MSTORE PUSH1 0x0 DUP1 DUP3 MSTORE PUSH1 0x20 DUP3 ADD DUP2 SWAP1 MSTORE SWAP2 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE SWAP1 JUMP JUMPDEST PUSH2 0x100 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 PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xC7E DUP3 CALLDATALOAD PUSH2 0x19D9 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xC7E DUP3 MLOAD PUSH2 0x19D9 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xD5F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xD72 PUSH2 0xD6D DUP3 PUSH2 0x1968 JUMP JUMPDEST PUSH2 0x1941 JUMP JUMPDEST SWAP2 POP DUP2 DUP2 DUP4 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH1 0x20 DUP2 ADD SWAP1 POP DUP4 DUP6 PUSH1 0x20 DUP5 MUL DUP3 ADD GT ISZERO PUSH2 0xD97 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xDC3 JUMPI DUP2 PUSH2 0xDAD DUP9 DUP3 PUSH2 0xD36 JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xD9A JUMP JUMPDEST POP POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xDDE JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xDEC PUSH2 0xD6D DUP3 PUSH2 0x1968 JUMP JUMPDEST DUP2 DUP2 MSTORE PUSH1 0x20 SWAP4 DUP5 ADD SWAP4 SWAP1 SWAP3 POP DUP3 ADD DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xDC3 JUMPI DUP2 CALLDATALOAD DUP7 ADD PUSH2 0xE14 DUP9 DUP3 PUSH2 0xF11 JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xDFE JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xE3B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 MLOAD PUSH2 0xE49 PUSH2 0xD6D DUP3 PUSH2 0x1968 JUMP JUMPDEST SWAP2 POP DUP2 DUP2 DUP4 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH1 0x20 DUP2 ADD SWAP1 POP DUP4 DUP6 PUSH1 0x60 DUP5 MUL DUP3 ADD GT ISZERO PUSH2 0xE6E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xDC3 JUMPI DUP2 PUSH2 0xE84 DUP9 DUP3 PUSH2 0xF57 JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 SWAP1 SWAP3 ADD SWAP2 PUSH1 0x60 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xE71 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xEAD JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xEBB PUSH2 0xD6D DUP3 PUSH2 0x1968 JUMP JUMPDEST DUP2 DUP2 MSTORE PUSH1 0x20 SWAP4 DUP5 ADD SWAP4 SWAP1 SWAP3 POP DUP3 ADD DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xDC3 JUMPI DUP2 CALLDATALOAD DUP7 ADD PUSH2 0xEE3 DUP9 DUP3 PUSH2 0xFB2 JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xECD JUMP JUMPDEST PUSH1 0x0 PUSH2 0xC7E DUP3 MLOAD PUSH2 0x1A20 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xC7E DUP3 MLOAD PUSH2 0x19F2 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1F DUP3 ADD DUP4 SGT PUSH2 0xF22 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xF30 PUSH2 0xD6D DUP3 PUSH2 0x1989 JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE PUSH1 0x20 DUP4 ADD PUSH1 0x20 DUP4 ADD DUP6 DUP4 DUP4 ADD GT ISZERO PUSH2 0xF4C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x955 DUP4 DUP3 DUP5 PUSH2 0x1A25 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xF69 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xF73 PUSH1 0x60 PUSH2 0x1941 JUMP JUMPDEST SWAP1 POP PUSH1 0x0 PUSH2 0xF81 DUP5 DUP5 PUSH2 0x1107 JUMP JUMPDEST DUP3 MSTORE POP PUSH1 0x20 PUSH2 0xF92 DUP5 DUP5 DUP4 ADD PUSH2 0xF05 JUMP JUMPDEST PUSH1 0x20 DUP4 ADD MSTORE POP PUSH1 0x40 PUSH2 0xFA6 DUP5 DUP3 DUP6 ADD PUSH2 0xF05 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x180 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xFC5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xFD0 PUSH2 0x180 PUSH2 0x1941 JUMP JUMPDEST SWAP1 POP PUSH1 0x0 PUSH2 0xFDE DUP5 DUP5 PUSH2 0xD36 JUMP JUMPDEST DUP3 MSTORE POP PUSH1 0x20 PUSH2 0xFEF DUP5 DUP5 DUP4 ADD PUSH2 0xD36 JUMP JUMPDEST PUSH1 0x20 DUP4 ADD MSTORE POP PUSH1 0x40 PUSH2 0x1003 DUP5 DUP3 DUP6 ADD PUSH2 0xD36 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MSTORE POP PUSH1 0x60 PUSH2 0x1017 DUP5 DUP3 DUP6 ADD PUSH2 0xD36 JUMP JUMPDEST PUSH1 0x60 DUP4 ADD MSTORE POP PUSH1 0x80 PUSH2 0x102B DUP5 DUP3 DUP6 ADD PUSH2 0x10FB JUMP JUMPDEST PUSH1 0x80 DUP4 ADD MSTORE POP PUSH1 0xA0 PUSH2 0x103F DUP5 DUP3 DUP6 ADD PUSH2 0x10FB JUMP JUMPDEST PUSH1 0xA0 DUP4 ADD MSTORE POP PUSH1 0xC0 PUSH2 0x1053 DUP5 DUP3 DUP6 ADD PUSH2 0x10FB JUMP JUMPDEST PUSH1 0xC0 DUP4 ADD MSTORE POP PUSH1 0xE0 PUSH2 0x1067 DUP5 DUP3 DUP6 ADD PUSH2 0x10FB JUMP JUMPDEST PUSH1 0xE0 DUP4 ADD MSTORE POP PUSH2 0x100 PUSH2 0x107C DUP5 DUP3 DUP6 ADD PUSH2 0x10FB JUMP JUMPDEST PUSH2 0x100 DUP4 ADD MSTORE POP PUSH2 0x120 PUSH2 0x1092 DUP5 DUP3 DUP6 ADD PUSH2 0x10FB JUMP JUMPDEST PUSH2 0x120 DUP4 ADD MSTORE POP PUSH2 0x140 DUP3 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x10B4 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x10C0 DUP5 DUP3 DUP6 ADD PUSH2 0xF11 JUMP JUMPDEST PUSH2 0x140 DUP4 ADD MSTORE POP PUSH2 0x160 DUP3 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x10E2 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x10EE DUP5 DUP3 DUP6 ADD PUSH2 0xF11 JUMP JUMPDEST PUSH2 0x160 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0xC7E DUP3 CALLDATALOAD PUSH2 0x19F2 JUMP JUMPDEST PUSH1 0x0 PUSH2 0xC7E DUP3 MLOAD PUSH2 0x1A1A JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x1125 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1131 DUP5 DUP5 PUSH2 0xD42 JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x114C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1158 DUP6 DUP6 PUSH2 0xD36 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 DUP4 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x1175 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1181 DUP6 DUP3 DUP7 ADD PUSH2 0xDCD JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x119E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x11AA DUP6 DUP6 PUSH2 0xD36 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 DUP4 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x11C7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1181 DUP6 DUP3 DUP7 ADD PUSH2 0xF11 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x11E6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x11F2 DUP6 DUP6 PUSH2 0xD36 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 PUSH2 0x1181 DUP6 DUP3 DUP7 ADD PUSH2 0x10FB JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x1215 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x122C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1131 DUP5 DUP3 DUP6 ADD PUSH2 0xE2A JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x124B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x1262 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x126E DUP6 DUP3 DUP7 ADD PUSH2 0xE9C JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 DUP4 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x128B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1181 DUP6 DUP3 DUP7 ADD PUSH2 0xD4E JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x12A9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1131 DUP5 DUP5 PUSH2 0xEF9 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x12C7 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1131 DUP5 DUP5 PUSH2 0xF57 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x12E6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP3 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x12FD JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1309 DUP6 DUP3 DUP7 ADD PUSH2 0xFB2 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 PUSH2 0x1181 DUP6 DUP3 DUP7 ADD PUSH2 0xD36 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x132C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x1131 DUP5 DUP5 PUSH2 0xF05 JUMP JUMPDEST PUSH2 0x1341 DUP2 PUSH2 0x19D9 JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x1352 DUP3 PUSH2 0x19D5 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH2 0x1364 DUP4 PUSH2 0x19CF JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x1394 JUMPI PUSH2 0x137A DUP7 DUP4 MLOAD PUSH2 0x1619 JUMP JUMPDEST PUSH2 0x1383 DUP3 PUSH2 0x19CF JUMP JUMPDEST PUSH1 0x60 SWAP7 SWAP1 SWAP7 ADD SWAP6 SWAP2 POP PUSH1 0x1 ADD PUSH2 0x1367 JUMP JUMPDEST POP SWAP4 SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x13A9 DUP3 PUSH2 0x19D5 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP DUP4 PUSH1 0x20 DUP3 MUL DUP6 ADD PUSH2 0x13C2 DUP6 PUSH2 0x19CF JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP5 DUP2 LT ISZERO PUSH2 0x13F9 JUMPI DUP4 DUP4 SUB DUP9 MSTORE PUSH2 0x13DD DUP4 DUP4 MLOAD PUSH2 0x1656 JUMP JUMPDEST SWAP3 POP PUSH2 0x13E8 DUP3 PUSH2 0x19CF JUMP JUMPDEST PUSH1 0x20 SWAP9 SWAP1 SWAP9 ADD SWAP8 SWAP2 POP PUSH1 0x1 ADD PUSH2 0x13C5 JUMP JUMPDEST POP SWAP1 SWAP7 SWAP6 POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x1410 DUP3 PUSH2 0x19D5 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH2 0x1422 DUP4 PUSH2 0x19CF JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x1394 JUMPI PUSH2 0x1438 DUP7 DUP4 MLOAD PUSH2 0x1759 JUMP JUMPDEST PUSH2 0x1441 DUP3 PUSH2 0x19CF JUMP JUMPDEST PUSH2 0x100 SWAP7 SWAP1 SWAP7 ADD SWAP6 SWAP2 POP PUSH1 0x1 ADD PUSH2 0x1425 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x145E DUP3 PUSH2 0x19D5 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH1 0x20 DUP5 ADD SWAP4 POP PUSH2 0x1470 DUP4 PUSH2 0x19CF JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x1394 JUMPI PUSH2 0x1486 DUP7 DUP4 MLOAD PUSH2 0x14A0 JUMP JUMPDEST PUSH2 0x148F DUP3 PUSH2 0x19CF JUMP JUMPDEST PUSH1 0x20 SWAP7 SWAP1 SWAP7 ADD SWAP6 SWAP2 POP PUSH1 0x1 ADD PUSH2 0x1473 JUMP JUMPDEST PUSH2 0x1341 DUP2 PUSH2 0x19F2 JUMP JUMPDEST PUSH2 0x1341 DUP2 PUSH2 0x19F5 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x14BD DUP3 PUSH2 0x19D5 JUMP JUMPDEST DUP1 DUP5 MSTORE PUSH2 0x14D1 DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x1A31 JUMP JUMPDEST PUSH2 0x14DA DUP2 PUSH2 0x1A5D JUMP JUMPDEST SWAP1 SWAP4 ADD PUSH1 0x20 ADD SWAP4 SWAP3 POP POP POP 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 0x17 DUP2 MSTORE PUSH32 0x554E535550504F525445445F41535345545F50524F5859000000000000000000 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 0x25 DUP2 MSTORE PUSH32 0x475245415445525F4F525F455155414C5F544F5F345F4C454E4754485F524551 PUSH1 0x20 DUP3 ADD MSTORE PUSH32 0x5549524544000000000000000000000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST DUP1 MLOAD PUSH1 0x60 DUP4 ADD SWAP1 PUSH2 0x162A DUP5 DUP3 PUSH2 0x17F0 JUMP JUMPDEST POP PUSH1 0x20 DUP3 ADD MLOAD PUSH2 0x163D PUSH1 0x20 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0x40 DUP3 ADD MLOAD PUSH2 0x1650 PUSH1 0x40 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP POP POP POP JUMP JUMPDEST DUP1 MLOAD PUSH1 0x0 SWAP1 PUSH2 0x180 DUP5 ADD SWAP1 PUSH2 0x166B DUP6 DUP3 PUSH2 0x1338 JUMP JUMPDEST POP PUSH1 0x20 DUP4 ADD MLOAD PUSH2 0x167E PUSH1 0x20 DUP7 ADD DUP3 PUSH2 0x1338 JUMP JUMPDEST POP PUSH1 0x40 DUP4 ADD MLOAD PUSH2 0x1691 PUSH1 0x40 DUP7 ADD DUP3 PUSH2 0x1338 JUMP JUMPDEST POP PUSH1 0x60 DUP4 ADD MLOAD PUSH2 0x16A4 PUSH1 0x60 DUP7 ADD DUP3 PUSH2 0x1338 JUMP JUMPDEST POP PUSH1 0x80 DUP4 ADD MLOAD PUSH2 0x16B7 PUSH1 0x80 DUP7 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0xA0 DUP4 ADD MLOAD PUSH2 0x16CA PUSH1 0xA0 DUP7 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0xC0 DUP4 ADD MLOAD PUSH2 0x16DD PUSH1 0xC0 DUP7 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0xE0 DUP4 ADD MLOAD PUSH2 0x16F0 PUSH1 0xE0 DUP7 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH2 0x100 DUP4 ADD MLOAD PUSH2 0x1705 PUSH2 0x100 DUP7 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH2 0x120 DUP4 ADD MLOAD PUSH2 0x171A PUSH2 0x120 DUP7 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH2 0x140 DUP4 ADD MLOAD DUP5 DUP3 SUB PUSH2 0x140 DUP7 ADD MSTORE PUSH2 0x1734 DUP3 DUP3 PUSH2 0x14B2 JUMP JUMPDEST SWAP2 POP POP PUSH2 0x160 DUP4 ADD MLOAD DUP5 DUP3 SUB PUSH2 0x160 DUP7 ADD MSTORE PUSH2 0x1750 DUP3 DUP3 PUSH2 0x14B2 JUMP JUMPDEST SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST DUP1 MLOAD PUSH2 0x100 DUP4 ADD SWAP1 PUSH2 0x176B DUP5 DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0x20 DUP3 ADD MLOAD PUSH2 0x177E PUSH1 0x20 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0x40 DUP3 ADD MLOAD PUSH2 0x1791 PUSH1 0x40 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0x60 DUP3 ADD MLOAD PUSH2 0x17A4 PUSH1 0x60 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0x80 DUP3 ADD MLOAD PUSH2 0x17B7 PUSH1 0x80 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0xA0 DUP3 ADD MLOAD PUSH2 0x17CA PUSH1 0xA0 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0xC0 DUP3 ADD MLOAD PUSH2 0x17DD PUSH1 0xC0 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST POP PUSH1 0xE0 DUP3 ADD MLOAD PUSH2 0x1650 PUSH1 0xE0 DUP6 ADD DUP3 PUSH2 0x14A0 JUMP JUMPDEST PUSH2 0x1341 DUP2 PUSH2 0x1A1A JUMP JUMPDEST PUSH1 0x20 DUP2 ADD PUSH2 0x9A3 DUP3 DUP5 PUSH2 0x1338 JUMP JUMPDEST PUSH1 0x40 DUP2 ADD PUSH2 0x1815 DUP3 DUP6 PUSH2 0x1338 JUMP JUMPDEST PUSH2 0xC7E PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x1338 JUMP JUMPDEST PUSH1 0x40 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x1833 DUP2 DUP6 PUSH2 0x1347 JUMP JUMPDEST SWAP1 POP DUP2 DUP2 SUB PUSH1 0x20 DUP4 ADD MSTORE PUSH2 0x1131 DUP2 DUP5 PUSH2 0x1405 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0xC7E DUP2 DUP5 PUSH2 0x139E JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0xC7E DUP2 DUP5 PUSH2 0x1405 JUMP JUMPDEST PUSH1 0x40 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x187A DUP2 DUP6 PUSH2 0x1453 JUMP JUMPDEST SWAP1 POP DUP2 DUP2 SUB PUSH1 0x20 DUP4 ADD MSTORE PUSH2 0x1131 DUP2 DUP5 PUSH2 0x1453 JUMP JUMPDEST PUSH1 0x20 DUP2 ADD PUSH2 0x9A3 DUP3 DUP5 PUSH2 0x14A9 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x9A3 DUP2 PUSH2 0x14E7 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x9A3 DUP2 PUSH2 0x153D JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x9A3 DUP2 PUSH2 0x156D JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0x9A3 DUP2 PUSH2 0x15C3 JUMP JUMPDEST PUSH2 0x160 DUP2 ADD PUSH2 0x18EB DUP3 DUP6 PUSH2 0x1619 JUMP JUMPDEST PUSH2 0xC7E PUSH1 0x60 DUP4 ADD DUP5 PUSH2 0x1759 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE DUP2 ADD PUSH2 0xC7E DUP2 DUP5 PUSH2 0x1656 JUMP JUMPDEST PUSH2 0x100 DUP2 ADD PUSH2 0x9A3 DUP3 DUP5 PUSH2 0x1759 JUMP JUMPDEST PUSH1 0x20 DUP2 ADD PUSH2 0x9A3 DUP3 DUP5 PUSH2 0x14A0 JUMP JUMPDEST PUSH1 0x40 DUP2 ADD PUSH2 0x1934 DUP3 DUP6 PUSH2 0x14A0 JUMP JUMPDEST PUSH2 0xC7E PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x14A0 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x1960 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT ISZERO PUSH2 0x197F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 SWAP1 DUP2 MUL ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT ISZERO PUSH2 0x19A0 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x20 PUSH1 0x1F SWAP2 SWAP1 SWAP2 ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND ADD SWAP1 JUMP JUMPDEST PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST MLOAD SWAP1 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH32 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 AND SWAP1 JUMP JUMPDEST PUSH1 0xFF AND 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 0x1A4C JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x1A34 JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x1650 JUMPI POP POP PUSH1 0x0 SWAP2 ADD MSTORE JUMP JUMPDEST PUSH1 0x1F ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND SWAP1 JUMP STOP LOG2 PUSH6 0x627A7A723058 KECCAK256 0xd3 0xd4 SWAP6 0xbc 0x28 PUSH23 0x63ED8CB2A513CFAD47804FFA6E4AD0CFA6D0D0EADF1F90 PUSH21 0x83586C6578706572696D656E74616CF50037000000 ", + "sourceMap": "898:8536:11:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2336:352;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;2336:352:11;;;;;;;;;;;;;;;;;;;;;;;;;;5614:1359;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;5614:1359:11;;;;;;;;;;;;;;;;;;3018:384;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;3018:384:11;;;;;;;;;;;;;;;;;;4716:452;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;4716:452:11;;;;;;;;;;;;;;;;;8218:1214;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;8218:1214:11;;;;;;;;;;;;;;;;;7416:517;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;7416:517:11;;;;;;;;;;;;;;;;;;3661:739;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;3661:739:11;;;;;;;;;;;;;;;;;2336:352;2463:35;;:::i;:::-;2500:28;;:::i;:::-;2556:8;;:28;;;;;:8;;;;;:21;;:28;;2578:5;;2556:28;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2556:28:11;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2556:28:11;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;2556:28:11;;;;;;;;;2544:40;;2607:34;2621:5;2628:12;2607:13;:34::i;:::-;2594:47;-1:-1:-1;2336:352:11;;;;;:::o;5614:1359::-;5731:15;;;;;;;;5803:23;:9;5731:15;5803:23;:20;:23;:::i;:::-;5781:45;-1:-1:-1;5852:25:11;:9;5874:2;5852:25;:21;:25;:::i;:::-;5908:8;;:36;;;;;5836:41;;-1:-1:-1;5908:8:11;;;:22;;:36;;5931:12;;5908:36;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5908:36:11;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5908:36:11;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;5908:36:11;;;;;;;;;977:32;;;;;;;;;;;;;;;;5887:57;;-1:-1:-1;5959:29:11;;;;;;;5955:975;;;6043:36;;;;;:28;;;;;;:36;;6072:6;;6043:36;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;6043:36:11;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6043:36:11;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;6043:36:11;;;;;;;;;6137:48;;;;;6033:46;;-1:-1:-1;6137:28:11;;;;;;:48;;6166:6;;6174:10;;6137:48;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;6137:48:11;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6137:48:11;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;6137:48:11;;;;;;;;;6125:60;;5955:975;;;1065:41;;;;;;;;;;;;;;;;6206:30;;;;;;;6202:728;;;6270:25;:9;6292:2;6270:25;:21;:25;:::i;:::-;6252:43;;6364:35;6384:5;6391:7;6364:19;:35::i;:::-;6348:51;;6496:5;6486:15;;:6;:15;;;:23;;6508:1;6486:23;;;6504:1;6486:23;6476:33;;;;6620:5;6607:36;;;6644:6;6652:10;6607:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;6607:56:11;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6607:56:11;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;6607:56:11;;;;;;;;;:114;;;;6711:10;6667:54;;6680:5;6667:31;;;6699:7;6667:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;6667:40:11;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6667:40:11;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;6667:40:11;;;;;;;;;:54;;;6607:114;6589:132;;6837:10;:18;;6854:1;6837:18;;;6850:1;6837:18;6825:30;;;;6202:728;;;6886:33;;;;;;;;;;;;;;;;;;;6202:728;5614:1359;;;;;;;;;;;:::o;3018:384::-;3261:8;;:30;;;;;3161:38;;;;3261:8;;;;;:22;;:30;;3284:6;;3261:30;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3261:30:11;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3261:30:11;;;;;;39:16:-1;36:1;17:17;2:54;101:4;3261:30:11;80:15:-1;;;97:9;76:31;65:43;;120:4;113:20;3261:30:11;;;;;;;;;3248:43;;3315:38;3330:6;3338:14;4716:452;4850:12;4885:20;4931:31;5010:9;4908:6;:13;4885:36;;4982:12;4965:30;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;4931:64;;5022:1;5010:13;;5005:129;5025:17;;;5005:129;;5080:43;5094:6;5101:1;5094:9;;;;;;;;;;;;;;;;;;5105:14;5120:1;5105:17;;;;;;;;;;;;;;;;;;5080:13;:43::i;:::-;5063:11;5075:1;5063:14;;;;;;;;;;;;;;;;;;:60;5044:3;;5005:129;;;5150:11;5143:18;;4716:452;;;;;;;;:::o;8218:1214::-;8324:13;8437:2;8431:9;8534:66;8525:7;8518:83;8638:7;8634:1;8625:7;8621:15;8614:32;9060:2;9007:7;8950:2;8903:7;8854:5;8809:3;8781:332;9240:7;9237:2;;;9281:7;9275:14;9266:23;;9237:2;-1:-1:-1;;8218:1214:11;;;;;:::o;7416:517::-;7537:9;7555;7587:14;7630:25;7689:27;7755:9;7604;:16;7587:33;;7672:6;7658:21;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;7658:21:11;;7630:49;;7733:6;7719:21;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;7719:21:11;;7689:51;;7767:1;7755:13;;7750:138;7770:11;;;7750:138;;7833:44;7856:6;7864:9;7874:1;7864:12;;;;;;;;;;;;;;;;;;7833:22;:44::i;:::-;7803:8;7812:1;7803:11;;;;;;;;;;;;;;;;;7816:10;7827:1;7816:13;;;;;;;;;;;;;;;;;;7802:75;;;;;7783:3;;7750:138;;;-1:-1:-1;7905:8:11;;7915:10;;-1:-1:-1;7416:517:11;-1:-1:-1;;;;7416:517:11:o;3661:739::-;3780:28;;:::i;:::-;4076:25;3879:64;3902:5;:18;;;3922:5;:20;;;3879:22;:64::i;:::-;3850:25;;;3824:119;;;4045:20;;;;4008:58;;4031:12;;4008:22;:58::i;:::-;3979:25;;;3953:113;3954:23;;;;3953:113;;;;4104:14;4076:42;;;;-1:-1:-1;4076:42:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4104:14;4076:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4189:56;4212:5;:18;;;4232:12;4189:22;:56::i;:::-;4157:28;;;4128:117;4129:26;;;4128:117;4316:50;4339:12;4353;4316:22;:50::i;:::-;4284:28;;;4255:111;4256:26;;;4255:111;3661:739;;;;;:::o;15559:559:53:-;15679:13;15741:5;15749:1;15741:9;15729:1;:8;:21;;15708:105;;;;;;;;;;;;;;;;-1:-1:-1;;15869:2:53;15862:10;15856:17;16012:66;16000:79;;15559:559::o;10259:886::-;10380:14;10443:5;10451:2;10443:10;10431:1;:8;:22;;10410:135;;;;;;;;;;;;;;;;-1:-1:-1;11047:13:53;10792:2;11047:13;11041:20;11063:42;11037:69;;10259:886::o;14699:195::-;14820:14;14865:21;14877:1;14880:5;14865:11;:21::i;:::-;14857:30;14699:195;-1:-1:-1;;;14699:195:53:o;13281:490::-;13402:14;13465:5;13473:2;13465:10;13453:1;:8;:22;;13432:107;;;;;;;;;;;;;;;;-1:-1:-1;13718:13:53;13620:2;13718:13;13712:20;;13281:490::o;898:8536:11:-;;;;;;;;;-1:-1:-1;898:8536:11;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;5:118:-1:-;;72:46;110:6;97:20;72:46;;130:122;;208:39;239:6;233:13;208:39;;277:707;;387:4;375:17;;371:27;-1:-1;361:2;;412:1;409;402:12;361:2;449:6;436:20;471:80;486:64;543:6;486:64;;;471:80;;;462:89;;568:5;593:6;586:5;579:21;623:4;615:6;611:17;601:27;;645:4;640:3;636:14;629:21;;698:6;745:3;737:4;729:6;725:17;720:3;716:27;713:36;710:2;;;762:1;759;752:12;710:2;787:1;772:206;797:6;794:1;791:13;772:206;;;855:3;877:37;910:3;898:10;877:37;;;865:50;;-1:-1;938:4;929:14;;;;957;;;;;819:1;812:9;772:206;;;776:14;354:630;;;;;;;;1008:693;;1123:4;1111:17;;1107:27;-1:-1;1097:2;;1148:1;1145;1138:12;1097:2;1185:6;1172:20;1207:85;1222:69;1284:6;1222:69;;1207:85;1320:21;;;1364:4;1352:17;;;;1198:94;;-1:-1;1377:14;;1352:17;1472:1;1457:238;1482:6;1479:1;1476:13;1457:238;;;1565:3;1552:17;1544:6;1540:30;1589:42;1627:3;1615:10;1589:42;;;1577:55;;-1:-1;1655:4;1646:14;;;;1674;;;;;1504:1;1497:9;1457:238;;1745:791;;1889:4;1877:17;;1873:27;-1:-1;1863:2;;1914:1;1911;1904:12;1863:2;1944:6;1938:13;1966:103;1981:87;2061:6;1981:87;;1966:103;1957:112;;2086:5;2111:6;2104:5;2097:21;2141:4;2133:6;2129:17;2119:27;;2163:4;2158:3;2154:14;2147:21;;2216:6;2263:3;2255:4;2247:6;2243:17;2238:3;2234:27;2231:36;2228:2;;;2280:1;2277;2270:12;2228:2;2305:1;2290:240;2315:6;2312:1;2309:13;2290:240;;;2373:3;2395:71;2462:3;2450:10;2395:71;;;2383:84;;-1:-1;2490:4;2481:14;;;;2518:4;2509:14;;;;;2337:1;2330:9;2290:240;;2576:735;;2705:4;2693:17;;2689:27;-1:-1;2679:2;;2730:1;2727;2720:12;2679:2;2767:6;2754:20;2789:99;2804:83;2880:6;2804:83;;2789:99;2916:21;;;2960:4;2948:17;;;;2780:108;;-1:-1;2973:14;;2948:17;3068:1;3053:252;3078:6;3075:1;3072:13;3053:252;;;3161:3;3148:17;3140:6;3136:30;3185:56;3237:3;3225:10;3185:56;;;3173:69;;-1:-1;3265:4;3256:14;;;;3284;;;;;3100:1;3093:9;3053:252;;3319:116;;3394:36;3422:6;3416:13;3394:36;;3442:122;;3520:39;3551:6;3545:13;3520:39;;3572:432;;3662:4;3650:17;;3646:27;-1:-1;3636:2;;3687:1;3684;3677:12;3636:2;3724:6;3711:20;3746:60;3761:44;3798:6;3761:44;;3746:60;3737:69;;3826:6;3819:5;3812:21;3862:4;3854:6;3850:17;3895:4;3888:5;3884:16;3930:3;3921:6;3916:3;3912:16;3909:25;3906:2;;;3947:1;3944;3937:12;3906:2;3957:41;3991:6;3986:3;3981;3957:41;;4493:685;;4616:4;4604:9;4599:3;4595:19;4591:30;4588:2;;;4634:1;4631;4624:12;4588:2;4652:20;4667:4;4652:20;;;4643:29;-1:-1;4729:1;4760:58;4814:3;4794:9;4760:58;;;4736:83;;-1:-1;4885:2;4918:60;4974:3;4950:22;;;4918:60;;;4911:4;4904:5;4900:16;4893:86;4840:150;5063:2;5096:60;5152:3;5143:6;5132:9;5128:22;5096:60;;;5089:4;5082:5;5078:16;5071:86;5000:168;4582:596;;;;;5941:2205;;6049:5;6037:9;6032:3;6028:19;6024:31;6021:2;;;6068:1;6065;6058:12;6021:2;6086:21;6101:5;6086:21;;;6077:30;-1:-1;6165:1;6196:49;6241:3;6221:9;6196:49;;;6172:74;;-1:-1;6315:2;6348:49;6393:3;6369:22;;;6348:49;;;6341:4;6334:5;6330:16;6323:75;6267:142;6474:2;6507:49;6552:3;6543:6;6532:9;6528:22;6507:49;;;6500:4;6493:5;6489:16;6482:75;6419:149;6627:2;6660:49;6705:3;6696:6;6685:9;6681:22;6660:49;;;6653:4;6646:5;6642:16;6635:75;6578:143;6783:3;6817:49;6862:3;6853:6;6842:9;6838:22;6817:49;;;6810:4;6803:5;6799:16;6792:75;6731:147;6940:3;6974:49;7019:3;7010:6;6999:9;6995:22;6974:49;;;6967:4;6960:5;6956:16;6949:75;6888:147;7089:3;7123:49;7168:3;7159:6;7148:9;7144:22;7123:49;;;7116:4;7109:5;7105:16;7098:75;7045:139;7238:3;7272:49;7317:3;7308:6;7297:9;7293:22;7272:49;;;7265:4;7258:5;7254:16;7247:75;7194:139;7400:3;7435:49;7480:3;7471:6;7460:9;7456:22;7435:49;;;7427:5;7420;7416:17;7409:76;7343:153;7546:3;7581:49;7626:3;7617:6;7606:9;7602:22;7581:49;;;7573:5;7566;7562:17;7555:76;7506:136;7730:3;7719:9;7715:19;7702:33;7755:18;7747:6;7744:30;7741:2;;;7787:1;7784;7777:12;7741:2;7823:54;7873:3;7864:6;7853:9;7849:22;7823:54;;;7815:5;7808;7804:17;7797:81;7652:237;7977:3;7966:9;7962:19;7949:33;8002:18;7994:6;7991:30;7988:2;;;8034:1;8031;8024:12;7988:2;8070:54;8120:3;8111:6;8100:9;8096:22;8070:54;;;8062:5;8055;8051:17;8044:81;7899:237;6015:2131;;;;;10397:118;;10464:46;10502:6;10489:20;10464:46;;10651:118;;10727:37;10756:6;10750:13;10727:37;;10776:263;;10891:2;10879:9;10870:7;10866:23;10862:32;10859:2;;;10907:1;10904;10897:12;10859:2;10942:1;10959:64;11015:7;10995:9;10959:64;;;10949:74;10853:186;-1:-1;;;;10853:186;11046:512;;;11197:2;11185:9;11176:7;11172:23;11168:32;11165:2;;;11213:1;11210;11203:12;11165:2;11248:1;11265:53;11310:7;11290:9;11265:53;;;11255:63;;11227:97;11383:2;11372:9;11368:18;11355:32;11407:18;11399:6;11396:30;11393:2;;;11439:1;11436;11429:12;11393:2;11459:83;11534:7;11525:6;11514:9;11510:22;11459:83;;;11449:93;;11334:214;11159:399;;;;;;11565:470;;;11695:2;11683:9;11674:7;11670:23;11666:32;11663:2;;;11711:1;11708;11701:12;11663:2;11746:1;11763:53;11808:7;11788:9;11763:53;;;11753:63;;11725:97;11881:2;11870:9;11866:18;11853:32;11905:18;11897:6;11894:30;11891:2;;;11937:1;11934;11927:12;11891:2;11957:62;12011:7;12002:6;11991:9;11987:22;11957:62;;12042:366;;;12163:2;12151:9;12142:7;12138:23;12134:32;12131:2;;;12179:1;12176;12169:12;12131:2;12214:1;12231:53;12276:7;12256:9;12231:53;;;12221:63;;12193:97;12321:2;12339:53;12384:7;12375:6;12364:9;12360:22;12339:53;;12415:438;;12578:2;12566:9;12557:7;12553:23;12549:32;12546:2;;;12594:1;12591;12584:12;12546:2;12629:24;;12673:18;12662:30;;12659:2;;;12705:1;12702;12695:12;12659:2;12725:112;12829:7;12820:6;12809:9;12805:22;12725:112;;12860:676;;;13050:2;13038:9;13029:7;13025:23;13021:32;13018:2;;;13066:1;13063;13056:12;13018:2;13101:31;;13152:18;13141:30;;13138:2;;;13184:1;13181;13174:12;13138:2;13204:97;13293:7;13284:6;13273:9;13269:22;13204:97;;;13194:107;;13080:227;13366:2;13355:9;13351:18;13338:32;13390:18;13382:6;13379:30;13376:2;;;13422:1;13419;13412:12;13376:2;13442:78;13512:7;13503:6;13492:9;13488:22;13442:78;;13543:257;;13655:2;13643:9;13634:7;13630:23;13626:32;13623:2;;;13671:1;13668;13661:12;13623:2;13706:1;13723:61;13776:7;13756:9;13723:61;;13807:317;;13949:2;13937:9;13928:7;13924:23;13920:32;13917:2;;;13965:1;13962;13955:12;13917:2;14000:1;14017:91;14100:7;14080:9;14017:91;;14131:498;;;14275:2;14263:9;14254:7;14250:23;14246:32;14243:2;;;14291:1;14288;14281:12;14243:2;14326:31;;14377:18;14366:30;;14363:2;;;14409:1;14406;14399:12;14363:2;14429:76;14497:7;14488:6;14477:9;14473:22;14429:76;;;14419:86;;14305:206;14542:2;14560:53;14605:7;14596:6;14585:9;14581:22;14560:53;;14636:263;;14751:2;14739:9;14730:7;14726:23;14722:32;14719:2;;;14767:1;14764;14757:12;14719:2;14802:1;14819:64;14875:7;14855:9;14819:64;;14906:110;14979:31;15004:5;14979:31;;;14974:3;14967:44;14961:55;;;15090:755;;15271:77;15342:5;15271:77;;;15366:6;15361:3;15354:19;15390:4;15385:3;15381:14;15374:21;;15435:79;15508:5;15435:79;;;15535:1;15520:303;15545:6;15542:1;15539:13;15520:303;;;15585:103;15684:3;15675:6;15669:13;15585:103;;;15705:83;15781:6;15705:83;;;15811:4;15802:14;;;;;15695:93;-1:-1;15567:1;15560:9;15520:303;;;-1:-1;15836:3;;15250:595;-1:-1;;;;15250:595;15912:864;;16085:73;16152:5;16085:73;;;16176:6;16171:3;16164:19;16200:4;16195:3;16191:14;16184:21;;16248:3;16290:4;16282:6;16278:17;16273:3;16269:27;16316:75;16385:5;16316:75;;;16412:1;16397:340;16422:6;16419:1;16416:13;16397:340;;;16484:9;16478:4;16474:20;16469:3;16462:33;16510:96;16601:4;16592:6;16586:13;16510:96;;;16502:104;;16623:79;16695:6;16623:79;;;16725:4;16716:14;;;;;16613:89;-1:-1;16444:1;16437:9;16397:340;;;-1:-1;16750:4;;16064:712;-1:-1;;;;;;16064:712;16865:749;;17044:76;17114:5;17044:76;;;17138:6;17133:3;17126:19;17162:4;17157:3;17153:14;17146:21;;17207:78;17279:5;17207:78;;;17306:1;17291:301;17316:6;17313:1;17310:13;17291:301;;;17356:101;17453:3;17444:6;17438:13;17356:101;;;17474:82;17549:6;17474:82;;;17579:5;17570:15;;;;;17464:92;-1:-1;17338:1;17331:9;17291:301;;17653:590;;17788:54;17836:5;17788:54;;;17860:6;17855:3;17848:19;17884:4;17879:3;17875:14;17868:21;;17929:56;17979:5;17929:56;;;18006:1;17991:230;18016:6;18013:1;18010:13;17991:230;;;18056:53;18105:3;18096:6;18090:13;18056:53;;;18126:60;18179:6;18126:60;;;18209:4;18200:14;;;;;18116:70;-1:-1;18038:1;18031:9;17991:230;;18251:110;18324:31;18349:5;18324:31;;18368:107;18439:30;18463:5;18439:30;;18482:289;;18578:34;18606:5;18578:34;;;18629:6;18624:3;18617:19;18641:63;18697:6;18690:4;18685:3;18681:14;18674:4;18667:5;18663:16;18641:63;;;18736:29;18758:6;18736:29;;;18716:50;;;18729:4;18716:50;;18558:213;-1:-1;;;18558:213;18779:397;18934:2;18922:15;;18971:66;18966:2;18957:12;;18950:88;19072:66;19067:2;19058:12;;19051:88;19167:2;19158:12;;18915:261;19185:296;19340:2;19328:15;;19377:66;19372:2;19363:12;;19356:88;19472:2;19463:12;;19321:160;19490:397;19645:2;19633:15;;19682:66;19677:2;19668:12;;19661:88;19783:66;19778:2;19769:12;;19762:88;19878:2;19869:12;;19626:261;19896:397;20051:2;20039:15;;20088:66;20083:2;20074:12;;20067:88;20189:66;20184:2;20175:12;;20168:88;20284:2;20275:12;;20032:261;20362:695;20575:22;;20499:4;20490:14;;;20609:57;20494:3;20575:22;20609:57;;;20519:159;20759:4;20752:5;20748:16;20742:23;20777:62;20833:4;20828:3;20824:14;20811:11;20777:62;;;20688:163;20950:4;20943:5;20939:16;20933:23;20968:62;21024:4;21019:3;21015:14;21002:11;20968:62;;;20861:181;20472:585;;;;21876:2419;22091:22;;21876:2419;;22013:5;22004:15;;;22125:61;22008:3;22091:22;22125:61;;;22034:164;22282:4;22275:5;22271:16;22265:23;22300:62;22356:4;22351:3;22347:14;22334:11;22300:62;;;22208:166;22465:4;22458:5;22454:16;22448:23;22483:62;22539:4;22534:3;22530:14;22517:11;22483:62;;;22384:173;22642:4;22635:5;22631:16;22625:23;22660:62;22716:4;22711:3;22707:14;22694:11;22660:62;;;22567:167;22822:4;22815:5;22811:16;22805:23;22840:62;22896:4;22891:3;22887:14;22874:11;22840:62;;;22744:170;23002:4;22995:5;22991:16;22985:23;23020:62;23076:4;23071:3;23067:14;23054:11;23020:62;;;22924:170;23174:4;23167:5;23163:16;23157:23;23192:62;23248:4;23243:3;23239:14;23226:11;23192:62;;;23104:162;23346:4;23339:5;23335:16;23329:23;23364:62;23420:4;23415:3;23411:14;23398:11;23364:62;;;23276:162;23531:5;23524;23520:17;23514:24;23550:63;23606:5;23601:3;23597:15;23584:11;23550:63;;;23448:177;23701:5;23694;23690:17;23684:24;23720:63;23776:5;23771:3;23767:15;23754:11;23720:63;;;23635:160;23881:5;23874;23870:17;23864:24;23934:3;23928:4;23924:14;23916:5;23911:3;23907:15;23900:39;23954:66;24015:4;24002:11;23954:66;;;23946:74;;23805:227;24118:5;24111;24107:17;24101:24;24171:3;24165:4;24161:14;24153:5;24148:3;24144:15;24137:39;24191:66;24252:4;24239:11;24191:66;;;24183:74;21986:2309;-1:-1;;;;;21986:2309;26852:1587;27065:22;;26987:5;26978:15;;;27099:61;26982:3;27065:22;27099:61;;;27008:164;27258:4;27251:5;27247:16;27241:23;27276:62;27332:4;27327:3;27323:14;27310:11;27276:62;;;27182:168;27434:4;27427:5;27423:16;27417:23;27452:62;27508:4;27503:3;27499:14;27486:11;27452:62;;;27360:166;27612:4;27605:5;27601:16;27595:23;27630:62;27686:4;27681:3;27677:14;27664:11;27630:62;;;27536:168;27791:4;27784:5;27780:16;27774:23;27809:62;27865:4;27860:3;27856:14;27843:11;27809:62;;;27714:169;27972:4;27965:5;27961:16;27955:23;27990:62;28046:4;28041:3;28037:14;28024:11;27990:62;;;27893:171;28151:4;28144:5;28140:16;28134:23;28169:62;28225:4;28220:3;28216:14;28203:11;28169:62;;;28074:169;28332:4;28325:5;28321:16;28315:23;28350:62;28406:4;28401:3;28397:14;28384:11;28350:62;;30228:104;30297:29;30320:5;30297:29;;30339:193;30447:2;30432:18;;30461:61;30436:9;30495:6;30461:61;;30539:294;30675:2;30660:18;;30689:61;30664:9;30723:6;30689:61;;;30761:62;30819:2;30808:9;30804:18;30795:6;30761:62;;30840:770;31166:2;31180:47;;;31151:18;;31241:144;31151:18;31371:6;31241:144;;;31233:152;;31433:9;31427:4;31423:20;31418:2;31407:9;31403:18;31396:48;31458:142;31595:4;31586:6;31458:142;;31617:417;31813:2;31827:47;;;31798:18;;31888:136;31798:18;32010:6;31888:136;;32041:429;32243:2;32257:47;;;32228:18;;32318:142;32228:18;32446:6;32318:142;;32477:590;32713:2;32727:47;;;32698:18;;32788:98;32698:18;32872:6;32788:98;;;32780:106;;32934:9;32928:4;32924:20;32919:2;32908:9;32904:18;32897:48;32959:98;33052:4;33043:6;32959:98;;33074:189;33180:2;33165:18;;33194:59;33169:9;33226:6;33194:59;;33270:387;33451:2;33465:47;;;33436:18;;33526:121;33436:18;33526:121;;33664:387;33845:2;33859:47;;;33830:18;;33920:121;33830:18;33920:121;;34058:387;34239:2;34253:47;;;34224:18;;34314:121;34224:18;34314:121;;34452:387;34633:2;34647:47;;;34618:18;;34708:121;34618:18;34708:121;;34846:507;35088:3;35073:19;;35103:115;35077:9;35191:6;35103:115;;;35229:114;35339:2;35328:9;35324:18;35315:6;35229:114;;35360:333;35514:2;35528:47;;;35499:18;;35589:94;35499:18;35669:6;35589:94;;35700:298;35860:3;35845:19;;35875:113;35849:9;35961:6;35875:113;;36005:193;36113:2;36098:18;;36127:61;36102:9;36161:6;36127:61;;36205:294;36341:2;36326:18;;36355:61;36330:9;36389:6;36355:61;;;36427:62;36485:2;36474:9;36470:18;36461:6;36427:62;;36506:256;36568:2;36562:9;36594:17;;;36669:18;36654:34;;36690:22;;;36651:62;36648:2;;;36726:1;36723;36716:12;36648:2;36742;36735:22;36546:216;;-1:-1;36546:216;36769:258;;36928:18;36920:6;36917:30;36914:2;;;36960:1;36957;36950:12;36914:2;-1:-1;36989:4;36977:17;;;37007:15;;36851:176;37876:254;;38015:18;38007:6;38004:30;38001:2;;;38047:1;38044;38037:12;38001:2;-1:-1;38120:4;38091;38068:17;;;;38087:9;38064:33;38110:15;;37938:192;38404:144;38536:4;38524:17;;38505:43;38994:130;39107:12;;39091:33;40196:128;40276:42;40265:54;;40248:76;40331:79;40400:5;40383:27;40417:151;40496:66;40485:78;;40468:100;40661:88;40739:4;40728:16;;40711:38;40891:92;40964:13;40957:21;;40940:43;41258:145;41339:6;41334:3;41329;41316:30;-1:-1;41395:1;41377:16;;41370:27;41309:94;41412:268;41477:1;41484:101;41498:6;41495:1;41492:13;41484:101;;;41565:11;;;41559:18;41546:11;;;41539:39;41520:2;41513:10;41484:101;;;41600:6;41597:1;41594:13;41591:2;;;-1:-1;;41665:1;41647:16;;41640:27;41461:219;41688:97;41776:2;41756:14;41772:7;41752:28;;41736:49" } } }, @@ -585,149 +612,171 @@ "2.0.0/extensions/OrderValidator/OrderValidator.sol": { "id": 11 }, - "2.0.0/protocol/AssetProxy/interfaces/IAssetProxy.sol": { + "2.0.0/protocol/AssetProxy/ERC20Proxy.sol": { "id": 12 }, - "2.0.0/protocol/AssetProxy/interfaces/IAuthorizable.sol": { + "2.0.0/protocol/AssetProxy/ERC721Proxy.sol": { "id": 13 }, - "2.0.0/protocol/Exchange/Exchange.sol": { + "2.0.0/protocol/AssetProxy/MixinAuthorizable.sol": { "id": 14 }, - "2.0.0/protocol/Exchange/MixinAssetProxyDispatcher.sol": { + "2.0.0/protocol/AssetProxy/interfaces/IAssetProxy.sol": { "id": 15 }, - "2.0.0/protocol/Exchange/MixinExchangeCore.sol": { + "2.0.0/protocol/AssetProxy/interfaces/IAuthorizable.sol": { "id": 16 }, - "2.0.0/protocol/Exchange/MixinMatchOrders.sol": { + "2.0.0/protocol/AssetProxy/mixins/MAuthorizable.sol": { "id": 17 }, - "2.0.0/protocol/Exchange/MixinSignatureValidator.sol": { + "2.0.0/protocol/Exchange/Exchange.sol": { "id": 18 }, - "2.0.0/protocol/Exchange/MixinTransactions.sol": { + "2.0.0/protocol/Exchange/MixinAssetProxyDispatcher.sol": { "id": 19 }, - "2.0.0/protocol/Exchange/MixinWrapperFunctions.sol": { + "2.0.0/protocol/Exchange/MixinExchangeCore.sol": { "id": 20 }, - "2.0.0/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol": { + "2.0.0/protocol/Exchange/MixinMatchOrders.sol": { "id": 21 }, - "2.0.0/protocol/Exchange/interfaces/IExchange.sol": { + "2.0.0/protocol/Exchange/MixinSignatureValidator.sol": { "id": 22 }, - "2.0.0/protocol/Exchange/interfaces/IExchangeCore.sol": { + "2.0.0/protocol/Exchange/MixinTransactions.sol": { "id": 23 }, - "2.0.0/protocol/Exchange/interfaces/IMatchOrders.sol": { + "2.0.0/protocol/Exchange/MixinWrapperFunctions.sol": { "id": 24 }, - "2.0.0/protocol/Exchange/interfaces/ISignatureValidator.sol": { + "2.0.0/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol": { "id": 25 }, - "2.0.0/protocol/Exchange/interfaces/ITransactions.sol": { + "2.0.0/protocol/Exchange/interfaces/IExchange.sol": { "id": 26 }, - "2.0.0/protocol/Exchange/interfaces/IValidator.sol": { + "2.0.0/protocol/Exchange/interfaces/IExchangeCore.sol": { "id": 27 }, - "2.0.0/protocol/Exchange/interfaces/IWallet.sol": { + "2.0.0/protocol/Exchange/interfaces/IMatchOrders.sol": { "id": 28 }, - "2.0.0/protocol/Exchange/interfaces/IWrapperFunctions.sol": { + "2.0.0/protocol/Exchange/interfaces/ISignatureValidator.sol": { "id": 29 }, - "2.0.0/protocol/Exchange/libs/LibAbiEncoder.sol": { + "2.0.0/protocol/Exchange/interfaces/ITransactions.sol": { "id": 30 }, - "2.0.0/protocol/Exchange/libs/LibConstants.sol": { + "2.0.0/protocol/Exchange/interfaces/IValidator.sol": { "id": 31 }, - "2.0.0/protocol/Exchange/libs/LibEIP712.sol": { + "2.0.0/protocol/Exchange/interfaces/IWallet.sol": { "id": 32 }, - "2.0.0/protocol/Exchange/libs/LibExchangeErrors.sol": { + "2.0.0/protocol/Exchange/interfaces/IWrapperFunctions.sol": { "id": 33 }, - "2.0.0/protocol/Exchange/libs/LibFillResults.sol": { + "2.0.0/protocol/Exchange/libs/LibAbiEncoder.sol": { "id": 34 }, - "2.0.0/protocol/Exchange/libs/LibMath.sol": { + "2.0.0/protocol/Exchange/libs/LibConstants.sol": { "id": 35 }, - "2.0.0/protocol/Exchange/libs/LibOrder.sol": { + "2.0.0/protocol/Exchange/libs/LibEIP712.sol": { "id": 36 }, - "2.0.0/protocol/Exchange/mixins/MAssetProxyDispatcher.sol": { + "2.0.0/protocol/Exchange/libs/LibExchangeErrors.sol": { "id": 37 }, - "2.0.0/protocol/Exchange/mixins/MExchangeCore.sol": { + "2.0.0/protocol/Exchange/libs/LibFillResults.sol": { "id": 38 }, - "2.0.0/protocol/Exchange/mixins/MMatchOrders.sol": { + "2.0.0/protocol/Exchange/libs/LibMath.sol": { "id": 39 }, - "2.0.0/protocol/Exchange/mixins/MSignatureValidator.sol": { + "2.0.0/protocol/Exchange/libs/LibOrder.sol": { "id": 40 }, - "2.0.0/protocol/Exchange/mixins/MTransactions.sol": { + "2.0.0/protocol/Exchange/mixins/MAssetProxyDispatcher.sol": { "id": 41 }, - "2.0.0/tokens/ERC20Token/ERC20Token.sol": { + "2.0.0/protocol/Exchange/mixins/MExchangeCore.sol": { "id": 42 }, - "2.0.0/tokens/ERC20Token/IERC20Token.sol": { + "2.0.0/protocol/Exchange/mixins/MMatchOrders.sol": { "id": 43 }, - "2.0.0/tokens/ERC721Token/ERC721Token.sol": { + "2.0.0/protocol/Exchange/mixins/MSignatureValidator.sol": { "id": 44 }, - "2.0.0/tokens/ERC721Token/IERC721Receiver.sol": { + "2.0.0/protocol/Exchange/mixins/MTransactions.sol": { "id": 45 }, - "2.0.0/tokens/ERC721Token/IERC721Token.sol": { + "2.0.0/protocol/Exchange/mixins/MWrapperFunctions.sol": { "id": 46 }, - "2.0.0/tokens/EtherToken/IEtherToken.sol": { + "2.0.0/tokens/ERC20Token/ERC20Token.sol": { "id": 47 }, - "2.0.0/utils/LibBytes/LibBytes.sol": { + "2.0.0/tokens/ERC20Token/IERC20Token.sol": { "id": 48 }, - "2.0.0/utils/Ownable/IOwnable.sol": { + "2.0.0/tokens/ERC721Token/ERC721Token.sol": { "id": 49 }, - "2.0.0/utils/Ownable/Ownable.sol": { + "2.0.0/tokens/ERC721Token/IERC721Receiver.sol": { "id": 50 }, - "2.0.0/utils/SafeMath/SafeMath.sol": { + "2.0.0/tokens/ERC721Token/IERC721Token.sol": { "id": 51 + }, + "2.0.0/tokens/EtherToken/IEtherToken.sol": { + "id": 52 + }, + "2.0.0/utils/LibBytes/LibBytes.sol": { + "id": 53 + }, + "2.0.0/utils/Ownable/IOwnable.sol": { + "id": 54 + }, + "2.0.0/utils/Ownable/Ownable.sol": { + "id": 55 + }, + "2.0.0/utils/ReentrancyGuard/ReentrancyGuard.sol": { + "id": 56 + }, + "2.0.0/utils/SafeMath/SafeMath.sol": { + "id": 57 } }, "sourceCodes": { - "2.0.0/extensions/Forwarder/Forwarder.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 \"./MixinWeth.sol\";\nimport \"./MixinForwarderCore.sol\";\nimport \"./libs/LibConstants.sol\";\nimport \"./MixinAssets.sol\";\nimport \"./MixinExchangeWrapper.sol\";\n\n\n// solhint-disable no-empty-blocks\ncontract Forwarder is\n LibConstants,\n MixinWeth,\n MixinAssets,\n MixinExchangeWrapper,\n MixinForwarderCore\n{\n\n constructor (\n address _exchange,\n address _etherToken,\n address _zrxToken,\n bytes memory _zrxAssetData,\n bytes memory _wethAssetData\n )\n public\n LibConstants(\n _exchange,\n _etherToken,\n _zrxToken,\n _zrxAssetData,\n _wethAssetData\n )\n MixinForwarderCore()\n {}\n}\n", + "2.0.0/extensions/Forwarder/Forwarder.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 \"./MixinWeth.sol\";\nimport \"./MixinForwarderCore.sol\";\nimport \"./libs/LibConstants.sol\";\nimport \"./MixinAssets.sol\";\nimport \"./MixinExchangeWrapper.sol\";\n\n\n// solhint-disable no-empty-blocks\ncontract Forwarder is\n LibConstants,\n MixinWeth,\n MixinAssets,\n MixinExchangeWrapper,\n MixinForwarderCore\n{\n\n constructor (\n address _exchange,\n bytes memory _zrxAssetData,\n bytes memory _wethAssetData\n )\n public\n LibConstants(\n _exchange,\n _zrxAssetData,\n _wethAssetData\n )\n MixinForwarderCore()\n {}\n}\n", "2.0.0/extensions/Forwarder/MixinAssets.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 \"../../utils/LibBytes/LibBytes.sol\";\nimport \"../../utils/Ownable/Ownable.sol\";\nimport \"../../tokens/ERC20Token/IERC20Token.sol\";\nimport \"../../tokens/ERC721Token/IERC721Token.sol\";\nimport \"./libs/LibConstants.sol\";\nimport \"./mixins/MAssets.sol\";\n\n\ncontract MixinAssets is\n Ownable,\n LibConstants,\n MAssets\n{\n\n using LibBytes for bytes;\n\n bytes4 constant internal ERC20_TRANSFER_SELECTOR = bytes4(keccak256(\"transfer(address,uint256)\"));\n\n /// @dev Withdraws assets from this contract. The contract requires a ZRX balance in order to \n /// function optimally, and this function allows the ZRX to be withdrawn by owner. It may also be\n /// used to withdraw assets that were accidentally sent to this contract.\n /// @param assetData Byte array encoded for the respective asset proxy.\n /// @param amount Amount of ERC20 token to withdraw.\n function withdrawAsset(\n bytes assetData,\n uint256 amount\n )\n external\n onlyOwner\n {\n transferAssetToSender(assetData, amount);\n }\n\n /// @dev Transfers given amount of asset to sender.\n /// @param assetData Byte array encoded for the respective asset proxy.\n /// @param amount Amount of asset to transfer to sender.\n function transferAssetToSender(\n bytes memory assetData,\n uint256 amount\n )\n internal\n {\n bytes4 proxyId = assetData.readBytes4(0);\n\n if (proxyId == ERC20_DATA_ID) {\n transferERC20Token(assetData, amount);\n } else if (proxyId == ERC721_DATA_ID) {\n transferERC721Token(assetData, amount);\n } else {\n revert(\"UNSUPPORTED_ASSET_PROXY\");\n }\n }\n\n /// @dev Decodes ERC20 assetData and transfers given amount to sender.\n /// @param assetData Byte array encoded for the respective asset proxy.\n /// @param amount Amount of asset to transfer to sender.\n function transferERC20Token(\n bytes memory assetData,\n uint256 amount\n )\n internal\n {\n address token = assetData.readAddress(16);\n\n // Transfer tokens.\n // We do a raw call so we can check the success separate\n // from the return data.\n bool success = token.call(abi.encodeWithSelector(\n ERC20_TRANSFER_SELECTOR,\n msg.sender,\n amount\n ));\n require(\n success,\n \"TRANSFER_FAILED\"\n );\n \n // Check return data.\n // If there is no return data, we assume the token incorrectly\n // does not return a bool. In this case we expect it to revert\n // on failure, which was handled above.\n // If the token does return data, we require that it is a single\n // value that evaluates to true.\n assembly {\n if returndatasize {\n success := 0\n if eq(returndatasize, 32) {\n // First 64 bytes of memory are reserved scratch space\n returndatacopy(0, 0, 32)\n success := mload(0)\n }\n }\n }\n require(\n success,\n \"TRANSFER_FAILED\"\n );\n }\n\n /// @dev Decodes ERC721 assetData and transfers given amount to sender.\n /// @param assetData Byte array encoded for the respective asset proxy.\n /// @param amount Amount of asset to transfer to sender.\n function transferERC721Token(\n bytes memory assetData,\n uint256 amount\n )\n internal\n {\n require(\n amount == 1,\n \"INVALID_AMOUNT\"\n );\n // Decode asset data.\n address token = assetData.readAddress(16);\n uint256 tokenId = assetData.readUint256(36);\n\n // Perform transfer.\n IERC721Token(token).transferFrom(\n address(this),\n msg.sender,\n tokenId\n );\n }\n}\n", - "2.0.0/extensions/Forwarder/MixinExchangeWrapper.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 \"./libs/LibConstants.sol\";\nimport \"./mixins/MExchangeWrapper.sol\";\nimport \"../../protocol/Exchange/libs/LibAbiEncoder.sol\";\nimport \"../../protocol/Exchange/libs/LibOrder.sol\";\nimport \"../../protocol/Exchange/libs/LibFillResults.sol\";\nimport \"../../protocol/Exchange/libs/LibMath.sol\";\n\n\ncontract MixinExchangeWrapper is\n LibAbiEncoder,\n LibFillResults,\n LibMath,\n LibConstants,\n MExchangeWrapper\n{\n\n /// @dev Fills the input order.\n /// Returns false if the transaction would otherwise revert.\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 fillOrderNoThrow(\n LibOrder.Order memory order,\n uint256 takerAssetFillAmount,\n bytes memory signature\n )\n internal\n returns (FillResults memory fillResults)\n {\n // ABI encode calldata for `fillOrder`\n bytes memory fillOrderCalldata = abiEncodeFillOrder(\n order,\n takerAssetFillAmount,\n signature\n );\n\n address exchange = address(EXCHANGE);\n\n // Call `fillOrder` and handle any exceptions gracefully\n assembly {\n let success := call(\n gas, // forward all gas, TODO: look into gas consumption of assert/throw\n exchange, // call address of Exchange contract\n 0, // transfer 0 wei\n add(fillOrderCalldata, 32), // pointer to start of input (skip array length in first 32 bytes)\n mload(fillOrderCalldata), // length of input\n fillOrderCalldata, // write output over input\n 128 // output size is 128 bytes\n )\n switch success\n case 0 {\n mstore(fillResults, 0)\n mstore(add(fillResults, 32), 0)\n mstore(add(fillResults, 64), 0)\n mstore(add(fillResults, 96), 0)\n }\n case 1 {\n mstore(fillResults, mload(fillOrderCalldata))\n mstore(add(fillResults, 32), mload(add(fillOrderCalldata, 32)))\n mstore(add(fillResults, 64), mload(add(fillOrderCalldata, 64)))\n mstore(add(fillResults, 96), mload(add(fillOrderCalldata, 96)))\n }\n }\n return fillResults;\n }\n\n /// @dev Synchronously executes multiple calls of fillOrder until total amount of WETH has been sold by taker.\n /// Returns false if the transaction would otherwise revert.\n /// @param orders Array of order specifications.\n /// @param wethSellAmount Desired amount of WETH 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 marketSellWeth(\n LibOrder.Order[] memory orders,\n uint256 wethSellAmount,\n bytes[] memory signatures\n )\n internal\n returns (FillResults memory totalFillResults)\n {\n bytes memory makerAssetData = orders[0].makerAssetData;\n bytes memory wethAssetData = WETH_ASSET_DATA;\n\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n\n // We assume that asset being bought by taker is the same for each order.\n // We assume that asset being sold by taker is WETH for each order.\n orders[i].makerAssetData = makerAssetData;\n orders[i].takerAssetData = wethAssetData;\n\n // Calculate the remaining amount of WETH to sell\n uint256 remainingTakerAssetFillAmount = safeSub(wethSellAmount, totalFillResults.takerAssetFilledAmount);\n\n // Attempt to sell the remaining amount of WETH\n FillResults memory singleFillResults = fillOrderNoThrow(\n orders[i],\n remainingTakerAssetFillAmount,\n signatures[i]\n );\n\n // Update amounts filled and fees paid by maker and taker\n addFillResults(totalFillResults, singleFillResults);\n\n // Stop execution if the entire amount of takerAsset has been sold\n if (totalFillResults.takerAssetFilledAmount >= wethSellAmount) {\n break;\n }\n }\n return totalFillResults;\n }\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 /// The asset being sold by taker must always be WETH.\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 marketBuyExactAmountWithWeth(\n LibOrder.Order[] memory orders,\n uint256 makerAssetFillAmount,\n bytes[] memory signatures\n )\n internal\n returns (FillResults memory totalFillResults)\n {\n bytes memory makerAssetData = orders[0].makerAssetData;\n bytes memory wethAssetData = WETH_ASSET_DATA;\n\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n\n // We assume that asset being bought by taker is the same for each order.\n // We assume that asset being sold by taker is WETH for each order.\n orders[i].makerAssetData = makerAssetData;\n orders[i].takerAssetData = wethAssetData;\n\n // Calculate the remaining amount of makerAsset to buy\n uint256 remainingMakerAssetFillAmount = safeSub(makerAssetFillAmount, totalFillResults.makerAssetFilledAmount);\n\n // Convert the remaining amount of makerAsset to buy into remaining amount\n // of takerAsset to sell, assuming entire amount can be sold in the current order\n uint256 remainingTakerAssetFillAmount = getPartialAmount(\n orders[i].takerAssetAmount,\n orders[i].makerAssetAmount,\n remainingMakerAssetFillAmount\n );\n\n // Attempt to sell the remaining amount of takerAsset\n FillResults memory singleFillResults = fillOrderNoThrow(\n orders[i],\n remainingTakerAssetFillAmount,\n signatures[i]\n );\n\n // Update amounts filled and fees paid by maker and taker\n addFillResults(totalFillResults, singleFillResults);\n\n // Stop execution if the entire amount of makerAsset has been bought\n uint256 makerAssetFilledAmount = totalFillResults.makerAssetFilledAmount;\n if (makerAssetFilledAmount >= makerAssetFillAmount) {\n break;\n }\n }\n\n require(\n makerAssetFilledAmount >= makerAssetFillAmount,\n \"COMPLETE_FILL_FAILED\"\n );\n return totalFillResults;\n }\n\n /// @dev Buys zrxBuyAmount of ZRX fee tokens, taking into account ZRX fees for each order. This will guarantee\n /// that at least zrxBuyAmount of ZRX is purchased (sometimes slightly over due to rounding issues).\n /// It is possible that a request to buy 200 ZRX will require purchasing 202 ZRX\n /// as 2 ZRX is required to purchase the 200 ZRX fee tokens. This guarantees at least 200 ZRX for future purchases.\n /// The asset being sold by taker must always be WETH. \n /// @param orders Array of order specifications containing ZRX as makerAsset and WETH as takerAsset.\n /// @param zrxBuyAmount Desired amount of ZRX to buy.\n /// @param signatures Proofs that orders have been created by makers.\n /// @return totalFillResults Amounts filled and fees paid by maker and taker.\n function marketBuyExactZrxWithWeth(\n LibOrder.Order[] memory orders,\n uint256 zrxBuyAmount,\n bytes[] memory signatures\n )\n internal\n returns (FillResults memory totalFillResults)\n {\n // Do nothing if zrxBuyAmount == 0\n if (zrxBuyAmount == 0) {\n return totalFillResults;\n }\n\n bytes memory zrxAssetData = ZRX_ASSET_DATA;\n bytes memory wethAssetData = WETH_ASSET_DATA;\n uint256 zrxPurchased = 0;\n\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n\n // All of these are ZRX/WETH, so we can drop the respective assetData from calldata.\n orders[i].makerAssetData = zrxAssetData;\n orders[i].takerAssetData = wethAssetData;\n\n // Calculate the remaining amount of ZRX to buy.\n uint256 remainingZrxBuyAmount = safeSub(zrxBuyAmount, zrxPurchased);\n\n // Convert the remaining amount of ZRX to buy into remaining amount\n // of WETH to sell, assuming entire amount can be sold in the current order.\n uint256 remainingWethSellAmount = getPartialAmount(\n orders[i].takerAssetAmount,\n safeSub(orders[i].makerAssetAmount, orders[i].takerFee), // our exchange rate after fees \n remainingZrxBuyAmount\n );\n\n // Attempt to sell the remaining amount of WETH.\n FillResults memory singleFillResult = fillOrderNoThrow(\n orders[i],\n safeAdd(remainingWethSellAmount, 1), // we add 1 wei to the fill amount to make up for rounding errors\n signatures[i]\n );\n\n // Update amounts filled and fees paid by maker and taker.\n addFillResults(totalFillResults, singleFillResult);\n zrxPurchased = safeSub(totalFillResults.makerAssetFilledAmount, totalFillResults.takerFeePaid);\n\n // Stop execution if the entire amount of ZRX has been bought.\n if (zrxPurchased >= zrxBuyAmount) {\n break;\n }\n }\n\n require(\n zrxPurchased >= zrxBuyAmount,\n \"COMPLETE_FILL_FAILED\"\n );\n return totalFillResults;\n }\n}\n", - "2.0.0/extensions/Forwarder/MixinForwarderCore.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 \"./libs/LibConstants.sol\";\nimport \"./mixins/MWeth.sol\";\nimport \"./mixins/MAssets.sol\";\nimport \"./mixins/MExchangeWrapper.sol\";\nimport \"./interfaces/IForwarderCore.sol\";\nimport \"../../utils/LibBytes/LibBytes.sol\";\nimport \"../../protocol/Exchange/libs/LibOrder.sol\";\nimport \"../../protocol/Exchange/libs/LibFillResults.sol\";\nimport \"../../protocol/Exchange/libs/LibMath.sol\";\n\n\ncontract MixinForwarderCore is\n LibFillResults,\n LibMath,\n LibConstants,\n MWeth,\n MAssets,\n MExchangeWrapper,\n IForwarderCore\n{\n\n using LibBytes for bytes;\n\n /// @dev Constructor approves ERC20 proxy to transfer ZRX and WETH on this contract's behalf.\n constructor ()\n public\n {\n address proxyAddress = EXCHANGE.getAssetProxy(ERC20_DATA_ID);\n if (proxyAddress != address(0)) {\n ETHER_TOKEN.approve(proxyAddress, MAX_UINT);\n ZRX_TOKEN.approve(proxyAddress, MAX_UINT);\n }\n }\n\n /// @dev Purchases as much of orders' makerAssets as possible by selling up to 95% of transaction's ETH value.\n /// Any ZRX required to pay fees for primary orders will automatically be purchased by this contract.\n /// 5% of ETH value is reserved for paying fees to order feeRecipients (in ZRX) and forwarding contract feeRecipient (in ETH).\n /// Any ETH not spent will be refunded to sender.\n /// @param orders Array of order specifications used containing desired makerAsset and WETH as takerAsset. \n /// @param signatures Proofs that orders have been created by makers.\n /// @param feeOrders Array of order specifications containing ZRX as makerAsset and WETH as takerAsset. Used to purchase ZRX for primary order fees.\n /// @param feeSignatures Proofs that feeOrders have been created by makers.\n /// @param feePercentage Percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.\n /// @param feeRecipient Address that will receive ETH when orders are filled.\n /// @return Amounts filled and fees paid by maker and taker for both sets of orders.\n function marketSellOrdersWithEth(\n LibOrder.Order[] memory orders,\n bytes[] memory signatures,\n LibOrder.Order[] memory feeOrders,\n bytes[] memory feeSignatures,\n uint256 feePercentage,\n address feeRecipient\n )\n public\n payable\n returns (\n FillResults memory orderFillResults,\n FillResults memory feeOrderFillResults\n )\n {\n // Convert ETH to WETH.\n convertEthToWeth();\n\n uint256 wethSellAmount;\n uint256 zrxBuyAmount;\n uint256 makerAssetAmountPurchased;\n if (orders[0].makerAssetData.equals(ZRX_ASSET_DATA)) {\n // Calculate amount of WETH that won't be spent on ETH fees.\n wethSellAmount = getPartialAmount(\n PERCENTAGE_DENOMINATOR,\n safeAdd(PERCENTAGE_DENOMINATOR, feePercentage),\n msg.value\n );\n // Market sell available WETH.\n // ZRX fees are paid with this contract's balance.\n orderFillResults = marketSellWeth(\n orders,\n wethSellAmount,\n signatures\n );\n // The fee amount must be deducted from the amount transfered back to sender.\n makerAssetAmountPurchased = safeSub(orderFillResults.makerAssetFilledAmount, orderFillResults.takerFeePaid);\n } else {\n // 5% of WETH is reserved for filling feeOrders and paying feeRecipient.\n wethSellAmount = getPartialAmount(\n MAX_WETH_FILL_PERCENTAGE,\n PERCENTAGE_DENOMINATOR,\n msg.value\n );\n // Market sell 95% of WETH.\n // ZRX fees are payed with this contract's balance.\n orderFillResults = marketSellWeth(\n orders,\n wethSellAmount,\n signatures\n );\n // Buy back all ZRX spent on fees.\n zrxBuyAmount = orderFillResults.takerFeePaid;\n feeOrderFillResults = marketBuyExactZrxWithWeth(\n feeOrders,\n zrxBuyAmount,\n feeSignatures\n );\n makerAssetAmountPurchased = orderFillResults.makerAssetFilledAmount;\n }\n\n // Transfer feePercentage of total ETH spent on primary orders to feeRecipient.\n // Refund remaining ETH to msg.sender.\n transferEthFeeAndRefund(\n orderFillResults.takerAssetFilledAmount,\n feeOrderFillResults.takerAssetFilledAmount,\n feePercentage,\n feeRecipient\n );\n\n // Transfer purchased assets to msg.sender.\n transferAssetToSender(orders[0].makerAssetData, makerAssetAmountPurchased);\n }\n\n /// @dev Attempt to purchase makerAssetFillAmount of makerAsset by selling ETH provided with transaction.\n /// Any ZRX required to pay fees for primary orders will automatically be purchased by this contract.\n /// Any ETH not spent will be refunded to sender.\n /// @param orders Array of order specifications used containing desired makerAsset and WETH as takerAsset. \n /// @param makerAssetFillAmount Desired amount of makerAsset to purchase.\n /// @param signatures Proofs that orders have been created by makers.\n /// @param feeOrders Array of order specifications containing ZRX as makerAsset and WETH as takerAsset. Used to purchase ZRX for primary order fees.\n /// @param feeSignatures Proofs that feeOrders have been created by makers.\n /// @param feePercentage Percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.\n /// @param feeRecipient Address that will receive ETH when orders are filled.\n /// @return Amounts filled and fees paid by maker and taker for both sets of orders.\n function marketBuyOrdersWithEth(\n LibOrder.Order[] memory orders,\n uint256 makerAssetFillAmount,\n bytes[] memory signatures,\n LibOrder.Order[] memory feeOrders,\n bytes[] memory feeSignatures,\n uint256 feePercentage,\n address feeRecipient\n )\n public\n payable\n returns (\n FillResults memory orderFillResults,\n FillResults memory feeOrderFillResults\n )\n {\n // Convert ETH to WETH.\n convertEthToWeth();\n\n uint256 zrxBuyAmount;\n uint256 makerAssetAmountPurchased;\n if (orders[0].makerAssetData.equals(ZRX_ASSET_DATA)) {\n // If the makerAsset is ZRX, it is not necessary to pay fees out of this\n // contracts's ZRX balance because fees are factored into the price of the order.\n orderFillResults = marketBuyExactZrxWithWeth(\n orders,\n makerAssetFillAmount,\n signatures\n );\n // The fee amount must be deducted from the amount transfered back to sender.\n makerAssetAmountPurchased = safeSub(orderFillResults.makerAssetFilledAmount, orderFillResults.takerFeePaid);\n } else {\n // Attemp to purchase desired amount of makerAsset.\n // ZRX fees are payed with this contract's balance.\n orderFillResults = marketBuyExactAmountWithWeth(\n orders,\n makerAssetFillAmount,\n signatures\n );\n // Buy back all ZRX spent on fees.\n zrxBuyAmount = orderFillResults.takerFeePaid;\n feeOrderFillResults = marketBuyExactZrxWithWeth(\n feeOrders,\n zrxBuyAmount,\n feeSignatures\n );\n makerAssetAmountPurchased = orderFillResults.makerAssetFilledAmount;\n }\n\n // Transfer feePercentage of total ETH spent on primary orders to feeRecipient.\n // Refund remaining ETH to msg.sender.\n transferEthFeeAndRefund(\n orderFillResults.takerAssetFilledAmount,\n feeOrderFillResults.takerAssetFilledAmount,\n feePercentage,\n feeRecipient\n );\n\n // Transfer purchased assets to msg.sender.\n transferAssetToSender(orders[0].makerAssetData, makerAssetAmountPurchased);\n }\n}\n", - "2.0.0/extensions/Forwarder/MixinWeth.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 \"../../protocol/Exchange/libs/LibMath.sol\";\nimport \"./libs/LibConstants.sol\";\nimport \"./mixins/MWeth.sol\";\n\n\ncontract MixinWeth is\n LibMath,\n LibConstants,\n MWeth\n{\n\n /// @dev Default payabale function, this allows us to withdraw WETH\n function ()\n public\n payable\n {\n require(\n msg.sender == address(ETHER_TOKEN),\n \"DEFAULT_FUNCTION_WETH_CONTRACT_ONLY\"\n );\n }\n\n /// @dev Converts message call's ETH value into WETH.\n function convertEthToWeth()\n internal\n {\n require(\n msg.value > 0,\n \"INVALID_MSG_VALUE\"\n );\n ETHER_TOKEN.deposit.value(msg.value)();\n }\n\n /// @dev Transfers feePercentage of WETH spent on primary orders to feeRecipient.\n /// Refunds any excess ETH to msg.sender.\n /// @param wethSoldExcludingFeeOrders Amount of WETH sold when filling primary orders.\n /// @param wethSoldForZrx Amount of WETH sold when purchasing ZRX required for primary order fees.\n /// @param feePercentage Percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.\n /// @param feeRecipient Address that will receive ETH when orders are filled.\n function transferEthFeeAndRefund(\n uint256 wethSoldExcludingFeeOrders,\n uint256 wethSoldForZrx,\n uint256 feePercentage,\n address feeRecipient\n )\n internal\n {\n // Ensure feePercentage is less than 5%.\n require(\n feePercentage <= MAX_FEE_PERCENTAGE,\n \"FEE_PERCENTAGE_TOO_LARGE\"\n );\n\n // Ensure that no extra WETH owned by this contract has been sold.\n uint256 wethSold = safeAdd(wethSoldExcludingFeeOrders, wethSoldForZrx);\n require(\n wethSold <= msg.value,\n \"OVERSOLD_WETH\"\n );\n\n // Calculate amount of WETH that hasn't been sold.\n uint256 wethRemaining = safeSub(msg.value, wethSold);\n\n // Calculate ETH fee to pay to feeRecipient.\n uint256 ethFee = getPartialAmount(\n feePercentage,\n PERCENTAGE_DENOMINATOR,\n wethSoldExcludingFeeOrders\n );\n\n // Ensure fee is less than amount of WETH remaining.\n require(\n ethFee <= wethRemaining,\n \"INSUFFICIENT_ETH_REMAINING\"\n );\n \n // Do nothing if no WETH remaining\n if (wethRemaining > 0) {\n // Convert remaining WETH to ETH\n ETHER_TOKEN.withdraw(wethRemaining);\n\n // Pay ETH to feeRecipient\n if (ethFee > 0) {\n feeRecipient.transfer(ethFee);\n }\n\n // Refund remaining ETH to msg.sender.\n uint256 ethRefund = safeSub(wethRemaining, ethFee);\n if (ethRefund > 0) {\n msg.sender.transfer(ethRefund);\n }\n }\n }\n}\n", + "2.0.0/extensions/Forwarder/MixinExchangeWrapper.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 \"./libs/LibConstants.sol\";\nimport \"./mixins/MExchangeWrapper.sol\";\nimport \"../../protocol/Exchange/libs/LibAbiEncoder.sol\";\nimport \"../../protocol/Exchange/libs/LibOrder.sol\";\nimport \"../../protocol/Exchange/libs/LibFillResults.sol\";\nimport \"../../protocol/Exchange/libs/LibMath.sol\";\n\n\ncontract MixinExchangeWrapper is\n LibAbiEncoder,\n LibFillResults,\n LibMath,\n LibConstants,\n MExchangeWrapper\n{\n\n /// @dev Fills the input order.\n /// Returns false if the transaction would otherwise revert.\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 fillOrderNoThrow(\n LibOrder.Order memory order,\n uint256 takerAssetFillAmount,\n bytes memory signature\n )\n internal\n returns (FillResults memory fillResults)\n {\n // ABI encode calldata for `fillOrder`\n bytes memory fillOrderCalldata = abiEncodeFillOrder(\n order,\n takerAssetFillAmount,\n signature\n );\n\n address exchange = address(EXCHANGE);\n\n // Call `fillOrder` and handle any exceptions gracefully\n assembly {\n let success := call(\n gas, // forward all gas, TODO: look into gas consumption of assert/throw\n exchange, // call address of Exchange contract\n 0, // transfer 0 wei\n add(fillOrderCalldata, 32), // pointer to start of input (skip array length in first 32 bytes)\n mload(fillOrderCalldata), // length of input\n fillOrderCalldata, // write output over input\n 128 // output size is 128 bytes\n )\n switch success\n case 0 {\n mstore(fillResults, 0)\n mstore(add(fillResults, 32), 0)\n mstore(add(fillResults, 64), 0)\n mstore(add(fillResults, 96), 0)\n }\n case 1 {\n mstore(fillResults, mload(fillOrderCalldata))\n mstore(add(fillResults, 32), mload(add(fillOrderCalldata, 32)))\n mstore(add(fillResults, 64), mload(add(fillOrderCalldata, 64)))\n mstore(add(fillResults, 96), mload(add(fillOrderCalldata, 96)))\n }\n }\n return fillResults;\n }\n\n /// @dev Synchronously executes multiple calls of fillOrder until total amount of WETH has been sold by taker.\n /// Returns false if the transaction would otherwise revert.\n /// @param orders Array of order specifications.\n /// @param wethSellAmount Desired amount of WETH 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 marketSellWeth(\n LibOrder.Order[] memory orders,\n uint256 wethSellAmount,\n bytes[] memory signatures\n )\n internal\n returns (FillResults memory totalFillResults)\n {\n bytes memory makerAssetData = orders[0].makerAssetData;\n bytes memory wethAssetData = WETH_ASSET_DATA;\n\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n\n // We assume that asset being bought by taker is the same for each order.\n // We assume that asset being sold by taker is WETH for each order.\n orders[i].makerAssetData = makerAssetData;\n orders[i].takerAssetData = wethAssetData;\n\n // Calculate the remaining amount of WETH to sell\n uint256 remainingTakerAssetFillAmount = safeSub(wethSellAmount, totalFillResults.takerAssetFilledAmount);\n\n // Attempt to sell the remaining amount of WETH\n FillResults memory singleFillResults = fillOrderNoThrow(\n orders[i],\n remainingTakerAssetFillAmount,\n signatures[i]\n );\n\n // Update amounts filled and fees paid by maker and taker\n addFillResults(totalFillResults, singleFillResults);\n\n // Stop execution if the entire amount of takerAsset has been sold\n if (totalFillResults.takerAssetFilledAmount >= wethSellAmount) {\n break;\n }\n }\n return totalFillResults;\n }\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 /// The asset being sold by taker must always be WETH.\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 marketBuyExactAmountWithWeth(\n LibOrder.Order[] memory orders,\n uint256 makerAssetFillAmount,\n bytes[] memory signatures\n )\n internal\n returns (FillResults memory totalFillResults)\n {\n bytes memory makerAssetData = orders[0].makerAssetData;\n bytes memory wethAssetData = WETH_ASSET_DATA;\n\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n\n // We assume that asset being bought by taker is the same for each order.\n // We assume that asset being sold by taker is WETH for each order.\n orders[i].makerAssetData = makerAssetData;\n orders[i].takerAssetData = wethAssetData;\n\n // Calculate the remaining amount of makerAsset to buy\n uint256 remainingMakerAssetFillAmount = safeSub(makerAssetFillAmount, totalFillResults.makerAssetFilledAmount);\n\n // Convert the remaining amount of makerAsset to buy into remaining amount\n // of takerAsset to sell, assuming entire amount can be sold in the current order\n uint256 remainingTakerAssetFillAmount = getPartialAmountFloor(\n orders[i].takerAssetAmount,\n orders[i].makerAssetAmount,\n remainingMakerAssetFillAmount\n );\n\n // Attempt to sell the remaining amount of takerAsset\n FillResults memory singleFillResults = fillOrderNoThrow(\n orders[i],\n remainingTakerAssetFillAmount,\n signatures[i]\n );\n\n // Update amounts filled and fees paid by maker and taker\n addFillResults(totalFillResults, singleFillResults);\n\n // Stop execution if the entire amount of makerAsset has been bought\n uint256 makerAssetFilledAmount = totalFillResults.makerAssetFilledAmount;\n if (makerAssetFilledAmount >= makerAssetFillAmount) {\n break;\n }\n }\n\n require(\n makerAssetFilledAmount >= makerAssetFillAmount,\n \"COMPLETE_FILL_FAILED\"\n );\n return totalFillResults;\n }\n\n /// @dev Buys zrxBuyAmount of ZRX fee tokens, taking into account ZRX fees for each order. This will guarantee\n /// that at least zrxBuyAmount of ZRX is purchased (sometimes slightly over due to rounding issues).\n /// It is possible that a request to buy 200 ZRX will require purchasing 202 ZRX\n /// as 2 ZRX is required to purchase the 200 ZRX fee tokens. This guarantees at least 200 ZRX for future purchases.\n /// The asset being sold by taker must always be WETH. \n /// @param orders Array of order specifications containing ZRX as makerAsset and WETH as takerAsset.\n /// @param zrxBuyAmount Desired amount of ZRX to buy.\n /// @param signatures Proofs that orders have been created by makers.\n /// @return totalFillResults Amounts filled and fees paid by maker and taker.\n function marketBuyExactZrxWithWeth(\n LibOrder.Order[] memory orders,\n uint256 zrxBuyAmount,\n bytes[] memory signatures\n )\n internal\n returns (FillResults memory totalFillResults)\n {\n // Do nothing if zrxBuyAmount == 0\n if (zrxBuyAmount == 0) {\n return totalFillResults;\n }\n\n bytes memory zrxAssetData = ZRX_ASSET_DATA;\n bytes memory wethAssetData = WETH_ASSET_DATA;\n uint256 zrxPurchased = 0;\n\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n\n // All of these are ZRX/WETH, so we can drop the respective assetData from calldata.\n orders[i].makerAssetData = zrxAssetData;\n orders[i].takerAssetData = wethAssetData;\n\n // Calculate the remaining amount of ZRX to buy.\n uint256 remainingZrxBuyAmount = safeSub(zrxBuyAmount, zrxPurchased);\n\n // Convert the remaining amount of ZRX to buy into remaining amount\n // of WETH to sell, assuming entire amount can be sold in the current order.\n uint256 remainingWethSellAmount = getPartialAmountFloor(\n orders[i].takerAssetAmount,\n safeSub(orders[i].makerAssetAmount, orders[i].takerFee), // our exchange rate after fees \n remainingZrxBuyAmount\n );\n\n // Attempt to sell the remaining amount of WETH.\n FillResults memory singleFillResult = fillOrderNoThrow(\n orders[i],\n safeAdd(remainingWethSellAmount, 1), // we add 1 wei to the fill amount to make up for rounding errors\n signatures[i]\n );\n\n // Update amounts filled and fees paid by maker and taker.\n addFillResults(totalFillResults, singleFillResult);\n zrxPurchased = safeSub(totalFillResults.makerAssetFilledAmount, totalFillResults.takerFeePaid);\n\n // Stop execution if the entire amount of ZRX has been bought.\n if (zrxPurchased >= zrxBuyAmount) {\n break;\n }\n }\n\n require(\n zrxPurchased >= zrxBuyAmount,\n \"COMPLETE_FILL_FAILED\"\n );\n return totalFillResults;\n }\n}\n", + "2.0.0/extensions/Forwarder/MixinForwarderCore.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 \"./libs/LibConstants.sol\";\nimport \"./mixins/MWeth.sol\";\nimport \"./mixins/MAssets.sol\";\nimport \"./mixins/MExchangeWrapper.sol\";\nimport \"./interfaces/IForwarderCore.sol\";\nimport \"../../utils/LibBytes/LibBytes.sol\";\nimport \"../../protocol/Exchange/libs/LibOrder.sol\";\nimport \"../../protocol/Exchange/libs/LibFillResults.sol\";\nimport \"../../protocol/Exchange/libs/LibMath.sol\";\n\n\ncontract MixinForwarderCore is\n LibFillResults,\n LibMath,\n LibConstants,\n MWeth,\n MAssets,\n MExchangeWrapper,\n IForwarderCore\n{\n\n using LibBytes for bytes;\n\n /// @dev Constructor approves ERC20 proxy to transfer ZRX and WETH on this contract's behalf.\n constructor ()\n public\n {\n address proxyAddress = EXCHANGE.getAssetProxy(ERC20_DATA_ID);\n if (proxyAddress != address(0)) {\n ETHER_TOKEN.approve(proxyAddress, MAX_UINT);\n ZRX_TOKEN.approve(proxyAddress, MAX_UINT);\n }\n }\n\n /// @dev Purchases as much of orders' makerAssets as possible by selling up to 95% of transaction's ETH value.\n /// Any ZRX required to pay fees for primary orders will automatically be purchased by this contract.\n /// 5% of ETH value is reserved for paying fees to order feeRecipients (in ZRX) and forwarding contract feeRecipient (in ETH).\n /// Any ETH not spent will be refunded to sender.\n /// @param orders Array of order specifications used containing desired makerAsset and WETH as takerAsset. \n /// @param signatures Proofs that orders have been created by makers.\n /// @param feeOrders Array of order specifications containing ZRX as makerAsset and WETH as takerAsset. Used to purchase ZRX for primary order fees.\n /// @param feeSignatures Proofs that feeOrders have been created by makers.\n /// @param feePercentage Percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.\n /// @param feeRecipient Address that will receive ETH when orders are filled.\n /// @return Amounts filled and fees paid by maker and taker for both sets of orders.\n function marketSellOrdersWithEth(\n LibOrder.Order[] memory orders,\n bytes[] memory signatures,\n LibOrder.Order[] memory feeOrders,\n bytes[] memory feeSignatures,\n uint256 feePercentage,\n address feeRecipient\n )\n public\n payable\n returns (\n FillResults memory orderFillResults,\n FillResults memory feeOrderFillResults\n )\n {\n // Convert ETH to WETH.\n convertEthToWeth();\n\n uint256 wethSellAmount;\n uint256 zrxBuyAmount;\n uint256 makerAssetAmountPurchased;\n if (orders[0].makerAssetData.equals(ZRX_ASSET_DATA)) {\n // Calculate amount of WETH that won't be spent on ETH fees.\n wethSellAmount = getPartialAmountFloor(\n PERCENTAGE_DENOMINATOR,\n safeAdd(PERCENTAGE_DENOMINATOR, feePercentage),\n msg.value\n );\n // Market sell available WETH.\n // ZRX fees are paid with this contract's balance.\n orderFillResults = marketSellWeth(\n orders,\n wethSellAmount,\n signatures\n );\n // The fee amount must be deducted from the amount transfered back to sender.\n makerAssetAmountPurchased = safeSub(orderFillResults.makerAssetFilledAmount, orderFillResults.takerFeePaid);\n } else {\n // 5% of WETH is reserved for filling feeOrders and paying feeRecipient.\n wethSellAmount = getPartialAmountFloor(\n MAX_WETH_FILL_PERCENTAGE,\n PERCENTAGE_DENOMINATOR,\n msg.value\n );\n // Market sell 95% of WETH.\n // ZRX fees are payed with this contract's balance.\n orderFillResults = marketSellWeth(\n orders,\n wethSellAmount,\n signatures\n );\n // Buy back all ZRX spent on fees.\n zrxBuyAmount = orderFillResults.takerFeePaid;\n feeOrderFillResults = marketBuyExactZrxWithWeth(\n feeOrders,\n zrxBuyAmount,\n feeSignatures\n );\n makerAssetAmountPurchased = orderFillResults.makerAssetFilledAmount;\n }\n\n // Transfer feePercentage of total ETH spent on primary orders to feeRecipient.\n // Refund remaining ETH to msg.sender.\n transferEthFeeAndRefund(\n orderFillResults.takerAssetFilledAmount,\n feeOrderFillResults.takerAssetFilledAmount,\n feePercentage,\n feeRecipient\n );\n\n // Transfer purchased assets to msg.sender.\n transferAssetToSender(orders[0].makerAssetData, makerAssetAmountPurchased);\n }\n\n /// @dev Attempt to purchase makerAssetFillAmount of makerAsset by selling ETH provided with transaction.\n /// Any ZRX required to pay fees for primary orders will automatically be purchased by this contract.\n /// Any ETH not spent will be refunded to sender.\n /// @param orders Array of order specifications used containing desired makerAsset and WETH as takerAsset. \n /// @param makerAssetFillAmount Desired amount of makerAsset to purchase.\n /// @param signatures Proofs that orders have been created by makers.\n /// @param feeOrders Array of order specifications containing ZRX as makerAsset and WETH as takerAsset. Used to purchase ZRX for primary order fees.\n /// @param feeSignatures Proofs that feeOrders have been created by makers.\n /// @param feePercentage Percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.\n /// @param feeRecipient Address that will receive ETH when orders are filled.\n /// @return Amounts filled and fees paid by maker and taker for both sets of orders.\n function marketBuyOrdersWithEth(\n LibOrder.Order[] memory orders,\n uint256 makerAssetFillAmount,\n bytes[] memory signatures,\n LibOrder.Order[] memory feeOrders,\n bytes[] memory feeSignatures,\n uint256 feePercentage,\n address feeRecipient\n )\n public\n payable\n returns (\n FillResults memory orderFillResults,\n FillResults memory feeOrderFillResults\n )\n {\n // Convert ETH to WETH.\n convertEthToWeth();\n\n uint256 zrxBuyAmount;\n uint256 makerAssetAmountPurchased;\n if (orders[0].makerAssetData.equals(ZRX_ASSET_DATA)) {\n // If the makerAsset is ZRX, it is not necessary to pay fees out of this\n // contracts's ZRX balance because fees are factored into the price of the order.\n orderFillResults = marketBuyExactZrxWithWeth(\n orders,\n makerAssetFillAmount,\n signatures\n );\n // The fee amount must be deducted from the amount transfered back to sender.\n makerAssetAmountPurchased = safeSub(orderFillResults.makerAssetFilledAmount, orderFillResults.takerFeePaid);\n } else {\n // Attemp to purchase desired amount of makerAsset.\n // ZRX fees are payed with this contract's balance.\n orderFillResults = marketBuyExactAmountWithWeth(\n orders,\n makerAssetFillAmount,\n signatures\n );\n // Buy back all ZRX spent on fees.\n zrxBuyAmount = orderFillResults.takerFeePaid;\n feeOrderFillResults = marketBuyExactZrxWithWeth(\n feeOrders,\n zrxBuyAmount,\n feeSignatures\n );\n makerAssetAmountPurchased = orderFillResults.makerAssetFilledAmount;\n }\n\n // Transfer feePercentage of total ETH spent on primary orders to feeRecipient.\n // Refund remaining ETH to msg.sender.\n transferEthFeeAndRefund(\n orderFillResults.takerAssetFilledAmount,\n feeOrderFillResults.takerAssetFilledAmount,\n feePercentage,\n feeRecipient\n );\n\n // Transfer purchased assets to msg.sender.\n transferAssetToSender(orders[0].makerAssetData, makerAssetAmountPurchased);\n }\n}\n", + "2.0.0/extensions/Forwarder/MixinWeth.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 \"../../protocol/Exchange/libs/LibMath.sol\";\nimport \"./libs/LibConstants.sol\";\nimport \"./mixins/MWeth.sol\";\n\n\ncontract MixinWeth is\n LibMath,\n LibConstants,\n MWeth\n{\n\n /// @dev Default payabale function, this allows us to withdraw WETH\n function ()\n public\n payable\n {\n require(\n msg.sender == address(ETHER_TOKEN),\n \"DEFAULT_FUNCTION_WETH_CONTRACT_ONLY\"\n );\n }\n\n /// @dev Converts message call's ETH value into WETH.\n function convertEthToWeth()\n internal\n {\n require(\n msg.value > 0,\n \"INVALID_MSG_VALUE\"\n );\n ETHER_TOKEN.deposit.value(msg.value)();\n }\n\n /// @dev Transfers feePercentage of WETH spent on primary orders to feeRecipient.\n /// Refunds any excess ETH to msg.sender.\n /// @param wethSoldExcludingFeeOrders Amount of WETH sold when filling primary orders.\n /// @param wethSoldForZrx Amount of WETH sold when purchasing ZRX required for primary order fees.\n /// @param feePercentage Percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.\n /// @param feeRecipient Address that will receive ETH when orders are filled.\n function transferEthFeeAndRefund(\n uint256 wethSoldExcludingFeeOrders,\n uint256 wethSoldForZrx,\n uint256 feePercentage,\n address feeRecipient\n )\n internal\n {\n // Ensure feePercentage is less than 5%.\n require(\n feePercentage <= MAX_FEE_PERCENTAGE,\n \"FEE_PERCENTAGE_TOO_LARGE\"\n );\n\n // Ensure that no extra WETH owned by this contract has been sold.\n uint256 wethSold = safeAdd(wethSoldExcludingFeeOrders, wethSoldForZrx);\n require(\n wethSold <= msg.value,\n \"OVERSOLD_WETH\"\n );\n\n // Calculate amount of WETH that hasn't been sold.\n uint256 wethRemaining = safeSub(msg.value, wethSold);\n\n // Calculate ETH fee to pay to feeRecipient.\n uint256 ethFee = getPartialAmountFloor(\n feePercentage,\n PERCENTAGE_DENOMINATOR,\n wethSoldExcludingFeeOrders\n );\n\n // Ensure fee is less than amount of WETH remaining.\n require(\n ethFee <= wethRemaining,\n \"INSUFFICIENT_ETH_REMAINING\"\n );\n \n // Do nothing if no WETH remaining\n if (wethRemaining > 0) {\n // Convert remaining WETH to ETH\n ETHER_TOKEN.withdraw(wethRemaining);\n\n // Pay ETH to feeRecipient\n if (ethFee > 0) {\n feeRecipient.transfer(ethFee);\n }\n\n // Refund remaining ETH to msg.sender.\n uint256 ethRefund = safeSub(wethRemaining, ethFee);\n if (ethRefund > 0) {\n msg.sender.transfer(ethRefund);\n }\n }\n }\n}\n", "2.0.0/extensions/Forwarder/interfaces/IAssets.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 IAssets {\n\n /// @dev Withdraws assets from this contract. The contract requires a ZRX balance in order to \n /// function optimally, and this function allows the ZRX to be withdrawn by owner. It may also be\n /// used to withdraw assets that were accidentally sent to this contract.\n /// @param assetData Byte array encoded for the respective asset proxy.\n /// @param amount Amount of ERC20 token to withdraw.\n function withdrawAsset(\n bytes assetData,\n uint256 amount\n )\n external;\n}\n", "2.0.0/extensions/Forwarder/interfaces/IForwarderCore.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 \"../../../protocol/Exchange/libs/LibOrder.sol\";\nimport \"../../../protocol/Exchange/libs/LibFillResults.sol\";\n\n\ncontract IForwarderCore {\n\n /// @dev Purchases as much of orders' makerAssets as possible by selling up to 95% of transaction's ETH value.\n /// Any ZRX required to pay fees for primary orders will automatically be purchased by this contract.\n /// 5% of ETH value is reserved for paying fees to order feeRecipients (in ZRX) and forwarding contract feeRecipient (in ETH).\n /// Any ETH not spent will be refunded to sender.\n /// @param orders Array of order specifications used containing desired makerAsset and WETH as takerAsset. \n /// @param signatures Proofs that orders have been created by makers.\n /// @param feeOrders Array of order specifications containing ZRX as makerAsset and WETH as takerAsset. Used to purchase ZRX for primary order fees.\n /// @param feeSignatures Proofs that feeOrders have been created by makers.\n /// @param feePercentage Percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.\n /// @param feeRecipient Address that will receive ETH when orders are filled.\n /// @return Amounts filled and fees paid by maker and taker for both sets of orders.\n function marketSellOrdersWithEth(\n LibOrder.Order[] memory orders,\n bytes[] memory signatures,\n LibOrder.Order[] memory feeOrders,\n bytes[] memory feeSignatures,\n uint256 feePercentage,\n address feeRecipient\n )\n public\n payable\n returns (\n LibFillResults.FillResults memory orderFillResults,\n LibFillResults.FillResults memory feeOrderFillResults\n );\n\n /// @dev Attempt to purchase makerAssetFillAmount of makerAsset by selling ETH provided with transaction.\n /// Any ZRX required to pay fees for primary orders will automatically be purchased by this contract.\n /// Any ETH not spent will be refunded to sender.\n /// @param orders Array of order specifications used containing desired makerAsset and WETH as takerAsset. \n /// @param makerAssetFillAmount Desired amount of makerAsset to purchase.\n /// @param signatures Proofs that orders have been created by makers.\n /// @param feeOrders Array of order specifications containing ZRX as makerAsset and WETH as takerAsset. Used to purchase ZRX for primary order fees.\n /// @param feeSignatures Proofs that feeOrders have been created by makers.\n /// @param feePercentage Percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.\n /// @param feeRecipient Address that will receive ETH when orders are filled.\n /// @return Amounts filled and fees paid by maker and taker for both sets of orders.\n function marketBuyOrdersWithEth(\n LibOrder.Order[] memory orders,\n uint256 makerAssetFillAmount,\n bytes[] memory signatures,\n LibOrder.Order[] memory feeOrders,\n bytes[] memory feeSignatures,\n uint256 feePercentage,\n address feeRecipient\n )\n public\n payable\n returns (\n LibFillResults.FillResults memory orderFillResults,\n LibFillResults.FillResults memory feeOrderFillResults\n );\n}\n", - "2.0.0/extensions/Forwarder/libs/LibConstants.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 \"../../../protocol/Exchange/interfaces/IExchange.sol\";\nimport \"../../../tokens/EtherToken/IEtherToken.sol\";\nimport \"../../../tokens/ERC20Token/IERC20Token.sol\";\n\n\ncontract LibConstants {\n\n bytes4 constant internal ERC20_DATA_ID = bytes4(keccak256(\"ERC20Token(address)\"));\n bytes4 constant internal ERC721_DATA_ID = bytes4(keccak256(\"ERC721Token(address,uint256)\"));\n uint256 constant internal MAX_UINT = 2**256 - 1;\n uint256 constant internal PERCENTAGE_DENOMINATOR = 10**18; \n uint256 constant internal MAX_FEE_PERCENTAGE = 5 * PERCENTAGE_DENOMINATOR / 100; // 5%\n uint256 constant internal MAX_WETH_FILL_PERCENTAGE = 95 * PERCENTAGE_DENOMINATOR / 100; // 95%\n \n // solhint-disable var-name-mixedcase\n IExchange internal EXCHANGE;\n IEtherToken internal ETHER_TOKEN;\n IERC20Token internal ZRX_TOKEN;\n bytes internal ZRX_ASSET_DATA;\n bytes internal WETH_ASSET_DATA;\n // solhint-enable var-name-mixedcase\n\n constructor (\n address _exchange,\n address _etherToken,\n address _zrxToken,\n bytes memory _zrxAssetData,\n bytes memory _wethAssetData\n )\n public\n {\n EXCHANGE = IExchange(_exchange);\n ETHER_TOKEN = IEtherToken(_etherToken);\n ZRX_TOKEN = IERC20Token(_zrxToken);\n ZRX_ASSET_DATA = _zrxAssetData;\n WETH_ASSET_DATA = _wethAssetData;\n }\n}\n", + "2.0.0/extensions/Forwarder/libs/LibConstants.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 \"../../../utils/LibBytes/LibBytes.sol\";\nimport \"../../../protocol/Exchange/interfaces/IExchange.sol\";\nimport \"../../../tokens/EtherToken/IEtherToken.sol\";\nimport \"../../../tokens/ERC20Token/IERC20Token.sol\";\n\n\ncontract LibConstants {\n\n using LibBytes for bytes;\n\n bytes4 constant internal ERC20_DATA_ID = bytes4(keccak256(\"ERC20Token(address)\"));\n bytes4 constant internal ERC721_DATA_ID = bytes4(keccak256(\"ERC721Token(address,uint256)\"));\n uint256 constant internal MAX_UINT = 2**256 - 1;\n uint256 constant internal PERCENTAGE_DENOMINATOR = 10**18; \n uint256 constant internal MAX_FEE_PERCENTAGE = 5 * PERCENTAGE_DENOMINATOR / 100; // 5%\n uint256 constant internal MAX_WETH_FILL_PERCENTAGE = 95 * PERCENTAGE_DENOMINATOR / 100; // 95%\n \n // solhint-disable var-name-mixedcase\n IExchange internal EXCHANGE;\n IEtherToken internal ETHER_TOKEN;\n IERC20Token internal ZRX_TOKEN;\n bytes internal ZRX_ASSET_DATA;\n bytes internal WETH_ASSET_DATA;\n // solhint-enable var-name-mixedcase\n\n constructor (\n address _exchange,\n bytes memory _zrxAssetData,\n bytes memory _wethAssetData\n )\n public\n {\n EXCHANGE = IExchange(_exchange);\n ZRX_ASSET_DATA = _zrxAssetData;\n WETH_ASSET_DATA = _wethAssetData;\n\n address etherToken = _wethAssetData.readAddress(16);\n address zrxToken = _zrxAssetData.readAddress(16);\n ETHER_TOKEN = IEtherToken(etherToken);\n ZRX_TOKEN = IERC20Token(zrxToken);\n }\n}\n", "2.0.0/extensions/Forwarder/mixins/MAssets.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 \"../interfaces/IAssets.sol\";\n\n\ncontract MAssets is\n IAssets\n{\n\n /// @dev Transfers given amount of asset to sender.\n /// @param assetData Byte array encoded for the respective asset proxy.\n /// @param amount Amount of asset to transfer to sender.\n function transferAssetToSender(\n bytes memory assetData,\n uint256 amount\n )\n internal;\n\n /// @dev Decodes ERC20 assetData and transfers given amount to sender.\n /// @param assetData Byte array encoded for the respective asset proxy.\n /// @param amount Amount of asset to transfer to sender.\n function transferERC20Token(\n bytes memory assetData,\n uint256 amount\n )\n internal;\n\n /// @dev Decodes ERC721 assetData and transfers given amount to sender.\n /// @param assetData Byte array encoded for the respective asset proxy.\n /// @param amount Amount of asset to transfer to sender.\n function transferERC721Token(\n bytes memory assetData,\n uint256 amount\n )\n internal;\n}\n", "2.0.0/extensions/Forwarder/mixins/MExchangeWrapper.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 \"../../../protocol/Exchange/libs/LibOrder.sol\";\nimport \"../../../protocol/Exchange/libs/LibFillResults.sol\";\n\n\ncontract MExchangeWrapper {\n\n /// @dev Fills the input order.\n /// Returns false if the transaction would otherwise revert.\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 fillOrderNoThrow(\n LibOrder.Order memory order,\n uint256 takerAssetFillAmount,\n bytes memory signature\n )\n internal\n returns (LibFillResults.FillResults memory fillResults);\n\n /// @dev Synchronously executes multiple calls of fillOrder until total amount of WETH has been sold by taker.\n /// Returns false if the transaction would otherwise revert.\n /// @param orders Array of order specifications.\n /// @param wethSellAmount Desired amount of WETH 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 marketSellWeth(\n LibOrder.Order[] memory orders,\n uint256 wethSellAmount,\n bytes[] memory signatures\n )\n internal\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 /// The asset being sold by taker must always be WETH.\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 marketBuyExactAmountWithWeth(\n LibOrder.Order[] memory orders,\n uint256 makerAssetFillAmount,\n bytes[] memory signatures\n )\n internal\n returns (LibFillResults.FillResults memory totalFillResults);\n\n /// @dev Buys zrxBuyAmount of ZRX fee tokens, taking into account ZRX fees for each order. This will guarantee\n /// that at least zrxBuyAmount of ZRX is purchased (sometimes slightly over due to rounding issues).\n /// It is possible that a request to buy 200 ZRX will require purchasing 202 ZRX\n /// as 2 ZRX is required to purchase the 200 ZRX fee tokens. This guarantees at least 200 ZRX for future purchases.\n /// The asset being sold by taker must always be WETH. \n /// @param orders Array of order specifications containing ZRX as makerAsset and WETH as takerAsset.\n /// @param zrxBuyAmount Desired amount of ZRX to buy.\n /// @param signatures Proofs that orders have been created by makers.\n /// @return totalFillResults Amounts filled and fees paid by maker and taker.\n function marketBuyExactZrxWithWeth(\n LibOrder.Order[] memory orders,\n uint256 zrxBuyAmount,\n bytes[] memory signatures\n )\n internal\n returns (LibFillResults.FillResults memory totalFillResults);\n}\n", "2.0.0/extensions/Forwarder/mixins/MWeth.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 MWeth {\n\n /// @dev Converts message call's ETH value into WETH.\n function convertEthToWeth()\n internal;\n\n /// @dev Transfers feePercentage of WETH spent on primary orders to feeRecipient.\n /// Refunds any excess ETH to msg.sender.\n /// @param wethSoldExcludingFeeOrders Amount of WETH sold when filling primary orders.\n /// @param wethSoldForZrx Amount of WETH sold when purchasing ZRX required for primary order fees.\n /// @param feePercentage Percentage of WETH sold that will payed as fee to forwarding contract feeRecipient.\n /// @param feeRecipient Address that will receive ETH when orders are filled.\n function transferEthFeeAndRefund(\n uint256 wethSoldExcludingFeeOrders,\n uint256 wethSoldForZrx,\n uint256 feePercentage,\n address feeRecipient\n )\n internal;\n}\n", - "2.0.0/extensions/OrderValidator/OrderValidator.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 \"../../protocol/Exchange/interfaces/IExchange.sol\";\nimport \"../../protocol/Exchange/libs/LibOrder.sol\";\nimport \"../../tokens/ERC20Token/IERC20Token.sol\";\nimport \"../../tokens/ERC721Token/IERC721Token.sol\";\nimport \"../../utils/LibBytes/LibBytes.sol\";\n\n\ncontract OrderValidator {\n\n bytes4 constant internal ERC20_DATA_ID = bytes4(keccak256(\"ERC20Token(address)\"));\n bytes4 constant internal ERC721_DATA_ID = bytes4(keccak256(\"ERC721Token(address,uint256)\"));\n\n using LibBytes for bytes;\n\n struct TraderInfo {\n uint256 makerBalance; // Maker's balance of makerAsset\n uint256 makerAllowance; // Maker's allowance to corresponding AssetProxy\n uint256 takerBalance; // Taker's balance of takerAsset\n uint256 takerAllowance; // Taker's allowance to corresponding AssetProxy\n uint256 makerZrxBalance; // Maker's balance of ZRX\n uint256 makerZrxAllowance; // Maker's allowance of ZRX to ERC20Proxy\n uint256 takerZrxBalance; // Taker's balance of ZRX\n uint256 takerZrxAllowance; // Taker's allowance of ZRX to ERC20Proxy\n }\n\n // solhint-disable var-name-mixedcase\n IExchange internal EXCHANGE;\n bytes internal ZRX_ASSET_DATA;\n // solhint-enable var-name-mixedcase\n\n constructor (address _exchange, bytes memory _zrxAssetData)\n public\n {\n EXCHANGE = IExchange(_exchange);\n ZRX_ASSET_DATA = _zrxAssetData;\n }\n\n /// @dev Fetches information for order and maker/taker of order.\n /// @param order The order structure.\n /// @param takerAddress Address that will be filling the order.\n /// @return OrderInfo and TraderInfo instances for given order.\n function getOrderAndTraderInfo(LibOrder.Order memory order, address takerAddress)\n public\n view\n returns (LibOrder.OrderInfo memory orderInfo, TraderInfo memory traderInfo)\n {\n orderInfo = EXCHANGE.getOrderInfo(order);\n traderInfo = getTraderInfo(order, takerAddress);\n return (orderInfo, traderInfo);\n }\n\n /// @dev Fetches information for all passed in orders and the makers/takers of each order.\n /// @param orders Array of order specifications.\n /// @param takerAddresses Array of taker addresses corresponding to each order.\n /// @return Arrays of OrderInfo and TraderInfo instances that correspond to each order.\n function getOrdersAndTradersInfo(LibOrder.Order[] memory orders, address[] memory takerAddresses)\n public\n view\n returns (LibOrder.OrderInfo[] memory ordersInfo, TraderInfo[] memory tradersInfo)\n {\n ordersInfo = EXCHANGE.getOrdersInfo(orders);\n tradersInfo = getTradersInfo(orders, takerAddresses);\n return (ordersInfo, tradersInfo);\n }\n\n /// @dev Fetches balance and allowances for maker and taker of order.\n /// @param order The order structure.\n /// @param takerAddress Address that will be filling the order.\n /// @return Balances and allowances of maker and taker of order.\n function getTraderInfo(LibOrder.Order memory order, address takerAddress)\n public\n view\n returns (TraderInfo memory traderInfo)\n {\n (traderInfo.makerBalance, traderInfo.makerAllowance) = getBalanceAndAllowance(order.makerAddress, order.makerAssetData);\n (traderInfo.takerBalance, traderInfo.takerAllowance) = getBalanceAndAllowance(takerAddress, order.takerAssetData);\n bytes memory zrxAssetData = ZRX_ASSET_DATA;\n (traderInfo.makerZrxBalance, traderInfo.makerZrxAllowance) = getBalanceAndAllowance(order.makerAddress, zrxAssetData);\n (traderInfo.takerZrxBalance, traderInfo.takerZrxAllowance) = getBalanceAndAllowance(takerAddress, zrxAssetData);\n return traderInfo;\n }\n\n /// @dev Fetches balances and allowances of maker and taker for each provided order.\n /// @param orders Array of order specifications.\n /// @param takerAddresses Array of taker addresses corresponding to each order.\n /// @return Array of balances and allowances for maker and taker of each order.\n function getTradersInfo(LibOrder.Order[] memory orders, address[] memory takerAddresses)\n public\n view\n returns (TraderInfo[] memory)\n {\n uint256 ordersLength = orders.length;\n TraderInfo[] memory tradersInfo = new TraderInfo[](ordersLength);\n for (uint256 i = 0; i != ordersLength; i++) {\n tradersInfo[i] = getTraderInfo(orders[i], takerAddresses[i]);\n }\n return tradersInfo;\n }\n\n /// @dev Fetches token balances and allowances of an address to given assetProxy. Supports ERC20 and ERC721.\n /// @param target Address to fetch balances and allowances of.\n /// @param assetData Encoded data that can be decoded by a specified proxy contract when transferring asset.\n /// @return Balance of asset and allowance set to given proxy of asset.\n /// For ERC721 tokens, these values will always be 1 or 0.\n function getBalanceAndAllowance(address target, bytes memory assetData)\n public\n view\n returns (uint256 balance, uint256 allowance)\n {\n bytes4 assetProxyId = assetData.readBytes4(0);\n address token = assetData.readAddress(16);\n address assetProxy = EXCHANGE.getAssetProxy(assetProxyId);\n\n if (assetProxyId == ERC20_DATA_ID) {\n // Query balance\n balance = IERC20Token(token).balanceOf(target);\n\n // Query allowance\n allowance = IERC20Token(token).allowance(target, assetProxy);\n } else if (assetProxyId == ERC721_DATA_ID) {\n uint256 tokenId = assetData.readUint256(36);\n\n // Query owner of tokenId\n address owner = getERC721TokenOwner(token, tokenId);\n\n // Set balance to 1 if tokenId is owned by target\n balance = target == owner ? 1 : 0;\n\n // Check if ERC721Proxy is approved to spend tokenId\n bool isApproved = IERC721Token(token).isApprovedForAll(target, assetProxy) || IERC721Token(token).getApproved(tokenId) == assetProxy;\n \n // Set alowance to 1 if ERC721Proxy is approved to spend tokenId\n allowance = isApproved ? 1 : 0;\n } else {\n revert(\"UNSUPPORTED_ASSET_PROXY\");\n }\n return (balance, allowance);\n }\n\n /// @dev Calls `token.ownerOf(tokenId)`, but returns a null owner instead of reverting on an unowned token.\n /// @param token Address of ERC721 token.\n /// @param tokenId The identifier for the specific NFT.\n /// @return Owner of tokenId or null address if unowned.\n function getERC721TokenOwner(address token, uint256 tokenId)\n public\n view\n returns (address owner)\n {\n assembly {\n // load free memory pointer\n let cdStart := mload(64)\n\n // bytes4(keccak256(ownerOf(uint256))) = 0x6352211e\n mstore(cdStart, 0x6352211e00000000000000000000000000000000000000000000000000000000)\n mstore(add(cdStart, 4), tokenId)\n\n // staticcall `ownerOf(tokenId)`\n // `ownerOf` will revert if tokenId is not owned\n let success := staticcall(\n gas, // forward all gas\n token, // call token contract\n cdStart, // start of calldata\n 36, // length of input is 36 bytes\n cdStart, // write output over input\n 32 // size of output is 32 bytes\n )\n\n // Success implies that tokenId is owned\n // Copy owner from return data if successful\n if success {\n owner := mload(cdStart)\n } \n }\n\n // Owner initialized to address(0), no need to modify if call is unsuccessful\n return owner;\n }\n}\n", + "2.0.0/extensions/OrderValidator/OrderValidator.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 \"../../protocol/Exchange/interfaces/IExchange.sol\";\nimport \"../../protocol/Exchange/libs/LibOrder.sol\";\nimport \"../../tokens/ERC20Token/IERC20Token.sol\";\nimport \"../../tokens/ERC721Token/IERC721Token.sol\";\nimport \"../../utils/LibBytes/LibBytes.sol\";\n\n\ncontract OrderValidator {\n\n bytes4 constant internal ERC20_DATA_ID = bytes4(keccak256(\"ERC20Token(address)\"));\n bytes4 constant internal ERC721_DATA_ID = bytes4(keccak256(\"ERC721Token(address,uint256)\"));\n\n using LibBytes for bytes;\n\n struct TraderInfo {\n uint256 makerBalance; // Maker's balance of makerAsset\n uint256 makerAllowance; // Maker's allowance to corresponding AssetProxy\n uint256 takerBalance; // Taker's balance of takerAsset\n uint256 takerAllowance; // Taker's allowance to corresponding AssetProxy\n uint256 makerZrxBalance; // Maker's balance of ZRX\n uint256 makerZrxAllowance; // Maker's allowance of ZRX to ERC20Proxy\n uint256 takerZrxBalance; // Taker's balance of ZRX\n uint256 takerZrxAllowance; // Taker's allowance of ZRX to ERC20Proxy\n }\n\n // solhint-disable var-name-mixedcase\n IExchange internal EXCHANGE;\n bytes internal ZRX_ASSET_DATA;\n // solhint-enable var-name-mixedcase\n\n constructor (address _exchange, bytes memory _zrxAssetData)\n public\n {\n EXCHANGE = IExchange(_exchange);\n ZRX_ASSET_DATA = _zrxAssetData;\n }\n\n /// @dev Fetches information for order and maker/taker of order.\n /// @param order The order structure.\n /// @param takerAddress Address that will be filling the order.\n /// @return OrderInfo and TraderInfo instances for given order.\n function getOrderAndTraderInfo(LibOrder.Order memory order, address takerAddress)\n public\n view\n returns (LibOrder.OrderInfo memory orderInfo, TraderInfo memory traderInfo)\n {\n orderInfo = EXCHANGE.getOrderInfo(order);\n traderInfo = getTraderInfo(order, takerAddress);\n return (orderInfo, traderInfo);\n }\n\n /// @dev Fetches information for all passed in orders and the makers/takers of each order.\n /// @param orders Array of order specifications.\n /// @param takerAddresses Array of taker addresses corresponding to each order.\n /// @return Arrays of OrderInfo and TraderInfo instances that correspond to each order.\n function getOrdersAndTradersInfo(LibOrder.Order[] memory orders, address[] memory takerAddresses)\n public\n view\n returns (LibOrder.OrderInfo[] memory ordersInfo, TraderInfo[] memory tradersInfo)\n {\n ordersInfo = EXCHANGE.getOrdersInfo(orders);\n tradersInfo = getTradersInfo(orders, takerAddresses);\n return (ordersInfo, tradersInfo);\n }\n\n /// @dev Fetches balance and allowances for maker and taker of order.\n /// @param order The order structure.\n /// @param takerAddress Address that will be filling the order.\n /// @return Balances and allowances of maker and taker of order.\n function getTraderInfo(LibOrder.Order memory order, address takerAddress)\n public\n view\n returns (TraderInfo memory traderInfo)\n {\n (traderInfo.makerBalance, traderInfo.makerAllowance) = getBalanceAndAllowance(order.makerAddress, order.makerAssetData);\n (traderInfo.takerBalance, traderInfo.takerAllowance) = getBalanceAndAllowance(takerAddress, order.takerAssetData);\n bytes memory zrxAssetData = ZRX_ASSET_DATA;\n (traderInfo.makerZrxBalance, traderInfo.makerZrxAllowance) = getBalanceAndAllowance(order.makerAddress, zrxAssetData);\n (traderInfo.takerZrxBalance, traderInfo.takerZrxAllowance) = getBalanceAndAllowance(takerAddress, zrxAssetData);\n return traderInfo;\n }\n\n /// @dev Fetches balances and allowances of maker and taker for each provided order.\n /// @param orders Array of order specifications.\n /// @param takerAddresses Array of taker addresses corresponding to each order.\n /// @return Array of balances and allowances for maker and taker of each order.\n function getTradersInfo(LibOrder.Order[] memory orders, address[] memory takerAddresses)\n public\n view\n returns (TraderInfo[] memory)\n {\n uint256 ordersLength = orders.length;\n TraderInfo[] memory tradersInfo = new TraderInfo[](ordersLength);\n for (uint256 i = 0; i != ordersLength; i++) {\n tradersInfo[i] = getTraderInfo(orders[i], takerAddresses[i]);\n }\n return tradersInfo;\n }\n\n /// @dev Fetches token balances and allowances of an address to given assetProxy. Supports ERC20 and ERC721.\n /// @param target Address to fetch balances and allowances of.\n /// @param assetData Encoded data that can be decoded by a specified proxy contract when transferring asset.\n /// @return Balance of asset and allowance set to given proxy of asset.\n /// For ERC721 tokens, these values will always be 1 or 0.\n function getBalanceAndAllowance(address target, bytes memory assetData)\n public\n view\n returns (uint256 balance, uint256 allowance)\n {\n bytes4 assetProxyId = assetData.readBytes4(0);\n address token = assetData.readAddress(16);\n address assetProxy = EXCHANGE.getAssetProxy(assetProxyId);\n\n if (assetProxyId == ERC20_DATA_ID) {\n // Query balance\n balance = IERC20Token(token).balanceOf(target);\n\n // Query allowance\n allowance = IERC20Token(token).allowance(target, assetProxy);\n } else if (assetProxyId == ERC721_DATA_ID) {\n uint256 tokenId = assetData.readUint256(36);\n\n // Query owner of tokenId\n address owner = getERC721TokenOwner(token, tokenId);\n\n // Set balance to 1 if tokenId is owned by target\n balance = target == owner ? 1 : 0;\n\n // Check if ERC721Proxy is approved to spend tokenId\n bool isApproved = IERC721Token(token).isApprovedForAll(target, assetProxy) || IERC721Token(token).getApproved(tokenId) == assetProxy;\n \n // Set alowance to 1 if ERC721Proxy is approved to spend tokenId\n allowance = isApproved ? 1 : 0;\n } else {\n revert(\"UNSUPPORTED_ASSET_PROXY\");\n }\n return (balance, allowance);\n }\n\n /// @dev Fetches token balances and allowances of an address for each given assetProxy. Supports ERC20 and ERC721.\n /// @param target Address to fetch balances and allowances of.\n /// @param assetData Array of encoded byte arrays that can be decoded by a specified proxy contract when transferring asset.\n /// @return Balances and allowances of assets.\n /// For ERC721 tokens, these values will always be 1 or 0.\n function getBalancesAndAllowances(address target, bytes[] memory assetData)\n public\n view\n returns (uint256[] memory, uint256[] memory)\n {\n uint256 length = assetData.length;\n uint256[] memory balances = new uint256[](length);\n uint256[] memory allowances = new uint256[](length);\n for (uint256 i = 0; i != length; i++) {\n (balances[i], allowances[i]) = getBalanceAndAllowance(target, assetData[i]);\n }\n return (balances, allowances);\n }\n\n /// @dev Calls `token.ownerOf(tokenId)`, but returns a null owner instead of reverting on an unowned token.\n /// @param token Address of ERC721 token.\n /// @param tokenId The identifier for the specific NFT.\n /// @return Owner of tokenId or null address if unowned.\n function getERC721TokenOwner(address token, uint256 tokenId)\n public\n view\n returns (address owner)\n {\n assembly {\n // load free memory pointer\n let cdStart := mload(64)\n\n // bytes4(keccak256(ownerOf(uint256))) = 0x6352211e\n mstore(cdStart, 0x6352211e00000000000000000000000000000000000000000000000000000000)\n mstore(add(cdStart, 4), tokenId)\n\n // staticcall `ownerOf(tokenId)`\n // `ownerOf` will revert if tokenId is not owned\n let success := staticcall(\n gas, // forward all gas\n token, // call token contract\n cdStart, // start of calldata\n 36, // length of input is 36 bytes\n cdStart, // write output over input\n 32 // size of output is 32 bytes\n )\n\n // Success implies that tokenId is owned\n // Copy owner from return data if successful\n if success {\n owner := mload(cdStart)\n } \n }\n\n // Owner initialized to address(0), no need to modify if call is unsuccessful\n return owner;\n }\n}\n", + "2.0.0/protocol/AssetProxy/ERC20Proxy.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 \"../../utils/LibBytes/LibBytes.sol\";\nimport \"./MixinAuthorizable.sol\";\n\n\ncontract ERC20Proxy is\n MixinAuthorizable\n{\n // Id of this proxy.\n bytes4 constant internal PROXY_ID = bytes4(keccak256(\"ERC20Token(address)\"));\n \n // solhint-disable-next-line payable-fallback\n function () \n external\n {\n assembly {\n // The first 4 bytes of calldata holds the function selector\n let selector := and(calldataload(0), 0xffffffff00000000000000000000000000000000000000000000000000000000)\n\n // `transferFrom` will be called with the following parameters:\n // assetData Encoded byte array.\n // from Address to transfer asset from.\n // to Address to transfer asset to.\n // amount Amount of asset to transfer.\n // bytes4(keccak256(\"transferFrom(bytes,address,address,uint256)\")) = 0xa85e59e4\n if eq(selector, 0xa85e59e400000000000000000000000000000000000000000000000000000000) {\n\n // To lookup a value in a mapping, we load from the storage location keccak256(k, p),\n // where k is the key left padded to 32 bytes and p is the storage slot\n let start := mload(64)\n mstore(start, and(caller, 0xffffffffffffffffffffffffffffffffffffffff))\n mstore(add(start, 32), authorized_slot)\n\n // Revert if authorized[msg.sender] == false\n if iszero(sload(keccak256(start, 64))) {\n // Revert with `Error(\"SENDER_NOT_AUTHORIZED\")`\n mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)\n mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)\n mstore(64, 0x0000001553454e4445525f4e4f545f415554484f52495a454400000000000000)\n mstore(96, 0)\n revert(0, 100)\n }\n \n /////// Token contract address ///////\n // The token address is found as follows:\n // * It is stored at offset 4 in `assetData` contents.\n // * This is stored at offset 32 from `assetData`.\n // * The offset to `assetData` from Params is stored at offset\n // 4 in calldata.\n // * The offset of Params in calldata is 4.\n // So we read location 4 and add 32 + 4 + 4 to it.\n let token := calldataload(add(calldataload(4), 40))\n \n /////// Setup Header Area ///////\n // This area holds the 4-byte `transferFrom` selector.\n // Any trailing data in transferFromSelector will be\n // overwritten in the next `mstore` call.\n mstore(0, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\n \n /////// Setup Params Area ///////\n // We copy the fields `from`, `to` and `amount` in bulk\n // from our own calldata to the new calldata.\n calldatacopy(4, 36, 96)\n\n /////// Call `token.transferFrom` using the calldata ///////\n let success := call(\n gas, // forward all gas\n token, // call address of token contract\n 0, // don't send any ETH\n 0, // pointer to start of input\n 100, // length of input\n 0, // write output over input\n 32 // output size should be 32 bytes\n )\n\n /////// Check return data. ///////\n // If there is no return data, we assume the token incorrectly\n // does not return a bool. In this case we expect it to revert\n // on failure, which was handled above.\n // If the token does return data, we require that it is a single\n // nonzero 32 bytes value.\n // So the transfer succeeded if the call succeeded and either\n // returned nothing, or returned a non-zero 32 byte value. \n success := and(success, or(\n iszero(returndatasize),\n and(\n eq(returndatasize, 32),\n gt(mload(0), 0)\n )\n ))\n if success {\n return(0, 0)\n }\n \n // Revert with `Error(\"TRANSFER_FAILED\")`\n mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)\n mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)\n mstore(64, 0x0000000f5452414e534645525f4641494c454400000000000000000000000000)\n mstore(96, 0)\n revert(0, 100)\n }\n\n // Revert if undefined function is called\n revert(0, 0)\n }\n }\n\n /// @dev Gets the proxy id associated with the proxy address.\n /// @return Proxy id.\n function getProxyId()\n external\n pure\n returns (bytes4)\n {\n return PROXY_ID;\n }\n}\n", + "2.0.0/protocol/AssetProxy/ERC721Proxy.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 \"../../utils/LibBytes/LibBytes.sol\";\nimport \"./MixinAuthorizable.sol\";\n\n\ncontract ERC721Proxy is\n MixinAuthorizable\n{\n // Id of this proxy.\n bytes4 constant internal PROXY_ID = bytes4(keccak256(\"ERC721Token(address,uint256)\"));\n\n // solhint-disable-next-line payable-fallback\n function () \n external\n {\n assembly {\n // The first 4 bytes of calldata holds the function selector\n let selector := and(calldataload(0), 0xffffffff00000000000000000000000000000000000000000000000000000000)\n\n // `transferFrom` will be called with the following parameters:\n // assetData Encoded byte array.\n // from Address to transfer asset from.\n // to Address to transfer asset to.\n // amount Amount of asset to transfer.\n // bytes4(keccak256(\"transferFrom(bytes,address,address,uint256)\")) = 0xa85e59e4\n if eq(selector, 0xa85e59e400000000000000000000000000000000000000000000000000000000) {\n\n // To lookup a value in a mapping, we load from the storage location keccak256(k, p),\n // where k is the key left padded to 32 bytes and p is the storage slot\n let start := mload(64)\n mstore(start, and(caller, 0xffffffffffffffffffffffffffffffffffffffff))\n mstore(add(start, 32), authorized_slot)\n\n // Revert if authorized[msg.sender] == false\n if iszero(sload(keccak256(start, 64))) {\n // Revert with `Error(\"SENDER_NOT_AUTHORIZED\")`\n mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)\n mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)\n mstore(64, 0x0000001553454e4445525f4e4f545f415554484f52495a454400000000000000)\n mstore(96, 0)\n revert(0, 100)\n }\n\n // `transferFrom`.\n // The function is marked `external`, so no abi decodeding is done for\n // us. Instead, we expect the `calldata` memory to contain the\n // following:\n //\n // | Area | Offset | Length | Contents |\n // |----------|--------|---------|-------------------------------------|\n // | Header | 0 | 4 | function selector |\n // | Params | | 4 * 32 | function parameters: |\n // | | 4 | | 1. offset to assetData (*) |\n // | | 36 | | 2. from |\n // | | 68 | | 3. to |\n // | | 100 | | 4. amount |\n // | Data | | | assetData: |\n // | | 132 | 32 | assetData Length |\n // | | 164 | ** | assetData Contents |\n //\n // (*): offset is computed from start of function parameters, so offset\n // by an additional 4 bytes in the calldata.\n //\n // WARNING: The ABIv2 specification allows additional padding between\n // the Params and Data section. This will result in a larger\n // offset to assetData.\n\n // Asset data itself is encoded as follows:\n //\n // | Area | Offset | Length | Contents |\n // |----------|--------|---------|-------------------------------------|\n // | Header | 0 | 4 | function selector |\n // | Params | | 2 * 32 | function parameters: |\n // | | 4 | 12 + 20 | 1. token address |\n // | | 36 | | 2. tokenId |\n \n // We construct calldata for the `token.transferFrom` ABI.\n // The layout of this calldata is in the table below.\n // \n // | Area | Offset | Length | Contents |\n // |----------|--------|---------|-------------------------------------|\n // | Header | 0 | 4 | function selector |\n // | Params | | 3 * 32 | function parameters: |\n // | | 4 | | 1. from |\n // | | 36 | | 2. to |\n // | | 68 | | 3. tokenId |\n\n // There exists only 1 of each token.\n // require(amount == 1, \"INVALID_AMOUNT\")\n if sub(calldataload(100), 1) {\n // Revert with `Error(\"INVALID_AMOUNT\")`\n mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)\n mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)\n mstore(64, 0x0000000e494e56414c49445f414d4f554e540000000000000000000000000000)\n mstore(96, 0)\n revert(0, 100)\n }\n\n /////// Setup Header Area ///////\n // This area holds the 4-byte `transferFrom` selector.\n // Any trailing data in transferFromSelector will be\n // overwritten in the next `mstore` call.\n mstore(0, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\n \n /////// Setup Params Area ///////\n // We copy the fields `from` and `to` in bulk\n // from our own calldata to the new calldata.\n calldatacopy(4, 36, 64)\n\n // Copy `tokenId` field from our own calldata to the new calldata.\n let assetDataOffset := calldataload(4)\n calldatacopy(68, add(assetDataOffset, 72), 32)\n\n /////// Call `token.transferFrom` using the calldata ///////\n let token := calldataload(add(assetDataOffset, 40))\n let success := call(\n gas, // forward all gas\n token, // call address of token contract\n 0, // don't send any ETH\n 0, // pointer to start of input\n 100, // length of input\n 0, // write output to null\n 0 // output size is 0 bytes\n )\n if success {\n return(0, 0)\n }\n \n // Revert with `Error(\"TRANSFER_FAILED\")`\n mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)\n mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)\n mstore(64, 0x0000000f5452414e534645525f4641494c454400000000000000000000000000)\n mstore(96, 0)\n revert(0, 100)\n }\n\n // Revert if undefined function is called\n revert(0, 0)\n }\n }\n\n /// @dev Gets the proxy id associated with the proxy address.\n /// @return Proxy id.\n function getProxyId()\n external\n pure\n returns (bytes4)\n {\n return PROXY_ID;\n }\n}\n", + "2.0.0/protocol/AssetProxy/MixinAuthorizable.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 \"../../utils/Ownable/Ownable.sol\";\nimport \"./mixins/MAuthorizable.sol\";\n\n\ncontract MixinAuthorizable is\n Ownable,\n MAuthorizable\n{\n\n /// @dev Only authorized addresses can invoke functions with this modifier.\n modifier onlyAuthorized {\n require(\n authorized[msg.sender],\n \"SENDER_NOT_AUTHORIZED\"\n );\n _;\n }\n\n mapping (address => bool) public authorized;\n address[] public authorities;\n\n /// @dev Authorizes an address.\n /// @param target Address to authorize.\n function addAuthorizedAddress(address target)\n external\n onlyOwner\n {\n require(\n !authorized[target],\n \"TARGET_ALREADY_AUTHORIZED\"\n );\n\n authorized[target] = true;\n authorities.push(target);\n emit AuthorizedAddressAdded(target, msg.sender);\n }\n\n /// @dev Removes authorizion of an address.\n /// @param target Address to remove authorization from.\n function removeAuthorizedAddress(address target)\n external\n onlyOwner\n {\n require(\n authorized[target],\n \"TARGET_NOT_AUTHORIZED\"\n );\n\n delete authorized[target];\n for (uint256 i = 0; i < authorities.length; i++) {\n if (authorities[i] == target) {\n authorities[i] = authorities[authorities.length - 1];\n authorities.length -= 1;\n break;\n }\n }\n emit AuthorizedAddressRemoved(target, msg.sender);\n }\n\n /// @dev Removes authorizion of an address.\n /// @param target Address to remove authorization from.\n /// @param index Index of target in authorities array.\n function removeAuthorizedAddressAtIndex(\n address target,\n uint256 index\n )\n external\n onlyOwner\n {\n require(\n authorized[target],\n \"TARGET_NOT_AUTHORIZED\"\n );\n require(\n index < authorities.length,\n \"INDEX_OUT_OF_BOUNDS\"\n );\n require(\n authorities[index] == target,\n \"AUTHORIZED_ADDRESS_MISMATCH\"\n );\n\n delete authorized[target];\n authorities[index] = authorities[authorities.length - 1];\n authorities.length -= 1;\n emit AuthorizedAddressRemoved(target, msg.sender);\n }\n\n /// @dev Gets all authorized addresses.\n /// @return Array of authorized addresses.\n function getAuthorizedAddresses()\n external\n view\n returns (address[] memory)\n {\n return authorities;\n }\n}\n", "2.0.0/protocol/AssetProxy/interfaces/IAssetProxy.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 \"./IAuthorizable.sol\";\n\n\ncontract IAssetProxy is\n IAuthorizable\n{\n\n /// @dev Transfers assets. Either succeeds or throws.\n /// @param assetData Byte array encoded for the respective asset proxy.\n /// @param from Address to transfer asset from.\n /// @param to Address to transfer asset to.\n /// @param amount Amount of asset to transfer.\n function transferFrom(\n bytes assetData,\n address from,\n address to,\n uint256 amount\n )\n external;\n \n /// @dev Gets the proxy id associated with the proxy address.\n /// @return Proxy id.\n function getProxyId()\n external\n pure\n returns (bytes4);\n}\n", "2.0.0/protocol/AssetProxy/interfaces/IAuthorizable.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 \"../../../utils/Ownable/IOwnable.sol\";\n\n\ncontract IAuthorizable is\n IOwnable\n{\n\n /// @dev Authorizes an address.\n /// @param target Address to authorize.\n function addAuthorizedAddress(address target)\n external;\n\n /// @dev Removes authorizion of an address.\n /// @param target Address to remove authorization from.\n function removeAuthorizedAddress(address target)\n external;\n\n /// @dev Removes authorizion of an address.\n /// @param target Address to remove authorization from.\n /// @param index Index of target in authorities array.\n function removeAuthorizedAddressAtIndex(\n address target,\n uint256 index\n )\n external;\n \n /// @dev Gets all authorized addresses.\n /// @return Array of authorized addresses.\n function getAuthorizedAddresses()\n external\n view\n returns (address[] memory);\n}\n", + "2.0.0/protocol/AssetProxy/mixins/MAuthorizable.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 \"../interfaces/IAuthorizable.sol\";\n\n\ncontract MAuthorizable is\n IAuthorizable\n{\n\n // Event logged when a new address is authorized.\n event AuthorizedAddressAdded(\n address indexed target,\n address indexed caller\n );\n\n // Event logged when a currently authorized address is unauthorized.\n event AuthorizedAddressRemoved(\n address indexed target,\n address indexed caller\n );\n\n /// @dev Only authorized addresses can invoke functions with this modifier.\n modifier onlyAuthorized { revert(); _; }\n}\n", "2.0.0/protocol/Exchange/Exchange.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 \"./libs/LibConstants.sol\";\nimport \"./MixinExchangeCore.sol\";\nimport \"./MixinSignatureValidator.sol\";\nimport \"./MixinWrapperFunctions.sol\";\nimport \"./MixinAssetProxyDispatcher.sol\";\nimport \"./MixinTransactions.sol\";\nimport \"./MixinMatchOrders.sol\";\n\n\n// solhint-disable no-empty-blocks\ncontract Exchange is\n MixinExchangeCore,\n MixinMatchOrders,\n MixinSignatureValidator,\n MixinTransactions,\n MixinAssetProxyDispatcher,\n MixinWrapperFunctions\n{\n\n string constant public VERSION = \"2.0.1-alpha\";\n\n // Mixins are instantiated in the order they are inherited\n constructor (bytes memory _zrxAssetData)\n public\n LibConstants(_zrxAssetData) // @TODO: Remove when we deploy.\n MixinExchangeCore()\n MixinMatchOrders()\n MixinSignatureValidator()\n MixinTransactions()\n MixinAssetProxyDispatcher()\n MixinWrapperFunctions()\n {}\n}\n", - "2.0.0/protocol/Exchange/MixinAssetProxyDispatcher.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 \"../../utils/Ownable/Ownable.sol\";\nimport \"../../utils/LibBytes/LibBytes.sol\";\nimport \"./mixins/MAssetProxyDispatcher.sol\";\nimport \"../AssetProxy/interfaces/IAssetProxy.sol\";\n\n\ncontract MixinAssetProxyDispatcher is\n Ownable,\n MAssetProxyDispatcher\n{\n using LibBytes for bytes;\n \n // Mapping from Asset Proxy Id's to their respective Asset Proxy\n mapping (bytes4 => IAssetProxy) public assetProxies;\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 onlyOwner\n {\n IAssetProxy assetProxyContract = IAssetProxy(assetProxy);\n\n // Ensure that no asset proxy exists with current id.\n bytes4 assetProxyId = assetProxyContract.getProxyId();\n address currentAssetProxy = assetProxies[assetProxyId];\n require(\n currentAssetProxy == address(0),\n \"ASSET_PROXY_ALREADY_EXISTS\"\n );\n\n // Add asset proxy and log registration.\n assetProxies[assetProxyId] = assetProxyContract;\n emit AssetProxyRegistered(\n assetProxyId,\n assetProxy\n );\n }\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 return assetProxies[assetProxyId];\n }\n\n /// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws.\n /// @param assetData Byte array encoded for the asset.\n /// @param from Address to transfer token from.\n /// @param to Address to transfer token to.\n /// @param amount Amount of token to transfer.\n function dispatchTransferFrom(\n bytes memory assetData,\n address from,\n address to,\n uint256 amount\n )\n internal\n {\n // Do nothing if no amount should be transferred.\n if (amount > 0) {\n // Ensure assetData length is valid\n require(\n assetData.length > 3,\n \"LENGTH_GREATER_THAN_3_REQUIRED\"\n );\n \n // Lookup assetProxy\n bytes4 assetProxyId;\n assembly {\n assetProxyId := and(mload(\n add(assetData, 32)),\n 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000\n )\n }\n address assetProxy = assetProxies[assetProxyId];\n\n // Ensure that assetProxy exists\n require(\n assetProxy != address(0),\n \"ASSET_PROXY_DOES_NOT_EXIST\"\n );\n \n // We construct calldata for the `assetProxy.transferFrom` ABI.\n // The layout of this calldata is in the table below.\n // \n // | Area | Offset | Length | Contents |\n // | -------- |--------|---------|-------------------------------------------- |\n // | Header | 0 | 4 | function selector |\n // | Params | | 4 * 32 | function parameters: |\n // | | 4 | | 1. offset to assetData (*) |\n // | | 36 | | 2. from |\n // | | 68 | | 3. to |\n // | | 100 | | 4. amount |\n // | Data | | | assetData: |\n // | | 132 | 32 | assetData Length |\n // | | 164 | ** | assetData Contents |\n\n assembly {\n /////// Setup State ///////\n // `cdStart` is the start of the calldata for `assetProxy.transferFrom` (equal to free memory ptr).\n let cdStart := mload(64)\n // `dataAreaLength` is the total number of words needed to store `assetData`\n // As-per the ABI spec, this value is padded up to the nearest multiple of 32,\n // and includes 32-bytes for length.\n let dataAreaLength := and(add(mload(assetData), 63), 0xFFFFFFFFFFFE0)\n // `cdEnd` is the end of the calldata for `assetProxy.transferFrom`.\n let cdEnd := add(cdStart, add(132, dataAreaLength))\n\n \n /////// Setup Header Area ///////\n // This area holds the 4-byte `transferFromSelector`.\n // bytes4(keccak256(\"transferFrom(bytes,address,address,uint256)\")) = 0xa85e59e4\n mstore(cdStart, 0xa85e59e400000000000000000000000000000000000000000000000000000000)\n \n /////// Setup Params Area ///////\n // Each parameter is padded to 32-bytes. The entire Params Area is 128 bytes.\n // Notes:\n // 1. The offset to `assetData` is the length of the Params Area (128 bytes).\n // 2. A 20-byte mask is applied to addresses to zero-out the unused bytes.\n mstore(add(cdStart, 4), 128)\n mstore(add(cdStart, 36), and(from, 0xffffffffffffffffffffffffffffffffffffffff))\n mstore(add(cdStart, 68), and(to, 0xffffffffffffffffffffffffffffffffffffffff))\n mstore(add(cdStart, 100), amount)\n \n /////// Setup Data Area ///////\n // This area holds `assetData`.\n let dataArea := add(cdStart, 132)\n // solhint-disable-next-line no-empty-blocks\n for {} lt(dataArea, cdEnd) {} {\n mstore(dataArea, mload(assetData))\n dataArea := add(dataArea, 32)\n assetData := add(assetData, 32)\n }\n\n /////// Call `assetProxy.transferFrom` using the constructed calldata ///////\n let success := call(\n gas, // forward all gas\n assetProxy, // call address of asset proxy\n 0, // don't send any ETH\n cdStart, // pointer to start of input\n sub(cdEnd, cdStart), // length of input \n cdStart, // write output over input\n 512 // reserve 512 bytes for output\n )\n if iszero(success) {\n revert(cdStart, returndatasize())\n }\n }\n }\n }\n}\n", - "2.0.0/protocol/Exchange/MixinExchangeCore.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 \"./libs/LibConstants.sol\";\nimport \"./libs/LibFillResults.sol\";\nimport \"./libs/LibOrder.sol\";\nimport \"./libs/LibMath.sol\";\nimport \"./mixins/MExchangeCore.sol\";\nimport \"./mixins/MSignatureValidator.sol\";\nimport \"./mixins/MTransactions.sol\";\nimport \"./mixins/MAssetProxyDispatcher.sol\";\n\n\ncontract MixinExchangeCore is\n LibConstants,\n LibMath,\n LibOrder,\n LibFillResults,\n MAssetProxyDispatcher,\n MExchangeCore,\n MSignatureValidator,\n MTransactions\n{\n // Mapping of orderHash => amount of takerAsset already bought by maker\n mapping (bytes32 => uint256) public filled;\n\n // Mapping of orderHash => cancelled\n mapping (bytes32 => bool) public cancelled;\n\n // Mapping of makerAddress => senderAddress => lowest salt an order can have in order to be fillable\n // Orders with specified senderAddress and with a salt less than their epoch are considered cancelled\n mapping (address => mapping (address => uint256)) public orderEpoch;\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 address makerAddress = getCurrentContextAddress();\n // If this function is called via `executeTransaction`, we only update the orderEpoch for the makerAddress/msg.sender combination.\n // This allows external filter contracts to add rules to how orders are cancelled via this function.\n address senderAddress = makerAddress == msg.sender ? address(0) : msg.sender;\n\n // orderEpoch is initialized to 0, so to cancelUpTo we need salt + 1\n uint256 newOrderEpoch = targetOrderEpoch + 1; \n uint256 oldOrderEpoch = orderEpoch[makerAddress][senderAddress];\n\n // Ensure orderEpoch is monotonically increasing\n require(\n newOrderEpoch > oldOrderEpoch, \n \"INVALID_NEW_ORDER_EPOCH\"\n );\n\n // Update orderEpoch\n orderEpoch[makerAddress][senderAddress] = newOrderEpoch;\n emit CancelUpTo(makerAddress, senderAddress, newOrderEpoch);\n }\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 Order memory order,\n uint256 takerAssetFillAmount,\n bytes memory signature\n )\n public\n returns (FillResults memory fillResults)\n {\n // Fetch order info\n OrderInfo memory orderInfo = getOrderInfo(order);\n\n // Fetch taker address\n address takerAddress = getCurrentContextAddress();\n\n // Get amount of takerAsset to fill\n uint256 remainingTakerAssetAmount = safeSub(order.takerAssetAmount, orderInfo.orderTakerAssetFilledAmount);\n uint256 takerAssetFilledAmount = min256(takerAssetFillAmount, remainingTakerAssetAmount);\n\n // Validate context\n assertValidFill(\n order,\n orderInfo,\n takerAddress,\n takerAssetFillAmount,\n takerAssetFilledAmount,\n signature\n );\n\n // Compute proportional fill amounts\n fillResults = calculateFillResults(order, takerAssetFilledAmount);\n\n // Update exchange internal state\n updateFilledState(\n order,\n takerAddress,\n orderInfo.orderHash,\n orderInfo.orderTakerAssetFilledAmount,\n fillResults\n );\n \n // Settle order\n settleOrder(order, takerAddress, fillResults);\n\n return fillResults;\n }\n\n /// @dev After calling, the order can not be filled anymore.\n /// Throws if order is invalid or sender does not have permission to cancel.\n /// @param order Order to cancel. Order must be OrderStatus.FILLABLE.\n function cancelOrder(Order memory order)\n public\n {\n // Fetch current order status\n OrderInfo memory orderInfo = getOrderInfo(order);\n\n // Validate context\n assertValidCancel(order, orderInfo);\n\n // Perform cancel\n updateCancelledState(order, orderInfo.orderHash);\n }\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(Order memory order)\n public\n view\n returns (OrderInfo memory orderInfo)\n {\n // Compute the order hash\n orderInfo.orderHash = getOrderHash(order);\n\n // Fetch filled amount\n orderInfo.orderTakerAssetFilledAmount = filled[orderInfo.orderHash];\n\n // If order.makerAssetAmount is zero, we also reject the order.\n // While the Exchange contract handles them correctly, they create\n // edge cases in the supporting infrastructure because they have\n // an 'infinite' price when computed by a simple division.\n if (order.makerAssetAmount == 0) {\n orderInfo.orderStatus = uint8(OrderStatus.INVALID_MAKER_ASSET_AMOUNT);\n return orderInfo;\n }\n\n // If order.takerAssetAmount is zero, then the order will always\n // be considered filled because 0 == takerAssetAmount == orderTakerAssetFilledAmount\n // Instead of distinguishing between unfilled and filled zero taker\n // amount orders, we choose not to support them.\n if (order.takerAssetAmount == 0) {\n orderInfo.orderStatus = uint8(OrderStatus.INVALID_TAKER_ASSET_AMOUNT);\n return orderInfo;\n }\n\n // Validate order availability\n if (orderInfo.orderTakerAssetFilledAmount >= order.takerAssetAmount) {\n orderInfo.orderStatus = uint8(OrderStatus.FULLY_FILLED);\n return orderInfo;\n }\n\n // Validate order expiration\n // solhint-disable-next-line not-rely-on-time\n if (block.timestamp >= order.expirationTimeSeconds) {\n orderInfo.orderStatus = uint8(OrderStatus.EXPIRED);\n return orderInfo;\n }\n\n // Check if order has been cancelled\n if (cancelled[orderInfo.orderHash]) {\n orderInfo.orderStatus = uint8(OrderStatus.CANCELLED);\n return orderInfo;\n }\n if (orderEpoch[order.makerAddress][order.senderAddress] > order.salt) {\n orderInfo.orderStatus = uint8(OrderStatus.CANCELLED);\n return orderInfo;\n }\n\n // All other statuses are ruled out: order is Fillable\n orderInfo.orderStatus = uint8(OrderStatus.FILLABLE);\n return orderInfo;\n }\n\n /// @dev Updates state with results of a fill order.\n /// @param order that was filled.\n /// @param takerAddress Address of taker who filled the order.\n /// @param orderTakerAssetFilledAmount Amount of order already filled.\n function updateFilledState(\n Order memory order,\n address takerAddress,\n bytes32 orderHash,\n uint256 orderTakerAssetFilledAmount,\n FillResults memory fillResults\n )\n internal\n {\n // Update state\n filled[orderHash] = safeAdd(orderTakerAssetFilledAmount, fillResults.takerAssetFilledAmount);\n\n // Log order\n emit Fill(\n order.makerAddress,\n order.feeRecipientAddress,\n takerAddress,\n msg.sender,\n fillResults.makerAssetFilledAmount,\n fillResults.takerAssetFilledAmount,\n fillResults.makerFeePaid,\n fillResults.takerFeePaid,\n orderHash,\n order.makerAssetData,\n order.takerAssetData\n );\n }\n\n /// @dev Updates state with results of cancelling an order.\n /// State is only updated if the order is currently fillable.\n /// Otherwise, updating state would have no effect.\n /// @param order that was cancelled.\n /// @param orderHash Hash of order that was cancelled.\n function updateCancelledState(\n Order memory order,\n bytes32 orderHash\n )\n internal\n {\n // Perform cancel\n cancelled[orderHash] = true;\n\n // Log cancel\n emit Cancel(\n order.makerAddress,\n order.feeRecipientAddress,\n msg.sender,\n orderHash,\n order.makerAssetData,\n order.takerAssetData\n );\n }\n\n /// @dev Validates context for fillOrder. Succeeds or throws.\n /// @param order to be filled.\n /// @param orderInfo OrderStatus, orderHash, and amount already filled of order.\n /// @param takerAddress Address of order taker.\n /// @param takerAssetFillAmount Desired amount of order to fill by taker.\n /// @param takerAssetFilledAmount Amount of takerAsset that will be filled.\n /// @param signature Proof that the orders was created by its maker.\n function assertValidFill(\n Order memory order,\n OrderInfo memory orderInfo,\n address takerAddress,\n uint256 takerAssetFillAmount,\n uint256 takerAssetFilledAmount,\n bytes memory signature\n )\n internal\n view\n {\n // An order can only be filled if its status is FILLABLE.\n require(\n orderInfo.orderStatus == uint8(OrderStatus.FILLABLE),\n \"ORDER_UNFILLABLE\"\n );\n\n // Revert if fill amount is invalid\n require(\n takerAssetFillAmount != 0,\n \"INVALID_TAKER_AMOUNT\"\n );\n\n // Validate sender is allowed to fill this order\n if (order.senderAddress != address(0)) {\n require(\n order.senderAddress == msg.sender,\n \"INVALID_SENDER\"\n );\n }\n\n // Validate taker is allowed to fill this order\n if (order.takerAddress != address(0)) {\n require(\n order.takerAddress == takerAddress,\n \"INVALID_TAKER\"\n );\n }\n\n // Validate Maker signature (check only if first time seen)\n if (orderInfo.orderTakerAssetFilledAmount == 0) {\n require(\n isValidSignature(\n orderInfo.orderHash,\n order.makerAddress,\n signature\n ),\n \"INVALID_ORDER_SIGNATURE\"\n );\n }\n\n // Validate fill order rounding\n require(\n !isRoundingError(\n takerAssetFilledAmount,\n order.takerAssetAmount,\n order.makerAssetAmount\n ),\n \"ROUNDING_ERROR\"\n );\n }\n\n /// @dev Validates context for cancelOrder. Succeeds or throws.\n /// @param order to be cancelled.\n /// @param orderInfo OrderStatus, orderHash, and amount already filled of order.\n function assertValidCancel(\n Order memory order,\n OrderInfo memory orderInfo\n )\n internal\n view\n {\n // Ensure order is valid\n // An order can only be cancelled if its status is FILLABLE.\n require(\n orderInfo.orderStatus == uint8(OrderStatus.FILLABLE),\n \"ORDER_UNFILLABLE\"\n );\n\n // Validate sender is allowed to cancel this order\n if (order.senderAddress != address(0)) {\n require(\n order.senderAddress == msg.sender,\n \"INVALID_SENDER\"\n );\n }\n\n // Validate transaction signed by maker\n address makerAddress = getCurrentContextAddress();\n require(\n order.makerAddress == makerAddress,\n \"INVALID_MAKER\"\n );\n }\n\n /// @dev Calculates amounts filled and fees paid by maker and taker.\n /// @param order to be filled.\n /// @param takerAssetFilledAmount Amount of takerAsset that will be filled.\n /// @return fillResults Amounts filled and fees paid by maker and taker.\n function calculateFillResults(\n Order memory order,\n uint256 takerAssetFilledAmount\n )\n internal\n pure\n returns (FillResults memory fillResults)\n {\n // Compute proportional transfer amounts\n fillResults.takerAssetFilledAmount = takerAssetFilledAmount;\n fillResults.makerAssetFilledAmount = getPartialAmount(\n takerAssetFilledAmount,\n order.takerAssetAmount,\n order.makerAssetAmount\n );\n fillResults.makerFeePaid = getPartialAmount(\n takerAssetFilledAmount,\n order.takerAssetAmount,\n order.makerFee\n );\n fillResults.takerFeePaid = getPartialAmount(\n takerAssetFilledAmount,\n order.takerAssetAmount,\n order.takerFee\n );\n\n return fillResults;\n }\n\n /// @dev Settles an order by transferring assets between counterparties.\n /// @param order Order struct containing order specifications.\n /// @param takerAddress Address selling takerAsset and buying makerAsset.\n /// @param fillResults Amounts to be filled and fees paid by maker and taker.\n function settleOrder(\n LibOrder.Order memory order,\n address takerAddress,\n LibFillResults.FillResults memory fillResults\n )\n private\n {\n bytes memory zrxAssetData = ZRX_ASSET_DATA;\n dispatchTransferFrom(\n order.makerAssetData,\n order.makerAddress,\n takerAddress,\n fillResults.makerAssetFilledAmount\n );\n dispatchTransferFrom(\n order.takerAssetData,\n takerAddress,\n order.makerAddress,\n fillResults.takerAssetFilledAmount\n );\n dispatchTransferFrom(\n zrxAssetData,\n order.makerAddress,\n order.feeRecipientAddress,\n fillResults.makerFeePaid\n );\n dispatchTransferFrom(\n zrxAssetData,\n takerAddress,\n order.feeRecipientAddress,\n fillResults.takerFeePaid\n );\n }\n}\n", - "2.0.0/protocol/Exchange/MixinMatchOrders.sol": "/*\n Copyright 2018 ZeroEx Intl.\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 http://www.apache.org/licenses/LICENSE-2.0\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 \"./libs/LibConstants.sol\";\nimport \"./libs/LibMath.sol\";\nimport \"./libs/LibOrder.sol\";\nimport \"./libs/LibFillResults.sol\";\nimport \"./mixins/MExchangeCore.sol\";\nimport \"./mixins/MMatchOrders.sol\";\nimport \"./mixins/MTransactions.sol\";\nimport \"./mixins/MAssetProxyDispatcher.sol\";\n\n\ncontract MixinMatchOrders is\n LibConstants,\n LibMath,\n MAssetProxyDispatcher,\n MExchangeCore,\n MMatchOrders,\n MTransactions\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 // We assume that rightOrder.takerAssetData == leftOrder.makerAssetData and rightOrder.makerAssetData == leftOrder.takerAssetData.\n // If this assumption isn't true, the match will fail at signature validation.\n rightOrder.makerAssetData = leftOrder.takerAssetData;\n rightOrder.takerAssetData = leftOrder.makerAssetData;\n\n // Get left & right order info\n LibOrder.OrderInfo memory leftOrderInfo = getOrderInfo(leftOrder);\n LibOrder.OrderInfo memory rightOrderInfo = getOrderInfo(rightOrder);\n\n // Fetch taker address\n address takerAddress = getCurrentContextAddress();\n\n // Either our context is valid or we revert\n assertValidMatch(leftOrder, rightOrder);\n\n // Compute proportional fill amounts\n matchedFillResults = calculateMatchedFillResults(\n leftOrder,\n rightOrder,\n leftOrderInfo.orderTakerAssetFilledAmount,\n rightOrderInfo.orderTakerAssetFilledAmount\n );\n\n // Validate fill contexts\n assertValidFill(\n leftOrder,\n leftOrderInfo,\n takerAddress,\n matchedFillResults.left.takerAssetFilledAmount,\n matchedFillResults.left.takerAssetFilledAmount,\n leftSignature\n );\n assertValidFill(\n rightOrder,\n rightOrderInfo,\n takerAddress,\n matchedFillResults.right.takerAssetFilledAmount,\n matchedFillResults.right.takerAssetFilledAmount,\n rightSignature\n );\n\n // Update exchange state\n updateFilledState(\n leftOrder,\n takerAddress,\n leftOrderInfo.orderHash,\n leftOrderInfo.orderTakerAssetFilledAmount,\n matchedFillResults.left\n );\n updateFilledState(\n rightOrder,\n takerAddress,\n rightOrderInfo.orderHash,\n rightOrderInfo.orderTakerAssetFilledAmount,\n matchedFillResults.right\n );\n \n // Settle matched orders. Succeeds or throws.\n settleMatchedOrders(\n leftOrder,\n rightOrder,\n takerAddress,\n matchedFillResults\n );\n\n return matchedFillResults;\n }\n\n /// @dev Validates context for matchOrders. Succeeds or throws.\n /// @param leftOrder First order to match.\n /// @param rightOrder Second order to match.\n function assertValidMatch(\n LibOrder.Order memory leftOrder,\n LibOrder.Order memory rightOrder\n )\n internal\n pure\n {\n // Make sure there is a profitable spread.\n // There is a profitable spread iff the cost per unit bought (OrderA.MakerAmount/OrderA.TakerAmount) for each order is greater\n // than the profit per unit sold of the matched order (OrderB.TakerAmount/OrderB.MakerAmount).\n // This is satisfied by the equations below:\n // <leftOrder.makerAssetAmount> / <leftOrder.takerAssetAmount> >= <rightOrder.takerAssetAmount> / <rightOrder.makerAssetAmount>\n // AND\n // <rightOrder.makerAssetAmount> / <rightOrder.takerAssetAmount> >= <leftOrder.takerAssetAmount> / <leftOrder.makerAssetAmount>\n // These equations can be combined to get the following:\n require(\n safeMul(leftOrder.makerAssetAmount, rightOrder.makerAssetAmount) >=\n safeMul(leftOrder.takerAssetAmount, rightOrder.takerAssetAmount),\n \"NEGATIVE_SPREAD_REQUIRED\"\n );\n }\n\n /// @dev Calculates fill amounts for the matched orders.\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 leftOrder 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 leftOrderTakerAssetFilledAmount Amount of left order already filled.\n /// @param rightOrderTakerAssetFilledAmount Amount of right order already filled.\n /// @param matchedFillResults Amounts to fill and fees to pay by maker and taker of matched orders.\n function calculateMatchedFillResults(\n LibOrder.Order memory leftOrder,\n LibOrder.Order memory rightOrder,\n uint256 leftOrderTakerAssetFilledAmount,\n uint256 rightOrderTakerAssetFilledAmount\n )\n internal\n pure\n returns (LibFillResults.MatchedFillResults memory matchedFillResults)\n {\n // We settle orders at the exchange rate of the right order.\n // The amount saved by the left maker goes to the taker.\n // Either the left or right order will be fully filled; possibly both.\n // The left order is fully filled iff the right order can sell more than left can buy.\n // That is: the amount required to fill the left order is less than or equal to\n // the amount we can spend from the right order:\n // <leftTakerAssetAmountRemaining> <= <rightTakerAssetAmountRemaining> * <rightMakerToTakerRatio>\n // <leftTakerAssetAmountRemaining> <= <rightTakerAssetAmountRemaining> * <rightOrder.makerAssetAmount> / <rightOrder.takerAssetAmount>\n // <leftTakerAssetAmountRemaining> * <rightOrder.takerAssetAmount> <= <rightTakerAssetAmountRemaining> * <rightOrder.makerAssetAmount>\n uint256 leftTakerAssetAmountRemaining = safeSub(leftOrder.takerAssetAmount, leftOrderTakerAssetFilledAmount);\n uint256 rightTakerAssetAmountRemaining = safeSub(rightOrder.takerAssetAmount, rightOrderTakerAssetFilledAmount);\n uint256 leftTakerAssetFilledAmount;\n uint256 rightTakerAssetFilledAmount;\n if (\n safeMul(leftTakerAssetAmountRemaining, rightOrder.takerAssetAmount) <=\n safeMul(rightTakerAssetAmountRemaining, rightOrder.makerAssetAmount)\n ) {\n // Left order will be fully filled: maximally fill left\n leftTakerAssetFilledAmount = leftTakerAssetAmountRemaining;\n\n // The right order receives an amount proportional to how much was spent.\n rightTakerAssetFilledAmount = getPartialAmount(\n rightOrder.takerAssetAmount,\n rightOrder.makerAssetAmount,\n leftTakerAssetFilledAmount\n );\n } else {\n // Right order will be fully filled: maximally fill right\n rightTakerAssetFilledAmount = rightTakerAssetAmountRemaining;\n\n // The left order receives an amount proportional to how much was spent.\n leftTakerAssetFilledAmount = getPartialAmount(\n rightOrder.makerAssetAmount,\n rightOrder.takerAssetAmount,\n rightTakerAssetFilledAmount\n );\n }\n\n // Calculate fill results for left order\n matchedFillResults.left = calculateFillResults(\n leftOrder,\n leftTakerAssetFilledAmount\n );\n\n // Calculate fill results for right order\n matchedFillResults.right = calculateFillResults(\n rightOrder,\n rightTakerAssetFilledAmount\n );\n\n // Calculate amount given to taker\n matchedFillResults.leftMakerAssetSpreadAmount = safeSub(\n matchedFillResults.left.makerAssetFilledAmount,\n matchedFillResults.right.takerAssetFilledAmount\n );\n\n // Return fill results\n return matchedFillResults;\n }\n\n /// @dev Settles matched order by transferring appropriate funds between order makers, taker, and fee recipient.\n /// @param leftOrder First matched order.\n /// @param rightOrder Second matched order.\n /// @param takerAddress Address that matched the orders. The taker receives the spread between orders as profit.\n /// @param matchedFillResults Struct holding amounts to transfer between makers, taker, and fee recipients.\n function settleMatchedOrders(\n LibOrder.Order memory leftOrder,\n LibOrder.Order memory rightOrder,\n address takerAddress,\n LibFillResults.MatchedFillResults memory matchedFillResults\n )\n private\n {\n bytes memory zrxAssetData = ZRX_ASSET_DATA;\n // Order makers and taker\n dispatchTransferFrom(\n leftOrder.makerAssetData,\n leftOrder.makerAddress,\n rightOrder.makerAddress,\n matchedFillResults.right.takerAssetFilledAmount\n );\n dispatchTransferFrom(\n rightOrder.makerAssetData,\n rightOrder.makerAddress,\n leftOrder.makerAddress,\n matchedFillResults.left.takerAssetFilledAmount\n );\n dispatchTransferFrom(\n leftOrder.makerAssetData,\n leftOrder.makerAddress,\n takerAddress,\n matchedFillResults.leftMakerAssetSpreadAmount\n );\n\n // Maker fees\n dispatchTransferFrom(\n zrxAssetData,\n leftOrder.makerAddress,\n leftOrder.feeRecipientAddress,\n matchedFillResults.left.makerFeePaid\n );\n dispatchTransferFrom(\n zrxAssetData,\n rightOrder.makerAddress,\n rightOrder.feeRecipientAddress,\n matchedFillResults.right.makerFeePaid\n );\n\n // Taker fees\n if (leftOrder.feeRecipientAddress == rightOrder.feeRecipientAddress) {\n dispatchTransferFrom(\n zrxAssetData,\n takerAddress,\n leftOrder.feeRecipientAddress,\n safeAdd(\n matchedFillResults.left.takerFeePaid,\n matchedFillResults.right.takerFeePaid\n )\n );\n } else {\n dispatchTransferFrom(\n zrxAssetData,\n takerAddress,\n leftOrder.feeRecipientAddress,\n matchedFillResults.left.takerFeePaid\n );\n dispatchTransferFrom(\n zrxAssetData,\n takerAddress,\n rightOrder.feeRecipientAddress,\n matchedFillResults.right.takerFeePaid\n );\n }\n }\n}\n", - "2.0.0/protocol/Exchange/MixinSignatureValidator.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 \"../../utils/LibBytes/LibBytes.sol\";\nimport \"./mixins/MSignatureValidator.sol\";\nimport \"./mixins/MTransactions.sol\";\nimport \"./interfaces/IWallet.sol\";\nimport \"./interfaces/IValidator.sol\";\n\n\ncontract MixinSignatureValidator is\n MSignatureValidator,\n MTransactions\n{\n using LibBytes for bytes;\n \n // Mapping of hash => signer => signed\n mapping (bytes32 => mapping (address => bool)) public preSigned;\n\n // Mapping of signer => validator => approved\n mapping (address => mapping (address => bool)) public allowedValidators;\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 require(\n isValidSignature(\n hash,\n signerAddress,\n signature\n ),\n \"INVALID_SIGNATURE\"\n );\n preSigned[hash][signerAddress] = true;\n }\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 address signerAddress = getCurrentContextAddress();\n allowedValidators[signerAddress][validatorAddress] = approval;\n emit SignatureValidatorApproval(\n signerAddress,\n validatorAddress,\n approval\n );\n }\n\n /// @dev Verifies that a hash has been signed by the given signer.\n /// @param hash Any 32 byte hash.\n /// @param signerAddress Address that should have signed the given hash.\n /// @param signature Proof that the hash has been signed by signer.\n /// @return True if the address recovered from the provided signature matches the input signer address.\n function isValidSignature(\n bytes32 hash,\n address signerAddress,\n bytes memory signature\n )\n public\n view\n returns (bool isValid)\n {\n require(\n signature.length > 0,\n \"LENGTH_GREATER_THAN_0_REQUIRED\"\n );\n\n // Pop last byte off of signature byte array.\n uint8 signatureTypeRaw = uint8(signature.popLastByte());\n\n // Ensure signature is supported\n require(\n signatureTypeRaw < uint8(SignatureType.NSignatureTypes),\n \"SIGNATURE_UNSUPPORTED\"\n );\n\n SignatureType signatureType = SignatureType(signatureTypeRaw);\n\n // Variables are not scoped in Solidity.\n uint8 v;\n bytes32 r;\n bytes32 s;\n address recovered;\n\n // Always illegal signature.\n // This is always an implicit option since a signer can create a\n // signature array with invalid type or length. We may as well make\n // it an explicit option. This aids testing and analysis. It is\n // also the initialization value for the enum type.\n if (signatureType == SignatureType.Illegal) {\n revert(\"SIGNATURE_ILLEGAL\");\n\n // Always invalid signature.\n // Like Illegal, this is always implicitly available and therefore\n // offered explicitly. It can be implicitly created by providing\n // a correctly formatted but incorrect signature.\n } else if (signatureType == SignatureType.Invalid) {\n require(\n signature.length == 0,\n \"LENGTH_0_REQUIRED\"\n );\n isValid = false;\n return isValid;\n\n // Signature using EIP712\n } else if (signatureType == SignatureType.EIP712) {\n require(\n signature.length == 65,\n \"LENGTH_65_REQUIRED\"\n );\n v = uint8(signature[0]);\n r = signature.readBytes32(1);\n s = signature.readBytes32(33);\n recovered = ecrecover(\n hash,\n v,\n r,\n s\n );\n isValid = signerAddress == recovered;\n return isValid;\n\n // Signed using web3.eth_sign\n } else if (signatureType == SignatureType.EthSign) {\n require(\n signature.length == 65,\n \"LENGTH_65_REQUIRED\"\n );\n v = uint8(signature[0]);\n r = signature.readBytes32(1);\n s = signature.readBytes32(33);\n recovered = ecrecover(\n keccak256(abi.encodePacked(\n \"\\x19Ethereum Signed Message:\\n32\",\n hash\n )),\n v,\n r,\n s\n );\n isValid = signerAddress == recovered;\n return isValid;\n\n // Implicitly signed by caller.\n // The signer has initiated the call. In the case of non-contract\n // accounts it means the transaction itself was signed.\n // Example: let's say for a particular operation three signatures\n // A, B and C are required. To submit the transaction, A and B can\n // give a signature to C, who can then submit the transaction using\n // `Caller` for his own signature. Or A and C can sign and B can\n // submit using `Caller`. Having `Caller` allows this flexibility.\n } else if (signatureType == SignatureType.Caller) {\n require(\n signature.length == 0,\n \"LENGTH_0_REQUIRED\"\n );\n isValid = signerAddress == msg.sender;\n return isValid;\n\n // Signature verified by wallet contract.\n // If used with an order, the maker of the order is the wallet contract.\n } else if (signatureType == SignatureType.Wallet) {\n isValid = IWallet(signerAddress).isValidSignature(hash, signature);\n return isValid;\n\n // Signature verified by validator contract.\n // If used with an order, the maker of the order can still be an EOA.\n // A signature using this type should be encoded as:\n // | Offset | Length | Contents |\n // | 0x00 | x | Signature to validate |\n // | 0x00 + x | 20 | Address of validator contract |\n // | 0x14 + x | 1 | Signature type is always \"\\x06\" |\n } else if (signatureType == SignatureType.Validator) {\n // Pop last 20 bytes off of signature byte array.\n address validatorAddress = signature.popLast20Bytes();\n \n // Ensure signer has approved validator.\n if (!allowedValidators[signerAddress][validatorAddress]) {\n return false;\n }\n isValid = IValidator(validatorAddress).isValidSignature(\n hash,\n signerAddress,\n signature\n );\n return isValid;\n\n // Signer signed hash previously using the preSign function.\n } else if (signatureType == SignatureType.PreSigned) {\n isValid = preSigned[hash][signerAddress];\n return isValid;\n\n // Signature from Trezor hardware wallet.\n // It differs from web3.eth_sign in the encoding of message length\n // (Bitcoin varint encoding vs ascii-decimal, the latter is not\n // self-terminating which leads to ambiguities).\n // See also:\n // https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer\n // https://github.com/trezor/trezor-mcu/blob/master/firmware/ethereum.c#L602\n // https://github.com/trezor/trezor-mcu/blob/master/firmware/crypto.c#L36\n } else if (signatureType == SignatureType.Trezor) {\n require(\n signature.length == 65,\n \"LENGTH_65_REQUIRED\"\n );\n v = uint8(signature[0]);\n r = signature.readBytes32(1);\n s = signature.readBytes32(33);\n recovered = ecrecover(\n keccak256(abi.encodePacked(\n \"\\x19Ethereum Signed Message:\\n\\x20\",\n hash\n )),\n v,\n r,\n s\n );\n isValid = signerAddress == recovered;\n return isValid;\n }\n\n // Anything else is illegal (We do not return false because\n // the signature may actually be valid, just not in a format\n // that we currently support. In this case returning false\n // may lead the caller to incorrectly believe that the\n // signature was invalid.)\n revert(\"SIGNATURE_UNSUPPORTED\");\n }\n}\n", - "2.0.0/protocol/Exchange/MixinTransactions.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\nimport \"./libs/LibExchangeErrors.sol\";\nimport \"./mixins/MSignatureValidator.sol\";\nimport \"./mixins/MTransactions.sol\";\nimport \"./libs/LibEIP712.sol\";\n\n\ncontract MixinTransactions is\n LibEIP712,\n MSignatureValidator,\n MTransactions\n{\n\n // Mapping of transaction hash => executed\n // This prevents transactions from being executed more than once.\n mapping (bytes32 => bool) public transactions;\n\n // Address of current transaction signer\n address public currentContextAddress;\n\n // Hash for the EIP712 ZeroEx Transaction Schema\n bytes32 constant internal EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH = keccak256(abi.encodePacked(\n \"ZeroExTransaction(\",\n \"uint256 salt,\",\n \"address signerAddress,\",\n \"bytes data\",\n \")\"\n ));\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 // Prevent reentrancy\n require(\n currentContextAddress == address(0),\n \"REENTRANCY_ILLEGAL\"\n );\n\n bytes32 transactionHash = hashEIP712Message(hashZeroExTransaction(\n salt,\n signerAddress,\n data\n ));\n\n // Validate transaction has not been executed\n require(\n !transactions[transactionHash],\n \"INVALID_TX_HASH\"\n );\n\n // Transaction always valid if signer is sender of transaction\n if (signerAddress != msg.sender) {\n // Validate signature\n require(\n isValidSignature(\n transactionHash,\n signerAddress,\n signature\n ),\n \"INVALID_TX_SIGNATURE\"\n );\n\n // Set the current transaction signer\n currentContextAddress = signerAddress;\n }\n\n // Execute transaction\n transactions[transactionHash] = true;\n require(\n address(this).delegatecall(data),\n \"FAILED_EXECUTION\"\n );\n\n // Reset current transaction signer if it was previously updated\n if (signerAddress != msg.sender) {\n currentContextAddress = address(0);\n }\n }\n\n /// @dev Calculates EIP712 hash of the Transaction.\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 /// @return EIP712 hash of the Transaction.\n function hashZeroExTransaction(\n uint256 salt,\n address signerAddress,\n bytes memory data\n )\n internal\n pure\n returns (bytes32 result)\n {\n bytes32 schemaHash = EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH;\n bytes32 dataHash = keccak256(data);\n\n // Assembly for more efficiently computing:\n // keccak256(abi.encodePacked(\n // EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH,\n // salt,\n // bytes32(signerAddress),\n // keccak256(data)\n // ));\n\n assembly {\n // Load free memory pointer\n let memPtr := mload(64)\n\n mstore(memPtr, schemaHash) // hash of schema\n mstore(add(memPtr, 32), salt) // salt\n mstore(add(memPtr, 64), and(signerAddress, 0xffffffffffffffffffffffffffffffffffffffff)) // signerAddress\n mstore(add(memPtr, 96), dataHash) // hash of data\n\n // Compute hash\n result := keccak256(memPtr, 128)\n }\n return result;\n }\n\n /// @dev The current function will be called in the context of this address (either 0x transaction signer or `msg.sender`).\n /// If calling a fill function, this address will represent the taker.\n /// If calling a cancel function, this address will represent the maker.\n /// @return Signer of 0x transaction if entry point is `executeTransaction`.\n /// `msg.sender` if entry point is any other function.\n function getCurrentContextAddress()\n internal\n view\n returns (address)\n {\n address contextAddress = currentContextAddress == address(0) ? msg.sender : currentContextAddress;\n return contextAddress;\n }\n}\n", - "2.0.0/protocol/Exchange/MixinWrapperFunctions.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 \"./libs/LibMath.sol\";\nimport \"./libs/LibOrder.sol\";\nimport \"./libs/LibFillResults.sol\";\nimport \"./libs/LibAbiEncoder.sol\";\nimport \"./mixins/MExchangeCore.sol\";\n\n\ncontract MixinWrapperFunctions is\n LibMath,\n LibFillResults,\n LibAbiEncoder,\n MExchangeCore\n{\n\n /// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled.\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 function fillOrKillOrder(\n LibOrder.Order memory order,\n uint256 takerAssetFillAmount,\n bytes memory signature\n )\n public\n returns (FillResults memory fillResults)\n {\n fillResults = fillOrder(\n order,\n takerAssetFillAmount,\n signature\n );\n require(\n fillResults.takerAssetFilledAmount == takerAssetFillAmount,\n \"COMPLETE_FILL_FAILED\"\n );\n return fillResults;\n }\n\n /// @dev Fills the input order.\n /// Returns false if the transaction would otherwise revert.\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 fillOrderNoThrow(\n LibOrder.Order memory order,\n uint256 takerAssetFillAmount,\n bytes memory signature\n )\n public\n returns (FillResults memory fillResults)\n {\n // ABI encode calldata for `fillOrder`\n bytes memory fillOrderCalldata = abiEncodeFillOrder(\n order,\n takerAssetFillAmount,\n signature\n );\n\n // Delegate to `fillOrder` and handle any exceptions gracefully\n assembly {\n let success := delegatecall(\n gas, // forward all gas, TODO: look into gas consumption of assert/throw\n address, // call address of this contract\n add(fillOrderCalldata, 32), // pointer to start of input (skip array length in first 32 bytes)\n mload(fillOrderCalldata), // length of input\n fillOrderCalldata, // write output over input\n 128 // output size is 128 bytes\n )\n switch success\n case 0 {\n mstore(fillResults, 0)\n mstore(add(fillResults, 32), 0)\n mstore(add(fillResults, 64), 0)\n mstore(add(fillResults, 96), 0)\n }\n case 1 {\n mstore(fillResults, mload(fillOrderCalldata))\n mstore(add(fillResults, 32), mload(add(fillOrderCalldata, 32)))\n mstore(add(fillResults, 64), mload(add(fillOrderCalldata, 64)))\n mstore(add(fillResults, 96), mload(add(fillOrderCalldata, 96)))\n }\n }\n return fillResults;\n }\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 /// NOTE: makerAssetFilledAmount and takerAssetFilledAmount may include amounts filled of different assets.\n function batchFillOrders(\n LibOrder.Order[] memory orders,\n uint256[] memory takerAssetFillAmounts,\n bytes[] memory signatures\n )\n public\n returns (FillResults memory totalFillResults)\n {\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n FillResults memory singleFillResults = fillOrder(\n orders[i],\n takerAssetFillAmounts[i],\n signatures[i]\n );\n addFillResults(totalFillResults, singleFillResults);\n }\n return totalFillResults;\n }\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 /// NOTE: makerAssetFilledAmount and takerAssetFilledAmount may include amounts filled of different assets.\n function batchFillOrKillOrders(\n LibOrder.Order[] memory orders,\n uint256[] memory takerAssetFillAmounts,\n bytes[] memory signatures\n )\n public\n returns (FillResults memory totalFillResults)\n {\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n FillResults memory singleFillResults = fillOrKillOrder(\n orders[i],\n takerAssetFillAmounts[i],\n signatures[i]\n );\n addFillResults(totalFillResults, singleFillResults);\n }\n return totalFillResults;\n }\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 /// NOTE: makerAssetFilledAmount and takerAssetFilledAmount may include amounts filled of different assets.\n function batchFillOrdersNoThrow(\n LibOrder.Order[] memory orders,\n uint256[] memory takerAssetFillAmounts,\n bytes[] memory signatures\n )\n public\n returns (FillResults memory totalFillResults)\n {\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n FillResults memory singleFillResults = fillOrderNoThrow(\n orders[i],\n takerAssetFillAmounts[i],\n signatures[i]\n );\n addFillResults(totalFillResults, singleFillResults);\n }\n return totalFillResults;\n }\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 (FillResults memory totalFillResults)\n {\n bytes memory takerAssetData = orders[0].takerAssetData;\n \n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n\n // We assume that asset being sold by taker is the same for each order.\n // Rather than passing this in as calldata, we use the takerAssetData from the first order in all later orders.\n orders[i].takerAssetData = takerAssetData;\n\n // Calculate the remaining amount of takerAsset to sell\n uint256 remainingTakerAssetFillAmount = safeSub(takerAssetFillAmount, totalFillResults.takerAssetFilledAmount);\n\n // Attempt to sell the remaining amount of takerAsset\n FillResults memory singleFillResults = fillOrder(\n orders[i],\n remainingTakerAssetFillAmount,\n signatures[i]\n );\n\n // Update amounts filled and fees paid by maker and taker\n addFillResults(totalFillResults, singleFillResults);\n\n // Stop execution if the entire amount of takerAsset has been sold\n if (totalFillResults.takerAssetFilledAmount >= takerAssetFillAmount) {\n break;\n }\n }\n return totalFillResults;\n }\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 (FillResults memory totalFillResults)\n {\n bytes memory takerAssetData = orders[0].takerAssetData;\n\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n\n // We assume that asset being sold by taker is the same for each order.\n // Rather than passing this in as calldata, we use the takerAssetData from the first order in all later orders.\n orders[i].takerAssetData = takerAssetData;\n\n // Calculate the remaining amount of takerAsset to sell\n uint256 remainingTakerAssetFillAmount = safeSub(takerAssetFillAmount, totalFillResults.takerAssetFilledAmount);\n\n // Attempt to sell the remaining amount of takerAsset\n FillResults memory singleFillResults = fillOrderNoThrow(\n orders[i],\n remainingTakerAssetFillAmount,\n signatures[i]\n );\n\n // Update amounts filled and fees paid by maker and taker\n addFillResults(totalFillResults, singleFillResults);\n\n // Stop execution if the entire amount of takerAsset has been sold\n if (totalFillResults.takerAssetFilledAmount >= takerAssetFillAmount) {\n break;\n }\n }\n return totalFillResults;\n }\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 (FillResults memory totalFillResults)\n {\n bytes memory makerAssetData = orders[0].makerAssetData;\n\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n\n // We assume that asset being bought by taker is the same for each order.\n // Rather than passing this in as calldata, we copy the makerAssetData from the first order onto all later orders.\n orders[i].makerAssetData = makerAssetData;\n\n // Calculate the remaining amount of makerAsset to buy\n uint256 remainingMakerAssetFillAmount = safeSub(makerAssetFillAmount, totalFillResults.makerAssetFilledAmount);\n\n // Convert the remaining amount of makerAsset to buy into remaining amount\n // of takerAsset to sell, assuming entire amount can be sold in the current order\n uint256 remainingTakerAssetFillAmount = getPartialAmount(\n orders[i].takerAssetAmount,\n orders[i].makerAssetAmount,\n remainingMakerAssetFillAmount\n );\n\n // Attempt to sell the remaining amount of takerAsset\n FillResults memory singleFillResults = fillOrder(\n orders[i],\n remainingTakerAssetFillAmount,\n signatures[i]\n );\n\n // Update amounts filled and fees paid by maker and taker\n addFillResults(totalFillResults, singleFillResults);\n\n // Stop execution if the entire amount of makerAsset has been bought\n if (totalFillResults.makerAssetFilledAmount >= makerAssetFillAmount) {\n break;\n }\n }\n return totalFillResults;\n }\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 (FillResults memory totalFillResults)\n {\n bytes memory makerAssetData = orders[0].makerAssetData;\n\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n\n // We assume that asset being bought by taker is the same for each order.\n // Rather than passing this in as calldata, we copy the makerAssetData from the first order onto all later orders.\n orders[i].makerAssetData = makerAssetData;\n\n // Calculate the remaining amount of makerAsset to buy\n uint256 remainingMakerAssetFillAmount = safeSub(makerAssetFillAmount, totalFillResults.makerAssetFilledAmount);\n\n // Convert the remaining amount of makerAsset to buy into remaining amount\n // of takerAsset to sell, assuming entire amount can be sold in the current order\n uint256 remainingTakerAssetFillAmount = getPartialAmount(\n orders[i].takerAssetAmount,\n orders[i].makerAssetAmount,\n remainingMakerAssetFillAmount\n );\n\n // Attempt to sell the remaining amount of takerAsset\n FillResults memory singleFillResults = fillOrderNoThrow(\n orders[i],\n remainingTakerAssetFillAmount,\n signatures[i]\n );\n\n // Update amounts filled and fees paid by maker and taker\n addFillResults(totalFillResults, singleFillResults);\n\n // Stop execution if the entire amount of makerAsset has been bought\n if (totalFillResults.makerAssetFilledAmount >= makerAssetFillAmount) {\n break;\n }\n }\n return totalFillResults;\n }\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 uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n cancelOrder(orders[i]);\n }\n }\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 uint256 ordersLength = orders.length;\n LibOrder.OrderInfo[] memory ordersInfo = new LibOrder.OrderInfo[](ordersLength);\n for (uint256 i = 0; i != ordersLength; i++) {\n ordersInfo[i] = getOrderInfo(orders[i]);\n }\n return ordersInfo;\n }\n}\n", + "2.0.0/protocol/Exchange/MixinAssetProxyDispatcher.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 \"../../utils/Ownable/Ownable.sol\";\nimport \"../../utils/LibBytes/LibBytes.sol\";\nimport \"./mixins/MAssetProxyDispatcher.sol\";\nimport \"../AssetProxy/interfaces/IAssetProxy.sol\";\n\n\ncontract MixinAssetProxyDispatcher is\n Ownable,\n MAssetProxyDispatcher\n{\n using LibBytes for bytes;\n \n // Mapping from Asset Proxy Id's to their respective Asset Proxy\n mapping (bytes4 => IAssetProxy) public assetProxies;\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 onlyOwner\n {\n IAssetProxy assetProxyContract = IAssetProxy(assetProxy);\n\n // Ensure that no asset proxy exists with current id.\n bytes4 assetProxyId = assetProxyContract.getProxyId();\n address currentAssetProxy = assetProxies[assetProxyId];\n require(\n currentAssetProxy == address(0),\n \"ASSET_PROXY_ALREADY_EXISTS\"\n );\n\n // Add asset proxy and log registration.\n assetProxies[assetProxyId] = assetProxyContract;\n emit AssetProxyRegistered(\n assetProxyId,\n assetProxy\n );\n }\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 return assetProxies[assetProxyId];\n }\n\n /// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws.\n /// @param assetData Byte array encoded for the asset.\n /// @param from Address to transfer token from.\n /// @param to Address to transfer token to.\n /// @param amount Amount of token to transfer.\n function dispatchTransferFrom(\n bytes memory assetData,\n address from,\n address to,\n uint256 amount\n )\n internal\n {\n // Do nothing if no amount should be transferred.\n if (amount > 0 && from != to) {\n // Ensure assetData length is valid\n require(\n assetData.length > 3,\n \"LENGTH_GREATER_THAN_3_REQUIRED\"\n );\n \n // Lookup assetProxy\n bytes4 assetProxyId;\n assembly {\n assetProxyId := and(mload(\n add(assetData, 32)),\n 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000\n )\n }\n address assetProxy = assetProxies[assetProxyId];\n\n // Ensure that assetProxy exists\n require(\n assetProxy != address(0),\n \"ASSET_PROXY_DOES_NOT_EXIST\"\n );\n \n // We construct calldata for the `assetProxy.transferFrom` ABI.\n // The layout of this calldata is in the table below.\n // \n // | Area | Offset | Length | Contents |\n // | -------- |--------|---------|-------------------------------------------- |\n // | Header | 0 | 4 | function selector |\n // | Params | | 4 * 32 | function parameters: |\n // | | 4 | | 1. offset to assetData (*) |\n // | | 36 | | 2. from |\n // | | 68 | | 3. to |\n // | | 100 | | 4. amount |\n // | Data | | | assetData: |\n // | | 132 | 32 | assetData Length |\n // | | 164 | ** | assetData Contents |\n\n assembly {\n /////// Setup State ///////\n // `cdStart` is the start of the calldata for `assetProxy.transferFrom` (equal to free memory ptr).\n let cdStart := mload(64)\n // `dataAreaLength` is the total number of words needed to store `assetData`\n // As-per the ABI spec, this value is padded up to the nearest multiple of 32,\n // and includes 32-bytes for length.\n let dataAreaLength := and(add(mload(assetData), 63), 0xFFFFFFFFFFFE0)\n // `cdEnd` is the end of the calldata for `assetProxy.transferFrom`.\n let cdEnd := add(cdStart, add(132, dataAreaLength))\n\n \n /////// Setup Header Area ///////\n // This area holds the 4-byte `transferFromSelector`.\n // bytes4(keccak256(\"transferFrom(bytes,address,address,uint256)\")) = 0xa85e59e4\n mstore(cdStart, 0xa85e59e400000000000000000000000000000000000000000000000000000000)\n \n /////// Setup Params Area ///////\n // Each parameter is padded to 32-bytes. The entire Params Area is 128 bytes.\n // Notes:\n // 1. The offset to `assetData` is the length of the Params Area (128 bytes).\n // 2. A 20-byte mask is applied to addresses to zero-out the unused bytes.\n mstore(add(cdStart, 4), 128)\n mstore(add(cdStart, 36), and(from, 0xffffffffffffffffffffffffffffffffffffffff))\n mstore(add(cdStart, 68), and(to, 0xffffffffffffffffffffffffffffffffffffffff))\n mstore(add(cdStart, 100), amount)\n \n /////// Setup Data Area ///////\n // This area holds `assetData`.\n let dataArea := add(cdStart, 132)\n // solhint-disable-next-line no-empty-blocks\n for {} lt(dataArea, cdEnd) {} {\n mstore(dataArea, mload(assetData))\n dataArea := add(dataArea, 32)\n assetData := add(assetData, 32)\n }\n\n /////// Call `assetProxy.transferFrom` using the constructed calldata ///////\n let success := call(\n gas, // forward all gas\n assetProxy, // call address of asset proxy\n 0, // don't send any ETH\n cdStart, // pointer to start of input\n sub(cdEnd, cdStart), // length of input \n cdStart, // write output over input\n 512 // reserve 512 bytes for output\n )\n if iszero(success) {\n revert(cdStart, returndatasize())\n }\n }\n }\n }\n}\n", + "2.0.0/protocol/Exchange/MixinExchangeCore.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 \"../../utils/ReentrancyGuard/ReentrancyGuard.sol\";\nimport \"./libs/LibConstants.sol\";\nimport \"./libs/LibFillResults.sol\";\nimport \"./libs/LibOrder.sol\";\nimport \"./libs/LibMath.sol\";\nimport \"./mixins/MExchangeCore.sol\";\nimport \"./mixins/MSignatureValidator.sol\";\nimport \"./mixins/MTransactions.sol\";\nimport \"./mixins/MAssetProxyDispatcher.sol\";\n\n\ncontract MixinExchangeCore is\n ReentrancyGuard,\n LibConstants,\n LibMath,\n LibOrder,\n LibFillResults,\n MAssetProxyDispatcher,\n MExchangeCore,\n MSignatureValidator,\n MTransactions\n{\n // Mapping of orderHash => amount of takerAsset already bought by maker\n mapping (bytes32 => uint256) public filled;\n\n // Mapping of orderHash => cancelled\n mapping (bytes32 => bool) public cancelled;\n\n // Mapping of makerAddress => senderAddress => lowest salt an order can have in order to be fillable\n // Orders with specified senderAddress and with a salt less than their epoch are considered cancelled\n mapping (address => mapping (address => uint256)) public orderEpoch;\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 nonReentrant\n {\n address makerAddress = getCurrentContextAddress();\n // If this function is called via `executeTransaction`, we only update the orderEpoch for the makerAddress/msg.sender combination.\n // This allows external filter contracts to add rules to how orders are cancelled via this function.\n address senderAddress = makerAddress == msg.sender ? address(0) : msg.sender;\n\n // orderEpoch is initialized to 0, so to cancelUpTo we need salt + 1\n uint256 newOrderEpoch = targetOrderEpoch + 1; \n uint256 oldOrderEpoch = orderEpoch[makerAddress][senderAddress];\n\n // Ensure orderEpoch is monotonically increasing\n require(\n newOrderEpoch > oldOrderEpoch, \n \"INVALID_NEW_ORDER_EPOCH\"\n );\n\n // Update orderEpoch\n orderEpoch[makerAddress][senderAddress] = newOrderEpoch;\n emit CancelUpTo(makerAddress, senderAddress, newOrderEpoch);\n }\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 Order memory order,\n uint256 takerAssetFillAmount,\n bytes memory signature\n )\n public\n nonReentrant\n returns (FillResults memory fillResults)\n {\n fillResults = fillOrderInternal(\n order,\n takerAssetFillAmount,\n signature\n );\n return fillResults;\n }\n\n /// @dev After calling, the order can not be filled anymore.\n /// Throws if order is invalid or sender does not have permission to cancel.\n /// @param order Order to cancel. Order must be OrderStatus.FILLABLE.\n function cancelOrder(Order memory order)\n public\n nonReentrant\n {\n // Fetch current order status\n OrderInfo memory orderInfo = getOrderInfo(order);\n\n // Validate context\n assertValidCancel(order, orderInfo);\n\n // Perform cancel\n updateCancelledState(order, orderInfo.orderHash);\n }\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(Order memory order)\n public\n view\n returns (OrderInfo memory orderInfo)\n {\n // Compute the order hash\n orderInfo.orderHash = getOrderHash(order);\n\n // Fetch filled amount\n orderInfo.orderTakerAssetFilledAmount = filled[orderInfo.orderHash];\n\n // If order.makerAssetAmount is zero, we also reject the order.\n // While the Exchange contract handles them correctly, they create\n // edge cases in the supporting infrastructure because they have\n // an 'infinite' price when computed by a simple division.\n if (order.makerAssetAmount == 0) {\n orderInfo.orderStatus = uint8(OrderStatus.INVALID_MAKER_ASSET_AMOUNT);\n return orderInfo;\n }\n\n // If order.takerAssetAmount is zero, then the order will always\n // be considered filled because 0 == takerAssetAmount == orderTakerAssetFilledAmount\n // Instead of distinguishing between unfilled and filled zero taker\n // amount orders, we choose not to support them.\n if (order.takerAssetAmount == 0) {\n orderInfo.orderStatus = uint8(OrderStatus.INVALID_TAKER_ASSET_AMOUNT);\n return orderInfo;\n }\n\n // Validate order availability\n if (orderInfo.orderTakerAssetFilledAmount >= order.takerAssetAmount) {\n orderInfo.orderStatus = uint8(OrderStatus.FULLY_FILLED);\n return orderInfo;\n }\n\n // Validate order expiration\n // solhint-disable-next-line not-rely-on-time\n if (block.timestamp >= order.expirationTimeSeconds) {\n orderInfo.orderStatus = uint8(OrderStatus.EXPIRED);\n return orderInfo;\n }\n\n // Check if order has been cancelled\n if (cancelled[orderInfo.orderHash]) {\n orderInfo.orderStatus = uint8(OrderStatus.CANCELLED);\n return orderInfo;\n }\n if (orderEpoch[order.makerAddress][order.senderAddress] > order.salt) {\n orderInfo.orderStatus = uint8(OrderStatus.CANCELLED);\n return orderInfo;\n }\n\n // All other statuses are ruled out: order is Fillable\n orderInfo.orderStatus = uint8(OrderStatus.FILLABLE);\n return orderInfo;\n }\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 fillOrderInternal(\n Order memory order,\n uint256 takerAssetFillAmount,\n bytes memory signature\n )\n internal\n returns (FillResults memory fillResults)\n {\n // Fetch order info\n OrderInfo memory orderInfo = getOrderInfo(order);\n\n // Fetch taker address\n address takerAddress = getCurrentContextAddress();\n \n // Assert that the order is fillable by taker\n assertFillableOrder(\n order,\n orderInfo,\n takerAddress,\n signature\n );\n \n // Get amount of takerAsset to fill\n uint256 remainingTakerAssetAmount = safeSub(order.takerAssetAmount, orderInfo.orderTakerAssetFilledAmount);\n uint256 takerAssetFilledAmount = min256(takerAssetFillAmount, remainingTakerAssetAmount);\n\n // Validate context\n assertValidFill(\n order,\n orderInfo,\n takerAssetFillAmount,\n takerAssetFilledAmount,\n fillResults.makerAssetFilledAmount\n );\n\n // Compute proportional fill amounts\n fillResults = calculateFillResults(order, takerAssetFilledAmount);\n\n // Update exchange internal state\n updateFilledState(\n order,\n takerAddress,\n orderInfo.orderHash,\n orderInfo.orderTakerAssetFilledAmount,\n fillResults\n );\n \n // Settle order\n settleOrder(order, takerAddress, fillResults);\n\n return fillResults;\n }\n\n /// @dev Updates state with results of a fill order.\n /// @param order that was filled.\n /// @param takerAddress Address of taker who filled the order.\n /// @param orderTakerAssetFilledAmount Amount of order already filled.\n function updateFilledState(\n Order memory order,\n address takerAddress,\n bytes32 orderHash,\n uint256 orderTakerAssetFilledAmount,\n FillResults memory fillResults\n )\n internal\n {\n // Update state\n filled[orderHash] = safeAdd(orderTakerAssetFilledAmount, fillResults.takerAssetFilledAmount);\n\n // Log order\n emit Fill(\n order.makerAddress,\n order.feeRecipientAddress,\n takerAddress,\n msg.sender,\n fillResults.makerAssetFilledAmount,\n fillResults.takerAssetFilledAmount,\n fillResults.makerFeePaid,\n fillResults.takerFeePaid,\n orderHash,\n order.makerAssetData,\n order.takerAssetData\n );\n }\n\n /// @dev Updates state with results of cancelling an order.\n /// State is only updated if the order is currently fillable.\n /// Otherwise, updating state would have no effect.\n /// @param order that was cancelled.\n /// @param orderHash Hash of order that was cancelled.\n function updateCancelledState(\n Order memory order,\n bytes32 orderHash\n )\n internal\n {\n // Perform cancel\n cancelled[orderHash] = true;\n\n // Log cancel\n emit Cancel(\n order.makerAddress,\n order.feeRecipientAddress,\n msg.sender,\n orderHash,\n order.makerAssetData,\n order.takerAssetData\n );\n }\n \n /// @dev Validates context for fillOrder. Succeeds or throws.\n /// @param order to be filled.\n /// @param orderInfo OrderStatus, orderHash, and amount already filled of order.\n /// @param takerAddress Address of order taker.\n /// @param signature Proof that the orders was created by its maker.\n function assertFillableOrder(\n Order memory order,\n OrderInfo memory orderInfo,\n address takerAddress,\n bytes memory signature\n )\n internal\n view\n {\n // An order can only be filled if its status is FILLABLE.\n require(\n orderInfo.orderStatus == uint8(OrderStatus.FILLABLE),\n \"ORDER_UNFILLABLE\"\n );\n \n // Validate sender is allowed to fill this order\n if (order.senderAddress != address(0)) {\n require(\n order.senderAddress == msg.sender,\n \"INVALID_SENDER\"\n );\n }\n \n // Validate taker is allowed to fill this order\n if (order.takerAddress != address(0)) {\n require(\n order.takerAddress == takerAddress,\n \"INVALID_TAKER\"\n );\n }\n \n // Validate Maker signature (check only if first time seen)\n if (orderInfo.orderTakerAssetFilledAmount == 0) {\n require(\n isValidSignature(\n orderInfo.orderHash,\n order.makerAddress,\n signature\n ),\n \"INVALID_ORDER_SIGNATURE\"\n );\n }\n }\n \n /// @dev Validates context for fillOrder. Succeeds or throws.\n /// @param order to be filled.\n /// @param orderInfo OrderStatus, orderHash, and amount already filled of order.\n /// @param takerAssetFillAmount Desired amount of order to fill by taker.\n /// @param takerAssetFilledAmount Amount of takerAsset that will be filled.\n /// @param makerAssetFilledAmount Amount of makerAsset that will be transfered.\n function assertValidFill(\n Order memory order,\n OrderInfo memory orderInfo,\n uint256 takerAssetFillAmount, // TODO: use FillResults\n uint256 takerAssetFilledAmount,\n uint256 makerAssetFilledAmount\n )\n internal\n view\n {\n // Revert if fill amount is invalid\n // TODO: reconsider necessity for v2.1\n require(\n takerAssetFillAmount != 0,\n \"INVALID_TAKER_AMOUNT\"\n );\n \n // Make sure taker does not pay more than desired amount\n // NOTE: This assertion should never fail, it is here\n // as an extra defence against potential bugs.\n require(\n takerAssetFilledAmount <= takerAssetFillAmount,\n \"TAKER_OVERPAY\"\n );\n \n // Make sure order is not overfilled\n // NOTE: This assertion should never fail, it is here\n // as an extra defence against potential bugs.\n require(\n safeAdd(orderInfo.orderTakerAssetFilledAmount, takerAssetFilledAmount) <= order.takerAssetAmount,\n \"ORDER_OVERFILL\"\n );\n \n // Make sure order is filled at acceptable price.\n // The order has an implied price from the makers perspective:\n // order price = order.makerAssetAmount / order.takerAssetAmount\n // i.e. the number of makerAsset maker is paying per takerAsset. The\n // maker is guaranteed to get this price or a better (lower) one. The\n // actual price maker is getting in this fill is:\n // fill price = makerAssetFilledAmount / takerAssetFilledAmount\n // We need `fill price <= order price` for the fill to be fair to maker.\n // This amounts to:\n // makerAssetFilledAmount order.makerAssetAmount\n // ------------------------ <= -----------------------\n // takerAssetFilledAmount order.takerAssetAmount\n // or, equivalently:\n // makerAssetFilledAmount * order.takerAssetAmount <=\n // order.makerAssetAmount * takerAssetFilledAmount\n // NOTE: This assertion should never fail, it is here\n // as an extra defence against potential bugs.\n require(\n safeMul(makerAssetFilledAmount, order.takerAssetAmount)\n <= \n safeMul(order.makerAssetAmount, takerAssetFilledAmount),\n \"INVALID_FILL_PRICE\"\n );\n \n // Validate fill order rounding\n require(\n !isRoundingErrorFloor(\n takerAssetFilledAmount,\n order.takerAssetAmount,\n order.makerAssetAmount\n ),\n \"ROUNDING_ERROR\"\n );\n }\n\n /// @dev Validates context for cancelOrder. Succeeds or throws.\n /// @param order to be cancelled.\n /// @param orderInfo OrderStatus, orderHash, and amount already filled of order.\n function assertValidCancel(\n Order memory order,\n OrderInfo memory orderInfo\n )\n internal\n view\n {\n // Ensure order is valid\n // An order can only be cancelled if its status is FILLABLE.\n require(\n orderInfo.orderStatus == uint8(OrderStatus.FILLABLE),\n \"ORDER_UNFILLABLE\"\n );\n\n // Validate sender is allowed to cancel this order\n if (order.senderAddress != address(0)) {\n require(\n order.senderAddress == msg.sender,\n \"INVALID_SENDER\"\n );\n }\n\n // Validate transaction signed by maker\n address makerAddress = getCurrentContextAddress();\n require(\n order.makerAddress == makerAddress,\n \"INVALID_MAKER\"\n );\n }\n\n /// @dev Calculates amounts filled and fees paid by maker and taker.\n /// @param order to be filled.\n /// @param takerAssetFilledAmount Amount of takerAsset that will be filled.\n /// @return fillResults Amounts filled and fees paid by maker and taker.\n function calculateFillResults(\n Order memory order,\n uint256 takerAssetFilledAmount\n )\n internal\n pure\n returns (FillResults memory fillResults)\n {\n // Compute proportional transfer amounts\n fillResults.takerAssetFilledAmount = takerAssetFilledAmount;\n fillResults.makerAssetFilledAmount = getPartialAmountFloor(\n takerAssetFilledAmount,\n order.takerAssetAmount,\n order.makerAssetAmount\n );\n fillResults.makerFeePaid = getPartialAmountFloor(\n takerAssetFilledAmount,\n order.takerAssetAmount,\n order.makerFee\n );\n fillResults.takerFeePaid = getPartialAmountFloor(\n takerAssetFilledAmount,\n order.takerAssetAmount,\n order.takerFee\n );\n\n return fillResults;\n }\n\n /// @dev Settles an order by transferring assets between counterparties.\n /// @param order Order struct containing order specifications.\n /// @param takerAddress Address selling takerAsset and buying makerAsset.\n /// @param fillResults Amounts to be filled and fees paid by maker and taker.\n function settleOrder(\n LibOrder.Order memory order,\n address takerAddress,\n LibFillResults.FillResults memory fillResults\n )\n private\n {\n bytes memory zrxAssetData = ZRX_ASSET_DATA;\n dispatchTransferFrom(\n order.makerAssetData,\n order.makerAddress,\n takerAddress,\n fillResults.makerAssetFilledAmount\n );\n dispatchTransferFrom(\n order.takerAssetData,\n takerAddress,\n order.makerAddress,\n fillResults.takerAssetFilledAmount\n );\n dispatchTransferFrom(\n zrxAssetData,\n order.makerAddress,\n order.feeRecipientAddress,\n fillResults.makerFeePaid\n );\n dispatchTransferFrom(\n zrxAssetData,\n takerAddress,\n order.feeRecipientAddress,\n fillResults.takerFeePaid\n );\n }\n}\n", + "2.0.0/protocol/Exchange/MixinMatchOrders.sol": "/*\n Copyright 2018 ZeroEx Intl.\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 http://www.apache.org/licenses/LICENSE-2.0\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 \"../../utils/ReentrancyGuard/ReentrancyGuard.sol\";\nimport \"./libs/LibConstants.sol\";\nimport \"./libs/LibMath.sol\";\nimport \"./libs/LibOrder.sol\";\nimport \"./libs/LibFillResults.sol\";\nimport \"./mixins/MExchangeCore.sol\";\nimport \"./mixins/MMatchOrders.sol\";\nimport \"./mixins/MTransactions.sol\";\nimport \"./mixins/MAssetProxyDispatcher.sol\";\n\n\ncontract MixinMatchOrders is\n ReentrancyGuard,\n LibConstants,\n LibMath,\n MAssetProxyDispatcher,\n MExchangeCore,\n MMatchOrders,\n MTransactions\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 nonReentrant\n returns (LibFillResults.MatchedFillResults memory matchedFillResults)\n {\n // We assume that rightOrder.takerAssetData == leftOrder.makerAssetData and rightOrder.makerAssetData == leftOrder.takerAssetData.\n // If this assumption isn't true, the match will fail at signature validation.\n rightOrder.makerAssetData = leftOrder.takerAssetData;\n rightOrder.takerAssetData = leftOrder.makerAssetData;\n\n // Get left & right order info\n LibOrder.OrderInfo memory leftOrderInfo = getOrderInfo(leftOrder);\n LibOrder.OrderInfo memory rightOrderInfo = getOrderInfo(rightOrder);\n\n // Fetch taker address\n address takerAddress = getCurrentContextAddress();\n \n // Either our context is valid or we revert\n assertFillableOrder(\n leftOrder,\n leftOrderInfo,\n takerAddress,\n leftSignature\n );\n assertFillableOrder(\n rightOrder,\n rightOrderInfo,\n takerAddress,\n rightSignature\n );\n assertValidMatch(leftOrder, rightOrder);\n\n // Compute proportional fill amounts\n matchedFillResults = calculateMatchedFillResults(\n leftOrder,\n rightOrder,\n leftOrderInfo.orderTakerAssetFilledAmount,\n rightOrderInfo.orderTakerAssetFilledAmount\n );\n\n // Validate fill contexts\n assertValidFill(\n leftOrder,\n leftOrderInfo,\n matchedFillResults.left.takerAssetFilledAmount,\n matchedFillResults.left.takerAssetFilledAmount,\n matchedFillResults.left.makerAssetFilledAmount\n );\n assertValidFill(\n rightOrder,\n rightOrderInfo,\n matchedFillResults.right.takerAssetFilledAmount,\n matchedFillResults.right.takerAssetFilledAmount,\n matchedFillResults.right.makerAssetFilledAmount\n );\n \n // Update exchange state\n updateFilledState(\n leftOrder,\n takerAddress,\n leftOrderInfo.orderHash,\n leftOrderInfo.orderTakerAssetFilledAmount,\n matchedFillResults.left\n );\n updateFilledState(\n rightOrder,\n takerAddress,\n rightOrderInfo.orderHash,\n rightOrderInfo.orderTakerAssetFilledAmount,\n matchedFillResults.right\n );\n\n // Settle matched orders. Succeeds or throws.\n settleMatchedOrders(\n leftOrder,\n rightOrder,\n takerAddress,\n matchedFillResults\n );\n\n return matchedFillResults;\n }\n\n /// @dev Validates context for matchOrders. Succeeds or throws.\n /// @param leftOrder First order to match.\n /// @param rightOrder Second order to match.\n function assertValidMatch(\n LibOrder.Order memory leftOrder,\n LibOrder.Order memory rightOrder\n )\n internal\n pure\n {\n // Make sure there is a profitable spread.\n // There is a profitable spread iff the cost per unit bought (OrderA.MakerAmount/OrderA.TakerAmount) for each order is greater\n // than the profit per unit sold of the matched order (OrderB.TakerAmount/OrderB.MakerAmount).\n // This is satisfied by the equations below:\n // <leftOrder.makerAssetAmount> / <leftOrder.takerAssetAmount> >= <rightOrder.takerAssetAmount> / <rightOrder.makerAssetAmount>\n // AND\n // <rightOrder.makerAssetAmount> / <rightOrder.takerAssetAmount> >= <leftOrder.takerAssetAmount> / <leftOrder.makerAssetAmount>\n // These equations can be combined to get the following:\n require(\n safeMul(leftOrder.makerAssetAmount, rightOrder.makerAssetAmount) >=\n safeMul(leftOrder.takerAssetAmount, rightOrder.takerAssetAmount),\n \"NEGATIVE_SPREAD_REQUIRED\"\n );\n }\n\n /// @dev Calculates fill amounts for the matched orders.\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 leftOrder 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 leftOrderTakerAssetFilledAmount Amount of left order already filled.\n /// @param rightOrderTakerAssetFilledAmount Amount of right order already filled.\n /// @param matchedFillResults Amounts to fill and fees to pay by maker and taker of matched orders.\n function calculateMatchedFillResults(\n LibOrder.Order memory leftOrder,\n LibOrder.Order memory rightOrder,\n uint256 leftOrderTakerAssetFilledAmount,\n uint256 rightOrderTakerAssetFilledAmount\n )\n internal\n pure\n returns (LibFillResults.MatchedFillResults memory matchedFillResults)\n {\n // Derive maker asset amounts for left & right orders, given store taker assert amounts\n uint256 leftTakerAssetAmountRemaining = safeSub(leftOrder.takerAssetAmount, leftOrderTakerAssetFilledAmount);\n uint256 leftMakerAssetAmountRemaining = getPartialAmountFloor(\n leftOrder.makerAssetAmount,\n leftOrder.takerAssetAmount,\n leftTakerAssetAmountRemaining\n );\n uint256 rightTakerAssetAmountRemaining = safeSub(rightOrder.takerAssetAmount, rightOrderTakerAssetFilledAmount);\n uint256 rightMakerAssetAmountRemaining = getPartialAmountFloor(\n rightOrder.makerAssetAmount,\n rightOrder.takerAssetAmount,\n rightTakerAssetAmountRemaining\n );\n\n // Calculate fill results for maker and taker assets: at least one order will be fully filled.\n // The maximum amount the left maker can buy is `leftTakerAssetAmountRemaining`\n // The maximum amount the right maker can sell is `rightMakerAssetAmountRemaining`\n // We have two distinct cases for calculating the fill results:\n // Case 1.\n // If the left maker can buy more than the right maker can sell, then only the right order is fully filled.\n // If the left maker can buy exactly what the right maker can sell, then both orders are fully filled.\n // Case 2.\n // If the left maker cannot buy more than the right maker can sell, then only the left order is fully filled.\n if (leftTakerAssetAmountRemaining >= rightMakerAssetAmountRemaining) {\n // Case 1: Right order is fully filled\n matchedFillResults.right.makerAssetFilledAmount = rightMakerAssetAmountRemaining;\n matchedFillResults.right.takerAssetFilledAmount = rightTakerAssetAmountRemaining;\n matchedFillResults.left.takerAssetFilledAmount = matchedFillResults.right.makerAssetFilledAmount;\n // Round down to ensure the maker's exchange rate does not exceed the price specified by the order. \n // We favor the maker when the exchange rate must be rounded.\n matchedFillResults.left.makerAssetFilledAmount = getPartialAmountFloor(\n leftOrder.makerAssetAmount,\n leftOrder.takerAssetAmount,\n matchedFillResults.left.takerAssetFilledAmount\n );\n } else {\n // Case 2: Left order is fully filled\n matchedFillResults.left.makerAssetFilledAmount = leftMakerAssetAmountRemaining;\n matchedFillResults.left.takerAssetFilledAmount = leftTakerAssetAmountRemaining;\n matchedFillResults.right.makerAssetFilledAmount = matchedFillResults.left.takerAssetFilledAmount;\n // Round up to ensure the maker's exchange rate does not exceed the price specified by the order.\n // We favor the maker when the exchange rate must be rounded.\n matchedFillResults.right.takerAssetFilledAmount = getPartialAmountCeil(\n rightOrder.takerAssetAmount,\n rightOrder.makerAssetAmount,\n matchedFillResults.right.makerAssetFilledAmount\n );\n }\n\n // Calculate amount given to taker\n matchedFillResults.leftMakerAssetSpreadAmount = safeSub(\n matchedFillResults.left.makerAssetFilledAmount,\n matchedFillResults.right.takerAssetFilledAmount\n );\n\n // Compute fees for left order\n matchedFillResults.left.makerFeePaid = getPartialAmountFloor(\n matchedFillResults.left.makerAssetFilledAmount,\n leftOrder.makerAssetAmount,\n leftOrder.makerFee\n );\n matchedFillResults.left.takerFeePaid = getPartialAmountFloor(\n matchedFillResults.left.takerAssetFilledAmount,\n leftOrder.takerAssetAmount,\n leftOrder.takerFee\n );\n\n // Compute fees for right order\n matchedFillResults.right.makerFeePaid = getPartialAmountFloor(\n matchedFillResults.right.makerAssetFilledAmount,\n rightOrder.makerAssetAmount,\n rightOrder.makerFee\n );\n matchedFillResults.right.takerFeePaid = getPartialAmountFloor(\n matchedFillResults.right.takerAssetFilledAmount,\n rightOrder.takerAssetAmount,\n rightOrder.takerFee\n );\n\n // Return fill results\n return matchedFillResults;\n }\n\n /// @dev Settles matched order by transferring appropriate funds between order makers, taker, and fee recipient.\n /// @param leftOrder First matched order.\n /// @param rightOrder Second matched order.\n /// @param takerAddress Address that matched the orders. The taker receives the spread between orders as profit.\n /// @param matchedFillResults Struct holding amounts to transfer between makers, taker, and fee recipients.\n function settleMatchedOrders(\n LibOrder.Order memory leftOrder,\n LibOrder.Order memory rightOrder,\n address takerAddress,\n LibFillResults.MatchedFillResults memory matchedFillResults\n )\n private\n {\n bytes memory zrxAssetData = ZRX_ASSET_DATA;\n // Order makers and taker\n dispatchTransferFrom(\n leftOrder.makerAssetData,\n leftOrder.makerAddress,\n rightOrder.makerAddress,\n matchedFillResults.right.takerAssetFilledAmount\n );\n dispatchTransferFrom(\n rightOrder.makerAssetData,\n rightOrder.makerAddress,\n leftOrder.makerAddress,\n matchedFillResults.left.takerAssetFilledAmount\n );\n dispatchTransferFrom(\n leftOrder.makerAssetData,\n leftOrder.makerAddress,\n takerAddress,\n matchedFillResults.leftMakerAssetSpreadAmount\n );\n\n // Maker fees\n dispatchTransferFrom(\n zrxAssetData,\n leftOrder.makerAddress,\n leftOrder.feeRecipientAddress,\n matchedFillResults.left.makerFeePaid\n );\n dispatchTransferFrom(\n zrxAssetData,\n rightOrder.makerAddress,\n rightOrder.feeRecipientAddress,\n matchedFillResults.right.makerFeePaid\n );\n\n // Taker fees\n if (leftOrder.feeRecipientAddress == rightOrder.feeRecipientAddress) {\n dispatchTransferFrom(\n zrxAssetData,\n takerAddress,\n leftOrder.feeRecipientAddress,\n safeAdd(\n matchedFillResults.left.takerFeePaid,\n matchedFillResults.right.takerFeePaid\n )\n );\n } else {\n dispatchTransferFrom(\n zrxAssetData,\n takerAddress,\n leftOrder.feeRecipientAddress,\n matchedFillResults.left.takerFeePaid\n );\n dispatchTransferFrom(\n zrxAssetData,\n takerAddress,\n rightOrder.feeRecipientAddress,\n matchedFillResults.right.takerFeePaid\n );\n }\n }\n}\n", + "2.0.0/protocol/Exchange/MixinSignatureValidator.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 \"../../utils/LibBytes/LibBytes.sol\";\nimport \"../../utils/ReentrancyGuard/ReentrancyGuard.sol\";\nimport \"./mixins/MSignatureValidator.sol\";\nimport \"./mixins/MTransactions.sol\";\nimport \"./interfaces/IWallet.sol\";\nimport \"./interfaces/IValidator.sol\";\n\n\ncontract MixinSignatureValidator is\n ReentrancyGuard,\n MSignatureValidator,\n MTransactions\n{\n using LibBytes for bytes;\n \n // Mapping of hash => signer => signed\n mapping (bytes32 => mapping (address => bool)) public preSigned;\n\n // Mapping of signer => validator => approved\n mapping (address => mapping (address => bool)) public allowedValidators;\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 if (signerAddress != msg.sender) {\n require(\n isValidSignature(\n hash,\n signerAddress,\n signature\n ),\n \"INVALID_SIGNATURE\"\n );\n }\n preSigned[hash][signerAddress] = true;\n }\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 nonReentrant\n {\n address signerAddress = getCurrentContextAddress();\n allowedValidators[signerAddress][validatorAddress] = approval;\n emit SignatureValidatorApproval(\n signerAddress,\n validatorAddress,\n approval\n );\n }\n\n /// @dev Verifies that a hash has been signed by the given signer.\n /// @param hash Any 32 byte hash.\n /// @param signerAddress Address that should have signed the given hash.\n /// @param signature Proof that the hash has been signed by signer.\n /// @return True if the address recovered from the provided signature matches the input signer address.\n function isValidSignature(\n bytes32 hash,\n address signerAddress,\n bytes memory signature\n )\n public\n view\n returns (bool isValid)\n {\n require(\n signature.length > 0,\n \"LENGTH_GREATER_THAN_0_REQUIRED\"\n );\n\n // Pop last byte off of signature byte array.\n uint8 signatureTypeRaw = uint8(signature.popLastByte());\n\n // Ensure signature is supported\n require(\n signatureTypeRaw < uint8(SignatureType.NSignatureTypes),\n \"SIGNATURE_UNSUPPORTED\"\n );\n\n SignatureType signatureType = SignatureType(signatureTypeRaw);\n\n // Variables are not scoped in Solidity.\n uint8 v;\n bytes32 r;\n bytes32 s;\n address recovered;\n\n // Always illegal signature.\n // This is always an implicit option since a signer can create a\n // signature array with invalid type or length. We may as well make\n // it an explicit option. This aids testing and analysis. It is\n // also the initialization value for the enum type.\n if (signatureType == SignatureType.Illegal) {\n revert(\"SIGNATURE_ILLEGAL\");\n\n // Always invalid signature.\n // Like Illegal, this is always implicitly available and therefore\n // offered explicitly. It can be implicitly created by providing\n // a correctly formatted but incorrect signature.\n } else if (signatureType == SignatureType.Invalid) {\n require(\n signature.length == 0,\n \"LENGTH_0_REQUIRED\"\n );\n isValid = false;\n return isValid;\n\n // Signature using EIP712\n } else if (signatureType == SignatureType.EIP712) {\n require(\n signature.length == 65,\n \"LENGTH_65_REQUIRED\"\n );\n v = uint8(signature[0]);\n r = signature.readBytes32(1);\n s = signature.readBytes32(33);\n recovered = ecrecover(\n hash,\n v,\n r,\n s\n );\n isValid = signerAddress == recovered;\n return isValid;\n\n // Signed using web3.eth_sign\n } else if (signatureType == SignatureType.EthSign) {\n require(\n signature.length == 65,\n \"LENGTH_65_REQUIRED\"\n );\n v = uint8(signature[0]);\n r = signature.readBytes32(1);\n s = signature.readBytes32(33);\n recovered = ecrecover(\n keccak256(abi.encodePacked(\n \"\\x19Ethereum Signed Message:\\n32\",\n hash\n )),\n v,\n r,\n s\n );\n isValid = signerAddress == recovered;\n return isValid;\n\n // Signature verified by wallet contract.\n // If used with an order, the maker of the order is the wallet contract.\n } else if (signatureType == SignatureType.Wallet) {\n isValid = isValidWalletSignature(\n hash,\n signerAddress,\n signature\n );\n return isValid;\n\n // Signature verified by validator contract.\n // If used with an order, the maker of the order can still be an EOA.\n // A signature using this type should be encoded as:\n // | Offset | Length | Contents |\n // | 0x00 | x | Signature to validate |\n // | 0x00 + x | 20 | Address of validator contract |\n // | 0x14 + x | 1 | Signature type is always \"\\x06\" |\n } else if (signatureType == SignatureType.Validator) {\n // Pop last 20 bytes off of signature byte array.\n address validatorAddress = signature.popLast20Bytes();\n \n // Ensure signer has approved validator.\n if (!allowedValidators[signerAddress][validatorAddress]) {\n return false;\n }\n isValid = isValidValidatorSignature(\n validatorAddress,\n hash,\n signerAddress,\n signature\n );\n return isValid;\n\n // Signer signed hash previously using the preSign function.\n } else if (signatureType == SignatureType.PreSigned) {\n isValid = preSigned[hash][signerAddress];\n return isValid;\n }\n\n // Anything else is illegal (We do not return false because\n // the signature may actually be valid, just not in a format\n // that we currently support. In this case returning false\n // may lead the caller to incorrectly believe that the\n // signature was invalid.)\n revert(\"SIGNATURE_UNSUPPORTED\");\n }\n\n /// @dev Verifies signature using logic defined by Wallet contract.\n /// @param hash Any 32 byte hash.\n /// @param walletAddress Address that should have signed the given hash\n /// and defines its own signature verification method.\n /// @param signature Proof that the hash has been signed by signer.\n /// @return True if signature is valid for given wallet..\n function isValidWalletSignature(\n bytes32 hash,\n address walletAddress,\n bytes signature\n )\n internal\n view\n returns (bool isValid)\n {\n bytes memory calldata = abi.encodeWithSelector(\n IWallet(walletAddress).isValidSignature.selector,\n hash,\n signature\n );\n assembly {\n let cdStart := add(calldata, 32)\n let success := staticcall(\n gas, // forward all gas\n walletAddress, // address of Wallet contract\n cdStart, // pointer to start of input\n mload(calldata), // length of input\n cdStart, // write input over output\n 32 // output size is 32 bytes\n )\n\n switch success\n case 0 {\n // Revert with `Error(\"WALLET_ERROR\")`\n mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)\n mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)\n mstore(64, 0x0000000c57414c4c45545f4552524f5200000000000000000000000000000000)\n mstore(96, 0)\n revert(0, 100)\n }\n case 1 {\n // Signature is valid if call did not revert and returned true\n isValid := mload(cdStart)\n }\n }\n return isValid;\n }\n\n /// @dev Verifies signature using logic defined by Validator contract.\n /// @param validatorAddress Address of validator contract.\n /// @param hash Any 32 byte hash.\n /// @param signerAddress Address that should have signed the given hash.\n /// @param signature Proof that the hash has been signed by signer.\n /// @return True if the address recovered from the provided signature matches the input signer address.\n function isValidValidatorSignature(\n address validatorAddress,\n bytes32 hash,\n address signerAddress,\n bytes signature\n )\n internal\n view\n returns (bool isValid)\n {\n bytes memory calldata = abi.encodeWithSelector(\n IValidator(signerAddress).isValidSignature.selector,\n hash,\n signerAddress,\n signature\n );\n assembly {\n let cdStart := add(calldata, 32)\n let success := staticcall(\n gas, // forward all gas\n validatorAddress, // address of Validator contract\n cdStart, // pointer to start of input\n mload(calldata), // length of input\n cdStart, // write input over output\n 32 // output size is 32 bytes\n )\n\n switch success\n case 0 {\n // Revert with `Error(\"VALIDATOR_ERROR\")`\n mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)\n mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)\n mstore(64, 0x0000000f56414c494441544f525f4552524f5200000000000000000000000000)\n mstore(96, 0)\n revert(0, 100)\n }\n case 1 {\n // Signature is valid if call did not revert and returned true\n isValid := mload(cdStart)\n }\n }\n return isValid;\n }\n}\n", + "2.0.0/protocol/Exchange/MixinTransactions.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\nimport \"./libs/LibExchangeErrors.sol\";\nimport \"./mixins/MSignatureValidator.sol\";\nimport \"./mixins/MTransactions.sol\";\nimport \"./libs/LibEIP712.sol\";\n\n\ncontract MixinTransactions is\n LibEIP712,\n MSignatureValidator,\n MTransactions\n{\n\n // Mapping of transaction hash => executed\n // This prevents transactions from being executed more than once.\n mapping (bytes32 => bool) public transactions;\n\n // Address of current transaction signer\n address public currentContextAddress;\n\n // Hash for the EIP712 ZeroEx Transaction Schema\n bytes32 constant internal EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH = keccak256(abi.encodePacked(\n \"ZeroExTransaction(\",\n \"uint256 salt,\",\n \"address signerAddress,\",\n \"bytes data\",\n \")\"\n ));\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 // Prevent reentrancy\n require(\n currentContextAddress == address(0),\n \"REENTRANCY_ILLEGAL\"\n );\n\n bytes32 transactionHash = hashEIP712Message(hashZeroExTransaction(\n salt,\n signerAddress,\n data\n ));\n\n // Validate transaction has not been executed\n require(\n !transactions[transactionHash],\n \"INVALID_TX_HASH\"\n );\n\n // Transaction always valid if signer is sender of transaction\n if (signerAddress != msg.sender) {\n // Validate signature\n require(\n isValidSignature(\n transactionHash,\n signerAddress,\n signature\n ),\n \"INVALID_TX_SIGNATURE\"\n );\n\n // Set the current transaction signer\n currentContextAddress = signerAddress;\n }\n\n // Execute transaction\n transactions[transactionHash] = true;\n require(\n address(this).delegatecall(data),\n \"FAILED_EXECUTION\"\n );\n\n // Reset current transaction signer if it was previously updated\n if (signerAddress != msg.sender) {\n currentContextAddress = address(0);\n }\n }\n\n /// @dev Calculates EIP712 hash of the Transaction.\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 /// @return EIP712 hash of the Transaction.\n function hashZeroExTransaction(\n uint256 salt,\n address signerAddress,\n bytes memory data\n )\n internal\n pure\n returns (bytes32 result)\n {\n bytes32 schemaHash = EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH;\n bytes32 dataHash = keccak256(data);\n\n // Assembly for more efficiently computing:\n // keccak256(abi.encodePacked(\n // EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH,\n // salt,\n // bytes32(signerAddress),\n // keccak256(data)\n // ));\n\n assembly {\n // Load free memory pointer\n let memPtr := mload(64)\n\n mstore(memPtr, schemaHash) // hash of schema\n mstore(add(memPtr, 32), salt) // salt\n mstore(add(memPtr, 64), and(signerAddress, 0xffffffffffffffffffffffffffffffffffffffff)) // signerAddress\n mstore(add(memPtr, 96), dataHash) // hash of data\n\n // Compute hash\n result := keccak256(memPtr, 128)\n }\n return result;\n }\n\n /// @dev The current function will be called in the context of this address (either 0x transaction signer or `msg.sender`).\n /// If calling a fill function, this address will represent the taker.\n /// If calling a cancel function, this address will represent the maker.\n /// @return Signer of 0x transaction if entry point is `executeTransaction`.\n /// `msg.sender` if entry point is any other function.\n function getCurrentContextAddress()\n internal\n view\n returns (address)\n {\n address currentContextAddress_ = currentContextAddress;\n address contextAddress = currentContextAddress_ == address(0) ? msg.sender : currentContextAddress_;\n return contextAddress;\n }\n}\n", + "2.0.0/protocol/Exchange/MixinWrapperFunctions.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 \"../../utils/ReentrancyGuard/ReentrancyGuard.sol\";\nimport \"./libs/LibMath.sol\";\nimport \"./libs/LibOrder.sol\";\nimport \"./libs/LibFillResults.sol\";\nimport \"./libs/LibAbiEncoder.sol\";\nimport \"./mixins/MExchangeCore.sol\";\nimport \"./mixins/MWrapperFunctions.sol\";\n\n\ncontract MixinWrapperFunctions is\n ReentrancyGuard,\n LibMath,\n LibFillResults,\n LibAbiEncoder,\n MExchangeCore,\n MWrapperFunctions\n{\n\n /// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled.\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 function fillOrKillOrder(\n LibOrder.Order memory order,\n uint256 takerAssetFillAmount,\n bytes memory signature\n )\n public\n nonReentrant\n returns (FillResults memory fillResults)\n {\n fillResults = fillOrKillOrderInternal(\n order,\n takerAssetFillAmount,\n signature\n );\n return fillResults;\n }\n\n /// @dev Fills the input order.\n /// Returns false if the transaction would otherwise revert.\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 fillOrderNoThrow(\n LibOrder.Order memory order,\n uint256 takerAssetFillAmount,\n bytes memory signature\n )\n public\n returns (FillResults memory fillResults)\n {\n // ABI encode calldata for `fillOrder`\n bytes memory fillOrderCalldata = abiEncodeFillOrder(\n order,\n takerAssetFillAmount,\n signature\n );\n\n // Delegate to `fillOrder` and handle any exceptions gracefully\n assembly {\n let success := delegatecall(\n gas, // forward all gas, TODO: look into gas consumption of assert/throw\n address, // call address of this contract\n add(fillOrderCalldata, 32), // pointer to start of input (skip array length in first 32 bytes)\n mload(fillOrderCalldata), // length of input\n fillOrderCalldata, // write output over input\n 128 // output size is 128 bytes\n )\n if success {\n mstore(fillResults, mload(fillOrderCalldata))\n mstore(add(fillResults, 32), mload(add(fillOrderCalldata, 32)))\n mstore(add(fillResults, 64), mload(add(fillOrderCalldata, 64)))\n mstore(add(fillResults, 96), mload(add(fillOrderCalldata, 96)))\n }\n }\n return fillResults;\n }\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 /// NOTE: makerAssetFilledAmount and takerAssetFilledAmount may include amounts filled of different assets.\n function batchFillOrders(\n LibOrder.Order[] memory orders,\n uint256[] memory takerAssetFillAmounts,\n bytes[] memory signatures\n )\n public\n nonReentrant\n returns (FillResults memory totalFillResults)\n {\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n FillResults memory singleFillResults = fillOrderInternal(\n orders[i],\n takerAssetFillAmounts[i],\n signatures[i]\n );\n addFillResults(totalFillResults, singleFillResults);\n }\n return totalFillResults;\n }\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 /// NOTE: makerAssetFilledAmount and takerAssetFilledAmount may include amounts filled of different assets.\n function batchFillOrKillOrders(\n LibOrder.Order[] memory orders,\n uint256[] memory takerAssetFillAmounts,\n bytes[] memory signatures\n )\n public\n nonReentrant\n returns (FillResults memory totalFillResults)\n {\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n FillResults memory singleFillResults = fillOrKillOrderInternal(\n orders[i],\n takerAssetFillAmounts[i],\n signatures[i]\n );\n addFillResults(totalFillResults, singleFillResults);\n }\n return totalFillResults;\n }\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 /// NOTE: makerAssetFilledAmount and takerAssetFilledAmount may include amounts filled of different assets.\n function batchFillOrdersNoThrow(\n LibOrder.Order[] memory orders,\n uint256[] memory takerAssetFillAmounts,\n bytes[] memory signatures\n )\n public\n returns (FillResults memory totalFillResults)\n {\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n FillResults memory singleFillResults = fillOrderNoThrow(\n orders[i],\n takerAssetFillAmounts[i],\n signatures[i]\n );\n addFillResults(totalFillResults, singleFillResults);\n }\n return totalFillResults;\n }\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 nonReentrant\n returns (FillResults memory totalFillResults)\n {\n bytes memory takerAssetData = orders[0].takerAssetData;\n \n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n\n // We assume that asset being sold by taker is the same for each order.\n // Rather than passing this in as calldata, we use the takerAssetData from the first order in all later orders.\n orders[i].takerAssetData = takerAssetData;\n\n // Calculate the remaining amount of takerAsset to sell\n uint256 remainingTakerAssetFillAmount = safeSub(takerAssetFillAmount, totalFillResults.takerAssetFilledAmount);\n\n // Attempt to sell the remaining amount of takerAsset\n FillResults memory singleFillResults = fillOrderInternal(\n orders[i],\n remainingTakerAssetFillAmount,\n signatures[i]\n );\n\n // Update amounts filled and fees paid by maker and taker\n addFillResults(totalFillResults, singleFillResults);\n\n // Stop execution if the entire amount of takerAsset has been sold\n if (totalFillResults.takerAssetFilledAmount >= takerAssetFillAmount) {\n break;\n }\n }\n return totalFillResults;\n }\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 (FillResults memory totalFillResults)\n {\n bytes memory takerAssetData = orders[0].takerAssetData;\n\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n\n // We assume that asset being sold by taker is the same for each order.\n // Rather than passing this in as calldata, we use the takerAssetData from the first order in all later orders.\n orders[i].takerAssetData = takerAssetData;\n\n // Calculate the remaining amount of takerAsset to sell\n uint256 remainingTakerAssetFillAmount = safeSub(takerAssetFillAmount, totalFillResults.takerAssetFilledAmount);\n\n // Attempt to sell the remaining amount of takerAsset\n FillResults memory singleFillResults = fillOrderNoThrow(\n orders[i],\n remainingTakerAssetFillAmount,\n signatures[i]\n );\n\n // Update amounts filled and fees paid by maker and taker\n addFillResults(totalFillResults, singleFillResults);\n\n // Stop execution if the entire amount of takerAsset has been sold\n if (totalFillResults.takerAssetFilledAmount >= takerAssetFillAmount) {\n break;\n }\n }\n return totalFillResults;\n }\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 nonReentrant\n returns (FillResults memory totalFillResults)\n {\n bytes memory makerAssetData = orders[0].makerAssetData;\n\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n\n // We assume that asset being bought by taker is the same for each order.\n // Rather than passing this in as calldata, we copy the makerAssetData from the first order onto all later orders.\n orders[i].makerAssetData = makerAssetData;\n\n // Calculate the remaining amount of makerAsset to buy\n uint256 remainingMakerAssetFillAmount = safeSub(makerAssetFillAmount, totalFillResults.makerAssetFilledAmount);\n\n // Convert the remaining amount of makerAsset to buy into remaining amount\n // of takerAsset to sell, assuming entire amount can be sold in the current order\n uint256 remainingTakerAssetFillAmount = getPartialAmountFloor(\n orders[i].takerAssetAmount,\n orders[i].makerAssetAmount,\n remainingMakerAssetFillAmount\n );\n\n // Attempt to sell the remaining amount of takerAsset\n FillResults memory singleFillResults = fillOrderInternal(\n orders[i],\n remainingTakerAssetFillAmount,\n signatures[i]\n );\n\n // Update amounts filled and fees paid by maker and taker\n addFillResults(totalFillResults, singleFillResults);\n\n // Stop execution if the entire amount of makerAsset has been bought\n if (totalFillResults.makerAssetFilledAmount >= makerAssetFillAmount) {\n break;\n }\n }\n return totalFillResults;\n }\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 (FillResults memory totalFillResults)\n {\n bytes memory makerAssetData = orders[0].makerAssetData;\n\n uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n\n // We assume that asset being bought by taker is the same for each order.\n // Rather than passing this in as calldata, we copy the makerAssetData from the first order onto all later orders.\n orders[i].makerAssetData = makerAssetData;\n\n // Calculate the remaining amount of makerAsset to buy\n uint256 remainingMakerAssetFillAmount = safeSub(makerAssetFillAmount, totalFillResults.makerAssetFilledAmount);\n\n // Convert the remaining amount of makerAsset to buy into remaining amount\n // of takerAsset to sell, assuming entire amount can be sold in the current order\n uint256 remainingTakerAssetFillAmount = getPartialAmountFloor(\n orders[i].takerAssetAmount,\n orders[i].makerAssetAmount,\n remainingMakerAssetFillAmount\n );\n\n // Attempt to sell the remaining amount of takerAsset\n FillResults memory singleFillResults = fillOrderNoThrow(\n orders[i],\n remainingTakerAssetFillAmount,\n signatures[i]\n );\n\n // Update amounts filled and fees paid by maker and taker\n addFillResults(totalFillResults, singleFillResults);\n\n // Stop execution if the entire amount of makerAsset has been bought\n if (totalFillResults.makerAssetFilledAmount >= makerAssetFillAmount) {\n break;\n }\n }\n return totalFillResults;\n }\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 uint256 ordersLength = orders.length;\n for (uint256 i = 0; i != ordersLength; i++) {\n cancelOrder(orders[i]);\n }\n }\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 uint256 ordersLength = orders.length;\n LibOrder.OrderInfo[] memory ordersInfo = new LibOrder.OrderInfo[](ordersLength);\n for (uint256 i = 0; i != ordersLength; i++) {\n ordersInfo[i] = getOrderInfo(orders[i]);\n }\n return ordersInfo;\n }\n\n /// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled.\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 function fillOrKillOrderInternal(\n LibOrder.Order memory order,\n uint256 takerAssetFillAmount,\n bytes memory signature\n )\n internal\n returns (FillResults memory fillResults)\n {\n fillResults = fillOrderInternal(\n order,\n takerAssetFillAmount,\n signature\n );\n require(\n fillResults.takerAssetFilledAmount == takerAssetFillAmount,\n \"COMPLETE_FILL_FAILED\"\n );\n return fillResults;\n }\n}\n", "2.0.0/protocol/Exchange/interfaces/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", "2.0.0/protocol/Exchange/interfaces/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", "2.0.0/protocol/Exchange/interfaces/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 \"../libs/LibOrder.sol\";\nimport \"../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", @@ -742,13 +791,14 @@ "2.0.0/protocol/Exchange/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 // 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", "2.0.0/protocol/Exchange/libs/LibExchangeErrors.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\n// solhint-disable\npragma solidity 0.4.24;\n\n\n/// @dev This contract documents the revert reasons used in the Exchange contract.\n/// This contract is intended to serve as a reference, but is not actually used for efficiency reasons.\ncontract LibExchangeErrors {\n\n /// Order validation errors ///\n string constant ORDER_UNFILLABLE = \"ORDER_UNFILLABLE\"; // Order cannot be filled.\n string constant INVALID_MAKER = \"INVALID_MAKER\"; // Invalid makerAddress.\n string constant INVALID_TAKER = \"INVALID_TAKER\"; // Invalid takerAddress.\n string constant INVALID_SENDER = \"INVALID_SENDER\"; // Invalid `msg.sender`.\n string constant INVALID_ORDER_SIGNATURE = \"INVALID_ORDER_SIGNATURE\"; // Signature validation failed. \n \n /// fillOrder validation errors ///\n string constant INVALID_TAKER_AMOUNT = \"INVALID_TAKER_AMOUNT\"; // takerAssetFillAmount cannot equal 0.\n string constant ROUNDING_ERROR = \"ROUNDING_ERROR\"; // Rounding error greater than 0.1% of takerAssetFillAmount. \n \n /// Signature validation errors ///\n string constant INVALID_SIGNATURE = \"INVALID_SIGNATURE\"; // Signature validation failed. \n string constant SIGNATURE_ILLEGAL = \"SIGNATURE_ILLEGAL\"; // Signature type is illegal.\n string constant SIGNATURE_UNSUPPORTED = \"SIGNATURE_UNSUPPORTED\"; // Signature type unsupported.\n \n /// cancelOrdersUptTo errors ///\n string constant INVALID_NEW_ORDER_EPOCH = \"INVALID_NEW_ORDER_EPOCH\"; // Specified salt must be greater than or equal to existing orderEpoch.\n\n /// fillOrKillOrder errors ///\n string constant COMPLETE_FILL_FAILED = \"COMPLETE_FILL_FAILED\"; // Desired takerAssetFillAmount could not be completely filled. \n\n /// matchOrders errors ///\n string constant NEGATIVE_SPREAD_REQUIRED = \"NEGATIVE_SPREAD_REQUIRED\"; // Matched orders must have a negative spread.\n\n /// Transaction errors ///\n string constant REENTRANCY_ILLEGAL = \"REENTRANCY_ILLEGAL\"; // Recursive reentrancy is not allowed. \n string constant INVALID_TX_HASH = \"INVALID_TX_HASH\"; // Transaction has already been executed. \n string constant INVALID_TX_SIGNATURE = \"INVALID_TX_SIGNATURE\"; // Signature validation failed. \n string constant FAILED_EXECUTION = \"FAILED_EXECUTION\"; // Transaction execution failed. \n \n /// registerAssetProxy errors ///\n string constant ASSET_PROXY_ALREADY_EXISTS = \"ASSET_PROXY_ALREADY_EXISTS\"; // AssetProxy with same id already exists.\n\n /// dispatchTransferFrom errors ///\n string constant ASSET_PROXY_DOES_NOT_EXIST = \"ASSET_PROXY_DOES_NOT_EXIST\"; // No assetProxy registered at given id.\n string constant TRANSFER_FAILED = \"TRANSFER_FAILED\"; // Asset transfer unsuccesful.\n\n /// Length validation errors ///\n string constant LENGTH_GREATER_THAN_0_REQUIRED = \"LENGTH_GREATER_THAN_0_REQUIRED\"; // Byte array must have a length greater than 0.\n string constant LENGTH_GREATER_THAN_3_REQUIRED = \"LENGTH_GREATER_THAN_3_REQUIRED\"; // Byte array must have a length greater than 3.\n string constant LENGTH_0_REQUIRED = \"LENGTH_0_REQUIRED\"; // Byte array must have a length of 0.\n string constant LENGTH_65_REQUIRED = \"LENGTH_65_REQUIRED\"; // Byte array must have a length of 65.\n}\n", "2.0.0/protocol/Exchange/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 \"../../../utils/SafeMath/SafeMath.sol\";\n\n\ncontract LibFillResults is\n SafeMath\n{\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", - "2.0.0/protocol/Exchange/libs/LibMath.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 \"../../../utils/SafeMath/SafeMath.sol\";\n\n\ncontract LibMath is\n SafeMath\n{\n\n /// @dev Calculates partial value given a numerator and denominator.\n /// @param numerator Numerator.\n /// @param denominator Denominator.\n /// @param target Value to calculate partial of.\n /// @return Partial value of target.\n function getPartialAmount(\n uint256 numerator,\n uint256 denominator,\n uint256 target\n )\n internal\n pure\n returns (uint256 partialAmount)\n {\n partialAmount = safeDiv(\n safeMul(numerator, target),\n denominator\n );\n return partialAmount;\n }\n\n /// @dev Checks if rounding error > 0.1%.\n /// @param numerator Numerator.\n /// @param denominator Denominator.\n /// @param target Value to multiply with numerator/denominator.\n /// @return Rounding error is present.\n function isRoundingError(\n uint256 numerator,\n uint256 denominator,\n uint256 target\n )\n internal\n pure\n returns (bool isError)\n {\n uint256 remainder = mulmod(target, numerator, denominator);\n if (remainder == 0) {\n return false; // No rounding error.\n }\n\n uint256 errPercentageTimes1000000 = safeDiv(\n safeMul(remainder, 1000000),\n safeMul(numerator, target)\n );\n isError = errPercentageTimes1000000 > 1000;\n return isError;\n }\n}\n", + "2.0.0/protocol/Exchange/libs/LibMath.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 \"../../../utils/SafeMath/SafeMath.sol\";\n\n\ncontract LibMath is\n SafeMath\n{\n\n /// @dev Calculates partial value given a numerator and denominator rounded down.\n /// @param numerator Numerator.\n /// @param denominator Denominator.\n /// @param target Value to calculate partial of.\n /// @return Partial value of target rounded down.\n function getPartialAmountFloor(\n uint256 numerator,\n uint256 denominator,\n uint256 target\n )\n internal\n pure\n returns (uint256 partialAmount)\n {\n require(\n denominator > 0,\n \"DIVISION_BY_ZERO\"\n );\n \n partialAmount = safeDiv(\n safeMul(numerator, target),\n denominator\n );\n return partialAmount;\n }\n \n /// @dev Calculates partial value given a numerator and denominator rounded down.\n /// @param numerator Numerator.\n /// @param denominator Denominator.\n /// @param target Value to calculate partial of.\n /// @return Partial value of target rounded up.\n function getPartialAmountCeil(\n uint256 numerator,\n uint256 denominator,\n uint256 target\n )\n internal\n pure\n returns (uint256 partialAmount)\n {\n require(\n denominator > 0,\n \"DIVISION_BY_ZERO\"\n );\n \n // safeDiv computes `floor(a / b)`. We use the identity (a, b integer):\n // ceil(a / b) = floor((a + b - 1) / b)\n // To implement `ceil(a / b)` using safeDiv.\n partialAmount = safeDiv(\n safeAdd(\n safeMul(numerator, target),\n safeSub(denominator, 1)\n ),\n denominator\n );\n return partialAmount;\n }\n \n /// @dev Checks if rounding error >= 0.1% when rounding down.\n /// @param numerator Numerator.\n /// @param denominator Denominator.\n /// @param target Value to multiply with numerator/denominator.\n /// @return Rounding error is present.\n function isRoundingErrorFloor(\n uint256 numerator,\n uint256 denominator,\n uint256 target\n )\n internal\n pure\n returns (bool isError)\n {\n require(\n denominator > 0,\n \"DIVISION_BY_ZERO\"\n );\n \n // The absolute rounding error is the difference between the rounded\n // value and the ideal value. The relative rounding error is the\n // absolute rounding error divided by the absolute value of the\n // ideal value. This is undefined when the ideal value is zero.\n //\n // The ideal value is `numerator * target / denominator`.\n // Let's call `numerator * target % denominator` the remainder.\n // The absolute error is `remainder / denominator`.\n //\n // When the ideal value is zero, we require the absolute error to\n // be zero. Fortunately, this is always the case. The ideal value is\n // zero iff `numerator == 0` and/or `target == 0`. In this case the\n // remainder and absolute error are also zero. \n if (target == 0 || numerator == 0) {\n return false;\n }\n \n // Otherwise, we want the relative rounding error to be strictly\n // less than 0.1%.\n // The relative error is `remainder / (numerator * target)`.\n // We want the relative error less than 1 / 1000:\n // remainder / (numerator * denominator) < 1 / 1000\n // or equivalently:\n // 1000 * remainder < numerator * target\n // so we have a rounding error iff:\n // 1000 * remainder >= numerator * target\n uint256 remainder = mulmod(target, numerator, denominator);\n isError = safeMul(1000, remainder) >= safeMul(numerator, target);\n return isError;\n }\n \n /// @dev Checks if rounding error >= 0.1% when rounding up.\n /// @param numerator Numerator.\n /// @param denominator Denominator.\n /// @param target Value to multiply with numerator/denominator.\n /// @return Rounding error is present.\n function isRoundingErrorCeil(\n uint256 numerator,\n uint256 denominator,\n uint256 target\n )\n internal\n pure\n returns (bool isError)\n {\n require(\n denominator > 0,\n \"DIVISION_BY_ZERO\"\n );\n \n // See the comments in `isRoundingError`.\n if (target == 0 || numerator == 0) {\n // When either is zero, the ideal value and rounded value are zero\n // and there is no rounding error. (Although the relative error\n // is undefined.)\n return false;\n }\n // Compute remainder as before\n uint256 remainder = mulmod(target, numerator, denominator);\n // TODO: safeMod\n remainder = safeSub(denominator, remainder) % denominator;\n isError = safeMul(1000, remainder) >= safeMul(numerator, target);\n return isError;\n }\n}\n", "2.0.0/protocol/Exchange/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\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", "2.0.0/protocol/Exchange/mixins/MAssetProxyDispatcher.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 \"../interfaces/IAssetProxyDispatcher.sol\";\n\n\ncontract MAssetProxyDispatcher is\n IAssetProxyDispatcher\n{\n\n // Logs registration of new asset proxy\n event AssetProxyRegistered(\n bytes4 id, // Id of new registered AssetProxy.\n address assetProxy // Address of new registered AssetProxy.\n );\n\n /// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws.\n /// @param assetData Byte array encoded for the asset.\n /// @param from Address to transfer token from.\n /// @param to Address to transfer token to.\n /// @param amount Amount of token to transfer.\n function dispatchTransferFrom(\n bytes memory assetData,\n address from,\n address to,\n uint256 amount\n )\n internal;\n}\n", - "2.0.0/protocol/Exchange/mixins/MExchangeCore.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 \"../libs/LibOrder.sol\";\nimport \"../libs/LibFillResults.sol\";\nimport \"../interfaces/IExchangeCore.sol\";\n\n\ncontract MExchangeCore is\n IExchangeCore\n{\n // Fill event is emitted whenever an order is filled.\n event Fill(\n address indexed makerAddress, // Address that created the order. \n address indexed feeRecipientAddress, // Address that received fees.\n address takerAddress, // Address that filled the order.\n address senderAddress, // Address that called the Exchange contract (msg.sender).\n uint256 makerAssetFilledAmount, // Amount of makerAsset sold by maker and bought by taker. \n uint256 takerAssetFilledAmount, // Amount of takerAsset sold by taker and bought by maker.\n uint256 makerFeePaid, // Amount of ZRX paid to feeRecipient by maker.\n uint256 takerFeePaid, // Amount of ZRX paid to feeRecipient by taker.\n bytes32 indexed orderHash, // EIP712 hash of order (see LibOrder.getOrderHash).\n bytes makerAssetData, // Encoded data specific to makerAsset. \n bytes takerAssetData // Encoded data specific to takerAsset.\n );\n\n // Cancel event is emitted whenever an individual order is cancelled.\n event Cancel(\n address indexed makerAddress, // Address that created the order. \n address indexed feeRecipientAddress, // Address that would have recieved fees if order was filled. \n address senderAddress, // Address that called the Exchange contract (msg.sender).\n bytes32 indexed orderHash, // EIP712 hash of order (see LibOrder.getOrderHash).\n bytes makerAssetData, // Encoded data specific to makerAsset. \n bytes takerAssetData // Encoded data specific to takerAsset.\n );\n\n // CancelUpTo event is emitted whenever `cancelOrdersUpTo` is executed succesfully.\n event CancelUpTo(\n address indexed makerAddress, // Orders cancelled must have been created by this address.\n address indexed senderAddress, // Orders cancelled must have a `senderAddress` equal to this address.\n uint256 orderEpoch // Orders with specified makerAddress and senderAddress with a salt less than this value are considered cancelled.\n );\n\n /// @dev Updates state with results of a fill order.\n /// @param order that was filled.\n /// @param takerAddress Address of taker who filled the order.\n /// @param orderTakerAssetFilledAmount Amount of order already filled.\n /// @return fillResults Amounts filled and fees paid by maker and taker.\n function updateFilledState(\n LibOrder.Order memory order,\n address takerAddress,\n bytes32 orderHash,\n uint256 orderTakerAssetFilledAmount,\n LibFillResults.FillResults memory fillResults\n )\n internal;\n\n /// @dev Updates state with results of cancelling an order.\n /// State is only updated if the order is currently fillable.\n /// Otherwise, updating state would have no effect.\n /// @param order that was cancelled.\n /// @param orderHash Hash of order that was cancelled.\n function updateCancelledState(\n LibOrder.Order memory order,\n bytes32 orderHash\n )\n internal;\n\n /// @dev Validates context for fillOrder. Succeeds or throws.\n /// @param order to be filled.\n /// @param orderInfo Status, orderHash, and amount already filled of order.\n /// @param takerAddress Address of order taker.\n /// @param takerAssetFillAmount Desired amount of order to fill by taker.\n /// @param takerAssetFilledAmount Amount of takerAsset that will be filled.\n /// @param signature Proof that the orders was created by its maker.\n function assertValidFill(\n LibOrder.Order memory order,\n LibOrder.OrderInfo memory orderInfo,\n address takerAddress,\n uint256 takerAssetFillAmount,\n uint256 takerAssetFilledAmount,\n bytes memory signature\n )\n internal\n view;\n\n /// @dev Validates context for cancelOrder. Succeeds or throws.\n /// @param order to be cancelled.\n /// @param orderInfo OrderStatus, orderHash, and amount already filled of order.\n function assertValidCancel(\n LibOrder.Order memory order,\n LibOrder.OrderInfo memory orderInfo\n )\n internal\n view;\n\n /// @dev Calculates amounts filled and fees paid by maker and taker.\n /// @param order to be filled.\n /// @param takerAssetFilledAmount Amount of takerAsset that will be filled.\n /// @return fillResults Amounts filled and fees paid by maker and taker.\n function calculateFillResults(\n LibOrder.Order memory order,\n uint256 takerAssetFilledAmount\n )\n internal\n pure\n returns (LibFillResults.FillResults memory fillResults);\n\n}\n", + "2.0.0/protocol/Exchange/mixins/MExchangeCore.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 \"../libs/LibOrder.sol\";\nimport \"../libs/LibFillResults.sol\";\nimport \"../interfaces/IExchangeCore.sol\";\n\n\ncontract MExchangeCore is\n IExchangeCore\n{\n // Fill event is emitted whenever an order is filled.\n event Fill(\n address indexed makerAddress, // Address that created the order. \n address indexed feeRecipientAddress, // Address that received fees.\n address takerAddress, // Address that filled the order.\n address senderAddress, // Address that called the Exchange contract (msg.sender).\n uint256 makerAssetFilledAmount, // Amount of makerAsset sold by maker and bought by taker. \n uint256 takerAssetFilledAmount, // Amount of takerAsset sold by taker and bought by maker.\n uint256 makerFeePaid, // Amount of ZRX paid to feeRecipient by maker.\n uint256 takerFeePaid, // Amount of ZRX paid to feeRecipient by taker.\n bytes32 indexed orderHash, // EIP712 hash of order (see LibOrder.getOrderHash).\n bytes makerAssetData, // Encoded data specific to makerAsset. \n bytes takerAssetData // Encoded data specific to takerAsset.\n );\n\n // Cancel event is emitted whenever an individual order is cancelled.\n event Cancel(\n address indexed makerAddress, // Address that created the order. \n address indexed feeRecipientAddress, // Address that would have recieved fees if order was filled. \n address senderAddress, // Address that called the Exchange contract (msg.sender).\n bytes32 indexed orderHash, // EIP712 hash of order (see LibOrder.getOrderHash).\n bytes makerAssetData, // Encoded data specific to makerAsset. \n bytes takerAssetData // Encoded data specific to takerAsset.\n );\n\n // CancelUpTo event is emitted whenever `cancelOrdersUpTo` is executed succesfully.\n event CancelUpTo(\n address indexed makerAddress, // Orders cancelled must have been created by this address.\n address indexed senderAddress, // Orders cancelled must have a `senderAddress` equal to this address.\n uint256 orderEpoch // Orders with specified makerAddress and senderAddress with a salt less than this value are considered cancelled.\n );\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 fillOrderInternal(\n LibOrder.Order memory order,\n uint256 takerAssetFillAmount,\n bytes memory signature\n )\n internal\n returns (LibFillResults.FillResults memory fillResults);\n\n /// @dev Updates state with results of a fill order.\n /// @param order that was filled.\n /// @param takerAddress Address of taker who filled the order.\n /// @param orderTakerAssetFilledAmount Amount of order already filled.\n /// @return fillResults Amounts filled and fees paid by maker and taker.\n function updateFilledState(\n LibOrder.Order memory order,\n address takerAddress,\n bytes32 orderHash,\n uint256 orderTakerAssetFilledAmount,\n LibFillResults.FillResults memory fillResults\n )\n internal;\n\n /// @dev Updates state with results of cancelling an order.\n /// State is only updated if the order is currently fillable.\n /// Otherwise, updating state would have no effect.\n /// @param order that was cancelled.\n /// @param orderHash Hash of order that was cancelled.\n function updateCancelledState(\n LibOrder.Order memory order,\n bytes32 orderHash\n )\n internal;\n \n /// @dev Validates context for fillOrder. Succeeds or throws.\n /// @param order to be filled.\n /// @param orderInfo OrderStatus, orderHash, and amount already filled of order.\n /// @param takerAddress Address of order taker.\n /// @param signature Proof that the orders was created by its maker.\n function assertFillableOrder(\n LibOrder.Order memory order,\n LibOrder.OrderInfo memory orderInfo,\n address takerAddress,\n bytes memory signature\n )\n internal\n view;\n \n /// @dev Validates context for fillOrder. Succeeds or throws.\n /// @param order to be filled.\n /// @param orderInfo Status, orderHash, and amount already filled of order.\n /// @param takerAssetFillAmount Desired amount of order to fill by taker.\n /// @param takerAssetFilledAmount Amount of takerAsset that will be filled.\n /// @param makerAssetFilledAmount Amount of makerAsset that will be transfered.\n function assertValidFill(\n LibOrder.Order memory order,\n LibOrder.OrderInfo memory orderInfo,\n uint256 takerAssetFillAmount,\n uint256 takerAssetFilledAmount,\n uint256 makerAssetFilledAmount\n )\n internal\n view;\n\n /// @dev Validates context for cancelOrder. Succeeds or throws.\n /// @param order to be cancelled.\n /// @param orderInfo OrderStatus, orderHash, and amount already filled of order.\n function assertValidCancel(\n LibOrder.Order memory order,\n LibOrder.OrderInfo memory orderInfo\n )\n internal\n view;\n\n /// @dev Calculates amounts filled and fees paid by maker and taker.\n /// @param order to be filled.\n /// @param takerAssetFilledAmount Amount of takerAsset that will be filled.\n /// @return fillResults Amounts filled and fees paid by maker and taker.\n function calculateFillResults(\n LibOrder.Order memory order,\n uint256 takerAssetFilledAmount\n )\n internal\n pure\n returns (LibFillResults.FillResults memory fillResults);\n\n}\n", "2.0.0/protocol/Exchange/mixins/MMatchOrders.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 \"../libs/LibOrder.sol\";\nimport \"../libs/LibFillResults.sol\";\nimport \"../interfaces/IMatchOrders.sol\";\n\n\ncontract MMatchOrders is\n IMatchOrders\n{\n\n /// @dev Validates context for matchOrders. Succeeds or throws.\n /// @param leftOrder First order to match.\n /// @param rightOrder Second order to match.\n function assertValidMatch(\n LibOrder.Order memory leftOrder,\n LibOrder.Order memory rightOrder\n )\n internal\n pure;\n\n /// @dev Calculates fill amounts for the matched orders.\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 leftOrder 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 leftOrderTakerAssetFilledAmount Amount of left order already filled.\n /// @param rightOrderTakerAssetFilledAmount Amount of right order already filled.\n /// @param matchedFillResults Amounts to fill and fees to pay by maker and taker of matched orders.\n function calculateMatchedFillResults(\n LibOrder.Order memory leftOrder,\n LibOrder.Order memory rightOrder,\n uint256 leftOrderTakerAssetFilledAmount,\n uint256 rightOrderTakerAssetFilledAmount\n )\n internal\n pure\n returns (LibFillResults.MatchedFillResults memory matchedFillResults);\n\n}\n", - "2.0.0/protocol/Exchange/mixins/MSignatureValidator.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 \"../interfaces/ISignatureValidator.sol\";\n\n\ncontract MSignatureValidator is\n ISignatureValidator\n{\n event SignatureValidatorApproval(\n address indexed signerAddress, // Address that approves or disapproves a contract to verify signatures.\n address indexed validatorAddress, // Address of signature validator contract.\n bool approved // Approval or disapproval of validator contract.\n );\n\n // Allowed signature types.\n enum SignatureType {\n Illegal, // 0x00, default value\n Invalid, // 0x01\n EIP712, // 0x02\n EthSign, // 0x03\n Caller, // 0x04\n Wallet, // 0x05\n Validator, // 0x06\n PreSigned, // 0x07\n Trezor, // 0x08\n NSignatureTypes // 0x09, number of signature types. Always leave at end.\n }\n}\n", + "2.0.0/protocol/Exchange/mixins/MSignatureValidator.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 \"../interfaces/ISignatureValidator.sol\";\n\n\ncontract MSignatureValidator is\n ISignatureValidator\n{\n event SignatureValidatorApproval(\n address indexed signerAddress, // Address that approves or disapproves a contract to verify signatures.\n address indexed validatorAddress, // Address of signature validator contract.\n bool approved // Approval or disapproval of validator contract.\n );\n\n // Allowed signature types.\n enum SignatureType {\n Illegal, // 0x00, default value\n Invalid, // 0x01\n EIP712, // 0x02\n EthSign, // 0x03\n Wallet, // 0x04\n Validator, // 0x05\n PreSigned, // 0x06\n NSignatureTypes // 0x07, number of signature types. Always leave at end.\n }\n\n /// @dev Verifies signature using logic defined by Wallet contract.\n /// @param hash Any 32 byte hash.\n /// @param walletAddress Address that should have signed the given hash\n /// and defines its own signature verification method.\n /// @param signature Proof that the hash has been signed by signer.\n /// @return True if the address recovered from the provided signature matches the input signer address.\n function isValidWalletSignature(\n bytes32 hash,\n address walletAddress,\n bytes signature\n )\n internal\n view\n returns (bool isValid);\n\n /// @dev Verifies signature using logic defined by Validator contract.\n /// @param validatorAddress Address of validator contract.\n /// @param hash Any 32 byte hash.\n /// @param signerAddress Address that should have signed the given hash.\n /// @param signature Proof that the hash has been signed by signer.\n /// @return True if the address recovered from the provided signature matches the input signer address.\n function isValidValidatorSignature(\n address validatorAddress,\n bytes32 hash,\n address signerAddress,\n bytes signature\n )\n internal\n view\n returns (bool isValid);\n}\n", "2.0.0/protocol/Exchange/mixins/MTransactions.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\nimport \"../interfaces/ITransactions.sol\";\n\n\ncontract MTransactions is\n ITransactions\n{\n\n /// @dev The current function will be called in the context of this address (either 0x transaction signer or `msg.sender`).\n /// If calling a fill function, this address will represent the taker.\n /// If calling a cancel function, this address will represent the maker.\n /// @return Signer of 0x transaction if entry point is `executeTransaction`.\n /// `msg.sender` if entry point is any other function.\n function getCurrentContextAddress()\n internal\n view\n returns (address);\n}\n", + "2.0.0/protocol/Exchange/mixins/MWrapperFunctions.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 \"../libs/LibOrder.sol\";\nimport \"../libs/LibFillResults.sol\";\nimport \"../interfaces/IWrapperFunctions.sol\";\n\n\ncontract MWrapperFunctions {\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 fillOrKillOrderInternal(\n LibOrder.Order memory order,\n uint256 takerAssetFillAmount,\n bytes memory signature\n )\n internal\n returns (LibFillResults.FillResults memory fillResults);\n}\n", "2.0.0/tokens/ERC20Token/ERC20Token.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 \"./IERC20Token.sol\";\n\n\ncontract ERC20Token is\n IERC20Token\n{\n\n mapping (address => uint256) internal balances;\n mapping (address => mapping (address => uint256)) internal allowed;\n\n uint256 internal _totalSupply;\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 require(\n balances[msg.sender] >= _value,\n \"ERC20_INSUFFICIENT_BALANCE\"\n );\n require(\n balances[_to] + _value >= balances[_to],\n \"UINT256_OVERFLOW\"\n );\n\n balances[msg.sender] -= _value;\n balances[_to] += _value;\n\n emit Transfer(\n msg.sender,\n _to,\n _value\n );\n\n return true;\n }\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 require(\n balances[_from] >= _value,\n \"ERC20_INSUFFICIENT_BALANCE\"\n );\n require(\n allowed[_from][msg.sender] >= _value,\n \"ERC20_INSUFFICIENT_ALLOWANCE\"\n );\n require(\n balances[_to] + _value >= balances[_to],\n \"UINT256_OVERFLOW\"\n );\n\n balances[_to] += _value;\n balances[_from] -= _value;\n allowed[_from][msg.sender] -= _value;\n \n emit Transfer(\n _from,\n _to,\n _value\n );\n \n return true;\n }\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 allowed[msg.sender][_spender] = _value;\n emit Approval(\n msg.sender,\n _spender,\n _value\n );\n return true;\n }\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 return _totalSupply;\n }\n\n /// @dev Query the balance of owner\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 return balances[_owner];\n }\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 return allowed[_owner][_spender];\n }\n}\n", "2.0.0/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", "2.0.0/tokens/ERC721Token/ERC721Token.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 \"./IERC721Token.sol\";\nimport \"./IERC721Receiver.sol\";\nimport \"../../utils/SafeMath/SafeMath.sol\";\n\n\ncontract ERC721Token is\n IERC721Token,\n SafeMath\n{\n // Function selector for ERC721Receiver.onERC721Received\n // 0x150b7a02\n bytes4 constant internal ERC721_RECEIVED = bytes4(keccak256(\"onERC721Received(address,address,uint256,bytes)\"));\n\n // Mapping of tokenId => owner\n mapping (uint256 => address) internal owners;\n\n // Mapping of tokenId => approved address\n mapping (uint256 => address) internal approvals;\n\n // Mapping of owner => number of tokens owned\n mapping (address => uint256) internal balances;\n\n // Mapping of owner => operator => approved\n mapping (address => mapping (address => bool)) internal operatorApprovals;\n\n /// @notice Transfers the ownership of an NFT from one address to another address\n /// @dev Throws unless `msg.sender` is the current owner, an authorized\n /// operator, or the approved address for this NFT. Throws if `_from` is\n /// not the current owner. Throws if `_to` is the zero address. Throws if\n /// `_tokenId` is not a valid NFT. When transfer is complete, this function\n /// checks if `_to` is a smart contract (code size > 0). If so, it calls\n /// `onERC721Received` on `_to` and throws if the return value is not\n /// `bytes4(keccak256(\"onERC721Received(address,address,uint256,bytes)\"))`.\n /// @param _from The current owner of the NFT\n /// @param _to The new owner\n /// @param _tokenId The NFT to transfer\n /// @param _data Additional data with no specified format, sent in call to `_to`\n function safeTransferFrom(\n address _from,\n address _to,\n uint256 _tokenId,\n bytes _data\n )\n external\n {\n transferFrom(\n _from,\n _to,\n _tokenId\n );\n\n uint256 receiverCodeSize;\n assembly {\n receiverCodeSize := extcodesize(_to)\n }\n if (receiverCodeSize > 0) {\n bytes4 selector = IERC721Receiver(_to).onERC721Received(\n msg.sender,\n _from,\n _tokenId,\n _data\n );\n require(\n selector == ERC721_RECEIVED,\n \"ERC721_INVALID_SELECTOR\"\n );\n }\n }\n\n /// @notice Transfers the ownership of an NFT from one address to another address\n /// @dev This works identically to the other function with an extra data parameter,\n /// except this function just sets data to \"\".\n /// @param _from The current owner of the NFT\n /// @param _to The new owner\n /// @param _tokenId The NFT to transfer\n function safeTransferFrom(\n address _from,\n address _to,\n uint256 _tokenId\n )\n external\n {\n transferFrom(\n _from,\n _to,\n _tokenId\n );\n\n uint256 receiverCodeSize;\n assembly {\n receiverCodeSize := extcodesize(_to)\n }\n if (receiverCodeSize > 0) {\n bytes4 selector = IERC721Receiver(_to).onERC721Received(\n msg.sender,\n _from,\n _tokenId,\n \"\"\n );\n require(\n selector == ERC721_RECEIVED,\n \"ERC721_INVALID_SELECTOR\"\n );\n }\n }\n\n /// @notice Change or reaffirm the approved address for an NFT\n /// @dev The zero address indicates there is no approved address.\n /// Throws unless `msg.sender` is the current NFT owner, or an authorized\n /// operator of the current owner.\n /// @param _approved The new approved NFT controller\n /// @param _tokenId The NFT to approve\n function approve(address _approved, uint256 _tokenId)\n external\n {\n address owner = ownerOf(_tokenId);\n require(\n msg.sender == owner || isApprovedForAll(owner, msg.sender),\n \"ERC721_INVALID_SENDER\"\n );\n\n approvals[_tokenId] = _approved;\n emit Approval(\n owner,\n _approved,\n _tokenId\n );\n }\n\n /// @notice Enable or disable approval for a third party (\"operator\") to manage\n /// all of `msg.sender`'s assets\n /// @dev Emits the ApprovalForAll event. The contract MUST allow\n /// multiple operators per owner.\n /// @param _operator Address to add to the set of authorized operators\n /// @param _approved True if the operator is approved, false to revoke approval\n function setApprovalForAll(address _operator, bool _approved)\n external\n {\n operatorApprovals[msg.sender][_operator] = _approved;\n emit ApprovalForAll(\n msg.sender,\n _operator,\n _approved\n );\n }\n \n /// @notice Count all NFTs assigned to an owner\n /// @dev NFTs assigned to the zero address are considered invalid, and this\n /// function throws for queries about the zero address.\n /// @param _owner An address for whom to query the balance\n /// @return The number of NFTs owned by `_owner`, possibly zero\n function balanceOf(address _owner)\n external\n view\n returns (uint256)\n {\n require(\n _owner != address(0),\n \"ERC721_ZERO_OWNER\"\n );\n return balances[_owner];\n }\n\n /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE\n /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE\n /// THEY MAY BE PERMANENTLY LOST\n /// @dev Throws unless `msg.sender` is the current owner, an authorized\n /// operator, or the approved address for this NFT. Throws if `_from` is\n /// not the current owner. Throws if `_to` is the zero address. Throws if\n /// `_tokenId` is not a valid NFT.\n /// @param _from The current owner of the NFT\n /// @param _to The new owner\n /// @param _tokenId The NFT to transfer\n function transferFrom(\n address _from,\n address _to,\n uint256 _tokenId\n )\n public\n {\n require(\n _to != address(0),\n \"ERC721_ZERO_TO_ADDRESS\"\n );\n\n address owner = ownerOf(_tokenId);\n require(\n _from == owner,\n \"ERC721_OWNER_MISMATCH\"\n );\n\n address spender = msg.sender;\n address approvedAddress = getApproved(_tokenId);\n require(\n spender == owner ||\n isApprovedForAll(owner, spender) ||\n approvedAddress == spender,\n \"ERC721_INVALID_SPENDER\"\n );\n\n if (approvedAddress != address(0)) {\n approvals[_tokenId] = address(0);\n }\n\n owners[_tokenId] = _to;\n balances[_from] = safeSub(balances[_from], 1);\n balances[_to] = safeAdd(balances[_to], 1);\n \n emit Transfer(\n _from,\n _to,\n _tokenId\n );\n }\n\n /// @notice Find the owner of an NFT\n /// @dev NFTs assigned to zero address are considered invalid, and queries\n /// about them do throw.\n /// @param _tokenId The identifier for an NFT\n /// @return The address of the owner of the NFT\n function ownerOf(uint256 _tokenId)\n public\n view\n returns (address)\n {\n address owner = owners[_tokenId];\n require(\n owner != address(0),\n \"ERC721_ZERO_OWNER\"\n );\n return owner;\n }\n\n /// @notice Get the approved address for a single NFT\n /// @dev Throws if `_tokenId` is not a valid NFT.\n /// @param _tokenId The NFT to find the approved address for\n /// @return The approved address for this NFT, or the zero address if there is none\n function getApproved(uint256 _tokenId)\n public\n view\n returns (address)\n {\n return approvals[_tokenId];\n }\n\n /// @notice Query if an address is an authorized operator for another address\n /// @param _owner The address that owns the NFTs\n /// @param _operator The address that acts on behalf of the owner\n /// @return True if `_operator` is an approved operator for `_owner`, false otherwise\n function isApprovedForAll(address _owner, address _operator)\n public\n view\n returns (bool)\n {\n return operatorApprovals[_owner][_operator];\n }\n}\n", @@ -758,9 +808,10 @@ "2.0.0/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 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 return uint256(readBytes32(b, index));\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 assembly {\n result := mload(add(b, 32))\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", "2.0.0/utils/Ownable/IOwnable.sol": "pragma solidity 0.4.24;\n\n/*\n * Ownable\n *\n * Base contract with an owner.\n * Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner.\n */\n\ncontract IOwnable {\n function transferOwnership(address newOwner)\n public;\n}\n", "2.0.0/utils/Ownable/Ownable.sol": "pragma solidity 0.4.24;\n\n/*\n * Ownable\n *\n * Base contract with an owner.\n * Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner.\n */\n\nimport \"./IOwnable.sol\";\n\n\ncontract Ownable is IOwnable {\n address public owner;\n\n constructor ()\n public\n {\n owner = msg.sender;\n }\n\n modifier onlyOwner() {\n require(\n msg.sender == owner,\n \"ONLY_CONTRACT_OWNER\"\n );\n _;\n }\n\n function transferOwnership(address newOwner)\n public\n onlyOwner\n {\n if (newOwner != address(0)) {\n owner = newOwner;\n }\n }\n}\n", + "2.0.0/utils/ReentrancyGuard/ReentrancyGuard.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 ReentrancyGuard {\n\n // Locked state of mutex\n bool private locked = false;\n\n /// @dev Functions with this modifer cannot be reentered. The mutex will be locked\n /// before function execution and unlocked after.\n modifier nonReentrant() {\n // Ensure mutex is unlocked\n require(\n !locked,\n \"REENTRANCY_ILLEGAL\"\n );\n\n // Lock mutex before function call\n locked = true;\n\n // Perform function call\n _;\n\n // Unlock mutex after function call\n locked = false;\n }\n}\n", "2.0.0/utils/SafeMath/SafeMath.sol": "pragma solidity 0.4.24;\n\n\ncontract SafeMath {\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" }, - "sourceTreeHashHex": "0xd6d4955beb696b73455fe763da7472fba92d3695d0c0455879babc4fae8663d3", + "sourceTreeHashHex": "0x41709e5597b9934bd39ebbfec8bdc1b39fa4db97e459fb1f13047a8643a68e76", "compiler": { "name": "solc", "version": "soljson-v0.4.24+commit.e67f0147.js", diff --git a/packages/migrations/package.json b/packages/migrations/package.json index 89cd4207a..bd8451328 100644 --- a/packages/migrations/package.json +++ b/packages/migrations/package.json @@ -8,8 +8,7 @@ "main": "lib/index.js", "types": "lib/index.d.ts", "scripts": { - "watch_without_deps": "yarn pre_build && tsc -w", - "build": "yarn pre_build && tsc", + "build": "yarn pre_build && tsc -b", "pre_build": "run-s compile:v2 copy_artifacts generate_contract_wrappers", "copy_artifacts": "copyfiles 'artifacts/**/*' ./lib", "clean": "shx rm -rf lib src/1.0.0/contract_wrappers src/2.0.0/contract_wrappers src/2.0.0-beta-testnet/contract_wrappers artifacts/2.0.0", diff --git a/packages/migrations/tsconfig.json b/packages/migrations/tsconfig.json index f5f4b37c2..56689eaa3 100644 --- a/packages/migrations/tsconfig.json +++ b/packages/migrations/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "src" }, "include": ["src/**/*"] } diff --git a/packages/monorepo-scripts/package.json b/packages/monorepo-scripts/package.json index a2f2343b8..f1d0ff29c 100644 --- a/packages/monorepo-scripts/package.json +++ b/packages/monorepo-scripts/package.json @@ -9,8 +9,7 @@ "main": "lib/index.js", "types": "lib/index.d.ts", "scripts": { - "watch_without_deps": "tsc -w", - "build": "tsc", + "build": "tsc -b", "lint": "tslint --project .", "clean": "shx rm -rf lib", "test:publish": "run-s build script:publish", diff --git a/packages/monorepo-scripts/src/doc_gen_configs.ts b/packages/monorepo-scripts/src/doc_gen_configs.ts index 6d7560943..102b5d7ca 100644 --- a/packages/monorepo-scripts/src/doc_gen_configs.ts +++ b/packages/monorepo-scripts/src/doc_gen_configs.ts @@ -39,6 +39,7 @@ export const docGenConfigs: DocGenConfigs = { 'EtherTokenWrapper', 'ExchangeWrapper', 'ForwarderWrapper', + 'OrderValidatorWrapper', 'TransactionEncoder', ], // Some types are not explicitly part of the public interface like params, return values, etc... But we still diff --git a/packages/monorepo-scripts/tsconfig.json b/packages/monorepo-scripts/tsconfig.json index 332d3a5e1..c8b1d23e5 100644 --- a/packages/monorepo-scripts/tsconfig.json +++ b/packages/monorepo-scripts/tsconfig.json @@ -2,7 +2,8 @@ "extends": "../../tsconfig", "compilerOptions": { "typeRoots": ["../../node_modules/@types", "node_modules/@types"], - "outDir": "lib" + "outDir": "lib", + "rootDir": "src" }, "include": ["./src/**/*"] } diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json index 77a4142fc..7d2caa0e8 100644 --- a/packages/order-utils/package.json +++ b/packages/order-utils/package.json @@ -8,10 +8,8 @@ "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { - "watch_without_deps": "yarn pre_build && tsc -w", - "build": "run-s pre_build transpile", + "build": "yarn pre_build && tsc -b", "pre_build": "run-s update_artifacts_v2_beta generate_contract_wrappers", - "transpile": "tsc", "generate_contract_wrappers": "abi-gen --abis 'lib/src/artifacts/@(Exchange|IWallet|IValidator|DummyERC20Token|ERC20Proxy|ERC20Token).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers", "update_artifacts_v2_beta": "for i in ${npm_package_config_contracts_v2_beta}; do copyfiles -u 4 ../migrations/artifacts/2.0.0-beta-testnet/$i.json lib/src/artifacts; done;", "test": "yarn run_mocha", @@ -22,7 +20,7 @@ "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "clean": "shx rm -rf lib lib/src/artifacts src/generated_contract_wrappers generated_docs", "lint": "tslint --project . --exclude **/src/generated_contract_wrappers/**/*", - "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES" + "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" }, "config": { "contracts_v2_beta": "IWallet IValidator Exchange ERC20Proxy ERC20Token DummyERC20Token", diff --git a/packages/order-utils/tsconfig.json b/packages/order-utils/tsconfig.json index 8b4cd47a2..718e623c7 100644 --- a/packages/order-utils/tsconfig.json +++ b/packages/order-utils/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "." }, "include": ["src/**/*", "test/**/*"] } diff --git a/packages/order-utils/typedoc-tsconfig.json b/packages/order-utils/typedoc-tsconfig.json new file mode 100644 index 000000000..b9c6b36f3 --- /dev/null +++ b/packages/order-utils/typedoc-tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../typedoc-tsconfig", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["src/**/*", "test/**/*"] +} diff --git a/packages/order-watcher/package.json b/packages/order-watcher/package.json index 0d5bfd48c..27eeca6fd 100644 --- a/packages/order-watcher/package.json +++ b/packages/order-watcher/package.json @@ -12,8 +12,7 @@ "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { - "watch_without_deps": "yarn pre_build && tsc -w", - "build": "yarn pre_build && tsc", + "build": "yarn pre_build && tsc -b", "pre_build": "run-s update_artifacts copy_artifacts generate_contract_wrappers", "lint": "tslint --project . --exclude **/src/generated_contract_wrappers/**/*", "generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers", @@ -26,7 +25,7 @@ "update_artifacts": "for i in ${npm_package_config_contracts_v2_beta}; do copyfiles -u 4 ../migrations/artifacts/2.0.0-beta-testnet/$i.json src/artifacts; done;", "clean": "shx rm -rf _bundles lib test_temp test/artifacts src/generated_contract_wrappers generated_docs", "run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit", - "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES" + "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" }, "config": { "contracts_v2_beta": "AssetProxyOwner ERC20Proxy ERC20Token ERC721Proxy ERC721Token Exchange Forwarder OrderValidator WETH9 ZRXToken", diff --git a/packages/order-watcher/tsconfig.json b/packages/order-watcher/tsconfig.json index e35816553..2ee711adc 100644 --- a/packages/order-watcher/tsconfig.json +++ b/packages/order-watcher/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "." }, "include": ["./src/**/*", "./test/**/*"] } diff --git a/packages/order-watcher/typedoc-tsconfig.json b/packages/order-watcher/typedoc-tsconfig.json new file mode 100644 index 000000000..c9b0af1ae --- /dev/null +++ b/packages/order-watcher/typedoc-tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../typedoc-tsconfig", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["./src/**/*", "./test/**/*"] +} diff --git a/packages/react-docs/package.json b/packages/react-docs/package.json index adc06a501..d500601fd 100644 --- a/packages/react-docs/package.json +++ b/packages/react-docs/package.json @@ -9,8 +9,7 @@ "types": "lib/index.d.ts", "scripts": { "lint": "tslint --project .", - "build": "tsc", - "watch_without_deps": "tsc -w", + "build": "tsc -b", "clean": "shx rm -rf lib" }, "author": "Fabio Berger", @@ -38,7 +37,7 @@ "@0xproject/types": "^1.0.1-rc.6", "@0xproject/utils": "^1.0.7", "@types/lodash": "4.14.104", - "@types/material-ui": "0.18.0", + "@types/material-ui": "^0.20.0", "@types/node": "^8.0.53", "@types/react": "*", "@types/react-dom": "*", @@ -46,9 +45,9 @@ "basscss": "^8.0.3", "compare-versions": "^3.0.1", "lodash": "^4.17.5", - "material-ui": "^0.17.1", - "react": "15.6.1", - "react-dom": "15.6.1", + "material-ui": "^0.20.0", + "react": "^16.4.2", + "react-dom": "^16.4.2", "react-markdown": "^3.2.2", "react-scroll": "0xproject/react-scroll#similar-to-pr-330", "react-tooltip": "^3.2.7", diff --git a/packages/react-docs/src/docs_info.ts b/packages/react-docs/src/docs_info.ts index f9137d69d..fa5aa0da3 100644 --- a/packages/react-docs/src/docs_info.ts +++ b/packages/react-docs/src/docs_info.ts @@ -1,6 +1,5 @@ import { MenuSubsectionsBySection } from '@0xproject/react-shared'; import { DocAgnosticFormat, GeneratedDocJson, TypeDefinitionByName } from '@0xproject/types'; -import compareVersions = require('compare-versions'); import * as _ from 'lodash'; import { diff --git a/packages/react-docs/tsconfig.json b/packages/react-docs/tsconfig.json index 82f44a62c..76e2cd027 100644 --- a/packages/react-docs/tsconfig.json +++ b/packages/react-docs/tsconfig.json @@ -1,9 +1,10 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "./lib/", + "outDir": "lib", + "rootDir": "src", "jsx": "react", - "baseUrl": "./", + "baseUrl": ".", "strictNullChecks": false, "paths": { "*": ["node_modules/@types/*", "*"] diff --git a/packages/react-shared/package.json b/packages/react-shared/package.json index eb6679044..57aa9d51d 100644 --- a/packages/react-shared/package.json +++ b/packages/react-shared/package.json @@ -33,6 +33,7 @@ "typescript": "3.0.1" }, "dependencies": { + "@material-ui/core": "^3.0.1", "@types/is-mobile": "0.3.0", "@types/lodash": "4.14.104", "@types/material-ui": "0.18.0", @@ -44,13 +45,12 @@ "change-case": "^3.0.2", "is-mobile": "^0.2.2", "lodash": "^4.17.5", - "material-ui": "^0.17.1", - "react": "15.6.1", - "react-dom": "15.6.1", - "react-highlight": "0xproject/react-highlight", + "material-ui": "^0.20.0", + "react": "^16.4.2", + "react-dom": "^16.4.2", + "react-highlight": "0xproject/react-highlight#2f40a42e0a3f0ad126f9f42d505b97b603fc7162", "react-markdown": "^3.2.2", - "react-scroll": "0xproject/react-scroll#similar-to-pr-330", - "react-tap-event-plugin": "^2.0.1" + "react-scroll": "0xproject/react-scroll#similar-to-pr-330" }, "publishConfig": { "access": "public" diff --git a/packages/react-shared/src/components/anchor_title.tsx b/packages/react-shared/src/components/anchor_title.tsx index 451ba1729..8f7e4af27 100644 --- a/packages/react-shared/src/components/anchor_title.tsx +++ b/packages/react-shared/src/components/anchor_title.tsx @@ -3,7 +3,6 @@ import { Link as ScrollLink } from 'react-scroll'; import { HeaderSizes, Styles } from '../types'; import { constants } from '../utils/constants'; -import { utils } from '../utils/utils'; const headerSizeToScrollOffset: { [headerSize: string]: number } = { h2: -20, diff --git a/packages/react-shared/src/components/version_drop_down.tsx b/packages/react-shared/src/components/version_drop_down.tsx index e41590957..5ff4bed54 100644 --- a/packages/react-shared/src/components/version_drop_down.tsx +++ b/packages/react-shared/src/components/version_drop_down.tsx @@ -1,6 +1,6 @@ +import MenuItem from '@material-ui/core/MenuItem'; +import Select from '@material-ui/core/Select'; import * as _ from 'lodash'; -import DropDownMenu from 'material-ui/DropDownMenu'; -import MenuItem from 'material-ui/MenuItem'; import * as React from 'react'; export interface VersionDropDownProps { @@ -15,23 +15,23 @@ export class VersionDropDown extends React.Component<VersionDropDownProps, Versi public render(): React.ReactNode { return ( <div className="mx-auto" style={{ width: 120 }}> - <DropDownMenu - maxHeight={300} - value={this.props.selectedVersion} - onChange={this._updateSelectedVersion.bind(this)} - > + <Select value={this.props.selectedVersion} onChange={this._updateSelectedVersion.bind(this)}> {this._renderDropDownItems()} - </DropDownMenu> + </Select> </div> ); } private _renderDropDownItems(): React.ReactNode[] { const items = _.map(this.props.versions, version => { - return <MenuItem key={version} value={version} primaryText={`v${version}`} />; + return ( + <MenuItem key={version} value={version}> + v{version} + </MenuItem> + ); }); return items; } - private _updateSelectedVersion(_e: any, _index: number, semver: string): void { - this.props.onVersionSelected(semver); + private _updateSelectedVersion(event: React.ChangeEvent<HTMLSelectElement>): void { + this.props.onVersionSelected(event.target.value); } } diff --git a/packages/react-shared/tsconfig.json b/packages/react-shared/tsconfig.json index 687bd1f4e..5abe0ab4e 100644 --- a/packages/react-shared/tsconfig.json +++ b/packages/react-shared/tsconfig.json @@ -1,9 +1,10 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "./lib/", + "outDir": "lib", + "rootDir": "src", "jsx": "react", - "baseUrl": "./", + "baseUrl": ".", "paths": { "*": ["node_modules/@types/*", "*"] } diff --git a/packages/sol-compiler/package.json b/packages/sol-compiler/package.json index f60edc1f9..eab96fcce 100644 --- a/packages/sol-compiler/package.json +++ b/packages/sol-compiler/package.json @@ -8,8 +8,7 @@ "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { - "watch_without_deps": "yarn pre_build && tsc -w", - "build": "yarn pre_build && tsc", + "build": "yarn pre_build && tsc -b", "pre_build": "run-s update_contract_fixtures", "update_contract_fixtures": "copyfiles 'test/fixtures/contracts/**/*' ./lib", "test": "yarn run_mocha", @@ -21,7 +20,7 @@ "migrate": "npm run build; node lib/src/cli.js migrate", "lint": "tslint --project .", "test:circleci": "yarn test:coverage", - "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES" + "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" }, "config": { "postpublish": { diff --git a/packages/sol-compiler/tsconfig.json b/packages/sol-compiler/tsconfig.json index 63cbc75c3..c6ffbb99b 100644 --- a/packages/sol-compiler/tsconfig.json +++ b/packages/sol-compiler/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig", "compilerOptions": { "outDir": "lib", + "rootDir": ".", "strictFunctionTypes": false }, "include": ["./src/**/*", "./test/**/*"] diff --git a/packages/sol-compiler/typedoc-tsconfig.json b/packages/sol-compiler/typedoc-tsconfig.json new file mode 100644 index 000000000..22897c131 --- /dev/null +++ b/packages/sol-compiler/typedoc-tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../typedoc-tsconfig", + "compilerOptions": { + "outDir": "lib", + "strictFunctionTypes": false + }, + "include": ["./src/**/*", "./test/**/*"] +} diff --git a/packages/sol-cov/package.json b/packages/sol-cov/package.json index b8c008b3e..3772d02c5 100644 --- a/packages/sol-cov/package.json +++ b/packages/sol-cov/package.json @@ -8,8 +8,7 @@ "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { - "watch_without_deps": "yarn pre_build && tsc -w", - "build": "yarn pre_build && tsc", + "build": "yarn pre_build && tsc -b", "pre_build": "run-s copy_test_fixtures", "lint": "tslint --project .", "test": "run-s compile_test run_mocha", @@ -21,7 +20,7 @@ "clean": "shx rm -rf lib test/fixtures/artifacts src/artifacts generated_docs", "copy_test_fixtures": "copyfiles 'test/fixtures/**/*' ./lib", "compile_test": "sol-compiler compile", - "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES" + "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" }, "config": { "postpublish": { diff --git a/packages/sol-cov/tsconfig.json b/packages/sol-cov/tsconfig.json index e35816553..2ee711adc 100644 --- a/packages/sol-cov/tsconfig.json +++ b/packages/sol-cov/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "." }, "include": ["./src/**/*", "./test/**/*"] } diff --git a/packages/sol-cov/typedoc-tsconfig.json b/packages/sol-cov/typedoc-tsconfig.json new file mode 100644 index 000000000..c9b0af1ae --- /dev/null +++ b/packages/sol-cov/typedoc-tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../typedoc-tsconfig", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["./src/**/*", "./test/**/*"] +} diff --git a/packages/sol-resolver/package.json b/packages/sol-resolver/package.json index f3772a118..7a773ce7c 100644 --- a/packages/sol-resolver/package.json +++ b/packages/sol-resolver/package.json @@ -8,8 +8,7 @@ "main": "lib/index.js", "types": "lib/index.d.ts", "scripts": { - "watch_without_deps": "tsc -w", - "build": "tsc", + "build": "tsc -b", "clean": "shx rm -rf lib", "lint": "tslint --project ." }, diff --git a/packages/sol-resolver/tsconfig.json b/packages/sol-resolver/tsconfig.json index f5f4b37c2..56689eaa3 100644 --- a/packages/sol-resolver/tsconfig.json +++ b/packages/sol-resolver/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "src" }, "include": ["src/**/*"] } diff --git a/packages/sra-report/package.json b/packages/sra-report/package.json index 91b97dd98..481794d5d 100644 --- a/packages/sra-report/package.json +++ b/packages/sra-report/package.json @@ -8,9 +8,8 @@ "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { - "watch_without_deps": "tsc -w", "clean": "shx rm -rf lib", - "build": "tsc", + "build": "tsc -b", "lint": "tslint --project .", "test:circleci": "yarn test:coverage", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", diff --git a/packages/sra-report/tsconfig.json b/packages/sra-report/tsconfig.json index e35816553..2ee711adc 100644 --- a/packages/sra-report/tsconfig.json +++ b/packages/sra-report/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "." }, "include": ["./src/**/*", "./test/**/*"] } diff --git a/packages/sra-spec/package.json b/packages/sra-spec/package.json index b560fa77b..f11b1bb5a 100644 --- a/packages/sra-spec/package.json +++ b/packages/sra-spec/package.json @@ -5,8 +5,8 @@ "node": ">=6.12" }, "description": "Standard Relayer API Open API Spec", - "main": "lib/index.js", - "types": "lib/index.d.ts", + "main": "lib/src/index.js", + "types": "lib/src/index.d.ts", "scripts": { "serve": "redoc-cli serve lib/api.json --watch", "watch_without_deps": "run-p build-json:watch serve", @@ -17,10 +17,10 @@ "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "test:circleci": "yarn test:coverage", "clean": "shx rm -rf lib", - "build": "tsc && yarn copy_md_files && yarn build-json", - "build-json": "ts-node build_scripts/buildJson.ts", + "build": "tsc -b && yarn copy_md_files && yarn build-json", + "build-json": "node ./lib/build_scripts/buildJson", "build-json:watch": "chokidar 'src/**/*' -c 'yarn build-json' ", - "copy_md_files": "copyfiles -u 2 './src/md/**/*.md' ./lib/md", + "copy_md_files": "copyfiles -u 2 './src/md/**/*.md' ./lib/src/md", "deploy-site": "discharge deploy" }, "repository": { @@ -54,7 +54,7 @@ "swagger-cli": "^2.1.1", "ts-node": "^7.0.0", "tslint": "5.11.0", - "typescript": "2.7.1" + "typescript": "3.0.1" }, "publishConfig": { "access": "public" diff --git a/packages/sra-spec/tsconfig.json b/packages/sra-spec/tsconfig.json index e60028885..785ed914d 100644 --- a/packages/sra-spec/tsconfig.json +++ b/packages/sra-spec/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "." }, - "include": ["./src/**/*", "./test/*"] + "include": ["./src/**/*", "./test/*", "./build_scripts/*", "./md/*"] } diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json index 48c6d5ae9..d9583b357 100644 --- a/packages/subproviders/package.json +++ b/packages/subproviders/package.json @@ -8,8 +8,7 @@ "types": "lib/src/index.d.ts", "license": "Apache-2.0", "scripts": { - "watch_without_deps": "tsc -w", - "build": "tsc", + "build": "tsc -b", "clean": "shx rm -rf lib generated_docs", "lint": "tslint --project .", "run_mocha_unit": "mocha --require source-map-support/register --require make-promises-safe lib/test/unit/**/*_test.js --timeout 10000 --bail --exit", @@ -21,7 +20,7 @@ "test:all": "run-s test:unit test:integration", "test:unit": "run-s clean build run_mocha_unit", "test:integration": "run-s clean build run_mocha_integration", - "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES" + "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" }, "config": { "postpublish": { diff --git a/packages/subproviders/tsconfig.json b/packages/subproviders/tsconfig.json index e35816553..2ee711adc 100644 --- a/packages/subproviders/tsconfig.json +++ b/packages/subproviders/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "." }, "include": ["./src/**/*", "./test/**/*"] } diff --git a/packages/subproviders/typedoc-tsconfig.json b/packages/subproviders/typedoc-tsconfig.json new file mode 100644 index 000000000..c9b0af1ae --- /dev/null +++ b/packages/subproviders/typedoc-tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../typedoc-tsconfig", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["./src/**/*", "./test/**/*"] +} diff --git a/packages/testnet-faucets/package.json b/packages/testnet-faucets/package.json index 9c32dde47..2e5e1f30a 100644 --- a/packages/testnet-faucets/package.json +++ b/packages/testnet-faucets/package.json @@ -8,7 +8,6 @@ "description": "A faucet micro-service that dispenses test ERC20 tokens or Ether", "main": "server.js", "scripts": { - "watch_without_deps": "tsc -w", "build": "node ../../node_modules/gulp/bin/gulp.js build", "dev": "node ../../node_modules/gulp/bin/gulp.js run", "start": "node ./server/server.js", diff --git a/packages/testnet-faucets/tsconfig.json b/packages/testnet-faucets/tsconfig.json index d7e89a1e2..4997ce208 100644 --- a/packages/testnet-faucets/tsconfig.json +++ b/packages/testnet-faucets/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig", "compilerOptions": { "outDir": "lib", + "rootDir": "src/ts", "strictPropertyInitialization": false }, "include": ["./src/ts/**/*"] diff --git a/packages/tslint-config/package.json b/packages/tslint-config/package.json index 330314974..0907b43b6 100644 --- a/packages/tslint-config/package.json +++ b/packages/tslint-config/package.json @@ -7,8 +7,7 @@ "description": "Lint rules related to 0xProject for TSLint", "main": "tslint.json", "scripts": { - "watch_without_deps": "tsc -w", - "build": "tsc", + "build": "tsc -b", "clean": "shx rm -rf lib", "lint": "tslint --project ." }, diff --git a/packages/tslint-config/tsconfig.json b/packages/tslint-config/tsconfig.json index 1935fedc6..44845cf1f 100644 --- a/packages/tslint-config/tsconfig.json +++ b/packages/tslint-config/tsconfig.json @@ -1,8 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "typeRoots": ["../../node_modules/@types", "node_modules/@types"], - "outDir": "lib" + "outDir": "lib", + "rootDir": "rules" }, "include": ["./rules/**/*"] } diff --git a/packages/tslint-config/tslint.json b/packages/tslint-config/tslint.json index f207d0709..fd1849dd0 100644 --- a/packages/tslint-config/tslint.json +++ b/packages/tslint-config/tslint.json @@ -76,6 +76,7 @@ "no-unbound-method": true, "no-unnecessary-class": true, "no-unnecessary-type-assertion": true, + "no-unused-variable": true, "no-unsafe-finally": true, "number-literal-format": true, "object-literal-key-quotes": false, diff --git a/packages/types/CHANGELOG.json b/packages/types/CHANGELOG.json index e96d2a742..0bd9e3b37 100644 --- a/packages/types/CHANGELOG.json +++ b/packages/types/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "1.0.1-rc.7", + "changes": [ + { + "note": "Add AssetProxyOwner revert reasons", + "pr": 1041 + } + ] + }, + { "version": "1.0.1-rc.6", "changes": [ { diff --git a/packages/types/package.json b/packages/types/package.json index 291452cbb..362c8f639 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -8,8 +8,7 @@ "main": "lib/index.js", "types": "lib/index.d.ts", "scripts": { - "watch_without_deps": "tsc -w", - "build": "tsc", + "build": "tsc -b", "clean": "shx rm -rf lib", "lint": "tslint --project ." }, diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 16405dca6..a22f44c08 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -224,6 +224,9 @@ export enum RevertReason { Erc721InvalidSelector = 'ERC721_INVALID_SELECTOR', WalletError = 'WALLET_ERROR', ValidatorError = 'VALIDATOR_ERROR', + InvalidFunctionSelector = 'INVALID_FUNCTION_SELECTOR', + InvalidAssetProxy = 'INVALID_ASSET_PROXY', + UnregisteredAssetProxy = 'UNREGISTERED_ASSET_PROXY', } export enum StatusCodes { diff --git a/packages/types/tsconfig.json b/packages/types/tsconfig.json index ce916a635..56689eaa3 100644 --- a/packages/types/tsconfig.json +++ b/packages/types/tsconfig.json @@ -1,8 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "typeRoots": ["../../node_modules/@types", "node_modules/@types"], - "outDir": "lib" + "outDir": "lib", + "rootDir": "src" }, "include": ["src/**/*"] } diff --git a/packages/typescript-typings/package.json b/packages/typescript-typings/package.json index c047a5328..08cf708a6 100644 --- a/packages/typescript-typings/package.json +++ b/packages/typescript-typings/package.json @@ -6,8 +6,7 @@ }, "description": "0x project typescript type definitions", "scripts": { - "watch_without_deps": "tsc -w", - "build": "tsc", + "build": "tsc -b", "clean": "shx rm -rf lib" }, "repository": { @@ -32,6 +31,7 @@ }, "devDependencies": { "copyfiles": "^2.0.0", + "typescript": "3.0.1", "shx": "^0.2.2" }, "publishConfig": { diff --git a/packages/typescript-typings/tsconfig.json b/packages/typescript-typings/tsconfig.json index a9a644b17..7f0fe2f7a 100644 --- a/packages/typescript-typings/tsconfig.json +++ b/packages/typescript-typings/tsconfig.json @@ -1,6 +1,7 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "." } } diff --git a/packages/typescript-typings/types/react-typist/index.d.ts b/packages/typescript-typings/types/react-typist/index.d.ts new file mode 100644 index 000000000..692c596a5 --- /dev/null +++ b/packages/typescript-typings/types/react-typist/index.d.ts @@ -0,0 +1 @@ +declare module 'react-typist'; diff --git a/packages/utils/package.json b/packages/utils/package.json index c72fb4c83..d93163e81 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -8,8 +8,7 @@ "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { - "watch_without_deps": "tsc -w", - "build": "tsc", + "build": "tsc -b", "clean": "shx rm -rf lib", "lint": "tslint --project .", "test": "yarn run_mocha", diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json index 8b4cd47a2..718e623c7 100644 --- a/packages/utils/tsconfig.json +++ b/packages/utils/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "." }, "include": ["src/**/*", "test/**/*"] } diff --git a/packages/web3-wrapper/package.json b/packages/web3-wrapper/package.json index f84074447..6361fbde7 100644 --- a/packages/web3-wrapper/package.json +++ b/packages/web3-wrapper/package.json @@ -8,8 +8,7 @@ "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { - "watch_without_deps": "tsc -w", - "build": "tsc", + "build": "tsc -b", "clean": "shx rm -rf lib generated_docs", "lint": "tslint --project .", "test": "yarn run_mocha", @@ -18,7 +17,7 @@ "run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --bail --exit", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", - "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES" + "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" }, "config": { "postpublish": { diff --git a/packages/web3-wrapper/tsconfig.json b/packages/web3-wrapper/tsconfig.json index 8b4cd47a2..718e623c7 100644 --- a/packages/web3-wrapper/tsconfig.json +++ b/packages/web3-wrapper/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig", "compilerOptions": { - "outDir": "lib" + "outDir": "lib", + "rootDir": "." }, "include": ["src/**/*", "test/**/*"] } diff --git a/packages/web3-wrapper/typedoc-tsconfig.json b/packages/web3-wrapper/typedoc-tsconfig.json new file mode 100644 index 000000000..b9c6b36f3 --- /dev/null +++ b/packages/web3-wrapper/typedoc-tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../typedoc-tsconfig", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["src/**/*", "test/**/*"] +} diff --git a/packages/website/package.json b/packages/website/package.json index 9b6a0ba36..a7da19c9e 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -21,7 +21,7 @@ "@0xproject/contract-wrappers": "^0.0.5", "@0xproject/order-utils": "^0.0.9", "@0xproject/react-docs": "^1.0.7", - "@0xproject/react-shared": "^0.2.3", + "@0xproject/react-shared": "^1.0.8", "@0xproject/subproviders": "^2.0.1", "@0xproject/types": "^0.8.1", "@0xproject/typescript-typings": "^0.4.3", @@ -37,22 +37,22 @@ "jsonschema": "^1.2.0", "less": "^2.7.2", "lodash": "^4.17.5", - "material-ui": "^0.17.1", + "material-ui": "^0.20.0", "moment": "2.21.0", "numeral": "^2.0.6", "polished": "^1.9.2", "query-string": "^6.0.0", - "react": "15.6.1", - "react-copy-to-clipboard": "^4.2.3", + "react": "^16.4.2", + "react-copy-to-clipboard": "^5.0.0", "react-document-title": "^2.0.3", - "react-dom": "15.6.1", + "react-dom": "^16.4.2", "react-helmet": "^5.2.0", "react-popper": "^1.0.0-beta.6", "react-redux": "^5.0.3", "react-router-dom": "^4.1.1", "react-scroll": "0xproject/react-scroll#similar-to-pr-330", - "react-tap-event-plugin": "^2.0.1", "react-tooltip": "^3.2.7", + "react-typist": "^2.0.4", "redux": "^3.6.0", "redux-devtools-extension": "^2.13.2", "semver-sort": "0.0.4", @@ -69,13 +69,13 @@ "@types/find-versions": "^2.0.0", "@types/jsonschema": "^1.1.1", "@types/lodash": "4.14.104", - "@types/material-ui": "0.18.0", + "@types/material-ui": "^0.20.0", "@types/node": "^8.0.53", "@types/numeral": "^0.0.22", "@types/query-string": "^5.1.0", - "@types/react": "16.3.13", + "@types/react": "^16.4.2", "@types/react-copy-to-clipboard": "^4.2.0", - "@types/react-dom": "^16.0.3", + "@types/react-dom": "^16.0.7", "@types/react-helmet": "^5.0.6", "@types/react-redux": "^4.4.37", "@types/react-router-dom": "^4.0.4", diff --git a/packages/website/public/images/landing/0x_homepage.svg b/packages/website/public/images/landing/0x_homepage.svg new file mode 100644 index 000000000..061ac8939 --- /dev/null +++ b/packages/website/public/images/landing/0x_homepage.svg @@ -0,0 +1,386 @@ +<svg width="410" height="254" viewBox="0 0 410 254" fill="none" xmlns="http://www.w3.org/2000/svg"> +<rect width="410" height="254" fill="black" fill-opacity="0"/> +<rect width="410" height="254" fill="black" fill-opacity="0"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M409.979 122.524C410.195 134.531 408.758 137.636 404.251 140.251L210.864 252.464C207.334 254.512 202.985 254.512 199.455 252.464L6.06657 140.251C1.55911 137.635 -1.2295 135.189 0.536218 121.797L409.979 122.524Z" fill="#D0CAFF"/> +<rect width="98.1672" height="56.8942" fill="black" fill-opacity="0" transform="translate(87.1703 125.679)"/> +<path d="M178.097 125.679L87.1703 178.372" stroke="#C4AED9" stroke-width="1.32046" stroke-linecap="round"/> +<path d="M181.659 127.746L90.732 180.439" stroke="#C4AED9" stroke-width="1.32046" stroke-linecap="round"/> +<path d="M185.338 129.88L94.41 182.573" stroke="#C4AED9" stroke-width="1.32046" stroke-linecap="round"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M199.455 245.823L6.06657 133.61C-1.53963 129.196 -1.53963 118.163 6.06657 113.749L199.453 1.53604C202.984 -0.512014 207.333 -0.512014 210.863 1.53604L404.251 113.75C411.858 118.163 411.858 129.197 404.251 133.611L210.864 245.823C207.334 247.871 202.985 247.871 199.455 245.823Z" fill="#F0EEFF"/> +<rect width="107.203" height="36.2243" fill="black" fill-opacity="0" transform="translate(79.7358 74.3805)"/> +<path d="M79.7358 107.066L133.382 75.8612C136.304 73.965 139.326 73.974 141.767 75.4102L186.939 101.973" stroke="#DBDBFF" stroke-width="1.32046" stroke-linecap="round"/> +<path d="M82.4662 108.801L134.79 78.5156C136.798 77.3507 139.273 77.3583 141.274 78.5356L184.001 103.681" stroke="#DBDBFF" stroke-width="1.32046" stroke-linecap="round"/> +<path d="M85.1381 110.605L134.534 82.5144C136.541 81.3495 139.017 81.3571 141.017 82.5348L180.403 105.714" stroke="#DBDBFF" stroke-width="1.32046" stroke-linecap="round"/> +<rect width="100.727" height="37.9813" fill="black" fill-opacity="0" transform="translate(226.643 123.734)"/> +<path d="M327.37 126.923L270.289 160.234C267.367 162.131 264.345 162.121 261.903 160.685L226.643 140.288" stroke="#DBDBFF" stroke-width="1.32046" stroke-linecap="round"/> +<path d="M323.336 125.886L268.881 157.58C266.873 158.745 264.398 158.737 262.397 157.56L229.58 138.58" stroke="#DBDBFF" stroke-width="1.32046" stroke-linecap="round"/> +<path d="M319.925 123.734L269.137 153.581C267.129 154.746 264.654 154.739 262.653 153.561L233.178 136.547" stroke="#DBDBFF" stroke-width="1.32046" stroke-linecap="round"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M322.112 124.6C313.477 119.589 313.477 111.465 322.112 106.454C330.747 101.444 344.748 101.444 353.383 106.454C362.018 111.465 362.018 119.589 353.383 124.6C344.748 129.611 330.747 129.611 322.112 124.6Z" stroke="#DBDBFF" stroke-width="2"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M50.8048 126.749C42.1698 121.739 42.1698 113.614 50.8048 108.604C59.4403 103.593 73.4409 103.593 82.0764 108.604C90.7115 113.614 90.7115 121.739 82.0764 126.749C73.4409 131.76 59.4403 131.76 50.8048 126.749Z" stroke="#DBDBFF" stroke-width="2"/> +<g opacity="0.372566"> +<rect width="34.2587" height="23.7724" fill="black" fill-opacity="0" transform="translate(169.644 179.583)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M171.171 194.759L170.656 194.461C170.619 194.439 170.596 194.399 170.596 194.357V192.616C170.596 192.524 170.695 192.466 170.775 192.513L171.29 192.811C171.327 192.833 171.35 192.872 171.35 192.915V194.655C171.35 194.748 171.251 194.805 171.171 194.759Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M172.622 195.59L172.107 195.291C172.07 195.269 172.047 195.23 172.047 195.187V193.447C172.047 193.354 172.146 193.297 172.226 193.343L172.741 193.642C172.778 193.663 172.801 193.703 172.801 193.745V195.486C172.801 195.578 172.702 195.635 172.622 195.59Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M174.073 196.42L173.558 196.122C173.521 196.1 173.499 196.06 173.499 196.018V194.277C173.499 194.185 173.598 194.127 173.677 194.174L174.192 194.472C174.23 194.494 174.252 194.533 174.252 194.576V196.316C174.252 196.409 174.153 196.466 174.073 196.42Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M175.525 197.251L175.009 196.952C174.973 196.93 174.95 196.891 174.95 196.848V195.108C174.95 195.015 175.049 194.958 175.128 195.004L175.644 195.303C175.681 195.324 175.703 195.364 175.703 195.406V197.147C175.703 197.239 175.604 197.296 175.525 197.251Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M176.976 198.081L176.46 197.783C176.424 197.761 176.401 197.721 176.401 197.679V195.938C176.401 195.846 176.5 195.789 176.579 195.835L177.095 196.133C177.132 196.155 177.154 196.194 177.154 196.237V197.978C177.154 198.07 177.055 198.127 176.976 198.081Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M178.427 198.912L177.912 198.613C177.875 198.591 177.852 198.552 177.852 198.509V196.769C177.852 196.676 177.951 196.619 178.031 196.665L178.546 196.964C178.583 196.985 178.606 197.025 178.606 197.067V198.808C178.606 198.9 178.506 198.958 178.427 198.912Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M179.878 199.742L179.363 199.444C179.326 199.422 179.303 199.382 179.303 199.34V197.599C179.303 197.507 179.402 197.45 179.482 197.496L179.997 197.794C180.034 197.816 180.057 197.855 180.057 197.898V199.639C180.057 199.731 179.958 199.788 179.878 199.742Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M181.33 200.652L180.814 200.353C180.777 200.332 180.754 200.293 180.754 200.25V198.509C180.754 198.417 180.854 198.359 180.933 198.406L181.449 198.704C181.485 198.725 181.508 198.765 181.508 198.808V200.548C181.508 200.64 181.409 200.698 181.33 200.652Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M182.781 201.443L182.265 201.144C182.228 201.123 182.205 201.083 182.205 201.041V199.3C182.205 199.208 182.305 199.15 182.384 199.196L182.9 199.495C182.936 199.517 182.959 199.556 182.959 199.599V201.339C182.959 201.432 182.86 201.489 182.781 201.443Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M184.232 202.313L183.716 202.014C183.679 201.993 183.657 201.954 183.657 201.911V200.17C183.657 200.078 183.756 200.02 183.836 200.067L184.351 200.365C184.388 200.387 184.41 200.426 184.41 200.469V202.209C184.41 202.302 184.311 202.359 184.232 202.313Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M185.683 203.144L185.168 202.845C185.131 202.824 185.108 202.784 185.108 202.741V201.001C185.108 200.909 185.207 200.851 185.287 200.897L185.802 201.196C185.839 201.217 185.862 201.256 185.862 201.299V203.04C185.862 203.132 185.763 203.19 185.683 203.144Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M202.343 194.776L202.869 194.471C202.907 194.449 202.93 194.409 202.93 194.365V192.588C202.93 192.494 202.829 192.435 202.748 192.482L202.221 192.786C202.184 192.808 202.161 192.849 202.161 192.893V194.67C202.161 194.764 202.262 194.823 202.343 194.776Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M200.861 195.624L201.387 195.319C201.425 195.297 201.448 195.257 201.448 195.214V193.436C201.448 193.342 201.347 193.283 201.266 193.33L200.74 193.635C200.702 193.656 200.679 193.697 200.679 193.741V195.518C200.679 195.612 200.78 195.671 200.861 195.624Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M199.379 196.472L199.905 196.167C199.943 196.145 199.966 196.105 199.966 196.062V194.284C199.966 194.19 199.865 194.131 199.784 194.178L199.257 194.483C199.22 194.505 199.197 194.545 199.197 194.589V196.366C199.197 196.461 199.298 196.519 199.379 196.472Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M197.897 197.32L198.423 197.015C198.461 196.993 198.484 196.953 198.484 196.91V195.132C198.484 195.038 198.383 194.979 198.302 195.026L197.775 195.331C197.738 195.353 197.715 195.393 197.715 195.437V197.214C197.715 197.309 197.816 197.367 197.897 197.32Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M196.415 198.168L196.941 197.863C196.979 197.841 197.002 197.801 197.002 197.758V195.98C197.002 195.886 196.901 195.827 196.82 195.874L196.294 196.179C196.256 196.201 196.233 196.242 196.233 196.285V198.062C196.233 198.157 196.334 198.215 196.415 198.168Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M194.933 199.017L195.459 198.711C195.497 198.69 195.52 198.649 195.52 198.606V196.828C195.52 196.735 195.419 196.676 195.338 196.722L194.811 197.027C194.774 197.049 194.751 197.09 194.751 197.133V198.91C194.751 199.005 194.852 199.063 194.933 199.017Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M193.451 199.865L193.977 199.56C194.015 199.538 194.038 199.498 194.038 199.454V197.676C194.038 197.583 193.937 197.524 193.856 197.571L193.329 197.876C193.292 197.897 193.269 197.938 193.269 197.982V199.758C193.269 199.853 193.37 199.912 193.451 199.865Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M191.969 200.794L192.495 200.489C192.533 200.467 192.556 200.427 192.556 200.383V198.605C192.556 198.512 192.455 198.453 192.374 198.5L191.848 198.805C191.81 198.827 191.787 198.867 191.787 198.91V200.688C191.787 200.782 191.888 200.841 191.969 200.794Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M190.487 201.601L191.013 201.296C191.051 201.274 191.074 201.234 191.074 201.191V199.413C191.074 199.319 190.973 199.26 190.892 199.307L190.366 199.612C190.328 199.634 190.305 199.674 190.305 199.718V201.496C190.305 201.59 190.406 201.649 190.487 201.601Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M189.005 202.49L189.531 202.185C189.569 202.163 189.592 202.123 189.592 202.08V200.302C189.592 200.208 189.491 200.149 189.41 200.196L188.883 200.501C188.846 200.523 188.823 200.563 188.823 200.607V202.384C188.823 202.478 188.924 202.537 189.005 202.49Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M187.523 203.338L188.049 203.033C188.087 203.011 188.11 202.971 188.11 202.928V201.15C188.11 201.056 188.009 200.998 187.928 201.044L187.402 201.349C187.364 201.371 187.341 201.411 187.341 201.455V203.232C187.341 203.327 187.442 203.386 187.523 203.338Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M169.65 190.038L169.661 192.12C169.591 192.497 169.745 192.91 170.122 193.129L186.297 202.514C186.592 202.686 186.956 202.686 187.251 202.514L203.426 193.129C203.803 192.911 203.957 192.497 203.887 192.12L203.897 190.038" fill="#8B81E6"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M186.297 200.143L170.122 190.757C169.485 190.389 169.485 189.466 170.122 189.097L186.297 179.711C186.592 179.54 186.956 179.54 187.251 179.711L203.426 189.097C204.062 189.466 204.062 190.389 203.426 190.757L187.251 200.143C186.956 200.314 186.592 200.314 186.297 200.143Z" fill="#A59EF7"/> +</g> +<path fill-rule="evenodd" clip-rule="evenodd" d="M98.8553 102.466C96.2624 102.466 94.1604 100.354 94.1604 97.7481C94.1604 95.1427 96.2624 93.0301 98.8553 93.0301C101.448 93.0301 103.55 95.1427 103.55 97.7481C103.55 100.354 101.448 102.466 98.8553 102.466Z" fill="#92F6D2"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M117.665 88.5403C117.665 91.1457 115.563 93.2582 112.97 93.2582C110.377 93.2582 108.275 91.1457 108.275 88.5403C108.275 85.9345 110.377 83.8219 112.97 83.8219C115.563 83.8219 117.665 85.9345 117.665 88.5403Z" fill="#92F6D2"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M131.779 80.8495C131.779 83.4553 129.677 85.5679 127.085 85.5679C124.492 85.5679 122.39 83.4553 122.39 80.8495C122.39 78.2436 124.492 76.1315 127.085 76.1315C129.677 76.1315 131.779 78.2436 131.779 80.8495Z" fill="#92F6D2"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M141.021 82.3654C138.429 82.3654 136.326 80.2528 136.326 77.647C136.326 75.0416 138.429 72.9291 141.021 72.9291C143.614 72.9291 145.716 75.0416 145.716 77.647C145.716 80.2528 143.614 82.3654 141.021 82.3654Z" fill="#92F6D2"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M159.481 85.568C159.481 88.1734 157.379 90.2859 154.786 90.2859C152.194 90.2859 150.092 88.1734 150.092 85.568C150.092 82.9622 152.194 80.8496 154.786 80.8496C157.379 80.8496 159.481 82.9622 159.481 85.568Z" fill="#92F6D2"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M171.279 95.0541C171.279 97.6595 169.177 99.7721 166.585 99.7721C163.992 99.7721 161.89 97.6595 161.89 95.0541C161.89 92.4483 163.992 90.3357 166.585 90.3357C169.177 90.3357 171.279 92.4483 171.279 95.0541Z" fill="#92F6D2"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M244.927 140.363C244.927 142.969 242.825 145.082 240.232 145.082C237.639 145.082 235.537 142.969 235.537 140.363C235.537 137.758 237.639 135.645 240.232 135.645C242.825 135.645 244.927 137.758 244.927 140.363Z" fill="#8CB6FF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M258.321 149.423C258.321 152.029 256.219 154.141 253.626 154.141C251.033 154.141 248.931 152.029 248.931 149.423C248.931 146.817 251.033 144.705 253.626 144.705C256.219 144.705 258.321 146.817 258.321 149.423Z" fill="#8CB6FF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M267.921 161.512C265.328 161.512 263.226 159.399 263.226 156.793C263.226 154.188 265.328 152.075 267.921 152.075C270.514 152.075 272.616 154.188 272.616 156.793C272.616 159.399 270.514 161.512 267.921 161.512Z" fill="#8CB6FF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M288.178 149.398C288.178 152.004 286.076 154.116 283.483 154.116C280.891 154.116 278.789 152.004 278.789 149.398C278.789 146.792 280.891 144.68 283.483 144.68C286.076 144.68 288.178 146.792 288.178 149.398Z" fill="#8CB6FF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M302.505 141.805C302.505 144.411 300.403 146.523 297.811 146.523C295.218 146.523 293.116 144.411 293.116 141.805C293.116 139.199 295.218 137.087 297.811 137.087C300.403 137.087 302.505 139.199 302.505 141.805Z" fill="#8CB6FF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M315.374 133.208C315.374 135.813 313.272 137.926 310.679 137.926C308.086 137.926 305.984 135.813 305.984 133.208C305.984 130.602 308.086 128.489 310.679 128.489C313.272 128.489 315.374 130.602 315.374 133.208Z" fill="#8CB6FF"/> +<rect width="94.7557" height="54.8453" fill="black" fill-opacity="0" transform="translate(89.638 130.896)"/> +<path d="M177.154 130.896L89.638 182.735" stroke="#DBDBFF" stroke-width="1.32046" stroke-linecap="round"/> +<path d="M180.715 132.963L93.2464 184.097" stroke="#DBDBFF" stroke-width="1.32046" stroke-linecap="round"/> +<path d="M184.394 135.097L96.4554 185.742" stroke="#DBDBFF" stroke-width="1.32046" stroke-linecap="round"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M157.606 126.233L156.096 125.357C155.988 125.295 155.922 125.178 155.922 125.053V119.944C155.922 119.674 156.212 119.505 156.445 119.64L157.956 120.516C158.064 120.579 158.13 120.695 158.13 120.821V125.929C158.13 126.2 157.839 126.368 157.606 126.233Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M161.866 128.671L160.355 127.795C160.247 127.732 160.181 127.616 160.181 127.491V122.382C160.181 122.112 160.472 121.943 160.705 122.078L162.215 122.954C162.323 123.017 162.389 123.133 162.389 123.258V128.367C162.389 128.637 162.099 128.806 161.866 128.671Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M166.125 131.109L164.615 130.232C164.507 130.17 164.44 130.054 164.44 129.929V124.819C164.44 124.549 164.731 124.38 164.964 124.516L166.474 125.392C166.582 125.455 166.649 125.57 166.649 125.696V130.805C166.649 131.075 166.358 131.244 166.125 131.109Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M170.384 133.546L168.874 132.67C168.766 132.608 168.699 132.491 168.699 132.366V127.257C168.699 126.987 168.991 126.818 169.223 126.953L170.733 127.829C170.841 127.892 170.908 128.008 170.908 128.133V133.242C170.908 133.513 170.617 133.681 170.384 133.546Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M174.644 135.984L173.133 135.107C173.025 135.045 172.959 134.929 172.959 134.804V129.695C172.959 129.425 173.249 129.255 173.483 129.391L174.993 130.267C175.101 130.33 175.167 130.445 175.167 130.571V135.68C175.167 135.95 174.876 136.119 174.644 135.984Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M178.903 138.422L177.393 137.545C177.285 137.483 177.218 137.366 177.218 137.242V132.132C177.218 131.862 177.509 131.693 177.742 131.828L179.252 132.704C179.36 132.767 179.427 132.883 179.427 133.008V138.118C179.427 138.388 179.136 138.556 178.903 138.422Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M183.162 140.859L181.652 139.983C181.544 139.92 181.477 139.804 181.477 139.679V134.57C181.477 134.3 181.768 134.13 182.001 134.266L183.511 135.142C183.619 135.205 183.686 135.321 183.686 135.446V140.555C183.686 140.826 183.395 140.994 183.162 140.859Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M187.422 143.53L185.911 142.653C185.803 142.591 185.737 142.475 185.737 142.35V137.24C185.737 136.97 186.028 136.801 186.261 136.936L187.771 137.812C187.879 137.876 187.945 137.991 187.945 138.117V143.226C187.945 143.496 187.654 143.665 187.422 143.53Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M191.681 145.851L190.171 144.974C190.063 144.912 189.996 144.796 189.996 144.671V139.562C189.996 139.292 190.287 139.122 190.52 139.258L192.03 140.134C192.138 140.197 192.205 140.312 192.205 140.438V145.547C192.205 145.817 191.913 145.986 191.681 145.851Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M195.94 148.405L194.43 147.528C194.322 147.466 194.255 147.35 194.255 147.225V142.116C194.255 141.846 194.546 141.676 194.779 141.812L196.289 142.688C196.398 142.751 196.464 142.866 196.464 142.992V148.101C196.464 148.371 196.173 148.54 195.94 148.405Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M200.199 150.843L198.689 149.966C198.581 149.904 198.515 149.788 198.515 149.663V144.553C198.515 144.283 198.805 144.114 199.038 144.249L200.549 145.125C200.657 145.188 200.723 145.304 200.723 145.43V150.539C200.723 150.809 200.432 150.978 200.199 150.843Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M249.098 126.283L250.641 125.388C250.751 125.324 250.819 125.206 250.819 125.078V119.86C250.819 119.584 250.522 119.412 250.284 119.55L248.742 120.445C248.632 120.509 248.564 120.627 248.564 120.755V125.973C248.564 126.249 248.861 126.421 249.098 126.283Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M244.749 128.773L246.291 127.877C246.401 127.813 246.469 127.695 246.469 127.567V122.349C246.469 122.073 246.172 121.901 245.934 122.039L244.392 122.934C244.282 122.998 244.214 123.116 244.214 123.244V128.462C244.214 128.738 244.511 128.91 244.749 128.773Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M240.399 131.262L241.941 130.367C242.052 130.303 242.12 130.185 242.12 130.057V124.839C242.12 124.563 241.822 124.391 241.585 124.528L240.043 125.423C239.932 125.488 239.864 125.606 239.864 125.734V130.952C239.864 131.227 240.162 131.4 240.399 131.262Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M236.049 133.751L237.592 132.856C237.702 132.792 237.77 132.674 237.77 132.546V127.328C237.77 127.052 237.473 126.88 237.235 127.018L235.693 127.913C235.583 127.977 235.515 128.095 235.515 128.223V133.441C235.515 133.717 235.812 133.889 236.049 133.751Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M231.7 136.24L233.242 135.345C233.353 135.282 233.42 135.163 233.42 135.035V129.818C233.42 129.541 233.123 129.369 232.885 129.507L231.343 130.402C231.233 130.466 231.165 130.584 231.165 130.713V135.93C231.165 136.206 231.462 136.378 231.7 136.24Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M227.35 138.73L228.892 137.835C229.003 137.771 229.071 137.653 229.071 137.525V132.307C229.071 132.031 228.773 131.858 228.536 131.996L226.994 132.891C226.883 132.956 226.815 133.074 226.815 133.202V138.42C226.815 138.695 227.113 138.868 227.35 138.73Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M223 141.219L224.543 140.324C224.653 140.26 224.721 140.142 224.721 140.014V134.796C224.721 134.52 224.424 134.348 224.186 134.486L222.644 135.381C222.534 135.445 222.466 135.563 222.466 135.691V140.909C222.466 141.185 222.763 141.357 223 141.219Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M218.651 143.946L220.193 143.051C220.304 142.988 220.371 142.869 220.371 142.741V137.523C220.371 137.247 220.074 137.075 219.836 137.213L218.294 138.107C218.184 138.172 218.116 138.29 218.116 138.419V143.636C218.116 143.912 218.413 144.084 218.651 143.946Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M214.301 146.316L215.843 145.421C215.954 145.358 216.022 145.239 216.022 145.111V139.894C216.022 139.618 215.724 139.446 215.487 139.584L213.945 140.478C213.834 140.542 213.766 140.661 213.766 140.789V146.006C213.766 146.282 214.064 146.454 214.301 146.316Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M209.951 148.925L211.494 148.03C211.604 147.966 211.672 147.847 211.672 147.719V142.502C211.672 142.226 211.375 142.054 211.137 142.192L209.595 143.086C209.485 143.15 209.417 143.269 209.417 143.397V148.614C209.417 148.89 209.714 149.063 209.951 148.925Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M205.602 151.414L207.144 150.519C207.255 150.456 207.322 150.337 207.322 150.209V144.991C207.322 144.716 207.025 144.543 206.787 144.681L205.245 145.575C205.135 145.64 205.067 145.758 205.067 145.886V151.104C205.067 151.38 205.364 151.552 205.602 151.414Z" fill="#6D6475"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M153.145 112.376L153.176 118.488C152.971 119.595 153.422 120.808 154.529 121.45L202.003 148.997C202.87 149.5 203.937 149.5 204.804 148.997L252.278 121.45C253.384 120.808 253.834 119.595 253.63 118.488L253.661 112.376" fill="#454545"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M202.003 141.196L154.529 113.649C152.661 112.566 152.661 109.857 154.529 108.774L202.003 81.2263C202.869 80.724 203.937 80.724 204.803 81.2263L252.277 108.774C254.145 109.857 254.145 112.566 252.277 113.649L204.804 141.196C203.937 141.699 202.869 141.699 202.003 141.196Z" fill="#545454"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M175.567 115.451C176.655 117.855 178.687 120.153 181.699 122.145C185.86 124.897 191.256 126.654 196.991 127.388C199.842 127.753 202.776 127.865 205.685 127.718C206.117 126.191 206.527 124.595 206.902 122.944C207.004 122.499 207.098 122.046 207.194 121.595C203.77 122.037 200.182 121.902 196.884 121.206L196.817 117.242L175.567 115.451Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M195.709 95.2149C191.624 95.8524 187.723 97.0234 184.334 98.748C179.587 101.165 176.557 104.299 175.295 107.631C174.67 109.279 174.479 110.975 174.729 112.656C177.361 112.907 180.112 113.146 182.96 113.364C183.724 113.423 184.504 113.478 185.281 113.534C184.522 111.549 184.756 109.47 185.953 107.559L192.84 107.513L195.709 95.2149Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M230.792 106.981C229.705 104.573 227.673 102.272 224.657 100.277C220.492 97.5232 215.09 95.7649 209.349 95.0321C206.508 94.6693 203.586 94.5587 200.688 94.7034C200.256 96.2311 199.844 97.8272 199.468 99.4797C199.366 99.9231 199.271 100.376 199.175 100.826C202.597 100.386 206.182 100.522 209.476 101.217L209.48 101.218L209.558 104.945L230.792 106.981Z" fill="white"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M210.774 127.184C214.812 126.542 218.668 125.381 222.022 123.674C226.764 121.26 229.793 118.129 231.057 114.802C231.686 113.147 231.878 111.444 231.626 109.757C228.994 109.506 226.244 109.268 223.397 109.051C222.632 108.992 221.851 108.936 221.073 108.881C221.837 110.871 221.602 112.957 220.398 114.873L220.371 114.912L213.699 114.981L210.774 127.184Z" fill="white"/> +<g opacity="0.372566"> +<rect width="57.1535" height="39.6589" fill="black" fill-opacity="0" transform="translate(180.849 191.194)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M183.395 216.512L182.537 216.014C182.475 215.978 182.437 215.912 182.437 215.842V212.937C182.437 212.784 182.603 212.687 182.735 212.764L183.593 213.262C183.655 213.298 183.693 213.364 183.693 213.435V216.34C183.693 216.493 183.527 216.589 183.395 216.512Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M185.816 217.898L184.958 217.399C184.896 217.364 184.858 217.298 184.858 217.227V214.323C184.858 214.169 185.024 214.073 185.156 214.15L186.014 214.648C186.076 214.683 186.114 214.75 186.114 214.821V217.725C186.114 217.879 185.948 217.974 185.816 217.898Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M188.237 219.284L187.379 218.785C187.317 218.75 187.279 218.684 187.279 218.613V215.709C187.279 215.555 187.445 215.459 187.577 215.536L188.435 216.034C188.497 216.069 188.535 216.135 188.535 216.207V219.111C188.535 219.264 188.369 219.36 188.237 219.284Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M190.658 220.669L189.8 220.171C189.738 220.135 189.7 220.069 189.7 219.998V217.094C189.7 216.94 189.866 216.844 189.998 216.921L190.856 217.419C190.918 217.455 190.956 217.521 190.956 217.592V220.496C190.956 220.65 190.79 220.746 190.658 220.669Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M193.079 222.054L192.221 221.556C192.159 221.521 192.121 221.455 192.121 221.384V218.48C192.121 218.326 192.287 218.23 192.419 218.307L193.277 218.805C193.339 218.84 193.377 218.906 193.377 218.978V221.882C193.377 222.035 193.211 222.131 193.079 222.054Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M195.5 223.44L194.642 222.942C194.58 222.906 194.542 222.84 194.542 222.769V219.865C194.542 219.711 194.708 219.615 194.84 219.692L195.698 220.19C195.76 220.226 195.798 220.292 195.798 220.363V223.268C195.798 223.421 195.632 223.517 195.5 223.44Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M197.921 224.826L197.063 224.327C197.001 224.292 196.963 224.226 196.963 224.155V221.251C196.963 221.097 197.129 221.001 197.261 221.078L198.119 221.576C198.181 221.611 198.219 221.677 198.219 221.749V224.653C198.219 224.807 198.053 224.902 197.921 224.826Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M200.342 226.343L199.484 225.846C199.422 225.81 199.385 225.744 199.385 225.673V222.769C199.385 222.615 199.55 222.519 199.682 222.596L200.541 223.094C200.602 223.13 200.64 223.195 200.64 223.267V226.171C200.64 226.324 200.474 226.42 200.342 226.343Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M202.763 227.663L201.905 227.165C201.843 227.129 201.806 227.063 201.806 226.992V224.088C201.806 223.934 201.971 223.839 202.103 223.915L202.962 224.413C203.023 224.449 203.061 224.515 203.061 224.586V227.49C203.061 227.644 202.895 227.74 202.763 227.663Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M205.184 229.115L204.326 228.616C204.264 228.581 204.227 228.515 204.227 228.444V225.54C204.227 225.386 204.392 225.29 204.524 225.367L205.383 225.865C205.444 225.9 205.482 225.966 205.482 226.038V228.942C205.482 229.095 205.316 229.191 205.184 229.115Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M207.605 230.5L206.747 230.002C206.685 229.967 206.648 229.901 206.648 229.83V226.926C206.648 226.772 206.813 226.676 206.945 226.752L207.804 227.251C207.865 227.286 207.903 227.352 207.903 227.424V230.328C207.903 230.481 207.738 230.577 207.605 230.5Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M235.4 216.54L236.277 216.032C236.339 215.995 236.378 215.928 236.378 215.855V212.889C236.378 212.733 236.209 212.635 236.074 212.713L235.197 213.222C235.134 213.258 235.096 213.325 235.096 213.398V216.364C235.096 216.521 235.265 216.619 235.4 216.54Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M232.927 217.955L233.804 217.447C233.867 217.41 233.906 217.343 233.906 217.27V214.305C233.906 214.148 233.737 214.05 233.601 214.128L232.725 214.637C232.662 214.673 232.624 214.74 232.624 214.813V217.779C232.624 217.936 232.792 218.034 232.927 217.955Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M230.455 219.37L231.332 218.862C231.395 218.825 231.433 218.758 231.433 218.685V215.719C231.433 215.562 231.264 215.464 231.129 215.543L230.253 216.052C230.19 216.088 230.151 216.155 230.151 216.228V219.194C230.151 219.351 230.32 219.449 230.455 219.37Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M227.983 220.785L228.859 220.277C228.922 220.24 228.961 220.173 228.961 220.1V217.134C228.961 216.977 228.792 216.879 228.657 216.958L227.78 217.467C227.717 217.503 227.678 217.57 227.678 217.643V220.609C227.678 220.765 227.848 220.863 227.983 220.785Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M225.51 222.2L226.387 221.692C226.45 221.655 226.489 221.588 226.489 221.515V218.549C226.489 218.392 226.319 218.295 226.184 218.373L225.308 218.882C225.245 218.918 225.206 218.985 225.206 219.058V222.024C225.206 222.18 225.375 222.278 225.51 222.2Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M223.038 223.615L223.915 223.107C223.977 223.07 224.016 223.003 224.016 222.93V219.964C224.016 219.808 223.847 219.71 223.712 219.788L222.835 220.297C222.772 220.333 222.734 220.4 222.734 220.473V223.439C222.734 223.595 222.903 223.693 223.038 223.615Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M220.565 225.03L221.442 224.522C221.505 224.485 221.544 224.418 221.544 224.345V221.379C221.544 221.222 221.375 221.124 221.239 221.203L220.363 221.712C220.3 221.748 220.262 221.815 220.262 221.888V224.854C220.262 225.011 220.43 225.109 220.565 225.03Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M218.093 226.58L218.97 226.072C219.033 226.035 219.071 225.968 219.071 225.895V222.929C219.071 222.773 218.902 222.675 218.767 222.753L217.891 223.262C217.828 223.298 217.789 223.365 217.789 223.438V226.404C217.789 226.561 217.958 226.658 218.093 226.58Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M215.621 227.928L216.498 227.419C216.56 227.382 216.599 227.315 216.599 227.242V224.277C216.599 224.12 216.43 224.022 216.295 224.1L215.418 224.609C215.355 224.646 215.317 224.713 215.317 224.786V227.751C215.317 227.908 215.486 228.006 215.621 227.928Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M213.148 229.41L214.025 228.902C214.088 228.865 214.127 228.798 214.127 228.725V225.759C214.127 225.602 213.958 225.504 213.822 225.583L212.946 226.092C212.883 226.128 212.844 226.195 212.844 226.268V229.234C212.844 229.391 213.013 229.489 213.148 229.41Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M210.676 230.825L211.552 230.317C211.615 230.28 211.654 230.213 211.654 230.14V227.174C211.654 227.017 211.485 226.919 211.35 226.998L210.473 227.507C210.411 227.543 210.372 227.61 210.372 227.683V230.649C210.372 230.805 210.541 230.903 210.676 230.825Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M180.859 208.635L180.877 212.11C180.76 212.739 181.017 213.428 181.646 213.793L208.63 229.452C209.123 229.737 209.73 229.737 210.222 229.452L237.207 213.793C237.836 213.429 238.092 212.739 237.975 212.11L237.993 208.635" fill="#8B81E6"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M208.63 225.495L181.646 209.837C180.584 209.221 180.584 207.682 181.646 207.065L208.63 191.408C209.123 191.122 209.73 191.122 210.222 191.408L237.207 207.065C238.268 207.682 238.268 209.221 237.207 209.837L210.222 225.495C209.73 225.781 209.123 225.781 208.63 225.495Z" fill="#A59EF7"/> +</g> +<g opacity="0.327785"> +<rect width="73.5288" height="51.0612" fill="black" fill-opacity="0" transform="translate(200.318 30.1121)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M203.593 62.7101L202.489 62.0689C202.41 62.0228 202.361 61.9378 202.361 61.8468V58.1075C202.361 57.9094 202.574 57.7857 202.744 57.8848L203.848 58.5259C203.927 58.5721 203.976 58.657 203.976 58.7487V62.4879C203.976 62.6855 203.763 62.8085 203.593 62.7101Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M206.707 64.4942L205.603 63.8524C205.524 63.8069 205.475 63.722 205.475 63.6303V59.8916C205.475 59.6935 205.688 59.5698 205.858 59.6689L206.963 60.31C207.042 60.3556 207.09 60.4411 207.09 60.5328V64.2721C207.09 64.4696 206.878 64.5926 206.707 64.4942Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M209.822 66.2782L208.718 65.6365C208.638 65.5909 208.59 65.506 208.59 65.4143V61.6757C208.59 61.4775 208.803 61.3539 208.973 61.4529L210.077 62.0941C210.156 62.1396 210.205 62.2245 210.205 62.3168V66.0555C210.205 66.253 209.992 66.3767 209.822 66.2782Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M212.937 68.0617L211.833 67.4205C211.753 67.375 211.705 67.2901 211.705 67.1984V63.4591C211.705 63.261 211.918 63.1379 212.088 63.2364L213.192 63.8781C213.271 63.9237 213.32 64.0086 213.32 64.1009V67.8395C213.32 68.0371 213.107 68.1607 212.937 68.0617Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M216.052 69.8457L214.947 69.2046C214.868 69.1584 214.819 69.0735 214.819 68.9824V65.2431C214.819 65.045 215.032 64.922 215.202 65.0204L216.307 65.6616C216.386 65.7077 216.435 65.7926 216.435 65.8849V69.6236C216.435 69.8211 216.222 69.9448 216.052 69.8457Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M219.166 71.6298L218.062 70.9886C217.983 70.9425 217.934 70.8576 217.934 70.7659V67.0272C217.934 66.8291 218.147 66.7054 218.317 66.8045L219.421 67.4456C219.5 67.4918 219.549 67.5767 219.549 67.6684V71.4076C219.549 71.6052 219.336 71.7282 219.166 71.6298Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M222.281 73.4138L221.177 72.772C221.097 72.7265 221.049 72.6416 221.049 72.5499V68.8112C221.049 68.6131 221.262 68.4894 221.432 68.5885L222.536 69.2297C222.615 69.2752 222.664 69.3601 222.664 69.4524V73.1917C222.664 73.3892 222.451 73.5123 222.281 73.4138Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M225.396 75.3679L224.292 74.7268C224.212 74.6806 224.164 74.5957 224.164 74.5047V70.7654C224.164 70.5672 224.377 70.4442 224.547 70.5426L225.651 71.1838C225.73 71.2299 225.779 71.3149 225.779 71.4071V75.1458C225.779 75.3433 225.566 75.467 225.396 75.3679Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M228.51 77.0667L227.406 76.4255C227.327 76.3794 227.278 76.2945 227.278 76.2034V72.4641C227.278 72.266 227.491 72.1429 227.661 72.2414L228.766 72.8825C228.844 72.9287 228.893 73.0136 228.893 73.1053V76.8446C228.893 77.0421 228.681 77.1658 228.51 77.0667Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M231.625 78.9361L230.52 78.2943C230.441 78.2488 230.393 78.1639 230.393 78.0722V74.3335C230.393 74.1354 230.605 74.0117 230.776 74.1108L231.88 74.7519C231.959 74.7975 232.008 74.8824 232.008 74.9747V78.7134C232.008 78.9109 231.795 79.0346 231.625 78.9361Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M234.74 80.7195L233.635 80.0784C233.556 80.0328 233.508 79.9479 233.508 79.8562V76.1176C233.508 75.9195 233.72 75.7958 233.891 75.8942L234.995 76.536C235.074 76.5815 235.123 76.6664 235.123 76.7587V80.4974C235.123 80.6949 234.91 80.8186 234.74 80.7195Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M270.498 62.7461L271.626 62.0914C271.707 62.0441 271.756 61.9579 271.756 61.8638V58.0457C271.756 57.8439 271.539 57.7178 271.365 57.8187L270.237 58.474C270.157 58.5208 270.107 58.6069 270.107 58.701V62.5191C270.107 62.7209 270.324 62.847 270.498 62.7461Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M267.317 64.5681L268.445 63.9134C268.526 63.866 268.576 63.7799 268.576 63.6857V59.8677C268.576 59.6659 268.358 59.5397 268.184 59.6406L267.057 60.2959C266.976 60.3421 266.926 60.4289 266.926 60.523V64.341C266.926 64.5429 267.143 64.669 267.317 64.5681Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M264.136 66.39L265.265 65.7353C265.345 65.6879 265.395 65.6018 265.395 65.5076V61.689C265.395 61.4871 265.178 61.361 265.003 61.4619L263.876 62.1172C263.795 62.164 263.746 62.2501 263.746 62.3443V66.1629C263.746 66.3647 263.963 66.4909 264.136 66.39Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M260.956 68.2113L262.083 67.5572C262.165 67.5098 262.214 67.4231 262.214 67.3296V63.5109C262.214 63.3091 261.996 63.1829 261.823 63.2839L260.695 63.9392C260.614 63.9859 260.564 64.0721 260.564 64.1662V67.9843C260.564 68.1861 260.782 68.3122 260.956 68.2113Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M257.775 70.0332L258.902 69.3785C258.983 69.3311 259.033 69.245 259.033 69.1508V65.3328C259.033 65.131 258.816 65.0048 258.642 65.1057L257.514 65.7611C257.434 65.8078 257.383 65.894 257.383 65.9881V69.8061C257.383 70.008 257.601 70.1341 257.775 70.0332Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M254.594 71.8551L255.722 71.2004C255.803 71.153 255.852 71.0669 255.852 70.9727V67.1547C255.852 66.9529 255.635 66.8267 255.461 66.9277L254.333 67.583C254.253 67.6297 254.203 67.7159 254.203 67.81V71.6281C254.203 71.8299 254.42 71.956 254.594 71.8551Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M251.413 73.6771L252.541 73.0224C252.622 72.975 252.672 72.8888 252.672 72.7947V68.976C252.672 68.7742 252.455 68.6481 252.28 68.749L251.153 69.4043C251.072 69.4511 251.022 69.5372 251.022 69.6313V73.45C251.022 73.6518 251.24 73.778 251.413 73.6771Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M248.233 75.6726L249.361 75.0179C249.441 74.9705 249.491 74.8844 249.491 74.7902V70.9722C249.491 70.7704 249.274 70.6442 249.099 70.7451L247.972 71.4004C247.891 71.4472 247.842 71.5333 247.842 71.6275V75.4455C247.842 75.6474 248.059 75.7735 248.233 75.6726Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M245.052 77.4074L246.18 76.7527C246.261 76.7053 246.31 76.6192 246.31 76.525V72.707C246.31 72.5052 246.093 72.379 245.919 72.4799L244.791 73.1353C244.711 73.182 244.661 73.2682 244.661 73.3623V77.1803C244.661 77.3822 244.878 77.5083 245.052 77.4074Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M241.871 79.3164L242.999 78.6617C243.08 78.6144 243.129 78.5282 243.129 78.4341V74.6154C243.129 74.4136 242.912 74.2874 242.738 74.3884L241.61 75.0437C241.53 75.0904 241.48 75.1766 241.48 75.2707V79.0894C241.48 79.2912 241.697 79.4173 241.871 79.3164Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M238.69 81.1378L239.818 80.4837C239.899 80.4363 239.949 80.3495 239.949 80.256V76.4374C239.949 76.2355 239.731 76.1094 239.557 76.2103L238.43 76.8656C238.349 76.9124 238.299 76.9985 238.299 77.0927V80.9107C238.299 81.1125 238.517 81.2387 238.69 81.1378Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M200.331 52.5682L200.353 57.0421C200.203 57.8519 200.533 58.7392 201.342 59.2093L236.058 79.3695C236.692 79.7369 237.473 79.7369 238.107 79.3695L272.823 59.2093C273.632 58.7398 273.961 57.8519 273.811 57.0421L273.835 52.5682" fill="#8B81E6"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M236.058 74.2755L201.342 54.1153C199.977 53.3227 199.977 51.3408 201.342 50.547L236.058 30.388C236.692 30.0201 237.473 30.0201 238.107 30.388L272.823 50.547C274.188 51.3408 274.188 53.3227 272.823 54.1153L238.107 74.2755C237.473 74.6435 236.692 74.6435 236.058 74.2755Z" fill="#A59EF7"/> +</g> +<g opacity="0.120697"> +<rect width="28.3611" height="20.2117" fill="black" fill-opacity="0" transform="translate(79.9083 149.104)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M81.1767 162.008L80.746 161.754C80.7152 161.736 80.6961 161.702 80.6961 161.666V160.186C80.6961 160.107 80.7792 160.058 80.8455 160.098L81.2762 160.351C81.3072 160.37 81.3261 160.403 81.3261 160.44V161.92C81.3261 161.998 81.243 162.047 81.1767 162.008Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M82.3781 162.714L81.9474 162.46C81.9166 162.442 81.8975 162.408 81.8975 162.372V160.892C81.8975 160.814 81.9806 160.765 82.0469 160.804L82.4776 161.058C82.5084 161.076 82.5275 161.11 82.5275 161.146V162.626C82.5275 162.704 82.4444 162.753 82.3781 162.714Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M83.5795 163.42L83.1488 163.166C83.1178 163.148 83.0989 163.114 83.0989 163.078V161.598C83.0989 161.52 83.182 161.471 83.2483 161.51L83.679 161.764C83.7098 161.782 83.7288 161.815 83.7288 161.852V163.332C83.7288 163.41 83.6458 163.459 83.5795 163.42Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M84.7809 164.126L84.3502 163.872C84.3191 163.854 84.3003 163.821 84.3003 163.784V162.304C84.3003 162.226 84.3833 162.177 84.4497 162.216L84.8804 162.47C84.9111 162.488 84.9302 162.522 84.9302 162.558V164.038C84.9302 164.116 84.8472 164.165 84.7809 164.126Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M85.9823 164.832L85.5516 164.578C85.5205 164.56 85.5017 164.527 85.5017 164.49V163.01C85.5017 162.932 85.5847 162.883 85.6511 162.922L86.0817 163.176C86.1125 163.194 86.1316 163.228 86.1316 163.264V164.744C86.1316 164.822 86.0486 164.871 85.9823 164.832Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M87.1837 165.538L86.753 165.285C86.7219 165.266 86.7031 165.233 86.7031 165.196V163.717C86.7031 163.638 86.7861 163.589 86.8525 163.628L87.2832 163.882C87.3139 163.9 87.333 163.934 87.333 163.97V165.45C87.333 165.529 87.25 165.577 87.1837 165.538Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M88.385 166.245L87.9543 165.991C87.9233 165.972 87.9045 165.939 87.9045 165.903V164.423C87.9045 164.344 87.9875 164.295 88.0538 164.335L88.4845 164.588C88.5153 164.606 88.5344 164.64 88.5344 164.676V166.157C88.5344 166.235 88.4514 166.284 88.385 166.245Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M89.5864 167.018L89.1557 166.764C89.1247 166.746 89.1059 166.712 89.1059 166.676V165.196C89.1059 165.118 89.1889 165.069 89.2552 165.108L89.6859 165.362C89.7167 165.38 89.7358 165.414 89.7358 165.45V166.93C89.7358 167.008 89.6528 167.057 89.5864 167.018Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M90.7878 167.69L90.3571 167.437C90.3261 167.418 90.3073 167.385 90.3073 167.349V165.869C90.3073 165.79 90.39 165.742 90.4566 165.78L90.8873 166.034C90.9181 166.053 90.9372 166.086 90.9372 166.122V167.603C90.9372 167.681 90.8541 167.73 90.7878 167.69Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M91.9892 168.43L91.5583 168.176C91.5275 168.158 91.5086 168.125 91.5086 168.089V166.609C91.5086 166.53 91.5914 166.481 91.658 166.52L92.0887 166.774C92.1195 166.792 92.1386 166.826 92.1386 166.862V168.342C92.1386 168.42 92.0555 168.469 91.9892 168.43Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M93.1906 169.136L92.7596 168.883C92.7289 168.865 92.71 168.831 92.71 168.795V167.315C92.71 167.236 92.7928 167.187 92.8594 167.226L93.2901 167.48C93.3209 167.498 93.3399 167.532 93.3399 167.569V169.048C93.3399 169.127 93.2569 169.176 93.1906 169.136Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M106.978 162.022L107.413 161.763C107.444 161.744 107.463 161.71 107.463 161.673V160.161C107.463 160.081 107.379 160.032 107.312 160.071L106.877 160.331C106.846 160.349 106.827 160.383 106.827 160.421V161.932C106.827 162.012 106.911 162.062 106.978 162.022Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M105.751 162.743L106.186 162.484C106.217 162.465 106.236 162.431 106.236 162.394V160.883C106.236 160.803 106.152 160.753 106.085 160.793L105.65 161.052C105.619 161.07 105.6 161.105 105.6 161.142V162.653C105.6 162.733 105.684 162.783 105.751 162.743Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M104.524 163.464L104.959 163.205C104.99 163.186 105.009 163.152 105.009 163.115V161.603C105.009 161.524 104.926 161.474 104.858 161.514L104.423 161.773C104.392 161.791 104.373 161.826 104.373 161.863V163.374C104.373 163.454 104.457 163.504 104.524 163.464Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M103.297 164.185L103.732 163.926C103.763 163.908 103.782 163.873 103.782 163.836V162.325C103.782 162.245 103.698 162.195 103.631 162.235L103.197 162.494C103.165 162.513 103.146 162.547 103.146 162.584V164.095C103.146 164.175 103.23 164.225 103.297 164.185Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M102.07 164.906L102.505 164.647C102.536 164.628 102.556 164.594 102.556 164.557V163.046C102.556 162.966 102.472 162.916 102.405 162.956L101.97 163.215C101.939 163.234 101.919 163.268 101.919 163.305V164.817C101.919 164.896 102.003 164.946 102.07 164.906Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M100.843 165.628L101.278 165.368C101.31 165.35 101.329 165.316 101.329 165.278V163.767C101.329 163.687 101.245 163.637 101.178 163.677L100.743 163.937C100.712 163.955 100.693 163.989 100.693 164.026V165.538C100.693 165.618 100.776 165.668 100.843 165.628Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M99.6164 166.349L100.052 166.09C100.083 166.071 100.102 166.037 100.102 165.999V164.488C100.102 164.408 100.018 164.358 99.9508 164.398L99.5159 164.657C99.4848 164.676 99.4657 164.71 99.4657 164.747V166.259C99.4657 166.339 99.5494 166.389 99.6164 166.349Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M98.3896 167.139L98.8247 166.879C98.8559 166.861 98.875 166.827 98.875 166.789V165.278C98.875 165.198 98.7912 165.148 98.724 165.188L98.2891 165.448C98.2579 165.466 98.2388 165.5 98.2388 165.537V167.049C98.2388 167.129 98.3226 167.179 98.3896 167.139Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M97.1627 167.825L97.5979 167.566C97.629 167.547 97.6481 167.513 97.6481 167.476V165.965C97.6481 165.885 97.5644 165.835 97.4971 165.875L97.0622 166.134C97.0311 166.153 97.012 166.187 97.012 166.224V167.735C97.012 167.815 97.0957 167.865 97.1627 167.825Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M95.9359 168.581L96.371 168.322C96.4021 168.303 96.4213 168.269 96.4213 168.232V166.72C96.4213 166.64 96.3375 166.59 96.2702 166.63L95.8353 166.89C95.8042 166.908 95.7849 166.942 95.7849 166.98V168.491C95.7849 168.571 95.8689 168.621 95.9359 168.581Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M94.709 169.302L95.1439 169.043C95.1751 169.024 95.1944 168.99 95.1944 168.953V167.441C95.1944 167.361 95.1104 167.312 95.0434 167.352L94.6085 167.611C94.5774 167.629 94.558 167.664 94.558 167.701V169.212C94.558 169.292 94.642 169.342 94.709 169.302Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M79.9131 157.993L79.9218 159.764C79.864 160.085 79.9912 160.436 80.3034 160.622L93.6939 168.602C93.9383 168.747 94.2394 168.747 94.4839 168.602L107.874 160.622C108.186 160.436 108.314 160.085 108.256 159.764L108.265 157.993" fill="#8B81E6"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M93.6938 166.586L80.3033 158.606C79.7767 158.292 79.7767 157.507 80.3033 157.193L93.6938 149.214C93.9383 149.068 94.2394 149.068 94.4839 149.214L107.874 157.193C108.401 157.507 108.401 158.292 107.874 158.606L94.4839 166.586C94.2396 166.731 93.9383 166.731 93.6938 166.586Z" fill="#A59EF7"/> +</g> +<g opacity="0.120697"> +<rect width="28.3611" height="20.2117" fill="black" fill-opacity="0" transform="translate(99.2107 137.283)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M100.479 150.186L100.048 149.932C100.018 149.914 99.9986 149.88 99.9986 149.844V148.364C99.9986 148.286 100.082 148.237 100.148 148.276L100.579 148.53C100.61 148.548 100.629 148.582 100.629 148.618V150.098C100.629 150.176 100.545 150.225 100.479 150.186Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M101.681 150.892L101.25 150.638C101.219 150.62 101.2 150.587 101.2 150.55V149.07C101.2 148.992 101.283 148.943 101.349 148.982L101.78 149.236C101.811 149.254 101.83 149.288 101.83 149.324V150.804C101.83 150.882 101.747 150.931 101.681 150.892Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M102.882 151.598L102.451 151.344C102.42 151.326 102.401 151.293 102.401 151.256V149.777C102.401 149.698 102.484 149.649 102.551 149.688L102.981 149.942C103.012 149.96 103.031 149.994 103.031 150.03V151.51C103.031 151.588 102.948 151.637 102.882 151.598Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M104.083 152.304L103.653 152.051C103.622 152.033 103.603 151.999 103.603 151.963V150.482C103.603 150.404 103.686 150.355 103.752 150.394L104.183 150.648C104.214 150.666 104.233 150.7 104.233 150.737V152.216C104.233 152.295 104.15 152.344 104.083 152.304Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M105.285 153.011L104.854 152.757C104.823 152.738 104.804 152.705 104.804 152.669V151.189C104.804 151.11 104.887 151.062 104.954 151.101L105.384 151.354C105.415 151.373 105.434 151.406 105.434 151.443V152.923C105.434 153.001 105.351 153.05 105.285 153.011Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M106.486 153.717L106.055 153.463C106.024 153.445 106.006 153.411 106.006 153.375V151.895C106.006 151.816 106.089 151.767 106.155 151.807L106.586 152.06C106.616 152.079 106.635 152.112 106.635 152.149V153.629C106.635 153.707 106.552 153.756 106.486 153.717Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M107.687 154.423L107.257 154.169C107.226 154.151 107.207 154.117 107.207 154.081V152.601C107.207 152.523 107.29 152.474 107.356 152.513L107.787 152.767C107.818 152.785 107.837 152.818 107.837 152.855V154.335C107.837 154.413 107.754 154.462 107.687 154.423Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M108.889 155.196L108.458 154.943C108.427 154.924 108.408 154.891 108.408 154.855V153.375C108.408 153.296 108.491 153.247 108.558 153.286L108.988 153.54C109.019 153.558 109.038 153.592 109.038 153.629V155.108C109.038 155.187 108.955 155.236 108.889 155.196Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M110.09 155.869L109.66 155.615C109.629 155.597 109.61 155.563 109.61 155.527V154.047C109.61 153.969 109.693 153.92 109.759 153.959L110.19 154.213C110.221 154.231 110.24 154.264 110.24 154.301V155.781C110.24 155.859 110.157 155.908 110.09 155.869Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M111.292 156.609L110.861 156.355C110.83 156.337 110.811 156.303 110.811 156.267V154.787C110.811 154.709 110.894 154.66 110.96 154.699L111.391 154.953C111.422 154.971 111.441 155.004 111.441 155.041V156.521C111.441 156.599 111.358 156.648 111.292 156.609Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M112.493 157.315L112.062 157.061C112.031 157.043 112.012 157.009 112.012 156.973V155.493C112.012 155.415 112.095 155.366 112.162 155.405L112.593 155.659C112.623 155.677 112.642 155.71 112.642 155.747V157.227C112.642 157.305 112.559 157.354 112.493 157.315Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M126.28 150.2L126.715 149.941C126.746 149.922 126.766 149.888 126.766 149.851V148.34C126.766 148.26 126.682 148.21 126.614 148.25L126.18 148.509C126.148 148.528 126.129 148.562 126.129 148.599V150.11C126.129 150.19 126.213 150.24 126.28 150.2Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M125.053 150.921L125.488 150.662C125.52 150.644 125.539 150.609 125.539 150.572V149.061C125.539 148.981 125.455 148.931 125.388 148.971L124.953 149.23C124.922 149.249 124.902 149.283 124.902 149.32V150.832C124.902 150.911 124.986 150.961 125.053 150.921Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M123.826 151.643L124.262 151.383C124.293 151.365 124.312 151.331 124.312 151.293V149.782C124.312 149.702 124.228 149.652 124.161 149.692L123.726 149.951C123.695 149.97 123.676 150.004 123.676 150.041V151.553C123.676 151.633 123.759 151.683 123.826 151.643Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M122.6 152.364L123.034 152.105C123.066 152.086 123.085 152.052 123.085 152.015V150.503C123.085 150.423 123.001 150.373 122.934 150.413L122.499 150.673C122.468 150.691 122.449 150.725 122.449 150.762V152.274C122.449 152.354 122.533 152.404 122.6 152.364Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M121.373 153.085L121.808 152.826C121.839 152.807 121.858 152.773 121.858 152.735V151.224C121.858 151.144 121.774 151.094 121.707 151.134L121.272 151.394C121.241 151.412 121.222 151.446 121.222 151.484V152.995C121.222 153.075 121.306 153.125 121.373 153.085Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M120.146 153.806L120.581 153.547C120.612 153.528 120.631 153.494 120.631 153.457V151.945C120.631 151.865 120.547 151.816 120.48 151.855L120.045 152.115C120.014 152.133 119.995 152.167 119.995 152.205V153.716C119.995 153.796 120.079 153.846 120.146 153.806Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M118.919 154.527L119.354 154.268C119.385 154.249 119.404 154.215 119.404 154.178V152.666C119.404 152.586 119.321 152.536 119.253 152.576L118.818 152.836C118.787 152.854 118.768 152.888 118.768 152.926V154.437C118.768 154.517 118.852 154.567 118.919 154.527Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M117.692 155.317L118.127 155.058C118.158 155.039 118.177 155.005 118.177 154.968V153.456C118.177 153.377 118.094 153.327 118.026 153.367L117.592 153.626C117.56 153.644 117.541 153.679 117.541 153.716V155.227C117.541 155.307 117.625 155.357 117.692 155.317Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M116.465 156.004L116.9 155.745C116.931 155.726 116.951 155.692 116.951 155.654V154.143C116.951 154.063 116.867 154.013 116.8 154.053L116.365 154.313C116.334 154.331 116.314 154.365 116.314 154.403V155.914C116.314 155.994 116.398 156.044 116.465 156.004Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M115.238 156.759L115.673 156.5C115.705 156.481 115.724 156.447 115.724 156.41V154.899C115.724 154.819 115.64 154.769 115.573 154.809L115.138 155.068C115.107 155.087 115.087 155.121 115.087 155.158V156.669C115.087 156.749 115.171 156.799 115.238 156.759Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M114.011 157.48L114.446 157.221C114.478 157.203 114.497 157.168 114.497 157.131V155.62C114.497 155.54 114.413 155.49 114.346 155.53L113.911 155.789C113.88 155.808 113.86 155.842 113.86 155.879V157.39C113.86 157.47 113.944 157.52 114.011 157.48Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M99.2155 146.172L99.2243 147.942C99.1665 148.263 99.2936 148.614 99.6058 148.8L112.996 156.78C113.241 156.926 113.542 156.926 113.786 156.78L127.177 148.8C127.489 148.614 127.616 148.263 127.558 147.942L127.567 146.172" fill="#8B81E6"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M112.996 154.764L99.6058 146.784C99.0791 146.47 99.0791 145.686 99.6058 145.371L112.996 137.392C113.241 137.246 113.542 137.246 113.786 137.392L127.177 145.371C127.703 145.686 127.703 146.47 127.177 146.784L113.786 154.764C113.542 154.91 113.241 154.91 112.996 154.764Z" fill="#A59EF7"/> +</g> +<g opacity="0.120697"> +<rect width="28.3611" height="20.2117" fill="black" fill-opacity="0" transform="translate(268.643 57.7552)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M269.912 70.6586L269.481 70.4048C269.45 70.3865 269.431 70.3529 269.431 70.3169V68.8367C269.431 68.7583 269.514 68.7093 269.581 68.7486L270.011 69.0024C270.042 69.0206 270.061 69.0542 270.061 69.0905V70.5707C270.061 70.6488 269.978 70.6975 269.912 70.6586Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M271.113 71.3648L270.683 71.1108C270.652 71.0927 270.633 71.0591 270.633 71.0228V69.5429C270.633 69.4645 270.716 69.4156 270.782 69.4548L271.213 69.7086C271.243 69.7266 271.263 69.7604 271.263 69.7967V71.2769C271.263 71.355 271.18 71.4038 271.113 71.3648Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M272.315 72.071L271.884 71.8169C271.853 71.7989 271.834 71.7653 271.834 71.729V70.2491C271.834 70.1707 271.917 70.1217 271.983 70.161L272.414 70.4147C272.445 70.4328 272.464 70.4664 272.464 70.5029V71.9828C272.464 72.061 272.381 72.1099 272.315 72.071Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M273.516 72.7769L273.085 72.5231C273.054 72.5051 273.035 72.4715 273.035 72.4352V70.9551C273.035 70.8766 273.118 70.8279 273.185 70.8669L273.616 71.1209C273.646 71.1389 273.665 71.1726 273.665 71.2091V72.689C273.665 72.7672 273.582 72.8161 273.516 72.7769Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M274.717 73.4831L274.287 73.2293C274.256 73.211 274.237 73.1774 274.237 73.1414V71.6613C274.237 71.5828 274.32 71.5341 274.386 71.5731L274.817 71.8269C274.848 71.8451 274.867 71.8788 274.867 71.9153V73.3952C274.867 73.4734 274.784 73.5223 274.717 73.4831Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M275.919 74.1893L275.488 73.9355C275.457 73.9172 275.438 73.8836 275.438 73.8473V72.3674C275.438 72.289 275.521 72.2401 275.588 72.2793L276.018 72.5331C276.049 72.5513 276.068 72.5849 276.068 72.6212V74.1014C276.068 74.1795 275.985 74.2283 275.919 74.1893Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M277.12 74.8955L276.689 74.6414C276.658 74.6234 276.64 74.5898 276.64 74.5535V73.0736C276.64 72.9952 276.723 72.9462 276.789 72.9855L277.22 73.2393C277.25 73.2573 277.27 73.2909 277.27 73.3274V74.8076C277.27 74.8857 277.186 74.9344 277.12 74.8955Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M278.322 75.669L277.891 75.4152C277.86 75.3969 277.841 75.3633 277.841 75.3273V73.8471C277.841 73.7687 277.924 73.72 277.99 73.759L278.421 74.0128C278.452 74.031 278.471 74.0646 278.471 74.1012V75.5811C278.471 75.6592 278.388 75.7082 278.322 75.669Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M279.523 76.3414L279.092 76.0876C279.061 76.0693 279.042 76.0357 279.042 75.9997V74.5196C279.042 74.4411 279.125 74.3924 279.192 74.4314L279.622 74.6852C279.653 74.7034 279.672 74.7371 279.672 74.7733V76.2535C279.672 76.3317 279.589 76.3806 279.523 76.3414Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M280.724 77.0814L280.293 76.8273C280.263 76.8093 280.244 76.7757 280.244 76.7394V75.2595C280.244 75.1811 280.327 75.1322 280.393 75.1714L280.824 75.4252C280.855 75.4432 280.874 75.4768 280.874 75.5133V76.9932C280.874 77.0714 280.791 77.1204 280.724 77.0814Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M281.926 77.7873L281.495 77.5335C281.464 77.5155 281.445 77.4819 281.445 77.4456V75.9657C281.445 75.8873 281.528 75.8383 281.595 75.8773L282.025 76.1313C282.056 76.1494 282.075 76.183 282.075 76.2195V77.6994C282.075 77.7776 281.992 77.8265 281.926 77.7873Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M295.713 70.6729L296.148 70.4137C296.179 70.3949 296.198 70.3608 296.198 70.3236V68.8123C296.198 68.7324 296.114 68.6825 296.047 68.7224L295.612 68.9818C295.581 69.0003 295.562 69.0344 295.562 69.0717V70.583C295.562 70.6629 295.646 70.7128 295.713 70.6729Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M294.486 71.394L294.921 71.1349C294.952 71.1161 294.971 71.082 294.971 71.0448V69.5335C294.971 69.4536 294.888 69.4036 294.82 69.4436L294.385 69.703C294.354 69.7212 294.335 69.7556 294.335 69.7929V71.3042C294.335 71.3841 294.419 71.434 294.486 71.394Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M293.259 72.1152L293.694 71.856C293.725 71.8373 293.744 71.8032 293.744 71.7659V70.2544C293.744 70.1745 293.661 70.1246 293.593 70.1645L293.159 70.4239C293.127 70.4424 293.108 70.4765 293.108 70.5138V72.0253C293.108 72.1052 293.192 72.1551 293.259 72.1152Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M292.032 72.8362L292.467 72.5772C292.499 72.5585 292.518 72.5241 292.518 72.4871V70.9756C292.518 70.8957 292.434 70.8458 292.367 70.8857L291.932 71.1451C291.901 71.1636 291.881 71.1977 291.881 71.235V72.7463C291.881 72.8262 291.965 72.8761 292.032 72.8362Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M290.805 73.5573L291.24 73.2982C291.271 73.2794 291.291 73.2453 291.291 73.2081V71.6967C291.291 71.6169 291.207 71.5669 291.14 71.6069L290.705 71.8663C290.674 71.8848 290.654 71.9189 290.654 71.9561V73.4674C290.654 73.5473 290.738 73.5973 290.805 73.5573Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M289.578 74.2785L290.014 74.0193C290.045 74.0006 290.064 73.9665 290.064 73.9292V72.4179C290.064 72.338 289.98 72.2881 289.913 72.328L289.478 72.5874C289.447 72.6059 289.428 72.64 289.428 72.6773V74.1886C289.428 74.2685 289.511 74.3184 289.578 74.2785Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M288.352 74.9997L288.787 74.7405C288.818 74.7218 288.837 74.6877 288.837 74.6504V73.1389C288.837 73.059 288.753 73.009 288.686 73.049L288.251 73.3084C288.22 73.3269 288.201 73.361 288.201 73.3982V74.9098C288.201 74.9897 288.285 75.0396 288.352 74.9997Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M287.125 75.7896L287.56 75.5304C287.591 75.5117 287.61 75.4776 287.61 75.4403V73.929C287.61 73.8491 287.526 73.7992 287.459 73.8391L287.024 74.0985C286.993 74.117 286.974 74.1511 286.974 74.1884V75.6997C286.974 75.7796 287.058 75.8295 287.125 75.7896Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M285.898 76.4763L286.333 76.2171C286.364 76.1984 286.383 76.1643 286.383 76.127V74.6157C286.383 74.5358 286.3 74.4859 286.232 74.5258L285.797 74.7852C285.766 74.8037 285.747 74.8378 285.747 74.8751V76.3864C285.747 76.4663 285.831 76.5162 285.898 76.4763Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M284.671 77.2319L285.106 76.9728C285.137 76.954 285.156 76.9199 285.156 76.8827V75.3711C285.156 75.2912 285.073 75.2413 285.005 75.2812L284.57 75.5406C284.539 75.5591 284.52 75.5932 284.52 75.6305V77.1421C284.52 77.2219 284.604 77.2719 284.671 77.2319Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M283.444 77.9529L283.879 77.694C283.91 77.6752 283.93 77.6409 283.93 77.6038V76.0923C283.93 76.0124 283.846 75.9625 283.779 76.0024L283.344 76.2618C283.313 76.2803 283.293 76.3144 283.293 76.3517V77.863C283.293 77.9429 283.377 77.9928 283.444 77.9529Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M268.648 66.6441L268.657 68.415C268.599 68.7355 268.726 69.0868 269.039 69.2728L282.429 77.2529C282.673 77.3983 282.975 77.3983 283.219 77.2529L296.61 69.2728C296.921 69.087 297.049 68.7355 296.991 68.415L297 66.6441" fill="#8B81E6"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M282.429 75.2366L269.038 67.2565C268.512 66.9428 268.512 66.1582 269.038 65.844L282.429 57.8644C282.673 57.7188 282.974 57.7188 283.219 57.8644L296.609 65.844C297.136 66.1582 297.136 66.9428 296.609 67.2565L283.219 75.2366C282.975 75.3822 282.673 75.3822 282.429 75.2366Z" fill="#A59EF7"/> +</g> +<g opacity="0.327785"> +<rect width="49.9817" height="34.933" fill="black" fill-opacity="0" transform="translate(180.671 11.4867)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M182.898 33.788L182.147 33.3494C182.093 33.3176 182.06 33.2598 182.06 33.1975V30.6391C182.06 30.5041 182.205 30.4195 182.32 30.4867L183.071 30.9253C183.125 30.957 183.158 31.0149 183.158 31.0784V33.6362C183.158 33.7712 183.013 33.8552 182.898 33.788Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M185.015 35.0087L184.264 34.57C184.21 34.5383 184.177 34.4798 184.177 34.4176V31.8592C184.177 31.7248 184.322 31.6395 184.438 31.7073L185.188 32.146C185.242 32.1777 185.275 32.2356 185.275 32.2984V34.8562C185.275 34.9919 185.13 35.0759 185.015 35.0087Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M187.132 36.2287L186.381 35.7901C186.327 35.759 186.295 35.7005 186.295 35.6383V33.0798C186.295 32.9448 186.439 32.8602 186.555 32.9274L187.306 33.3667C187.359 33.3978 187.392 33.4563 187.392 33.5191V36.0769C187.392 36.2119 187.247 36.2966 187.132 36.2287Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M189.249 37.4495L188.498 37.0108C188.445 36.9791 188.411 36.9212 188.411 36.8584V34.2999C188.411 34.1656 188.557 34.0809 188.672 34.1481L189.423 34.5868C189.477 34.6185 189.509 34.6764 189.509 34.7398V37.297C189.509 37.4327 189.365 37.5167 189.249 37.4495Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M191.366 38.6695L190.616 38.2309C190.562 38.1998 190.529 38.1413 190.529 38.0791V35.5206C190.529 35.3856 190.674 35.301 190.789 35.3688L191.54 35.8075C191.594 35.8386 191.627 35.8971 191.627 35.9599V38.5177C191.627 38.6534 191.482 38.7374 191.366 38.6695Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M193.484 39.8902L192.733 39.4516C192.679 39.4198 192.646 39.362 192.646 39.2998V36.7413C192.646 36.6063 192.791 36.5217 192.906 36.5889L193.657 37.0275C193.711 37.0593 193.744 37.1171 193.744 37.1806V39.7384C193.744 39.8734 193.599 39.9574 193.484 39.8902Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M195.601 41.1109L194.85 40.6722C194.796 40.6405 194.763 40.582 194.763 40.5198V37.9614C194.763 37.827 194.908 37.7423 195.024 37.8095L195.774 38.2482C195.828 38.2799 195.861 38.3378 195.861 38.4006V40.9585C195.861 41.0941 195.717 41.1781 195.601 41.1109Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M197.718 42.4477L196.967 42.009C196.913 41.9773 196.881 41.9194 196.881 41.8572V39.2988C196.881 39.1637 197.025 39.0791 197.141 39.1463L197.892 39.585C197.945 39.6167 197.979 39.6752 197.979 39.738V42.2959C197.979 42.4309 197.834 42.5155 197.718 42.4477Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M199.835 43.61L199.084 43.1713C199.031 43.1396 198.998 43.0817 198.998 43.0189V40.4605C198.998 40.3261 199.143 40.2414 199.258 40.3086L200.009 40.7473C200.063 40.779 200.095 40.8369 200.095 40.9003V43.4576C200.095 43.5932 199.951 43.6772 199.835 43.61Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M201.953 44.8884L201.202 44.4498C201.148 44.4187 201.115 44.3602 201.115 44.2979V41.7395C201.115 41.6045 201.26 41.5199 201.375 41.5877L202.126 42.0263C202.18 42.0574 202.213 42.1159 202.213 42.1788V44.7366C202.213 44.8722 202.068 44.9562 201.953 44.8884Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M204.07 46.1091L203.319 45.6704C203.265 45.6387 203.233 45.5808 203.233 45.518V42.9602C203.233 42.8252 203.377 42.7405 203.493 42.8077L204.243 43.2464C204.297 43.2781 204.33 43.336 204.33 43.3994V45.9573C204.33 46.0923 204.185 46.1763 204.07 46.1091Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M228.377 33.8129L229.143 33.3643C229.198 33.3332 229.232 33.2735 229.232 33.2094V30.5968C229.232 30.4587 229.084 30.3728 228.966 30.4419L228.199 30.8898C228.144 30.9222 228.111 30.9807 228.111 31.0454V33.6574C228.111 33.7955 228.259 33.8813 228.377 33.8129Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M226.215 35.0591L226.981 34.6112C227.036 34.5794 227.07 34.5197 227.07 34.4556V31.8437C227.07 31.7049 226.922 31.619 226.803 31.6881L226.037 32.1361C225.982 32.1684 225.949 32.2275 225.949 32.2916V34.9036C225.949 35.0423 226.097 35.1282 226.215 35.0591Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M224.052 36.3053L224.819 35.8574C224.873 35.8256 224.908 35.7665 224.908 35.7018V33.0899C224.908 32.9511 224.76 32.8652 224.642 32.9343L223.875 33.3829C223.821 33.4146 223.786 33.4737 223.786 33.5378V36.1498C223.786 36.2885 223.934 36.3744 224.052 36.3053Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M221.89 37.5515L222.657 37.1035C222.711 37.0718 222.746 37.0127 222.746 36.948V34.336C222.746 34.1979 222.598 34.112 222.48 34.1805L221.713 34.6291C221.658 34.6608 221.624 34.7199 221.624 34.784V37.3966C221.624 37.5347 221.772 37.6206 221.89 37.5515Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M219.728 38.7983L220.495 38.3497C220.549 38.3186 220.583 38.2589 220.583 38.1948V35.5822C220.583 35.4441 220.436 35.3582 220.318 35.4273L219.551 35.8753C219.496 35.9076 219.462 35.9661 219.462 36.0308V38.6428C219.462 38.7809 219.61 38.8668 219.728 38.7983Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M217.566 40.0446L218.333 39.596C218.388 39.5649 218.421 39.5051 218.421 39.4411V36.8285C218.421 36.6903 218.273 36.6045 218.155 36.6735L217.389 37.1215C217.334 37.1539 217.3 37.2124 217.3 37.2771V39.889C217.3 40.0272 217.448 40.1136 217.566 40.0446Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M215.404 41.2908L216.171 40.8428C216.225 40.8111 216.259 40.7513 216.259 40.6873V38.0753C216.259 37.9365 216.111 37.8507 215.993 37.9197L215.226 38.3677C215.172 38.4001 215.138 38.4592 215.138 38.5233V41.1352C215.138 41.274 215.286 41.3598 215.404 41.2908Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M213.242 42.656L214.008 42.2081C214.063 42.1763 214.097 42.1172 214.097 42.0525V39.4406C214.097 39.3024 213.949 39.2159 213.831 39.285L213.064 39.7336C213.009 39.7653 212.975 39.8245 212.975 39.8885V42.5011C212.975 42.6392 213.124 42.7251 213.242 42.656Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M211.08 43.8433L211.846 43.3947C211.901 43.363 211.935 43.3039 211.935 43.2392V40.6272C211.935 40.4891 211.787 40.4032 211.668 40.4717L210.902 40.9203C210.847 40.9526 210.813 41.0111 210.813 41.0758V43.6878C210.813 43.8259 210.962 43.9118 211.08 43.8433Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M208.917 45.1491L209.684 44.7005C209.738 44.6694 209.773 44.6097 209.773 44.5456V41.933C209.773 41.7949 209.625 41.709 209.507 41.7781L208.74 42.2261C208.686 42.2584 208.651 42.3169 208.651 42.3816V44.9936C208.651 45.1317 208.799 45.2176 208.917 45.1491Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M206.755 46.3953L207.522 45.9473C207.576 45.9156 207.611 45.8559 207.611 45.7918V43.1798C207.611 43.0411 207.463 42.9552 207.345 43.0243L206.578 43.4722C206.523 43.5046 206.489 43.5631 206.489 43.6278V46.2397C206.489 46.3785 206.637 46.4644 206.755 46.3953Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M180.68 26.8497L180.695 29.9103C180.593 30.4646 180.818 31.0713 181.368 31.3936L204.966 45.1851C205.397 45.437 205.928 45.437 206.359 45.1851L229.957 31.3936C230.507 31.0719 230.731 30.4646 230.629 29.9103L230.645 26.8497" fill="#8B81E6"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M204.966 41.7003L181.368 27.9082C180.439 27.3656 180.439 26.0092 181.368 25.4673L204.966 11.6752C205.397 11.4238 205.927 11.4238 206.358 11.6752L229.957 25.4673C230.885 26.0099 230.885 27.3656 229.957 27.9082L206.358 41.7003C205.927 41.9517 205.397 41.9517 204.966 41.7003Z" fill="#A59EF7"/> +</g> +<g opacity="0.327785"> +<rect width="34.9717" height="24.8959" fill="black" fill-opacity="0" transform="translate(167.802 36.5651)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M169.36 52.459L168.834 52.1463C168.797 52.1237 168.774 52.0822 168.774 52.0375V50.215C168.774 50.1181 168.875 50.0584 168.956 50.1062L169.482 50.4188C169.52 50.4415 169.543 50.4824 169.543 50.5277V52.3501C169.543 52.4464 169.442 52.5068 169.36 52.459Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M170.842 53.3282L170.316 53.0156C170.278 52.9936 170.255 52.952 170.255 52.9074V51.0849C170.255 50.988 170.357 50.9283 170.437 50.9761L170.963 51.2887C171.001 51.3108 171.024 51.3523 171.024 51.3976V53.22C171.024 53.3163 170.923 53.3767 170.842 53.3282Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M172.323 54.1982L171.797 53.8855C171.76 53.8635 171.737 53.822 171.737 53.7773V51.9542C171.737 51.8573 171.838 51.7976 171.919 51.846L172.445 52.1586C172.483 52.1807 172.505 52.2222 172.505 52.2669V54.09C172.505 54.1862 172.405 54.2466 172.323 54.1982Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M173.805 55.0681L173.279 54.7554C173.241 54.7334 173.218 54.6912 173.218 54.6472V52.8241C173.218 52.7272 173.319 52.6675 173.4 52.7159L173.926 53.0286C173.964 53.0506 173.987 53.0915 173.987 53.1368V54.9599C173.987 55.0555 173.885 55.1159 173.805 55.0681Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M175.286 55.938L174.76 55.6254C174.723 55.6027 174.699 55.5612 174.699 55.5165V53.6941C174.699 53.5972 174.801 53.5374 174.882 53.5852L175.408 53.8979C175.446 53.9205 175.469 53.9614 175.469 54.0067V55.8292C175.469 55.9254 175.367 55.9858 175.286 55.938Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M176.768 56.8079L176.241 56.4953C176.204 56.4726 176.181 56.4311 176.181 56.3864V54.564C176.181 54.4671 176.282 54.4073 176.363 54.4551L176.889 54.7678C176.926 54.7904 176.95 54.8313 176.95 54.8766V56.6991C176.95 56.7953 176.848 56.8557 176.768 56.8079Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M178.249 57.6772L177.723 57.3645C177.685 57.3425 177.662 57.301 177.662 57.2563V55.4332C177.662 55.337 177.764 55.2772 177.844 55.325L178.37 55.6377C178.408 55.6597 178.432 55.7012 178.432 55.7459V57.569C178.432 57.6653 178.33 57.7256 178.249 57.6772Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M179.73 58.6301L179.204 58.3174C179.166 58.2954 179.144 58.2539 179.144 58.2092V56.3868C179.144 56.2899 179.245 56.2301 179.326 56.2779L179.852 56.5906C179.889 56.6126 179.912 56.6541 179.912 56.6994V58.5219C179.912 58.6181 179.811 58.6785 179.73 58.6301Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M181.212 59.4588L180.686 59.1461C180.648 59.1235 180.625 59.082 180.625 59.0373V57.2148C180.625 57.1179 180.726 57.0582 180.807 57.106L181.333 57.4187C181.371 57.4413 181.394 57.4822 181.394 57.5275V59.35C181.394 59.4462 181.293 59.5066 181.212 59.4588Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M182.693 60.3699L182.167 60.0573C182.129 60.0352 182.107 59.9931 182.107 59.9491V58.1259C182.107 58.0291 182.207 57.9693 182.289 58.0177L182.815 58.3304C182.852 58.3524 182.875 58.3933 182.875 58.4386V60.2617C182.875 60.3573 182.774 60.4177 182.693 60.3699Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M184.174 61.2398L183.648 60.9272C183.611 60.9045 183.588 60.863 183.588 60.8183V58.9959C183.588 58.899 183.689 58.8392 183.77 58.887L184.296 59.1997C184.334 59.2223 184.357 59.2632 184.357 59.3085V61.131C184.357 61.2272 184.256 61.2876 184.174 61.2398Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M201.181 52.4761L201.718 52.1572C201.757 52.1339 201.78 52.0924 201.78 52.0459V50.1844C201.78 50.0862 201.677 50.0252 201.594 50.0743L201.057 50.3926C201.018 50.4165 200.995 50.458 200.995 50.504V52.3654C200.995 52.4636 201.099 52.5252 201.181 52.4761Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M199.668 53.3645L200.205 53.0449C200.244 53.0223 200.268 52.9807 200.268 52.9342V51.0727C200.268 50.9746 200.164 50.9129 200.081 50.9626L199.544 51.2809C199.506 51.3042 199.482 51.3464 199.482 51.3923V53.2538C199.482 53.3519 199.586 53.4136 199.668 53.3645Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M198.155 54.2528L198.693 53.9332C198.731 53.9106 198.755 53.8684 198.755 53.8225V51.9611C198.755 51.8623 198.652 51.8013 198.569 51.8503L198.031 52.1693C197.993 52.1926 197.969 52.2347 197.969 52.28V54.1421C197.969 54.2402 198.073 54.3019 198.155 54.2528Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M196.643 55.1412L197.18 54.8217C197.218 54.799 197.242 54.7569 197.242 54.7109V52.8488C197.242 52.7507 197.139 52.6897 197.056 52.7387L196.519 53.0577C196.48 53.081 196.456 53.1231 196.456 53.1684V55.0305C196.456 55.1286 196.56 55.1903 196.643 55.1412Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M195.13 56.0296L195.667 55.71C195.705 55.6873 195.729 55.6452 195.729 55.5993V53.7372C195.729 53.639 195.626 53.578 195.543 53.6271L195.006 53.946C194.967 53.9693 194.943 54.0114 194.943 54.0567V55.9182C194.943 56.017 195.047 56.0786 195.13 56.0296Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M193.617 56.9179L194.154 56.5983C194.193 56.5757 194.216 56.5335 194.216 56.487V54.6255C194.216 54.5274 194.113 54.4663 194.03 54.5154L193.493 54.8344C193.454 54.8576 193.431 54.8998 193.431 54.9451V56.8066C193.431 56.9047 193.534 56.967 193.617 56.9179Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M192.104 57.8056L192.641 57.4867C192.68 57.4634 192.704 57.4219 192.704 57.3753V55.5138C192.704 55.4157 192.6 55.3547 192.517 55.4037L191.98 55.7221C191.942 55.746 191.918 55.7875 191.918 55.8334V57.6949C191.918 57.793 192.022 57.8547 192.104 57.8056Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M190.591 58.7787L191.128 58.4598C191.167 58.4365 191.191 58.395 191.191 58.3485V56.487C191.191 56.3888 191.087 56.3272 191.004 56.3769L190.467 56.6952C190.429 56.7191 190.405 56.7606 190.405 56.8066V58.668C190.405 58.7662 190.509 58.8278 190.591 58.7787Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M189.078 59.6247L189.616 59.3051C189.654 59.2825 189.678 59.2403 189.678 59.1944V57.3329C189.678 57.2341 189.575 57.1731 189.492 57.2222L188.954 57.5411C188.916 57.5644 188.892 57.6066 188.892 57.6519V59.514C188.892 59.6121 188.996 59.6737 189.078 59.6247Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M187.566 60.5554L188.103 60.2358C188.141 60.2132 188.165 60.171 188.165 60.1251V58.2636C188.165 58.1649 188.062 58.1039 187.979 58.1529L187.442 58.4719C187.403 58.4952 187.379 58.5373 187.379 58.5826V60.4447C187.379 60.5428 187.483 60.6045 187.566 60.5554Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M186.053 61.4438L186.59 61.1242C186.628 61.1015 186.652 61.0594 186.652 61.0135V59.1514C186.652 59.0532 186.549 58.9922 186.466 59.0413L185.929 59.3602C185.89 59.3835 185.866 59.4256 185.866 59.4709V61.333C185.866 61.4312 185.97 61.4928 186.053 61.4438Z" fill="#8C87C4"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M167.808 47.5141L167.819 49.6951C167.747 50.0902 167.904 50.5224 168.289 50.7514L184.801 60.5809C185.102 60.7608 185.474 60.7608 185.775 60.5809L202.286 50.752C202.671 50.523 202.828 50.0902 202.757 49.6951L202.768 47.5141" fill="#8B81E6"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M184.801 58.0974L168.289 48.2686C167.64 47.8817 167.64 46.9154 168.289 46.5285L184.801 36.6996C185.102 36.5203 185.473 36.5203 185.775 36.6996L202.287 46.5285C202.936 46.9154 202.936 47.8823 202.287 48.2686L185.775 58.0974C185.474 58.2767 185.102 58.2767 184.801 58.0974Z" fill="#A59EF7"/> +</g> +<rect width="29.9899" height="49.737" fill="black" fill-opacity="0" transform="translate(189.659 18.6826)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M189.659 43.6672L204.642 52.5638V18.6826L189.659 43.6672Z" fill="#6659FF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M204.672 18.6826V52.5638L219.649 43.6672L204.672 18.6826Z" fill="#5135E6"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M189.659 46.6247L204.861 68.4196L204.642 55.5213L189.659 46.6247Z" fill="#6659FF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M204.672 54.7454L204.917 67.4584L219.482 45.55L204.672 54.7454Z" fill="#4259DB"/> +<rect width="37.5326" height="24.718" fill="black" fill-opacity="0" transform="translate(318.852 99.4725)"/> +<rect width="37.5326" height="24.2005" fill="black" fill-opacity="0" transform="translate(318.852 99.4725)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M350.888 120.595C343.56 124.699 331.678 124.699 324.349 120.595C317.02 116.492 317.02 109.838 324.349 105.734C331.677 101.631 343.56 101.631 350.888 105.735C358.217 109.838 358.217 116.492 350.888 120.595Z" fill="#7F95EF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M318.852 112.846H356.385V109.662H318.852V112.846Z" fill="#838DB7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M350.888 117.411C343.56 121.515 331.678 121.515 324.349 117.411C317.02 113.307 317.02 106.654 324.349 102.55C331.677 98.4465 343.56 98.4465 350.888 102.55C358.217 106.654 358.217 113.307 350.888 117.411Z" fill="#93A8FF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M326.211 115.967C319.911 112.485 319.911 106.839 326.211 103.358C332.511 99.8757 342.726 99.8757 349.026 103.358C355.326 106.84 355.326 112.485 349.026 115.967C342.726 119.449 332.511 119.449 326.211 115.967Z" fill="#9ABFFF"/> +<g opacity="0.370867"> +<rect width="19.296" height="11.091" fill="black" fill-opacity="0" transform="translate(327.431 104.017)"/> +<g opacity="0.653363"> +<rect width="14.9457" height="5.18221" fill="black" fill-opacity="0" transform="translate(327.431 109.926)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M342.161 110.157C342.497 110.398 342.355 110.571 342.298 110.734C341.315 113.539 336.078 115.549 331.129 115.025C328.909 114.79 327.621 114.016 327.452 112.816C327.266 111.493 328.324 110.596 330.572 110.173C331.906 109.922 333.285 109.901 334.667 109.943C337.204 110.021 339.711 110.353 342.161 110.157Z" fill="#4562DF"/> +</g> +<g opacity="0.653363"> +<rect width="14.909" height="5.19137" fill="black" fill-opacity="0" transform="translate(331.818 104.017)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M331.818 108.942C332.063 106.358 336.216 104.162 340.869 104.029C341.632 104.007 342.397 104.01 343.152 104.108C345.409 104.4 346.637 105.208 346.723 106.465C346.805 107.672 345.734 108.521 343.592 108.934C342.419 109.16 341.201 109.235 339.972 109.201C337.284 109.128 334.63 108.791 331.818 108.942Z" fill="#4562DF"/> +</g> +</g> +<rect width="37.5326" height="24.718" fill="black" fill-opacity="0" transform="translate(318.852 95.1737)"/> +<rect width="37.5326" height="24.2005" fill="black" fill-opacity="0" transform="translate(318.852 95.1737)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M350.888 116.296C343.56 120.4 331.678 120.4 324.349 116.296C317.02 112.193 317.02 105.539 324.349 101.436C331.677 97.332 343.56 97.332 350.888 101.436C358.217 105.539 358.217 112.193 350.888 116.296Z" fill="#7F95EF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M318.852 108.548H356.385V105.363H318.852V108.548Z" fill="#838DB7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M350.888 113.112C343.56 117.216 331.678 117.216 324.349 113.112C317.02 109.008 317.02 102.355 324.349 98.2514C331.677 94.1478 343.56 94.1478 350.888 98.2515C358.217 102.355 358.217 109.009 350.888 113.112Z" fill="#93A8FF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M326.211 111.668C319.911 108.186 319.911 102.541 326.211 99.0588C332.511 95.5769 342.726 95.5769 349.026 99.0588C355.326 102.541 355.326 108.186 349.026 111.668C342.726 115.15 332.511 115.15 326.211 111.668Z" fill="#9ABFFF"/> +<g opacity="0.370867"> +<rect width="19.296" height="11.091" fill="black" fill-opacity="0" transform="translate(327.431 99.7187)"/> +<g opacity="0.653363"> +<rect width="14.9457" height="5.18221" fill="black" fill-opacity="0" transform="translate(327.431 105.627)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M342.161 105.859C342.497 106.1 342.355 106.272 342.298 106.435C341.315 109.24 336.078 111.251 331.129 110.726C328.909 110.491 327.621 109.717 327.452 108.517C327.266 107.194 328.324 106.297 330.572 105.874C331.906 105.624 333.285 105.603 334.667 105.644C337.204 105.722 339.711 106.054 342.161 105.859Z" fill="#4562DF"/> +</g> +<g opacity="0.653363"> +<rect width="14.909" height="5.19137" fill="black" fill-opacity="0" transform="translate(331.818 99.7187)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M331.818 104.643C332.063 102.059 336.216 99.8633 340.869 99.7298C341.632 99.7079 342.397 99.7109 343.152 99.8089C345.409 100.102 346.637 100.909 346.723 102.166C346.805 103.373 345.734 104.222 343.592 104.635C342.419 104.861 341.201 104.936 339.972 104.903C337.284 104.829 334.63 104.492 331.818 104.643Z" fill="#4562DF"/> +</g> +</g> +<rect width="37.5326" height="24.718" fill="black" fill-opacity="0" transform="translate(47.5456 103.771)"/> +<rect width="37.5326" height="24.2005" fill="black" fill-opacity="0" transform="translate(47.5456 103.771)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M79.5817 124.894C72.253 128.998 60.3709 128.998 53.0422 124.894C45.7135 120.79 45.7134 114.137 53.0421 110.033C60.3708 105.93 72.2529 105.93 79.5816 110.033C86.9103 114.137 86.9104 120.79 79.5817 124.894Z" fill="#61C9A7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M47.5456 117.145H85.0782V113.961H47.5456V117.145Z" fill="#61C9A7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M53.0422 121.71C45.7135 117.606 45.7134 110.953 53.0421 106.849C60.3708 102.745 72.2529 102.745 79.5816 106.849C86.9103 110.953 86.9104 117.606 79.5817 121.71C72.253 125.813 60.3709 125.813 53.0422 121.71Z" fill="#86F7D1"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M54.9046 120.265C48.6045 116.784 48.6044 111.138 54.9046 107.656C61.2046 104.174 71.4191 104.174 77.7192 107.656C84.0193 111.138 84.0194 116.784 77.7193 120.266C71.4192 123.747 61.2047 123.747 54.9046 120.265Z" fill="#95FFDA"/> +<rect width="26.809" height="10.7469" fill="black" fill-opacity="0" transform="translate(52.9074 109.145)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M78.1519 112.724C78.1579 112.71 78.1629 112.697 78.1681 112.684C78.1741 112.687 78.1793 112.69 78.1852 112.692L78.2281 112.712L78.1519 112.724ZM75.2505 115.293C74.8038 115.693 74.3155 116.07 73.7899 116.421C73.5585 116.576 73.3192 116.726 73.0736 116.871C71.4102 116.816 70.5534 116.576 70.1138 116.331C69.5898 116.039 69.6552 115.742 69.6552 115.742C69.6552 115.702 69.6552 115.662 69.6711 115.622C69.6711 115.622 69.6791 115.586 69.7054 115.531C69.7421 115.454 69.8139 115.34 69.9495 115.225C70.1816 115.027 70.6037 114.83 71.3568 114.828H71.3703C71.5698 114.824 71.7692 114.842 71.9367 114.886C72.7345 115.083 72.216 115.45 72.216 115.45C72.2758 115.446 72.3364 115.44 72.3978 115.433C73.3567 115.315 74.4376 114.814 74.2502 113.976C74.2079 113.785 74.0682 113.615 73.8744 113.464C73.3862 113.083 72.5533 112.83 72.0795 112.708C71.8632 112.653 71.7213 112.625 71.7213 112.625C71.7452 112.557 71.7532 112.504 71.7532 112.464C71.7532 112.456 71.7532 112.449 71.7515 112.442C71.7476 112.377 71.7213 112.352 71.7213 112.352C66.7753 110.986 62.9222 111.281 62.9222 111.281L63.8795 111.718C63.8755 111.718 63.8723 111.718 63.8684 111.718C63.7758 111.715 63.6761 111.715 63.5844 111.715C62.2306 111.737 60.9685 111.926 59.8908 112.241C57.7728 112.857 56.3649 113.954 56.3649 115.207C56.3649 115.265 56.3687 115.322 56.3752 115.376C56.3464 115.351 56.3186 115.326 56.2898 115.3C56.1422 115.169 56.0042 115.039 55.875 114.911C54.8969 113.945 54.4 113.097 54.1861 112.662C59.0388 110.884 64.9445 109.989 65.7701 109.872C66.0015 109.905 66.6285 109.999 67.5188 110.155C68.5295 110.333 69.8785 110.592 71.3719 110.935C73.2681 111.372 75.3956 111.944 77.3542 112.66C77.11 113.151 76.5037 114.17 75.2505 115.293ZM67.8363 112.25C69.1517 112.246 70.3396 112.388 71.2092 112.628C71.1812 112.624 70.7249 112.558 70.2615 112.53C70.0221 112.643 69.8147 112.691 69.7509 112.705C69.7429 112.709 69.7349 112.712 69.7349 112.712C68.3389 112.578 67.8363 112.25 67.8363 112.25ZM78.3792 112.23C73.4834 110.339 67.3313 109.373 66.1507 109.199L65.7677 109.145L65.3928 109.198C64.2081 109.373 58.0481 110.34 53.1515 112.233L52.9074 112.327L52.9672 112.482C53.0685 112.733 53.6549 114.058 55.291 115.528C56.3425 116.47 57.6284 117.296 59.1131 117.985C60.9223 118.822 63.0339 119.442 65.3929 119.83L65.7758 119.892L66.0246 119.847L66.1571 119.826C68.5016 119.441 70.6133 118.82 72.4345 117.982C73.9111 117.301 75.197 116.474 76.2572 115.524C77.903 114.049 78.5212 112.682 78.5842 112.468H78.585L78.644 112.316L78.3792 112.23Z" fill="#6CF0D1"/> +<path opacity="0.175894" fill-rule="evenodd" clip-rule="evenodd" d="M78.9765 112.492L78.644 112.548C78.6703 112.485 78.6928 112.425 78.7153 112.369C78.7416 112.382 78.7636 112.392 78.7899 112.405L78.9765 112.492Z" fill="#000CA5"/> +<path opacity="0.175894" fill-rule="evenodd" clip-rule="evenodd" d="M78.7893 112.405C78.7631 112.392 78.7411 112.382 78.7148 112.369C78.6923 112.425 78.6698 112.485 78.644 112.548L78.9759 112.492L78.7893 112.405Z" fill="#000CA5"/> +<rect width="37.5326" height="24.718" fill="black" fill-opacity="0" transform="translate(47.5456 99.4725)"/> +<rect width="37.5326" height="24.2005" fill="black" fill-opacity="0" transform="translate(47.5456 99.4725)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M79.5817 120.595C72.253 124.699 60.3709 124.699 53.0422 120.595C45.7135 116.492 45.7134 109.838 53.0421 105.734C60.3708 101.631 72.2529 101.631 79.5816 105.735C86.9103 109.838 86.9104 116.492 79.5817 120.595Z" fill="#61C9A7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M47.5456 112.846H85.0782V109.662H47.5456V112.846Z" fill="#61C9A7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M53.0422 117.411C45.7135 113.307 45.7134 106.654 53.0421 102.55C60.3708 98.4465 72.2529 98.4465 79.5816 102.55C86.9103 106.654 86.9104 113.307 79.5817 117.411C72.253 121.515 60.3709 121.515 53.0422 117.411Z" fill="#86F7D1"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M54.9046 115.967C48.6045 112.485 48.6044 106.839 54.9046 103.358C61.2046 99.8757 71.4191 99.8757 77.7192 103.358C84.0193 106.84 84.0194 112.485 77.7193 115.967C71.4192 119.449 61.2047 119.449 54.9046 115.967Z" fill="#95FFDA"/> +<rect width="26.809" height="10.7469" fill="black" fill-opacity="0" transform="translate(52.9074 104.846)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M78.1519 108.426C78.1579 108.412 78.1629 108.398 78.1681 108.386C78.1741 108.388 78.1793 108.391 78.1852 108.394L78.2281 108.413L78.1519 108.426ZM75.2505 110.994C74.8038 111.395 74.3155 111.771 73.7899 112.122C73.5585 112.277 73.3192 112.427 73.0736 112.572C71.4102 112.517 70.5534 112.277 70.1138 112.032C69.5898 111.741 69.6552 111.443 69.6552 111.443C69.6552 111.403 69.6552 111.363 69.6711 111.323C69.6711 111.323 69.6791 111.288 69.7054 111.232C69.7421 111.155 69.8139 111.041 69.9495 110.926C70.1816 110.729 70.6037 110.532 71.3568 110.529H71.3703C71.5698 110.525 71.7692 110.544 71.9367 110.587C72.7345 110.784 72.216 111.152 72.216 111.152C72.2758 111.147 72.3364 111.142 72.3978 111.134C73.3567 111.016 74.4376 110.516 74.2502 109.677C74.2079 109.487 74.0682 109.316 73.8744 109.165C73.3862 108.784 72.5533 108.531 72.0795 108.41C71.8632 108.354 71.7213 108.326 71.7213 108.326C71.7452 108.258 71.7532 108.205 71.7532 108.165C71.7532 108.157 71.7532 108.15 71.7515 108.143C71.7476 108.078 71.7213 108.053 71.7213 108.053C66.7753 106.688 62.9222 106.983 62.9222 106.983L63.8795 107.42C63.8755 107.42 63.8723 107.419 63.8684 107.419C63.7758 107.416 63.6761 107.416 63.5844 107.416C62.2306 107.438 60.9685 107.627 59.8908 107.942C57.7728 108.558 56.3649 109.656 56.3649 110.908C56.3649 110.966 56.3687 111.023 56.3752 111.077C56.3464 111.052 56.3186 111.027 56.2898 111.002C56.1422 110.87 56.0042 110.74 55.875 110.612C54.8969 109.646 54.4 108.798 54.1861 108.363C59.0388 106.586 64.9445 105.691 65.7701 105.573C66.0015 105.606 66.6285 105.7 67.5188 105.856C68.5295 106.034 69.8785 106.293 71.3719 106.637C73.2681 107.073 75.3956 107.645 77.3542 108.361C77.11 108.852 76.5037 109.871 75.2505 110.994ZM67.8363 107.951C69.1517 107.948 70.3396 108.09 71.2092 108.329C71.1812 108.325 70.7249 108.26 70.2615 108.232C70.0221 108.344 69.8147 108.392 69.7509 108.406C69.7429 108.41 69.7349 108.414 69.7349 108.414C68.3389 108.279 67.8363 107.951 67.8363 107.951ZM78.3792 107.931C73.4834 106.04 67.3313 105.074 66.1507 104.9L65.7677 104.846L65.3928 104.899C64.2081 105.074 58.0481 106.041 53.1515 107.935L52.9074 108.029L52.9672 108.183C53.0685 108.434 53.6549 109.759 55.291 111.229C56.3425 112.171 57.6284 112.997 59.1131 113.686C60.9223 114.523 63.0339 115.144 65.3929 115.531L65.7758 115.593L66.0246 115.548L66.1571 115.527C68.5016 115.142 70.6133 114.522 72.4345 113.683C73.9111 113.002 75.197 112.175 76.2572 111.225C77.903 109.75 78.5212 108.383 78.5842 108.17H78.585L78.644 108.017L78.3792 107.931Z" fill="#6CF0D1"/> +<path opacity="0.175894" fill-rule="evenodd" clip-rule="evenodd" d="M78.9765 108.193L78.644 108.249C78.6703 108.186 78.6928 108.126 78.7153 108.07C78.7416 108.083 78.7636 108.093 78.7899 108.107L78.9765 108.193Z" fill="#000CA5"/> +<path opacity="0.175894" fill-rule="evenodd" clip-rule="evenodd" d="M78.7893 108.107C78.7631 108.094 78.7411 108.083 78.7148 108.07C78.6923 108.126 78.6698 108.186 78.644 108.249L78.9759 108.193L78.7893 108.107Z" fill="#000CA5"/> +<rect width="37.5326" height="24.718" fill="black" fill-opacity="0" transform="translate(47.5456 95.1737)"/> +<rect width="37.5326" height="24.2005" fill="black" fill-opacity="0" transform="translate(47.5456 95.1737)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M79.5817 116.296C72.253 120.4 60.3709 120.4 53.0422 116.296C45.7135 112.193 45.7134 105.539 53.0421 101.436C60.3708 97.332 72.2529 97.332 79.5816 101.436C86.9103 105.539 86.9104 112.193 79.5817 116.296Z" fill="#61C9A7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M47.5456 108.548H85.0782V105.363H47.5456V108.548Z" fill="#61C9A7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M53.0422 113.112C45.7135 109.008 45.7134 102.355 53.0421 98.2514C60.3708 94.1478 72.2529 94.1478 79.5816 98.2515C86.9103 102.355 86.9104 109.009 79.5817 113.112C72.253 117.216 60.3709 117.216 53.0422 113.112Z" fill="#86F7D1"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M54.9046 111.668C48.6045 108.186 48.6044 102.541 54.9046 99.0588C61.2046 95.5769 71.4191 95.5769 77.7192 99.0588C84.0193 102.541 84.0194 108.186 77.7193 111.668C71.4192 115.15 61.2047 115.15 54.9046 111.668Z" fill="#95FFDA"/> +<rect width="26.809" height="10.7469" fill="black" fill-opacity="0" transform="translate(52.9074 100.547)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M78.1519 104.127C78.1579 104.113 78.1629 104.099 78.1681 104.087C78.1741 104.09 78.1793 104.092 78.1852 104.095L78.2281 104.114L78.1519 104.127ZM75.2505 106.696C74.8038 107.096 74.3155 107.472 73.7899 107.824C73.5585 107.978 73.3192 108.128 73.0736 108.273C71.4102 108.218 70.5534 107.978 70.1138 107.733C69.5898 107.442 69.6552 107.144 69.6552 107.144C69.6552 107.104 69.6552 107.064 69.6711 107.024C69.6711 107.024 69.6791 106.989 69.7054 106.933C69.7421 106.857 69.8139 106.742 69.9495 106.627C70.1816 106.43 70.6037 106.233 71.3568 106.23H71.3703C71.5698 106.227 71.7692 106.245 71.9367 106.289C72.7345 106.485 72.216 106.853 72.216 106.853C72.2758 106.849 72.3364 106.843 72.3978 106.835C73.3567 106.717 74.4376 106.217 74.2502 105.378C74.2079 105.188 74.0682 105.017 73.8744 104.867C73.3862 104.485 72.5533 104.232 72.0795 104.111C71.8632 104.055 71.7213 104.027 71.7213 104.027C71.7452 103.959 71.7532 103.907 71.7532 103.866C71.7532 103.858 71.7532 103.851 71.7515 103.844C71.7476 103.779 71.7213 103.754 71.7213 103.754C66.7753 102.389 62.9222 102.684 62.9222 102.684L63.8795 103.121C63.8755 103.121 63.8723 103.12 63.8684 103.12C63.7758 103.117 63.6761 103.117 63.5844 103.117C62.2306 103.139 60.9685 103.329 59.8908 103.643C57.7728 104.26 56.3649 105.357 56.3649 106.609C56.3649 106.668 56.3687 106.724 56.3752 106.779C56.3464 106.754 56.3186 106.728 56.2898 106.703C56.1422 106.572 56.0042 106.441 55.875 106.313C54.8969 105.348 54.4 104.5 54.1861 104.065C59.0388 102.287 64.9445 101.392 65.7701 101.275C66.0015 101.307 66.6285 101.401 67.5188 101.558C68.5295 101.735 69.8785 101.994 71.3719 102.338C73.2681 102.774 75.3956 103.347 77.3542 104.062C77.11 104.553 76.5037 105.573 75.2505 106.696ZM67.8363 103.652C69.1517 103.649 70.3396 103.791 71.2092 104.031C71.1812 104.027 70.7249 103.961 70.2615 103.933C70.0221 104.046 69.8147 104.093 69.7509 104.108C69.7429 104.111 69.7349 104.115 69.7349 104.115C68.3389 103.98 67.8363 103.652 67.8363 103.652ZM78.3792 103.632C73.4834 101.741 67.3313 100.775 66.1507 100.601L65.7677 100.547L65.3928 100.601C64.2081 100.775 58.0481 101.742 53.1515 103.636L52.9074 103.73L52.9672 103.884C53.0685 104.135 53.6549 105.46 55.291 106.93C56.3425 107.872 57.6284 108.699 59.1131 109.388C60.9223 110.224 63.0339 110.845 65.3929 111.232L65.7758 111.294L66.0246 111.25L66.1571 111.229C68.5016 110.843 70.6133 110.223 72.4345 109.384C73.9111 108.703 75.197 107.876 76.2572 106.927C77.903 105.451 78.5212 104.084 78.5842 103.871H78.585L78.644 103.718L78.3792 103.632Z" fill="#6CF0D1"/> +<path opacity="0.175894" fill-rule="evenodd" clip-rule="evenodd" d="M78.9765 103.894L78.644 103.95C78.6703 103.887 78.6928 103.827 78.7153 103.771C78.7416 103.784 78.7636 103.794 78.7899 103.808L78.9765 103.894Z" fill="#000CA5"/> +<path opacity="0.175894" fill-rule="evenodd" clip-rule="evenodd" d="M78.7893 103.808C78.7631 103.795 78.7411 103.784 78.7148 103.771C78.6923 103.827 78.6698 103.887 78.644 103.951L78.9759 103.894L78.7893 103.808Z" fill="#000CA5"/> +<rect width="37.5326" height="24.718" fill="black" fill-opacity="0" transform="translate(47.5456 90.8749)"/> +<rect width="37.5326" height="24.2005" fill="black" fill-opacity="0" transform="translate(47.5456 90.8749)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M79.5817 111.998C72.253 116.101 60.3709 116.101 53.0422 111.998C45.7135 107.894 45.7134 101.241 53.0421 97.1369C60.3708 93.0333 72.2529 93.0333 79.5816 97.137C86.9103 101.241 86.9104 107.894 79.5817 111.998Z" fill="#61C9A7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M47.5456 104.249H85.0782V101.065H47.5456V104.249Z" fill="#61C9A7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M53.0422 108.813C45.7135 104.71 45.7134 98.0563 53.0421 93.9526C60.3708 89.849 72.2529 89.849 79.5816 93.9527C86.9103 98.0564 86.9104 104.71 79.5817 108.813C72.253 112.917 60.3709 112.917 53.0422 108.813Z" fill="#86F7D1"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M54.9046 107.369C48.6045 103.887 48.6044 98.2419 54.9046 94.7601C61.2046 91.2781 71.4191 91.2781 77.7192 94.7601C84.0193 98.242 84.0194 103.887 77.7193 107.369C71.4192 110.851 61.2047 110.851 54.9046 107.369Z" fill="#95FFDA"/> +<rect width="26.809" height="10.7469" fill="black" fill-opacity="0" transform="translate(52.9074 96.2484)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M78.1519 99.828C78.1579 99.814 78.1629 99.8006 78.1681 99.788C78.1741 99.7909 78.1793 99.7933 78.1852 99.7962L78.2281 99.8156L78.1519 99.828ZM75.2505 102.397C74.8038 102.797 74.3155 103.174 73.7899 103.525C73.5585 103.68 73.3192 103.829 73.0736 103.974C71.4102 103.92 70.5534 103.679 70.1138 103.434C69.5898 103.143 69.6552 102.845 69.6552 102.845C69.6552 102.805 69.6552 102.765 69.6711 102.725C69.6711 102.725 69.6791 102.69 69.7054 102.634C69.7421 102.558 69.8139 102.443 69.9495 102.328C70.1816 102.131 70.6037 101.934 71.3568 101.932H71.3703C71.5698 101.928 71.7692 101.946 71.9367 101.99C72.7345 102.186 72.216 102.554 72.216 102.554C72.2758 102.55 72.3364 102.544 72.3978 102.536C73.3567 102.419 74.4376 101.918 74.2502 101.08C74.2079 100.889 74.0682 100.719 73.8744 100.568C73.3862 100.187 72.5533 99.9333 72.0795 99.812C71.8632 99.7567 71.7213 99.7287 71.7213 99.7287C71.7452 99.6605 71.7532 99.6078 71.7532 99.5673C71.7532 99.5597 71.7532 99.5524 71.7515 99.5455C71.7476 99.4806 71.7213 99.4555 71.7213 99.4555C66.7753 98.0901 62.9222 98.3851 62.9222 98.3851L63.8795 98.822C63.8755 98.822 63.8723 98.8216 63.8684 98.8216C63.7758 98.8183 63.6761 98.8183 63.5844 98.8183C62.2306 98.8405 60.9685 99.0299 59.8908 99.3442C57.7728 99.9609 56.3649 101.058 56.3649 102.31C56.3649 102.369 56.3687 102.425 56.3752 102.48C56.3464 102.455 56.3186 102.43 56.2898 102.404C56.1422 102.273 56.0042 102.142 55.875 102.015C54.8969 101.049 54.4 100.201 54.1861 99.7658C59.0388 97.9881 64.9445 97.0932 65.7701 96.9759C66.0015 97.0086 66.6285 97.1023 67.5188 97.2588C68.5295 97.4365 69.8785 97.6953 71.3719 98.0391C73.2681 98.4754 75.3956 99.0478 77.3542 99.7635C77.11 100.254 76.5037 101.274 75.2505 102.397ZM67.8363 99.3536C69.1517 99.35 70.3396 99.4919 71.2092 99.7319C71.1812 99.7279 70.7249 99.662 70.2615 99.634C70.0221 99.7469 69.8147 99.7942 69.7509 99.8087C69.7429 99.8125 69.7349 99.8161 69.7349 99.8161C68.3389 99.6813 67.8363 99.3536 67.8363 99.3536ZM78.3792 99.3332C73.4834 97.4423 67.3313 96.4767 66.1507 96.3026L65.7677 96.2484L65.3928 96.3019C64.2081 96.4767 58.0481 97.4434 53.1515 99.3371L52.9074 99.4312L52.9672 99.5855C53.0685 99.8364 53.6549 101.161 55.291 102.631C56.3425 103.573 57.6284 104.4 59.1131 105.089C60.9223 105.926 63.0339 106.546 65.3929 106.933L65.7758 106.995L66.0246 106.951L66.1571 106.93C68.5016 106.545 70.6133 105.924 72.4345 105.085C73.9111 104.404 75.197 103.577 76.2572 102.628C77.903 101.153 78.5212 99.7855 78.5842 99.572H78.585L78.644 99.4196L78.3792 99.3332Z" fill="#6CF0D1"/> +<path opacity="0.175894" fill-rule="evenodd" clip-rule="evenodd" d="M78.9765 99.5955L78.644 99.6514C78.6703 99.5885 78.6928 99.5284 78.7153 99.4725C78.7416 99.4854 78.7636 99.4956 78.7899 99.509L78.9765 99.5955Z" fill="#000CA5"/> +<path opacity="0.175894" fill-rule="evenodd" clip-rule="evenodd" d="M78.7893 99.509C78.7631 99.4961 78.7411 99.4854 78.7148 99.4725C78.6923 99.5284 78.6698 99.5885 78.644 99.6519L78.9759 99.5955L78.7893 99.509Z" fill="#000CA5"/> +<rect width="37.5326" height="24.718" fill="black" fill-opacity="0" transform="translate(47.5456 86.5761)"/> +<rect width="37.5326" height="24.2005" fill="black" fill-opacity="0" transform="translate(47.5456 86.5761)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M79.5817 107.699C72.253 111.803 60.3709 111.803 53.0422 107.699C45.7135 103.595 45.7134 96.9418 53.0421 92.8381C60.3708 88.7345 72.2529 88.7345 79.5816 92.8382C86.9103 96.9419 86.9104 103.595 79.5817 107.699Z" fill="#61C9A7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M47.5456 99.9501H85.0782V96.7658H47.5456V99.9501Z" fill="#61C9A7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M53.0422 104.515C45.7135 100.411 45.7134 93.7575 53.0421 89.6539C60.3708 85.5502 72.2529 85.5502 79.5816 89.6539C86.9103 93.7576 86.9104 100.411 79.5817 104.515C72.253 108.618 60.3709 108.618 53.0422 104.515Z" fill="#86F7D1"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M54.9046 103.07C48.6045 99.5884 48.6044 93.9431 54.9046 90.4613C61.2046 86.9794 71.4191 86.9794 77.7192 90.4613C84.0193 93.9432 84.0194 99.5885 77.7193 103.07C71.4192 106.552 61.2047 106.552 54.9046 103.07Z" fill="#95FFDA"/> +<rect width="26.809" height="10.7469" fill="black" fill-opacity="0" transform="translate(52.9074 91.9496)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M78.1519 95.5293C78.1579 95.5152 78.1629 95.5018 78.1681 95.4892C78.1741 95.4921 78.1793 95.4945 78.1852 95.4974L78.2281 95.5168L78.1519 95.5293ZM75.2505 98.0981C74.8038 98.4983 74.3155 98.8747 73.7899 99.2261C73.5585 99.3809 73.3192 99.5305 73.0736 99.6755C71.4102 99.6208 70.5534 99.3805 70.1138 99.1355C69.5898 98.8442 69.6552 98.5467 69.6552 98.5467C69.6552 98.5067 69.6552 98.4665 69.6711 98.4266C69.6711 98.4266 69.6791 98.3912 69.7054 98.3355C69.7421 98.259 69.8139 98.1444 69.9495 98.0297C70.1816 97.8323 70.6037 97.6353 71.3568 97.6327H71.3703C71.5698 97.6291 71.7692 97.6473 71.9367 97.6911C72.7345 97.8876 72.216 98.2554 72.216 98.2554C72.2758 98.251 72.3364 98.2452 72.3978 98.2376C73.3567 98.1199 74.4376 97.6193 74.2502 96.7808C74.2079 96.5903 74.0682 96.4199 73.8744 96.2691C73.3862 95.8879 72.5533 95.6345 72.0795 95.5132C71.8632 95.4579 71.7213 95.4299 71.7213 95.4299C71.7452 95.3618 71.7532 95.309 71.7532 95.2685C71.7532 95.2609 71.7532 95.2536 71.7515 95.2467C71.7476 95.1818 71.7213 95.1567 71.7213 95.1567C66.7753 93.7913 62.9222 94.0863 62.9222 94.0863L63.8795 94.5232C63.8755 94.5232 63.8723 94.5228 63.8684 94.5228C63.7758 94.5195 63.6761 94.5195 63.5844 94.5195C62.2306 94.5417 60.9685 94.7311 59.8908 95.0454C57.7728 95.6622 56.3649 96.7592 56.3649 98.0115C56.3649 98.07 56.3687 98.1264 56.3752 98.1811C56.3464 98.1561 56.3186 98.1309 56.2898 98.1053C56.1422 97.974 56.0042 97.8435 55.875 97.7158C54.8969 96.7501 54.4 95.9021 54.1861 95.467C59.0388 93.6893 64.9445 92.7944 65.7701 92.6771C66.0015 92.7099 66.6285 92.8035 67.5188 92.9601C68.5295 93.1377 69.8785 93.3965 71.3719 93.7403C73.2681 94.1766 75.3956 94.749 77.3542 95.4648C77.11 95.9556 76.5037 96.9751 75.2505 98.0981ZM67.8363 95.0548C69.1517 95.0512 70.3396 95.1932 71.2092 95.4331C71.1812 95.4292 70.7249 95.3632 70.2615 95.3352C70.0221 95.4481 69.8147 95.4954 69.7509 95.51C69.7429 95.5137 69.7349 95.5173 69.7349 95.5173C68.3389 95.3825 67.8363 95.0548 67.8363 95.0548ZM78.3792 95.0344C73.4834 93.1435 67.3313 92.1779 66.1507 92.0039L65.7677 91.9496L65.3928 92.0031C64.2081 92.1779 58.0481 93.1446 53.1515 95.0383L52.9074 95.1324L52.9672 95.2867C53.0685 95.5376 53.6549 96.8626 55.291 98.3326C56.3425 99.2745 57.6284 100.101 59.1131 100.79C60.9223 101.627 63.0339 102.247 65.3929 102.635L65.7758 102.697L66.0246 102.652L66.1571 102.631C68.5016 102.246 70.6133 101.625 72.4345 100.786C73.9111 100.106 75.197 99.2786 76.2572 98.329C77.903 96.8539 78.5212 95.4867 78.5842 95.2732H78.585L78.644 95.1208L78.3792 95.0344Z" fill="#6CF0D1"/> +<path opacity="0.175894" fill-rule="evenodd" clip-rule="evenodd" d="M78.9765 95.2967L78.644 95.3526C78.6703 95.2898 78.6928 95.2296 78.7153 95.1737C78.7416 95.1866 78.7636 95.1968 78.7899 95.2102L78.9765 95.2967Z" fill="#000CA5"/> +<path opacity="0.175894" fill-rule="evenodd" clip-rule="evenodd" d="M78.7893 95.2102C78.7631 95.1973 78.7411 95.1866 78.7148 95.1737C78.6923 95.2296 78.6698 95.2898 78.644 95.3532L78.9759 95.2967L78.7893 95.2102Z" fill="#000CA5"/> +<rect width="37.5326" height="24.718" fill="black" fill-opacity="0" transform="translate(318.852 90.8749)"/> +<rect width="37.5326" height="24.2005" fill="black" fill-opacity="0" transform="translate(318.852 90.8749)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M350.888 111.998C343.56 116.101 331.678 116.101 324.349 111.998C317.02 107.894 317.02 101.241 324.349 97.1369C331.677 93.0333 343.56 93.0333 350.888 97.137C358.217 101.241 358.217 107.894 350.888 111.998Z" fill="#7F95EF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M318.852 104.249H356.385V101.065H318.852V104.249Z" fill="#838DB7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M350.888 108.813C343.56 112.917 331.678 112.917 324.349 108.813C317.02 104.71 317.02 98.0563 324.349 93.9526C331.677 89.849 343.56 89.849 350.888 93.9527C358.217 98.0564 358.217 104.71 350.888 108.813Z" fill="#93A8FF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M326.211 107.369C319.911 103.887 319.911 98.2419 326.211 94.7601C332.511 91.2781 342.726 91.2781 349.026 94.7601C355.326 98.242 355.326 103.887 349.026 107.369C342.726 110.851 332.511 110.851 326.211 107.369Z" fill="#9ABFFF"/> +<g opacity="0.370867"> +<rect width="19.296" height="11.091" fill="black" fill-opacity="0" transform="translate(327.431 95.4199)"/> +<g opacity="0.653363"> +<rect width="14.9457" height="5.18222" fill="black" fill-opacity="0" transform="translate(327.431 101.329)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M342.161 101.56C342.497 101.801 342.355 101.973 342.298 102.137C341.315 104.941 336.078 106.952 331.129 106.428C328.909 106.192 327.621 105.418 327.452 104.219C327.266 102.896 328.324 101.998 330.572 101.576C331.906 101.325 333.285 101.304 334.667 101.346C337.204 101.423 339.711 101.755 342.161 101.56Z" fill="#4562DF"/> +</g> +<g opacity="0.653363"> +<rect width="14.909" height="5.19137" fill="black" fill-opacity="0" transform="translate(331.818 95.4199)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M331.818 100.345C332.063 97.7602 336.216 95.5645 340.869 95.4311C341.632 95.4091 342.397 95.4121 343.152 95.5101C345.409 95.8029 346.637 96.6105 346.723 97.8673C346.805 99.0741 345.734 99.9235 343.592 100.336C342.419 100.562 341.201 100.637 339.972 100.604C337.284 100.53 334.63 100.194 331.818 100.345Z" fill="#4562DF"/> +</g> +</g> +</svg> diff --git a/packages/website/public/images/landing/exchange_everywhere.png b/packages/website/public/images/landing/exchange_everywhere.png Binary files differnew file mode 100644 index 000000000..e63093929 --- /dev/null +++ b/packages/website/public/images/landing/exchange_everywhere.png diff --git a/packages/website/translations/english.json b/packages/website/translations/english.json index 541c29997..9ce458111 100644 --- a/packages/website/translations/english.json +++ b/packages/website/translations/english.json @@ -9,7 +9,7 @@ "FULL_LIST_LINK": "full list", "TOKENIZED_SECTION_HEADER": "the world's value is becoming tokenized", "TOKENIZED_SECTION_DESCRIPTION": - "the Ethereum blockchain is an open, borderless financial system that represents a wide variety of assets as cryptographic tokens. In the future, most digital assets and goods will be tokenized.", + "0x is the critical infrastructure layer in the emerging financial stack built on a foundation of Ethereum token standards. Developers needing exchange functionality for ERC 20 tokens, ERC 721 tokens, or any new asset type can easily integrate the 0x protocol into their application.", "CURRENCY": "currency", "TRADITIONAL_ASSETS": "traditional assets", "DIGITAL_GOODS": "digital goods", @@ -19,15 +19,16 @@ "in 0x protocol, orders are transported off-chain, massively reducing gas costs and eliminating blockchain bloat. Relayers help broadcast orders and collect a fee each time they facilitate a trade. Anyone can build a relayer.", "RELAYERS_HEADER": "relayers building on 0x", "BENEFITS_HEADER": "benefits of 0x", - "BENEFIT_ONE_TITLE": "trustless exchange", + "USE_CASES_HEADER": "use cases of 0x", + "BENEFIT_ONE_TITLE": "any asset", "BENEFIT_ONE_DESCRIPTION": - "built on Ethereum's distributed network with no centralized point of failure and no down time, each trade is settled atomically and without counterparty risk.", - "BENEFIT_TWO_TITLE": "shared liquidity", + "the 0x protocol facilitates the exchange of a growing number of Ethereum-based tokens including currencies, game items, and many more digital assets.", + "BENEFIT_TWO_TITLE": "networked liquidity", "BENEFIT_TWO_DESCRIPTION": "by sharing a standard API, relayers can easily aggregate liquidity pools, creating network effects around liquidity that compound as more relayers come online.", - "BENEFIT_THREE_TITLE": "open source", + "BENEFIT_THREE_TITLE": "exchange everywhere", "BENEFIT_THREE_DESCRIPTION": - "0x is open source, permissionless and free to use. Trade directly with a known counterparty for free or pay a relayer some ZRX tokens to access their liquidity pool.", + "0x allows trade functionality to fade into the background, enabling developers to focus on building while 0x handles the exchange.", "BUILDING_BLOCK_SECTION_HEADER": "a building block for dApps", "BUILDING_BLOCK_SECTION_DESCRIPTION": "0x protocol is a pluggable building block for dApps that require exchange functionality. Join the many developers that are already using 0x in their web applications and smart contracts.", @@ -43,10 +44,10 @@ "decentralized prediction market platforms generate sets of tokens that represent a financial stake in the outcomes of real-world events. 0x allows these tokens to be instantly tradable.", "STABLE_TOKENS": "stable tokens", "STABLE_TOKENS_DESCRIPTION": - "Novel economic constructs such as stable coins require efficient, liquid markets to succeed. 0x will facilitate the underlying economic mechanisms that allow these tokens to remain stable.", + "novel economic constructs such as stable coins require efficient, liquid markets to succeed. 0x will facilitate the underlying economic mechanisms that allow these tokens to remain stable.", "DECENTRALIZED_LOANS": "decentralized loans", "DECENTRALIZED_LOANS_DESCRIPTION": - "Efficient lending requires liquid markets where investors can buy and re-sell loans. 0x enables an ecosystem of lenders to self-organize and efficiently determine market prices for all outstanding loans.", + "efficient lending requires liquid markets where investors can buy and re-sell loans. 0x enables an ecosystem of lenders to self-organize and efficiently determine market prices for all outstanding loans.", "FUND_MANAGEMENT": "fund management", "FUND_MANAGEMENT_DESCRIPTION": "Decentralized fund management limits fund managers to investing in pre-agreed upon asset classes. Embedding 0x into fund management smart contracts enables them to enforce these security constraints.", @@ -80,5 +81,12 @@ "DEVELOPERS": "developers", "HOME": "home", "ROCKETCHAT": "rocket.chat", - "TRADE_CALL_TO_ACTION": "trade on 0x" + "TRADE_CALL_TO_ACTION": "trade on 0x", + "OUR_MISSION_AND_VALUES": "our mission & values", + "GAMING_AND_COLLECTABLES": "gaming & collectables", + "GAMING_AND_COLLECTABLES_DESCRIPTION": + "artists and game makers are tokenizing digital art and in-game items known as non-fungible tokens (NFTs). 0x enables these creators to add exchange functionality to give access and the ability to build marketplaces for NFT trading.", + "ORDER_BOOKS": "order books", + "ORDER_BOOKS_DESCRIPTION": + "there are thousands of decentralized apps that have native utility tokens. 0x provides market makers and professional exchanges an ability to host order books to facilitate the exchange of these assets." } diff --git a/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx b/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx index c8e10303f..18c060991 100644 --- a/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx +++ b/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx @@ -22,7 +22,7 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp key="blockchainErrOk" label="Ok" primary={true} - onTouchTap={this.props.toggleDialogFn.bind(this.props.toggleDialogFn, false)} + onClick={this.props.toggleDialogFn.bind(this.props.toggleDialogFn, false)} />, ]; diff --git a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx index 5f4bf8519..f2cfb279a 100644 --- a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx +++ b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx @@ -54,8 +54,8 @@ export class EthWethConversionDialog extends React.Component< } public render(): React.ReactNode { const convertDialogActions = [ - <FlatButton key="cancel" label="Cancel" onTouchTap={this._onCancel.bind(this)} />, - <FlatButton key="convert" label="Convert" primary={true} onTouchTap={this._onConvertClick.bind(this)} />, + <FlatButton key="cancel" label="Cancel" onClick={this._onCancel.bind(this)} />, + <FlatButton key="convert" label="Convert" primary={true} onClick={this._onConvertClick.bind(this)} />, ]; const title = this.props.direction === Side.Deposit ? 'Wrap ETH' : 'Unwrap WETH'; return !_.isUndefined(this.props.etherBalanceInWei) ? ( diff --git a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx index d2f373d67..fbc6c868b 100644 --- a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx +++ b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx @@ -64,7 +64,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps, } public render(): React.ReactNode { const dialogActions = [ - <FlatButton key="ledgerConnectCancel" label="Cancel" onTouchTap={this._onClose.bind(this)} />, + <FlatButton key="ledgerConnectCancel" label="Cancel" onClick={this._onClose.bind(this)} />, ]; const dialogTitle = this.state.stepIndex === LedgerSteps.CONNECT ? 'Connect to your Ledger' : 'Select desired address'; diff --git a/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx b/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx index 41a17fe96..ef295762b 100644 --- a/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx +++ b/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx @@ -13,7 +13,7 @@ export const PortalDisclaimerDialog = (props: PortalDisclaimerDialogProps) => { <Dialog title="0x Portal Disclaimer" titleStyle={{ fontWeight: 100 }} - actions={[<FlatButton key="portalAgree" label="I Agree" onTouchTap={props.onToggleDialog} />]} + actions={[<FlatButton key="portalAgree" label="I Agree" onClick={props.onToggleDialog} />]} open={props.isOpen} onRequestClose={props.onToggleDialog} autoScrollBodyContent={true} diff --git a/packages/website/ts/components/dialogs/send_dialog.tsx b/packages/website/ts/components/dialogs/send_dialog.tsx index c1179dbd0..2754b153f 100644 --- a/packages/website/ts/components/dialogs/send_dialog.tsx +++ b/packages/website/ts/components/dialogs/send_dialog.tsx @@ -38,13 +38,13 @@ export class SendDialog extends React.Component<SendDialogProps, SendDialogState } public render(): React.ReactNode { const transferDialogActions = [ - <FlatButton key="cancelTransfer" label="Cancel" onTouchTap={this._onCancel.bind(this)} />, + <FlatButton key="cancelTransfer" label="Cancel" onClick={this._onCancel.bind(this)} />, <FlatButton key="sendTransfer" disabled={this._hasErrors()} label="Send" primary={true} - onTouchTap={this._onSendClick.bind(this)} + onClick={this._onSendClick.bind(this)} />, ]; return ( diff --git a/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx b/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx index 3751ce06f..c8d5af6b6 100644 --- a/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx +++ b/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx @@ -43,12 +43,12 @@ export class TrackTokenConfirmationDialog extends React.Component< <FlatButton key="trackNo" label="No" - onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, false)} + onClick={this._onTrackConfirmationRespondedAsync.bind(this, false)} />, <FlatButton key="trackYes" label="Yes" - onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, true)} + onClick={this._onTrackConfirmationRespondedAsync.bind(this, true)} />, ]} open={this.props.isOpen} diff --git a/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx b/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx index 3ebab03ef..afbb30b82 100644 --- a/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx +++ b/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx @@ -14,7 +14,7 @@ export const U2fNotSupportedDialog = (props: U2fNotSupportedDialogProps) => { <Dialog title="U2F Not Supported" titleStyle={{ fontWeight: 100 }} - actions={[<FlatButton key="u2fNo" label="Ok" onTouchTap={props.onToggleDialog} />]} + actions={[<FlatButton key="u2fNo" label="Ok" onClick={props.onToggleDialog} />]} open={props.isOpen} onRequestClose={props.onToggleDialog} autoScrollBodyContent={true} diff --git a/packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx b/packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx index 78b270c1e..cf2c4dda5 100644 --- a/packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx +++ b/packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx @@ -14,7 +14,7 @@ export const WrappedEthSectionNoticeDialog = (props: WrappedEthSectionNoticeDial title="Dedicated Wrapped Ether Section" titleStyle={{ fontWeight: 100 }} actions={[ - <FlatButton key="acknowledgeWrapEthSection" label="Sounds good" onTouchTap={props.onToggleDialog} />, + <FlatButton key="acknowledgeWrapEthSection" label="Sounds good" onClick={props.onToggleDialog} />, ]} open={props.isOpen} onRequestClose={props.onToggleDialog} diff --git a/packages/website/ts/components/fill_warning_dialog.tsx b/packages/website/ts/components/fill_warning_dialog.tsx index 45c492221..4821aaabe 100644 --- a/packages/website/ts/components/fill_warning_dialog.tsx +++ b/packages/website/ts/components/fill_warning_dialog.tsx @@ -18,12 +18,12 @@ export const FillWarningDialog = (props: FillWarningDialogProps) => { <FlatButton key="fillWarningCancel" label="Cancel" - onTouchTap={() => props.onToggleDialog(didCancel)} // tslint:disable-line:jsx-no-lambda + onClick={() => props.onToggleDialog(didCancel)} // tslint:disable-line:jsx-no-lambda />, <FlatButton key="fillWarningContinue" label="Fill Order" - onTouchTap={() => props.onToggleDialog(!didCancel)} // tslint:disable-line:jsx-no-lambda + onClick={() => props.onToggleDialog(!didCancel)} // tslint:disable-line:jsx-no-lambda />, ]} open={props.isOpen} diff --git a/packages/website/ts/components/generate_order/asset_picker.tsx b/packages/website/ts/components/generate_order/asset_picker.tsx index 2dca3483f..98aad6c62 100644 --- a/packages/website/ts/components/generate_order/asset_picker.tsx +++ b/packages/website/ts/components/generate_order/asset_picker.tsx @@ -73,12 +73,12 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt <FlatButton key="noTracking" label="No" - onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, false)} + onClick={this._onTrackConfirmationRespondedAsync.bind(this, false)} />, <FlatButton key="yesTrack" label="Yes" - onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, true)} + onClick={this._onTrackConfirmationRespondedAsync.bind(this, true)} />, ], }, diff --git a/packages/website/ts/components/token_balances.tsx b/packages/website/ts/components/token_balances.tsx index 969ef32ff..7e7a8d1fa 100644 --- a/packages/website/ts/components/token_balances.tsx +++ b/packages/website/ts/components/token_balances.tsx @@ -165,7 +165,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala key="errorOkBtn" label="Ok" primary={true} - onTouchTap={this._onErrorDialogToggle.bind(this, false)} + onClick={this._onErrorDialogToggle.bind(this, false)} />, ]; const isTestNetwork = utils.isTestNetwork(this.props.networkId); diff --git a/packages/website/ts/components/top_bar/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx index 9ef8211a9..bb61e4fb9 100644 --- a/packages/website/ts/components/top_bar/top_bar.tsx +++ b/packages/website/ts/components/top_bar/top_bar.tsx @@ -19,7 +19,7 @@ import { TopBarMenuItem } from 'ts/components/top_bar/top_bar_menu_item'; import { Container } from 'ts/components/ui/container'; import { DropDown } from 'ts/components/ui/drop_down'; import { Dispatcher } from 'ts/redux/dispatcher'; -import { Deco, Key, ProviderType, WebsiteLegacyPaths, WebsitePaths } from 'ts/types'; +import { Deco, Key, ProviderType, WebsitePaths } from 'ts/types'; import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; @@ -238,7 +238,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { const fullWidthClasses = isExpandedDisplayType ? 'pr4' : ''; const logoUrl = isNightVersion ? '/images/protocol_logo_white.png' : '/images/protocol_logo_black.png'; const menuClasses = `col col-${ - isExpandedDisplayType ? '4' : '5' + isExpandedDisplayType ? '4' : '6' } ${fullWidthClasses} lg-pr0 md-pr2 sm-hide xs-hide`; const menuIconStyle = { fontSize: 25, @@ -302,6 +302,13 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { isExternal={false} /> <TopBarMenuItem + title={this.props.translate.get(Key.Careers, Deco.Cap)} + path={`${WebsitePaths.Careers}`} + style={styles.menuItem} + isNightVersion={isNightVersion} + isExternal={false} + /> + <TopBarMenuItem title={this.props.translate.get(Key.TradeCallToAction, Deco.Cap)} path={`${WebsitePaths.Portal}`} isPrimary={true} @@ -406,11 +413,14 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { <Link to={`${WebsitePaths.About}`} className="text-decoration-none"> <MenuItem className="py2">{this.props.translate.get(Key.About, Deco.Cap)}</MenuItem> </Link> + <Link to={`${WebsitePaths.Careers}`} className="text-decoration-none"> + <MenuItem className="py2">{this.props.translate.get(Key.Careers, Deco.Cap)}</MenuItem> + </Link> <a className="text-decoration-none" target="_blank" href={constants.URL_BLOG}> <MenuItem className="py2">{this.props.translate.get(Key.Blog, Deco.Cap)}</MenuItem> </a> <Link to={`${WebsitePaths.FAQ}`} className="text-decoration-none"> - <MenuItem className="py2" onTouchTap={this._onMenuButtonClick.bind(this)}> + <MenuItem className="py2" onClick={this._onMenuButtonClick.bind(this)}> {this.props.translate.get(Key.Faq, Deco.Cap)} </MenuItem> </Link> diff --git a/packages/website/ts/components/ui/button.tsx b/packages/website/ts/components/ui/button.tsx index 2952c8859..75ba7bcff 100644 --- a/packages/website/ts/components/ui/button.tsx +++ b/packages/website/ts/components/ui/button.tsx @@ -96,4 +96,5 @@ export const CallToAction: React.StatelessComponent<CallToActionProps> = ({ CallToAction.defaultProps = { type: 'dark', fontSize: '14px', + padding: '0.9em 1.6em', }; diff --git a/packages/website/ts/components/ui/lifecycle_raised_button.tsx b/packages/website/ts/components/ui/lifecycle_raised_button.tsx index 380fbc77d..0bb99b9d8 100644 --- a/packages/website/ts/components/ui/lifecycle_raised_button.tsx +++ b/packages/website/ts/components/ui/lifecycle_raised_button.tsx @@ -71,7 +71,7 @@ export class LifeCycleRaisedButton extends React.Component<LifeCycleRaisedButton style={{ width: '100%' }} backgroundColor={this.props.backgroundColor} labelColor={this.props.labelColor} - onTouchTap={this.onClickAsync.bind(this)} + onClick={this.onClickAsync.bind(this)} disabled={this.props.isDisabled || this.state.buttonState !== ButtonState.READY} /> ); diff --git a/packages/website/ts/components/ui/text.tsx b/packages/website/ts/components/ui/text.tsx index 734483564..cd8f290e3 100644 --- a/packages/website/ts/components/ui/text.tsx +++ b/packages/website/ts/components/ui/text.tsx @@ -20,6 +20,7 @@ export interface TextProps { onClick?: (event: React.MouseEvent<HTMLElement>) => void; hoverColor?: string; noWrap?: boolean; + display?: string; } const PlainText: React.StatelessComponent<TextProps> = ({ children, className, onClick, Tag }) => ( @@ -41,6 +42,7 @@ export const Text = styled(PlainText)` ${props => (props.onClick ? 'cursor: pointer' : '')}; transition: color 0.5s ease; ${props => (props.noWrap ? 'white-space: nowrap' : '')}; + ${props => (props.display ? `display: ${props.display}` : '')}; &:hover { ${props => (props.onClick ? `color: ${props.hoverColor || darken(0.3, props.fontColor)}` : '')}; } diff --git a/packages/website/ts/components/ui/typed_text.tsx b/packages/website/ts/components/ui/typed_text.tsx new file mode 100644 index 000000000..2bb2d40b0 --- /dev/null +++ b/packages/website/ts/components/ui/typed_text.tsx @@ -0,0 +1,76 @@ +import * as _ from 'lodash'; +import { darken } from 'polished'; +import * as React from 'react'; +import Typist from 'react-typist'; + +import { Text, TextProps } from 'ts/components/ui/text'; + +import 'react-typist/dist/Typist.css'; + +export interface TypedTextProps extends TextProps { + textList: string[]; + shouldRepeat?: boolean; + wordDelayMs?: number; + avgKeystrokeDelayMs?: number; + stdKeystrokeDelay?: number; +} + +export interface TypedTextState { + cycleCount: number; +} + +export class TypedText extends React.Component<TypedTextProps, TypedTextState> { + public static defaultProps = { + shouldRepeat: false, + avgKeystrokeDelayMs: 90, + wordDelayMs: 1000, + }; + public state = { + cycleCount: 0, + }; + public render(): React.ReactNode { + const { + textList, + shouldRepeat, + wordDelayMs, + avgKeystrokeDelayMs, + stdKeystrokeDelay, + // tslint:disable-next-line + ...textProps + } = this.props; + const { cycleCount } = this.state; + if (_.isEmpty(textList)) { + return null; + } + const typistChildren: React.ReactNode[] = []; + _.forEach(textList, text => { + typistChildren.push( + <Text key={`text-${text}-${cycleCount}`} {...textProps}> + {text} + </Text>, + ); + if (wordDelayMs) { + typistChildren.push(<Typist.Delay key={`delay-${text}-${cycleCount}`} ms={wordDelayMs} />); + } + typistChildren.push(<Typist.Backspace key={`backspace-${text}-${cycleCount}`} count={text.length} />); + }); + return ( + <Typist + avgTypingDelay={avgKeystrokeDelayMs} + stdTypingDelay={stdKeystrokeDelay} + className="inline" + key={`typist-key-${cycleCount}`} + onTypingDone={this._onTypingDone.bind(this)} + > + {typistChildren} + </Typist> + ); + } + private _onTypingDone(): void { + if (this.props.shouldRepeat) { + this.setState({ + cycleCount: this.state.cycleCount + 1, + }); + } + } +} diff --git a/packages/website/ts/containers/connect_documentation.ts b/packages/website/ts/containers/connect_documentation.ts index 90137243c..a728abe2c 100644 --- a/packages/website/ts/containers/connect_documentation.ts +++ b/packages/website/ts/containers/connect_documentation.ts @@ -1,4 +1,4 @@ -import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs'; +import { DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs'; import * as React from 'react'; import { connect } from 'react-redux'; import { Dispatch } from 'redux'; diff --git a/packages/website/ts/containers/contract_wrappers_documentation.ts b/packages/website/ts/containers/contract_wrappers_documentation.ts index fd8599192..1e1735846 100644 --- a/packages/website/ts/containers/contract_wrappers_documentation.ts +++ b/packages/website/ts/containers/contract_wrappers_documentation.ts @@ -1,4 +1,4 @@ -import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs'; +import { DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs'; import * as React from 'react'; import { connect } from 'react-redux'; import { Dispatch } from 'redux'; @@ -6,7 +6,6 @@ import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentatio import { Dispatcher } from 'ts/redux/dispatcher'; import { State } from 'ts/redux/reducer'; import { DocPackages } from 'ts/types'; -import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; /* tslint:disable:no-var-requires */ diff --git a/packages/website/ts/containers/ethereum_types_documentation.ts b/packages/website/ts/containers/ethereum_types_documentation.ts index e0bf9a83e..2b6d6e64d 100644 --- a/packages/website/ts/containers/ethereum_types_documentation.ts +++ b/packages/website/ts/containers/ethereum_types_documentation.ts @@ -6,7 +6,6 @@ import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentatio import { Dispatcher } from 'ts/redux/dispatcher'; import { State } from 'ts/redux/reducer'; import { DocPackages } from 'ts/types'; -import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; /* tslint:disable:no-var-requires */ diff --git a/packages/website/ts/containers/order_utils_documentation.ts b/packages/website/ts/containers/order_utils_documentation.ts index 47ac35268..b54c30a1e 100644 --- a/packages/website/ts/containers/order_utils_documentation.ts +++ b/packages/website/ts/containers/order_utils_documentation.ts @@ -6,7 +6,6 @@ import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentatio import { Dispatcher } from 'ts/redux/dispatcher'; import { State } from 'ts/redux/reducer'; import { DocPackages } from 'ts/types'; -import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; /* tslint:disable:no-var-requires */ diff --git a/packages/website/ts/containers/order_watcher_documentation.ts b/packages/website/ts/containers/order_watcher_documentation.ts index 2fa2a9d61..59a018847 100644 --- a/packages/website/ts/containers/order_watcher_documentation.ts +++ b/packages/website/ts/containers/order_watcher_documentation.ts @@ -6,7 +6,6 @@ import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentatio import { Dispatcher } from 'ts/redux/dispatcher'; import { State } from 'ts/redux/reducer'; import { DocPackages } from 'ts/types'; -import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; /* tslint:disable:no-var-requires */ diff --git a/packages/website/ts/containers/sol_compiler_documentation.ts b/packages/website/ts/containers/sol_compiler_documentation.ts index 7cde68e5c..20f26ed1d 100644 --- a/packages/website/ts/containers/sol_compiler_documentation.ts +++ b/packages/website/ts/containers/sol_compiler_documentation.ts @@ -1,4 +1,4 @@ -import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs'; +import { DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs'; import * as React from 'react'; import { connect } from 'react-redux'; import { Dispatch } from 'redux'; diff --git a/packages/website/ts/containers/sol_cov_documentation.ts b/packages/website/ts/containers/sol_cov_documentation.ts index a457cbc1e..27efd641e 100644 --- a/packages/website/ts/containers/sol_cov_documentation.ts +++ b/packages/website/ts/containers/sol_cov_documentation.ts @@ -1,4 +1,4 @@ -import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs'; +import { DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs'; import * as React from 'react'; import { connect } from 'react-redux'; import { Dispatch } from 'redux'; diff --git a/packages/website/ts/containers/subproviders_documentation.ts b/packages/website/ts/containers/subproviders_documentation.ts index 43f06b4ed..28b2e9508 100644 --- a/packages/website/ts/containers/subproviders_documentation.ts +++ b/packages/website/ts/containers/subproviders_documentation.ts @@ -1,4 +1,4 @@ -import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs'; +import { DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs'; import * as React from 'react'; import { connect } from 'react-redux'; import { Dispatch } from 'redux'; @@ -6,7 +6,6 @@ import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentatio import { Dispatcher } from 'ts/redux/dispatcher'; import { State } from 'ts/redux/reducer'; import { DocPackages } from 'ts/types'; -import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; /* tslint:disable:no-var-requires */ diff --git a/packages/website/ts/containers/web3_wrapper_documentation.ts b/packages/website/ts/containers/web3_wrapper_documentation.ts index 13924fde8..dc9d23304 100644 --- a/packages/website/ts/containers/web3_wrapper_documentation.ts +++ b/packages/website/ts/containers/web3_wrapper_documentation.ts @@ -1,4 +1,4 @@ -import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs'; +import { DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs'; import * as React from 'react'; import { connect } from 'react-redux'; import { Dispatch } from 'redux'; @@ -6,7 +6,6 @@ import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentatio import { Dispatcher } from 'ts/redux/dispatcher'; import { State } from 'ts/redux/reducer'; import { DocPackages } from 'ts/types'; -import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; /* tslint:disable:no-var-requires */ diff --git a/packages/website/ts/containers/zero_ex_js_documentation.ts b/packages/website/ts/containers/zero_ex_js_documentation.ts index 367d3e064..922dd3c10 100644 --- a/packages/website/ts/containers/zero_ex_js_documentation.ts +++ b/packages/website/ts/containers/zero_ex_js_documentation.ts @@ -1,4 +1,4 @@ -import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs'; +import { DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs'; import * as React from 'react'; import { connect } from 'react-redux'; import { Dispatch } from 'redux'; @@ -6,7 +6,6 @@ import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentatio import { Dispatcher } from 'ts/redux/dispatcher'; import { State } from 'ts/redux/reducer'; import { DocPackages } from 'ts/types'; -import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; /* tslint:disable:no-var-requires */ diff --git a/packages/website/ts/index.tsx b/packages/website/ts/index.tsx index 981c6f2cb..9e59b00ac 100644 --- a/packages/website/ts/index.tsx +++ b/packages/website/ts/index.tsx @@ -3,7 +3,6 @@ import * as React from 'react'; import { render } from 'react-dom'; import { Provider } from 'react-redux'; import { BrowserRouter as Router, Redirect, Route, Switch } from 'react-router-dom'; -import * as injectTapEventPlugin from 'react-tap-event-plugin'; import { MetaTags } from 'ts/components/meta_tags'; import { About } from 'ts/containers/about'; import { FAQ } from 'ts/containers/faq'; @@ -17,8 +16,6 @@ import { tradeHistoryStorage } from 'ts/local_storage/trade_history_storage'; import { store } from 'ts/redux/store'; import { WebsiteLegacyPaths, WebsitePaths } from 'ts/types'; import { muiTheme } from 'ts/utils/mui_theme'; -// Polyfills -injectTapEventPlugin(); // Check if we've introduced an update that requires us to clear the tradeHistory local storage entries tradeHistoryStorage.clearIfRequired(); diff --git a/packages/website/ts/pages/landing/landing.tsx b/packages/website/ts/pages/landing/landing.tsx index 78f5fc3c1..7dfd9c9df 100644 --- a/packages/website/ts/pages/landing/landing.tsx +++ b/packages/website/ts/pages/landing/landing.tsx @@ -8,6 +8,9 @@ import { SubscribeForm } from 'ts/components/forms/subscribe_form'; import { TopBar } from 'ts/components/top_bar/top_bar'; import { CallToAction } from 'ts/components/ui/button'; import { Container } from 'ts/components/ui/container'; +import { Image } from 'ts/components/ui/image'; +import { Text } from 'ts/components/ui/text'; +import { TypedText } from 'ts/components/ui/typed_text'; import { Dispatcher } from 'ts/redux/dispatcher'; import { Deco, Key, Language, ScreenWidths, WebsitePaths } from 'ts/types'; import { constants } from 'ts/utils/constants'; @@ -19,6 +22,7 @@ interface BoxContent { description: string; imageUrl: string; classNames: string; + maxWidth: number; } interface AssetType { title: string; @@ -31,7 +35,6 @@ interface UseCase { description: string; classNames: string; style?: React.CSSProperties; - projectIconUrls: string[]; } interface Project { logoFileName: string; @@ -41,72 +44,22 @@ interface Project { const THROTTLE_TIMEOUT = 100; const WHATS_NEW_TITLE = '18 ideas for 0x relayers in 2018'; const WHATS_NEW_URL = 'https://blog.0xproject.com/18-ideas-for-0x-relayers-in-2018-80a1498b955f'; - -const relayersAndDappProjects: Project[] = [ - { - logoFileName: 'ercdex.png', - projectUrl: constants.PROJECT_URL_ERC_DEX, - }, - { - logoFileName: 'radar_relay.png', - projectUrl: constants.PROJECT_URL_RADAR_RELAY, - }, - { - logoFileName: 'paradex.png', - projectUrl: constants.PROJECT_URL_PARADEX, - }, - { - logoFileName: 'the_ocean.png', - projectUrl: constants.PROJECT_URL_0CEAN, - }, - { - logoFileName: 'dydx.png', - projectUrl: constants.PROJECT_URL_DYDX, - }, - { - logoFileName: 'ethfinex.png', - projectUrl: constants.PROJECT_URL_ETHFINEX, - }, - { - logoFileName: 'melonport.png', - projectUrl: constants.PROJECT_URL_MELONPORT, - }, - { - logoFileName: 'maker.png', - projectUrl: constants.PROJECT_URL_MAKER, - }, - { - logoFileName: 'dharma.png', - projectUrl: constants.PROJECT_URL_DHARMA, - }, - { - logoFileName: 'lendroid.png', - projectUrl: constants.PROJECT_URL_LENDROID, - }, - { - logoFileName: 'district0x.png', - projectUrl: constants.PROJECT_URL_DISTRICT_0X, - }, - { - logoFileName: 'aragon.png', - projectUrl: constants.PROJECT_URL_ARAGON, - }, - { - logoFileName: 'blocknet.png', - projectUrl: constants.PROJECT_URL_BLOCKNET, - }, - { - logoFileName: 'imtoken.png', - projectUrl: constants.PROJECT_URL_IMTOKEN, - }, - { - logoFileName: 'augur.png', - projectUrl: constants.PROJECT_URL_AUGUR, - }, - { - logoFileName: 'anx.png', - projectUrl: constants.PROJECT_URL_OPEN_ANX, - }, +const TITLE_STYLE: React.CSSProperties = { + fontFamily: 'Roboto Mono', + color: colors.grey, + fontWeight: 300, + letterSpacing: 3, +}; +const ROTATING_LIST = [ + 'tokens', + 'game items', + 'digital art', + 'futures', + 'stocks', + 'derivatives', + 'loans', + 'cats', + 'everything', ]; const relayerProjects: Project[] = [ @@ -199,21 +152,13 @@ export class Landing extends React.Component<LandingProps, LandingState> { /> {this._renderHero()} {this._renderProjects( - relayersAndDappProjects, - this.props.translate.get(Key.ProjectsHeader, Deco.Upper), - colors.projectsGrey, - false, - )} - {this._renderTokenizationSection()} - {this._renderProtocolSection()} - {this._renderProjects( relayerProjects, this.props.translate.get(Key.RelayersHeader, Deco.Upper), - colors.heroGrey, + colors.projectsGrey, true, )} {this._renderInfoBoxes()} - {this._renderBuildingBlocksSection()} + {this._renderTokenizationSection()} {this._renderUseCases()} {this._renderCallToAction()} <Footer translate={this.props.translate} dispatcher={this.props.dispatcher} /> @@ -222,15 +167,18 @@ export class Landing extends React.Component<LandingProps, LandingState> { } private _renderHero(): React.ReactNode { const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; - const left = 'col lg-col-7 md-col-7 col-12 lg-pl4 md-pl4 sm-pl0 sm-px3 sm-center'; + const left = 'col lg-col-6 md-col-6 col-12 lg-pl4 md-pl4 sm-pl0 sm-px3 sm-center'; + const flexClassName = isSmallScreen + ? 'flex items-center flex-column justify-center' + : 'flex items-center justify-center'; return ( <div className="clearfix py4" style={{ backgroundColor: colors.heroGrey }}> <div className="mx-auto max-width-4 clearfix"> {this._renderWhatsNew()} - <div className="lg-pt4 md-pt4 sm-pt2 lg-pb4 md-pb4 lg-mt4 md-mt4 sm-mt2 sm-mb4 clearfix"> - <div className="col lg-col-5 md-col-5 col-12 sm-center"> - <img src="/images/landing/hero_chip_image.png" height={isSmallScreen ? 300 : 395} /> - </div> + <div className={`${flexClassName} lg-pt4 md-pt4 sm-pt2 lg-pb4 md-pb4 lg-mt4 md-mt4 sm-mt2 sm-mb4`}> + <Container marginTop="30px" marginBottom="30px" marginLeft="15px" marginRight="15px"> + <Image src="/images/landing/0x_homepage.svg" maxWidth="100%" height="auto" /> + </Container> <div className={left} style={{ color: colors.white, height: 390, lineHeight: '390px' }}> <div className="inline-block lg-align-middle md-align-middle sm-align-top" @@ -239,37 +187,46 @@ export class Landing extends React.Component<LandingProps, LandingState> { lineHeight: '36px', }} > - <div + <Text className="sm-pb2" - style={{ - fontFamily: 'Roboto Mono', - fontSize: isSmallScreen ? 26 : 34, - }} + fontFamily="Roboto" + display="inline-block" + fontColor={colors.grey300} + fontWeight={500} + lineHeight="1.3em" + fontSize={isSmallScreen ? '28px' : '36px'} > {this.props.translate.get(Key.TopHeader, Deco.Cap)} - </div> - <div - className="pt2 h5 sm-mx-auto" - style={{ - maxWidth: 446, - fontFamily: 'Roboto Mono', - lineHeight: 1.7, - fontWeight: 300, - }} + {this.props.translate.getLanguage() === Language.English && ( + <React.Fragment> + {' '} + for{' '} + <TypedText + fontFamily="Roboto" + display="inline-block" + fontColor={colors.white} + fontWeight={700} + lineHeight="1.3em" + fontSize={isSmallScreen ? '28px' : '36px'} + textList={ROTATING_LIST} + shouldRepeat={true} + /> + </React.Fragment> + )} + </Text> + <Container + className={`pt3 flex clearfix sm-mx-auto ${isSmallScreen ? 'justify-center' : ''}`} > - {this.props.translate.get(Key.TopTagline)} - </div> - <Container className="pt3 clearfix sm-mx-auto" maxWidth="390px"> - <div className="lg-pr2 md-pr2 lg-col lg-col-6 sm-center sm-col sm-col-12 mb2"> + <Container paddingRight="20px"> <Link to={WebsitePaths.ZeroExJs} className="text-decoration-none"> - <CallToAction width="175px" type="light"> + <CallToAction type="light"> {this.props.translate.get(Key.BuildCallToAction, Deco.Cap)} </CallToAction> </Link> - </div> - <div className="lg-col lg-col-6 sm-center sm-col sm-col-12"> + </Container> + <div> <Link to={WebsitePaths.Portal} className="text-decoration-none"> - <CallToAction width="175px"> + <CallToAction> {this.props.translate.get(Key.TradeCallToAction, Deco.Cap)} </CallToAction> </Link> @@ -287,19 +244,24 @@ export class Landing extends React.Component<LandingProps, LandingState> { return ( <div className="sm-center sm-px1"> <a href={WHATS_NEW_URL} target="_blank" className="inline-block text-decoration-none"> - <div className="flex sm-pl0 md-pl2 lg-pl0" style={{ fontFamily: 'Roboto Mono', fontWeight: 600 }}> - <div - className="mr1 px1" - style={{ - backgroundColor: colors.white, - borderRadius: 3, - color: colors.heroGrey, - height: 23, - }} + <div className="flex items-center sm-pl0 md-pl2 lg-pl0"> + <Container + paddingTop="3px" + paddingLeft="8px" + paddingBottom="3px" + paddingRight="8px" + backgroundColor={colors.white} + borderRadius={6} > - New - </div> - <div style={{ color: colors.darkGrey }}>{WHATS_NEW_TITLE}</div> + <Text fontSize="14px" fontWeight={500} fontColor={colors.heroGrey}> + New + </Text> + </Container> + <Container marginLeft="12px"> + <Text fontSize="16px" fontWeight={500} fontColor={colors.grey300}> + {WHATS_NEW_TITLE} + </Text> + </Container> </div> </a> </div> @@ -344,16 +306,10 @@ export class Landing extends React.Component<LandingProps, LandingState> { </div> ); }); - const titleStyle: React.CSSProperties = { - fontFamily: 'Roboto Mono', - color: colors.grey, - fontWeight: 300, - letterSpacing: 3, - }; return ( <div className={`clearfix py4 ${isTitleCenter && 'center'}`} style={{ backgroundColor }}> <div className="mx-auto max-width-4 clearfix sm-px3"> - <div className="h4 pb3 lg-pl0 md-pl3 sm-pl2" style={titleStyle}> + <div className="h4 pb3 lg-pl0 md-pl3 sm-pl2" style={TITLE_STYLE}> {title} </div> <div className="clearfix">{projectList}</div> @@ -368,7 +324,7 @@ export class Landing extends React.Component<LandingProps, LandingState> { > {this.props.translate.get(Key.FullListPrompt)}{' '} <Link - to={`${WebsitePaths.Wiki}#List-of-Projects-Using-0x-Protocol`} + to={WebsitePaths.Portal} className="text-decoration-none underline" style={{ color: colors.landingLinkGrey }} > @@ -402,7 +358,7 @@ export class Landing extends React.Component<LandingProps, LandingState> { > {this.props.translate.get(Key.TokenizedSectionDescription, Deco.Cap)} </div> - <div className="flex pt1 sm-px3">{this._renderAssetTypes()}</div> + <div className="flex pt1 sm-px3">{this._renderMissionAndValuesButton()}</div> </div> </div> {!isSmallScreen && this._renderTokenCloud()} @@ -410,116 +366,6 @@ export class Landing extends React.Component<LandingProps, LandingState> { </div> ); } - private _renderProtocolSection(): React.ReactNode { - const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; - return ( - <div className="clearfix pt4" style={{ backgroundColor: colors.heroGrey }}> - <div className="mx-auto max-width-4 pt4 clearfix"> - <div className="col lg-col-6 md-col-6 col-12 sm-center"> - <img src="/images/landing/relayer_diagram.png" height={isSmallScreen ? 326 : 426} /> - </div> - <div - className="col lg-col-6 md-col-6 col-12 lg-pr3 md-pr3 sm-mx-auto" - style={{ - color: colors.beigeWhite, - maxWidth: isSmallScreen ? 'none' : 445, - height: 430, - lineHeight: '430px', - }} - > - <div - className="inline-block lg-align-middle md-align-middle sm-align-top" - style={{ lineHeight: '43px' }} - > - <div - className="lg-h1 md-h1 sm-h2 pb1 sm-pt3 sm-center" - style={{ fontFamily: 'Roboto Mono' }} - > - <div>{this.props.translate.get(Key.OffChainOrderRelay, Deco.Cap)}</div> - <div> {this.props.translate.get(Key.OnChainSettlement, Deco.Cap)}</div> - </div> - <div - className="pb2 pt2 h5 sm-center sm-px3 sm-mx-auto" - style={{ - fontFamily: 'Roboto Mono', - lineHeight: 1.7, - fontWeight: 300, - maxWidth: 445, - }} - > - {this.props.translate.get(Key.OffChainOnChainDescription, Deco.Cap)} - </div> - </div> - </div> - </div> - </div> - ); - } - private _renderBuildingBlocksSection(): React.ReactNode { - const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; - const descriptionStyle: React.CSSProperties = { - fontFamily: 'Roboto Mono', - lineHeight: isSmallScreen ? 1.5 : 2, - fontWeight: 300, - fontSize: 15, - maxWidth: isSmallScreen ? 375 : 'none', - }; - const callToActionStyle: React.CSSProperties = { - fontFamily: 'Roboto Mono', - fontSize: 15, - fontWeight: 300, - maxWidth: isSmallScreen ? 375 : 441, - }; - return ( - <div className="clearfix lg-pt4 md-pt4" style={{ backgroundColor: colors.heroGrey }}> - <div className="mx-auto max-width-4 lg-pt4 md-pt4 lg-mb4 md-mb4 sm-mb2 clearfix"> - {isSmallScreen && this._renderBlockChipImage()} - <div - className="col lg-col-6 md-col-6 col-12 lg-pr3 md-pr3 sm-px3" - style={{ color: colors.beigeWhite }} - > - <div - className="pb1 lg-pt4 md-pt4 sm-pt3 lg-h1 md-h1 sm-h2 sm-px3 sm-center" - style={{ fontFamily: 'Roboto Mono' }} - > - {this.props.translate.get(Key.BuildingBlockSectionHeader, Deco.Cap)} - </div> - <div className="pb3 pt2 sm-mx-auto sm-center" style={descriptionStyle}> - {this.props.translate.get(Key.BuildingBlockSectionDescription, Deco.Cap)} - </div> - <div className="sm-mx-auto sm-center" style={callToActionStyle}> - {this.props.translate.get(Key.DevToolsPrompt, Deco.Cap)}{' '} - <Link - to={WebsitePaths.ZeroExJs} - className="text-decoration-none underline" - style={{ color: colors.beigeWhite, fontFamily: 'Roboto Mono' }} - > - 0x.js - </Link>{' '} - {this.props.translate.get(Key.And)}{' '} - <Link - to={WebsitePaths.SmartContracts} - className="text-decoration-none underline" - style={{ color: colors.beigeWhite, fontFamily: 'Roboto Mono' }} - > - {this.props.translate.get(Key.SmartContract)} - </Link>{' '} - {this.props.translate.get(Key.Docs)} - </div> - </div> - {!isSmallScreen && this._renderBlockChipImage()} - </div> - </div> - ); - } - private _renderBlockChipImage(): React.ReactNode { - const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; - return ( - <div className="col lg-col-6 md-col-6 col-12 sm-center"> - <img src="/images/landing/0x_chips.png" height={isSmallScreen ? 240 : 368} /> - </div> - ); - } private _renderTokenCloud(): React.ReactNode { const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; return ( @@ -528,48 +374,16 @@ export class Landing extends React.Component<LandingProps, LandingState> { </div> ); } - private _renderAssetTypes(): React.ReactNode { - const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; - const assetTypes: AssetType[] = [ - { - title: this.props.translate.get(Key.Currency, Deco.Cap), - imageUrl: '/images/landing/currency.png', - }, - { - title: this.props.translate.get(Key.TraditionalAssets, Deco.Cap), - imageUrl: '/images/landing/stocks.png', - style: { - paddingLeft: isSmallScreen ? 41 : 56, - paddingRight: isSmallScreen ? 41 : 56, - }, - }, - { - title: this.props.translate.get(Key.DigitalGoods, Deco.Cap), - imageUrl: '/images/landing/digital_goods.png', - }, - ]; - const assets = _.map(assetTypes, (assetType: AssetType) => { - const style = _.isUndefined(assetType.style) ? {} : assetType.style; - return ( - <div key={`asset-${assetType.title}`} className="center" style={{ opacity: 0.8, ...style }}> - <div> - <img src={assetType.imageUrl} height="80" /> - </div> - <div - style={{ - fontFamily: 'Roboto Mono', - fontSize: 13.5, - fontWeight: 400, - color: colors.darkestGrey, - lineHeight: 1.4, - }} - > - {assetType.title} - </div> - </div> - ); - }); - return assets; + private _renderMissionAndValuesButton(): React.ReactNode { + return ( + <a + href={constants.URL_MISSION_AND_VALUES_BLOG_POST} + target="_blank" + className="inline-block text-decoration-none" + > + <CallToAction>{this.props.translate.get(Key.OurMissionAndValues, Deco.CapWords)}</CallToAction> + </a> + ); } private _renderInfoBoxes(): React.ReactNode { const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; @@ -586,27 +400,34 @@ export class Landing extends React.Component<LandingProps, LandingState> { description: this.props.translate.get(Key.BenefitOneDescription, Deco.Cap), imageUrl: '/images/landing/distributed_network.png', classNames: '', + maxWidth: 160, }, { title: this.props.translate.get(Key.BenefitTwoTitle, Deco.Cap), description: this.props.translate.get(Key.BenefitTwoDescription, Deco.Cap), imageUrl: '/images/landing/liquidity.png', classNames: 'mx-auto', + maxWidth: 160, }, { title: this.props.translate.get(Key.BenefitThreeTitle, Deco.Cap), description: this.props.translate.get(Key.BenefitThreeDescription, Deco.Cap), - imageUrl: '/images/landing/open_source.png', + imageUrl: '/images/landing/exchange_everywhere.png', classNames: 'right', + maxWidth: 130, }, ]; const boxes = _.map(boxContents, (boxContent: BoxContent) => { return ( <div key={`box-${boxContent.title}`} className="col lg-col-4 md-col-4 col-12 sm-pb4"> <div className={`center sm-mx-auto ${!isSmallScreen && boxContent.classNames}`} style={boxStyle}> - <div> - <img src={boxContent.imageUrl} style={{ height: 210 }} /> - </div> + <Container className="flex items-center" height="210px"> + <img + className="mx-auto" + src={boxContent.imageUrl} + style={{ height: 'auto', maxWidth: boxContent.maxWidth }} + /> + </Container> <div className="h3" style={{ color: 'black', fontFamily: 'Roboto Mono' }}> {boxContent.title} </div> @@ -617,15 +438,9 @@ export class Landing extends React.Component<LandingProps, LandingState> { </div> ); }); - const titleStyle: React.CSSProperties = { - fontFamily: 'Roboto Mono', - color: colors.grey, - fontWeight: 300, - letterSpacing: 3, - }; return ( <div className="clearfix" style={{ backgroundColor: colors.heroGrey }}> - <div className="center pb3 pt4" style={titleStyle}> + <div className="center pb3 pt4" style={TITLE_STYLE}> {this.props.translate.get(Key.BenefitsHeader, Deco.Upper)} </div> <div className="mx-auto pb4 sm-mt2 clearfix" style={{ maxWidth: '60em' }}> @@ -634,53 +449,92 @@ export class Landing extends React.Component<LandingProps, LandingState> { </div> ); } - private _renderUseCases(): React.ReactNode { + private _getUseCases(): UseCase[] { const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; - - const useCases: UseCase[] = [ - { - imageUrl: '/images/landing/governance_icon.png', - type: this.props.translate.get(Key.DecentralizedGovernance, Deco.Upper), - description: this.props.translate.get(Key.DecentralizedGovernanceDescription, Deco.Cap), - projectIconUrls: ['/images/landing/aragon.png'], - classNames: 'lg-px2 md-px2', - }, - { - imageUrl: '/images/landing/prediction_market_icon.png', - type: this.props.translate.get(Key.PredictionMarkets, Deco.Upper), - description: this.props.translate.get(Key.PredictionMarketsDescription, Deco.Cap), - projectIconUrls: ['/images/landing/augur.png'], - classNames: 'lg-px2 md-px2', - }, - { - imageUrl: '/images/landing/stable_tokens_icon.png', - type: this.props.translate.get(Key.StableTokens, Deco.Upper), - description: this.props.translate.get(Key.StableTokensDescription, Deco.Cap), - projectIconUrls: ['/images/landing/maker.png'], - classNames: 'lg-px2 md-px2', - }, - { - imageUrl: '/images/landing/loans_icon.png', - type: this.props.translate.get(Key.DecentralizedLoans, Deco.Upper), - description: this.props.translate.get(Key.DecentralizedLoansDescription, Deco.Cap), - projectIconUrls: ['/images/landing/dharma.png', '/images/landing/lendroid.png'], - classNames: 'lg-pr2 md-pr2 lg-col-6 md-col-6', - style: { - width: 291, - float: 'right', - marginTop: !isSmallScreen ? 38 : 0, + const isEnglish = this.props.translate.getLanguage() === Language.English; + if (isEnglish) { + return [ + { + imageUrl: '/images/landing/governance_icon.png', + type: this.props.translate.get(Key.GamingAndCollectables, Deco.Upper), + description: this.props.translate.get(Key.GamingAndCollectablesDescription, Deco.Cap), + classNames: 'lg-px2 md-px2', }, - }, - { - imageUrl: '/images/landing/fund_management_icon.png', - type: this.props.translate.get(Key.FundManagement, Deco.Upper), - description: this.props.translate.get(Key.FundManagementDescription, Deco.Cap), - projectIconUrls: ['/images/landing/melonport.png'], - classNames: 'lg-pl2 md-pl2 lg-col-6 md-col-6', - style: { width: 291, marginTop: !isSmallScreen ? 38 : 0 }, - }, - ]; - + { + imageUrl: '/images/landing/prediction_market_icon.png', + type: this.props.translate.get(Key.PredictionMarkets, Deco.Upper), + description: this.props.translate.get(Key.PredictionMarketsDescription, Deco.Cap), + classNames: 'lg-px2 md-px2', + }, + { + imageUrl: '/images/landing/fund_management_icon.png', + type: this.props.translate.get(Key.OrderBooks, Deco.Upper), + description: this.props.translate.get(Key.OrderBooksDescription, Deco.Cap), + classNames: 'lg-px2 md-px2', + }, + { + imageUrl: '/images/landing/loans_icon.png', + type: this.props.translate.get(Key.DecentralizedLoans, Deco.Upper), + description: this.props.translate.get(Key.DecentralizedLoansDescription, Deco.Cap), + classNames: 'lg-pr2 md-pr2 lg-col-6 md-col-6', + style: { + width: 291, + float: 'right', + marginTop: !isSmallScreen ? 38 : 0, + }, + }, + { + imageUrl: '/images/landing/stable_tokens_icon.png', + type: this.props.translate.get(Key.StableTokens, Deco.Upper), + description: this.props.translate.get(Key.StableTokensDescription, Deco.Cap), + classNames: 'lg-pl2 md-pl2 lg-col-6 md-col-6', + style: { width: 291, marginTop: !isSmallScreen ? 38 : 0 }, + }, + ]; + } else { + return [ + { + imageUrl: '/images/landing/governance_icon.png', + type: this.props.translate.get(Key.DecentralizedGovernance, Deco.Upper), + description: this.props.translate.get(Key.DecentralizedGovernanceDescription, Deco.Cap), + classNames: 'lg-px2 md-px2', + }, + { + imageUrl: '/images/landing/prediction_market_icon.png', + type: this.props.translate.get(Key.PredictionMarkets, Deco.Upper), + description: this.props.translate.get(Key.PredictionMarketsDescription, Deco.Cap), + classNames: 'lg-px2 md-px2', + }, + { + imageUrl: '/images/landing/stable_tokens_icon.png', + type: this.props.translate.get(Key.StableTokens, Deco.Upper), + description: this.props.translate.get(Key.StableTokensDescription, Deco.Cap), + classNames: 'lg-px2 md-px2', + }, + { + imageUrl: '/images/landing/loans_icon.png', + type: this.props.translate.get(Key.DecentralizedLoans, Deco.Upper), + description: this.props.translate.get(Key.DecentralizedLoansDescription, Deco.Cap), + classNames: 'lg-pr2 md-pr2 lg-col-6 md-col-6', + style: { + width: 291, + float: 'right', + marginTop: !isSmallScreen ? 38 : 0, + }, + }, + { + imageUrl: '/images/landing/fund_management_icon.png', + type: this.props.translate.get(Key.FundManagement, Deco.Upper), + description: this.props.translate.get(Key.FundManagementDescription, Deco.Cap), + classNames: 'lg-pl2 md-pl2 lg-col-6 md-col-6', + style: { width: 291, marginTop: !isSmallScreen ? 38 : 0 }, + }, + ]; + } + } + private _renderUseCases(): React.ReactNode { + const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm; + const useCases = this._getUseCases(); const cases = _.map(useCases, (useCase: UseCase) => { const style = _.isUndefined(useCase.style) || isSmallScreen ? {} : useCase.style; const useCaseBoxStyle = { @@ -715,7 +569,7 @@ export class Landing extends React.Component<LandingProps, LandingState> { lineHeight: 1.5, fontSize: 14, overflow: 'hidden', - height: 104, + height: 124, }} > {useCase.description} @@ -725,7 +579,10 @@ export class Landing extends React.Component<LandingProps, LandingState> { ); }); return ( - <div className="clearfix pb4 lg-pt2 md-pt2 sm-pt4" style={{ backgroundColor: colors.heroGrey }}> + <div className="clearfix py4" style={{ backgroundColor: colors.heroGrey }}> + <div className="center h4 pb3 lg-pl0 md-pl3 sm-pl2" style={TITLE_STYLE}> + {this.props.translate.get(Key.UseCasesHeader, Deco.Upper)} + </div> <div className="mx-auto pb4 pt3 mt1 sm-mt2 clearfix" style={{ maxWidth: '67em' }}> {cases} </div> diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts index c637171dd..6ab17e261 100644 --- a/packages/website/ts/types.ts +++ b/packages/website/ts/types.ts @@ -415,6 +415,7 @@ export enum Key { OffChainOnChainDescription = 'OFFCHAIN_ONCHAIN_DESCRIPTION', RelayersHeader = 'RELAYERS_HEADER', BenefitsHeader = 'BENEFITS_HEADER', + UseCasesHeader = 'USE_CASES_HEADER', BenefitOneTitle = 'BENEFIT_ONE_TITLE', BenefitOneDescription = 'BENEFIT_ONE_DESCRIPTION', BenefitTwoTitle = 'BENEFIT_TWO_TITLE', @@ -436,6 +437,10 @@ export enum Key { DecentralizedLoansDescription = 'DECENTRALIZED_LOANS_DESCRIPTION', FundManagement = 'FUND_MANAGEMENT', FundManagementDescription = 'FUND_MANAGEMENT_DESCRIPTION', + GamingAndCollectables = 'GAMING_AND_COLLECTABLES', + GamingAndCollectablesDescription = 'GAMING_AND_COLLECTABLES_DESCRIPTION', + OrderBooks = 'ORDER_BOOKS', + OrderBooksDescription = 'ORDER_BOOKS_DESCRIPTION', FinalCallToAction = 'FINAL_CALL_TO_ACTION', Documentation = 'DOCUMENTATION', Community = 'COMMUNITY', @@ -468,6 +473,7 @@ export enum Key { Home = 'HOME', RocketChat = 'ROCKETCHAT', TradeCallToAction = 'TRADE_CALL_TO_ACTION', + OurMissionAndValues = 'OUR_MISSION_AND_VALUES', } export enum SmartContractDocSections { diff --git a/packages/website/tsconfig.json b/packages/website/tsconfig.json index 34171b51e..6421cd459 100644 --- a/packages/website/tsconfig.json +++ b/packages/website/tsconfig.json @@ -8,7 +8,12 @@ "allowJs": true, "strictNullChecks": false, "noImplicitThis": false, + // tsconfig.json at the monorepo root contains some options required for + // project references which do not work for website. We override those + // options here. "declaration": false, + "declarationMap": false, + "composite": false, "paths": { "*": ["node_modules/@types/*", "*"] } |