|
|
@@ -0,0 +1,1238 @@
|
|
|
+// test/Messages.sol
|
|
|
+// SPDX-License-Identifier: Apache 2
|
|
|
+
|
|
|
+pragma solidity ^0.8.0;
|
|
|
+
|
|
|
+import "../contracts/Implementation.sol";
|
|
|
+import "../contracts/Setup.sol";
|
|
|
+import "../contracts/Wormhole.sol";
|
|
|
+import "forge-std/Test.sol";
|
|
|
+import "forge-test/rv-helpers/TestUtils.sol";
|
|
|
+import "forge-test/rv-helpers/MyImplementation.sol";
|
|
|
+import "forge-test/rv-helpers/IMyWormhole.sol";
|
|
|
+
|
|
|
+contract TestGovernance is TestUtils {
|
|
|
+
|
|
|
+ uint16 constant CHAINID = 2;
|
|
|
+ uint256 constant EVMCHAINID = 1;
|
|
|
+ bytes32 constant MODULE = 0x00000000000000000000000000000000000000000000000000000000436f7265;
|
|
|
+ bytes32 constant governanceContract = 0x0000000000000000000000000000000000000000000000000000000000000004;
|
|
|
+
|
|
|
+ bytes32 constant CHAINID_SLOT = bytes32(uint256(0));
|
|
|
+ bytes32 constant GUARDIANSETS_SLOT = bytes32(uint256(2));
|
|
|
+ bytes32 constant GUARDIANSETINDEX_SLOT = bytes32(uint256(3));
|
|
|
+ bytes32 constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
|
|
|
+ bytes32 constant CONSUMED_ACTIONS_SLOT = bytes32(uint256(5));
|
|
|
+ bytes32 constant INIT_IMPLEMENTATION_SLOT = bytes32(uint256(6));
|
|
|
+ bytes32 constant MESSAGEFEE_SLOT = bytes32(uint256(7));
|
|
|
+ bytes32 constant EVMCHAINID_SLOT = bytes32(uint256(8));
|
|
|
+
|
|
|
+ Wormhole proxy;
|
|
|
+ Implementation impl;
|
|
|
+ Setup setup;
|
|
|
+ Setup proxiedSetup;
|
|
|
+ IMyWormhole proxied;
|
|
|
+
|
|
|
+ uint256 constant testGuardian = 93941733246223705020089879371323733820373732307041878556247502674739205313440;
|
|
|
+
|
|
|
+ event ContractUpgraded(address indexed oldContract, address indexed newContract);
|
|
|
+
|
|
|
+ function setUp() public {
|
|
|
+ // Deploy setup
|
|
|
+ setup = new Setup();
|
|
|
+ // Deploy implementation contract
|
|
|
+ impl = new Implementation();
|
|
|
+ // Deploy proxy
|
|
|
+ proxy = new Wormhole(address(setup), bytes(""));
|
|
|
+
|
|
|
+ address[] memory keys = new address[](1);
|
|
|
+ keys[0] = 0xbeFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe; // vm.addr(testGuardian)
|
|
|
+
|
|
|
+ //proxied setup
|
|
|
+ proxiedSetup = Setup(address(proxy));
|
|
|
+
|
|
|
+ vm.chainId(1);
|
|
|
+ proxiedSetup.setup({
|
|
|
+ implementation: address(impl),
|
|
|
+ initialGuardians: keys,
|
|
|
+ chainId: CHAINID,
|
|
|
+ governanceChainId: 1,
|
|
|
+ governanceContract: governanceContract,
|
|
|
+ evmChainId: EVMCHAINID
|
|
|
+ });
|
|
|
+
|
|
|
+ proxied = IMyWormhole(address(proxy));
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitContractUpgrade(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ MyImplementation newImpl = new MyImplementation(EVMCHAINID, CHAINID);
|
|
|
+
|
|
|
+ vm.assume(storageSlot != IMPLEMENTATION_SLOT);
|
|
|
+ vm.assume(storageSlot != hashedLocation(address(newImpl), INIT_IMPLEMENTATION_SLOT));
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitContract(MODULE, CHAINID, address(newImpl));
|
|
|
+ (bytes memory _vm, bytes32 hash) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.assume(storageSlot != hashedLocation(hash, CONSUMED_ACTIONS_SLOT));
|
|
|
+
|
|
|
+ proxied.submitContractUpgrade(_vm);
|
|
|
+
|
|
|
+ assertEq(address(newImpl), address(proxied.getImplementation()));
|
|
|
+ assertEq(true, proxied.isInitialized(address(newImpl)));
|
|
|
+ assertEq(true, proxied.governanceActionIsConsumed(hash));
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitContractUpgrade_Emit(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ MyImplementation newImpl = new MyImplementation(EVMCHAINID, CHAINID);
|
|
|
+
|
|
|
+ vm.assume(storageSlot != IMPLEMENTATION_SLOT);
|
|
|
+ vm.assume(storageSlot != hashedLocation(address(newImpl), INIT_IMPLEMENTATION_SLOT));
|
|
|
+
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitContract(MODULE, CHAINID, address(newImpl));
|
|
|
+ (bytes memory _vm, bytes32 hash) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.assume(storageSlot != hashedLocation(hash, CONSUMED_ACTIONS_SLOT));
|
|
|
+
|
|
|
+ vm.expectEmit(true,true,true,true);
|
|
|
+ emit ContractUpgraded(address(impl), address(newImpl));
|
|
|
+
|
|
|
+ proxied.submitContractUpgrade(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testInitialize_after_upgrade_revert(bytes32 storageSlot, address alice)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ Implementation newImpl = new Implementation();
|
|
|
+
|
|
|
+ vm.assume(storageSlot != IMPLEMENTATION_SLOT);
|
|
|
+ vm.assume(storageSlot != hashedLocation(address(newImpl), INIT_IMPLEMENTATION_SLOT));
|
|
|
+
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitContract(MODULE, 2, address(newImpl));
|
|
|
+ (bytes memory _vm, bytes32 hash) = validVm(0, 0, 0, 1, governanceContract, 0, 0, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.assume(storageSlot != hashedLocation(hash, CONSUMED_ACTIONS_SLOT));
|
|
|
+
|
|
|
+ proxied.submitContractUpgrade(_vm);
|
|
|
+
|
|
|
+ vm.prank(alice);
|
|
|
+ vm.expectRevert("already initialized");
|
|
|
+ proxied.initialize();
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitContractUpgrade_Revert_InvalidFork(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint64 evmChainId,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(evmChainId != EVMCHAINID);
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+
|
|
|
+ MyImplementation newImpl = new MyImplementation(evmChainId, CHAINID);
|
|
|
+ bytes memory payload = payloadSubmitContract(MODULE, CHAINID, address(newImpl));
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("invalid fork");
|
|
|
+ proxied.submitContractUpgrade(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitContractUpgrade_Revert_InvalidModule(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ bytes32 module)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(module != MODULE);
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ MyImplementation newImpl = new MyImplementation(EVMCHAINID, CHAINID);
|
|
|
+ bytes memory payload = payloadSubmitContract(module, CHAINID, address(newImpl));
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("Invalid Module");
|
|
|
+ proxied.submitContractUpgrade(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitContractUpgrade_Revert_InvalidChain(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint16 chainId)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(chainId != CHAINID);
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ MyImplementation newImpl = new MyImplementation(EVMCHAINID, CHAINID);
|
|
|
+ bytes memory payload = payloadSubmitContract(MODULE, chainId, address(newImpl));
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("Invalid Chain");
|
|
|
+ proxied.submitContractUpgrade(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitContractUpgrade_Revert_InvalidGuardianSetIndex(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 guardianSetIndex,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(guardianSetIndex != 0);
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ MyImplementation newImpl = new MyImplementation(EVMCHAINID, CHAINID);
|
|
|
+ bytes memory payload = payloadSubmitContract(MODULE, CHAINID, address(newImpl));
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ guardianSetIndex, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ // Since the current version of the test uses only one guardian set,
|
|
|
+ // in practice only the 'else' branch will be taken
|
|
|
+ if (guardianSetIndex < proxied.getCurrentGuardianSetIndex()) {
|
|
|
+ vm.expectRevert("not signed by current guardian set");
|
|
|
+ } else {
|
|
|
+ vm.expectRevert("invalid guardian set");
|
|
|
+ }
|
|
|
+
|
|
|
+ proxied.submitContractUpgrade(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitContractUpgrade_Revert_WrongGovernanceChain(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint16 emitterChainId,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(emitterChainId != 1);
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ MyImplementation newImpl = new MyImplementation(EVMCHAINID, CHAINID);
|
|
|
+ bytes memory payload = payloadSubmitContract(MODULE, CHAINID, address(newImpl));
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, emitterChainId, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("wrong governance chain");
|
|
|
+ proxied.submitContractUpgrade(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitContractUpgrade_Revert_WrongGovernanceContract(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ bytes32 emitterAddress,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(emitterAddress != governanceContract);
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ MyImplementation newImpl = new MyImplementation(EVMCHAINID, CHAINID);
|
|
|
+ bytes memory payload = payloadSubmitContract(MODULE, CHAINID, address(newImpl));
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, emitterAddress, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("wrong governance contract");
|
|
|
+ proxied.submitContractUpgrade(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitContractUpgrade_Revert_ReplayAttack(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ MyImplementation newImpl = new MyImplementation(EVMCHAINID, CHAINID);
|
|
|
+ bytes memory payload = payloadSubmitContract(MODULE, CHAINID, address(newImpl));
|
|
|
+ (bytes memory _vm, bytes32 hash) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.assume(storageSlot != hashedLocation(hash, CONSUMED_ACTIONS_SLOT));
|
|
|
+
|
|
|
+ proxied.submitContractUpgrade(_vm);
|
|
|
+
|
|
|
+ vm.expectRevert("governance action already consumed");
|
|
|
+ proxied.submitContractUpgrade(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitSetMessageFee(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint256 newMessageFee)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(storageSlot != MESSAGEFEE_SLOT);
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitMessageFee(MODULE, CHAINID, newMessageFee);
|
|
|
+ (bytes memory _vm, bytes32 hash) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.assume(storageSlot != hashedLocation(hash, CONSUMED_ACTIONS_SLOT));
|
|
|
+
|
|
|
+ proxied.submitSetMessageFee(_vm);
|
|
|
+
|
|
|
+ assertEq(newMessageFee, proxied.messageFee());
|
|
|
+ assertEq(true, proxied.governanceActionIsConsumed(hash));
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitSetMessageFee_Revert_InvalidModule(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ bytes32 module,
|
|
|
+ uint256 newMessageFee)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(module != MODULE);
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitMessageFee(module, CHAINID, newMessageFee);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("Invalid Module");
|
|
|
+ proxied.submitSetMessageFee(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitSetMessageFee_Revert_InvalidChain(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint16 chainId,
|
|
|
+ uint256 newMessageFee)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(chainId != CHAINID);
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitMessageFee(MODULE, chainId, newMessageFee);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("Invalid Chain");
|
|
|
+ proxied.submitSetMessageFee(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitSetMessageFee_Revert_InvalidEvmChain(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint64 evmChainId,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint256 newMessageFee)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(evmChainId != EVMCHAINID);
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitMessageFee(MODULE, CHAINID, newMessageFee);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("Invalid Chain");
|
|
|
+ proxied.submitSetMessageFee(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitSetMessageFee_Revert_InvalidGuardianSetIndex(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 guardianSetIndex,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint256 newMessageFee)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(guardianSetIndex != 0);
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitMessageFee(MODULE, CHAINID, newMessageFee);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ guardianSetIndex, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ // Since the current version of the test uses only one guardian set,
|
|
|
+ // in practice only the 'else' branch will be taken
|
|
|
+ if (guardianSetIndex < proxied.getCurrentGuardianSetIndex()) {
|
|
|
+ vm.expectRevert("not signed by current guardian set");
|
|
|
+ } else {
|
|
|
+ vm.expectRevert("invalid guardian set");
|
|
|
+ }
|
|
|
+
|
|
|
+ proxied.submitSetMessageFee(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitSetMessageFee_Revert_WrongGovernanceChain(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint16 emitterChainId,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint256 newMessageFee)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(emitterChainId != 1);
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitMessageFee(MODULE, CHAINID, newMessageFee);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, emitterChainId, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("wrong governance chain");
|
|
|
+ proxied.submitSetMessageFee(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitSetMessageFee_Revert_WrongGovernanceContract(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ bytes32 emitterAddress,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint256 newMessageFee)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(emitterAddress != governanceContract);
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitMessageFee(MODULE, CHAINID, newMessageFee);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, emitterAddress, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("wrong governance contract");
|
|
|
+ proxied.submitSetMessageFee(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitSetMessageFee_Revert_ReplayAttack(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint256 newMessageFee)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(storageSlot != MESSAGEFEE_SLOT);
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitMessageFee(MODULE, CHAINID, newMessageFee);
|
|
|
+ (bytes memory _vm, bytes32 hash) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.assume(storageSlot != hashedLocation(hash, CONSUMED_ACTIONS_SLOT));
|
|
|
+
|
|
|
+ proxied.submitSetMessageFee(_vm);
|
|
|
+
|
|
|
+ vm.expectRevert("governance action already consumed");
|
|
|
+ proxied.submitSetMessageFee(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ //Make a similar test but with chainId = 0
|
|
|
+ function testSubmitNewGuardianSet(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ address[] memory newGuardianSet)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(storageSlot != hashedLocationOffset(0, GUARDIANSETS_SLOT, 1));
|
|
|
+ vm.assume(storageSlot != hashedLocationOffset(0, GUARDIANSETS_SLOT, 0));
|
|
|
+ vm.assume(storageSlot != GUARDIANSETINDEX_SLOT);
|
|
|
+ vm.assume(0 < newGuardianSet.length);
|
|
|
+ vm.assume(newGuardianSet.length < 20);
|
|
|
+ for(uint8 i = 0; i < newGuardianSet.length; i++)
|
|
|
+ vm.assume(newGuardianSet[i] != address(0));
|
|
|
+
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitNewGuardianSet(MODULE, CHAINID, 1, newGuardianSet);
|
|
|
+ (bytes memory _vm, bytes32 hash) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.assume(storageSlot != hashedLocation(hash, CONSUMED_ACTIONS_SLOT));
|
|
|
+
|
|
|
+ proxied.submitNewGuardianSet(_vm);
|
|
|
+
|
|
|
+ assertEq(true, proxied.governanceActionIsConsumed(hash));
|
|
|
+ assertEq(uint32(block.timestamp) + 86400, proxied.getGuardianSet(0).expirationTime);
|
|
|
+ assertEq(newGuardianSet, proxied.getGuardianSet(1).keys);
|
|
|
+ assertEq(1, proxied.getCurrentGuardianSetIndex());
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitNewGuardianSet_Revert_InvalidModule(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint64 evmChainId,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ bytes32 module,
|
|
|
+ uint16 chainId,
|
|
|
+ address[] memory newGuardianSet)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(module != MODULE);
|
|
|
+ vm.assume(chainId == 0 || (chainId == CHAINID && evmChainId == EVMCHAINID));
|
|
|
+ vm.assume(newGuardianSet.length < 20);
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitNewGuardianSet(module,chainId, 1, newGuardianSet);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("invalid Module");
|
|
|
+ proxied.submitNewGuardianSet(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitNewGuardianSet_Revert_InvalidChain(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint16 chainId,
|
|
|
+ address[] memory newGuardianSet)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(chainId != CHAINID && chainId != 0);
|
|
|
+ vm.assume(newGuardianSet.length < 20);
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitNewGuardianSet(MODULE, chainId, 1, newGuardianSet);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("invalid Chain");
|
|
|
+ proxied.submitNewGuardianSet(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitNewGuardianSet_Revert_InvalidEvmChain(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint64 evmChainId,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ address[] memory newGuardianSet)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(evmChainId != EVMCHAINID);
|
|
|
+ vm.assume(newGuardianSet.length < 20);
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitNewGuardianSet(MODULE, CHAINID, 1, newGuardianSet);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("invalid Chain");
|
|
|
+ proxied.submitNewGuardianSet(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitNewGuardianSet_Revert_GuardianSetEmpty(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint64 evmChainId,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint16 chainId)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(chainId == 0 || (chainId == CHAINID && evmChainId == EVMCHAINID));
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+
|
|
|
+ address[] memory newGuardianSet = new address[](0); // Empty guardian set
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitNewGuardianSet(MODULE, chainId, 1, newGuardianSet);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("new guardian set is empty");
|
|
|
+ proxied.submitNewGuardianSet(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitNewGuardianSet_Revert_WrongIndex(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint64 evmChainId,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint16 chainId,
|
|
|
+ uint32 newGuardianSetIndex,
|
|
|
+ address[] memory newGuardianSet)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(newGuardianSetIndex != 1);
|
|
|
+ vm.assume(chainId == 0 || (chainId == CHAINID && evmChainId == EVMCHAINID));
|
|
|
+ vm.assume(0 < newGuardianSet.length);
|
|
|
+ vm.assume(newGuardianSet.length < 20);
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitNewGuardianSet(MODULE, chainId, newGuardianSetIndex, newGuardianSet);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("index must increase in steps of 1");
|
|
|
+ proxied.submitNewGuardianSet(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitNewGuardianSet_Revert_InvalidGuardianSetIndex(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 guardianSetIndex,
|
|
|
+ uint64 evmChainId,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint16 chainId,
|
|
|
+ address[] memory newGuardianSet)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(guardianSetIndex != 0);
|
|
|
+ vm.assume(chainId == 0 || (chainId == CHAINID && evmChainId == EVMCHAINID));
|
|
|
+ vm.assume(0 < newGuardianSet.length);
|
|
|
+ vm.assume(newGuardianSet.length < 20);
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitNewGuardianSet(MODULE, chainId, 1, newGuardianSet);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ guardianSetIndex, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ // Since the current version of the test uses only one guardian set,
|
|
|
+ // in practice only the 'else' branch will be taken
|
|
|
+ if (guardianSetIndex < proxied.getCurrentGuardianSetIndex()) {
|
|
|
+ vm.expectRevert("not signed by current guardian set");
|
|
|
+ } else {
|
|
|
+ vm.expectRevert("invalid guardian set");
|
|
|
+ }
|
|
|
+
|
|
|
+ proxied.submitNewGuardianSet(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitNewGuardianSet_Revert_WrongGovernanceChain(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint64 evmChainId,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint16 emitterChainId,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint16 chainId,
|
|
|
+ address[] memory newGuardianSet)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(emitterChainId != 1);
|
|
|
+ vm.assume(chainId == 0 || (chainId == CHAINID && evmChainId == EVMCHAINID));
|
|
|
+ vm.assume(0 < newGuardianSet.length);
|
|
|
+ vm.assume(newGuardianSet.length < 20);
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitNewGuardianSet(MODULE, chainId, 1, newGuardianSet);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, emitterChainId, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("wrong governance chain");
|
|
|
+ proxied.submitNewGuardianSet(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitNewGuardianSet_Revert_WrongGovernanceContract(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint64 evmChainId,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ bytes32 emitterAddress,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint16 chainId,
|
|
|
+ address[] memory newGuardianSet)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(emitterAddress != governanceContract);
|
|
|
+ vm.assume(chainId == 0 || (chainId == CHAINID && evmChainId == EVMCHAINID));
|
|
|
+ vm.assume(0 < newGuardianSet.length);
|
|
|
+ vm.assume(newGuardianSet.length < 20);
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitNewGuardianSet(MODULE, chainId, 1, newGuardianSet);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, emitterAddress, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("wrong governance contract");
|
|
|
+ proxied.submitNewGuardianSet(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitNewGuardianSet_Revert_ReplayAttack(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ address[] memory newGuardianSet)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(storageSlot != hashedLocationOffset(0, GUARDIANSETS_SLOT, 1));
|
|
|
+ vm.assume(storageSlot != hashedLocationOffset(0, GUARDIANSETS_SLOT, 0));
|
|
|
+ vm.assume(storageSlot != GUARDIANSETINDEX_SLOT);
|
|
|
+ vm.assume(0 < newGuardianSet.length);
|
|
|
+ vm.assume(newGuardianSet.length < 20);
|
|
|
+ for(uint8 i = 0; i < newGuardianSet.length; i++)
|
|
|
+ vm.assume(newGuardianSet[i] != address(0));
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitNewGuardianSet(MODULE, CHAINID, 1, newGuardianSet);
|
|
|
+ (bytes memory _vm, bytes32 hash) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.assume(storageSlot != hashedLocation(hash, CONSUMED_ACTIONS_SLOT));
|
|
|
+
|
|
|
+ proxied.submitNewGuardianSet(_vm);
|
|
|
+
|
|
|
+ // The error message is not "governance action already consumed" because the guardian set index is updated,
|
|
|
+ // and the check for the current guardian set index comes first than the check for action already consumed
|
|
|
+ vm.expectRevert("not signed by current guardian set");
|
|
|
+ proxied.submitNewGuardianSet(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function isReservedAddress(address addr) internal view returns (bool) {
|
|
|
+ return
|
|
|
+ // Avoid precompiled contracts
|
|
|
+ addr <= address(0x9) ||
|
|
|
+ // Wormhole contract does not accept assets
|
|
|
+ addr == address(impl) ||
|
|
|
+ // Setup contract
|
|
|
+ addr == address(setup) ||
|
|
|
+ // Test contract
|
|
|
+ addr == address(this) ||
|
|
|
+ // Cheatcode contract
|
|
|
+ addr == address(vm) ||
|
|
|
+ // Create2Deployer address
|
|
|
+ addr == address(0x4e59b44847b379578588920cA78FbF26c0B4956C);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitTransferFees(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint256 amount,
|
|
|
+ bytes32 recipient)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ // Avoid reserved addresses (which will cause the transfer to revert)
|
|
|
+ vm.assume(!isReservedAddress(address(uint160(uint256(recipient)))));
|
|
|
+
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+ vm.deal(address(proxied), amount);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitTransferFees(MODULE, CHAINID, amount, recipient);
|
|
|
+ (bytes memory _vm, bytes32 hash) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.assume(storageSlot != hashedLocation(hash, CONSUMED_ACTIONS_SLOT));
|
|
|
+
|
|
|
+ address payable receiver = payable(address(uint160(uint256(recipient))));
|
|
|
+ uint256 previousBalance = receiver.balance;
|
|
|
+
|
|
|
+ proxied.submitTransferFees(_vm);
|
|
|
+
|
|
|
+ assertEq(receiver.balance, previousBalance + amount);
|
|
|
+ assertEq(address(proxied).balance, 0);
|
|
|
+ assertEq(true, proxied.governanceActionIsConsumed(hash));
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitTransferFees_Revert_InvalidModule(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint64 evmChainId,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ bytes32 module,
|
|
|
+ uint16 chainId,
|
|
|
+ uint256 amount,
|
|
|
+ bytes32 recipient)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(module != MODULE);
|
|
|
+ vm.assume(chainId == 0 || (chainId == CHAINID && evmChainId == EVMCHAINID));
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+ vm.deal(address(proxied), amount);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitTransferFees(module, CHAINID, amount, recipient);
|
|
|
+ bytes memory body = abi.encodePacked(
|
|
|
+ timestamp, nonce, uint16(1), governanceContract, sequence, consistencyLevel, payload);
|
|
|
+
|
|
|
+ bytes32 hash = keccak256(abi.encodePacked(keccak256(body)));
|
|
|
+
|
|
|
+ bytes memory _vm = bytes.concat(validVmHeader(0), validSignature(testGuardian, hash), body);
|
|
|
+
|
|
|
+ vm.expectRevert("invalid Module");
|
|
|
+ proxied.submitTransferFees(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitTransferFees_Revert_InvalidChain(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint16 chainId,
|
|
|
+ uint256 amount,
|
|
|
+ bytes32 recipient)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(chainId != CHAINID && chainId != 0);
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+ vm.deal(address(proxied), amount);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitTransferFees(MODULE, chainId, amount, recipient);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("invalid Chain");
|
|
|
+ proxied.submitTransferFees(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitTransferFees_Revert_InvalidEvmChain(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint64 evmchainId,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint256 amount,
|
|
|
+ bytes32 recipient)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(evmchainId != EVMCHAINID);
|
|
|
+ vm.chainId(evmchainId);
|
|
|
+ vm.deal(address(proxied), amount);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitTransferFees(MODULE, CHAINID, amount, recipient);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("invalid Chain");
|
|
|
+ proxied.submitTransferFees(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ function testSubmitTransferFees_Revert_InvalidGuardianSet(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint64 evmChainId,
|
|
|
+ uint32 guardianSetIndex,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint16 chainId,
|
|
|
+ uint256 amount,
|
|
|
+ bytes32 recipient)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(guardianSetIndex != 0);
|
|
|
+ vm.assume(chainId == 0 || (chainId == CHAINID && evmChainId == EVMCHAINID));
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+ vm.deal(address(proxied), amount);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitTransferFees(MODULE, chainId, amount, recipient);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ guardianSetIndex, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ // Since the current version of the test uses only one guardian set,
|
|
|
+ // in practice only the 'else' branch will be taken
|
|
|
+ if (guardianSetIndex < proxied.getCurrentGuardianSetIndex()) {
|
|
|
+ vm.expectRevert("not signed by current guardian set");
|
|
|
+ } else {
|
|
|
+ vm.expectRevert("invalid guardian set");
|
|
|
+ }
|
|
|
+
|
|
|
+ proxied.submitTransferFees(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitTransferFees_Revert_WrongGovernanceChain(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint64 evmChainId,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint16 emitterChainId,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint16 chainId,
|
|
|
+ uint256 amount,
|
|
|
+ bytes32 recipient)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(emitterChainId != 1);
|
|
|
+ vm.assume(chainId == 0 || (chainId == CHAINID && evmChainId == EVMCHAINID));
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+ vm.deal(address(proxied), amount);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitTransferFees(MODULE, chainId, amount, recipient);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, emitterChainId, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("wrong governance chain");
|
|
|
+ proxied.submitTransferFees(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitTransferFees_Revert_WrongGovernanceContract(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint64 evmChainId,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ bytes32 emitterAddress,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint16 chainId,
|
|
|
+ uint256 amount,
|
|
|
+ bytes32 recipient)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(emitterAddress != governanceContract);
|
|
|
+ vm.assume(chainId == 0 || (chainId == CHAINID && evmChainId == EVMCHAINID));
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+ vm.deal(address(proxied), amount);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitTransferFees(MODULE, chainId, amount, recipient);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, emitterAddress, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("wrong governance contract");
|
|
|
+ proxied.submitTransferFees(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitTransferFees_Revert_ReplayAttack(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint256 amount,
|
|
|
+ bytes32 recipient)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ // Avoid reserved addresses (which will cause the transfer to revert)
|
|
|
+ vm.assume(!isReservedAddress(address(uint160(uint256(recipient)))));
|
|
|
+
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+ vm.deal(address(proxied), amount);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitTransferFees(MODULE, CHAINID, amount, recipient);
|
|
|
+ (bytes memory _vm, bytes32 hash) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.assume(storageSlot != hashedLocation(hash, CONSUMED_ACTIONS_SLOT));
|
|
|
+
|
|
|
+ proxied.submitTransferFees(_vm);
|
|
|
+
|
|
|
+ vm.expectRevert("governance action already consumed");
|
|
|
+ proxied.submitTransferFees(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitRecoverChainId(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint256 evmChainId,
|
|
|
+ uint16 newChainId)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(storageSlot != CHAINID_SLOT);
|
|
|
+ vm.assume(storageSlot != EVMCHAINID_SLOT);
|
|
|
+ vm.assume(evmChainId != EVMCHAINID);
|
|
|
+ vm.assume(evmChainId < 2 ** 64);
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitRecoverChainId(MODULE, evmChainId, newChainId);
|
|
|
+ (bytes memory _vm, bytes32 hash) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.assume(storageSlot != hashedLocation(hash, CONSUMED_ACTIONS_SLOT));
|
|
|
+
|
|
|
+ proxied.submitRecoverChainId(_vm);
|
|
|
+
|
|
|
+ assertEq(true, proxied.governanceActionIsConsumed(hash));
|
|
|
+ assertEq(evmChainId, proxied.evmChainId());
|
|
|
+ assertEq(newChainId, proxied.chainId());
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitRecoverChainId_Revert_NotAFork(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint256 evmChainId,
|
|
|
+ uint16 newChainId)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(evmChainId != EVMCHAINID);
|
|
|
+ vm.chainId(EVMCHAINID);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitRecoverChainId(MODULE, evmChainId, newChainId);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("not a fork");
|
|
|
+ proxied.submitRecoverChainId(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitRecoverChainId_Revert_InvalidModule(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ bytes32 module,
|
|
|
+ uint256 evmChainId,
|
|
|
+ uint16 newChainId)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(module != MODULE);
|
|
|
+ vm.assume(evmChainId != EVMCHAINID);
|
|
|
+ vm.assume(evmChainId < 2 ** 64);
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+
|
|
|
+ vm.assume(module != MODULE);
|
|
|
+ bytes memory payload = payloadSubmitRecoverChainId(module, evmChainId, newChainId);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("invalid Module");
|
|
|
+ proxied.submitRecoverChainId(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitRecoverChainId_Revert_InvalidEVMChain(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint64 blockChainId,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint256 evmChainId,
|
|
|
+ uint16 newChainId)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(evmChainId != EVMCHAINID);
|
|
|
+ vm.assume(evmChainId < 2 ** 64);
|
|
|
+ vm.assume(blockChainId != evmChainId && blockChainId != EVMCHAINID);
|
|
|
+ vm.chainId(blockChainId);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitRecoverChainId(MODULE, evmChainId, newChainId);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("invalid EVM Chain");
|
|
|
+ proxied.submitRecoverChainId(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ function testSubmitRecoverChainId_Revert_InvalidGuardianSetIndex(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 guardianSetIndex,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint256 evmChainId,
|
|
|
+ uint16 newChainId)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(guardianSetIndex != 0);
|
|
|
+ vm.assume(evmChainId != EVMCHAINID);
|
|
|
+ vm.assume(evmChainId < 2 ** 64);
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitRecoverChainId(MODULE, evmChainId, newChainId);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ guardianSetIndex, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ // Since the current version of the test uses only one guardian set,
|
|
|
+ // in practice only the 'else' branch will be taken
|
|
|
+ if (guardianSetIndex < proxied.getCurrentGuardianSetIndex()) {
|
|
|
+ vm.expectRevert("not signed by current guardian set");
|
|
|
+ } else {
|
|
|
+ vm.expectRevert("invalid guardian set");
|
|
|
+ }
|
|
|
+
|
|
|
+ proxied.submitRecoverChainId(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitRecoverChainId_Revert_WrongGovernanceChain(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint16 emitterChainId,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint256 evmChainId,
|
|
|
+ uint16 newChainId)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(emitterChainId != 1);
|
|
|
+ vm.assume(evmChainId != EVMCHAINID);
|
|
|
+ vm.assume(evmChainId < 2 ** 64);
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitRecoverChainId(MODULE, evmChainId, newChainId);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, emitterChainId, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("wrong governance chain");
|
|
|
+ proxied.submitRecoverChainId(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitRecoverChainId_Revert_WrongGovernanceContract(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ bytes32 emitterAddress,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint256 evmChainId,
|
|
|
+ uint16 newChainId)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(emitterAddress != governanceContract);
|
|
|
+ vm.assume(evmChainId != EVMCHAINID);
|
|
|
+ vm.assume(evmChainId < 2 ** 64);
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitRecoverChainId(MODULE, evmChainId, newChainId);
|
|
|
+ (bytes memory _vm, ) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, emitterAddress, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.expectRevert("wrong governance contract");
|
|
|
+ proxied.submitRecoverChainId(_vm);
|
|
|
+ }
|
|
|
+
|
|
|
+ function testSubmitRecoverChainId_Revert_ReplayAttack(
|
|
|
+ bytes32 storageSlot,
|
|
|
+ uint32 timestamp,
|
|
|
+ uint32 nonce,
|
|
|
+ uint64 sequence,
|
|
|
+ uint8 consistencyLevel,
|
|
|
+ uint256 evmChainId,
|
|
|
+ uint16 newChainId)
|
|
|
+ public
|
|
|
+ unchangedStorage(address(proxied), storageSlot)
|
|
|
+ {
|
|
|
+ vm.assume(storageSlot != CHAINID_SLOT);
|
|
|
+ vm.assume(storageSlot != EVMCHAINID_SLOT);
|
|
|
+ vm.assume(evmChainId != EVMCHAINID);
|
|
|
+ vm.assume(evmChainId < 2 ** 64);
|
|
|
+ vm.chainId(evmChainId);
|
|
|
+
|
|
|
+ bytes memory payload = payloadSubmitRecoverChainId(MODULE, evmChainId, newChainId);
|
|
|
+ (bytes memory _vm, bytes32 hash) = validVm(
|
|
|
+ 0, timestamp, nonce, 1, governanceContract, sequence, consistencyLevel, payload, testGuardian);
|
|
|
+
|
|
|
+ vm.assume(storageSlot != hashedLocation(hash, CONSUMED_ACTIONS_SLOT));
|
|
|
+
|
|
|
+ proxied.submitRecoverChainId(_vm);
|
|
|
+
|
|
|
+ // The error message is not "governance action already consumed" because the evmChainId is updated,
|
|
|
+ // and the check for isFork() comes first than the check for action already consumed
|
|
|
+ vm.expectRevert("not a fork");
|
|
|
+ proxied.submitRecoverChainId(_vm);
|
|
|
+ }
|
|
|
+}
|