diff --git a/contracts/asset-proxy/CHANGELOG.json b/contracts/asset-proxy/CHANGELOG.json index b05613fb2a..b14c13f75c 100644 --- a/contracts/asset-proxy/CHANGELOG.json +++ b/contracts/asset-proxy/CHANGELOG.json @@ -21,6 +21,9 @@ { "note": "Add `DexForwaderBridge` bridge contract.", "pr": 2525 + }, + { + "note": "Add Gas Token freeing to `DexForwaderBridge` contract." } ] }, diff --git a/contracts/asset-proxy/contracts/src/bridges/DexForwarderBridge.sol b/contracts/asset-proxy/contracts/src/bridges/DexForwarderBridge.sol index 70409719db..a6cd09fee4 100644 --- a/contracts/asset-proxy/contracts/src/bridges/DexForwarderBridge.sol +++ b/contracts/asset-proxy/contracts/src/bridges/DexForwarderBridge.sol @@ -23,15 +23,19 @@ import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol"; import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol"; +import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol"; import "@0x/contracts-utils/contracts/src/LibBytes.sol"; import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; import "../interfaces/IERC20Bridge.sol"; +import "./MixinGasToken.sol"; // solhint-disable space-after-comma, indent contract DexForwarderBridge is IERC20Bridge, - IWallet + IWallet, + DeploymentConstants, + MixinGasToken { using LibSafeMath for uint256; @@ -68,6 +72,7 @@ contract DexForwarderBridge is bytes calldata bridgeData ) external + freesGasTokensFromCollector returns (bytes4 success) { TransferFromState memory state; @@ -84,16 +89,15 @@ contract DexForwarderBridge is break; } - BridgeCall memory call = state.calls[i]; // Compute token amounts. state.callInputTokenAmount = LibSafeMath.min256( - call.inputTokenAmount, + state.calls[i].inputTokenAmount, state.initialInputTokenBalance.safeSub(state.totalInputTokenSold) ); state.callOutputTokenAmount = LibMath.getPartialAmountFloor( state.callInputTokenAmount, - call.inputTokenAmount, - call.outputTokenAmount + state.calls[i].inputTokenAmount, + state.calls[i].outputTokenAmount ); // Execute the call in a new context so we can recoup transferred @@ -101,13 +105,13 @@ contract DexForwarderBridge is (bool didSucceed, ) = address(this) .call(abi.encodeWithSelector( this.executeBridgeCall.selector, - call.target, + state.calls[i].target, to, state.inputToken, outputToken, state.callInputTokenAmount, state.callOutputTokenAmount, - call.bridgeData + state.calls[i].bridgeData )); if (didSucceed) { diff --git a/contracts/asset-proxy/contracts/test/TestDexForwarderBridge.sol b/contracts/asset-proxy/contracts/test/TestDexForwarderBridge.sol index c0ada6c30b..dcb72fe093 100644 --- a/contracts/asset-proxy/contracts/test/TestDexForwarderBridge.sol +++ b/contracts/asset-proxy/contracts/test/TestDexForwarderBridge.sol @@ -156,6 +156,7 @@ contract TestDexForwarderBridge is ITestDexForwarderBridge, DexForwarderBridge { + function createBridge( bytes4 returnCode, string memory revertError @@ -217,4 +218,12 @@ contract TestDexForwarderBridge is function balanceOf(address token, address owner) public view returns (uint256) { return TestDexForwarderBridgeTestToken(token).balanceOf(owner); } + + function _getGstAddress() + internal + view + returns (address gst) + { + return address(0); + } } 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 9c220b03b8..30c2f16d8c 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/orders.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/orders.ts @@ -152,10 +152,19 @@ export function createOrdersFromPath(path: Fill[], opts: CreateOrderFromPathOpts ++i; continue; } + // Liquidity Provider must be called by ERC20BridgeProxy + if (collapsedPath[i].source === ERC20BridgeSource.LiquidityProvider) { + orders.push(createBridgeOrder(collapsedPath[i], opts)); + ++i; + continue; + } // If there are contiguous bridge orders, we can batch them together. const contiguousBridgeFills = [collapsedPath[i]]; for (let j = i + 1; j < collapsedPath.length; ++j) { - if (collapsedPath[j].source === ERC20BridgeSource.Native) { + if ( + collapsedPath[j].source === ERC20BridgeSource.Native || + collapsedPath[j].source === ERC20BridgeSource.LiquidityProvider + ) { break; } contiguousBridgeFills.push(collapsedPath[j]); diff --git a/packages/contract-addresses/CHANGELOG.json b/packages/contract-addresses/CHANGELOG.json index e1739a3faa..f0d7a7f954 100644 --- a/packages/contract-addresses/CHANGELOG.json +++ b/packages/contract-addresses/CHANGELOG.json @@ -29,6 +29,12 @@ { "note": "Redeploy `Forwarder` on all networks", "pr": 2521 + }, + { + "note": "Redeploy `DexForwarderBridge` on Mainnet with Gas Token freeing" + }, + { + "note": "Revert to older Curve Bridge (without Gas Tokens)" } ] }, diff --git a/packages/contract-addresses/addresses.json b/packages/contract-addresses/addresses.json index 45e9820fa8..123a1d2202 100644 --- a/packages/contract-addresses/addresses.json +++ b/packages/contract-addresses/addresses.json @@ -28,9 +28,9 @@ "godsUnchainedValidator": "0x09a379ef7218bcfd8913faa8b281ebc5a2e0bc04", "broker": "0xd4690a51044db77d91d7aa8f7a3a5ad5da331af0", "chainlinkStopLimit": "0xeb27220f95f364e1d9531992c48613f231839f53", - "curveBridge": "0x1cf6ccc7e15d0d99a9498f37e16ba65b5c54bdd0", + "curveBridge": "0x6dc7950423ada9f56fb2c93a23edb787f1e29088", "maximumGasPrice": "0xe2bfd35306495d11e3c9db0d8de390cda24563cf", - "dexForwarderBridge": "0xa96844087062acf8556ca06a27702c6d19f87e57" + "dexForwarderBridge": "0x2b135c732110be20db72e44ab2a4b149fa213599" }, "3": { "erc20Proxy": "0xb1408f4c245a23c31b98d2c626777d4c0d766caa",