From 728f0ce7347721de83c27075e84c0b6889d17a3b Mon Sep 17 00:00:00 2001 From: graykode Date: Tue, 14 Feb 2023 23:15:22 +0900 Subject: [PATCH 1/7] add clober-dex's market order function --- .../bridges/mixins/MixinClober.sol | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinClober.sol diff --git a/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinClober.sol b/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinClober.sol new file mode 100644 index 0000000000..26704c1ef4 --- /dev/null +++ b/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinClober.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + Copyright 2023 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-erc20/contracts/src/v06/IEtherTokenV06.sol"; +import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol"; + +interface ICloberOrderBook { + function quoteToRaw(uint256 quoteAmount, bool roundingUp) external view returns (uint64 rawAmount); +} + +interface ICloberRouter { + struct MarketOrderParams { + address market; + uint64 deadline; + address user; + uint16 limitPriceIndex; + uint64 rawAmount; + bool expendInput; + bool useNative; + uint256 baseAmount; + } + + function marketBid(MarketOrderParams calldata params) external payable; + + function marketAsk(MarketOrderParams calldata params) external payable; +} + +contract MixinClober { + using LibERC20TokenV06 for IERC20TokenV06; + using LibSafeMathV06 for uint256; + + IEtherTokenV06 private immutable WETH; + + constructor(IEtherTokenV06 weth) public { + WETH = weth; + } + + function _tradeClober( + IERC20TokenV06 sellToken, + IERC20TokenV06 buyToken, + uint256 sellAmount, + bytes memory bridgeData + ) internal returns (uint256 boughtAmount) { + (ICloberRouter router, ICloberOrderBook market, bool isTakingBid) = abi.decode( + bridgeData, + (ICloberRouter, ICloberOrderBook, bool) + ); + + // Grant the Clober router an allowance to sell the sell token. + sellToken.approveIfBelow(address(router), sellAmount); + + ICloberRouter.MarketOrderParams memory params = ICloberRouter.MarketOrderParams({ + market: address(market), + deadline: uint64(block.timestamp + 100), + user: msg.sender, + limitPriceIndex: isTakingBid ? 0 : type(uint16).max, + rawAmount: isTakingBid ? 0 : market.quoteToRaw(sellAmount, true), + expendInput: true, + useNative: address(sellToken) == address(WETH) ? true : false, + baseAmount: isTakingBid ? sellAmount : 0 + }); + + uint256 beforeBalance = buyToken.balanceOf(address(this)); + if (isTakingBid) { + router.marketAsk(params); + } else { + router.marketBid(params); + } + return buyToken.balanceOf(address(this)).safeSub(beforeBalance); + } +} From 7a459cff69983e169080d31771a02bb730a92a2d Mon Sep 17 00:00:00 2001 From: graykode Date: Tue, 14 Feb 2023 23:15:33 +0900 Subject: [PATCH 2/7] add clober dex router in ethereum, polygon and arbitrum --- .../transformers/bridges/ArbitrumBridgeAdapter.sol | 11 +++++++++-- .../src/transformers/bridges/BridgeProtocols.sol | 1 + .../transformers/bridges/EthereumBridgeAdapter.sol | 10 +++++++++- .../src/transformers/bridges/PolygonBridgeAdapter.sol | 11 +++++++++-- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/contracts/zero-ex/contracts/src/transformers/bridges/ArbitrumBridgeAdapter.sol b/contracts/zero-ex/contracts/src/transformers/bridges/ArbitrumBridgeAdapter.sol index 70714bb565..54db84122a 100644 --- a/contracts/zero-ex/contracts/src/transformers/bridges/ArbitrumBridgeAdapter.sol +++ b/contracts/zero-ex/contracts/src/transformers/bridges/ArbitrumBridgeAdapter.sol @@ -29,6 +29,7 @@ import "./mixins/MixinUniswapV3.sol"; import "./mixins/MixinUniswapV2.sol"; import "./mixins/MixinWOOFi.sol"; import "./mixins/MixinZeroExBridge.sol"; +import "./mixins/MixinClober.sol"; contract ArbitrumBridgeAdapter is AbstractBridgeAdapter(42161, "Arbitrum"), @@ -43,9 +44,10 @@ contract ArbitrumBridgeAdapter is MixinUniswapV3, MixinUniswapV2, MixinWOOFi, - MixinZeroExBridge + MixinZeroExBridge, + MixinClober { - constructor(IEtherTokenV06 weth) public MixinCurve(weth) MixinAaveV3(true) {} + constructor(IEtherTokenV06 weth) public MixinCurve(weth) MixinAaveV3(true) MixinClober(weth) {} function _trade( BridgeOrder memory order, @@ -115,6 +117,11 @@ contract ArbitrumBridgeAdapter is return (0, true); } boughtAmount = _tradeWOOFi(sellToken, buyToken, sellAmount, order.bridgeData); + } else if (protocolId == BridgeProtocols.CLOBER) { + if (dryRun) { + return (0, true); + } + boughtAmount = _tradeClober(sellToken, buyToken, sellAmount, order.bridgeData); } emit BridgeFill(order.source, sellToken, buyToken, sellAmount, boughtAmount); diff --git a/contracts/zero-ex/contracts/src/transformers/bridges/BridgeProtocols.sol b/contracts/zero-ex/contracts/src/transformers/bridges/BridgeProtocols.sol index f2c4ce73fd..7ebaeace8b 100644 --- a/contracts/zero-ex/contracts/src/transformers/bridges/BridgeProtocols.sol +++ b/contracts/zero-ex/contracts/src/transformers/bridges/BridgeProtocols.sol @@ -54,4 +54,5 @@ library BridgeProtocols { uint128 internal constant SYNTHETIX = 30; uint128 internal constant WOOFI = 31; uint128 internal constant AAVEV3 = 32; + uint128 internal constant CLOBER = 33; } diff --git a/contracts/zero-ex/contracts/src/transformers/bridges/EthereumBridgeAdapter.sol b/contracts/zero-ex/contracts/src/transformers/bridges/EthereumBridgeAdapter.sol index bb911510fd..d944043a56 100644 --- a/contracts/zero-ex/contracts/src/transformers/bridges/EthereumBridgeAdapter.sol +++ b/contracts/zero-ex/contracts/src/transformers/bridges/EthereumBridgeAdapter.sol @@ -39,6 +39,7 @@ import "./mixins/MixinUniswap.sol"; import "./mixins/MixinUniswapV2.sol"; import "./mixins/MixinUniswapV3.sol"; import "./mixins/MixinZeroExBridge.sol"; +import "./mixins/MixinClober.sol"; contract EthereumBridgeAdapter is AbstractBridgeAdapter(1, "Ethereum"), @@ -63,7 +64,8 @@ contract EthereumBridgeAdapter is MixinUniswap, MixinUniswapV2, MixinUniswapV3, - MixinZeroExBridge + MixinZeroExBridge, + MixinClober { constructor( IEtherTokenV06 weth @@ -75,6 +77,7 @@ contract EthereumBridgeAdapter is MixinCurve(weth) MixinLido(weth) MixinUniswap(weth) + MixinClober(weth) {} function _trade( @@ -195,6 +198,11 @@ contract EthereumBridgeAdapter is return (0, true); } boughtAmount = _tradeZeroExBridge(sellToken, buyToken, sellAmount, order.bridgeData); + } else if (protocolId == BridgeProtocols.CLOBER) { + if (dryRun) { + return (0, true); + } + boughtAmount = _tradeClober(sellToken, buyToken, sellAmount, order.bridgeData); } emit BridgeFill(order.source, sellToken, buyToken, sellAmount, boughtAmount); diff --git a/contracts/zero-ex/contracts/src/transformers/bridges/PolygonBridgeAdapter.sol b/contracts/zero-ex/contracts/src/transformers/bridges/PolygonBridgeAdapter.sol index 9ccb827ac3..26f3adeadc 100644 --- a/contracts/zero-ex/contracts/src/transformers/bridges/PolygonBridgeAdapter.sol +++ b/contracts/zero-ex/contracts/src/transformers/bridges/PolygonBridgeAdapter.sol @@ -32,6 +32,7 @@ import "./mixins/MixinUniswapV2.sol"; import "./mixins/MixinUniswapV3.sol"; import "./mixins/MixinWOOFi.sol"; import "./mixins/MixinZeroExBridge.sol"; +import "./mixins/MixinClober.sol"; contract PolygonBridgeAdapter is AbstractBridgeAdapter(137, "Polygon"), @@ -49,9 +50,10 @@ contract PolygonBridgeAdapter is MixinUniswapV3, MixinSolidly, MixinWOOFi, - MixinZeroExBridge + MixinZeroExBridge, + MixinClober { - constructor(IEtherTokenV06 weth) public MixinCurve(weth) MixinAaveV3(false) {} + constructor(IEtherTokenV06 weth) public MixinCurve(weth) MixinAaveV3(false) MixinClober(weth) {} function _trade( BridgeOrder memory order, @@ -136,6 +138,11 @@ contract PolygonBridgeAdapter is return (0, true); } boughtAmount = _tradeAaveV3(sellToken, buyToken, sellAmount, order.bridgeData); + } else if (protocolId == BridgeProtocols.CLOBER) { + if (dryRun) { + return (0, true); + } + boughtAmount = _tradeClober(sellToken, buyToken, sellAmount, order.bridgeData); } emit BridgeFill(order.source, sellToken, buyToken, sellAmount, boughtAmount); From df33da279819266b96877ea20495c1b232885d9f Mon Sep 17 00:00:00 2001 From: graykode Date: Wed, 15 Feb 2023 00:09:16 +0900 Subject: [PATCH 3/7] update changelog --- contracts/zero-ex/CHANGELOG.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/contracts/zero-ex/CHANGELOG.json b/contracts/zero-ex/CHANGELOG.json index 6b357dfcf8..b7479345c3 100644 --- a/contracts/zero-ex/CHANGELOG.json +++ b/contracts/zero-ex/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "timestamp": 1676384530, + "version": "0.38.7", + "changes": [ + { + "note": "Add support for Clober to bridge adapter" + } + ] + }, { "timestamp": 1675210931, "version": "0.38.6", From 22a8401a0ae855174606bd95ef9e091c19d2edc4 Mon Sep 17 00:00:00 2001 From: graykode Date: Wed, 15 Feb 2023 00:09:34 +0900 Subject: [PATCH 4/7] add Clober in FillQuoteTransformerData --- packages/protocol-utils/src/transformer_utils.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/protocol-utils/src/transformer_utils.ts b/packages/protocol-utils/src/transformer_utils.ts index dd7cc46389..ab5f6e81d9 100644 --- a/packages/protocol-utils/src/transformer_utils.ts +++ b/packages/protocol-utils/src/transformer_utils.ts @@ -163,6 +163,7 @@ export enum BridgeProtocol { Synthetix, WOOFi, AaveV3, + Clober } /** From 7d499135428dcd61515f792ce7469e0d0b0b69d6 Mon Sep 17 00:00:00 2001 From: graykode Date: Wed, 15 Feb 2023 11:03:35 +0900 Subject: [PATCH 5/7] style: more clean code --- .../bridges/mixins/MixinClober.sol | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinClober.sol b/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinClober.sol index 26704c1ef4..5edb46005d 100644 --- a/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinClober.sol +++ b/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinClober.sol @@ -65,22 +65,34 @@ contract MixinClober { // Grant the Clober router an allowance to sell the sell token. sellToken.approveIfBelow(address(router), sellAmount); - ICloberRouter.MarketOrderParams memory params = ICloberRouter.MarketOrderParams({ - market: address(market), - deadline: uint64(block.timestamp + 100), - user: msg.sender, - limitPriceIndex: isTakingBid ? 0 : type(uint16).max, - rawAmount: isTakingBid ? 0 : market.quoteToRaw(sellAmount, true), - expendInput: true, - useNative: address(sellToken) == address(WETH) ? true : false, - baseAmount: isTakingBid ? sellAmount : 0 - }); - + bool useNative = address(sellToken) == address(WETH) ? true : false; uint256 beforeBalance = buyToken.balanceOf(address(this)); if (isTakingBid) { - router.marketAsk(params); + router.marketAsk( + ICloberRouter.MarketOrderParams({ + market: address(market), + deadline: uint64(block.timestamp + 100), + user: msg.sender, + limitPriceIndex: 0, + rawAmount: 0, + expendInput: true, + useNative: useNative, + baseAmount: sellAmount + }) + ); } else { - router.marketBid(params); + router.marketBid( + ICloberRouter.MarketOrderParams({ + market: address(market), + deadline: uint64(block.timestamp + 100), + user: msg.sender, + limitPriceIndex: type(uint16).max, + rawAmount: market.quoteToRaw(sellAmount, true), + expendInput: true, + useNative: useNative, + baseAmount: 0 + }) + ); } return buyToken.balanceOf(address(this)).safeSub(beforeBalance); } From 1561df5a79f7ab670be7c9768afdf1d0a076ee5d Mon Sep 17 00:00:00 2001 From: graykode Date: Wed, 15 Feb 2023 15:42:51 +0900 Subject: [PATCH 6/7] style: lint to alpabet order --- .../src/transformers/bridges/ArbitrumBridgeAdapter.sol | 6 +++--- .../src/transformers/bridges/EthereumBridgeAdapter.sol | 6 +++--- .../src/transformers/bridges/PolygonBridgeAdapter.sol | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contracts/zero-ex/contracts/src/transformers/bridges/ArbitrumBridgeAdapter.sol b/contracts/zero-ex/contracts/src/transformers/bridges/ArbitrumBridgeAdapter.sol index 54db84122a..de2c19f910 100644 --- a/contracts/zero-ex/contracts/src/transformers/bridges/ArbitrumBridgeAdapter.sol +++ b/contracts/zero-ex/contracts/src/transformers/bridges/ArbitrumBridgeAdapter.sol @@ -35,6 +35,7 @@ contract ArbitrumBridgeAdapter is AbstractBridgeAdapter(42161, "Arbitrum"), MixinAaveV3, MixinBalancerV2Batch, + MixinClober, MixinCurve, MixinCurveV2, MixinDodoV2, @@ -44,10 +45,9 @@ contract ArbitrumBridgeAdapter is MixinUniswapV3, MixinUniswapV2, MixinWOOFi, - MixinZeroExBridge, - MixinClober + MixinZeroExBridge { - constructor(IEtherTokenV06 weth) public MixinCurve(weth) MixinAaveV3(true) MixinClober(weth) {} + constructor(IEtherTokenV06 weth) public MixinClober(weth) MixinCurve(weth) MixinAaveV3(true) {} function _trade( BridgeOrder memory order, diff --git a/contracts/zero-ex/contracts/src/transformers/bridges/EthereumBridgeAdapter.sol b/contracts/zero-ex/contracts/src/transformers/bridges/EthereumBridgeAdapter.sol index d944043a56..78c79b210c 100644 --- a/contracts/zero-ex/contracts/src/transformers/bridges/EthereumBridgeAdapter.sol +++ b/contracts/zero-ex/contracts/src/transformers/bridges/EthereumBridgeAdapter.sol @@ -48,6 +48,7 @@ contract EthereumBridgeAdapter is MixinBalancerV2Batch, MixinBancor, MixinBancorV3, + MixinClober, MixinCompound, MixinCurve, MixinCurveV2, @@ -64,8 +65,7 @@ contract EthereumBridgeAdapter is MixinUniswap, MixinUniswapV2, MixinUniswapV3, - MixinZeroExBridge, - MixinClober + MixinZeroExBridge { constructor( IEtherTokenV06 weth @@ -73,11 +73,11 @@ contract EthereumBridgeAdapter is public MixinBancor(weth) MixinBancorV3(weth) + MixinClober(weth) MixinCompound(weth) MixinCurve(weth) MixinLido(weth) MixinUniswap(weth) - MixinClober(weth) {} function _trade( diff --git a/contracts/zero-ex/contracts/src/transformers/bridges/PolygonBridgeAdapter.sol b/contracts/zero-ex/contracts/src/transformers/bridges/PolygonBridgeAdapter.sol index 26f3adeadc..9b43428a4f 100644 --- a/contracts/zero-ex/contracts/src/transformers/bridges/PolygonBridgeAdapter.sol +++ b/contracts/zero-ex/contracts/src/transformers/bridges/PolygonBridgeAdapter.sol @@ -39,6 +39,7 @@ contract PolygonBridgeAdapter is MixinAaveV3, MixinAaveV2, MixinBalancerV2Batch, + MixinClober, MixinCurve, MixinCurveV2, MixinDodo, @@ -50,10 +51,9 @@ contract PolygonBridgeAdapter is MixinUniswapV3, MixinSolidly, MixinWOOFi, - MixinZeroExBridge, - MixinClober + MixinZeroExBridge { - constructor(IEtherTokenV06 weth) public MixinCurve(weth) MixinAaveV3(false) MixinClober(weth) {} + constructor(IEtherTokenV06 weth) public MixinClober(weth) MixinCurve(weth) MixinAaveV3(false) {} function _trade( BridgeOrder memory order, From faac6a9961d1015ebfdb7f35f2090738c2a91883 Mon Sep 17 00:00:00 2001 From: graykode Date: Wed, 15 Feb 2023 16:07:09 +0900 Subject: [PATCH 7/7] fix: add shouldUseFakeGasEstimate to prevent default gas limit --- contracts/test-utils/src/web3_wrapper.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/test-utils/src/web3_wrapper.ts b/contracts/test-utils/src/web3_wrapper.ts index 10040f1996..99bd69e7f5 100644 --- a/contracts/test-utils/src/web3_wrapper.ts +++ b/contracts/test-utils/src/web3_wrapper.ts @@ -17,6 +17,7 @@ export const txDefaults = { export const providerConfigs: Web3Config = { total_accounts: constants.NUM_TEST_ACCOUNTS, shouldUseInProcessGanache: true, + shouldUseFakeGasEstimate: false, shouldAllowUnlimitedContractSize: true, hardfork: 'istanbul', gasLimit: 100e6,