Files
strategic/contracts/test/AtomicExecutorEdgeCases.t.sol
2026-02-09 21:51:54 -08:00

135 lines
3.9 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Test, console} from "forge-std/Test.sol";
import {AtomicExecutor} from "../AtomicExecutor.sol";
contract MockTarget {
uint256 public value;
function setValue(uint256 _value) external {
value = _value;
}
function revertTest() external pure {
revert("Test revert");
}
receive() external payable {}
}
contract AtomicExecutorEdgeCasesTest is Test {
AtomicExecutor executor;
MockTarget target;
address owner = address(1);
address user = address(2);
function setUp() public {
vm.prank(owner);
executor = new AtomicExecutor(owner);
target = new MockTarget();
vm.prank(owner);
executor.setAllowedTarget(address(target), true);
}
function testEmptyBatch() public {
address[] memory targets = new address[](0);
bytes[] memory calldatas = new bytes[](0);
vm.prank(user);
executor.executeBatch(targets, calldatas);
// Should succeed (no-op)
}
function testVeryLargeBatch() public {
// Test with 50 calls (near gas limit)
address[] memory targets = new address[](50);
bytes[] memory calldatas = new bytes[](50);
for (uint i = 0; i < 50; i++) {
targets[i] = address(target);
calldatas[i] = abi.encodeWithSignature("setValue(uint256)", i);
}
vm.prank(user);
executor.executeBatch(targets, calldatas);
assertEq(target.value(), 49); // Last value set
}
function testReentrancyAttempt() public {
// Create a contract that tries to reenter
ReentrancyAttacker attacker = new ReentrancyAttacker(executor, target);
vm.prank(owner);
executor.setAllowedTarget(address(attacker), true);
address[] memory targets = new address[](1);
bytes[] memory calldatas = new bytes[](1);
targets[0] = address(attacker);
calldatas[0] = abi.encodeWithSignature("attack()");
vm.prank(user);
// Should revert due to ReentrancyGuard
vm.expectRevert();
executor.executeBatch(targets, calldatas);
}
function testValueHandling() public {
address[] memory targets = new address[](1);
bytes[] memory calldatas = new bytes[](1);
targets[0] = address(target);
calldatas[0] = abi.encodeWithSignature("setValue(uint256)", 100);
vm.deal(address(executor), 1 ether);
vm.prank(user);
executor.executeBatch(targets, calldatas);
// Executor should not send value unless explicitly in call
assertEq(address(executor).balance, 1 ether);
}
function testDelegatecallProtection() public {
// Attempt delegatecall (should not be possible with standard call)
address[] memory targets = new address[](1);
bytes[] memory calldatas = new bytes[](1);
// Standard call, not delegatecall
targets[0] = address(target);
calldatas[0] = abi.encodeWithSignature("setValue(uint256)", 100);
vm.prank(user);
executor.executeBatch(targets, calldatas);
// Should succeed (delegatecall protection is implicit with standard call)
assertEq(target.value(), 100);
}
}
contract ReentrancyAttacker {
AtomicExecutor executor;
MockTarget target;
constructor(AtomicExecutor _executor, MockTarget _target) {
executor = _executor;
target = _target;
}
function attack() external {
// Try to reenter executor
address[] memory targets = new address[](1);
bytes[] memory calldatas = new bytes[](1);
targets[0] = address(target);
calldatas[0] = abi.encodeWithSignature("setValue(uint256)", 999);
executor.executeBatch(targets, calldatas);
}
}