TGViewer
Из Solidity в AI и дальше Из Solidity в AI и дальше @solidityset · 2.49K subscribers
Post #958 1.06K
Foundry с 0. Часть 37

Когда я разбирался с документацией Foundry, то видел там раздел по написанию тестов для подписей стандарта EIP712.

Долгое время все никак не получалось подступиться к ним, и вот пришло время разобраться в этой теме.

Вот сама ссылка на документацию:

https://book.getfoundry.sh/tutorials/testing-eip712

А сейчас мы быстро пробежимся по коду.

Итак, для написания тестов в данном случае мы будем работать с токеном ERC20 от компании Solmate, так как там уже по умолчанию идет функция permit().

https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol

Нам также потребуются еще два контракта: это MockToken, который будет наследовать от ERC20 и SigUtils, который поможет правильно работать с подписями.

Наш токен предельно простой:

contract MyToken is ERC20 {
address public owner;
constructor(address newOwner) ERC20("token", "MTK", 18) {}

function mint(address user, uint256 amount) public {
_mint(user, amount);
}
}


SigUtils чуть более длинный:

contract SigUtils {
bytes32 internal DOMAIN_SEPARATOR;

constructor(bytes32 _DOMAIN_SEPARATOR) {
DOMAIN_SEPARATOR = _DOMAIN_SEPARATOR;
}

// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;

struct Permit {
address owner;
address spender;
uint256 value;
uint256 nonce;
uint256 deadline;
}

function getStructHash(Permit memory _permit)
internal
pure
returns (bytes32)
{
return
keccak256(
abi.encode(
PERMIT_TYPEHASH,
_permit.owner,
_permit.spender,
_permit.value,
_permit.nonce,
_permit.deadline
)
);
}

function getTypedDataHash(Permit memory _permit)
public
view
returns (bytes32)
{
return
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR,
getStructHash(_permit)
)
);
}
}


Все просто: мы создали структуру подписи подобную ERC20 permit() и две функции для хеширования структуры подписи и цельных данных.

И теперь мы готовы писать тесты для нашего токена.

Для начала нам потребуется в настройках развернуть контракты MyToken и SigUtils, создать приватные ключи и на их основе сгенерировать адреса пользователей, так как сами подписи нужно создавать с использованием приватного ключа.

function setUp() public {
token = new MyToken(address(this));
sigUtils = new SigUtils(token.DOMAIN_SEPARATOR());

ownerPrivateKey = 0xA11CE;
spenderPrivateKey = 0xB0B;

owner = vm.addr(ownerPrivateKey);
spender = vm.addr(spenderPrivateKey);

token.mint(owner, 1e18);
}


После этого можно написать первый тест для функции permit():

function test_Permit() public {
SigUtils.Permit memory permit = SigUtils.Permit({
owner: owner,
spender: spender,
value: 1e18,
nonce: 0,
deadline: 1 days
});

bytes32 digest = sigUtils.getTypedDataHash(permit);

(uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerPrivateKey, digest);

token.permit(
permit.owner,
permit.spender,
permit.value,
permit.deadline,
v,
r,
s
);

assertEq(token.allowance(owner, spender), 1e18);
assertEq(token.nonces(owner), 1);
}


Тут мы создаем структуры с помощью контракта SigUtils, хешируем и подписываем с помощью приватного ключа, затем уже вызываем функцию permit() и делаем проверки на nonce и allowance.

В файле примере, который вы найдете в конце поста, можно посмотреть тесты на: срок действия подписи, невалидного signer и nonce, а также на signature replay.
  • 👍 3
  • ❤ 2
More from @solidityset
  1. Sep 22, 2026Какой язык программирования учить сейчас? На днях в Твиттере увидел небольшой пост о разви…
  2. Sep 18, 2026Интересная модель Jev Буквально пару дней назад в Твиттере многие начали обсуждение новой…
  3. Sep 14, 2026Графы повсюду Если вы также следите за новостями в мире ИИ, то наверняка уже все чаще встр…
  4. Sep 10, 2026GTA6, Cyberleek, блокчейн и безопасность Увидел несколько постов (тут и тут) про Cyberleek…
  5. Sep 9, 2026Работа с чистой энергией Дисклеймер Сегодня ава и название канала, наконец, поменялись. Я…
  6. Sep 9, 2026Channel name was changed to «Из Solidity в AI и дальше»
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →