import { artifacts as assetProxyArtifacts } from '@0x/contracts-asset-proxy'; import { CurveBridgeContract } from '@0x/contracts-asset-proxy/lib/src/wrappers'; import { ERC20TokenContract } from '@0x/contracts-erc20'; import { blockchainTests, constants, describe, toBaseUnitAmount } from '@0x/contracts-test-utils'; import { AbiEncoder } from '@0x/utils'; const USDC_WALLET = '0x3dfd23a6c5e8bbcfc9581d2e864a68feb6a076d3'; const DAI_WALLET = '0x6cc5f688a315f3dc28a7781717a9a798a59fda7b'; const WBTC_WALLET = '0x56178a0d5F301bAf6CF3e1Cd53d9863437345Bf9'; blockchainTests.configure({ fork: { unlockedAccounts: [USDC_WALLET, DAI_WALLET, WBTC_WALLET], }, }); blockchainTests.fork('Mainnet curve bridge tests', env => { let testContract: CurveBridgeContract; const RECEIVER = '0x986ccf5234d9cfbb25246f1a5bfa51f4ccfcb308'; const bridgeDataEncoder = AbiEncoder.create([ { name: 'curveAddress', type: 'address' }, { name: 'exchangeFunctionSelector', type: 'bytes4' }, { name: 'fromTokenAddress', type: 'address' }, { name: 'fromTokenIdx', type: 'int128' }, { name: 'toTokenIdx', type: 'int128' }, ]); before(async () => { testContract = await CurveBridgeContract.deployFrom0xArtifactAsync( assetProxyArtifacts.CurveBridge, env.provider, { ...env.txDefaults }, {}, ); }); describe('bridgeTransferFrom()', () => { describe('exchange_underlying()', () => { const USDC_ADDRESS = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'; const DAI_ADDRESS = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; const DAI_TOKEN_IDX = 0; const USDC_TOKEN_IDX = 1; const EXCHANGE_UNDERLYING_SELECTOR = '0xa6417ed6'; const CURVE_ADDRESS = '0xa2b47e3d5c44877cca798226b7b8118f9bfb7a56'; it('succeeds exchanges DAI for USDC', async () => { const bridgeData = bridgeDataEncoder.encode([ CURVE_ADDRESS, EXCHANGE_UNDERLYING_SELECTOR, DAI_ADDRESS, DAI_TOKEN_IDX, USDC_TOKEN_IDX, ]); // Fund the Bridge const dai = new ERC20TokenContract(DAI_ADDRESS, env.provider, { ...env.txDefaults, from: DAI_WALLET }); await dai .transfer(testContract.address, toBaseUnitAmount(1)) .awaitTransactionSuccessAsync({}, { shouldValidate: false }); // Exchange via Curve await testContract .bridgeTransferFrom( USDC_ADDRESS, constants.NULL_ADDRESS, RECEIVER, constants.ZERO_AMOUNT, bridgeData, ) .awaitTransactionSuccessAsync({}, { shouldValidate: false }); }); it('succeeds exchanges USDC for DAI', async () => { const bridgeData = bridgeDataEncoder.encode([ CURVE_ADDRESS, EXCHANGE_UNDERLYING_SELECTOR, USDC_ADDRESS, USDC_TOKEN_IDX, DAI_TOKEN_IDX, ]); // Fund the Bridge const usdc = new ERC20TokenContract(USDC_ADDRESS, env.provider, { ...env.txDefaults, from: USDC_WALLET, }); await usdc .transfer(testContract.address, toBaseUnitAmount(1, 6)) .awaitTransactionSuccessAsync({}, { shouldValidate: false }); // Exchange via Curve await testContract .bridgeTransferFrom( DAI_ADDRESS, constants.NULL_ADDRESS, RECEIVER, constants.ZERO_AMOUNT, bridgeData, ) .awaitTransactionSuccessAsync({}, { shouldValidate: false }); }); }); describe('exchange()', () => { const WBTC_ADDRESS = '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599'; const RENBTC_ADDRESS = '0xeb4c2781e4eba804ce9a9803c67d0893436bb27d'; const RENBTC_TOKEN_IDX = 0; const WBTC_TOKEN_IDX = 1; const EXCHANGE_SELECTOR = '0x3df02124'; const CURVE_ADDRESS = '0x7fc77b5c7614e1533320ea6ddc2eb61fa00a9714'; it('succeeds exchanges WBTC for renBTC', async () => { const bridgeData = bridgeDataEncoder.encode([ CURVE_ADDRESS, EXCHANGE_SELECTOR, WBTC_ADDRESS, WBTC_TOKEN_IDX, RENBTC_TOKEN_IDX, ]); // Fund the Bridge const wbtc = new ERC20TokenContract(WBTC_ADDRESS, env.provider, { ...env.txDefaults, from: WBTC_WALLET, }); await wbtc .transfer(testContract.address, toBaseUnitAmount(1, 8)) .awaitTransactionSuccessAsync({}, { shouldValidate: false }); // Exchange via Curve await testContract .bridgeTransferFrom( RENBTC_ADDRESS, constants.NULL_ADDRESS, RECEIVER, constants.ZERO_AMOUNT, bridgeData, ) .awaitTransactionSuccessAsync({ gas: 6e6 }, { shouldValidate: false }); }); }); }); });