diff --git a/target_chains/ethereum/contracts/contracts/executor/Executor.sol b/target_chains/ethereum/contracts/contracts/executor/Executor.sol index 934ff547..2d586630 100644 --- a/target_chains/ethereum/contracts/contracts/executor/Executor.sol +++ b/target_chains/ethereum/contracts/contracts/executor/Executor.sol @@ -65,7 +65,7 @@ contract Executor { // whose payload is a serialized GovernanceInstruction. function execute( bytes memory encodedVm - ) public returns (bytes memory response) { + ) public payable returns (bytes memory response) { IWormhole.VM memory vm = verifyGovernanceVM(encodedVm); GovernanceInstruction memory gi = parseGovernanceInstruction( @@ -179,4 +179,16 @@ contract Executor { encodedInstruction.length - index ); } + + function getOwnerChainId() public view returns (uint64) { + return ownerEmitterChainId; + } + + function getOwnerEmitterAddress() public view returns (bytes32) { + return ownerEmitterAddress; + } + + function getLastExecutedSequence() public view returns (uint64) { + return lastExecutedSequence; + } } diff --git a/target_chains/ethereum/contracts/contracts/executor/ExecutorUpgradable.sol b/target_chains/ethereum/contracts/contracts/executor/ExecutorUpgradable.sol index 36b0b0dd..c60174c4 100644 --- a/target_chains/ethereum/contracts/contracts/executor/ExecutorUpgradable.sol +++ b/target_chains/ethereum/contracts/contracts/executor/ExecutorUpgradable.sol @@ -94,6 +94,6 @@ contract ExecutorUpgradable is } function version() public pure returns (string memory) { - return "0.1.0"; + return "0.1.1"; } } diff --git a/target_chains/ethereum/contracts/forge-test/Executor.t.sol b/target_chains/ethereum/contracts/forge-test/Executor.t.sol index 2b986f8a..128fdac3 100644 --- a/target_chains/ethereum/contracts/forge-test/Executor.t.sol +++ b/target_chains/ethereum/contracts/forge-test/Executor.t.sol @@ -95,6 +95,16 @@ contract ExecutorTest is Test, WormholeTestUtils { ); } + function testExecutorOwnerChainId() public { + uint chainId = executor.getOwnerChainId(); + assertEq(chainId, OWNER_CHAIN_ID); + } + + function testExecutorOwnerEmitterAddress() public { + bytes32 ownerEmitterAddress = executor.getOwnerEmitterAddress(); + assertEq(ownerEmitterAddress, OWNER_EMITTER); + } + function testExecutorOwner() public { assertEq(address(executor), executor.owner()); } @@ -123,6 +133,58 @@ contract ExecutorTest is Test, WormholeTestUtils { executor.execute(vaa); } + function testLastExecutedSequenceUpdateOnSucceed() public { + callable.reset(); + + uint32 c = callable.fooCount(); + uint oldSequence = executor.getLastExecutedSequence(); + uint64 sequence = 1; + assertEq(callable.lastCaller(), address(bytes20(0))); + testExecute( + address(callable), + abi.encodeWithSelector(ICallable.foo.selector), + sequence, + 0 + ); + uint newSequence = executor.getLastExecutedSequence(); + + assertGt(newSequence, oldSequence); + assertEq(newSequence, sequence); + assertEq(callable.fooCount(), c + 1); + assertEq(callable.lastCaller(), address(executor)); + // Sanity check to make sure the check above is meaningful. + assert(address(executor) != address(this)); + } + + function testLastExecutedSequenceNoChangeOnFail() public { + uint oldSequence = executor.getLastExecutedSequence(); + + bytes memory payload = abi.encodePacked( + uint32(0x5054474d), + PythGovernanceInstructions.GovernanceModule.EvmExecutor, + Executor.ExecutorAction.Execute, + CHAIN_ID, + address(executor), + address(callable), + uint(0), + abi.encodeWithSelector(ICallable.reverts.selector) + ); + + bytes memory vaa = generateVaa( + uint32(block.timestamp), + OWNER_CHAIN_ID, + OWNER_EMITTER, + 1, + payload, + NUM_SIGNERS + ); + + vm.expectRevert("call should revert"); + executor.execute(vaa); + uint newSequence = executor.getLastExecutedSequence(); + assertEq(newSequence, oldSequence); + } + function testCallSucceeds() public { callable.reset();