Compare commits
	
		
			5 Commits
		
	
	
		
			@0x/protoc
			...
			@0x/contra
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 2a6d66cc2a | ||
|  | b02992a373 | ||
|  | 92ad924965 | ||
|  | 138383e95c | ||
|  | 0487cb7d39 | 
| @@ -1,16 +1,7 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1617311315, | ||||
|         "version": "3.7.9", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1616005394, | ||||
|         "version": "3.7.8", | ||||
|         "timestamp": 1615932869, | ||||
|         "version": "3.7.8-multiplex.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|   | ||||
| @@ -5,11 +5,7 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v3.7.9 - _April 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.7.8 - _March 17, 2021_ | ||||
| ## v3.7.8-multiplex.0 - _March 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-asset-proxy", | ||||
|     "version": "3.7.9", | ||||
|     "version": "3.7.8-multiplex.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -52,10 +52,10 @@ | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/protocol", | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.4.21", | ||||
|         "@0x/contract-wrappers": "^13.15.0", | ||||
|         "@0x/contract-wrappers": "^13.14.0-multiplex", | ||||
|         "@0x/contracts-gen": "^2.0.32", | ||||
|         "@0x/contracts-test-utils": "^5.3.24", | ||||
|         "@0x/contracts-utils": "^4.7.6", | ||||
|         "@0x/contracts-test-utils": "^5.3.23-multiplex.0", | ||||
|         "@0x/contracts-utils": "^4.7.5-multiplex.0", | ||||
|         "@0x/dev-utils": "^4.2.1", | ||||
|         "@0x/sol-compiler": "^4.6.1", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
| @@ -76,15 +76,15 @@ | ||||
|         "truffle": "^5.0.32", | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.2.18", | ||||
|         "@0x/contracts-erc1155": "^2.1.27", | ||||
|         "@0x/contracts-erc20": "^3.3.6", | ||||
|         "@0x/contracts-erc721": "^3.1.27", | ||||
|         "@0x/contracts-exchange-libs": "^4.3.27", | ||||
|         "@0x/order-utils": "^10.4.19", | ||||
|         "@0x/contracts-erc1155": "^2.1.26-multiplex.0", | ||||
|         "@0x/contracts-erc20": "^3.3.5-multiplex.0", | ||||
|         "@0x/contracts-erc721": "^3.1.26-multiplex.0", | ||||
|         "@0x/contracts-exchange-libs": "^4.3.26-multiplex.0", | ||||
|         "@0x/order-utils": "^10.4.18-multiplex.0", | ||||
|         "@0x/types": "^3.3.1", | ||||
|         "@0x/typescript-typings": "^5.1.6", | ||||
|         "@0x/utils": "^6.2.0", | ||||
|   | ||||
							
								
								
									
										354
									
								
								contracts/asset-proxy/test/dex_forwarder_bridge.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										354
									
								
								contracts/asset-proxy/test/dex_forwarder_bridge.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,354 @@ | ||||
| import { ContractTxFunctionObj } from '@0x/contract-wrappers'; | ||||
| import { | ||||
|     blockchainTests, | ||||
|     constants, | ||||
|     expect, | ||||
|     filterLogsToArguments, | ||||
|     getRandomInteger, | ||||
|     randomAddress, | ||||
|     shortZip, | ||||
| } from '@0x/contracts-test-utils'; | ||||
| import { BigNumber, hexUtils, NULL_ADDRESS } from '@0x/utils'; | ||||
| import { DecodedLogs } from 'ethereum-types'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| import { DexForwarderBridgeCall, dexForwarderBridgeDataEncoder } from '../src/dex_forwarder_bridge'; | ||||
|  | ||||
| import { artifacts } from './artifacts'; | ||||
| import { | ||||
|     TestDexForwarderBridgeBridgeTransferFromCalledEventArgs as BtfCalledEventArgs, | ||||
|     TestDexForwarderBridgeContract, | ||||
|     TestDexForwarderBridgeEvents as TestEvents, | ||||
| } from './wrappers'; | ||||
|  | ||||
| const { ZERO_AMOUNT } = constants; | ||||
|  | ||||
| blockchainTests.resets('DexForwarderBridge unit tests', env => { | ||||
|     let testContract: TestDexForwarderBridgeContract; | ||||
|     let inputToken: string; | ||||
|     let outputToken: string; | ||||
|     const BRIDGE_SUCCESS = '0xdc1600f3'; | ||||
|     const BRIDGE_FAILURE = '0xffffffff'; | ||||
|     const BRIDGE_REVERT_ERROR = 'oopsie'; | ||||
|     const NOT_AUTHORIZED_REVERT = 'DexForwarderBridge/SENDER_NOT_AUTHORIZED'; | ||||
|     const DEFAULTS = { | ||||
|         toAddress: randomAddress(), | ||||
|     }; | ||||
|  | ||||
|     before(async () => { | ||||
|         testContract = await TestDexForwarderBridgeContract.deployFrom0xArtifactAsync( | ||||
|             artifacts.TestDexForwarderBridge, | ||||
|             env.provider, | ||||
|             env.txDefaults, | ||||
|             artifacts, | ||||
|         ); | ||||
|         // Create test tokens. | ||||
|         [inputToken, outputToken] = [ | ||||
|             await callAndTransactAsync(testContract.createToken()), | ||||
|             await callAndTransactAsync(testContract.createToken()), | ||||
|         ]; | ||||
|         await callAndTransactAsync(testContract.setAuthorized(env.txDefaults.from as string)); | ||||
|     }); | ||||
|  | ||||
|     async function callAndTransactAsync<TResult>(fnCall: ContractTxFunctionObj<TResult>): Promise<TResult> { | ||||
|         const result = await fnCall.callAsync(); | ||||
|         await fnCall.awaitTransactionSuccessAsync({}, { shouldValidate: false }); | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     function getRandomBridgeCall( | ||||
|         bridgeAddress: string, | ||||
|         fields: Partial<DexForwarderBridgeCall> = {}, | ||||
|     ): DexForwarderBridgeCall { | ||||
|         return { | ||||
|             target: bridgeAddress, | ||||
|             inputTokenAmount: getRandomInteger(1, '100e18'), | ||||
|             outputTokenAmount: getRandomInteger(1, '100e18'), | ||||
|             bridgeData: hexUtils.leftPad(inputToken), | ||||
|             ...fields, | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     describe('bridgeTransferFrom()', () => { | ||||
|         let goodBridgeCalls: DexForwarderBridgeCall[]; | ||||
|         let revertingBridgeCall: DexForwarderBridgeCall; | ||||
|         let failingBridgeCall: DexForwarderBridgeCall; | ||||
|         let allBridgeCalls: DexForwarderBridgeCall[]; | ||||
|         let totalFillableOutputAmount: BigNumber; | ||||
|         let totalFillableInputAmount: BigNumber; | ||||
|         let recipientOutputBalance: BigNumber; | ||||
|  | ||||
|         beforeEach(async () => { | ||||
|             goodBridgeCalls = []; | ||||
|             for (let i = 0; i < 4; ++i) { | ||||
|                 goodBridgeCalls.push(await createBridgeCallAsync({ returnCode: BRIDGE_SUCCESS })); | ||||
|             } | ||||
|             revertingBridgeCall = await createBridgeCallAsync({ revertError: BRIDGE_REVERT_ERROR }); | ||||
|             failingBridgeCall = await createBridgeCallAsync({ returnCode: BRIDGE_FAILURE }); | ||||
|             allBridgeCalls = _.shuffle([failingBridgeCall, revertingBridgeCall, ...goodBridgeCalls]); | ||||
|  | ||||
|             totalFillableInputAmount = BigNumber.sum(...goodBridgeCalls.map(c => c.inputTokenAmount)); | ||||
|             totalFillableOutputAmount = BigNumber.sum(...goodBridgeCalls.map(c => c.outputTokenAmount)); | ||||
|  | ||||
|             // Grant the taker some output tokens. | ||||
|             await testContract.setTokenBalance( | ||||
|                 outputToken, | ||||
|                 DEFAULTS.toAddress, | ||||
|                 (recipientOutputBalance = getRandomInteger(1, '100e18')), | ||||
|             ); | ||||
|         }); | ||||
|  | ||||
|         async function setForwarderInputBalanceAsync(amount: BigNumber): Promise<void> { | ||||
|             await testContract | ||||
|                 .setTokenBalance(inputToken, testContract.address, amount) | ||||
|                 .awaitTransactionSuccessAsync({}, { shouldValidate: false }); | ||||
|         } | ||||
|  | ||||
|         async function createBridgeCallAsync( | ||||
|             opts: Partial<{ | ||||
|                 returnCode: string; | ||||
|                 revertError: string; | ||||
|                 callFields: Partial<DexForwarderBridgeCall>; | ||||
|                 outputFillAmount: BigNumber; | ||||
|             }>, | ||||
|         ): Promise<DexForwarderBridgeCall> { | ||||
|             const { returnCode, revertError, callFields, outputFillAmount } = { | ||||
|                 returnCode: BRIDGE_SUCCESS, | ||||
|                 revertError: '', | ||||
|                 ...opts, | ||||
|             }; | ||||
|             const bridge = await callAndTransactAsync(testContract.createBridge(returnCode, revertError)); | ||||
|             const call = getRandomBridgeCall(bridge, callFields); | ||||
|             await testContract | ||||
|                 .setBridgeTransferAmount(call.target, outputFillAmount || call.outputTokenAmount) | ||||
|                 .awaitTransactionSuccessAsync({}, { shouldValidate: false }); | ||||
|             return call; | ||||
|         } | ||||
|  | ||||
|         async function callBridgeTransferFromAsync(opts: { | ||||
|             bridgeData: string; | ||||
|             sellAmount?: BigNumber; | ||||
|             buyAmount?: BigNumber; | ||||
|         }): Promise<DecodedLogs> { | ||||
|             // Fund the forwarder with input tokens to sell. | ||||
|             await setForwarderInputBalanceAsync(opts.sellAmount || totalFillableInputAmount); | ||||
|             const call = testContract.bridgeTransferFrom( | ||||
|                 outputToken, | ||||
|                 testContract.address, | ||||
|                 DEFAULTS.toAddress, | ||||
|                 opts.buyAmount || totalFillableOutputAmount, | ||||
|                 opts.bridgeData, | ||||
|             ); | ||||
|             const returnCode = await call.callAsync(); | ||||
|             if (returnCode !== BRIDGE_SUCCESS) { | ||||
|                 throw new Error('Expected BRIDGE_SUCCESS'); | ||||
|             } | ||||
|             const receipt = await call.awaitTransactionSuccessAsync({}, { shouldValidate: false }); | ||||
|             // tslint:disable-next-line: no-unnecessary-type-assertion | ||||
|             return receipt.logs as DecodedLogs; | ||||
|         } | ||||
|  | ||||
|         it('succeeds with no bridge calls and no input balance', async () => { | ||||
|             const bridgeData = dexForwarderBridgeDataEncoder.encode({ | ||||
|                 inputToken, | ||||
|                 calls: [], | ||||
|             }); | ||||
|             await callBridgeTransferFromAsync({ bridgeData, sellAmount: ZERO_AMOUNT }); | ||||
|         }); | ||||
|  | ||||
|         it('succeeds with bridge calls and no input balance', async () => { | ||||
|             const bridgeData = dexForwarderBridgeDataEncoder.encode({ | ||||
|                 inputToken, | ||||
|                 calls: allBridgeCalls, | ||||
|             }); | ||||
|             await callBridgeTransferFromAsync({ bridgeData, sellAmount: ZERO_AMOUNT }); | ||||
|         }); | ||||
|  | ||||
|         it('succeeds with no bridge calls and an input balance', async () => { | ||||
|             const bridgeData = dexForwarderBridgeDataEncoder.encode({ | ||||
|                 inputToken, | ||||
|                 calls: [], | ||||
|             }); | ||||
|             await callBridgeTransferFromAsync({ | ||||
|                 bridgeData, | ||||
|                 sellAmount: new BigNumber(1), | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('succeeds if entire input token balance is not consumed', async () => { | ||||
|             const bridgeData = dexForwarderBridgeDataEncoder.encode({ | ||||
|                 inputToken, | ||||
|                 calls: allBridgeCalls, | ||||
|             }); | ||||
|             await callBridgeTransferFromAsync({ | ||||
|                 bridgeData, | ||||
|                 sellAmount: totalFillableInputAmount.plus(1), | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('fails if not authorized', async () => { | ||||
|             const calls = goodBridgeCalls.slice(0, 1); | ||||
|             const bridgeData = dexForwarderBridgeDataEncoder.encode({ | ||||
|                 inputToken, | ||||
|                 calls, | ||||
|             }); | ||||
|             await callAndTransactAsync(testContract.setAuthorized(NULL_ADDRESS)); | ||||
|             return expect(callBridgeTransferFromAsync({ bridgeData, sellAmount: new BigNumber(1) })).to.revertWith( | ||||
|                 NOT_AUTHORIZED_REVERT, | ||||
|             ); | ||||
|         }); | ||||
|  | ||||
|         it('succeeds with one bridge call', async () => { | ||||
|             const calls = goodBridgeCalls.slice(0, 1); | ||||
|             const bridgeData = dexForwarderBridgeDataEncoder.encode({ | ||||
|                 inputToken, | ||||
|                 calls, | ||||
|             }); | ||||
|             await callBridgeTransferFromAsync({ bridgeData, sellAmount: calls[0].inputTokenAmount }); | ||||
|         }); | ||||
|  | ||||
|         it('succeeds with many bridge calls', async () => { | ||||
|             const calls = goodBridgeCalls; | ||||
|             const bridgeData = dexForwarderBridgeDataEncoder.encode({ | ||||
|                 inputToken, | ||||
|                 calls, | ||||
|             }); | ||||
|             await callBridgeTransferFromAsync({ bridgeData }); | ||||
|         }); | ||||
|  | ||||
|         it('swallows a failing bridge call', async () => { | ||||
|             const calls = _.shuffle([...goodBridgeCalls, failingBridgeCall]); | ||||
|             const bridgeData = dexForwarderBridgeDataEncoder.encode({ | ||||
|                 inputToken, | ||||
|                 calls, | ||||
|             }); | ||||
|             await callBridgeTransferFromAsync({ bridgeData }); | ||||
|         }); | ||||
|  | ||||
|         it('consumes input tokens for output tokens', async () => { | ||||
|             const calls = allBridgeCalls; | ||||
|             const bridgeData = dexForwarderBridgeDataEncoder.encode({ | ||||
|                 inputToken, | ||||
|                 calls, | ||||
|             }); | ||||
|             await callBridgeTransferFromAsync({ bridgeData }); | ||||
|             const currentBridgeInputBalance = await testContract | ||||
|                 .balanceOf(inputToken, testContract.address) | ||||
|                 .callAsync(); | ||||
|             expect(currentBridgeInputBalance).to.bignumber.eq(0); | ||||
|             const currentRecipientOutputBalance = await testContract | ||||
|                 .balanceOf(outputToken, DEFAULTS.toAddress) | ||||
|                 .callAsync(); | ||||
|             expect(currentRecipientOutputBalance).to.bignumber.eq(totalFillableOutputAmount); | ||||
|         }); | ||||
|  | ||||
|         it("transfers only up to each call's input amount to each bridge", async () => { | ||||
|             const calls = goodBridgeCalls; | ||||
|             const bridgeData = dexForwarderBridgeDataEncoder.encode({ | ||||
|                 inputToken, | ||||
|                 calls, | ||||
|             }); | ||||
|             const logs = await callBridgeTransferFromAsync({ bridgeData }); | ||||
|             const btfs = filterLogsToArguments<BtfCalledEventArgs>(logs, TestEvents.BridgeTransferFromCalled); | ||||
|             for (const [call, btf] of shortZip(goodBridgeCalls, btfs)) { | ||||
|                 expect(btf.inputTokenBalance).to.bignumber.eq(call.inputTokenAmount); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         it('transfers only up to outstanding sell amount to each bridge', async () => { | ||||
|             // Prepend an extra bridge call. | ||||
|             const calls = [ | ||||
|                 await createBridgeCallAsync({ | ||||
|                     callFields: { | ||||
|                         inputTokenAmount: new BigNumber(1), | ||||
|                         outputTokenAmount: new BigNumber(1), | ||||
|                     }, | ||||
|                 }), | ||||
|                 ...goodBridgeCalls, | ||||
|             ]; | ||||
|             const bridgeData = dexForwarderBridgeDataEncoder.encode({ | ||||
|                 inputToken, | ||||
|                 calls, | ||||
|             }); | ||||
|             const logs = await callBridgeTransferFromAsync({ bridgeData }); | ||||
|             const btfs = filterLogsToArguments<BtfCalledEventArgs>(logs, TestEvents.BridgeTransferFromCalled); | ||||
|             expect(btfs).to.be.length(goodBridgeCalls.length + 1); | ||||
|             // The last call will receive 1 less token. | ||||
|             const lastCall = calls.slice(-1)[0]; | ||||
|             const lastBtf = btfs.slice(-1)[0]; | ||||
|             expect(lastBtf.inputTokenBalance).to.bignumber.eq(lastCall.inputTokenAmount.minus(1)); | ||||
|         }); | ||||
|  | ||||
|         it('recoups funds from a bridge that fails', async () => { | ||||
|             // Prepend a call that will take the whole input amount but will | ||||
|             // fail. | ||||
|             const badCall = await createBridgeCallAsync({ | ||||
|                 callFields: { inputTokenAmount: totalFillableInputAmount }, | ||||
|                 returnCode: BRIDGE_FAILURE, | ||||
|             }); | ||||
|             const calls = [badCall, ...goodBridgeCalls]; | ||||
|             const bridgeData = dexForwarderBridgeDataEncoder.encode({ | ||||
|                 inputToken, | ||||
|                 calls, | ||||
|             }); | ||||
|             const logs = await callBridgeTransferFromAsync({ bridgeData }); | ||||
|             const btfs = filterLogsToArguments<BtfCalledEventArgs>(logs, TestEvents.BridgeTransferFromCalled); | ||||
|             expect(btfs).to.be.length(goodBridgeCalls.length); | ||||
|         }); | ||||
|  | ||||
|         it('recoups funds from a bridge that reverts', async () => { | ||||
|             // Prepend a call that will take the whole input amount but will | ||||
|             // revert. | ||||
|             const badCall = await createBridgeCallAsync({ | ||||
|                 callFields: { inputTokenAmount: totalFillableInputAmount }, | ||||
|                 revertError: BRIDGE_REVERT_ERROR, | ||||
|             }); | ||||
|             const calls = [badCall, ...goodBridgeCalls]; | ||||
|             const bridgeData = dexForwarderBridgeDataEncoder.encode({ | ||||
|                 inputToken, | ||||
|                 calls, | ||||
|             }); | ||||
|             const logs = await callBridgeTransferFromAsync({ bridgeData }); | ||||
|             const btfs = filterLogsToArguments<BtfCalledEventArgs>(logs, TestEvents.BridgeTransferFromCalled); | ||||
|             expect(btfs).to.be.length(goodBridgeCalls.length); | ||||
|         }); | ||||
|  | ||||
|         it('recoups funds from a bridge that under-pays', async () => { | ||||
|             // Prepend a call that will take the whole input amount but will | ||||
|             // underpay the output amount.. | ||||
|             const badCall = await createBridgeCallAsync({ | ||||
|                 callFields: { | ||||
|                     inputTokenAmount: totalFillableInputAmount, | ||||
|                     outputTokenAmount: new BigNumber(2), | ||||
|                 }, | ||||
|                 outputFillAmount: new BigNumber(1), | ||||
|             }); | ||||
|             const calls = [badCall, ...goodBridgeCalls]; | ||||
|             const bridgeData = dexForwarderBridgeDataEncoder.encode({ | ||||
|                 inputToken, | ||||
|                 calls, | ||||
|             }); | ||||
|             const logs = await callBridgeTransferFromAsync({ bridgeData }); | ||||
|             const btfs = filterLogsToArguments<BtfCalledEventArgs>(logs, TestEvents.BridgeTransferFromCalled); | ||||
|             expect(btfs).to.be.length(goodBridgeCalls.length); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('executeBridgeCall()', () => { | ||||
|         it('cannot be called externally', async () => { | ||||
|             return expect( | ||||
|                 testContract | ||||
|                     .executeBridgeCall( | ||||
|                         randomAddress(), | ||||
|                         randomAddress(), | ||||
|                         randomAddress(), | ||||
|                         randomAddress(), | ||||
|                         new BigNumber(1), | ||||
|                         new BigNumber(1), | ||||
|                         constants.NULL_BYTES, | ||||
|                     ) | ||||
|                     .callAsync(), | ||||
|             ).to.revertWith('DexForwarderBridge/ONLY_SELF'); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| @@ -1,16 +1,7 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1617311315, | ||||
|         "version": "1.1.27", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1616005394, | ||||
|         "version": "1.1.26", | ||||
|         "timestamp": 1615932869, | ||||
|         "version": "1.1.26-multiplex.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|   | ||||
| @@ -5,11 +5,7 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v1.1.27 - _April 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v1.1.26 - _March 17, 2021_ | ||||
| ## v1.1.26-multiplex.0 - _March 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-broker", | ||||
|     "version": "1.1.27", | ||||
|     "version": "1.1.26-multiplex.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -52,14 +52,14 @@ | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions", | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.4.21", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.9", | ||||
|         "@0x/contracts-erc20": "^3.3.6", | ||||
|         "@0x/contracts-erc721": "^3.1.27", | ||||
|         "@0x/contracts-exchange": "^3.2.28", | ||||
|         "@0x/contracts-exchange-libs": "^4.3.27", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0", | ||||
|         "@0x/contracts-erc20": "^3.3.5-multiplex.0", | ||||
|         "@0x/contracts-erc721": "^3.1.26-multiplex.0", | ||||
|         "@0x/contracts-exchange": "^3.2.27-multiplex.0", | ||||
|         "@0x/contracts-exchange-libs": "^4.3.26-multiplex.0", | ||||
|         "@0x/contracts-gen": "^2.0.32", | ||||
|         "@0x/contracts-test-utils": "^5.3.24", | ||||
|         "@0x/contracts-utils": "^4.7.6", | ||||
|         "@0x/contracts-test-utils": "^5.3.23-multiplex.0", | ||||
|         "@0x/contracts-utils": "^4.7.5-multiplex.0", | ||||
|         "@0x/sol-compiler": "^4.6.1", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
|         "@0x/tslint-config": "^4.1.3", | ||||
| @@ -81,11 +81,11 @@ | ||||
|         "truffle": "^5.0.32", | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.2.18", | ||||
|         "@0x/order-utils": "^10.4.19", | ||||
|         "@0x/order-utils": "^10.4.18-multiplex.0", | ||||
|         "@0x/typescript-typings": "^5.1.6", | ||||
|         "@0x/utils": "^6.2.0", | ||||
|         "ethereum-types": "^3.4.0" | ||||
|   | ||||
| @@ -1,16 +1,7 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1617311315, | ||||
|         "version": "3.1.28", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1616005394, | ||||
|         "version": "3.1.27", | ||||
|         "timestamp": 1615932869, | ||||
|         "version": "3.1.27-multiplex.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|   | ||||
| @@ -5,11 +5,7 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v3.1.28 - _April 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.1.27 - _March 17, 2021_ | ||||
| ## v3.1.27-multiplex.0 - _March 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-coordinator", | ||||
|     "version": "3.1.28", | ||||
|     "version": "3.1.27-multiplex.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -53,12 +53,12 @@ | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions", | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.4.21", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.9", | ||||
|         "@0x/contracts-dev-utils": "^1.3.26", | ||||
|         "@0x/contracts-erc20": "^3.3.6", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0", | ||||
|         "@0x/contracts-dev-utils": "^1.3.25-multiplex.0", | ||||
|         "@0x/contracts-erc20": "^3.3.5-multiplex.0", | ||||
|         "@0x/contracts-gen": "^2.0.32", | ||||
|         "@0x/dev-utils": "^4.2.1", | ||||
|         "@0x/order-utils": "^10.4.19", | ||||
|         "@0x/order-utils": "^10.4.18-multiplex.0", | ||||
|         "@0x/sol-compiler": "^4.6.1", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
|         "@0x/tslint-config": "^4.1.3", | ||||
| @@ -79,15 +79,15 @@ | ||||
|         "truffle": "^5.0.32", | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/assert": "^3.0.21", | ||||
|         "@0x/base-contract": "^6.2.18", | ||||
|         "@0x/contract-addresses": "^6.0.0", | ||||
|         "@0x/contracts-exchange": "^3.2.28", | ||||
|         "@0x/contracts-test-utils": "^5.3.24", | ||||
|         "@0x/contracts-utils": "^4.7.6", | ||||
|         "@0x/contract-addresses": "^5.11.0", | ||||
|         "@0x/contracts-exchange": "^3.2.27-multiplex.0", | ||||
|         "@0x/contracts-test-utils": "^5.3.23-multiplex.0", | ||||
|         "@0x/contracts-utils": "^4.7.5-multiplex.0", | ||||
|         "@0x/json-schemas": "^5.4.1", | ||||
|         "@0x/types": "^3.3.1", | ||||
|         "@0x/typescript-typings": "^5.1.6", | ||||
|   | ||||
| @@ -1,16 +1,7 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1617311315, | ||||
|         "version": "1.3.26", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1616005394, | ||||
|         "version": "1.3.25", | ||||
|         "timestamp": 1615932869, | ||||
|         "version": "1.3.25-multiplex.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|   | ||||
| @@ -5,11 +5,7 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v1.3.26 - _April 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v1.3.25 - _March 17, 2021_ | ||||
| ## v1.3.25-multiplex.0 - _March 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-dev-utils", | ||||
|     "version": "1.3.26", | ||||
|     "version": "1.3.25-multiplex.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -43,10 +43,10 @@ | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.4.21", | ||||
|         "@0x/assert": "^3.0.21", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.9", | ||||
|         "@0x/contracts-erc20": "^3.3.6", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0", | ||||
|         "@0x/contracts-erc20": "^3.3.5-multiplex.0", | ||||
|         "@0x/contracts-gen": "^2.0.32", | ||||
|         "@0x/contracts-test-utils": "^5.3.24", | ||||
|         "@0x/contracts-test-utils": "^5.3.23-multiplex.0", | ||||
|         "@0x/sol-compiler": "^4.6.1", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
|         "@0x/tslint-config": "^4.1.3", | ||||
| @@ -60,7 +60,7 @@ | ||||
|         "truffle": "^5.0.32", | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.2.18", | ||||
|   | ||||
| @@ -1,16 +1,7 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1617311315, | ||||
|         "version": "2.1.27", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1616005394, | ||||
|         "version": "2.1.26", | ||||
|         "timestamp": 1615932869, | ||||
|         "version": "2.1.26-multiplex.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|   | ||||
| @@ -5,11 +5,7 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v2.1.27 - _April 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v2.1.26 - _March 17, 2021_ | ||||
| ## v2.1.26-multiplex.0 - _March 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-erc1155", | ||||
|     "version": "2.1.27", | ||||
|     "version": "2.1.26-multiplex.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -54,7 +54,7 @@ | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.4.21", | ||||
|         "@0x/contracts-gen": "^2.0.32", | ||||
|         "@0x/contracts-utils": "^4.7.6", | ||||
|         "@0x/contracts-utils": "^4.7.5-multiplex.0", | ||||
|         "@0x/dev-utils": "^4.2.1", | ||||
|         "@0x/sol-compiler": "^4.6.1", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
| @@ -77,11 +77,11 @@ | ||||
|         "truffle": "^5.0.32", | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.2.18", | ||||
|         "@0x/contracts-test-utils": "^5.3.24", | ||||
|         "@0x/contracts-test-utils": "^5.3.23-multiplex.0", | ||||
|         "@0x/utils": "^6.2.0", | ||||
|         "@0x/web3-wrapper": "^7.4.1", | ||||
|         "lodash": "^4.17.11" | ||||
|   | ||||
| @@ -1,16 +1,7 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1617311315, | ||||
|         "version": "3.3.6", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1616005394, | ||||
|         "version": "3.3.5", | ||||
|         "timestamp": 1615932869, | ||||
|         "version": "3.3.5-multiplex.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|   | ||||
| @@ -5,11 +5,7 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v3.3.6 - _April 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.3.5 - _March 17, 2021_ | ||||
| ## v3.3.5-multiplex.0 - _March 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-erc20", | ||||
|     "version": "3.3.6", | ||||
|     "version": "3.3.5-multiplex.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -53,8 +53,8 @@ | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.4.21", | ||||
|         "@0x/contracts-gen": "^2.0.32", | ||||
|         "@0x/contracts-test-utils": "^5.3.24", | ||||
|         "@0x/contracts-utils": "^4.7.6", | ||||
|         "@0x/contracts-test-utils": "^5.3.23-multiplex.0", | ||||
|         "@0x/contracts-utils": "^4.7.5-multiplex.0", | ||||
|         "@0x/dev-utils": "^4.2.1", | ||||
|         "@0x/sol-compiler": "^4.6.1", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
| @@ -79,7 +79,7 @@ | ||||
|         "solhint": "^1.4.1", | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.2.18" | ||||
|   | ||||
| @@ -39,8 +39,8 @@ describe('EtherToken', () => { | ||||
|             artifacts.WETH9, | ||||
|             provider, | ||||
|             { | ||||
|                 ...txDefaults, | ||||
|                 gasPrice, | ||||
|                 ...txDefaults, | ||||
|             }, | ||||
|             artifacts, | ||||
|         ); | ||||
|   | ||||
| @@ -1,16 +1,7 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1617311315, | ||||
|         "version": "3.1.27", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1616005394, | ||||
|         "version": "3.1.26", | ||||
|         "timestamp": 1615932869, | ||||
|         "version": "3.1.26-multiplex.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|   | ||||
| @@ -5,11 +5,7 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v3.1.27 - _April 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.1.26 - _March 17, 2021_ | ||||
| ## v3.1.26-multiplex.0 - _March 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-erc721", | ||||
|     "version": "3.1.27", | ||||
|     "version": "3.1.26-multiplex.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -54,8 +54,8 @@ | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.4.21", | ||||
|         "@0x/contracts-gen": "^2.0.32", | ||||
|         "@0x/contracts-test-utils": "^5.3.24", | ||||
|         "@0x/contracts-utils": "^4.7.6", | ||||
|         "@0x/contracts-test-utils": "^5.3.23-multiplex.0", | ||||
|         "@0x/contracts-utils": "^4.7.5-multiplex.0", | ||||
|         "@0x/dev-utils": "^4.2.1", | ||||
|         "@0x/sol-compiler": "^4.6.1", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
| @@ -81,7 +81,7 @@ | ||||
|         "truffle": "^5.0.32", | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.2.18" | ||||
|   | ||||
| @@ -1,16 +1,7 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1617311315, | ||||
|         "version": "4.2.28", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1616005394, | ||||
|         "version": "4.2.27", | ||||
|         "timestamp": 1615932869, | ||||
|         "version": "4.2.27-multiplex.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|   | ||||
| @@ -5,11 +5,7 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v4.2.28 - _April 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v4.2.27 - _March 17, 2021_ | ||||
| ## v4.2.27-multiplex.0 - _March 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-exchange-forwarder", | ||||
|     "version": "4.2.28", | ||||
|     "version": "4.2.27-multiplex.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -53,18 +53,18 @@ | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions", | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.4.21", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.9", | ||||
|         "@0x/contracts-dev-utils": "^1.3.26", | ||||
|         "@0x/contracts-erc1155": "^2.1.27", | ||||
|         "@0x/contracts-erc20": "^3.3.6", | ||||
|         "@0x/contracts-erc721": "^3.1.27", | ||||
|         "@0x/contracts-exchange": "^3.2.28", | ||||
|         "@0x/contracts-exchange-libs": "^4.3.27", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0", | ||||
|         "@0x/contracts-dev-utils": "^1.3.25-multiplex.0", | ||||
|         "@0x/contracts-erc1155": "^2.1.26-multiplex.0", | ||||
|         "@0x/contracts-erc20": "^3.3.5-multiplex.0", | ||||
|         "@0x/contracts-erc721": "^3.1.26-multiplex.0", | ||||
|         "@0x/contracts-exchange": "^3.2.27-multiplex.0", | ||||
|         "@0x/contracts-exchange-libs": "^4.3.26-multiplex.0", | ||||
|         "@0x/contracts-gen": "^2.0.32", | ||||
|         "@0x/contracts-test-utils": "^5.3.24", | ||||
|         "@0x/contracts-utils": "^4.7.6", | ||||
|         "@0x/contracts-test-utils": "^5.3.23-multiplex.0", | ||||
|         "@0x/contracts-utils": "^4.7.5-multiplex.0", | ||||
|         "@0x/dev-utils": "^4.2.1", | ||||
|         "@0x/order-utils": "^10.4.19", | ||||
|         "@0x/order-utils": "^10.4.18-multiplex.0", | ||||
|         "@0x/sol-compiler": "^4.6.1", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
|         "@0x/tslint-config": "^4.1.3", | ||||
| @@ -87,7 +87,7 @@ | ||||
|         "truffle": "^5.0.32", | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.2.18", | ||||
|   | ||||
| @@ -1,16 +1,7 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1617311315, | ||||
|         "version": "4.3.27", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1616005394, | ||||
|         "version": "4.3.26", | ||||
|         "timestamp": 1615932869, | ||||
|         "version": "4.3.26-multiplex.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|   | ||||
| @@ -5,11 +5,7 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v4.3.27 - _April 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v4.3.26 - _March 17, 2021_ | ||||
| ## v4.3.26-multiplex.0 - _March 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-exchange-libs", | ||||
|     "version": "4.3.27", | ||||
|     "version": "4.3.26-multiplex.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -77,13 +77,13 @@ | ||||
|         "truffle": "^5.0.32", | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.2.18", | ||||
|         "@0x/contracts-test-utils": "^5.3.24", | ||||
|         "@0x/contracts-utils": "^4.7.6", | ||||
|         "@0x/order-utils": "^10.4.19", | ||||
|         "@0x/contracts-test-utils": "^5.3.23-multiplex.0", | ||||
|         "@0x/contracts-utils": "^4.7.5-multiplex.0", | ||||
|         "@0x/order-utils": "^10.4.18-multiplex.0", | ||||
|         "@0x/types": "^3.3.1", | ||||
|         "@0x/typescript-typings": "^5.1.6", | ||||
|         "@0x/utils": "^6.2.0", | ||||
|   | ||||
| @@ -1,16 +1,7 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1617311315, | ||||
|         "version": "3.2.28", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1616005394, | ||||
|         "version": "3.2.27", | ||||
|         "timestamp": 1615932869, | ||||
|         "version": "3.2.27-multiplex.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|   | ||||
| @@ -5,11 +5,7 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v3.2.28 - _April 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v3.2.27 - _March 17, 2021_ | ||||
| ## v3.2.27-multiplex.0 - _March 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-exchange", | ||||
|     "version": "3.2.28", | ||||
|     "version": "3.2.27-multiplex.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -53,13 +53,13 @@ | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/protocol", | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.4.21", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.9", | ||||
|         "@0x/contracts-exchange-libs": "^4.3.27", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0", | ||||
|         "@0x/contracts-exchange-libs": "^4.3.26-multiplex.0", | ||||
|         "@0x/contracts-gen": "^2.0.32", | ||||
|         "@0x/contracts-multisig": "^4.1.28", | ||||
|         "@0x/contracts-staking": "^2.0.35", | ||||
|         "@0x/contracts-test-utils": "^5.3.24", | ||||
|         "@0x/contracts-utils": "^4.7.6", | ||||
|         "@0x/contracts-multisig": "^4.1.27-multiplex.0", | ||||
|         "@0x/contracts-staking": "^2.0.34-multiplex.0", | ||||
|         "@0x/contracts-test-utils": "^5.3.23-multiplex.0", | ||||
|         "@0x/contracts-utils": "^4.7.5-multiplex.0", | ||||
|         "@0x/dev-utils": "^4.2.1", | ||||
|         "@0x/sol-compiler": "^4.6.1", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
| @@ -85,15 +85,15 @@ | ||||
|         "truffle": "^5.0.32", | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.2.18", | ||||
|         "@0x/contracts-dev-utils": "^1.3.26", | ||||
|         "@0x/contracts-erc1155": "^2.1.27", | ||||
|         "@0x/contracts-erc20": "^3.3.6", | ||||
|         "@0x/contracts-erc721": "^3.1.27", | ||||
|         "@0x/order-utils": "^10.4.19", | ||||
|         "@0x/contracts-dev-utils": "^1.3.25-multiplex.0", | ||||
|         "@0x/contracts-erc1155": "^2.1.26-multiplex.0", | ||||
|         "@0x/contracts-erc20": "^3.3.5-multiplex.0", | ||||
|         "@0x/contracts-erc721": "^3.1.26-multiplex.0", | ||||
|         "@0x/order-utils": "^10.4.18-multiplex.0", | ||||
|         "@0x/utils": "^6.2.0", | ||||
|         "lodash": "^4.17.11" | ||||
|     }, | ||||
|   | ||||
| @@ -12,12 +12,12 @@ export abstract class AbstractBalanceAndProxyAllowanceFetcher { | ||||
|      * @param userAddress Ethereum address for which to fetch the balance | ||||
|      * @return Balance amount in base units | ||||
|      */ | ||||
|     public abstract getBalanceAsync(assetData: string, userAddress: string): Promise<BigNumber>; | ||||
|     public abstract async getBalanceAsync(assetData: string, userAddress: string): Promise<BigNumber>; | ||||
|     /** | ||||
|      * Get the 0x asset proxy allowance of assetData for userAddress | ||||
|      * @param assetData AssetData for which to fetch the allowance | ||||
|      * @param userAddress Ethereum address for which to fetch the allowance | ||||
|      * @return Allowance amount in base units | ||||
|      */ | ||||
|     public abstract getProxyAllowanceAsync(assetData: string, userAddress: string): Promise<BigNumber>; | ||||
|     public abstract async getProxyAllowanceAsync(assetData: string, userAddress: string): Promise<BigNumber>; | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| import { BigNumber } from '@0x/utils'; | ||||
|  | ||||
| export abstract class AbstractBalanceAndProxyAllowanceLazyStore { | ||||
|     public abstract getBalanceAsync(assetData: string, userAddress: string): Promise<BigNumber>; | ||||
|     public abstract getProxyAllowanceAsync(assetData: string, userAddress: string): Promise<BigNumber>; | ||||
|     public abstract async getBalanceAsync(assetData: string, userAddress: string): Promise<BigNumber>; | ||||
|     public abstract async getProxyAllowanceAsync(assetData: string, userAddress: string): Promise<BigNumber>; | ||||
|     public abstract setBalance(assetData: string, userAddress: string, balance: BigNumber): void; | ||||
|     public abstract deleteBalance(assetData: string, userAddress: string): void; | ||||
|     public abstract setProxyAllowance(assetData: string, userAddress: string, proxyAllowance: BigNumber): void; | ||||
|   | ||||
| @@ -11,5 +11,5 @@ export abstract class AbstractOrderFilledCancelledFetcher { | ||||
|      * @param orderHash OrderHash of order we are interested in | ||||
|      * @return FilledTakerAmount | ||||
|      */ | ||||
|     public abstract getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber>; | ||||
|     public abstract async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber>; | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import { BigNumber } from '@0x/utils'; | ||||
|  | ||||
| export abstract class AbstractOrderFilledCancelledLazyStore { | ||||
|     public abstract getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber>; | ||||
|     public abstract async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber>; | ||||
|     public abstract setFilledTakerAmount(orderHash: string, balance: BigNumber): void; | ||||
|     public abstract deleteFilledTakerAmount(orderHash: string): void; | ||||
|     public abstract setIsCancelled(orderHash: string, isCancelled: boolean): void; | ||||
|   | ||||
| @@ -18,7 +18,6 @@ import { | ||||
|     IsolatedExchangeFillEventArgs as FillEventArgs, | ||||
| } from '../wrappers'; | ||||
|  | ||||
| export { Order } from '@0x/types'; | ||||
| export interface AssetBalances { | ||||
|     [assetData: string]: { [address: string]: BigNumber }; | ||||
| } | ||||
| @@ -28,6 +27,7 @@ export interface IsolatedExchangeEvents { | ||||
|     transferFromCalls: DispatchTransferFromCallArgs[]; | ||||
| } | ||||
|  | ||||
| export type Order = Order; | ||||
| export type Numberish = string | number | BigNumber; | ||||
|  | ||||
| export const DEFAULT_GOOD_SIGNATURE = createGoodSignature(); | ||||
|   | ||||
| @@ -1,16 +1,7 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1617311315, | ||||
|         "version": "6.2.22", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1616005394, | ||||
|         "version": "6.2.21", | ||||
|         "timestamp": 1615932869, | ||||
|         "version": "6.2.21-multiplex.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|   | ||||
| @@ -5,11 +5,7 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v6.2.22 - _April 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v6.2.21 - _March 17, 2021_ | ||||
| ## v6.2.21-multiplex.0 - _March 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-extensions", | ||||
|     "version": "6.2.22", | ||||
|     "version": "6.2.21-multiplex.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -53,16 +53,16 @@ | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions", | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.4.21", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.9", | ||||
|         "@0x/contracts-dev-utils": "^1.3.26", | ||||
|         "@0x/contracts-erc20": "^3.3.6", | ||||
|         "@0x/contracts-erc721": "^3.1.27", | ||||
|         "@0x/contracts-exchange": "^3.2.28", | ||||
|         "@0x/contracts-exchange-libs": "^4.3.27", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0", | ||||
|         "@0x/contracts-dev-utils": "^1.3.25-multiplex.0", | ||||
|         "@0x/contracts-erc20": "^3.3.5-multiplex.0", | ||||
|         "@0x/contracts-erc721": "^3.1.26-multiplex.0", | ||||
|         "@0x/contracts-exchange": "^3.2.27-multiplex.0", | ||||
|         "@0x/contracts-exchange-libs": "^4.3.26-multiplex.0", | ||||
|         "@0x/contracts-gen": "^2.0.32", | ||||
|         "@0x/contracts-utils": "^4.7.6", | ||||
|         "@0x/contracts-utils": "^4.7.5-multiplex.0", | ||||
|         "@0x/dev-utils": "^4.2.1", | ||||
|         "@0x/order-utils": "^10.4.19", | ||||
|         "@0x/order-utils": "^10.4.18-multiplex.0", | ||||
|         "@0x/sol-compiler": "^4.6.1", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
|         "@0x/tslint-config": "^4.1.3", | ||||
| @@ -87,11 +87,11 @@ | ||||
|         "truffle": "^5.0.32", | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.2.18", | ||||
|         "@0x/contracts-test-utils": "^5.3.24", | ||||
|         "@0x/contracts-test-utils": "^5.3.23-multiplex.0", | ||||
|         "@0x/typescript-typings": "^5.1.6", | ||||
|         "ethereum-types": "^3.4.0" | ||||
|     }, | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-integrations", | ||||
|     "version": "2.7.36", | ||||
|     "version": "2.7.29-multiplex.0", | ||||
|     "private": true, | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
| @@ -53,21 +53,21 @@ | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions", | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.4.21", | ||||
|         "@0x/contract-addresses": "^6.0.0", | ||||
|         "@0x/contract-wrappers": "^13.15.0", | ||||
|         "@0x/contracts-broker": "^1.1.27", | ||||
|         "@0x/contracts-coordinator": "^3.1.28", | ||||
|         "@0x/contracts-dev-utils": "^1.3.26", | ||||
|         "@0x/contracts-exchange-forwarder": "^4.2.28", | ||||
|         "@0x/contracts-exchange-libs": "^4.3.27", | ||||
|         "@0x/contracts-extensions": "^6.2.22", | ||||
|         "@0x/contract-addresses": "^5.11.0", | ||||
|         "@0x/contract-wrappers": "^13.14.0-multiplex", | ||||
|         "@0x/contracts-broker": "^1.1.26-multiplex.0", | ||||
|         "@0x/contracts-coordinator": "^3.1.27-multiplex.0", | ||||
|         "@0x/contracts-dev-utils": "^1.3.25-multiplex.0", | ||||
|         "@0x/contracts-exchange-forwarder": "^4.2.27-multiplex.0", | ||||
|         "@0x/contracts-exchange-libs": "^4.3.26-multiplex.0", | ||||
|         "@0x/contracts-extensions": "^6.2.21-multiplex.0", | ||||
|         "@0x/contracts-gen": "^2.0.32", | ||||
|         "@0x/contracts-utils": "^4.7.6", | ||||
|         "@0x/contracts-utils": "^4.7.5-multiplex.0", | ||||
|         "@0x/coordinator-server": "^1.0.5", | ||||
|         "@0x/dev-utils": "^4.2.1", | ||||
|         "@0x/migrations": "^8.0.2", | ||||
|         "@0x/order-utils": "^10.4.19", | ||||
|         "@0x/protocol-utils": "^1.5.0", | ||||
|         "@0x/migrations": "^7.0.1-multiplex.0", | ||||
|         "@0x/order-utils": "^10.4.18-multiplex.0", | ||||
|         "@0x/protocol-utils": "^1.3.1-multiplex.0", | ||||
|         "@0x/sol-compiler": "^4.6.1", | ||||
|         "@0x/tslint-config": "^4.1.3", | ||||
|         "@0x/web3-wrapper": "^7.4.1", | ||||
| @@ -90,20 +90,20 @@ | ||||
|         "solhint": "^1.4.1", | ||||
|         "truffle": "^5.0.32", | ||||
|         "tslint": "5.11.0", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/asset-swapper": "^6.7.0", | ||||
|         "@0x/asset-swapper": "^6.3.0-multiplex", | ||||
|         "@0x/base-contract": "^6.2.18", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.9", | ||||
|         "@0x/contracts-erc1155": "^2.1.27", | ||||
|         "@0x/contracts-erc20": "^3.3.6", | ||||
|         "@0x/contracts-erc721": "^3.1.27", | ||||
|         "@0x/contracts-exchange": "^3.2.28", | ||||
|         "@0x/contracts-multisig": "^4.1.28", | ||||
|         "@0x/contracts-staking": "^2.0.35", | ||||
|         "@0x/contracts-test-utils": "^5.3.24", | ||||
|         "@0x/contracts-zero-ex": "^0.22.0", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0", | ||||
|         "@0x/contracts-erc1155": "^2.1.26-multiplex.0", | ||||
|         "@0x/contracts-erc20": "^3.3.5-multiplex.0", | ||||
|         "@0x/contracts-erc721": "^3.1.26-multiplex.0", | ||||
|         "@0x/contracts-exchange": "^3.2.27-multiplex.0", | ||||
|         "@0x/contracts-multisig": "^4.1.27-multiplex.0", | ||||
|         "@0x/contracts-staking": "^2.0.34-multiplex.0", | ||||
|         "@0x/contracts-test-utils": "^5.3.23-multiplex.0", | ||||
|         "@0x/contracts-zero-ex": "^0.20.0-multiplex", | ||||
|         "@0x/subproviders": "^6.4.1", | ||||
|         "@0x/types": "^3.3.1", | ||||
|         "@0x/typescript-typings": "^5.1.6", | ||||
|   | ||||
| @@ -63,9 +63,11 @@ blockchainTests.fork('DevUtils dydx order validation tests', env => { | ||||
|     let dai: ERC20TokenContract; | ||||
|     let usdc: ERC20TokenContract; | ||||
|     let devUtils: DevUtilsContract; | ||||
|     let accountOwner: string; | ||||
|     let minMarginRatio: number; | ||||
|  | ||||
|     before(async () => { | ||||
|         [accountOwner] = await env.getAccountAddressesAsync(); | ||||
|         dydx = new IDydxContract(DYDX_ADDRESS, env.provider, env.txDefaults); | ||||
|         dai = new ERC20TokenContract(DAI_ADDRESS, env.provider, env.txDefaults); | ||||
|         usdc = new ERC20TokenContract(USDC_ADDRESS, env.provider, env.txDefaults); | ||||
|   | ||||
| @@ -19,5 +19,5 @@ export function filterActorsByRole<TClass extends Constructor>( | ||||
|     actors: Actor[], | ||||
|     role: TClass, | ||||
| ): Array<InstanceType<typeof role>> { | ||||
|     return actors.filter(actor => actor.mixins.includes(role.name)) as Array<InstanceType<typeof role>>; | ||||
|     return actors.filter(actor => actor.mixins.includes(role.name)) as InstanceType<typeof role>; | ||||
| } | ||||
|   | ||||
| @@ -1,16 +1,7 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1617311315, | ||||
|         "version": "4.1.28", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1616005394, | ||||
|         "version": "4.1.27", | ||||
|         "timestamp": 1615932869, | ||||
|         "version": "4.1.27-multiplex.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|   | ||||
| @@ -5,11 +5,7 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v4.1.28 - _April 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v4.1.27 - _March 17, 2021_ | ||||
| ## v4.1.27-multiplex.0 - _March 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-multisig", | ||||
|     "version": "4.1.28", | ||||
|     "version": "4.1.27-multiplex.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -50,11 +50,11 @@ | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/multisig", | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.4.21", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.9", | ||||
|         "@0x/contracts-erc20": "^3.3.6", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0", | ||||
|         "@0x/contracts-erc20": "^3.3.5-multiplex.0", | ||||
|         "@0x/contracts-gen": "^2.0.32", | ||||
|         "@0x/contracts-test-utils": "^5.3.24", | ||||
|         "@0x/contracts-utils": "^4.7.6", | ||||
|         "@0x/contracts-test-utils": "^5.3.23-multiplex.0", | ||||
|         "@0x/contracts-utils": "^4.7.5-multiplex.0", | ||||
|         "@0x/dev-utils": "^4.2.1", | ||||
|         "@0x/sol-compiler": "^4.6.1", | ||||
|         "@0x/tslint-config": "^4.1.3", | ||||
| @@ -75,7 +75,7 @@ | ||||
|         "shx": "^0.2.2", | ||||
|         "solhint": "^1.4.1", | ||||
|         "tslint": "5.11.0", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.2.18", | ||||
|   | ||||
| @@ -1,16 +1,7 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1617311315, | ||||
|         "version": "2.0.35", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1616005394, | ||||
|         "version": "2.0.34", | ||||
|         "timestamp": 1615932869, | ||||
|         "version": "2.0.34-multiplex.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|   | ||||
| @@ -5,11 +5,7 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v2.0.35 - _April 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v2.0.34 - _March 17, 2021_ | ||||
| ## v2.0.34-multiplex.0 - _March 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-staking", | ||||
|     "version": "2.0.35", | ||||
|     "version": "2.0.34-multiplex.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -54,14 +54,14 @@ | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/tokens", | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.4.21", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.9", | ||||
|         "@0x/contracts-dev-utils": "^1.3.26", | ||||
|         "@0x/contracts-erc20": "^3.3.6", | ||||
|         "@0x/contracts-exchange-libs": "^4.3.27", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0", | ||||
|         "@0x/contracts-dev-utils": "^1.3.25-multiplex.0", | ||||
|         "@0x/contracts-erc20": "^3.3.5-multiplex.0", | ||||
|         "@0x/contracts-exchange-libs": "^4.3.26-multiplex.0", | ||||
|         "@0x/contracts-gen": "^2.0.32", | ||||
|         "@0x/contracts-utils": "^4.7.6", | ||||
|         "@0x/contracts-utils": "^4.7.5-multiplex.0", | ||||
|         "@0x/dev-utils": "^4.2.1", | ||||
|         "@0x/order-utils": "^10.4.19", | ||||
|         "@0x/order-utils": "^10.4.18-multiplex.0", | ||||
|         "@0x/sol-compiler": "^4.6.1", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
|         "@0x/tslint-config": "^4.1.3", | ||||
| @@ -84,11 +84,11 @@ | ||||
|         "truffle": "^5.0.32", | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.2.18", | ||||
|         "@0x/contracts-test-utils": "^5.3.24", | ||||
|         "@0x/contracts-test-utils": "^5.3.23-multiplex.0", | ||||
|         "@0x/typescript-typings": "^5.1.6", | ||||
|         "@0x/utils": "^6.2.0", | ||||
|         "ethereum-types": "^3.4.0", | ||||
|   | ||||
| @@ -4,7 +4,6 @@ import { DecodedLogArgs, LogWithDecodedArgs } from 'ethereum-types'; | ||||
|  | ||||
| import { constants as stakingConstants } from './constants'; | ||||
|  | ||||
| export { Numberish } from '@0x/contracts-test-utils'; | ||||
| // tslint:disable:max-classes-per-file | ||||
|  | ||||
| export interface StakingParams { | ||||
| @@ -260,3 +259,5 @@ export class AggregatedStats { | ||||
| export interface AggregatedStatsByEpoch { | ||||
|     [epoch: string]: AggregatedStats; | ||||
| } | ||||
|  | ||||
| export type Numberish = Numberish; | ||||
|   | ||||
| @@ -12,6 +12,7 @@ import { | ||||
|  | ||||
| blockchainTests.resets('Exchange Unit Tests', env => { | ||||
|     // Addresses | ||||
|     let nonOwner: string; | ||||
|     let owner: string; | ||||
|     let nonExchange: string; | ||||
|     let exchange: string; | ||||
| @@ -23,7 +24,7 @@ blockchainTests.resets('Exchange Unit Tests', env => { | ||||
|  | ||||
|     before(async () => { | ||||
|         // Set up addresses for testing. | ||||
|         [, owner, nonExchange, exchange, nonAuthority, authority] = await env.getAccountAddressesAsync(); | ||||
|         [nonOwner, owner, nonExchange, exchange, nonAuthority, authority] = await env.getAccountAddressesAsync(); | ||||
|  | ||||
|         // Deploy the Exchange Manager contract. | ||||
|         exchangeManager = await TestExchangeManagerContract.deployFrom0xArtifactAsync( | ||||
|   | ||||
| @@ -543,7 +543,7 @@ blockchainTests.resets('Finalizer unit tests', env => { | ||||
|             const expectedPoolRewards = await calculatePoolRewardsAsync(INITIAL_BALANCE, pools); | ||||
|             const [pool, reward] = _.sampleSize(shortZip(pools, expectedPoolRewards), 1)[0]; | ||||
|             return assertUnfinalizedPoolRewardsAsync(pool.poolId, { | ||||
|                 totalReward: reward, | ||||
|                 totalReward: (reward as any) as BigNumber, | ||||
|                 membersStake: pool.membersStake, | ||||
|             }); | ||||
|         }); | ||||
|   | ||||
| @@ -12,13 +12,17 @@ import * as _ from 'lodash'; | ||||
| import { artifacts } from '../artifacts'; | ||||
| import { TestCobbDouglasContract } from '../wrappers'; | ||||
|  | ||||
| // tslint:disable: no-unnecessary-type-assertion | ||||
| blockchainTests('LibCobbDouglas unit tests', env => { | ||||
|     const FUZZ_COUNT = 1024; | ||||
|     const PRECISION = 15; | ||||
|  | ||||
|     let testContract: TestCobbDouglasContract; | ||||
|     let ownerAddress: string; | ||||
|     let notOwnerAddress: string; | ||||
|  | ||||
|     before(async () => { | ||||
|         [ownerAddress, notOwnerAddress] = await env.getAccountAddressesAsync(); | ||||
|         testContract = await TestCobbDouglasContract.deployFrom0xArtifactAsync( | ||||
|             artifacts.TestCobbDouglas, | ||||
|             env.provider, | ||||
| @@ -207,3 +211,4 @@ blockchainTests('LibCobbDouglas unit tests', env => { | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| // tslint:enable:no-unnecessary-type-assertion | ||||
|   | ||||
| @@ -1,16 +1,7 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1617311315, | ||||
|         "version": "5.3.24", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1616005394, | ||||
|         "version": "5.3.23", | ||||
|         "timestamp": 1615932869, | ||||
|         "version": "5.3.23-multiplex.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|   | ||||
| @@ -5,11 +5,7 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v5.3.24 - _April 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v5.3.23 - _March 17, 2021_ | ||||
| ## v5.3.23-multiplex.0 - _March 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-test-utils", | ||||
|     "version": "5.3.24", | ||||
|     "version": "5.3.23-multiplex.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -39,15 +39,15 @@ | ||||
|         "npm-run-all": "^4.1.2", | ||||
|         "shx": "^0.2.2", | ||||
|         "tslint": "5.11.0", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/assert": "^3.0.21", | ||||
|         "@0x/base-contract": "^6.2.18", | ||||
|         "@0x/contract-addresses": "^6.0.0", | ||||
|         "@0x/contract-addresses": "^5.11.0", | ||||
|         "@0x/dev-utils": "^4.2.1", | ||||
|         "@0x/json-schemas": "^5.4.1", | ||||
|         "@0x/order-utils": "^10.4.19", | ||||
|         "@0x/order-utils": "^10.4.18-multiplex.0", | ||||
|         "@0x/sol-coverage": "^4.0.31", | ||||
|         "@0x/sol-profiler": "^4.1.21", | ||||
|         "@0x/sol-trace": "^3.0.31", | ||||
|   | ||||
| @@ -14,6 +14,6 @@ export function shortZip<T1, T2>(a: T1[], b: T2[]): Array<[T1, T2]> { | ||||
| export function replaceKeysDeep(obj: {}, mapKeys: (key: string) => string | void): _.Dictionary<{}> { | ||||
|     return _.transform(obj, (result, value, key) => { | ||||
|         const currentKey = mapKeys(key) || key; | ||||
|         result[currentKey] = _.isObject(value) ? replaceKeysDeep(value as {}, mapKeys) : (value as {}); | ||||
|         result[currentKey] = _.isObject(value) ? replaceKeysDeep(value, mapKeys) : value; | ||||
|     }); | ||||
| } | ||||
|   | ||||
| @@ -22,14 +22,14 @@ export class OrderFactory { | ||||
|     ): Promise<SignedOrder> { | ||||
|         const fifteenMinutesInSeconds = 15 * 60; | ||||
|         const currentBlockTimestamp = await getLatestBlockTimestampAsync(); | ||||
|         const order = { | ||||
|         const order = ({ | ||||
|             takerAddress: constants.NULL_ADDRESS, | ||||
|             senderAddress: constants.NULL_ADDRESS, | ||||
|             expirationTimeSeconds: new BigNumber(currentBlockTimestamp).plus(fifteenMinutesInSeconds), | ||||
|             salt: generatePseudoRandomSalt(), | ||||
|             ...this._defaultOrderParams, | ||||
|             ...customOrderParams, | ||||
|         } as Order; // tslint:disable-line:no-object-literal-type-assertion | ||||
|         } as any) as Order; | ||||
|         const orderHashBuff = orderHashUtils.getOrderHashBuffer(order); | ||||
|         const signature = signingUtils.signMessage(orderHashBuff, this._privateKey, signatureType); | ||||
|         const signedOrder = { | ||||
|   | ||||
| @@ -30,8 +30,7 @@ export const orderUtils = { | ||||
|         return cancel; | ||||
|     }, | ||||
|     createOrderWithoutSignature(signedOrder: SignedOrder): Order { | ||||
|         const { signature, ...order } = signedOrder; | ||||
|         return order; | ||||
|         return _.omit(signedOrder, ['signature']) as Order; | ||||
|     }, | ||||
|     createBatchMatchOrders(signedOrdersLeft: SignedOrder[], signedOrdersRight: SignedOrder[]): BatchMatchOrder { | ||||
|         return { | ||||
|   | ||||
| @@ -1,40 +1,13 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1619481586, | ||||
|         "version": "1.1.3", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1618259868, | ||||
|         "version": "1.1.2", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1617311315, | ||||
|         "version": "1.1.1", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "version": "1.1.0", | ||||
|         "version": "1.1.0-multiplex", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Make the proposal/quorum thresholds updatable", | ||||
|                 "pr": 165 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1616005394 | ||||
|         "timestamp": 1615932869 | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1614141718, | ||||
|   | ||||
| @@ -5,19 +5,7 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v1.1.3 - _April 26, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v1.1.2 - _April 12, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v1.1.1 - _April 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v1.1.0 - _March 17, 2021_ | ||||
| ## v1.1.0-multiplex - _March 16, 2021_ | ||||
|  | ||||
|     * Make the proposal/quorum thresholds updatable (#165) | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-treasury", | ||||
|     "version": "1.1.3", | ||||
|     "version": "1.1.0-multiplex", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -47,12 +47,12 @@ | ||||
|     "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/treasury", | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.4.21", | ||||
|         "@0x/contract-addresses": "^6.0.0", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.9", | ||||
|         "@0x/contracts-erc20": "^3.3.6", | ||||
|         "@0x/contract-addresses": "^5.11.0", | ||||
|         "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0", | ||||
|         "@0x/contracts-erc20": "^3.3.5-multiplex.0", | ||||
|         "@0x/contracts-gen": "^2.0.32", | ||||
|         "@0x/contracts-staking": "^2.0.35", | ||||
|         "@0x/contracts-test-utils": "^5.3.24", | ||||
|         "@0x/contracts-staking": "^2.0.34-multiplex.0", | ||||
|         "@0x/contracts-test-utils": "^5.3.23-multiplex.0", | ||||
|         "@0x/sol-compiler": "^4.6.1", | ||||
|         "@0x/ts-doc-gen": "^0.0.28", | ||||
|         "@0x/tslint-config": "^4.1.3", | ||||
| @@ -69,11 +69,11 @@ | ||||
|         "solhint": "^1.4.1", | ||||
|         "tslint": "5.11.0", | ||||
|         "typedoc": "~0.16.11", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.2.18", | ||||
|         "@0x/protocol-utils": "^1.5.0", | ||||
|         "@0x/protocol-utils": "^1.3.1-multiplex.0", | ||||
|         "@0x/subproviders": "^6.4.1", | ||||
|         "@0x/types": "^3.3.1", | ||||
|         "@0x/typescript-typings": "^5.1.6", | ||||
|   | ||||
| @@ -1,16 +1,7 @@ | ||||
| [ | ||||
|     { | ||||
|         "timestamp": 1617311315, | ||||
|         "version": "4.7.6", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1616005394, | ||||
|         "version": "4.7.5", | ||||
|         "timestamp": 1615932869, | ||||
|         "version": "4.7.5-multiplex.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|   | ||||
| @@ -5,11 +5,7 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v4.7.6 - _April 1, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v4.7.5 - _March 17, 2021_ | ||||
| ## v4.7.5-multiplex.0 - _March 16, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0x/contracts-utils", | ||||
|     "version": "4.7.6", | ||||
|     "version": "4.7.5-multiplex.0", | ||||
|     "engines": { | ||||
|         "node": ">=6.12" | ||||
|     }, | ||||
| @@ -52,9 +52,9 @@ | ||||
|     "devDependencies": { | ||||
|         "@0x/abi-gen": "^5.4.21", | ||||
|         "@0x/contracts-gen": "^2.0.32", | ||||
|         "@0x/contracts-test-utils": "^5.3.24", | ||||
|         "@0x/contracts-test-utils": "^5.3.23-multiplex.0", | ||||
|         "@0x/dev-utils": "^4.2.1", | ||||
|         "@0x/order-utils": "^10.4.19", | ||||
|         "@0x/order-utils": "^10.4.18-multiplex.0", | ||||
|         "@0x/sol-compiler": "^4.6.1", | ||||
|         "@0x/tslint-config": "^4.1.3", | ||||
|         "@0x/types": "^3.3.1", | ||||
| @@ -76,7 +76,7 @@ | ||||
|         "solhint": "^1.4.1", | ||||
|         "truffle": "^5.0.32", | ||||
|         "tslint": "5.11.0", | ||||
|         "typescript": "4.2.2" | ||||
|         "typescript": "3.0.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0x/base-contract": "^6.2.18", | ||||
|   | ||||
| @@ -1,55 +1,6 @@ | ||||
| [ | ||||
|     { | ||||
|         "version": "0.22.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add order signer registry to NativeOrdersFeature", | ||||
|                 "pr": 195 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1619481586 | ||||
|     }, | ||||
|     { | ||||
|         "timestamp": 1618259868, | ||||
|         "version": "0.21.1", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Dependencies updated" | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "version": "0.21.0", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Encoding protocol ID and source name in bridge source ID", | ||||
|                 "pr": 162 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Add PancakeSwapFeature", | ||||
|                 "pr": 164 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Remove TokenSpender/AllowanceTarget/greedy tokens stuff", | ||||
|                 "pr": 164 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Added Nerve in BridgeAdapter", | ||||
|                 "pr": 181 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Delete TokenSpenderFeature", | ||||
|                 "pr": 189 | ||||
|             }, | ||||
|             { | ||||
|                 "note": "Fix PancakeSwapFeature BakerySwap swap selector", | ||||
|                 "pr": 190 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1617311315 | ||||
|     }, | ||||
|     { | ||||
|         "version": "0.20.0", | ||||
|         "version": "0.20.0-multiplex", | ||||
|         "changes": [ | ||||
|             { | ||||
|                 "note": "Add `MooniswapLiquidityProvider`", | ||||
| @@ -68,7 +19,7 @@ | ||||
|                 "pr": 168 | ||||
|             } | ||||
|         ], | ||||
|         "timestamp": 1616005394 | ||||
|         "timestamp": 1615932869 | ||||
|     }, | ||||
|     { | ||||
|         "version": "0.19.0", | ||||
|   | ||||
| @@ -5,24 +5,7 @@ Edit the package's CHANGELOG.json file only. | ||||
|  | ||||
| CHANGELOG | ||||
|  | ||||
| ## v0.22.0 - _April 26, 2021_ | ||||
|  | ||||
|     * Add order signer registry to NativeOrdersFeature (#195) | ||||
|  | ||||
| ## v0.21.1 - _April 12, 2021_ | ||||
|  | ||||
|     * Dependencies updated | ||||
|  | ||||
| ## v0.21.0 - _April 1, 2021_ | ||||
|  | ||||
|     * Encoding protocol ID and source name in bridge source ID (#162) | ||||
|     * Add PancakeSwapFeature (#164) | ||||
|     * Remove TokenSpender/AllowanceTarget/greedy tokens stuff (#164) | ||||
|     * Added Nerve in BridgeAdapter (#181) | ||||
|     * Delete TokenSpenderFeature (#189) | ||||
|     * Fix PancakeSwapFeature BakerySwap swap selector (#190) | ||||
|  | ||||
| ## v0.20.0 - _March 17, 2021_ | ||||
| ## v0.20.0-multiplex - _March 16, 2021_ | ||||
|  | ||||
|     * Add `MooniswapLiquidityProvider` (#143) | ||||
|     * Emit `LiquidityProviderFill` event in `CurveLiquidityProvider` (#143) | ||||
|   | ||||
| @@ -26,7 +26,6 @@ import "./features/interfaces/ITokenSpenderFeature.sol"; | ||||
| import "./features/interfaces/ITransformERC20Feature.sol"; | ||||
| import "./features/interfaces/IMetaTransactionsFeature.sol"; | ||||
| import "./features/interfaces/IUniswapFeature.sol"; | ||||
| import "./features/interfaces/IPancakeSwapFeature.sol"; | ||||
| import "./features/interfaces/ILiquidityProviderFeature.sol"; | ||||
| import "./features/interfaces/INativeOrdersFeature.sol"; | ||||
| import "./features/interfaces/IBatchFillNativeOrdersFeature.sol"; | ||||
| @@ -37,10 +36,10 @@ import "./features/interfaces/IMultiplexFeature.sol"; | ||||
| interface IZeroEx is | ||||
|     IOwnableFeature, | ||||
|     ISimpleFunctionRegistryFeature, | ||||
|     ITokenSpenderFeature, | ||||
|     ITransformERC20Feature, | ||||
|     IMetaTransactionsFeature, | ||||
|     IUniswapFeature, | ||||
|     IPancakeSwapFeature, | ||||
|     ILiquidityProviderFeature, | ||||
|     INativeOrdersFeature, | ||||
|     IBatchFillNativeOrdersFeature, | ||||
|   | ||||
| @@ -88,21 +88,6 @@ library LibNativeOrdersRichErrors { | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     function InvalidSignerError( | ||||
|         address maker, | ||||
|         address signer | ||||
|     ) | ||||
|         internal | ||||
|         pure | ||||
|         returns (bytes memory) | ||||
|     { | ||||
|         return abi.encodeWithSelector( | ||||
|             bytes4(keccak256("InvalidSignerError(address,address)")), | ||||
|             maker, | ||||
|             signer | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     function OrderNotFillableBySenderError( | ||||
|         bytes32 orderHash, | ||||
|         address sender, | ||||
|   | ||||
| @@ -0,0 +1,47 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 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.6.5; | ||||
|  | ||||
|  | ||||
| library LibSpenderRichErrors { | ||||
|  | ||||
|     // solhint-disable func-name-mixedcase | ||||
|  | ||||
|     function SpenderERC20TransferFromFailedError( | ||||
|         address token, | ||||
|         address owner, | ||||
|         address to, | ||||
|         uint256 amount, | ||||
|         bytes memory errorData | ||||
|     ) | ||||
|         internal | ||||
|         pure | ||||
|         returns (bytes memory) | ||||
|     { | ||||
|         return abi.encodeWithSelector( | ||||
|             bytes4(keccak256("SpenderERC20TransferFromFailedError(address,address,address,uint256,bytes)")), | ||||
|             token, | ||||
|             owner, | ||||
|             to, | ||||
|             amount, | ||||
|             errorData | ||||
|         ); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										56
									
								
								contracts/zero-ex/contracts/src/external/AllowanceTarget.sol
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								contracts/zero-ex/contracts/src/external/AllowanceTarget.sol
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 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.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/v06/AuthorizableV06.sol"; | ||||
| import "../errors/LibSpenderRichErrors.sol"; | ||||
| import "./IAllowanceTarget.sol"; | ||||
|  | ||||
|  | ||||
| /// @dev The allowance target for the TokenSpender feature. | ||||
| contract AllowanceTarget is | ||||
|     IAllowanceTarget, | ||||
|     AuthorizableV06 | ||||
| { | ||||
|     // solhint-disable no-unused-vars,indent,no-empty-blocks | ||||
|     using LibRichErrorsV06 for bytes; | ||||
|  | ||||
|     /// @dev Execute an arbitrary call. Only an authority can call this. | ||||
|     /// @param target The call target. | ||||
|     /// @param callData The call data. | ||||
|     /// @return resultData The data returned by the call. | ||||
|     function executeCall( | ||||
|         address payable target, | ||||
|         bytes calldata callData | ||||
|     ) | ||||
|         external | ||||
|         override | ||||
|         onlyAuthorized | ||||
|         returns (bytes memory resultData) | ||||
|     { | ||||
|         bool success; | ||||
|         (success, resultData) = target.call(callData); | ||||
|         if (!success) { | ||||
|             resultData.rrevert(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										40
									
								
								contracts/zero-ex/contracts/src/external/IAllowanceTarget.sol
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								contracts/zero-ex/contracts/src/external/IAllowanceTarget.sol
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 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.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-utils/contracts/src/v06/interfaces/IAuthorizableV06.sol"; | ||||
|  | ||||
|  | ||||
| /// @dev The allowance target for the TokenSpender feature. | ||||
| interface IAllowanceTarget is | ||||
|     IAuthorizableV06 | ||||
| { | ||||
|     /// @dev Execute an arbitrary call. Only an authority can call this. | ||||
|     /// @param target The call target. | ||||
|     /// @param callData The call data. | ||||
|     /// @return resultData The data returned by the call. | ||||
|     function executeCall( | ||||
|         address payable target, | ||||
|         bytes calldata callData | ||||
|     ) | ||||
|         external | ||||
|         returns (bytes memory resultData); | ||||
| } | ||||
| @@ -47,14 +47,15 @@ contract LiquidityProviderFeature is | ||||
|     /// @dev Name of this feature. | ||||
|     string public constant override FEATURE_NAME = "LiquidityProviderFeature"; | ||||
|     /// @dev Version of this feature. | ||||
|     uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 4); | ||||
|     uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 3); | ||||
|  | ||||
|     /// @dev The sandbox contract address. | ||||
|     ILiquidityProviderSandbox public immutable sandbox; | ||||
|  | ||||
|     constructor(LiquidityProviderSandbox sandbox_) | ||||
|     constructor(LiquidityProviderSandbox sandbox_, bytes32 greedyTokensBloomFilter) | ||||
|         public | ||||
|         FixinCommon() | ||||
|         FixinTokenSpender(greedyTokensBloomFilter) | ||||
|     { | ||||
|         sandbox = sandbox_; | ||||
|     } | ||||
|   | ||||
| @@ -78,7 +78,7 @@ contract MetaTransactionsFeature is | ||||
|     /// @dev Name of this feature. | ||||
|     string public constant override FEATURE_NAME = "MetaTransactions"; | ||||
|     /// @dev Version of this feature. | ||||
|     uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 1); | ||||
|     uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 0); | ||||
|     /// @dev EIP712 typehash of the `MetaTransactionData` struct. | ||||
|     bytes32 public immutable MTX_EIP712_TYPEHASH = keccak256( | ||||
|         "MetaTransactionData(" | ||||
| @@ -105,10 +105,11 @@ contract MetaTransactionsFeature is | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     constructor(address zeroExAddress) | ||||
|     constructor(address zeroExAddress, bytes32 greedyTokensBloomFilter) | ||||
|         public | ||||
|         FixinCommon() | ||||
|         FixinEIP712(zeroExAddress) | ||||
|         FixinTokenSpender(greedyTokensBloomFilter) | ||||
|     { | ||||
|         // solhint-disable-next-line no-empty-blocks | ||||
|     } | ||||
|   | ||||
| @@ -55,7 +55,7 @@ contract MultiplexFeature is | ||||
|     /// @dev Name of this feature. | ||||
|     string public constant override FEATURE_NAME = "MultiplexFeature"; | ||||
|     /// @dev Version of this feature. | ||||
|     uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 1); | ||||
|     uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0); | ||||
|  | ||||
|     /// @dev The WETH token contract. | ||||
|     IEtherTokenV06 private immutable weth; | ||||
| @@ -73,10 +73,12 @@ contract MultiplexFeature is | ||||
|     constructor( | ||||
|         address zeroExAddress, | ||||
|         IEtherTokenV06 weth_, | ||||
|         ILiquidityProviderSandbox sandbox_ | ||||
|         ILiquidityProviderSandbox sandbox_, | ||||
|         bytes32 greedyTokensBloomFilter | ||||
|     ) | ||||
|         public | ||||
|         FixinEIP712(zeroExAddress) | ||||
|         FixinTokenSpender(greedyTokensBloomFilter) | ||||
|     { | ||||
|         weth = weth_; | ||||
|         sandbox = sandbox_; | ||||
|   | ||||
| @@ -34,14 +34,15 @@ contract NativeOrdersFeature is | ||||
|     /// @dev Name of this feature. | ||||
|     string public constant override FEATURE_NAME = "LimitOrders"; | ||||
|     /// @dev Version of this feature. | ||||
|     uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 0); | ||||
|     uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 1); | ||||
|  | ||||
|     constructor( | ||||
|         address zeroExAddress, | ||||
|         IEtherTokenV06 weth, | ||||
|         IStaking staking, | ||||
|         FeeCollectorController feeCollectorController, | ||||
|         uint32 protocolFeeMultiplier | ||||
|         uint32 protocolFeeMultiplier, | ||||
|         bytes32 greedyTokensBloomFilter | ||||
|     ) | ||||
|         public | ||||
|         NativeOrdersSettlement( | ||||
| @@ -49,7 +50,8 @@ contract NativeOrdersFeature is | ||||
|             weth, | ||||
|             staking, | ||||
|             feeCollectorController, | ||||
|             protocolFeeMultiplier | ||||
|             protocolFeeMultiplier, | ||||
|             greedyTokensBloomFilter | ||||
|         ) | ||||
|     { | ||||
|         // solhint-disable no-empty-blocks | ||||
| @@ -74,13 +76,9 @@ contract NativeOrdersFeature is | ||||
|         _registerFeatureFunction(this.batchCancelLimitOrders.selector); | ||||
|         _registerFeatureFunction(this.batchCancelRfqOrders.selector); | ||||
|         _registerFeatureFunction(this.cancelPairLimitOrders.selector); | ||||
|         _registerFeatureFunction(this.cancelPairLimitOrdersWithSigner.selector); | ||||
|         _registerFeatureFunction(this.batchCancelPairLimitOrders.selector); | ||||
|         _registerFeatureFunction(this.batchCancelPairLimitOrdersWithSigner.selector); | ||||
|         _registerFeatureFunction(this.cancelPairRfqOrders.selector); | ||||
|         _registerFeatureFunction(this.cancelPairRfqOrdersWithSigner.selector); | ||||
|         _registerFeatureFunction(this.batchCancelPairRfqOrders.selector); | ||||
|         _registerFeatureFunction(this.batchCancelPairRfqOrdersWithSigner.selector); | ||||
|         _registerFeatureFunction(this.getLimitOrderInfo.selector); | ||||
|         _registerFeatureFunction(this.getRfqOrderInfo.selector); | ||||
|         _registerFeatureFunction(this.getLimitOrderHash.selector); | ||||
| @@ -91,8 +89,6 @@ contract NativeOrdersFeature is | ||||
|         _registerFeatureFunction(this.getRfqOrderRelevantState.selector); | ||||
|         _registerFeatureFunction(this.batchGetLimitOrderRelevantStates.selector); | ||||
|         _registerFeatureFunction(this.batchGetRfqOrderRelevantStates.selector); | ||||
|         _registerFeatureFunction(this.registerAllowedOrderSigner.selector); | ||||
|         _registerFeatureFunction(this.isValidOrderSigner.selector); | ||||
|         return LibMigrate.MIGRATE_SUCCESS; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,423 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2021 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.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol"; | ||||
| import "../migrations/LibMigrate.sol"; | ||||
| import "../fixins/FixinCommon.sol"; | ||||
| import "./interfaces/IFeature.sol"; | ||||
| import "./interfaces/IPancakeSwapFeature.sol"; | ||||
|  | ||||
|  | ||||
| /// @dev VIP pancake fill functions. | ||||
| contract PancakeSwapFeature is | ||||
|     IFeature, | ||||
|     IPancakeSwapFeature, | ||||
|     FixinCommon | ||||
| { | ||||
|     /// @dev Name of this feature. | ||||
|     string public constant override FEATURE_NAME = "PancakeSwapFeature"; | ||||
|     /// @dev Version of this feature. | ||||
|     uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 1); | ||||
|     /// @dev WBNB contract. | ||||
|     IEtherTokenV06 private immutable WBNB; | ||||
|  | ||||
|     // 0xFF + address of the PancakeSwap factory contract. | ||||
|     uint256 constant private FF_PANCAKESWAP_FACTORY = 0xffbcfccbde45ce874adcb698cc183debcf179528120000000000000000000000; | ||||
|     // 0xFF + address of the BakerySwap factory contract. | ||||
|     uint256 constant private FF_BAKERYSWAP_FACTORY = 0xff01bf7c66c6bd861915cdaae475042d3c4bae16a70000000000000000000000; | ||||
|     // 0xFF + address of the SushiSwap factory contract. | ||||
|     uint256 constant private FF_SUSHISWAP_FACTORY = 0xffc35DADB65012eC5796536bD9864eD8773aBc74C40000000000000000000000; | ||||
|     // Init code hash of the PancakeSwap pair contract. | ||||
|     uint256 constant private PANCAKESWAP_PAIR_INIT_CODE_HASH = 0xd0d4c4cd0848c93cb4fd1f498d7013ee6bfb25783ea21593d5834f5d250ece66; | ||||
|     // Init code hash of the BakerySwap pair contract. | ||||
|     uint256 constant private BAKERYSWAP_PAIR_INIT_CODE_HASH = 0xe2e87433120e32c4738a7d8f3271f3d872cbe16241d67537139158d90bac61d3; | ||||
|     // Init code hash of the SushiSwap pair contract. | ||||
|     uint256 constant private SUSHISWAP_PAIR_INIT_CODE_HASH = 0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303; | ||||
|     // Mask of the lower 20 bytes of a bytes32. | ||||
|     uint256 constant private ADDRESS_MASK = 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff; | ||||
|     // BNB pseudo-token address. | ||||
|     uint256 constant private ETH_TOKEN_ADDRESS_32 = 0x000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee; | ||||
|     // Maximum token quantity that can be swapped against the PancakeSwapPair contract. | ||||
|     uint256 constant private MAX_SWAP_AMOUNT = 2**112; | ||||
|  | ||||
|     // bytes4(keccak256("executeCall(address,bytes)")) | ||||
|     uint256 constant private ALLOWANCE_TARGET_EXECUTE_CALL_SELECTOR_32 = 0xbca8c7b500000000000000000000000000000000000000000000000000000000; | ||||
|     // bytes4(keccak256("getReserves()")) | ||||
|     uint256 constant private PANCAKESWAP_PAIR_RESERVES_CALL_SELECTOR_32 = 0x0902f1ac00000000000000000000000000000000000000000000000000000000; | ||||
|     // bytes4(keccak256("swap(uint256,uint256,address,bytes)")) | ||||
|     uint256 constant private PANCAKESWAP_PAIR_SWAP_CALL_SELECTOR_32 = 0x022c0d9f00000000000000000000000000000000000000000000000000000000; | ||||
|     // bytes4(keccak256("swap(uint256,uint256,address)")) | ||||
|     uint256 constant private BAKERYSWAP_PAIR_SWAP_CALL_SELECTOR_32 = 0x6d9a640a00000000000000000000000000000000000000000000000000000000; | ||||
|     // bytes4(keccak256("transferFrom(address,address,uint256)")) | ||||
|     uint256 constant private TRANSFER_FROM_CALL_SELECTOR_32 = 0x23b872dd00000000000000000000000000000000000000000000000000000000; | ||||
|     // bytes4(keccak256("allowance(address,address)")) | ||||
|     uint256 constant private ALLOWANCE_CALL_SELECTOR_32 = 0xdd62ed3e00000000000000000000000000000000000000000000000000000000; | ||||
|     // bytes4(keccak256("withdraw(uint256)")) | ||||
|     uint256 constant private WETH_WITHDRAW_CALL_SELECTOR_32 = 0x2e1a7d4d00000000000000000000000000000000000000000000000000000000; | ||||
|     // bytes4(keccak256("deposit()")) | ||||
|     uint256 constant private WETH_DEPOSIT_CALL_SELECTOR_32 = 0xd0e30db000000000000000000000000000000000000000000000000000000000; | ||||
|     // bytes4(keccak256("transfer(address,uint256)")) | ||||
|     uint256 constant private ERC20_TRANSFER_CALL_SELECTOR_32 = 0xa9059cbb00000000000000000000000000000000000000000000000000000000; | ||||
|  | ||||
|     /// @dev Construct this contract. | ||||
|     /// @param wbnb The WBNB contract. | ||||
|     constructor(IEtherTokenV06 wbnb) public { | ||||
|         WBNB = wbnb; | ||||
|     } | ||||
|  | ||||
|     /// @dev Initialize and register this feature. | ||||
|     ///      Should be delegatecalled by `Migrate.migrate()`. | ||||
|     /// @return success `LibMigrate.SUCCESS` on success. | ||||
|     function migrate() | ||||
|         external | ||||
|         returns (bytes4 success) | ||||
|     { | ||||
|         _registerFeatureFunction(this.sellToPancakeSwap.selector); | ||||
|         return LibMigrate.MIGRATE_SUCCESS; | ||||
|     } | ||||
|  | ||||
|     /// @dev Efficiently sell directly to pancake/BakerySwap/SushiSwap. | ||||
|     /// @param tokens Sell path. | ||||
|     /// @param sellAmount of `tokens[0]` Amount to sell. | ||||
|     /// @param minBuyAmount Minimum amount of `tokens[-1]` to buy. | ||||
|     /// @param fork The protocol fork to use. | ||||
|     /// @return buyAmount Amount of `tokens[-1]` bought. | ||||
|     function sellToPancakeSwap( | ||||
|         IERC20TokenV06[] calldata tokens, | ||||
|         uint256 sellAmount, | ||||
|         uint256 minBuyAmount, | ||||
|         ProtocolFork fork | ||||
|     ) | ||||
|         external | ||||
|         payable | ||||
|         override | ||||
|         returns (uint256 buyAmount) | ||||
|     { | ||||
|         require(tokens.length > 1, "PancakeSwapFeature/InvalidTokensLength"); | ||||
|         { | ||||
|             // Load immutables onto the stack. | ||||
|             IEtherTokenV06 wbnb = WBNB; | ||||
|  | ||||
|             // Store some vars in memory to get around stack limits. | ||||
|             assembly { | ||||
|                 // calldataload(mload(0xA00)) == first element of `tokens` array | ||||
|                 mstore(0xA00, add(calldataload(0x04), 0x24)) | ||||
|                 // mload(0xA20) == fork | ||||
|                 mstore(0xA20, fork) | ||||
|                 // mload(0xA40) == WBNB | ||||
|                 mstore(0xA40, wbnb) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         assembly { | ||||
|             // numPairs == tokens.length - 1 | ||||
|             let numPairs := sub(calldataload(add(calldataload(0x04), 0x4)), 1) | ||||
|             // We use the previous buy amount as the sell amount for the next | ||||
|             // pair in a path. So for the first swap we want to set it to `sellAmount`. | ||||
|             buyAmount := sellAmount | ||||
|             let buyToken | ||||
|             let nextPair := 0 | ||||
|  | ||||
|             for {let i := 0} lt(i, numPairs) {i := add(i, 1)} { | ||||
|                 // sellToken = tokens[i] | ||||
|                 let sellToken := loadTokenAddress(i) | ||||
|                 // buyToken = tokens[i+1] | ||||
|                 buyToken := loadTokenAddress(add(i, 1)) | ||||
|                 // The canonical ordering of this token pair. | ||||
|                 let pairOrder := lt(normalizeToken(sellToken), normalizeToken(buyToken)) | ||||
|  | ||||
|                 // Compute the pair address if it hasn't already been computed | ||||
|                 // from the last iteration. | ||||
|                 let pair := nextPair | ||||
|                 if iszero(pair) { | ||||
|                     pair := computePairAddress(sellToken, buyToken) | ||||
|                     nextPair := 0 | ||||
|                 } | ||||
|  | ||||
|                 if iszero(i) { | ||||
|                     // This is the first token in the path. | ||||
|                     switch eq(sellToken, ETH_TOKEN_ADDRESS_32) | ||||
|                         case 0 { // Not selling BNB. Selling an ERC20 instead. | ||||
|                             // Make sure BNB was not attached to the call. | ||||
|                             if gt(callvalue(), 0) { | ||||
|                                 revert(0, 0) | ||||
|                             } | ||||
|                             // For the first pair we need to transfer sellTokens into the | ||||
|                             // pair contract. | ||||
|                             moveTakerTokensTo(sellToken, pair, sellAmount) | ||||
|                         } | ||||
|                         default { | ||||
|                             // If selling BNB, we need to wrap it to WBNB and transfer to the | ||||
|                             // pair contract. | ||||
|                             if iszero(eq(callvalue(), sellAmount)) { | ||||
|                                 revert(0, 0) | ||||
|                             } | ||||
|                             sellToken := mload(0xA40)// Re-assign to WBNB | ||||
|                             // Call `WBNB.deposit{value: sellAmount}()` | ||||
|                             mstore(0xB00, WETH_DEPOSIT_CALL_SELECTOR_32) | ||||
|                             if iszero(call(gas(), sellToken, sellAmount, 0xB00, 0x4, 0x00, 0x0)) { | ||||
|                                 bubbleRevert() | ||||
|                             } | ||||
|                             // Call `WBNB.transfer(pair, sellAmount)` | ||||
|                             mstore(0xB00, ERC20_TRANSFER_CALL_SELECTOR_32) | ||||
|                             mstore(0xB04, pair) | ||||
|                             mstore(0xB24, sellAmount) | ||||
|                             if iszero(call(gas(), sellToken, 0, 0xB00, 0x44, 0x00, 0x0)) { | ||||
|                                 bubbleRevert() | ||||
|                             } | ||||
|                         } | ||||
|                     // No need to check results, if deposit/transfers failed the PancakeSwapPair will | ||||
|                     // reject our trade (or it may succeed if somehow the reserve was out of sync) | ||||
|                     // this is fine for the taker. | ||||
|                 } | ||||
|  | ||||
|                 // Call pair.getReserves(), store the results at `0xC00` | ||||
|                 mstore(0xB00, PANCAKESWAP_PAIR_RESERVES_CALL_SELECTOR_32) | ||||
|                 if iszero(staticcall(gas(), pair, 0xB00, 0x4, 0xC00, 0x40)) { | ||||
|                     bubbleRevert() | ||||
|                 } | ||||
|                 // Revert if the pair contract does not return at least two words. | ||||
|                 if lt(returndatasize(), 0x40) { | ||||
|                     mstore(0, pair) | ||||
|                     revert(0, 32) | ||||
|                 } | ||||
|  | ||||
|                 // Sell amount for this hop is the previous buy amount. | ||||
|                 let pairSellAmount := buyAmount | ||||
|                 // Compute the buy amount based on the pair reserves. | ||||
|                 { | ||||
|                     let sellReserve | ||||
|                     let buyReserve | ||||
|                     switch iszero(pairOrder) | ||||
|                         case 0 { | ||||
|                             // Transpose if pair order is different. | ||||
|                             sellReserve := mload(0xC00) | ||||
|                             buyReserve := mload(0xC20) | ||||
|                         } | ||||
|                         default { | ||||
|                             sellReserve := mload(0xC20) | ||||
|                             buyReserve := mload(0xC00) | ||||
|                         } | ||||
|                     // Ensure that the sellAmount is < 2¹¹². | ||||
|                     if gt(pairSellAmount, MAX_SWAP_AMOUNT) { | ||||
|                         revert(0, 0) | ||||
|                     } | ||||
|                     // Pairs are in the range (0, 2¹¹²) so this shouldn't overflow. | ||||
|                     // buyAmount = (pairSellAmount * 997 * buyReserve) / | ||||
|                     //     (pairSellAmount * 997 + sellReserve * 1000); | ||||
|                     let sellAmountWithFee := mul(pairSellAmount, 997) | ||||
|                     buyAmount := div( | ||||
|                         mul(sellAmountWithFee, buyReserve), | ||||
|                         add(sellAmountWithFee, mul(sellReserve, 1000)) | ||||
|                     ) | ||||
|                 } | ||||
|  | ||||
|                 let receiver | ||||
|                 // Is this the last pair contract? | ||||
|                 switch eq(add(i, 1), numPairs) | ||||
|                     case 0 { | ||||
|                         // Not the last pair contract, so forward bought tokens to | ||||
|                         // the next pair contract. | ||||
|                         nextPair := computePairAddress( | ||||
|                             buyToken, | ||||
|                             loadTokenAddress(add(i, 2)) | ||||
|                         ) | ||||
|                         receiver := nextPair | ||||
|                     } | ||||
|                     default { | ||||
|                         // The last pair contract. | ||||
|                         // Forward directly to taker UNLESS they want BNB back. | ||||
|                         switch eq(buyToken, ETH_TOKEN_ADDRESS_32) | ||||
|                             case 0 { | ||||
|                                 receiver := caller() | ||||
|                             } | ||||
|                             default { | ||||
|                                 receiver := address() | ||||
|                             } | ||||
|                     } | ||||
|  | ||||
|                 // Call pair.swap() | ||||
|                 switch mload(0xA20) // fork | ||||
|                     case 1 { | ||||
|                         mstore(0xB00, BAKERYSWAP_PAIR_SWAP_CALL_SELECTOR_32) | ||||
|                     } | ||||
|                     default { | ||||
|                         mstore(0xB00, PANCAKESWAP_PAIR_SWAP_CALL_SELECTOR_32) | ||||
|                     } | ||||
|                 switch pairOrder | ||||
|                     case 0 { | ||||
|                         mstore(0xB04, buyAmount) | ||||
|                         mstore(0xB24, 0) | ||||
|                     } | ||||
|                     default { | ||||
|                         mstore(0xB04, 0) | ||||
|                         mstore(0xB24, buyAmount) | ||||
|                     } | ||||
|                 mstore(0xB44, receiver) | ||||
|                 mstore(0xB64, 0x80) | ||||
|                 mstore(0xB84, 0) | ||||
|                 if iszero(call(gas(), pair, 0, 0xB00, 0xA4, 0, 0)) { | ||||
|                     bubbleRevert() | ||||
|                 } | ||||
|             } // End for-loop. | ||||
|  | ||||
|             // If buying BNB, unwrap the WBNB first | ||||
|             if eq(buyToken, ETH_TOKEN_ADDRESS_32) { | ||||
|                 // Call `WBNB.withdraw(buyAmount)` | ||||
|                 mstore(0xB00, WETH_WITHDRAW_CALL_SELECTOR_32) | ||||
|                 mstore(0xB04, buyAmount) | ||||
|                 if iszero(call(gas(), mload(0xA40), 0, 0xB00, 0x24, 0x00, 0x0)) { | ||||
|                     bubbleRevert() | ||||
|                 } | ||||
|                 // Transfer BNB to the caller. | ||||
|                 if iszero(call(gas(), caller(), buyAmount, 0xB00, 0x0, 0x00, 0x0)) { | ||||
|                     bubbleRevert() | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Functions /////////////////////////////////////////////////////// | ||||
|  | ||||
|             // Load a token address from the `tokens` calldata argument. | ||||
|             function loadTokenAddress(idx) -> addr { | ||||
|                 addr := and(ADDRESS_MASK, calldataload(add(mload(0xA00), mul(idx, 0x20)))) | ||||
|             } | ||||
|  | ||||
|             // Convert BNB pseudo-token addresses to WBNB. | ||||
|             function normalizeToken(token) -> normalized { | ||||
|                 normalized := token | ||||
|                 // Translate BNB pseudo-tokens to WBNB. | ||||
|                 if eq(token, ETH_TOKEN_ADDRESS_32) { | ||||
|                     normalized := mload(0xA40) | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Compute the address of the PancakeSwapPair contract given two | ||||
|             // tokens. | ||||
|             function computePairAddress(tokenA, tokenB) -> pair { | ||||
|                 // Convert BNB pseudo-token addresses to WBNB. | ||||
|                 tokenA := normalizeToken(tokenA) | ||||
|                 tokenB := normalizeToken(tokenB) | ||||
|                 // There is one contract for every combination of tokens, | ||||
|                 // which is deployed using CREATE2. | ||||
|                 // The derivation of this address is given by: | ||||
|                 //   address(keccak256(abi.encodePacked( | ||||
|                 //       bytes(0xFF), | ||||
|                 //       address(PANCAKESWAP_FACTORY_ADDRESS), | ||||
|                 //       keccak256(abi.encodePacked( | ||||
|                 //           tokenA < tokenB ? tokenA : tokenB, | ||||
|                 //           tokenA < tokenB ? tokenB : tokenA, | ||||
|                 //       )), | ||||
|                 //       bytes32(PANCAKESWAP_PAIR_INIT_CODE_HASH), | ||||
|                 //   ))); | ||||
|  | ||||
|                 // Compute the salt (the hash of the sorted tokens). | ||||
|                 // Tokens are written in reverse memory order to packed encode | ||||
|                 // them as two 20-byte values in a 40-byte chunk of memory | ||||
|                 // starting at 0xB0C. | ||||
|                 switch lt(tokenA, tokenB) | ||||
|                     case 0 { | ||||
|                         mstore(0xB14, tokenA) | ||||
|                         mstore(0xB00, tokenB) | ||||
|                     } | ||||
|                     default { | ||||
|                         mstore(0xB14, tokenB) | ||||
|                         mstore(0xB00, tokenA) | ||||
|                     } | ||||
|                 let salt := keccak256(0xB0C, 0x28) | ||||
|                 // Compute the pair address by hashing all the components together. | ||||
|                 switch mload(0xA20) // fork | ||||
|                     case 0 { | ||||
|                         mstore(0xB00, FF_PANCAKESWAP_FACTORY) | ||||
|                         mstore(0xB15, salt) | ||||
|                         mstore(0xB35, PANCAKESWAP_PAIR_INIT_CODE_HASH) | ||||
|                     } | ||||
|                     case 1 { | ||||
|                         mstore(0xB00, FF_BAKERYSWAP_FACTORY) | ||||
|                         mstore(0xB15, salt) | ||||
|                         mstore(0xB35, BAKERYSWAP_PAIR_INIT_CODE_HASH) | ||||
|                     } | ||||
|                     default { | ||||
|                         mstore(0xB00, FF_SUSHISWAP_FACTORY) | ||||
|                         mstore(0xB15, salt) | ||||
|                         mstore(0xB35, SUSHISWAP_PAIR_INIT_CODE_HASH) | ||||
|                     } | ||||
|                 pair := and(ADDRESS_MASK, keccak256(0xB00, 0x55)) | ||||
|             } | ||||
|  | ||||
|             // Revert with the return data from the most recent call. | ||||
|             function bubbleRevert() { | ||||
|                 returndatacopy(0, 0, returndatasize()) | ||||
|                 revert(0, returndatasize()) | ||||
|             } | ||||
|  | ||||
|             // Move `amount` tokens from the taker/caller to `to`. | ||||
|             function moveTakerTokensTo(token, to, amount) { | ||||
|                 // Perform a `transferFrom()` | ||||
|                 mstore(0xB00, TRANSFER_FROM_CALL_SELECTOR_32) | ||||
|                 mstore(0xB04, caller()) | ||||
|                 mstore(0xB24, to) | ||||
|                 mstore(0xB44, amount) | ||||
|  | ||||
|                 let success := call( | ||||
|                     gas(), | ||||
|                     token, | ||||
|                     0, | ||||
|                     0xB00, | ||||
|                     0x64, | ||||
|                     0xC00, | ||||
|                     // Copy only the first 32 bytes of return data. We | ||||
|                     // only care about reading a boolean in the success | ||||
|                     // case. We will use returndatacopy() in the failure case. | ||||
|                     0x20 | ||||
|                 ) | ||||
|  | ||||
|                 let rdsize := returndatasize() | ||||
|  | ||||
|                 // Check for ERC20 success. ERC20 tokens should | ||||
|                 // return a boolean, but some return nothing or | ||||
|                 // extra data. We accept 0-length return data as | ||||
|                 // success, or at least 32 bytes that starts with | ||||
|                 // a 32-byte boolean true. | ||||
|                 success := and( | ||||
|                     success,                         // call itself succeeded | ||||
|                     or( | ||||
|                         iszero(rdsize),              // no return data, or | ||||
|                         and( | ||||
|                             iszero(lt(rdsize, 32)),  // at least 32 bytes | ||||
|                             eq(mload(0xC00), 1)      // starts with uint256(1) | ||||
|                         ) | ||||
|                     ) | ||||
|                 ) | ||||
|  | ||||
|                 if iszero(success) { | ||||
|                     // Revert with the data returned from the transferFrom call. | ||||
|                     returndatacopy(0, 0, rdsize) | ||||
|                     revert(0, rdsize) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Revert if we bought too little. | ||||
|         require(buyAmount >= minBuyAmount, "PancakeSwapFeature/UnderBought"); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										137
									
								
								contracts/zero-ex/contracts/src/features/TokenSpenderFeature.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								contracts/zero-ex/contracts/src/features/TokenSpenderFeature.sol
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,137 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 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.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; | ||||
| import "../errors/LibSpenderRichErrors.sol"; | ||||
| import "../fixins/FixinCommon.sol"; | ||||
| import "../migrations/LibMigrate.sol"; | ||||
| import "../external/IAllowanceTarget.sol"; | ||||
| import "../storage/LibTokenSpenderStorage.sol"; | ||||
| import "./interfaces/IFeature.sol"; | ||||
| import "./interfaces/ITokenSpenderFeature.sol"; | ||||
|  | ||||
|  | ||||
| /// @dev Feature that allows spending token allowances. | ||||
| contract TokenSpenderFeature is | ||||
|     IFeature, | ||||
|     ITokenSpenderFeature, | ||||
|     FixinCommon | ||||
| { | ||||
|     // solhint-disable | ||||
|     /// @dev Name of this feature. | ||||
|     string public constant override FEATURE_NAME = "TokenSpender"; | ||||
|     /// @dev Version of this feature. | ||||
|     uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0); | ||||
|     // solhint-enable | ||||
|  | ||||
|     using LibRichErrorsV06 for bytes; | ||||
|  | ||||
|     /// @dev Initialize and register this feature. Should be delegatecalled | ||||
|     ///      into during a `Migrate.migrate()`. | ||||
|     /// @param allowanceTarget An `allowanceTarget` instance, configured to have | ||||
|     ///        the ZeroeEx contract as an authority. | ||||
|     /// @return success `MIGRATE_SUCCESS` on success. | ||||
|     function migrate(IAllowanceTarget allowanceTarget) | ||||
|         external | ||||
|         returns (bytes4 success) | ||||
|     { | ||||
|         LibTokenSpenderStorage.getStorage().allowanceTarget = allowanceTarget; | ||||
|         _registerFeatureFunction(this.getAllowanceTarget.selector); | ||||
|         _registerFeatureFunction(this._spendERC20Tokens.selector); | ||||
|         _registerFeatureFunction(this.getSpendableERC20BalanceOf.selector); | ||||
|         return LibMigrate.MIGRATE_SUCCESS; | ||||
|     } | ||||
|  | ||||
|     /// @dev Transfers ERC20 tokens from `owner` to `to`. Only callable from within. | ||||
|     /// @param token The token to spend. | ||||
|     /// @param owner The owner of the tokens. | ||||
|     /// @param to The recipient of the tokens. | ||||
|     /// @param amount The amount of `token` to transfer. | ||||
|     function _spendERC20Tokens( | ||||
|         IERC20TokenV06 token, | ||||
|         address owner, | ||||
|         address to, | ||||
|         uint256 amount | ||||
|     ) | ||||
|         external | ||||
|         override | ||||
|         onlySelf | ||||
|     { | ||||
|         IAllowanceTarget spender = LibTokenSpenderStorage.getStorage().allowanceTarget; | ||||
|         // Have the allowance target execute an ERC20 `transferFrom()`. | ||||
|         (bool didSucceed, bytes memory resultData) = address(spender).call( | ||||
|             abi.encodeWithSelector( | ||||
|                 IAllowanceTarget.executeCall.selector, | ||||
|                 address(token), | ||||
|                 abi.encodeWithSelector( | ||||
|                     IERC20TokenV06.transferFrom.selector, | ||||
|                     owner, | ||||
|                     to, | ||||
|                     amount | ||||
|                 ) | ||||
|             ) | ||||
|         ); | ||||
|         if (didSucceed) { | ||||
|             resultData = abi.decode(resultData, (bytes)); | ||||
|         } | ||||
|         if (!didSucceed || !LibERC20TokenV06.isSuccessfulResult(resultData)) { | ||||
|             LibSpenderRichErrors.SpenderERC20TransferFromFailedError( | ||||
|                 address(token), | ||||
|                 owner, | ||||
|                 to, | ||||
|                 amount, | ||||
|                 resultData | ||||
|             ).rrevert(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// @dev Gets the maximum amount of an ERC20 token `token` that can be | ||||
|     ///      pulled from `owner` by the token spender. | ||||
|     /// @param token The token to spend. | ||||
|     /// @param owner The owner of the tokens. | ||||
|     /// @return amount The amount of tokens that can be pulled. | ||||
|     function getSpendableERC20BalanceOf(IERC20TokenV06 token, address owner) | ||||
|         external | ||||
|         override | ||||
|         view | ||||
|         returns (uint256 amount) | ||||
|     { | ||||
|         return LibSafeMathV06.min256( | ||||
|             token.allowance(owner, address(LibTokenSpenderStorage.getStorage().allowanceTarget)), | ||||
|             token.balanceOf(owner) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /// @dev Get the address of the allowance target. | ||||
|     /// @return target The target of token allowances. | ||||
|     function getAllowanceTarget() | ||||
|         external | ||||
|         override | ||||
|         view | ||||
|         returns (address target) | ||||
|     { | ||||
|         return address(LibTokenSpenderStorage.getStorage().allowanceTarget); | ||||
|     } | ||||
| } | ||||
| @@ -60,7 +60,10 @@ contract TransformERC20Feature is | ||||
|     /// @dev Version of this feature. | ||||
|     uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 3, 1); | ||||
|  | ||||
|     constructor() public {} | ||||
|     constructor(bytes32 greedyTokensBloomFilter) | ||||
|         public | ||||
|         FixinTokenSpender(greedyTokensBloomFilter) | ||||
|     {} | ||||
|  | ||||
|     /// @dev Initialize and register this feature. | ||||
|     ///      Should be delegatecalled by `Migrate.migrate()`. | ||||
|   | ||||
| @@ -23,6 +23,7 @@ pragma experimental ABIEncoderV2; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol"; | ||||
| import "../migrations/LibMigrate.sol"; | ||||
| import "../external/IAllowanceTarget.sol"; | ||||
| import "../fixins/FixinCommon.sol"; | ||||
| import "./interfaces/IFeature.sol"; | ||||
| import "./interfaces/IUniswapFeature.sol"; | ||||
| @@ -37,9 +38,13 @@ contract UniswapFeature is | ||||
|     /// @dev Name of this feature. | ||||
|     string public constant override FEATURE_NAME = "UniswapFeature"; | ||||
|     /// @dev Version of this feature. | ||||
|     uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 2); | ||||
|     uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 1); | ||||
|     /// @dev A bloom filter for tokens that consume all gas when `transferFrom()` fails. | ||||
|     bytes32 public immutable GREEDY_TOKENS_BLOOM_FILTER; | ||||
|     /// @dev WETH contract. | ||||
|     IEtherTokenV06 private immutable WETH; | ||||
|     /// @dev AllowanceTarget instance. | ||||
|     IAllowanceTarget private immutable ALLOWANCE_TARGET; | ||||
|  | ||||
|     // 0xFF + address of the UniswapV2Factory contract. | ||||
|     uint256 constant private FF_UNISWAP_FACTORY = 0xFF5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f0000000000000000000000; | ||||
| @@ -75,8 +80,16 @@ contract UniswapFeature is | ||||
|  | ||||
|     /// @dev Construct this contract. | ||||
|     /// @param weth The WETH contract. | ||||
|     constructor(IEtherTokenV06 weth) public { | ||||
|     /// @param allowanceTarget The AllowanceTarget contract. | ||||
|     /// @param greedyTokensBloomFilter The bloom filter for greedy tokens. | ||||
|     constructor( | ||||
|         IEtherTokenV06 weth, | ||||
|         IAllowanceTarget allowanceTarget, | ||||
|         bytes32 greedyTokensBloomFilter | ||||
|     ) public { | ||||
|         WETH = weth; | ||||
|         ALLOWANCE_TARGET = allowanceTarget; | ||||
|         GREEDY_TOKENS_BLOOM_FILTER = greedyTokensBloomFilter; | ||||
|     } | ||||
|  | ||||
|     /// @dev Initialize and register this feature. | ||||
| @@ -111,6 +124,8 @@ contract UniswapFeature is | ||||
|         { | ||||
|             // Load immutables onto the stack. | ||||
|             IEtherTokenV06 weth = WETH; | ||||
|             IAllowanceTarget allowanceTarget = ALLOWANCE_TARGET; | ||||
|             bytes32 greedyTokensBloomFilter = GREEDY_TOKENS_BLOOM_FILTER; | ||||
|  | ||||
|             // Store some vars in memory to get around stack limits. | ||||
|             assembly { | ||||
| @@ -120,6 +135,10 @@ contract UniswapFeature is | ||||
|                 mstore(0xA20, isSushi) | ||||
|                 // mload(0xA40) == WETH | ||||
|                 mstore(0xA40, weth) | ||||
|                 // mload(0xA60) == ALLOWANCE_TARGET | ||||
|                 mstore(0xA60, allowanceTarget) | ||||
|                 // mload(0xA80) == GREEDY_TOKENS_BLOOM_FILTER | ||||
|                 mstore(0xA80, greedyTokensBloomFilter) | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -354,7 +373,38 @@ contract UniswapFeature is | ||||
|  | ||||
|             // Move `amount` tokens from the taker/caller to `to`. | ||||
|             function moveTakerTokensTo(token, to, amount) { | ||||
|                 // Perform a `transferFrom()` | ||||
|  | ||||
|                 // If the token is possibly greedy, we check the allowance rather | ||||
|                 // than relying on letting the transferFrom() call fail and | ||||
|                 // falling through to legacy allowance target because the token | ||||
|                 // will eat all our gas. | ||||
|                 if isTokenPossiblyGreedy(token) { | ||||
|                     // Check if we have enough direct allowance by calling | ||||
|                     // `token.allowance()` | ||||
|                     mstore(0xB00, ALLOWANCE_CALL_SELECTOR_32) | ||||
|                     mstore(0xB04, caller()) | ||||
|                     mstore(0xB24, address()) | ||||
|                     let success := staticcall(gas(), token, 0xB00, 0x44, 0xC00, 0x20) | ||||
|                     if iszero(success) { | ||||
|                         // Call to allowance() failed. | ||||
|                         bubbleRevert() | ||||
|                     } | ||||
|                     // Make sure the allowance call returned at least a word. | ||||
|                     if lt(returndatasize(), 0x20) { | ||||
|                         revert(0, 0) | ||||
|                     } | ||||
|                     // Call succeeded. | ||||
|                     // Result is stored in 0xC00-0xC20. | ||||
|                     if lt(mload(0xC00), amount) { | ||||
|                         // We don't have enough direct allowance, so try | ||||
|                         // going through the legacy allowance taregt. | ||||
|                         moveTakerTokensToWithLegacyAllowanceTarget(token, to, amount) | ||||
|                         leave | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 // Otherwise we will optimistically try to perform a `transferFrom()` | ||||
|                 // directly then if it fails we will go through the legacy allowance target. | ||||
|                 mstore(0xB00, TRANSFER_FROM_CALL_SELECTOR_32) | ||||
|                 mstore(0xB04, caller()) | ||||
|                 mstore(0xB24, to) | ||||
| @@ -369,7 +419,8 @@ contract UniswapFeature is | ||||
|                     0xC00, | ||||
|                     // Copy only the first 32 bytes of return data. We | ||||
|                     // only care about reading a boolean in the success | ||||
|                     // case. We will use returndatacopy() in the failure case. | ||||
|                     // case, and we discard the return data in the | ||||
|                     // failure case. | ||||
|                     0x20 | ||||
|                 ) | ||||
|  | ||||
| @@ -392,11 +443,37 @@ contract UniswapFeature is | ||||
|                 ) | ||||
|  | ||||
|                 if iszero(success) { | ||||
|                     // Revert with the data returned from the transferFrom call. | ||||
|                     returndatacopy(0, 0, rdsize) | ||||
|                     revert(0, rdsize) | ||||
|                     // Try to fall back to the allowance target. | ||||
|                     moveTakerTokensToWithLegacyAllowanceTarget(token, to, amount) | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Move tokens by going through the legacy allowance target contract. | ||||
|             function moveTakerTokensToWithLegacyAllowanceTarget(token, to, amount) { | ||||
|                 mstore(0xB00, ALLOWANCE_TARGET_EXECUTE_CALL_SELECTOR_32) | ||||
|                 mstore(0xB04, token) | ||||
|                 mstore(0xB24, 0x40) | ||||
|                 mstore(0xB44, 0x64) | ||||
|                 mstore(0xB64, TRANSFER_FROM_CALL_SELECTOR_32) | ||||
|                 mstore(0xB68, caller()) | ||||
|                 mstore(0xB88, to) | ||||
|                 mstore(0xBA8, amount) | ||||
|                 if iszero(call(gas(), mload(0xA60), 0, 0xB00, 0xC8, 0x00, 0x0)) { | ||||
|                     bubbleRevert() | ||||
|                 } | ||||
|                 // If this fall back failed, the swap will most likely fail | ||||
|                 // so there's no need to validate the result. | ||||
|             } | ||||
|  | ||||
|             // Checks if a token possibly belongs to the GREEDY_TOKENS_BLOOM_FILTER | ||||
|             // bloom filter. | ||||
|             function isTokenPossiblyGreedy(token) -> isPossiblyGreedy { | ||||
|                 // The hash is given by: | ||||
|                 // (1 << (keccak256(token) % 256)) | (1 << (token % 256)) | ||||
|                 mstore(0, token) | ||||
|                 let h := or(shl(mod(keccak256(0, 32), 256), 1), shl(mod(token, 256), 1)) | ||||
|                 isPossiblyGreedy := eq(and(h, mload(0xA80)), h) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Revert if we bought too little. | ||||
|   | ||||
| @@ -113,14 +113,4 @@ interface INativeOrdersEvents { | ||||
|         address[] addrs, | ||||
|         bool allowed | ||||
|     ); | ||||
|  | ||||
|     /// @dev Emitted when new order signers are registered | ||||
|     /// @param maker The maker address that is registering a designated signer. | ||||
|     /// @param signer The address that will sign on behalf of maker. | ||||
|     /// @param allowed Indicates whether the address should be allowed. | ||||
|     event OrderSignerRegistered( | ||||
|         address maker, | ||||
|         address signer, | ||||
|         bool allowed | ||||
|     ); | ||||
| } | ||||
|   | ||||
| @@ -137,13 +137,13 @@ interface INativeOrdersFeature is | ||||
|         external | ||||
|         returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount); | ||||
|  | ||||
|     /// @dev Cancel a single limit order. The caller must be the maker or a valid order signer. | ||||
|     /// @dev Cancel a single limit order. The caller must be the maker. | ||||
|     ///      Silently succeeds if the order has already been cancelled. | ||||
|     /// @param order The limit order. | ||||
|     function cancelLimitOrder(LibNativeOrder.LimitOrder calldata order) | ||||
|         external; | ||||
|  | ||||
|     /// @dev Cancel a single RFQ order. The caller must be the maker or a valid order signer. | ||||
|     /// @dev Cancel a single RFQ order. The caller must be the maker. | ||||
|     ///      Silently succeeds if the order has already been cancelled. | ||||
|     /// @param order The RFQ order. | ||||
|     function cancelRfqOrder(LibNativeOrder.RfqOrder calldata order) | ||||
| @@ -156,13 +156,13 @@ interface INativeOrdersFeature is | ||||
|     function registerAllowedRfqOrigins(address[] memory origins, bool allowed) | ||||
|         external; | ||||
|  | ||||
|     /// @dev Cancel multiple limit orders. The caller must be the maker or a valid order signer. | ||||
|     /// @dev Cancel multiple limit orders. The caller must be the maker. | ||||
|     ///      Silently succeeds if the order has already been cancelled. | ||||
|     /// @param orders The limit orders. | ||||
|     function batchCancelLimitOrders(LibNativeOrder.LimitOrder[] calldata orders) | ||||
|         external; | ||||
|  | ||||
|     /// @dev Cancel multiple RFQ orders. The caller must be the maker or a valid order signer. | ||||
|     /// @dev Cancel multiple RFQ orders. The caller must be the maker. | ||||
|     ///      Silently succeeds if the order has already been cancelled. | ||||
|     /// @param orders The RFQ orders. | ||||
|     function batchCancelRfqOrders(LibNativeOrder.RfqOrder[] calldata orders) | ||||
| @@ -183,23 +183,7 @@ interface INativeOrdersFeature is | ||||
|         external; | ||||
|  | ||||
|     /// @dev Cancel all limit orders for a given maker and pair with a salt less | ||||
|     ///      than the value provided. The caller must be a signer registered to the maker. | ||||
|     ///      Subsequent calls to this function with the same maker and pair require the | ||||
|     ///      new salt to be >= the old salt. | ||||
|     /// @param maker The maker for which to cancel. | ||||
|     /// @param makerToken The maker token. | ||||
|     /// @param takerToken The taker token. | ||||
|     /// @param minValidSalt The new minimum valid salt. | ||||
|     function cancelPairLimitOrdersWithSigner( | ||||
|         address maker, | ||||
|         IERC20TokenV06 makerToken, | ||||
|         IERC20TokenV06 takerToken, | ||||
|         uint256 minValidSalt | ||||
|     ) | ||||
|         external; | ||||
|  | ||||
|     /// @dev Cancel all limit orders for a given maker and pairs with salts less | ||||
|     ///      than the values provided. The caller must be the maker. Subsequent | ||||
|     ///      than the value provided. The caller must be the maker. Subsequent | ||||
|     ///      calls to this function with the same caller and pair require the | ||||
|     ///      new salt to be >= the old salt. | ||||
|     /// @param makerTokens The maker tokens. | ||||
| @@ -212,22 +196,6 @@ interface INativeOrdersFeature is | ||||
|     ) | ||||
|         external; | ||||
|  | ||||
|     /// @dev Cancel all limit orders for a given maker and pairs with salts less | ||||
|     ///      than the values provided. The caller must be a signer registered to the maker. | ||||
|     ///      Subsequent calls to this function with the same maker and pair require the | ||||
|     ///      new salt to be >= the old salt. | ||||
|     /// @param maker The maker for which to cancel. | ||||
|     /// @param makerTokens The maker tokens. | ||||
|     /// @param takerTokens The taker tokens. | ||||
|     /// @param minValidSalts The new minimum valid salts. | ||||
|     function batchCancelPairLimitOrdersWithSigner( | ||||
|         address maker, | ||||
|         IERC20TokenV06[] memory makerTokens, | ||||
|         IERC20TokenV06[] memory takerTokens, | ||||
|         uint256[] memory minValidSalts | ||||
|     ) | ||||
|         external; | ||||
|  | ||||
|     /// @dev Cancel all RFQ orders for a given maker and pair with a salt less | ||||
|     ///      than the value provided. The caller must be the maker. Subsequent | ||||
|     ///      calls to this function with the same caller and pair require the | ||||
| @@ -243,23 +211,7 @@ interface INativeOrdersFeature is | ||||
|         external; | ||||
|  | ||||
|     /// @dev Cancel all RFQ orders for a given maker and pair with a salt less | ||||
|     ///      than the value provided. The caller must be a signer registered to the maker. | ||||
|     ///      Subsequent calls to this function with the same maker and pair require the | ||||
|     ///      new salt to be >= the old salt. | ||||
|     /// @param maker The maker for which to cancel. | ||||
|     /// @param makerToken The maker token. | ||||
|     /// @param takerToken The taker token. | ||||
|     /// @param minValidSalt The new minimum valid salt. | ||||
|     function cancelPairRfqOrdersWithSigner( | ||||
|         address maker, | ||||
|         IERC20TokenV06 makerToken, | ||||
|         IERC20TokenV06 takerToken, | ||||
|         uint256 minValidSalt | ||||
|     ) | ||||
|         external; | ||||
|  | ||||
|     /// @dev Cancel all RFQ orders for a given maker and pairs with salts less | ||||
|     ///      than the values provided. The caller must be the maker. Subsequent | ||||
|     ///      than the value provided. The caller must be the maker. Subsequent | ||||
|     ///      calls to this function with the same caller and pair require the | ||||
|     ///      new salt to be >= the old salt. | ||||
|     /// @param makerTokens The maker tokens. | ||||
| @@ -272,22 +224,6 @@ interface INativeOrdersFeature is | ||||
|     ) | ||||
|         external; | ||||
|  | ||||
|     /// @dev Cancel all RFQ orders for a given maker and pairs with salts less | ||||
|     ///      than the values provided. The caller must be a signer registered to the maker. | ||||
|     ///      Subsequent calls to this function with the same maker and pair require the | ||||
|     ///      new salt to be >= the old salt. | ||||
|     /// @param maker The maker for which to cancel. | ||||
|     /// @param makerTokens The maker tokens. | ||||
|     /// @param takerTokens The taker tokens. | ||||
|     /// @param minValidSalts The new minimum valid salts. | ||||
|     function batchCancelPairRfqOrdersWithSigner( | ||||
|         address maker, | ||||
|         IERC20TokenV06[] memory makerTokens, | ||||
|         IERC20TokenV06[] memory takerTokens, | ||||
|         uint256[] memory minValidSalts | ||||
|     ) | ||||
|         external; | ||||
|  | ||||
|     /// @dev Get the order info for a limit order. | ||||
|     /// @param order The limit order. | ||||
|     /// @return orderInfo Info about the order. | ||||
| @@ -409,25 +345,4 @@ interface INativeOrdersFeature is | ||||
|             uint128[] memory actualFillableTakerTokenAmounts, | ||||
|             bool[] memory isSignatureValids | ||||
|         ); | ||||
|  | ||||
|     /// @dev Register a signer who can sign on behalf of msg.sender | ||||
|     ///      This allows one to sign on behalf of a contract that calls this function | ||||
|     /// @param signer The address from which you plan to generate signatures | ||||
|     /// @param allowed True to register, false to unregister. | ||||
|     function registerAllowedOrderSigner( | ||||
|         address signer, | ||||
|         bool allowed | ||||
|     ) | ||||
|         external; | ||||
|  | ||||
|     /// @dev checks if a given address is registered to sign on behalf of a maker address | ||||
|     /// @param maker The maker address encoded in an order (can be a contract) | ||||
|     /// @param signer The address that is providing a signature | ||||
|     function isValidOrderSigner( | ||||
|         address maker, | ||||
|         address signer | ||||
|     ) | ||||
|         external | ||||
|         view | ||||
|         returns (bool isAllowed); | ||||
| } | ||||
|   | ||||
| @@ -1,50 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2021 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.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
|  | ||||
|  | ||||
| /// @dev VIP PancakeSwap/BakerySwap/SushiSwap fill functions. | ||||
| interface IPancakeSwapFeature { | ||||
|  | ||||
|     enum ProtocolFork { | ||||
|         PancakeSwap, | ||||
|         BakerySwap, | ||||
|         SushiSwap | ||||
|     } | ||||
|  | ||||
|     /// @dev Efficiently sell directly to PancakeSwap/BakerySwap/Sushiswap. | ||||
|     /// @param tokens Sell path. | ||||
|     /// @param sellAmount of `tokens[0]` Amount to sell. | ||||
|     /// @param minBuyAmount Minimum amount of `tokens[-1]` to buy. | ||||
|     /// @param fork The protocol fork to use. | ||||
|     /// @return buyAmount Amount of `tokens[-1]` bought. | ||||
|     function sellToPancakeSwap( | ||||
|         IERC20TokenV06[] calldata tokens, | ||||
|         uint256 sellAmount, | ||||
|         uint256 minBuyAmount, | ||||
|         ProtocolFork fork | ||||
|     ) | ||||
|         external | ||||
|         payable | ||||
|         returns (uint256 buyAmount); | ||||
| } | ||||
| @@ -40,22 +40,23 @@ abstract contract NativeOrdersCancellation is | ||||
|     uint256 private constant HIGH_BIT = 1 << 255; | ||||
|  | ||||
|     constructor( | ||||
|         address zeroExAddress | ||||
|         address zeroExAddress, | ||||
|         bytes32 greedyTokensBloomFilter | ||||
|     ) | ||||
|         internal | ||||
|         NativeOrdersInfo(zeroExAddress) | ||||
|         NativeOrdersInfo(zeroExAddress, greedyTokensBloomFilter) | ||||
|     { | ||||
|         // solhint-disable no-empty-blocks | ||||
|     } | ||||
|  | ||||
|     /// @dev Cancel a single limit order. The caller must be the maker or a valid order signer. | ||||
|     /// @dev Cancel a single limit order. The caller must be the maker. | ||||
|     ///      Silently succeeds if the order has already been cancelled. | ||||
|     /// @param order The limit order. | ||||
|     function cancelLimitOrder(LibNativeOrder.LimitOrder memory order) | ||||
|         public | ||||
|     { | ||||
|         bytes32 orderHash = getLimitOrderHash(order); | ||||
|         if (msg.sender != order.maker && !isValidOrderSigner(order.maker, msg.sender)) { | ||||
|         if (msg.sender != order.maker) { | ||||
|             LibNativeOrdersRichErrors.OnlyOrderMakerAllowed( | ||||
|                 orderHash, | ||||
|                 msg.sender, | ||||
| @@ -65,14 +66,14 @@ abstract contract NativeOrdersCancellation is | ||||
|         _cancelOrderHash(orderHash, order.maker); | ||||
|     } | ||||
|  | ||||
|     /// @dev Cancel a single RFQ order. The caller must be the maker or a valid order signer. | ||||
|     /// @dev Cancel a single RFQ order. The caller must be the maker. | ||||
|     ///      Silently succeeds if the order has already been cancelled. | ||||
|     /// @param order The RFQ order. | ||||
|     function cancelRfqOrder(LibNativeOrder.RfqOrder memory order) | ||||
|         public | ||||
|     { | ||||
|         bytes32 orderHash = getRfqOrderHash(order); | ||||
|         if (msg.sender != order.maker && !isValidOrderSigner(order.maker, msg.sender)) { | ||||
|         if (msg.sender != order.maker) { | ||||
|             LibNativeOrdersRichErrors.OnlyOrderMakerAllowed( | ||||
|                 orderHash, | ||||
|                 msg.sender, | ||||
| @@ -82,7 +83,7 @@ abstract contract NativeOrdersCancellation is | ||||
|         _cancelOrderHash(orderHash, order.maker); | ||||
|     } | ||||
|  | ||||
|     /// @dev Cancel multiple limit orders. The caller must be the maker or a valid order signer. | ||||
|     /// @dev Cancel multiple limit orders. The caller must be the maker. | ||||
|     ///      Silently succeeds if the order has already been cancelled. | ||||
|     /// @param orders The limit orders. | ||||
|     function batchCancelLimitOrders(LibNativeOrder.LimitOrder[] memory orders) | ||||
| @@ -93,7 +94,7 @@ abstract contract NativeOrdersCancellation is | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// @dev Cancel multiple RFQ orders. The caller must be the maker or a valid order signer. | ||||
|     /// @dev Cancel multiple RFQ orders. The caller must be the maker. | ||||
|     ///      Silently succeeds if the order has already been cancelled. | ||||
|     /// @param orders The RFQ orders. | ||||
|     function batchCancelRfqOrders(LibNativeOrder.RfqOrder[] memory orders) | ||||
| @@ -118,34 +119,33 @@ abstract contract NativeOrdersCancellation is | ||||
|     ) | ||||
|         public | ||||
|     { | ||||
|         _cancelPairLimitOrders(msg.sender, makerToken, takerToken, minValidSalt); | ||||
|     } | ||||
|         LibNativeOrdersStorage.Storage storage stor = | ||||
|             LibNativeOrdersStorage.getStorage(); | ||||
|  | ||||
|     /// @dev Cancel all limit orders for a given maker and pair with a salt less | ||||
|     ///      than the value provided. The caller must be a signer registered to the maker. | ||||
|     ///      Subsequent calls to this function with the same caller and pair require the | ||||
|     ///      new salt to be >= the old salt. | ||||
|     /// @param maker the maker for whom the msg.sender is the signer. | ||||
|     /// @param makerToken The maker token. | ||||
|     /// @param takerToken The taker token. | ||||
|     /// @param minValidSalt The new minimum valid salt. | ||||
|     function cancelPairLimitOrdersWithSigner( | ||||
|         address maker, | ||||
|         IERC20TokenV06 makerToken, | ||||
|         IERC20TokenV06 takerToken, | ||||
|         uint256 minValidSalt | ||||
|     ) | ||||
|         public | ||||
|     { | ||||
|         // verify that the signer is authorized for the maker | ||||
|         if (!isValidOrderSigner(maker, msg.sender)) { | ||||
|             LibNativeOrdersRichErrors.InvalidSignerError( | ||||
|                 maker, | ||||
|                 msg.sender | ||||
|             ).rrevert(); | ||||
|         uint256 oldMinValidSalt = | ||||
|             stor.limitOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt | ||||
|                 [msg.sender] | ||||
|                 [address(makerToken)] | ||||
|                 [address(takerToken)]; | ||||
|  | ||||
|         // New min salt must >= the old one. | ||||
|         if (oldMinValidSalt > minValidSalt) { | ||||
|             LibNativeOrdersRichErrors. | ||||
|                 CancelSaltTooLowError(minValidSalt, oldMinValidSalt) | ||||
|                     .rrevert(); | ||||
|         } | ||||
|  | ||||
|         _cancelPairLimitOrders(maker, makerToken, takerToken, minValidSalt); | ||||
|         stor.limitOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt | ||||
|             [msg.sender] | ||||
|             [address(makerToken)] | ||||
|             [address(takerToken)] = minValidSalt; | ||||
|  | ||||
|         emit PairCancelledLimitOrders( | ||||
|             msg.sender, | ||||
|             address(makerToken), | ||||
|             address(takerToken), | ||||
|             minValidSalt | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /// @dev Cancel all limit orders for a given maker and pair with a salt less | ||||
| @@ -169,47 +169,7 @@ abstract contract NativeOrdersCancellation is | ||||
|         ); | ||||
|  | ||||
|         for (uint256 i = 0; i < makerTokens.length; ++i) { | ||||
|             _cancelPairLimitOrders( | ||||
|                 msg.sender, | ||||
|                 makerTokens[i], | ||||
|                 takerTokens[i], | ||||
|                 minValidSalts[i] | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// @dev Cancel all limit orders for a given maker and pair with a salt less | ||||
|     ///      than the value provided. The caller must be a signer registered to the maker. | ||||
|     ///      Subsequent calls to this function with the same caller and pair require the | ||||
|     ///      new salt to be >= the old salt. | ||||
|     /// @param maker the maker for whom the msg.sender is the signer. | ||||
|     /// @param makerTokens The maker tokens. | ||||
|     /// @param takerTokens The taker tokens. | ||||
|     /// @param minValidSalts The new minimum valid salts. | ||||
|     function batchCancelPairLimitOrdersWithSigner( | ||||
|         address maker, | ||||
|         IERC20TokenV06[] memory makerTokens, | ||||
|         IERC20TokenV06[] memory takerTokens, | ||||
|         uint256[] memory minValidSalts | ||||
|     ) | ||||
|         public | ||||
|     { | ||||
|         require( | ||||
|             makerTokens.length == takerTokens.length && | ||||
|             makerTokens.length == minValidSalts.length, | ||||
|             "NativeOrdersFeature/MISMATCHED_PAIR_ORDERS_ARRAY_LENGTHS" | ||||
|         ); | ||||
|  | ||||
|         if (!isValidOrderSigner(maker, msg.sender)) { | ||||
|             LibNativeOrdersRichErrors.InvalidSignerError( | ||||
|                 maker, | ||||
|                 msg.sender | ||||
|             ).rrevert(); | ||||
|         } | ||||
|  | ||||
|         for (uint256 i = 0; i < makerTokens.length; ++i) { | ||||
|             _cancelPairLimitOrders( | ||||
|                 maker, | ||||
|             cancelPairLimitOrders( | ||||
|                 makerTokens[i], | ||||
|                 takerTokens[i], | ||||
|                 minValidSalts[i] | ||||
| @@ -231,33 +191,33 @@ abstract contract NativeOrdersCancellation is | ||||
|     ) | ||||
|         public | ||||
|     { | ||||
|         _cancelPairRfqOrders(msg.sender, makerToken, takerToken, minValidSalt); | ||||
|     } | ||||
|         LibNativeOrdersStorage.Storage storage stor = | ||||
|             LibNativeOrdersStorage.getStorage(); | ||||
|  | ||||
|     /// @dev Cancel all RFQ orders for a given maker and pair with a salt less | ||||
|     ///      than the value provided. The caller must be a signer registered to the maker. | ||||
|     ///      Subsequent calls to this function with the same caller and pair require the | ||||
|     ///      new salt to be >= the old salt. | ||||
|     /// @param maker the maker for whom the msg.sender is the signer. | ||||
|     /// @param makerToken The maker token. | ||||
|     /// @param takerToken The taker token. | ||||
|     /// @param minValidSalt The new minimum valid salt. | ||||
|     function cancelPairRfqOrdersWithSigner( | ||||
|         address maker, | ||||
|         IERC20TokenV06 makerToken, | ||||
|         IERC20TokenV06 takerToken, | ||||
|         uint256 minValidSalt | ||||
|     ) | ||||
|         public | ||||
|     { | ||||
|         if (!isValidOrderSigner(maker, msg.sender)) { | ||||
|             LibNativeOrdersRichErrors.InvalidSignerError( | ||||
|                 maker, | ||||
|                 msg.sender | ||||
|             ).rrevert(); | ||||
|         uint256 oldMinValidSalt = | ||||
|             stor.rfqOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt | ||||
|                 [msg.sender] | ||||
|                 [address(makerToken)] | ||||
|                 [address(takerToken)]; | ||||
|  | ||||
|         // New min salt must >= the old one. | ||||
|         if (oldMinValidSalt > minValidSalt) { | ||||
|             LibNativeOrdersRichErrors. | ||||
|                 CancelSaltTooLowError(minValidSalt, oldMinValidSalt) | ||||
|                     .rrevert(); | ||||
|         } | ||||
|  | ||||
|         _cancelPairRfqOrders(maker, makerToken, takerToken, minValidSalt); | ||||
|         stor.rfqOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt | ||||
|             [msg.sender] | ||||
|             [address(makerToken)] | ||||
|             [address(takerToken)] = minValidSalt; | ||||
|  | ||||
|         emit PairCancelledRfqOrders( | ||||
|             msg.sender, | ||||
|             address(makerToken), | ||||
|             address(takerToken), | ||||
|             minValidSalt | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /// @dev Cancel all RFQ orders for a given maker and pair with a salt less | ||||
| @@ -281,47 +241,7 @@ abstract contract NativeOrdersCancellation is | ||||
|         ); | ||||
|  | ||||
|         for (uint256 i = 0; i < makerTokens.length; ++i) { | ||||
|             _cancelPairRfqOrders( | ||||
|                 msg.sender, | ||||
|                 makerTokens[i], | ||||
|                 takerTokens[i], | ||||
|                 minValidSalts[i] | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// @dev Cancel all RFQ orders for a given maker and pairs with salts less | ||||
|     ///      than the values provided. The caller must be a signer registered to the maker. | ||||
|     ///      Subsequent calls to this function with the same caller and pair require the | ||||
|     ///      new salt to be >= the old salt. | ||||
|     /// @param maker the maker for whom the msg.sender is the signer. | ||||
|     /// @param makerTokens The maker tokens. | ||||
|     /// @param takerTokens The taker tokens. | ||||
|     /// @param minValidSalts The new minimum valid salts. | ||||
|     function batchCancelPairRfqOrdersWithSigner( | ||||
|         address maker, | ||||
|         IERC20TokenV06[] memory makerTokens, | ||||
|         IERC20TokenV06[] memory takerTokens, | ||||
|         uint256[] memory minValidSalts | ||||
|     ) | ||||
|         public | ||||
|     { | ||||
|         require( | ||||
|             makerTokens.length == takerTokens.length && | ||||
|             makerTokens.length == minValidSalts.length, | ||||
|             "NativeOrdersFeature/MISMATCHED_PAIR_ORDERS_ARRAY_LENGTHS" | ||||
|         ); | ||||
|  | ||||
|         if (!isValidOrderSigner(maker, msg.sender)) { | ||||
|             LibNativeOrdersRichErrors.InvalidSignerError( | ||||
|                 maker, | ||||
|                 msg.sender | ||||
|             ).rrevert(); | ||||
|         } | ||||
|  | ||||
|         for (uint256 i = 0; i < makerTokens.length; ++i) { | ||||
|             _cancelPairRfqOrders( | ||||
|                 maker, | ||||
|             cancelPairRfqOrders( | ||||
|                 makerTokens[i], | ||||
|                 takerTokens[i], | ||||
|                 minValidSalts[i] | ||||
| @@ -343,90 +263,4 @@ abstract contract NativeOrdersCancellation is | ||||
|  | ||||
|         emit OrderCancelled(orderHash, maker); | ||||
|     } | ||||
|  | ||||
|     /// @dev Cancel all RFQ orders for a given maker and pair with a salt less | ||||
|     ///      than the value provided. | ||||
|     /// @param maker The target maker address | ||||
|     /// @param makerToken The maker token. | ||||
|     /// @param takerToken The taker token. | ||||
|     /// @param minValidSalt The new minimum valid salt. | ||||
|     function _cancelPairRfqOrders( | ||||
|         address maker, | ||||
|         IERC20TokenV06 makerToken, | ||||
|         IERC20TokenV06 takerToken, | ||||
|         uint256 minValidSalt | ||||
|     ) | ||||
|         private | ||||
|     { | ||||
|         LibNativeOrdersStorage.Storage storage stor = | ||||
|             LibNativeOrdersStorage.getStorage(); | ||||
|  | ||||
|         uint256 oldMinValidSalt = | ||||
|             stor.rfqOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt | ||||
|                 [maker] | ||||
|                 [address(makerToken)] | ||||
|                 [address(takerToken)]; | ||||
|  | ||||
|         // New min salt must >= the old one. | ||||
|         if (oldMinValidSalt > minValidSalt) { | ||||
|             LibNativeOrdersRichErrors. | ||||
|                 CancelSaltTooLowError(minValidSalt, oldMinValidSalt) | ||||
|                     .rrevert(); | ||||
|         } | ||||
|  | ||||
|         stor.rfqOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt | ||||
|             [maker] | ||||
|             [address(makerToken)] | ||||
|             [address(takerToken)] = minValidSalt; | ||||
|  | ||||
|         emit PairCancelledRfqOrders( | ||||
|             maker, | ||||
|             address(makerToken), | ||||
|             address(takerToken), | ||||
|             minValidSalt | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /// @dev Cancel all limit orders for a given maker and pair with a salt less | ||||
|     ///      than the value provided. | ||||
|     /// @param maker The target maker address | ||||
|     /// @param makerToken The maker token. | ||||
|     /// @param takerToken The taker token. | ||||
|     /// @param minValidSalt The new minimum valid salt. | ||||
|     function _cancelPairLimitOrders( | ||||
|         address maker, | ||||
|         IERC20TokenV06 makerToken, | ||||
|         IERC20TokenV06 takerToken, | ||||
|         uint256 minValidSalt | ||||
|     ) | ||||
|         private | ||||
|     { | ||||
|         LibNativeOrdersStorage.Storage storage stor = | ||||
|             LibNativeOrdersStorage.getStorage(); | ||||
|  | ||||
|         uint256 oldMinValidSalt = | ||||
|             stor.limitOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt | ||||
|                 [maker] | ||||
|                 [address(makerToken)] | ||||
|                 [address(takerToken)]; | ||||
|  | ||||
|         // New min salt must >= the old one. | ||||
|         if (oldMinValidSalt > minValidSalt) { | ||||
|             LibNativeOrdersRichErrors. | ||||
|                 CancelSaltTooLowError(minValidSalt, oldMinValidSalt) | ||||
|                     .rrevert(); | ||||
|         } | ||||
|  | ||||
|         stor.limitOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt | ||||
|             [maker] | ||||
|             [address(makerToken)] | ||||
|             [address(takerToken)] = minValidSalt; | ||||
|  | ||||
|         emit PairCancelledLimitOrders( | ||||
|             maker, | ||||
|             address(makerToken), | ||||
|             address(takerToken), | ||||
|             minValidSalt | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -51,10 +51,12 @@ abstract contract NativeOrdersInfo is | ||||
|     uint256 private constant HIGH_BIT = 1 << 255; | ||||
|  | ||||
|     constructor( | ||||
|         address zeroExAddress | ||||
|         address zeroExAddress, | ||||
|         bytes32 greedyTokensBloomFilter | ||||
|     ) | ||||
|         internal | ||||
|         FixinEIP712(zeroExAddress) | ||||
|         FixinTokenSpender(greedyTokensBloomFilter) | ||||
|     { | ||||
|         // solhint-disable no-empty-blocks | ||||
|     } | ||||
| @@ -168,10 +170,8 @@ abstract contract NativeOrdersInfo is | ||||
|                 orderInfo: orderInfo | ||||
|             }) | ||||
|         ); | ||||
|         address signerOfHash = LibSignature.getSignerOfHash(orderInfo.orderHash, signature); | ||||
|         isSignatureValid = | ||||
|             (order.maker == signerOfHash) || | ||||
|             isValidOrderSigner(order.maker, signerOfHash); | ||||
|         isSignatureValid = order.maker == | ||||
|             LibSignature.getSignerOfHash(orderInfo.orderHash, signature); | ||||
|     } | ||||
|  | ||||
|     /// @dev Get order info, fillable amount, and signature validity for an RFQ order. | ||||
| @@ -204,10 +204,8 @@ abstract contract NativeOrdersInfo is | ||||
|                 orderInfo: orderInfo | ||||
|             }) | ||||
|         ); | ||||
|         address signerOfHash = LibSignature.getSignerOfHash(orderInfo.orderHash, signature); | ||||
|         isSignatureValid = | ||||
|             (order.maker == signerOfHash) || | ||||
|             isValidOrderSigner(order.maker, signerOfHash); | ||||
|         isSignatureValid = order.maker == | ||||
|             LibSignature.getSignerOfHash(orderInfo.orderHash, signature); | ||||
|     } | ||||
|  | ||||
|     /// @dev Batch version of `getLimitOrderRelevantState()`, without reverting. | ||||
| @@ -393,22 +391,4 @@ abstract contract NativeOrdersInfo is | ||||
|             uint256(params.orderTakerAmount) | ||||
|         ).safeDowncastToUint128(); | ||||
|     } | ||||
|  | ||||
|     /// @dev checks if a given address is registered to sign on behalf of a maker address | ||||
|     /// @param maker The maker address encoded in an order (can be a contract) | ||||
|     /// @param signer The address that is providing a signature | ||||
|     function isValidOrderSigner( | ||||
|         address maker, | ||||
|         address signer | ||||
|     ) | ||||
|         public | ||||
|         view | ||||
|         returns (bool isValid) | ||||
|     { | ||||
|         // returns false if it the mapping doesn't exist | ||||
|         return LibNativeOrdersStorage.getStorage() | ||||
|             .orderSignerRegistry | ||||
|                 [maker] | ||||
|                 [signer]; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -96,10 +96,11 @@ abstract contract NativeOrdersSettlement is | ||||
|         IEtherTokenV06 weth, | ||||
|         IStaking staking, | ||||
|         FeeCollectorController feeCollectorController, | ||||
|         uint32 protocolFeeMultiplier | ||||
|         uint32 protocolFeeMultiplier, | ||||
|         bytes32 greedyTokensBloomFilter | ||||
|     ) | ||||
|         public | ||||
|         NativeOrdersCancellation(zeroExAddress) | ||||
|         NativeOrdersCancellation(zeroExAddress, greedyTokensBloomFilter) | ||||
|         NativeOrdersProtocolFees(weth, staking, feeCollectorController, protocolFeeMultiplier) | ||||
|     { | ||||
|         // solhint-disable no-empty-blocks | ||||
| @@ -370,7 +371,7 @@ abstract contract NativeOrdersSettlement is | ||||
|                 orderInfo.orderHash, | ||||
|                 params.signature | ||||
|             ); | ||||
|             if (signer != params.order.maker && !isValidOrderSigner(params.order.maker, signer)) { | ||||
|             if (signer != params.order.maker) { | ||||
|                 LibNativeOrdersRichErrors.OrderNotSignedByMakerError( | ||||
|                     orderInfo.orderHash, | ||||
|                     signer, | ||||
| @@ -478,7 +479,7 @@ abstract contract NativeOrdersSettlement is | ||||
|         // Signature must be valid for the order. | ||||
|         { | ||||
|             address signer = LibSignature.getSignerOfHash(orderInfo.orderHash, signature); | ||||
|             if (signer != order.maker && !isValidOrderSigner(order.maker, signer)) { | ||||
|             if (signer != order.maker) { | ||||
|                 LibNativeOrdersRichErrors.OrderNotSignedByMakerError( | ||||
|                     orderInfo.orderHash, | ||||
|                     signer, | ||||
| @@ -565,21 +566,4 @@ abstract contract NativeOrdersSettlement is | ||||
|             makerTokenFilledAmount | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /// @dev register a signer who can sign on behalf of msg.sender | ||||
|     /// @param signer The address from which you plan to generate signatures | ||||
|     /// @param allowed True to register, false to unregister. | ||||
|     function registerAllowedOrderSigner( | ||||
|         address signer, | ||||
|         bool allowed | ||||
|     ) | ||||
|         external | ||||
|     { | ||||
|         LibNativeOrdersStorage.Storage storage stor = | ||||
|             LibNativeOrdersStorage.getStorage(); | ||||
|  | ||||
|         stor.orderSignerRegistry[msg.sender][signer] = allowed; | ||||
|  | ||||
|         emit OrderSignerRegistered(msg.sender, signer, allowed); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -22,13 +22,28 @@ pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol"; | ||||
| import "../features/interfaces/ITokenSpenderFeature.sol"; | ||||
| import "../errors/LibSpenderRichErrors.sol"; | ||||
| import "../external/FeeCollector.sol"; | ||||
| import "../vendor/v3/IStaking.sol"; | ||||
| import "../vendor/v3/IStaking.sol"; | ||||
|  | ||||
|  | ||||
| /// @dev Helpers for moving tokens around. | ||||
| abstract contract FixinTokenSpender { | ||||
|     using LibRichErrorsV06 for bytes; | ||||
|  | ||||
|     // Mask of the lower 20 bytes of a bytes32. | ||||
|     uint256 constant private ADDRESS_MASK = 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff; | ||||
|     /// @dev A bloom filter for tokens that consume all gas when `transferFrom()` fails. | ||||
|     bytes32 public immutable GREEDY_TOKENS_BLOOM_FILTER; | ||||
|  | ||||
|     /// @param greedyTokensBloomFilter The bloom filter for all greedy tokens. | ||||
|     constructor(bytes32 greedyTokensBloomFilter) | ||||
|         internal | ||||
|     { | ||||
|         GREEDY_TOKENS_BLOOM_FILTER = greedyTokensBloomFilter; | ||||
|     } | ||||
|  | ||||
|     /// @dev Transfers ERC20 tokens from `owner` to `to`. | ||||
|     /// @param token The token to spend. | ||||
| @@ -43,8 +58,29 @@ abstract contract FixinTokenSpender { | ||||
|     ) | ||||
|         internal | ||||
|     { | ||||
|         bool success; | ||||
|         bytes memory revertData; | ||||
|  | ||||
|         require(address(token) != address(this), "FixinTokenSpender/CANNOT_INVOKE_SELF"); | ||||
|  | ||||
|         // If the token eats all gas when failing, we do not want to perform | ||||
|         // optimistic fall through to the old AllowanceTarget contract if the | ||||
|         // direct transferFrom() fails. | ||||
|         if (_isTokenPossiblyGreedy(token)) { | ||||
|             // If the token does not have a direct allowance on us then we use | ||||
|             // the allowance target. | ||||
|             if (token.allowance(owner, address(this)) < amount) { | ||||
|                 _transferFromLegacyAllowanceTarget( | ||||
|                     token, | ||||
|                     owner, | ||||
|                     to, | ||||
|                     amount, | ||||
|                     "" | ||||
|                 ); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         assembly { | ||||
|             let ptr := mload(0x40) // free memory pointer | ||||
|  | ||||
| @@ -54,18 +90,20 @@ abstract contract FixinTokenSpender { | ||||
|             mstore(add(ptr, 0x24), and(to, ADDRESS_MASK)) | ||||
|             mstore(add(ptr, 0x44), amount) | ||||
|  | ||||
|             let success := call( | ||||
|             success := call( | ||||
|                 gas(), | ||||
|                 and(token, ADDRESS_MASK), | ||||
|                 0, | ||||
|                 ptr, | ||||
|                 0x64, | ||||
|                 ptr, | ||||
|                 32 | ||||
|                 0, | ||||
|                 0 | ||||
|             ) | ||||
|  | ||||
|             let rdsize := returndatasize() | ||||
|  | ||||
|             returndatacopy(add(ptr, 0x20), 0, rdsize) // reuse memory | ||||
|  | ||||
|             // Check for ERC20 success. ERC20 tokens should return a boolean, | ||||
|             // but some don't. We accept 0-length return data as success, or at | ||||
|             // least 32 bytes that starts with a 32-byte boolean true. | ||||
| @@ -75,16 +113,30 @@ abstract contract FixinTokenSpender { | ||||
|                     iszero(rdsize),                  // no return data, or | ||||
|                     and( | ||||
|                         iszero(lt(rdsize, 32)),      // at least 32 bytes | ||||
|                         eq(mload(ptr), 1)            // starts with uint256(1) | ||||
|                         eq(mload(add(ptr, 0x20)), 1) // starts with uint256(1) | ||||
|                     ) | ||||
|                 ) | ||||
|             ) | ||||
|  | ||||
|             if iszero(success) { | ||||
|                 returndatacopy(ptr, 0, rdsize) | ||||
|                 revert(ptr, rdsize) | ||||
|                 // revertData is a bytes, so length-prefixed data | ||||
|                 mstore(ptr, rdsize) | ||||
|                 revertData := ptr | ||||
|  | ||||
|                 // update free memory pointer (ptr + 32-byte length + return data) | ||||
|                 mstore(0x40, add(add(ptr, 0x20), rdsize)) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (!success) { | ||||
|             _transferFromLegacyAllowanceTarget( | ||||
|                 token, | ||||
|                 owner, | ||||
|                 to, | ||||
|                 amount, | ||||
|                 revertData | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// @dev Gets the maximum amount of an ERC20 token `token` that can be | ||||
| @@ -105,4 +157,53 @@ abstract contract FixinTokenSpender { | ||||
|             token.balanceOf(owner) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /// @dev Check if a token possibly belongs to the `GREEDY_TOKENS_BLOOM_FILTER` | ||||
|     ///      bloom filter. | ||||
|     function _isTokenPossiblyGreedy(IERC20TokenV06 token) | ||||
|         internal | ||||
|         view | ||||
|         returns (bool isPossiblyGreedy) | ||||
|     { | ||||
|         // The hash is given by: | ||||
|         // (1 << (keccak256(token) % 256)) | (1 << (token % 256)) | ||||
|         bytes32 h; | ||||
|         assembly { | ||||
|             mstore(0, token) | ||||
|             h := or(shl(mod(keccak256(0, 32), 256), 1), shl(mod(token, 256), 1)) | ||||
|         } | ||||
|         return (h & GREEDY_TOKENS_BLOOM_FILTER) == h; | ||||
|     } | ||||
|  | ||||
|     /// @dev Transfer tokens using the legacy allowance target instead of | ||||
|     ///      allowances directly set on the exchange proxy. | ||||
|     function _transferFromLegacyAllowanceTarget( | ||||
|         IERC20TokenV06 token, | ||||
|         address owner, | ||||
|         address to, | ||||
|         uint256 amount, | ||||
|         bytes memory initialRevertData | ||||
|     ) | ||||
|         private | ||||
|     { | ||||
|         // Try the old AllowanceTarget. | ||||
|         try ITokenSpenderFeature(address(this))._spendERC20Tokens( | ||||
|                 token, | ||||
|                 owner, | ||||
|                 to, | ||||
|                 amount | ||||
|             ) { | ||||
|         } catch (bytes memory revertData) { | ||||
|             // Bubble up the first error message. (In general, the fallback to the | ||||
|             // allowance target is opportunistic. We ignore the specific error | ||||
|             // message if it fails.) | ||||
|             LibSpenderRichErrors.SpenderERC20TransferFromFailedError( | ||||
|                 address(token), | ||||
|                 owner, | ||||
|                 to, | ||||
|                 amount, | ||||
|                 initialRevertData.length != 0 ? initialRevertData : revertData | ||||
|             ).rrevert(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -22,9 +22,11 @@ pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "../ZeroEx.sol"; | ||||
| import "../features/interfaces/IOwnableFeature.sol"; | ||||
| import "../features/TokenSpenderFeature.sol"; | ||||
| import "../features/TransformERC20Feature.sol"; | ||||
| import "../features/MetaTransactionsFeature.sol"; | ||||
| import "../features/NativeOrdersFeature.sol"; | ||||
| import "../external/AllowanceTarget.sol"; | ||||
| import "./InitialMigration.sol"; | ||||
|  | ||||
|  | ||||
| @@ -37,6 +39,7 @@ contract FullMigration { | ||||
|     struct Features { | ||||
|         SimpleFunctionRegistryFeature registry; | ||||
|         OwnableFeature ownable; | ||||
|         TokenSpenderFeature tokenSpender; | ||||
|         TransformERC20Feature transformERC20; | ||||
|         MetaTransactionsFeature metaTransactions; | ||||
|         NativeOrdersFeature nativeOrders; | ||||
| @@ -104,7 +107,7 @@ contract FullMigration { | ||||
|         ); | ||||
|  | ||||
|         // Add features. | ||||
|         _addFeatures(zeroEx, features, migrateOpts); | ||||
|         _addFeatures(zeroEx, owner, features, migrateOpts); | ||||
|  | ||||
|         // Transfer ownership to the real owner. | ||||
|         IOwnableFeature(address(zeroEx)).transferOwnership(owner); | ||||
| @@ -129,16 +132,36 @@ contract FullMigration { | ||||
|  | ||||
|     /// @dev Deploy and register features to the ZeroEx contract. | ||||
|     /// @param zeroEx The bootstrapped ZeroEx contract. | ||||
|     /// @param owner The ultimate owner of the ZeroEx contract. | ||||
|     /// @param features Features to add to the proxy. | ||||
|     /// @param migrateOpts Parameters needed to initialize features. | ||||
|     function _addFeatures( | ||||
|         ZeroEx zeroEx, | ||||
|         address owner, | ||||
|         Features memory features, | ||||
|         MigrateOpts memory migrateOpts | ||||
|     ) | ||||
|         private | ||||
|     { | ||||
|         IOwnableFeature ownable = IOwnableFeature(address(zeroEx)); | ||||
|         // TokenSpenderFeature | ||||
|         { | ||||
|             // Create the allowance target. | ||||
|             AllowanceTarget allowanceTarget = new AllowanceTarget(); | ||||
|             // Let the ZeroEx contract use the allowance target. | ||||
|             allowanceTarget.addAuthorizedAddress(address(zeroEx)); | ||||
|             // Transfer ownership of the allowance target to the (real) owner. | ||||
|             allowanceTarget.transferOwnership(owner); | ||||
|             // Register the feature. | ||||
|             ownable.migrate( | ||||
|                 address(features.tokenSpender), | ||||
|                 abi.encodeWithSelector( | ||||
|                     TokenSpenderFeature.migrate.selector, | ||||
|                     allowanceTarget | ||||
|                 ), | ||||
|                 address(this) | ||||
|             ); | ||||
|         } | ||||
|         // TransformERC20Feature | ||||
|         { | ||||
|             // Register the feature. | ||||
|   | ||||
| @@ -43,9 +43,6 @@ library LibNativeOrdersStorage { | ||||
|         // For a given order origin, which tx.origin addresses are allowed to | ||||
|         // fill the order. | ||||
|         mapping(address => mapping(address => bool)) originRegistry; | ||||
|         // For a given maker address, which addresses are allowed to | ||||
|         // sign on its behalf. | ||||
|         mapping(address => mapping(address => bool)) orderSignerRegistry; | ||||
|     } | ||||
|  | ||||
|     /// @dev Get the storage bucket for this contract. | ||||
|   | ||||
| @@ -0,0 +1,46 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 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.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./LibStorage.sol"; | ||||
| import "../external/IAllowanceTarget.sol"; | ||||
|  | ||||
|  | ||||
| /// @dev Storage helpers for the `TokenSpender` feature. | ||||
| library LibTokenSpenderStorage { | ||||
|  | ||||
|     /// @dev Storage bucket for this feature. | ||||
|     struct Storage { | ||||
|         // Allowance target contract. | ||||
|         IAllowanceTarget allowanceTarget; | ||||
|     } | ||||
|  | ||||
|     /// @dev Get the storage bucket for this contract. | ||||
|     function getStorage() internal pure returns (Storage storage stor) { | ||||
|         uint256 storageSlot = LibStorage.getStorageSlot( | ||||
|             LibStorage.StorageId.TokenSpender | ||||
|         ); | ||||
|         // Dip into assembly to change the slot pointed to by the local | ||||
|         // variable `stor`. | ||||
|         // See https://solidity.readthedocs.io/en/v0.6.8/assembly.html?highlight=slot#access-to-external-variables-functions-and-libraries | ||||
|         assembly { stor_slot := storageSlot } | ||||
|     } | ||||
| } | ||||
| @@ -1,7 +1,7 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2021 ZeroEx Intl. | ||||
|   Copyright 2020 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
| @@ -21,7 +21,7 @@ pragma solidity ^0.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "./IBridgeAdapter.sol"; | ||||
| import "./BridgeProtocols.sol"; | ||||
| import "./BridgeSource.sol"; | ||||
| import "./mixins/MixinBalancer.sol"; | ||||
| import "./mixins/MixinBancor.sol"; | ||||
| import "./mixins/MixinCoFiX.sol"; | ||||
| @@ -30,12 +30,11 @@ import "./mixins/MixinCryptoCom.sol"; | ||||
| import "./mixins/MixinDodo.sol"; | ||||
| import "./mixins/MixinDodoV2.sol"; | ||||
| import "./mixins/MixinKyber.sol"; | ||||
| import "./mixins/MixinMakerPSM.sol"; | ||||
| import "./mixins/MixinMooniswap.sol"; | ||||
| import "./mixins/MixinMStable.sol"; | ||||
| import "./mixins/MixinNerve.sol"; | ||||
| import "./mixins/MixinOasis.sol"; | ||||
| import "./mixins/MixinShell.sol"; | ||||
| import "./mixins/MixinSushiswap.sol"; | ||||
| import "./mixins/MixinUniswap.sol"; | ||||
| import "./mixins/MixinUniswapV2.sol"; | ||||
| import "./mixins/MixinZeroExBridge.sol"; | ||||
| @@ -50,12 +49,11 @@ contract BridgeAdapter is | ||||
|     MixinDodo, | ||||
|     MixinDodoV2, | ||||
|     MixinKyber, | ||||
|     MixinMakerPSM, | ||||
|     MixinMooniswap, | ||||
|     MixinMStable, | ||||
|     MixinNerve, | ||||
|     MixinOasis, | ||||
|     MixinShell, | ||||
|     MixinSushiswap, | ||||
|     MixinUniswap, | ||||
|     MixinUniswapV2, | ||||
|     MixinZeroExBridge | ||||
| @@ -70,12 +68,11 @@ contract BridgeAdapter is | ||||
|         MixinDodo() | ||||
|         MixinDodoV2() | ||||
|         MixinKyber(weth) | ||||
|         MixinMakerPSM() | ||||
|         MixinMooniswap(weth) | ||||
|         MixinMStable() | ||||
|         MixinNerve() | ||||
|         MixinOasis() | ||||
|         MixinShell() | ||||
|         MixinSushiswap() | ||||
|         MixinUniswap(weth) | ||||
|         MixinUniswapV2() | ||||
|         MixinZeroExBridge() | ||||
| @@ -91,113 +88,109 @@ contract BridgeAdapter is | ||||
|         override | ||||
|         returns (uint256 boughtAmount) | ||||
|     { | ||||
|         uint128 protocolId = uint128(uint256(order.source) >> 128); | ||||
|         if (protocolId == BridgeProtocols.CURVE) { | ||||
|         if (order.source == BridgeSource.CURVE || | ||||
|             order.source == BridgeSource.SWERVE || | ||||
|             order.source == BridgeSource.SNOWSWAP) { | ||||
|             boughtAmount = _tradeCurve( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNISWAPV2) { | ||||
|         } else if (order.source == BridgeSource.SUSHISWAP) { | ||||
|             boughtAmount = _tradeSushiswap( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (order.source == BridgeSource.UNISWAPV2 || | ||||
|                    order.source == BridgeSource.LINKSWAP) { | ||||
|             boughtAmount = _tradeUniswapV2( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.UNISWAP) { | ||||
|         } else if (order.source == BridgeSource.UNISWAP) { | ||||
|             boughtAmount = _tradeUniswap( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.BALANCER) { | ||||
|         } else if (order.source == BridgeSource.BALANCER || | ||||
|                    order.source == BridgeSource.CREAM) { | ||||
|             boughtAmount = _tradeBalancer( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.KYBER) { | ||||
|         } else if (order.source == BridgeSource.KYBER) { | ||||
|             boughtAmount = _tradeKyber( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.MAKERPSM) { | ||||
|             boughtAmount = _tradeMakerPsm( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.MOONISWAP) { | ||||
|         } else if (order.source == BridgeSource.MOONISWAP) { | ||||
|             boughtAmount = _tradeMooniswap( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.MSTABLE) { | ||||
|         } else if (order.source == BridgeSource.MSTABLE) { | ||||
|             boughtAmount = _tradeMStable( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.OASIS) { | ||||
|         } else if (order.source == BridgeSource.OASIS) { | ||||
|             boughtAmount = _tradeOasis( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.SHELL) { | ||||
|         } else if (order.source == BridgeSource.SHELL) { | ||||
|             boughtAmount = _tradeShell( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.DODO) { | ||||
|         } else if (order.source == BridgeSource.DODO) { | ||||
|             boughtAmount = _tradeDodo( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.DODOV2) { | ||||
|         } else if (order.source == BridgeSource.DODOV2) { | ||||
|             boughtAmount = _tradeDodoV2( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.CRYPTOCOM) { | ||||
|         } else if (order.source == BridgeSource.CRYPTOCOM) { | ||||
|             boughtAmount = _tradeCryptoCom( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.BANCOR) { | ||||
|         } else if (order.source == BridgeSource.BANCOR) { | ||||
|             boughtAmount = _tradeBancor( | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.COFIX) { | ||||
|         } else if (order.source == BridgeSource.COFIX) { | ||||
|             boughtAmount = _tradeCoFiX( | ||||
|                 sellToken, | ||||
|                 buyToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else if (protocolId == BridgeProtocols.NERVE) { | ||||
|             boughtAmount = _tradeNerve( | ||||
|                 sellToken, | ||||
|                 sellAmount, | ||||
|                 order.bridgeData | ||||
|             ); | ||||
|         } else { | ||||
|             boughtAmount = _tradeZeroExBridge( | ||||
|                 sellToken, | ||||
|   | ||||
| @@ -1,47 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2021 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.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
|  | ||||
|  | ||||
| library BridgeProtocols { | ||||
|     // A incrementally increasing, append-only list of protocol IDs. | ||||
|     // We don't use an enum so solidity doesn't throw when we pass in a | ||||
|     // new protocol ID that hasn't been rolled up yet. | ||||
|     uint128 internal constant UNKNOWN     = 0; | ||||
|     uint128 internal constant CURVE       = 1; | ||||
|     uint128 internal constant UNISWAPV2   = 2; | ||||
|     uint128 internal constant UNISWAP     = 3; | ||||
|     uint128 internal constant BALANCER    = 4; | ||||
|     uint128 internal constant KYBER       = 5; | ||||
|     uint128 internal constant MOONISWAP   = 6; | ||||
|     uint128 internal constant MSTABLE     = 7; | ||||
|     uint128 internal constant OASIS       = 8; | ||||
|     uint128 internal constant SHELL       = 9; | ||||
|     uint128 internal constant DODO        = 10; | ||||
|     uint128 internal constant DODOV2      = 11; | ||||
|     uint128 internal constant CRYPTOCOM   = 12; | ||||
|     uint128 internal constant BANCOR      = 13; | ||||
|     uint128 internal constant COFIX       = 14; | ||||
|     uint128 internal constant NERVE       = 15; | ||||
|     uint128 internal constant MAKERPSM    = 16; | ||||
| } | ||||
| @@ -0,0 +1,47 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 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.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
|  | ||||
| library BridgeSource { | ||||
|     uint256 constant internal BALANCER = 0; | ||||
|     uint256 constant internal BANCOR = 1; | ||||
|     uint256 constant internal COFIX = 2; | ||||
|     uint256 constant internal CURVE = 3; | ||||
|     uint256 constant internal CREAM = 4; | ||||
|     uint256 constant internal CRYPTOCOM = 5; | ||||
|     uint256 constant internal DODO = 6; | ||||
|     uint256 constant internal KYBER = 7; | ||||
|     uint256 constant internal LIQUIDITYPROVIDER = 8; | ||||
|     uint256 constant internal MOONISWAP = 9; | ||||
|     uint256 constant internal MSTABLE = 10; | ||||
|     uint256 constant internal OASIS = 11; | ||||
|     uint256 constant internal SHELL = 12; | ||||
|     uint256 constant internal SNOWSWAP = 13; | ||||
|     uint256 constant internal SUSHISWAP = 14; | ||||
|     uint256 constant internal SWERVE = 15; | ||||
|     uint256 constant internal UNISWAP = 16; | ||||
|     uint256 constant internal UNISWAPV2 = 17; | ||||
|     uint256 constant internal DODOV2 = 18; | ||||
|     uint256 constant internal LINKSWAP = 19; | ||||
|     // New sources should be APPENDED to this list, taking the next highest | ||||
|     // integer value. | ||||
| } | ||||
| @@ -1,7 +1,7 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2021 ZeroEx Intl. | ||||
|   Copyright 2020 ZeroEx Intl. | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
| @@ -26,24 +26,20 @@ import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
| interface IBridgeAdapter { | ||||
|  | ||||
|     struct BridgeOrder { | ||||
|         // Upper 16 bytes: uint128 protocol ID (right-aligned) | ||||
|         // Lower 16 bytes: ASCII source name (left-aligned) | ||||
|         bytes32 source; | ||||
|         uint256 source; | ||||
|         uint256 takerTokenAmount; | ||||
|         uint256 makerTokenAmount; | ||||
|         bytes bridgeData; | ||||
|     } | ||||
|  | ||||
|     /// @dev Emitted when tokens are swapped with an external source. | ||||
|     /// @param source A unique ID for the source, where the upper 16 bytes | ||||
|     ///        encodes the (right-aligned) uint128 protocol ID and the | ||||
|     ///        lower 16 bytes encodes an ASCII source name. | ||||
|     /// @param source The unique ID for the source. See `BridgeSource.sol` | ||||
|     /// @param inputToken The token the bridge is converting from. | ||||
|     /// @param outputToken The token the bridge is converting to. | ||||
|     /// @param inputTokenAmount Amount of input token sold. | ||||
|     /// @param outputTokenAmount Amount of output token bought. | ||||
|     event BridgeFill( | ||||
|         bytes32 source, | ||||
|         uint256 source, | ||||
|         IERC20TokenV06 inputToken, | ||||
|         IERC20TokenV06 outputToken, | ||||
|         uint256 inputTokenAmount, | ||||
|   | ||||
| @@ -1,114 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2021 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.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol"; | ||||
|  | ||||
| interface IPSM { | ||||
|     // @dev Get the fee for selling USDC to DAI in PSM | ||||
|     // @return tin toll in [wad] | ||||
|     function tin() external view returns (uint256); | ||||
|     // @dev Get the fee for selling DAI to USDC in PSM | ||||
|     // @return tout toll out [wad] | ||||
|     function tout() external view returns (uint256); | ||||
|  | ||||
|     // @dev Get the address of the PSM state Vat | ||||
|     // @return address of the Vat | ||||
|     function vat() external view returns (address); | ||||
|  | ||||
|     // @dev Get the address of the underlying vault powering PSM | ||||
|     // @return address of gemJoin contract | ||||
|     function gemJoin() external view returns (address); | ||||
|  | ||||
|     // @dev Sell USDC for DAI | ||||
|     // @param usr The address of the account trading USDC for DAI. | ||||
|     // @param gemAmt The amount of USDC to sell in USDC base units | ||||
|     function sellGem( | ||||
|         address usr, | ||||
|         uint256 gemAmt | ||||
|     ) external; | ||||
|     // @dev Buy USDC for DAI | ||||
|     // @param usr The address of the account trading DAI for USDC | ||||
|     // @param gemAmt The amount of USDC to buy in USDC base units | ||||
|     function buyGem( | ||||
|         address usr, | ||||
|         uint256 gemAmt | ||||
|     ) external; | ||||
| } | ||||
|  | ||||
| contract MixinMakerPSM { | ||||
|  | ||||
|     using LibERC20TokenV06 for IERC20TokenV06; | ||||
|     using LibSafeMathV06 for uint256; | ||||
|  | ||||
|     struct MakerPsmBridgeData { | ||||
|         address psmAddress; | ||||
|         address gemTokenAddres; | ||||
|     } | ||||
|  | ||||
|     // Maker units | ||||
|     // wad: fixed point decimal with 18 decimals (for basic quantities, e.g. balances) | ||||
|     uint256 constant private WAD = 10 ** 18; | ||||
|     // ray: fixed point decimal with 27 decimals (for precise quantites, e.g. ratios) | ||||
|     uint256 constant private RAY = 10 ** 27; | ||||
|     // rad: fixed point decimal with 45 decimals (result of integer multiplication with a wad and a ray) | ||||
|     uint256 constant private RAD = 10 ** 45; | ||||
|     // See https://github.com/makerdao/dss/blob/master/DEVELOPING.md | ||||
|  | ||||
|     function _tradeMakerPsm( | ||||
|         IERC20TokenV06 sellToken, | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bytes memory bridgeData | ||||
|     ) | ||||
|         internal | ||||
|         returns (uint256 boughtAmount) | ||||
|     { | ||||
|         // Decode the bridge data. | ||||
|         MakerPsmBridgeData memory data = abi.decode(bridgeData, (MakerPsmBridgeData)); | ||||
|         uint256 beforeBalance = buyToken.balanceOf(address(this)); | ||||
|  | ||||
|         IPSM psm = IPSM(data.psmAddress); | ||||
|  | ||||
|         if (address(sellToken) == data.gemTokenAddres) { | ||||
|             sellToken.approveIfBelow( | ||||
|                 psm.gemJoin(), | ||||
|                 sellAmount | ||||
|             ); | ||||
|  | ||||
|             psm.sellGem(address(this), sellAmount); | ||||
|         } else if (address(buyToken) == data.gemTokenAddres) { | ||||
|             uint256 feeDivisor = WAD.safeAdd(psm.tout()); // eg. 1.001 * 10 ** 18 with 0.1% fee [tout is in wad]; | ||||
|             uint256 buyTokenBaseUnit = uint256(10) ** uint256(buyToken.decimals()); | ||||
|             uint256 gemAmount =  sellAmount.safeMul(buyTokenBaseUnit).safeDiv(feeDivisor); | ||||
|  | ||||
|             sellToken.approveIfBelow( | ||||
|                 data.psmAddress, | ||||
|                 sellAmount | ||||
|             ); | ||||
|             psm.buyGem(address(this), gemAmount); | ||||
|         } | ||||
|  | ||||
|         return buyToken.balanceOf(address(this)).safeSub(beforeBalance); | ||||
|     } | ||||
| } | ||||
| @@ -1,72 +0,0 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 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.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
| import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol"; | ||||
|  | ||||
| contract MixinNerve { | ||||
|  | ||||
|     using LibERC20TokenV06 for IERC20TokenV06; | ||||
|     using LibSafeMathV06 for uint256; | ||||
|     using LibRichErrorsV06 for bytes; | ||||
|  | ||||
|  | ||||
|     struct NerveBridgeData { | ||||
|         address pool; | ||||
|         bytes4 exchangeFunctionSelector; | ||||
|         int128 fromCoinIdx; | ||||
|         int128 toCoinIdx; | ||||
|     } | ||||
|  | ||||
|     function _tradeNerve( | ||||
|         IERC20TokenV06 sellToken, | ||||
|         uint256 sellAmount, | ||||
|         bytes memory bridgeData | ||||
|     ) | ||||
|         internal | ||||
|         returns (uint256 boughtAmount) | ||||
|     { | ||||
|         // Basically a Curve fork but the swap option has a deadline | ||||
|  | ||||
|         // Decode the bridge data to get the Curve metadata. | ||||
|         NerveBridgeData memory data = abi.decode(bridgeData, (NerveBridgeData)); | ||||
|         sellToken.approveIfBelow(data.pool, sellAmount); | ||||
|         (bool success, bytes memory resultData) = | ||||
|             data.pool.call(abi.encodeWithSelector( | ||||
|                 data.exchangeFunctionSelector, | ||||
|                 data.fromCoinIdx, | ||||
|                 data.toCoinIdx, | ||||
|                 // dx | ||||
|                 sellAmount, | ||||
|                 // min dy | ||||
|                 1, | ||||
|                 // deadline | ||||
|                 block.timestamp | ||||
|             )); | ||||
|         if (!success) { | ||||
|             resultData.rrevert(); | ||||
|         } | ||||
|         return abi.decode(resultData, (uint256)); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,75 @@ | ||||
| // SPDX-License-Identifier: Apache-2.0 | ||||
|  | ||||
| /* | ||||
|  | ||||
|   Copyright 2020 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.6.5; | ||||
| pragma experimental ABIEncoderV2; | ||||
|  | ||||
| import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; | ||||
| import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; | ||||
| import "./MixinUniswapV2.sol"; | ||||
|  | ||||
| contract MixinSushiswap { | ||||
|  | ||||
|     using LibERC20TokenV06 for IERC20TokenV06; | ||||
|  | ||||
|     function _tradeSushiswap( | ||||
|         IERC20TokenV06 buyToken, | ||||
|         uint256 sellAmount, | ||||
|         bytes memory bridgeData | ||||
|     ) | ||||
|         internal | ||||
|         returns (uint256 boughtAmount) | ||||
|     { | ||||
|         IERC20TokenV06[] memory path; | ||||
|         IUniswapV2Router02 router; | ||||
|         { | ||||
|             address[] memory _path; | ||||
|             (router, _path) = | ||||
|                 abi.decode(bridgeData, (IUniswapV2Router02, address[])); | ||||
|             // To get around `abi.decode()` not supporting interface array types. | ||||
|             assembly { path := _path } | ||||
|         } | ||||
|  | ||||
|         require(path.length >= 2, "MixinSushiswap/PATH_LENGTH_MUST_BE_AT_LEAST_TWO"); | ||||
|         require( | ||||
|             path[path.length - 1] == buyToken, | ||||
|             "MixinSushiswap/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN" | ||||
|         ); | ||||
|         // Grant the Uniswap router an allowance to sell the first token. | ||||
|         path[0].approveIfBelow( | ||||
|             address(router), | ||||
|             sellAmount | ||||
|         ); | ||||
|  | ||||
|         uint[] memory amounts = router.swapExactTokensForTokens( | ||||
|              // Sell all tokens we hold. | ||||
|             sellAmount, | ||||
|              // Minimum buy amount. | ||||
|             1, | ||||
|             // Convert to `buyToken` along this path. | ||||
|             path, | ||||
|             // Recipient is `this`. | ||||
|             address(this), | ||||
|             // Expires after this block. | ||||
|             block.timestamp | ||||
|         ); | ||||
|         return amounts[amounts.length-1]; | ||||
|     } | ||||
| } | ||||
| @@ -26,7 +26,12 @@ import "../src/fixins/FixinTokenSpender.sol"; | ||||
| contract TestFixinTokenSpender is | ||||
|     FixinTokenSpender | ||||
| { | ||||
|     constructor() public {} | ||||
|     uint256 constant private TRIGGER_FALLBACK_SUCCESS_AMOUNT = 1340; | ||||
|  | ||||
|     constructor(bytes32 greedyTokensBloomFilter) | ||||
|         public | ||||
|         FixinTokenSpender(greedyTokensBloomFilter) | ||||
|     {} | ||||
|  | ||||
|     function transferERC20Tokens( | ||||
|         IERC20TokenV06 token, | ||||
| @@ -51,6 +56,21 @@ contract TestFixinTokenSpender is | ||||
|         uint256 amount | ||||
|     ); | ||||
|  | ||||
|     // This is called as a fallback when the original transferFrom() fails. | ||||
|     function _spendERC20Tokens( | ||||
|         IERC20TokenV06 token, | ||||
|         address owner, | ||||
|         address to, | ||||
|         uint256 amount | ||||
|     ) | ||||
|         external | ||||
|     { | ||||
|         require(amount == TRIGGER_FALLBACK_SUCCESS_AMOUNT, | ||||
|             "TokenSpenderFallback/FAILURE_AMOUNT"); | ||||
|  | ||||
|         emit FallbackCalled(address(token), owner, to, amount); | ||||
|     } | ||||
|  | ||||
|     function getSpendableERC20BalanceOf( | ||||
|         IERC20TokenV06 token, | ||||
|         address owner | ||||
| @@ -61,4 +81,12 @@ contract TestFixinTokenSpender is | ||||
|     { | ||||
|         return _getSpendableERC20BalanceOf(token, owner); | ||||
|     } | ||||
|  | ||||
|     function isTokenPossiblyGreedy(IERC20TokenV06 token) | ||||
|         external | ||||
|         view | ||||
|         returns (bool) | ||||
|     { | ||||
|         return _isTokenPossiblyGreedy(token); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -35,7 +35,8 @@ contract TestMetaTransactionsNativeOrdersFeature is | ||||
|             IEtherTokenV06(0), | ||||
|             IStaking(0), | ||||
|             FeeCollectorController(address(new TestFeeCollectorController())), | ||||
|             0 | ||||
|             0, | ||||
|             bytes32(0) | ||||
|         ) | ||||
|     {} | ||||
|  | ||||
|   | ||||
| @@ -38,7 +38,7 @@ contract TestMetaTransactionsTransformERC20Feature is | ||||
|         Transformation[] transformations | ||||
|     ); | ||||
|  | ||||
|     constructor() public TransformERC20Feature() {} | ||||
|     constructor() public TransformERC20Feature(0) {} | ||||
|  | ||||
|     function _transformERC20(TransformERC20Args memory args) | ||||
|         public | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user