From 9b131199ade048d3909da4ad29f69e8f5b35f21e Mon Sep 17 00:00:00 2001 From: Noah Khamliche Date: Thu, 2 Jun 2022 20:14:02 -0400 Subject: [PATCH] add weth/eth wrap/unwrap support for bancorv3 --- .../bridges/EthereumBridgeAdapter.sol | 1 + .../bridges/mixins/MixinBancorV3.sol | 44 ++++++++++++++++--- packages/asset-swapper/package.json | 3 +- .../utils/market_operation_utils/orders.ts | 4 +- .../sampler_operations.ts | 18 +++++--- 5 files changed, 56 insertions(+), 14 deletions(-) diff --git a/contracts/zero-ex/contracts/src/transformers/bridges/EthereumBridgeAdapter.sol b/contracts/zero-ex/contracts/src/transformers/bridges/EthereumBridgeAdapter.sol index 132cba58dc..d238836ff3 100644 --- a/contracts/zero-ex/contracts/src/transformers/bridges/EthereumBridgeAdapter.sol +++ b/contracts/zero-ex/contracts/src/transformers/bridges/EthereumBridgeAdapter.sol @@ -75,6 +75,7 @@ contract EthereumBridgeAdapter is constructor(IEtherTokenV06 weth) public MixinBancor(weth) + MixinBancorV3(weth) MixinCompound(weth) MixinCurve(weth) MixinLido(weth) diff --git a/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinBancorV3.sol b/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinBancorV3.sol index 74c9487f5e..8cf92d54de 100644 --- a/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinBancorV3.sol +++ b/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinBancorV3.sol @@ -23,6 +23,8 @@ pragma experimental ABIEncoderV2; import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; +import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol"; + /* BancorV3 @@ -42,25 +44,37 @@ interface IBancorV3 { uint256 minReturnAmount, uint256 deadline, address beneficiary - ) external returns (uint256 amount); + ) external payable returns (uint256 amount); } contract MixinBancorV3 { using LibERC20TokenV06 for IERC20TokenV06; + IERC20TokenV06 constant public BANCORV3_ETH_ADDRESS = + IERC20TokenV06(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); + IEtherTokenV06 private immutable WETH; + + constructor(IEtherTokenV06 weth) + public + { + WETH = weth; + } + function _tradeBancorV3( IERC20TokenV06 buyToken, uint256 sellAmount, bytes memory bridgeData ) - public + internal returns (uint256 amountOut) { IBancorV3 router; IERC20TokenV06[] memory path; address[] memory _path; + uint256 payableAmount = 0; + { (router, _path) = abi.decode(bridgeData, (IBancorV3, address[])); // To get around `abi.decode()` not supporting interface array types. @@ -72,11 +86,26 @@ contract MixinBancorV3 { path[path.length - 1] == buyToken, "MixinBancorV3/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN" ); - // Grant the BancorV3 router an allowance to sell the first token. - path[0].approveIfBelow(address(router), sellAmount); + + //swap WETH->ETH as Bancor only deals in ETH + if(_path[0] == address(WETH)) { + //withdraw the sell amount of WETH for ETH + WETH.withdraw(sellAmount); + payableAmount = sellAmount; + // set _path[0] to the ETH address if WETH is our buy token + _path[0] = address(BANCORV3_ETH_ADDRESS); + } else { + // Grant the BancorV3 router an allowance to sell the first token. + path[0].approveIfBelow(address(router), sellAmount); + } + + // if we are buying WETH we need to swap to ETH and deposit into WETH after the swap + if(_path[1] == address(WETH)){ + _path[1] = address(BANCORV3_ETH_ADDRESS); + } - uint256 amountOut = router.tradeBySourceAmount( + uint256 amountOut = router.tradeBySourceAmount{value: payableAmount}( _path[0], _path[1], // Sell all tokens we hold. @@ -89,6 +118,11 @@ contract MixinBancorV3 { address(this) ); + // if we want to return WETH deposit the ETH amount we sold + if(buyToken == WETH){ + WETH.deposit{value: amountOut}(); + } + return amountOut; } } \ No newline at end of file diff --git a/packages/asset-swapper/package.json b/packages/asset-swapper/package.json index d1fd122c53..a36ef8bf12 100644 --- a/packages/asset-swapper/package.json +++ b/packages/asset-swapper/package.json @@ -34,7 +34,8 @@ "contracts:gen": "contracts-gen generate", "contracts:copy": "contracts-gen copy", "publish:private": "yarn build && gitpkg publish", - "sampler-size": "jq .compilerOutput.evm.deployedBytecode.object -- test/generated-artifacts/ERC20BridgeSampler.json | echo $(( $(wc -c) / 2 - 1 ))" + "sampler-size": "jq .compilerOutput.evm.deployedBytecode.object -- test/generated-artifacts/ERC20BridgeSampler.json | echo $(( $(wc -c) / 2 - 1 ))", + "list:deps": "yarn lerna list -l" }, "config": { "publicInterfaceContracts": "ERC20BridgeSampler,BalanceChecker,FakeTaker", diff --git a/packages/asset-swapper/src/utils/market_operation_utils/orders.ts b/packages/asset-swapper/src/utils/market_operation_utils/orders.ts index cfe21b48d7..52bfb2378f 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/orders.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/orders.ts @@ -208,6 +208,8 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s return encodeBridgeSourceId(BridgeProtocol.Platypus, 'Platypus'); case ERC20BridgeSource.MeshSwap: return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'MeshSwap'); + case ERC20BridgeSource.BancorV3: + return encodeBridgeSourceId(BridgeProtocol.BancorV3, 'BancorV3'); default: throw new Error(AggregationError.NoBridgeForSource); } @@ -387,7 +389,7 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder break; case ERC20BridgeSource.BancorV3: const bancorV3FillData = (order as OptimizedMarketBridgeOrder).fillData; - bridgeData = encoder.encode([bancorV3FillData.networkAddress, bancorFillData.path, bancor]); + bridgeData = encoder.encode([bancorV3FillData.networkAddress, bancorV3FillData.path]); break; default: throw new Error(AggregationError.NoBridgeForSource); diff --git a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts index da7a9a361f..2d2adc990b 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts @@ -713,6 +713,7 @@ export class SamplerOperations { public getBancorV3SellQuotes( networkAddress: string, + networkInfoAddress: string, path: string[], takerFillAmounts: BigNumber[], ): SourceQuoteOperation { @@ -721,13 +722,14 @@ export class SamplerOperations { fillData: { networkAddress, path}, contract: this._samplerContract, function: this._samplerContract.sampleBuysFromBancorV3, - params: [networkAddress, path, takerFillAmounts], + params: [networkInfoAddress, path, takerFillAmounts], }); } // Unimplemented public getBancorV3BuyQuotes( networkAddress: string, + networkInfoAddress: string, path: string[], makerFillAmounts: BigNumber[], ): SourceQuoteOperation { @@ -736,7 +738,7 @@ export class SamplerOperations { fillData: { networkAddress, path}, contract: this._samplerContract, function: this._samplerContract.sampleBuysFromBancorV3, - params: [networkAddress, path, makerFillAmounts], + params: [networkInfoAddress, path, makerFillAmounts], }); } @@ -1710,9 +1712,10 @@ export class SamplerOperations { } case ERC20BridgeSource.BancorV3: { return this.getBancorV3SellQuotes( + BANCORV3_NETWORK_BY_CHAIN_ID[this.chainId], BANCORV3_NETWORK_INFO_BY_CHAIN_ID[this.chainId], - [takerToken,makerToken], - takerFillAmounts + [takerToken, makerToken], + takerFillAmounts, ); } default: @@ -2044,10 +2047,11 @@ export class SamplerOperations { ); } case ERC20BridgeSource.BancorV3: { - return this.getBancorV3SellQuotes( + return this.getBancorV3BuyQuotes( + BANCORV3_NETWORK_BY_CHAIN_ID[this.chainId], BANCORV3_NETWORK_INFO_BY_CHAIN_ID[this.chainId], - [takerToken,makerToken], - makerFillAmounts + [takerToken, makerToken], + makerFillAmounts, ); } default: