181 lines
6.7 KiB
Solidity
181 lines
6.7 KiB
Solidity
// 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();
|
|
}
|
|
}
|