В преддверии остальных, более сложных видов тестов, стоит поговорить о некоторых вариантах работы с токенами и nft.
Создадим простой контракт с использованием библиотек от Open Zeppelin: erc20 и erc721.
contract MyERC20 is ERC20 {
address immutable owner;
constructor() ERC20("Token1", "SYM1") {
owner = msg.sender;
_mint(msg.sender, 10_000_000);
}
function mint() external {
require(msg.sender == owner, 'not an owner');
_mint(msg.sender, 10000);
}
}
contract NFT is ERC721, Ownable {
using Strings for uint256;
string public baseURI;
uint256 public currentTokenId;
uint256 public constant TOTAL_SUPPLY = 10_000;
uint256 public constant MINT_PRICE = 0.08 ether;
constructor(
string memory _name,
string memory _symbol,
string memory _baseURI
) ERC721(_name, _symbol) {
baseURI = _baseURI;
}
function mintSimple(address recipient) public payable returns (uint256) {
uint256 newTokenId = ++currentTokenId;
_safeMint(recipient, newTokenId);
return newTokenId;
}
function mintTo(address recipient) public payable returns (uint256) {
if (msg.value != MINT_PRICE) {
revert MintPriceNotPaid();
}
uint256 newTokenId = ++currentTokenId;
if (newTokenId > TOTAL_SUPPLY) {
revert MaxSupply();
}
_safeMint(recipient, newTokenId);
return newTokenId;
}
}И поместим их в файл под названием Helper.sol.
Зачем это будет нужно?
Представьте, что вы разработали свой протокол, который работает с токенами и nft и нужно протестировать некоторые процессы: переводы на баланс контракта, минт долей, выдача прав и т.д. Для этого может потребоваться наличие некоторого количества токенов на счету фиктивных пользователей.
Да, можно через prank() подключать аккаунт админа токена и минтить на нужный адрес необходимое количество токенов, а можно все делать и через простые читкоды.
Для начала, как и для остальных тестов, мы подключаем библиотеки Test, контракта, который будем тестировать, и наш файл Helper.
В функции setUp() разворачиваем необходимые контракты из под нужных нам аккаунтов, например:
function setUp() public {
vm.startPrank(COUNTER_ADMIN);
counter = new Counter();
vm.stopPrank();
vm.startPrank(TOKEN_ADMIN);
token = new MyERC20();
vm.stopPrank();
vm.startPrank(NFT_ADMIN);
nft = new NFT(nftName, nftSymbol, nftLink);
vm.stopPrank();
}Итак, у нас есть развернутые контракты. А NFT, в одном из случаев, можно сминтить за Эфир. Но в только что созданных аккаунтах пользователей нет ни Эфира, ни токенов. Что же делать?
Для пополнения баланса Эфира любого аккаунта, можно использовать следующую команду:
vm.deal(USER, 19 ether);
где вместо USER вы можете указать любой адрес аккаунта.
А для пополнения баланса токенов следует использовать:
deal(address(DAI), USER, 1 ether);
Не забывайте проверять через console.log правильно ли установились балансы!
К слову сказать, на балансе контракта нашего теста, например CounterTest, уже по умолчанию будет лежать достаточно Эфира для проведения операций. Проверить это можно с помощью обычного лога:
console.log(address(this).balance);
Более того, есть специальный читкод, который объединяет deal() и prank()! Т.е. написав:
hoax(USER, 1000);
на счет пользователя зачислится 1000 Эфира и последующий вызов, будет эмулирован из-под аккаунта USER. Это бывает очень удобно, когда в тестах нам нужно, скажем, купить nft и вместо двух команд мы можем написать всего одну!
С помощью этих команд можно управлять балансами пользователей и проводить тесты более просто.
Также старайтесь держать архитектуру папки в правильном виде, сохраняя файлы помощники в папку Utils или mock файлы в одноименную папку.
#foundry #lesson20