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

Commit

Permalink
WIP: first bridgeTransferFrom() test succeeding!
Browse files Browse the repository at this point in the history
  • Loading branch information
xianny committed May 28, 2020
1 parent 84e0e66 commit 82ea407
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 101 deletions.
38 changes: 18 additions & 20 deletions contracts/asset-proxy/contracts/src/bridges/UniswapV2Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
import "@0x/contracts-utils/contracts/src/LibAddressArray.sol";
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "../interfaces/IUniswapV2Router01.sol";
import "../interfaces/IERC20Bridge.sol";
Expand All @@ -35,6 +36,7 @@ contract UniswapV2Bridge is
IWallet,
DeploymentConstants
{
using LibAddressArray for address[];

struct TransferState {
address fromTokenAddress;
Expand Down Expand Up @@ -66,38 +68,32 @@ contract UniswapV2Bridge is

// Decode the bridge data to get the `fromTokenAddress`.
(state.fromTokenAddress) = abi.decode(bridgeData, (address));
require(state.fromTokenAddress != address(0), 'non zero address');

// Just transfer the tokens if they're the same.
if (state.fromTokenAddress == toTokenAddress) {
if (state.fromTokenAddress == toTokenAddress) { // NOT TESTED
LibERC20Token.transfer(state.fromTokenAddress, to, amount);
return BRIDGE_SUCCESS;
}

// Get our balance of `fromTokenAddress` token.
state.fromTokenBalance = IERC20Token(state.fromTokenAddress).balanceOf(address(this));

require(state.fromTokenBalance > 0, 'balance is zero');

// Grant the Uniswap router an allowance.
LibERC20Token.approveIfBelow(
state.fromTokenAddress,
_getUniswapV2Router01Address(),
state.fromTokenBalance
);
revert('wtf4');
// // Grant the Uniswap router an allowance. // FIXME: REVERTING
// LibERC20Token.approve(
// state.fromTokenAddress,
// _getUniswapV2Router01Address(),
// // state.fromTokenBalance
// uint256(-1)
// );

// Convert directly from fromTokenAddress to toTokenAddress
address[] memory path;
path[0] = state.fromTokenAddress;
revert('wtf5');
path[1] = toTokenAddress;
revert('wtf6');
address[] memory path = new address[](2);
path = path.append(state.fromTokenAddress);
path = path.append(toTokenAddress);

// Buy as much `toTokenAddress` token with `fromTokenAddress` token
// and transfer it to `to`.
IUniswapV2Router01 router = IUniswapV2Router01(_getUniswapV2Router01Address());
revert('wtf7');
uint[] memory amounts = router.swapExactTokensForTokens(
// Sell all tokens we hold.
state.fromTokenBalance,
Expand All @@ -110,20 +106,22 @@ contract UniswapV2Bridge is
// Expires after this block.
block.timestamp
);
revert('wtf8');

state.boughtAmount = amounts[1];

revert('wtf9');

emit ERC20BridgeTransfer(
// input token
state.fromTokenAddress,
// output token
toTokenAddress,
// input token amount
state.fromTokenBalance,
// output token amount
state.boughtAmount,
from,
to
);

return BRIDGE_SUCCESS;
}

Expand Down
108 changes: 35 additions & 73 deletions contracts/asset-proxy/contracts/test/TestUniswapV2Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,18 @@ pragma experimental ABIEncoderV2;

import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
import "@0x/contracts-utils/contracts/src/LibAddressArray.sol";
import "../src/bridges/UniswapV2Bridge.sol";
import "../src/interfaces/IUniswapV2Router01.sol";


contract TestEventsRaiser {
/// @dev A minimalist ERC20/WETH token.
contract TestToken {

using LibSafeMath for uint256;

mapping (address => uint256) public balances;
string private _nextRevertReason;

event TokenTransfer(
address token,
Expand All @@ -39,66 +46,6 @@ contract TestEventsRaiser {
uint256 allowance
);

event TokenToTokenTransferInput(
address exchange,
uint256 tokensSold,
uint256 minTokensBought,
uint256 deadline,
address recipient,
address toTokenAddress
);

function raiseTokenToTokenTransferInput(
uint256 tokensSold,
uint256 minTokensBought,
uint256 deadline,
address recipient,
address toTokenAddress
)
external
{
emit TokenToTokenTransferInput(
msg.sender,
tokensSold,
minTokensBought,
deadline,
recipient,
toTokenAddress
);
}

function raiseTokenTransfer(
address from,
address to,
uint256 amount
)
external
{
emit TokenTransfer(
msg.sender,
from,
to,
amount
);
}

function raiseTokenApprove(address spender, uint256 allowance)
external
{
emit TokenApprove(spender, allowance);
}

}


/// @dev A minimalist ERC20/WETH token.
contract TestToken {

using LibSafeMath for uint256;

mapping (address => uint256) public balances;
string private _nextRevertReason;

/// @dev Set the balance for `owner`.
function setBalance(address owner)
external
Expand All @@ -115,29 +62,25 @@ contract TestToken {
_nextRevertReason = reason;
}

/// @dev Just calls `raiseTokenTransfer()` on the caller.
/// @dev Just emits a TokenTransfer event on the caller
function transfer(address to, uint256 amount)
external
returns (bool)
{
_revertIfReasonExists();
TestEventsRaiser(msg.sender).raiseTokenTransfer(msg.sender, to, amount);
emit TokenTransfer(msg.sender, msg.sender, to, amount);
return true;
}

/// @dev Just calls `raiseTokenApprove()` on the caller.
/// @dev Just emits a TokenApprove event on the caller
function approve(address spender, uint256 allowance)
external
returns (bool)
{
TestEventsRaiser(msg.sender).raiseTokenApprove(spender, allowance);
emit TokenApprove(spender, allowance);
return true;
}

function allowance(address, address) external view returns (uint256) {
return 0;
}

/// @dev `IWETH.deposit()` that increases balances and calls
/// `raiseWethDeposit()` on the caller.
function deposit()
Expand All @@ -160,6 +103,10 @@ contract TestToken {
// TestEventsRaiser(msg.sender).raiseWethWithdraw(amount);
}

function allowance(address, address) external view returns (uint256) {
return 0;
}

/// @dev Retrieve the balance for `owner`.
function balanceOf(address owner)
external
Expand All @@ -183,6 +130,16 @@ contract TestToken {
contract TestRouter is
IUniswapV2Router01
{

event TokenToTokenTransferInput(
address exchange,
uint256 tokensSold,
uint256 minTokensBought,
uint256 deadline,
address recipient,
address toTokenAddress
);

function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
Expand All @@ -191,24 +148,29 @@ contract TestRouter is
uint deadline
) external returns (uint[] memory amounts)
{
amounts = new uint[](2);
amounts[0] = amountIn;
// amounts[1] = address(this).balance;
amounts[1] = amountOutMin;
TestEventsRaiser(msg.sender).raiseTokenToTokenTransferInput(

emit TokenToTokenTransferInput(
msg.sender,
// tokens sold
amountIn,
// min tokens bought
// tokens bought
amountOutMin,
// expiry
// deadline
deadline,
// recipient
to,
// toTokenAddress
// output token (toTokenAddress)
path[1]
);
}

}


/// @dev UniswapV2Bridge overridden to mock tokens and Uniswap router
contract TestUniswapV2Bridge is
UniswapV2Bridge
Expand Down
14 changes: 6 additions & 8 deletions contracts/asset-proxy/test/uniswapv2_bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,13 @@ blockchainTests.resets.only('UniswapV2 unit tests', env => {
);
_opts.fromTokenAddress = await createFromTokenFn.callAsync(callData);
await createFromTokenFn.awaitTransactionSuccessAsync(callData);
console.log(`created fromtoken ${_opts.fromTokenAddress}`);

// Create the "to" token and exchange.
const createToTokenFn = testContract.createToken(
_opts.toTokenAddress,
);
_opts.toTokenAddress = await createToTokenFn.callAsync(callData);
await createToTokenFn.awaitTransactionSuccessAsync(callData);
console.log(`created totoken ${_opts.toTokenAddress}`);

// Set the token balance for the token we're converting from.
await testContract.setTokenBalance(_opts.fromTokenAddress).awaitTransactionSuccessAsync({
Expand Down Expand Up @@ -129,14 +127,14 @@ blockchainTests.resets.only('UniswapV2 unit tests', env => {

it('just transfers tokens to `to` if the same tokens are in play', async () => {
const { opts, result, logs } = await withdrawToAsync();
expect(result).to.eq(AssetProxyId.ERC20Bridge);
expect(result).to.eq(AssetProxyId.ERC20Bridge, 'asset proxy id');
const transfers = filterLogsToArguments<UniswapV2BridgeERC20BridgeTransferEventArgs>(logs, UniswapV2BridgeEvents.ERC20BridgeTransfer);
expect(transfers.length).to.eq(1);
expect(transfers[0].inputToken).to.eq(opts.fromTokenAddress);
expect(transfers[0].outputToken).to.eq(opts.toTokenAddress);
expect(transfers[0].from).to.eq(testContract.address);
expect(transfers[0].to).to.eq(opts.toAddress);
expect(transfers[0].inputTokenAmount).to.bignumber.eq(opts.amount);
expect(transfers[0].inputToken).to.eq(opts.fromTokenAddress, 'input token address');
expect(transfers[0].outputToken).to.eq(opts.toTokenAddress, 'output token address');
expect(transfers[0].to).to.eq(opts.toAddress, 'recipient address');
expect(transfers[0].inputTokenAmount).to.bignumber.eq(opts.fromTokenBalance, 'input token amount');
expect(transfers[0].outputTokenAmount).to.bignumber.eq(opts.amount, 'output token amount');
});
});
});

0 comments on commit 82ea407

Please sign in to comment.