我正在尝试通过 uniswap 路由器合约将 weth 令牌交换为 dai 令牌(均为 ERC20):
我尝试了以下两种方法:
1.使用 truffle 控制台来操作 weth/dai/router 合约。这种方法工作正常。详情见下文:
// Dai.sol
pragma solidity ^0.6.6;
contract Dai {
function balanceOf(address owner) external view returns(uint) {}
function totalSupply() external view returns (uint256){}
function transfer(address recipient, uint256 amount) external returns (bool){}
function allowance(address owner, address spender) external view returns (uint256){}
function approve(address spender, uint256 amount) external returns (bool){}
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool){}
}
// Weth.sol
pragma solidity ^0.6.6;
contract Weth {
function deposit() public payable {}
function approve(address spender, uint amount) external {}
function allowance(address owner, address spender) external view returns(uint) {}
function balanceOf(address owner) external view returns(uint) {}
function transfer(address recipient, uint256 amount) external returns (bool){}
}
// Router.sol
pragma solidity ^0.6.6;
contract Router {
function swapExactTokensForTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts){}
function getAmountsOut(uint amountIn, address[] memory path) public view returns (uint[] memory amounts){}
function getAmountsIn(uint amountOut, address[] memory path)public view virtual returns (uint[] memory amounts) {}
}
松露控制台上有一步一步的命令行:
truffle(kovan)> dai = await Dai.at("0x4f96fe3b7a6cf9725f59d353f723c1bdb64ca6aa")
truffle(kovan)> weth = await Weth.at("0xd0a1e359811322d97991e03f863a0c30c2cf029c")
truffle(kovan)> router =await Router.at("0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D")
truffle(kovan)> amountIn = await router.getAmountsIn(web3.utils.toWei("1"), [weth.address, dai.address])
truffle(kovan)> amountIn = amountIn[0]
truffle(kovan)> amountOut = web3.utils.toWei("1")
truffle(kovan)> weth.approve(router.address, amountIn)
truffle(kovan)> time = Math.floor((Date.now()/1000)) + 60*120
truffle(kovan)> router.swapExactTokensForTokens(amountIn, amountOut, [weth.address, dai.address], accounts[0], time)
本例中,swapExactTokensForTokens的交易已经成功通过 (https://kovan.etherscan.io/tx/0x11e51ad94d90ec9b2182768bcea87ad5a15d5cf83a91a02d52f2990cbaed5c61)
// SwapToken.sol
pragma solidity ^0.6.6;
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "@uniswap/v2-core/contracts/interfaces/IERC20.sol";
contract SwapTokens {
IUniswapV2Router02 public uniRouter = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
event test (uint timestamp, uint amountIn, uint amountOut, address[] path, uint allowance, address sender);
function swapper(address token1, address token2) public {
address[] memory path = new address[](2);
path[0] = token1;
path[1] = token2;
uint amountOut = 1 ether;
uint amountIn = uniRouter.getAmountsIn(
amountOut,
path
)[0];
IERC20(token1).approve(address(uniRouter), amountIn);
uint allowed = IERC20(token1).allowance(msg.sender, address(uniRouter));
emit test(now+90, amountIn, amountOut, path, allowed, msg.sender);
uniRouter.swapExactTokensForTokens(
amountIn,
amountOut,
path,
msg.sender,
now + 120
);
}
}
然后我运行交换函数如下:
sw = await SwapTokens.deployed()
sw.swapper(weth.address, dai.address)
交易失败,错误为“TransferHelper: TRANSFER_FROM_FAILED” (https://kovan.etherscan.io/tx/0x3324fd65004e001163b665b79583f894e17854bc3371b89f39d472504cb4b46a)
这两种方法对我来说似乎都是一样的。 我不知道我做错了哪一部分。
答案 0 :(得分:0)
在我看来,您发送的 swapExactTokensForTokens 的 'amountOutMin' 高于 'amountIn',这是不可能的。
见上swapExactTokensForTokens的函数原型:
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
amountOutMin 必须小于 amountIn,因为滑点。你可以在这里找到一个例子:
JS 脚本:
const amountIn = web3.utils.toWei("1");
const amountsOut = await uniswapv2router.getAmountsOut(amountIn, [WETH, SDT]);
const amountOutMin = amountsOut[1].mul(web3.utils.toBN(100 - SLIPPAGE_MAX)).div(web3.utils.toBN(100));
const txSwap = await swapRouter.swapTokens([WETH, SDT], amountIn, amountOutMin, account);
合同:
IUniswapV2Router(UNISWAP_V2_ROUTER).swapExactTokensForTokens(_amountIn, _amountOutMin, path, _to, block.timestamp);
答案 1 :(得分:0)
您应该在调用 swapper 函数之前批准代币到您的合约,并且需要将来自 msg.sender 的代币转移到您的合约中。
FROM node:14 as npm6
WORKDIR /app
# Create a node project using npm 6 and install a dev dependency
# that contains a binary.
RUN npm init --yes && \
npm install --save-dev typescript
FROM node:15 as npm7
COPY --from=npm6 /app/package*.json /app/
WORKDIR /app
# Install production dependencies, then all dependencies. This should
# link the binaries for typescript in (e.g. tsc) under node_modules/.bin.
RUN npm install -g npm@7.10.0 && \
npm install --production && \
npm install
# Causes error, tsc not found.
CMD ["npx", "-c", "tsc --version"]
此代码不会将令牌从 msg.sender 带到路由器。这意味着通过 uniRouter 在您的合约中交换令牌并将结果令牌发送到 msg.sender。