В протоколе PoolTogather заметил простой и удобный способ переключения prank вызовов внутри одной функции.
К примеру, у нас есть такая функция:
solidity
function someTestCall() public {
// действия от пользователя_1
// переключение на пользователя_2
// выполнение некоторых действий
// обратное переключение на пользователя_1
// продолжение действий
}
Да, можно все это сделать с обычными prank, stop/startPrank, hoax, но в итоге может получиться ситуация, когда в тесте будет слишком много этих не нужных читкодов.
Вот как сделала команда PoolTogather.
Они создали модификатор:
solidity
modifier prankception(address prankee) {
address prankBefore = currentPrankee;
vm.stopPrank();
vm.startPrank(prankee);
_;
vm.stopPrank();
if (prankBefore != address(0)) {
vm.startPrank(prankBefore);
}
}
а затем поместили его в нужные служебные функции, например, в такую:
solidity
function _accrueYield() internal virtual override prankception(_aTokenWhale) {
IERC20(_aToken).transfer(_yieldVault, 10 ** assetDecimals);
vm.warp(block.timestamp + 1 days);
}
и теперь ее можно вызывать внутри других функций, с изменение роли вызывающего:
solidity
function accrueYield() public returns (uint256) {
uint256 assetsBefore = prizeVault.totalAssets();
@> _accrueYield();
uint256 assetsAfter = prizeVault.totalAssets();
if (yieldVault.balanceOf(address(prizeVault)) > 0) {
require(assetsAfter > assetsBefore, "yield did not accrue");
} else {
if (underlyingAsset.balanceOf(address(prizeVault)) > 0) {
...
} else {
...
}
}
return assetsAfter - assetsBefore;
}
Т.е. тут идет сначала вызов от одного пользователя, затем в функции _accrueYield() он меняется на другого, выполняются какие-либо действия и роль возвращается к изначальному пользователю.
На мой взгляд достаточно чистый и красивый код теста.
#foundry #prank