@0x/contracts-asset-proxy: Update CurveBridge to support more varied curves.

`@0x/contracts-erc20-bridge-sampler`: Refactor.
`@0x/contracts-erc20-bridge-sampler`: Add support for more varied curves.
`@0x/contracts-integrations`: Update curve bridge tests.
This commit is contained in:
Lawrence Forman
2020-07-14 16:32:16 -04:00
committed by Lawrence Forman
parent 74d9df2fb0
commit 4dac620156
28 changed files with 1577 additions and 1463 deletions

View File

@@ -1,4 +1,13 @@
[
{
"version": "3.5.0",
"changes": [
{
"note": "Update `CurveBridge` to support more varied curves",
"pr": 2633
}
]
},
{
"version": "3.4.0",
"changes": [

View File

@@ -26,7 +26,6 @@ import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "../interfaces/IERC20Bridge.sol";
import "../interfaces/ICurve.sol";
import "./MixinGasToken.sol";
// solhint-disable not-rely-on-time
@@ -34,14 +33,14 @@ import "./MixinGasToken.sol";
contract CurveBridge is
IERC20Bridge,
IWallet,
DeploymentConstants,
MixinGasToken
DeploymentConstants
{
struct CurveBridgeData {
address curveAddress;
bytes4 exchangeFunctionSelector;
address fromTokenAddress;
int128 fromCoinIdx;
int128 toCoinIdx;
int128 version;
}
/// @dev Callback for `ICurve`. Tries to buy `amount` of
@@ -62,39 +61,31 @@ contract CurveBridge is
bytes calldata bridgeData
)
external
freesGasTokensFromCollector
returns (bytes4 success)
{
// Decode the bridge data to get the Curve metadata.
CurveBridgeData memory data = abi.decode(bridgeData, (CurveBridgeData));
address fromTokenAddress = ICurve(data.curveAddress).underlying_coins(data.fromCoinIdx);
require(toTokenAddress != fromTokenAddress, "CurveBridge/INVALID_PAIR");
uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
require(toTokenAddress != data.fromTokenAddress, "CurveBridge/INVALID_PAIR");
uint256 fromTokenBalance = IERC20Token(data.fromTokenAddress).balanceOf(address(this));
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
LibERC20Token.approveIfBelow(fromTokenAddress, data.curveAddress, fromTokenBalance);
LibERC20Token.approveIfBelow(data.fromTokenAddress, data.curveAddress, fromTokenBalance);
// Try to sell all of this contract's `fromTokenAddress` token balance.
if (data.version == 0) {
ICurve(data.curveAddress).exchange_underlying(
data.fromCoinIdx,
data.toCoinIdx,
// dx
fromTokenBalance,
// min dy
amount,
// expires
block.timestamp + 1
);
} else {
ICurve(data.curveAddress).exchange_underlying(
data.fromCoinIdx,
data.toCoinIdx,
// dx
fromTokenBalance,
// min dy
amount
);
{
(bool didSucceed, bytes memory resultData) =
data.curveAddress.call(abi.encodeWithSelector(
data.exchangeFunctionSelector,
data.fromCoinIdx,
data.toCoinIdx,
// dx
fromTokenBalance,
// min dy
amount
));
if (!didSucceed) {
assembly { revert(add(resultData, 32), mload(resultData)) }
}
}
uint256 toTokenBalance = IERC20Token(toTokenAddress).balanceOf(address(this));
@@ -102,7 +93,7 @@ contract CurveBridge is
LibERC20Token.transfer(toTokenAddress, to, toTokenBalance);
emit ERC20BridgeTransfer(
fromTokenAddress,
data.fromTokenAddress,
toTokenAddress,
fromTokenBalance,
toTokenBalance,

View File

@@ -22,22 +22,6 @@ pragma solidity ^0.5.9;
// solhint-disable func-name-mixedcase
interface ICurve {
/// @dev Sell `sellAmount` of `fromToken` token and receive `toToken` token.
/// This function exists on early versions of Curve (USDC/DAI)
/// @param i The token index being sold.
/// @param j The token index being bought.
/// @param sellAmount The amount of token being bought.
/// @param minBuyAmount The minimum buy amount of the token being bought.
/// @param deadline The time in seconds when this operation should expire.
function exchange_underlying(
int128 i,
int128 j,
uint256 sellAmount,
uint256 minBuyAmount,
uint256 deadline
)
external;
/// @dev Sell `sellAmount` of `fromToken` token and receive `toToken` token.
/// This function exists on later versions of Curve (USDC/DAI/USDT)
/// @param i The token index being sold.