Initial commit: add .gitignore and README
This commit is contained in:
134
contracts/test/AtomicExecutorEdgeCases.t.sol
Normal file
134
contracts/test/AtomicExecutorEdgeCases.t.sol
Normal file
@@ -0,0 +1,134 @@
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user