|
@@ -46,7 +46,6 @@ contract ExecutorTest is Test, WormholeTestUtils {
|
|
|
|
|
|
|
|
vaa = generateVaa(
|
|
vaa = generateVaa(
|
|
|
uint32(block.timestamp),
|
|
uint32(block.timestamp),
|
|
|
- // TODO: make these arguments so we can do adversarial tests
|
|
|
|
|
OWNER_CHAIN_ID,
|
|
OWNER_CHAIN_ID,
|
|
|
OWNER_EMITTER,
|
|
OWNER_EMITTER,
|
|
|
sequence,
|
|
sequence,
|
|
@@ -57,7 +56,7 @@ contract ExecutorTest is Test, WormholeTestUtils {
|
|
|
executor.execute(vaa);
|
|
executor.execute(vaa);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function testBasic() public {
|
|
|
|
|
|
|
+ function testCallSucceeds() public {
|
|
|
callable.reset();
|
|
callable.reset();
|
|
|
|
|
|
|
|
uint32 c = callable.fooCount();
|
|
uint32 c = callable.fooCount();
|
|
@@ -69,16 +68,275 @@ contract ExecutorTest is Test, WormholeTestUtils {
|
|
|
assert(address(executor) != address(this));
|
|
assert(address(executor) != address(this));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ function testCallWithArgsSucceeds() public {
|
|
|
|
|
+ callable.reset();
|
|
|
|
|
+
|
|
|
|
|
+ uint32 c = callable.fooCount();
|
|
|
|
|
+ assertEq(callable.lastCaller(), address(bytes20(0)));
|
|
|
|
|
+ testExecute(
|
|
|
|
|
+ address(callable),
|
|
|
|
|
+ abi.encodeCall(ICallable.fooWithArgs, (17)),
|
|
|
|
|
+ 1
|
|
|
|
|
+ );
|
|
|
|
|
+ assertEq(callable.fooCount(), c + 17);
|
|
|
|
|
+ assertEq(callable.lastCaller(), address(executor));
|
|
|
|
|
+ // Sanity check to make sure the check above is meaningful.
|
|
|
|
|
+ assert(address(executor) != address(this));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
function testCallerAddress() public {
|
|
function testCallerAddress() public {
|
|
|
uint32 c = callable.fooCount();
|
|
uint32 c = callable.fooCount();
|
|
|
testExecute(address(callable), abi.encodeCall(ICallable.foo, ()), 1);
|
|
testExecute(address(callable), abi.encodeCall(ICallable.foo, ()), 1);
|
|
|
assertEq(callable.fooCount(), c + 1);
|
|
assertEq(callable.fooCount(), c + 1);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ function testIncorrectVaa() public {
|
|
|
|
|
+ string[5] memory forgeItems = [
|
|
|
|
|
+ "vaaSignature",
|
|
|
|
|
+ "vaaVersion",
|
|
|
|
|
+ "vaaGuardianSetIndex",
|
|
|
|
|
+ "vaaNumSigners+",
|
|
|
|
|
+ "vaaNumSigners-"
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ for (uint i = 0; i < forgeItems.length; i++) {
|
|
|
|
|
+ bytes memory payload = abi.encodePacked(
|
|
|
|
|
+ uint32(0x5054474d),
|
|
|
|
|
+ PythGovernanceInstructions.GovernanceModule.EvmExecutor,
|
|
|
|
|
+ Executor.ExecutorAction.Execute,
|
|
|
|
|
+ CHAIN_ID,
|
|
|
|
|
+ address(executor),
|
|
|
|
|
+ address(callable),
|
|
|
|
|
+ abi.encodeCall(ICallable.foo, ())
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ bytes memory vaa = forgeVaa(
|
|
|
|
|
+ uint32(block.timestamp),
|
|
|
|
|
+ OWNER_CHAIN_ID,
|
|
|
|
|
+ OWNER_EMITTER,
|
|
|
|
|
+ 1,
|
|
|
|
|
+ payload,
|
|
|
|
|
+ NUM_SIGNERS,
|
|
|
|
|
+ bytes(forgeItems[i])
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ // ExecutorErrors.InvalidWormholeVaa.selector
|
|
|
|
|
+ vm.expectRevert();
|
|
|
|
|
+ executor.execute(vaa);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function testIncorrectOwnerEmitterAddress() public {
|
|
|
|
|
+ bytes memory payload = abi.encodePacked(
|
|
|
|
|
+ uint32(0x5054474d),
|
|
|
|
|
+ PythGovernanceInstructions.GovernanceModule.EvmExecutor,
|
|
|
|
|
+ Executor.ExecutorAction.Execute,
|
|
|
|
|
+ CHAIN_ID,
|
|
|
|
|
+ address(executor),
|
|
|
|
|
+ address(callable),
|
|
|
|
|
+ abi.encodeCall(ICallable.foo, ())
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ bytes memory vaa = generateVaa(
|
|
|
|
|
+ uint32(block.timestamp),
|
|
|
|
|
+ OWNER_CHAIN_ID,
|
|
|
|
|
+ bytes32(uint256(2)),
|
|
|
|
|
+ 1,
|
|
|
|
|
+ payload,
|
|
|
|
|
+ NUM_SIGNERS
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ vm.expectRevert(ExecutorErrors.UnauthorizedEmitter.selector);
|
|
|
|
|
+ executor.execute(vaa);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function testIncorrectOwnerEmitterChainId() public {
|
|
|
|
|
+ bytes memory payload = abi.encodePacked(
|
|
|
|
|
+ uint32(0x5054474d),
|
|
|
|
|
+ PythGovernanceInstructions.GovernanceModule.EvmExecutor,
|
|
|
|
|
+ Executor.ExecutorAction.Execute,
|
|
|
|
|
+ CHAIN_ID,
|
|
|
|
|
+ address(executor),
|
|
|
|
|
+ address(callable),
|
|
|
|
|
+ abi.encodeCall(ICallable.foo, ())
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ bytes memory vaa = generateVaa(
|
|
|
|
|
+ uint32(block.timestamp),
|
|
|
|
|
+ 8,
|
|
|
|
|
+ OWNER_EMITTER,
|
|
|
|
|
+ 1,
|
|
|
|
|
+ payload,
|
|
|
|
|
+ NUM_SIGNERS
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ vm.expectRevert(ExecutorErrors.UnauthorizedEmitter.selector);
|
|
|
|
|
+ executor.execute(vaa);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function testOutOfOrder() public {
|
|
|
|
|
+ testExecute(address(callable), abi.encodeCall(ICallable.foo, ()), 3);
|
|
|
|
|
+
|
|
|
|
|
+ bytes memory payload = abi.encodePacked(
|
|
|
|
|
+ uint32(0x5054474d),
|
|
|
|
|
+ PythGovernanceInstructions.GovernanceModule.EvmExecutor,
|
|
|
|
|
+ Executor.ExecutorAction.Execute,
|
|
|
|
|
+ CHAIN_ID,
|
|
|
|
|
+ address(executor),
|
|
|
|
|
+ address(callable),
|
|
|
|
|
+ abi.encodeCall(ICallable.foo, ())
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ bytes memory vaa = generateVaa(
|
|
|
|
|
+ uint32(block.timestamp),
|
|
|
|
|
+ OWNER_CHAIN_ID,
|
|
|
|
|
+ OWNER_EMITTER,
|
|
|
|
|
+ 3,
|
|
|
|
|
+ payload,
|
|
|
|
|
+ NUM_SIGNERS
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ vm.expectRevert(ExecutorErrors.MessageOutOfOrder.selector);
|
|
|
|
|
+ executor.execute(vaa);
|
|
|
|
|
+
|
|
|
|
|
+ callable.reset();
|
|
|
|
|
+ testExecute(address(callable), abi.encodeCall(ICallable.foo, ()), 4);
|
|
|
|
|
+ assertEq(callable.fooCount(), 1);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function testInvalidPayload() public {
|
|
|
|
|
+ bytes memory payload = abi.encodePacked(
|
|
|
|
|
+ uint32(0x5054474d),
|
|
|
|
|
+ PythGovernanceInstructions.GovernanceModule.EvmExecutor,
|
|
|
|
|
+ Executor.ExecutorAction.Execute,
|
|
|
|
|
+ CHAIN_ID,
|
|
|
|
|
+ address(executor),
|
|
|
|
|
+ address(callable),
|
|
|
|
|
+ abi.encodeCall(ICallable.foo, ())
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ bytes memory shortPayload = BytesLib.slice(
|
|
|
|
|
+ payload,
|
|
|
|
|
+ 0,
|
|
|
|
|
+ payload.length - 1
|
|
|
|
|
+ );
|
|
|
|
|
+ bytes memory shortVaa = generateVaa(
|
|
|
|
|
+ uint32(block.timestamp),
|
|
|
|
|
+ OWNER_CHAIN_ID,
|
|
|
|
|
+ OWNER_EMITTER,
|
|
|
|
|
+ 1,
|
|
|
|
|
+ shortPayload,
|
|
|
|
|
+ NUM_SIGNERS
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ vm.expectRevert();
|
|
|
|
|
+ executor.execute(shortVaa);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function testIncorrectTargetChainId() public {
|
|
|
|
|
+ bytes memory payload = abi.encodePacked(
|
|
|
|
|
+ uint32(0x5054474d),
|
|
|
|
|
+ PythGovernanceInstructions.GovernanceModule.EvmExecutor,
|
|
|
|
|
+ Executor.ExecutorAction.Execute,
|
|
|
|
|
+ uint16(3),
|
|
|
|
|
+ address(executor),
|
|
|
|
|
+ address(callable),
|
|
|
|
|
+ abi.encodeCall(ICallable.foo, ())
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ bytes memory vaa = generateVaa(
|
|
|
|
|
+ uint32(block.timestamp),
|
|
|
|
|
+ OWNER_CHAIN_ID,
|
|
|
|
|
+ OWNER_EMITTER,
|
|
|
|
|
+ 1,
|
|
|
|
|
+ payload,
|
|
|
|
|
+ NUM_SIGNERS
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ vm.expectRevert(ExecutorErrors.InvalidGovernanceTarget.selector);
|
|
|
|
|
+ executor.execute(vaa);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function testIncorrectTargetAddress() public {
|
|
|
|
|
+ bytes memory payload = abi.encodePacked(
|
|
|
|
|
+ uint32(0x5054474d),
|
|
|
|
|
+ PythGovernanceInstructions.GovernanceModule.EvmExecutor,
|
|
|
|
|
+ Executor.ExecutorAction.Execute,
|
|
|
|
|
+ CHAIN_ID,
|
|
|
|
|
+ address(0x1),
|
|
|
|
|
+ address(callable),
|
|
|
|
|
+ abi.encodeCall(ICallable.foo, ())
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ bytes memory vaa = generateVaa(
|
|
|
|
|
+ uint32(block.timestamp),
|
|
|
|
|
+ OWNER_CHAIN_ID,
|
|
|
|
|
+ OWNER_EMITTER,
|
|
|
|
|
+ 1,
|
|
|
|
|
+ payload,
|
|
|
|
|
+ NUM_SIGNERS
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ vm.expectRevert(ExecutorErrors.DeserializationError.selector);
|
|
|
|
|
+ executor.execute(vaa);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function testIncorrectAction() public {
|
|
|
|
|
+ bytes memory payload = abi.encodePacked(
|
|
|
|
|
+ uint32(0x5054474d),
|
|
|
|
|
+ PythGovernanceInstructions.GovernanceModule.EvmExecutor,
|
|
|
|
|
+ uint8(17),
|
|
|
|
|
+ CHAIN_ID,
|
|
|
|
|
+ address(executor),
|
|
|
|
|
+ address(callable),
|
|
|
|
|
+ abi.encodeCall(ICallable.foo, ())
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ bytes memory vaa = generateVaa(
|
|
|
|
|
+ uint32(block.timestamp),
|
|
|
|
|
+ OWNER_CHAIN_ID,
|
|
|
|
|
+ OWNER_EMITTER,
|
|
|
|
|
+ 1,
|
|
|
|
|
+ payload,
|
|
|
|
|
+ NUM_SIGNERS
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ vm.expectRevert();
|
|
|
|
|
+ executor.execute(vaa);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function testCallReverts() public {
|
|
|
|
|
+ bytes memory payload = abi.encodePacked(
|
|
|
|
|
+ uint32(0x5054474d),
|
|
|
|
|
+ PythGovernanceInstructions.GovernanceModule.EvmExecutor,
|
|
|
|
|
+ Executor.ExecutorAction.Execute,
|
|
|
|
|
+ CHAIN_ID,
|
|
|
|
|
+ address(executor),
|
|
|
|
|
+ address(callable),
|
|
|
|
|
+ abi.encodeCall(ICallable.reverts, ())
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ bytes memory vaa = generateVaa(
|
|
|
|
|
+ uint32(block.timestamp),
|
|
|
|
|
+ OWNER_CHAIN_ID,
|
|
|
|
|
+ OWNER_EMITTER,
|
|
|
|
|
+ 1,
|
|
|
|
|
+ payload,
|
|
|
|
|
+ NUM_SIGNERS
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ vm.expectRevert("call should revert");
|
|
|
|
|
+ executor.execute(vaa);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
interface ICallable {
|
|
interface ICallable {
|
|
|
function foo() external;
|
|
function foo() external;
|
|
|
|
|
|
|
|
|
|
+ function fooWithArgs(uint32 inc) external;
|
|
|
|
|
+
|
|
|
|
|
+ function reverts() external;
|
|
|
|
|
+
|
|
|
function reset() external;
|
|
function reset() external;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -97,4 +355,13 @@ contract TestCallable is ICallable {
|
|
|
fooCount += 1;
|
|
fooCount += 1;
|
|
|
lastCaller = msg.sender;
|
|
lastCaller = msg.sender;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ function fooWithArgs(uint32 inc) external override {
|
|
|
|
|
+ fooCount += inc;
|
|
|
|
|
+ lastCaller = msg.sender;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function reverts() external override {
|
|
|
|
|
+ revert("call should revert");
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|