Skip to content
This repository was archived by the owner on Jul 9, 2021. It is now read-only.

Commit e05a03a

Browse files
authored
Curve ERC20Bridge (#2480)
* Curve ERC20Bridge * ERC20BridgeSampler Curve (#2483) * ERC20Sampler Curve * Use Bridge Sources for each Curve * Support multiple versions of the Curve contract * CHANGELOG and redeployed Curve (mainnet) * Fix Market ops utils test * Added Curve DAI USDC USDT TUSD * Bump sampler gas limit default * Decode the Curve in tests * Disable Curve in Buy tests * blockchainTests.fork.resets Curve and Sampler
1 parent dcce827 commit e05a03a

File tree

35 files changed

+839
-35
lines changed

35 files changed

+839
-35
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
2+
/*
3+
4+
Copyright 2019 ZeroEx Intl.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
18+
*/
19+
20+
pragma solidity ^0.5.9;
21+
pragma experimental ABIEncoderV2;
22+
23+
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
24+
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
25+
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
26+
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
27+
import "../interfaces/IERC20Bridge.sol";
28+
import "../interfaces/ICurve.sol";
29+
30+
31+
// solhint-disable not-rely-on-time
32+
// solhint-disable space-after-comma
33+
contract CurveBridge is
34+
IERC20Bridge,
35+
IWallet,
36+
DeploymentConstants
37+
{
38+
/// @dev Callback for `ICurve`. Tries to buy `amount` of
39+
/// `toTokenAddress` tokens by selling the entirety of the opposing asset
40+
/// (DAI, USDC) to the Curve contract, then transfers the bought
41+
/// tokens to `to`.
42+
/// @param toTokenAddress The token to give to `to` (i.e DAI, USDC, USDT).
43+
/// @param to The recipient of the bought tokens.
44+
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
45+
/// @param bridgeData The abi-encoeded "from" token address.
46+
/// @return success The magic bytes if successful.
47+
function bridgeTransferFrom(
48+
address toTokenAddress,
49+
address /* from */,
50+
address to,
51+
uint256 amount,
52+
bytes calldata bridgeData
53+
)
54+
external
55+
returns (bytes4 success)
56+
{
57+
// Decode the bridge data to get the Curve metadata.
58+
(address curveAddress, int128 fromCoinIdx, int128 toCoinIdx, int128 version) = abi.decode(bridgeData, (address, int128, int128, int128));
59+
ICurve exchange = ICurve(curveAddress);
60+
61+
address fromTokenAddress = exchange.underlying_coins(fromCoinIdx);
62+
require(toTokenAddress != fromTokenAddress, "CurveBridge/INVALID_PAIR");
63+
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
64+
LibERC20Token.approve(fromTokenAddress, address(exchange), uint256(-1));
65+
66+
// Try to sell all of this contract's `fromTokenAddress` token balance.
67+
if (version == 0) {
68+
exchange.exchange_underlying(
69+
fromCoinIdx,
70+
toCoinIdx,
71+
// dx
72+
IERC20Token(fromTokenAddress).balanceOf(address(this)),
73+
// min dy
74+
amount,
75+
// expires
76+
block.timestamp + 1
77+
);
78+
} else {
79+
exchange.exchange_underlying(
80+
fromCoinIdx,
81+
toCoinIdx,
82+
// dx
83+
IERC20Token(fromTokenAddress).balanceOf(address(this)),
84+
// min dy
85+
amount
86+
);
87+
}
88+
89+
uint256 toTokenBalance = IERC20Token(toTokenAddress).balanceOf(address(this));
90+
// Transfer the converted `toToken`s to `to`.
91+
LibERC20Token.transfer(toTokenAddress, to, toTokenBalance);
92+
return BRIDGE_SUCCESS;
93+
}
94+
95+
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
96+
/// and sign for itself in orders. Always succeeds.
97+
/// @return magicValue Magic success bytes, always.
98+
function isValidSignature(
99+
bytes32,
100+
bytes calldata
101+
)
102+
external
103+
view
104+
returns (bytes4 magicValue)
105+
{
106+
return LEGACY_WALLET_MAGIC_VALUE;
107+
}
108+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
3+
Copyright 2019 ZeroEx Intl.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
17+
*/
18+
19+
pragma solidity ^0.5.9;
20+
21+
22+
// solhint-disable func-name-mixedcase
23+
interface ICurve {
24+
25+
/// @dev Sell `sellAmount` of `fromToken` token and receive `toToken` token.
26+
/// This function exists on early versions of Curve (USDC/DAI)
27+
/// @param i The token index being sold.
28+
/// @param j The token index being bought.
29+
/// @param sellAmount The amount of token being bought.
30+
/// @param minBuyAmount The minimum buy amount of the token being bought.
31+
/// @param deadline The time in seconds when this operation should expire.
32+
function exchange_underlying(
33+
int128 i,
34+
int128 j,
35+
uint256 sellAmount,
36+
uint256 minBuyAmount,
37+
uint256 deadline
38+
)
39+
external;
40+
41+
/// @dev Sell `sellAmount` of `fromToken` token and receive `toToken` token.
42+
/// This function exists on later versions of Curve (USDC/DAI/USDT)
43+
/// @param i The token index being sold.
44+
/// @param j The token index being bought.
45+
/// @param sellAmount The amount of token being bought.
46+
/// @param minBuyAmount The minimum buy amount of the token being bought.
47+
function exchange_underlying(
48+
int128 i,
49+
int128 j,
50+
uint256 sellAmount,
51+
uint256 minBuyAmount
52+
)
53+
external;
54+
55+
/// @dev Get the amount of `toToken` by selling `sellAmount` of `fromToken`
56+
/// @param i The token index being sold.
57+
/// @param j The token index being bought.
58+
/// @param sellAmount The amount of token being bought.
59+
function get_dy_underlying(
60+
int128 i,
61+
int128 j,
62+
uint256 sellAmount
63+
)
64+
external
65+
returns (uint256 dy);
66+
67+
/// @dev Get the amount of `fromToken` by buying `buyAmount` of `toToken`
68+
/// This function exists on later versions of Curve (USDC/DAI/USDT)
69+
/// @param i The token index being sold.
70+
/// @param j The token index being bought.
71+
/// @param buyAmount The amount of token being bought.
72+
function get_dx_underlying(
73+
int128 i,
74+
int128 j,
75+
uint256 buyAmount
76+
)
77+
external
78+
returns (uint256 dx);
79+
80+
/// @dev Get the underlying token address from the token index
81+
/// @param i The token index.
82+
function underlying_coins(
83+
int128 i
84+
)
85+
external
86+
returns (address tokenAddress);
87+
}

contracts/asset-proxy/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
3939
},
4040
"config": {
41-
"abis": "./test/generated-artifacts/@(ChaiBridge|DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IChai|IDydx|IDydxBridge|IERC20Bridge|IEth2Dai|IKyberNetworkProxy|IUniswapExchange|IUniswapExchangeFactory|KyberBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestChaiBridge|TestDydxBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|UniswapBridge).json",
41+
"abis": "./test/generated-artifacts/@(ChaiBridge|CurveBridge|DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IChai|ICurve|IDydx|IDydxBridge|IERC20Bridge|IEth2Dai|IKyberNetworkProxy|IUniswapExchange|IUniswapExchangeFactory|KyberBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestChaiBridge|TestDydxBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|UniswapBridge).json",
4242
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
4343
},
4444
"repository": {

contracts/asset-proxy/src/artifacts.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import { ContractArtifact } from 'ethereum-types';
77

88
import * as ChaiBridge from '../generated-artifacts/ChaiBridge.json';
9+
import * as CurveBridge from '../generated-artifacts/CurveBridge.json';
910
import * as DydxBridge from '../generated-artifacts/DydxBridge.json';
1011
import * as ERC1155Proxy from '../generated-artifacts/ERC1155Proxy.json';
1112
import * as ERC20BridgeProxy from '../generated-artifacts/ERC20BridgeProxy.json';
@@ -17,6 +18,7 @@ import * as IAssetProxy from '../generated-artifacts/IAssetProxy.json';
1718
import * as IAssetProxyDispatcher from '../generated-artifacts/IAssetProxyDispatcher.json';
1819
import * as IAuthorizable from '../generated-artifacts/IAuthorizable.json';
1920
import * as IChai from '../generated-artifacts/IChai.json';
21+
import * as ICurve from '../generated-artifacts/ICurve.json';
2022
import * as IDydx from '../generated-artifacts/IDydx.json';
2123
import * as IDydxBridge from '../generated-artifacts/IDydxBridge.json';
2224
import * as IERC20Bridge from '../generated-artifacts/IERC20Bridge.json';
@@ -49,6 +51,7 @@ export const artifacts = {
4951
MultiAssetProxy: MultiAssetProxy as ContractArtifact,
5052
StaticCallProxy: StaticCallProxy as ContractArtifact,
5153
ChaiBridge: ChaiBridge as ContractArtifact,
54+
CurveBridge: CurveBridge as ContractArtifact,
5255
DydxBridge: DydxBridge as ContractArtifact,
5356
Eth2DaiBridge: Eth2DaiBridge as ContractArtifact,
5457
KyberBridge: KyberBridge as ContractArtifact,
@@ -58,6 +61,7 @@ export const artifacts = {
5861
IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
5962
IAuthorizable: IAuthorizable as ContractArtifact,
6063
IChai: IChai as ContractArtifact,
64+
ICurve: ICurve as ContractArtifact,
6165
IDydx: IDydx as ContractArtifact,
6266
IDydxBridge: IDydxBridge as ContractArtifact,
6367
IERC20Bridge: IERC20Bridge as ContractArtifact,

contracts/asset-proxy/src/wrappers.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* -----------------------------------------------------------------------------
55
*/
66
export * from '../generated-wrappers/chai_bridge';
7+
export * from '../generated-wrappers/curve_bridge';
78
export * from '../generated-wrappers/dydx_bridge';
89
export * from '../generated-wrappers/erc1155_proxy';
910
export * from '../generated-wrappers/erc20_bridge_proxy';
@@ -15,6 +16,7 @@ export * from '../generated-wrappers/i_asset_proxy';
1516
export * from '../generated-wrappers/i_asset_proxy_dispatcher';
1617
export * from '../generated-wrappers/i_authorizable';
1718
export * from '../generated-wrappers/i_chai';
19+
export * from '../generated-wrappers/i_curve';
1820
export * from '../generated-wrappers/i_dydx';
1921
export * from '../generated-wrappers/i_dydx_bridge';
2022
export * from '../generated-wrappers/i_erc20_bridge';

contracts/asset-proxy/test/artifacts.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import { ContractArtifact } from 'ethereum-types';
77

88
import * as ChaiBridge from '../test/generated-artifacts/ChaiBridge.json';
9+
import * as CurveBridge from '../test/generated-artifacts/CurveBridge.json';
910
import * as DydxBridge from '../test/generated-artifacts/DydxBridge.json';
1011
import * as ERC1155Proxy from '../test/generated-artifacts/ERC1155Proxy.json';
1112
import * as ERC20BridgeProxy from '../test/generated-artifacts/ERC20BridgeProxy.json';
@@ -17,6 +18,7 @@ import * as IAssetProxy from '../test/generated-artifacts/IAssetProxy.json';
1718
import * as IAssetProxyDispatcher from '../test/generated-artifacts/IAssetProxyDispatcher.json';
1819
import * as IAuthorizable from '../test/generated-artifacts/IAuthorizable.json';
1920
import * as IChai from '../test/generated-artifacts/IChai.json';
21+
import * as ICurve from '../test/generated-artifacts/ICurve.json';
2022
import * as IDydx from '../test/generated-artifacts/IDydx.json';
2123
import * as IDydxBridge from '../test/generated-artifacts/IDydxBridge.json';
2224
import * as IERC20Bridge from '../test/generated-artifacts/IERC20Bridge.json';
@@ -49,6 +51,7 @@ export const artifacts = {
4951
MultiAssetProxy: MultiAssetProxy as ContractArtifact,
5052
StaticCallProxy: StaticCallProxy as ContractArtifact,
5153
ChaiBridge: ChaiBridge as ContractArtifact,
54+
CurveBridge: CurveBridge as ContractArtifact,
5255
DydxBridge: DydxBridge as ContractArtifact,
5356
Eth2DaiBridge: Eth2DaiBridge as ContractArtifact,
5457
KyberBridge: KyberBridge as ContractArtifact,
@@ -58,6 +61,7 @@ export const artifacts = {
5861
IAssetProxyDispatcher: IAssetProxyDispatcher as ContractArtifact,
5962
IAuthorizable: IAuthorizable as ContractArtifact,
6063
IChai: IChai as ContractArtifact,
64+
ICurve: ICurve as ContractArtifact,
6165
IDydx: IDydx as ContractArtifact,
6266
IDydxBridge: IDydxBridge as ContractArtifact,
6367
IERC20Bridge: IERC20Bridge as ContractArtifact,

contracts/asset-proxy/test/wrappers.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* -----------------------------------------------------------------------------
55
*/
66
export * from '../test/generated-wrappers/chai_bridge';
7+
export * from '../test/generated-wrappers/curve_bridge';
78
export * from '../test/generated-wrappers/dydx_bridge';
89
export * from '../test/generated-wrappers/erc1155_proxy';
910
export * from '../test/generated-wrappers/erc20_bridge_proxy';
@@ -15,6 +16,7 @@ export * from '../test/generated-wrappers/i_asset_proxy';
1516
export * from '../test/generated-wrappers/i_asset_proxy_dispatcher';
1617
export * from '../test/generated-wrappers/i_authorizable';
1718
export * from '../test/generated-wrappers/i_chai';
19+
export * from '../test/generated-wrappers/i_curve';
1820
export * from '../test/generated-wrappers/i_dydx';
1921
export * from '../test/generated-wrappers/i_dydx_bridge';
2022
export * from '../test/generated-wrappers/i_erc20_bridge';

contracts/asset-proxy/tsconfig.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
55
"files": [
66
"generated-artifacts/ChaiBridge.json",
7+
"generated-artifacts/CurveBridge.json",
78
"generated-artifacts/DydxBridge.json",
89
"generated-artifacts/ERC1155Proxy.json",
910
"generated-artifacts/ERC20BridgeProxy.json",
@@ -15,6 +16,7 @@
1516
"generated-artifacts/IAssetProxyDispatcher.json",
1617
"generated-artifacts/IAuthorizable.json",
1718
"generated-artifacts/IChai.json",
19+
"generated-artifacts/ICurve.json",
1820
"generated-artifacts/IDydx.json",
1921
"generated-artifacts/IDydxBridge.json",
2022
"generated-artifacts/IERC20Bridge.json",
@@ -37,6 +39,7 @@
3739
"generated-artifacts/TestUniswapBridge.json",
3840
"generated-artifacts/UniswapBridge.json",
3941
"test/generated-artifacts/ChaiBridge.json",
42+
"test/generated-artifacts/CurveBridge.json",
4043
"test/generated-artifacts/DydxBridge.json",
4144
"test/generated-artifacts/ERC1155Proxy.json",
4245
"test/generated-artifacts/ERC20BridgeProxy.json",
@@ -48,6 +51,7 @@
4851
"test/generated-artifacts/IAssetProxyDispatcher.json",
4952
"test/generated-artifacts/IAuthorizable.json",
5053
"test/generated-artifacts/IChai.json",
54+
"test/generated-artifacts/ICurve.json",
5155
"test/generated-artifacts/IDydx.json",
5256
"test/generated-artifacts/IDydxBridge.json",
5357
"test/generated-artifacts/IERC20Bridge.json",

contracts/erc20-bridge-sampler/CHANGELOG.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
11
[
2+
{
3+
"version": "1.4.0",
4+
"changes": [
5+
{
6+
"note": "Added Curve contract sampling",
7+
"pr": 2483
8+
}
9+
]
10+
},
211
{
312
"version": "1.3.0",
413
"changes": [

0 commit comments

Comments
 (0)