Files
smom-dbis-138/test/treasury/StrategyExecutor138.t.sol

181 lines
6.7 KiB
Solidity
Raw Normal View History

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Test, console} from "forge-std/Test.sol";
import {TreasuryVault} from "../../contracts/treasury/TreasuryVault.sol";
import {CcipBridgeAdapter138} from "../../contracts/treasury/CcipBridgeAdapter138.sol";
import {StrategyExecutor138} from "../../contracts/treasury/StrategyExecutor138.sol";
contract MockWETH {
mapping(address => uint256) public balanceOf;
function mint(address to, uint256 amount) external {
balanceOf[to] += amount;
}
function transfer(address to, uint256 amount) external returns (bool) {
balanceOf[msg.sender] -= amount;
balanceOf[to] += amount;
return true;
}
function transferFrom(address from, address to, uint256 amount) external returns (bool) {
balanceOf[from] -= amount;
balanceOf[to] += amount;
return true;
}
function approve(address, uint256) external pure returns (bool) { return true; }
}
contract MockBridge {
function sendCrossChain(uint64, address, uint256) external payable returns (bytes32) {
return keccak256("ok");
}
}
contract StrategyExecutor138Test is Test {
TreasuryVault public vault;
MockBridge public bridge;
CcipBridgeAdapter138 public adapter;
StrategyExecutor138 public executor;
MockWETH public weth9;
address public admin;
address public keeper;
address public receiverMainnet = address(0x99);
function setUp() public {
admin = address(1);
keeper = address(2);
weth9 = new MockWETH();
vault = new TreasuryVault(admin);
bridge = new MockBridge();
adapter = new CcipBridgeAdapter138(
address(weth9),
address(bridge),
receiverMainnet,
admin
);
executor = new StrategyExecutor138(address(vault), address(adapter), admin);
vm.startPrank(admin);
adapter.setStrategyExecutor(address(executor));
vault.setModule(address(executor), true);
vault.setModule(address(adapter), true);
vault.setToken(address(weth9), true);
executor.setToken(address(weth9), true);
executor.grantRole(executor.KEEPER_ROLE(), keeper);
adapter.setExportsEnabled(true);
vm.stopPrank();
weth9.mint(address(vault), 100e18);
}
function test_exportToMainnet_revert_tokenNotApproved() public {
MockWETH other = new MockWETH();
other.mint(address(vault), 50e18);
vm.prank(admin);
vault.setToken(address(other), true);
vm.prank(keeper);
vm.expectRevert(StrategyExecutor138.TokenNotApproved.selector);
executor.exportToMainnet(address(other), 50e18, block.timestamp + 3600);
}
function test_exportToMainnet_revert_cooldown() public {
vm.prank(admin);
executor.setCooldownBlocks(1);
vm.prank(keeper);
executor.exportToMainnet(address(weth9), 10e18, block.timestamp + 3600);
vm.prank(keeper);
vm.expectRevert(StrategyExecutor138.CooldownNotElapsed.selector);
executor.exportToMainnet(address(weth9), 10e18, block.timestamp + 3600);
}
function test_setExportPolicy_success() public {
StrategyExecutor138.ExportPolicy memory policy = StrategyExecutor138.ExportPolicy({
mode: StrategyExecutor138.ExportMode.Threshold,
minExportUsd: 10_000e6,
maxPerTxUsd: 50_000e6,
maxDailyUsd: 100_000e6,
rateLimitPerHour: 5,
cooldownBlocks: 10,
exportAsset: address(weth9),
destinationSelector: 5009297550715157269,
destinationReceiver: receiverMainnet
});
vm.prank(admin);
executor.setExportPolicy(policy);
(StrategyExecutor138.ExportMode mode, uint256 minExportUsd,,,, uint256 cooldownBlocks,,,) = executor.exportPolicy();
assertEq(uint8(mode), uint8(StrategyExecutor138.ExportMode.Threshold));
assertEq(minExportUsd, 10_000e6);
assertEq(cooldownBlocks, 10);
assertEq(executor.cooldownBlocks(), 10);
}
function test_recordExportIntent_success() public {
vm.prank(admin);
adapter.setExportsEnabled(false);
vm.prank(keeper);
executor.recordExportIntent(address(weth9), 5e18);
assertEq(executor.pendingIntentToken(), address(weth9));
assertEq(executor.pendingIntentAmount(), 5e18);
}
function test_recordExportIntent_revert_exportsEnabled() public {
vm.prank(admin);
adapter.setExportsEnabled(true);
vm.prank(keeper);
vm.expectRevert(StrategyExecutor138.ExportsNotEnabled.selector);
executor.recordExportIntent(address(weth9), 5e18);
}
function test_recordExportIntent_revert_tokenNotApproved() public {
MockWETH other = new MockWETH();
vm.prank(admin);
adapter.setExportsEnabled(false);
vm.prank(keeper);
vm.expectRevert(StrategyExecutor138.TokenNotApproved.selector);
executor.recordExportIntent(address(other), 1e18);
}
function test_processPendingIntent_revert_noIntent() public {
vm.prank(keeper);
vm.expectRevert(StrategyExecutor138.NoPendingIntent.selector);
executor.processPendingIntent{value: 0}(block.timestamp + 3600);
}
function test_processPendingIntent_revert_exportsDisabled() public {
vm.prank(admin);
adapter.setExportsEnabled(false);
vm.prank(keeper);
executor.recordExportIntent(address(weth9), 5e18);
vm.prank(admin);
adapter.setExportsEnabled(false);
vm.prank(keeper);
vm.expectRevert(StrategyExecutor138.ExportsNotEnabled.selector);
executor.processPendingIntent{value: 0}(block.timestamp + 3600);
}
function test_processPendingIntent_success() public {
vm.prank(admin);
adapter.setExportsEnabled(false);
vm.prank(keeper);
executor.recordExportIntent(address(weth9), 5e18);
vm.prank(admin);
adapter.setExportsEnabled(true);
uint256 vaultBefore = weth9.balanceOf(address(vault));
vm.prank(keeper);
executor.processPendingIntent{value: 0}(block.timestamp + 3600);
assertEq(executor.pendingIntentToken(), address(0));
assertEq(executor.pendingIntentAmount(), 0);
assertEq(weth9.balanceOf(address(vault)), vaultBefore - 5e18);
}
function test_harvestFees_revert_notImplemented() public {
vm.prank(keeper);
vm.expectRevert(StrategyExecutor138.NotImplemented.selector);
executor.harvestFees();
}
function test_rebalanceLp_revert_notImplemented() public {
vm.prank(keeper);
vm.expectRevert(StrategyExecutor138.NotImplemented.selector);
executor.rebalanceLp();
}
}