![](/img/trans.png)
[英]Deploying Uniswap v2 / Sushiswap or similar in Brownie, Hardhat or Truffle test suite
[英]How do I interact with Uniswap V2 in a Truffle test suite?
我正在寻找一种使用 Truffle 创建自动化测试套件的方法,该套件可以测试我的智能合约与 Uniswap V2 的交互。 Uniswap 文档简要提到了使用 Truffle 进行测试,但没有提供任何示例。 我希望使用带有 ganache 的 mai.net 分支来测试它。
我猜这是一个与这个问题的公认答案类似的过程,但我正在专门寻找一种使用 Truffle 和 web3.js 来完成它的方法。
例如,如果我正在测试以下合约:
pragma solidity ^0.6.6;
interface IUniswap {
function swapExactETHForTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline)
external
payable
returns (uint[] memory amounts);
function WETH() external pure returns (address);
}
contract MyContract {
IUniswap uniswap;
constructor(address _uniswap) public {
uniswap = IUniswap(_uniswap);
}
function swapExactETHForTokens(uint amountOutMin, address token) external payable {
address[] memory path = new address[](2);
path[0] = uniswap.WETH();
path[1] = token;
uniswap.swapExactETHForTokens{value: msg.value}(
amountOutMin,
path,
msg.sender,
now
);
}
}
我将如何创建一个单元测试来验证swapExactETHForTokens()
将 ETH 换成DAI ? 对于_uniswap
的值,我一直在使用UniswapV2Router02 。
任何帮助将不胜感激。
无论如何,我最终还是使用了 Hardhat/Ethers.js,只是因为设置 mai.net 分支和运行自动化测试套件是多么容易。 我在这里提供了一个答案,解释了设置 mai.net 分支所需的步骤,并在这个问题中重复使用了示例合同(完成测试)。
不过,为了具体回答这个问题, Hardhat 有一个支持使用 Truffle/Web3js 进行测试的插件,因此您仍然可以使用 Truffle/Web3js 来编写测试/合同,但已经使用 Hardhat 的 mai.net fork 功能与其他合同进行交互部署在 mai.net 上。
如果您使用 Uniswap 平台交换代币,您将有 2 个步骤。 您将批准令牌,在此步骤中将弹出元掩码,您将对其进行确认。 然后 Uniswap 将进行实际的交换,它将代币从你的钱包中取出并为你进行交换。
这是swapExactETHForTokens
function
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
virtual
override
payable
ensure(deadline)
returns (uint[] memory amounts)
{
require(path[0] == WETH, 'UniswapV2Router: INVALID_PATH');
amounts = UniswapV2Library.getAmountsOut(factory, msg.value, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT');
IWETH(WETH).deposit{value: amounts[0]}();
assert(IWETH(WETH).transfer(UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0]));
_swap(amounts, path, to);
}
最后 function _swap
调用swap
function:
同样重要的是要确保您的合约控制足够的 ETH/代币来进行交换,并已批准路由器撤回这么多代币。
想象一下,您想从智能合约中用 50 DAI 交换尽可能多的 ETH。
从转移
在交换之前,我们的智能合约需要控制 50 DAI。 完成此操作的最简单方法是在 DAI 上调用 transferFrom 并将所有者设置为 msg.sender:
uint amountIn = 50 * 10 ** DAI.decimals();
require(DAI.transferFrom(msg.sender, address(this), amountIn), 'transferFrom failed.');
最终 Uniswap 将transferFrom
,但在您的代币必须批准交易之前,它必须将uniswap address
添加到其allowance
映射中。
mapping(address=>mapping(address=>uint)) public allowance;
// token address is allowign uniswap address for this much token
除非您设置了交换令牌并且您的交换令牌必须调用approve
,否则您无法测试合同的当前实施。
如果你有前端应用程序,当你调用合约的 swap function 时,metamask 会弹出,你会确认它。 但是在测试环境中,您需要实际的 ERC20 合约,部署它并调用approve
。 在前端,您将有两个函数swapToken
和approve
。 你会按这个顺序给他们打电话吗?
const startSwap = async () => {
await approve()
await swapToken()
}
在测试套件中:
const MyContract = artifacts.require("MyContract");
const Dai = artifacts.require("Dai");
// ganache provides an array of accounts
contract("Uniswap", (ganachProvidedAccounts) => {
let myContract,dai;
// intialize the contracts before each test
before(async () => {
myContract = await myContract.new();
dai = await Dai.new();
})
describe("Swapping", async () => {
it("swap tokens", async () => {
let result;
// first ask for approval of 100 token transfer
await dai.approve(myContract.address, tokens("100"), {
from:ganachProvidedAccounts[0] ,
});
// // check staking for customer
await myContract.swapExactETHForTokens("100"), { from: ganachProvidedAccounts[0] });
// make your assetion
})})
您能否尝试在 truffle-config.json 文件中配置一个 mai.net 端口并运行类似
INFURA_API_KEY=A45..
MY_ACCOUNT=0x...
ganache-cli --fork https://ropsten.infura.io/v3/$INFURA_API_KEY \ --unlock $MY_ACCOUNT \ --networkId 999
在松露配置文件中将端口 999 设置为 ropsten_fork,然后在单独的控制台运行
truffle console --network ropsten_fork
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.