Implementation.t.sol 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270
  1. // test/Messages.sol
  2. // SPDX-License-Identifier: Apache 2
  3. pragma solidity ^0.8.0;
  4. import "../contracts/Implementation.sol";
  5. import "../contracts/Setup.sol";
  6. import "../contracts/Wormhole.sol";
  7. import "../contracts/interfaces/IWormhole.sol";
  8. import "forge-std/Test.sol";
  9. import "forge-test/rv-helpers/TestUtils.sol";
  10. import "../contracts/mock/MockImplementation.sol";
  11. contract TestImplementation is TestUtils {
  12. event LogMessagePublished(
  13. address indexed sender,
  14. uint64 sequence,
  15. uint32 nonce,
  16. bytes payload,
  17. uint8 consistencyLevel
  18. );
  19. Wormhole proxy;
  20. Implementation impl;
  21. Setup setup;
  22. Setup proxiedSetup;
  23. IWormhole public proxied;
  24. uint256 public constant testGuardian =
  25. 93941733246223705020089879371323733820373732307041878556247502674739205313440;
  26. uint16 public governanceChainId = 1;
  27. bytes32 public constant governanceContract =
  28. 0x0000000000000000000000000000000000000000000000000000000000000004;
  29. bytes32 constant MESSAGEFEE_STORAGESLOT = bytes32(uint256(7));
  30. bytes32 constant SEQUENCES_SLOT = bytes32(uint256(4));
  31. uint256 constant testBadSigner1PK =
  32. 61380885381456947260501717894649826485638944763666157704556612272461980735996;
  33. uint256 constant testSigner1 =
  34. 93941733246223705020089879371323733820373732307041878556247502674739205313440;
  35. uint256 constant testSigner2 =
  36. 62029033948131772461620424086954761227341731979036746506078649711513083917822;
  37. uint256 constant testSigner3 =
  38. 61380885381456947260501717894649826485638944763666157704556612272461980735995;
  39. // "Core" (left padded)
  40. bytes32 constant core =
  41. 0x00000000000000000000000000000000000000000000000000000000436f7265;
  42. uint8 actionContractUpgrade = 1;
  43. uint8 actionGuardianSetUpgrade = 2;
  44. uint8 actionMessageFee = 3;
  45. uint8 actionTransferFee = 4;
  46. uint8 actionRecoverChainId = 5;
  47. uint16 public testChainId = 2;
  48. uint256 public testEvmChainId = 1;
  49. uint16 fakeChainId = 1337;
  50. uint256 fakeEvmChainId = 10001;
  51. function setUp() public {
  52. // Deploy setup
  53. setup = new Setup();
  54. // Deploy implementation contract
  55. impl = new Implementation();
  56. // Deploy proxy
  57. proxy = new Wormhole(address(setup), bytes(""));
  58. address[] memory keys = new address[](1);
  59. keys[0] = 0xbeFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe;
  60. //keys[0] = vm.addr(testGuardian);
  61. //proxied setup
  62. proxiedSetup = Setup(address(proxy));
  63. vm.chainId(testEvmChainId);
  64. proxiedSetup.setup({
  65. implementation: address(impl),
  66. initialGuardians: keys,
  67. chainId: testChainId,
  68. governanceChainId: 1,
  69. governanceContract: governanceContract,
  70. evmChainId: testEvmChainId
  71. });
  72. proxied = IWormhole(address(proxy));
  73. }
  74. function uint256Array(
  75. uint256 member
  76. ) internal pure returns (uint256[] memory arr) {
  77. arr = new uint256[](1);
  78. arr[0] = member;
  79. }
  80. function testPublishMessage(
  81. bytes32 storageSlot,
  82. uint256 messageFee,
  83. address alice,
  84. uint256 aliceBalance,
  85. uint32 nonce,
  86. bytes memory payload,
  87. uint8 consistencyLevel
  88. ) public unchangedStorage(address(proxied), storageSlot) {
  89. uint64 sequence = proxied.nextSequence(alice);
  90. bytes32 storageLocation = hashedLocation(alice, SEQUENCES_SLOT);
  91. vm.assume(aliceBalance >= messageFee);
  92. vm.assume(storageSlot != storageLocation);
  93. vm.assume(storageSlot != MESSAGEFEE_STORAGESLOT);
  94. vm.store(address(proxied), MESSAGEFEE_STORAGESLOT, bytes32(messageFee));
  95. vm.deal(address(alice), aliceBalance);
  96. vm.prank(alice);
  97. proxied.publishMessage{value: messageFee}(
  98. nonce,
  99. payload,
  100. consistencyLevel
  101. );
  102. assertEq(sequence + 1, proxied.nextSequence(alice));
  103. }
  104. function testPublishMessage_Emit(
  105. bytes32 storageSlot,
  106. uint256 messageFee,
  107. address alice,
  108. uint256 aliceBalance,
  109. uint32 nonce,
  110. bytes memory payload,
  111. uint8 consistencyLevel
  112. ) public unchangedStorage(address(proxied), storageSlot) {
  113. uint64 sequence = proxied.nextSequence(alice);
  114. bytes32 storageLocation = hashedLocation(alice, SEQUENCES_SLOT);
  115. vm.assume(aliceBalance >= messageFee);
  116. vm.assume(storageSlot != storageLocation);
  117. vm.assume(storageSlot != MESSAGEFEE_STORAGESLOT);
  118. vm.store(address(proxied), MESSAGEFEE_STORAGESLOT, bytes32(messageFee));
  119. vm.deal(address(alice), aliceBalance);
  120. vm.prank(alice);
  121. vm.expectEmit(true, true, true, true);
  122. emit LogMessagePublished(
  123. alice,
  124. sequence,
  125. nonce,
  126. payload,
  127. consistencyLevel
  128. );
  129. proxied.publishMessage{value: messageFee}(
  130. nonce,
  131. payload,
  132. consistencyLevel
  133. );
  134. }
  135. function testPublishMessage_Revert_InvalidFee(
  136. bytes32 storageSlot,
  137. uint256 messageFee,
  138. address alice,
  139. uint256 aliceBalance,
  140. uint256 aliceFee,
  141. uint32 nonce,
  142. bytes memory payload,
  143. uint8 consistencyLevel
  144. ) public unchangedStorage(address(proxied), storageSlot) {
  145. vm.assume(aliceBalance >= aliceFee);
  146. vm.assume(aliceFee != messageFee);
  147. vm.assume(storageSlot != MESSAGEFEE_STORAGESLOT);
  148. vm.store(address(proxied), MESSAGEFEE_STORAGESLOT, bytes32(messageFee));
  149. vm.deal(address(alice), aliceBalance);
  150. vm.prank(alice);
  151. vm.expectRevert("invalid fee");
  152. proxied.publishMessage{value: aliceFee}(
  153. nonce,
  154. payload,
  155. consistencyLevel
  156. );
  157. }
  158. /// forge-config: default.allow_internal_expect_revert = true
  159. function testPublishMessage_Revert_OutOfFunds(
  160. bytes32 storageSlot,
  161. uint256 messageFee,
  162. address alice,
  163. uint256 aliceBalance,
  164. uint32 nonce,
  165. bytes memory payload,
  166. uint8 consistencyLevel
  167. ) public unchangedStorage(address(proxied), storageSlot) {
  168. vm.assume(aliceBalance < messageFee);
  169. vm.assume(storageSlot != MESSAGEFEE_STORAGESLOT);
  170. vm.store(address(proxied), MESSAGEFEE_STORAGESLOT, bytes32(messageFee));
  171. vm.deal(address(alice), aliceBalance);
  172. vm.prank(alice);
  173. vm.expectRevert();
  174. proxied.publishMessage{value: messageFee}(
  175. nonce,
  176. payload,
  177. consistencyLevel
  178. );
  179. }
  180. function testShouldBeInitializedWithCorrectSignersAndValues() public {
  181. uint32 index = proxied.getCurrentGuardianSetIndex();
  182. IWormhole.GuardianSet memory set = proxied.getGuardianSet(index);
  183. // check set
  184. assertEq(set.keys.length, 1, "Guardian set length wrong");
  185. assertEq(set.keys[0], vm.addr(testGuardian), "Guardian wrong");
  186. // check expiration
  187. assertEq(set.expirationTime, 0);
  188. // chain id
  189. uint16 chainId = proxied.chainId();
  190. assertEq(chainId, testChainId, "Wrong Chain ID");
  191. // evm chain id
  192. uint256 evmChainId = proxied.evmChainId();
  193. assertEq(evmChainId, testEvmChainId, "Wrong EVM Chain ID");
  194. // governance
  195. uint16 readGovernanceChainId = proxied.governanceChainId();
  196. bytes32 readGovernanceContract = proxied.governanceContract();
  197. assertEq(
  198. readGovernanceChainId,
  199. governanceChainId,
  200. "Wrong governance chain ID"
  201. );
  202. assertEq(
  203. readGovernanceContract,
  204. governanceContract,
  205. "Wrong governance contract"
  206. );
  207. }
  208. function testShouldLogAPublishedMessageCorrectly() public {
  209. vm.expectEmit();
  210. emit LogMessagePublished(
  211. address(this),
  212. uint64(0),
  213. uint32(291),
  214. bytes(hex"123321"),
  215. uint8(32)
  216. );
  217. proxied.publishMessage(0x123, hex"123321", 32);
  218. }
  219. function testShouldIncreaseTheSequenceForAnAccount() public {
  220. proxied.publishMessage(0x1, hex"01", 32);
  221. uint64 sequence = proxied.publishMessage(0x1, hex"01", 32);
  222. assertEq(sequence, 1, "Sequence number didn't increase");
  223. }
  224. function signAndEncodeVMFixedIndex(
  225. uint32 timestamp,
  226. uint32 nonce,
  227. uint16 emitterChainId,
  228. bytes32 emitterAddress,
  229. uint64 sequence,
  230. bytes memory data,
  231. uint256[] memory signers,
  232. uint32 guardianSetIndex,
  233. uint8 consistencyLevel
  234. ) public pure returns (bytes memory signedMessage) {
  235. bytes memory body = abi.encodePacked(
  236. timestamp,
  237. nonce,
  238. emitterChainId,
  239. emitterAddress,
  240. sequence,
  241. consistencyLevel,
  242. data
  243. );
  244. bytes32 bodyHash = keccak256(abi.encodePacked(keccak256(body)));
  245. // Sign the hash with the devnet guardian private key
  246. IWormhole.Signature[] memory sigs = new IWormhole.Signature[](
  247. signers.length
  248. );
  249. for (uint256 i = 0; i < signers.length; i++) {
  250. (sigs[i].v, sigs[i].r, sigs[i].s) = vm.sign(signers[i], bodyHash);
  251. sigs[i].guardianIndex = 0;
  252. }
  253. signedMessage = abi.encodePacked(
  254. uint8(1),
  255. guardianSetIndex,
  256. uint8(sigs.length)
  257. );
  258. for (uint256 i = 0; i < signers.length; i++) {
  259. signedMessage = abi.encodePacked(
  260. signedMessage,
  261. uint8(0),
  262. sigs[i].r,
  263. sigs[i].s,
  264. sigs[i].v - 27
  265. );
  266. }
  267. signedMessage = abi.encodePacked(signedMessage, body);
  268. }
  269. function signAndEncodeVM(
  270. uint32 timestamp,
  271. uint32 nonce,
  272. uint16 emitterChainId,
  273. bytes32 emitterAddress,
  274. uint64 sequence,
  275. bytes memory data,
  276. uint256[] memory signers,
  277. uint32 guardianSetIndex,
  278. uint8 consistencyLevel
  279. ) public pure returns (bytes memory signedMessage) {
  280. bytes memory body = abi.encodePacked(
  281. timestamp,
  282. nonce,
  283. emitterChainId,
  284. emitterAddress,
  285. sequence,
  286. consistencyLevel,
  287. data
  288. );
  289. bytes32 bodyHash = keccak256(abi.encodePacked(keccak256(body)));
  290. // Sign the hash with the devnet guardian private key
  291. IWormhole.Signature[] memory sigs = new IWormhole.Signature[](
  292. signers.length
  293. );
  294. for (uint256 i = 0; i < signers.length; i++) {
  295. (sigs[i].v, sigs[i].r, sigs[i].s) = vm.sign(signers[i], bodyHash);
  296. sigs[i].guardianIndex = 0;
  297. }
  298. signedMessage = abi.encodePacked(
  299. uint8(1),
  300. guardianSetIndex,
  301. uint8(sigs.length)
  302. );
  303. for (uint256 i = 0; i < signers.length; i++) {
  304. signedMessage = abi.encodePacked(
  305. signedMessage,
  306. sigs[i].guardianIndex,
  307. sigs[i].r,
  308. sigs[i].s,
  309. sigs[i].v - 27
  310. );
  311. }
  312. signedMessage = abi.encodePacked(signedMessage, body);
  313. }
  314. function testParseVMsCorrectly() public {
  315. uint32 timestamp = 1000;
  316. uint32 nonce = 1001;
  317. uint16 emitterChainId = 11;
  318. bytes32 emitterAddress = 0x0000000000000000000000000000000000000000000000000000000000000eee;
  319. uint64 sequence = 0;
  320. uint8 consistencyLevel = 2;
  321. uint32 guardianSetIndex = 0;
  322. bytes memory data = hex"aaaaaa";
  323. bytes memory signedMessage = signAndEncodeVM(
  324. timestamp,
  325. nonce,
  326. emitterChainId,
  327. emitterAddress,
  328. sequence,
  329. data,
  330. uint256Array(testGuardian),
  331. guardianSetIndex,
  332. consistencyLevel
  333. );
  334. (IWormhole.VM memory parsed, bool valid, string memory reason) = proxied
  335. .parseAndVerifyVM(signedMessage);
  336. assertEq(parsed.version, 1, "Wrong VM version");
  337. assertEq(parsed.timestamp, timestamp, "Wrong VM timestamp");
  338. assertEq(parsed.nonce, nonce, "Wrong VM nonce");
  339. assertEq(
  340. parsed.emitterChainId,
  341. emitterChainId,
  342. "Wrong emitter chain id"
  343. );
  344. assertEq(
  345. parsed.emitterAddress,
  346. emitterAddress,
  347. "Wrong emitter address"
  348. );
  349. assertEq(parsed.payload, data, "Wrong VM payload");
  350. assertEq(parsed.guardianSetIndex, 0, "Wrong VM guardian set index");
  351. assertEq(parsed.sequence, sequence, "Wrong VM sequence");
  352. assertEq(
  353. parsed.consistencyLevel,
  354. consistencyLevel,
  355. "Wrong VM consistency level"
  356. );
  357. assertEq(valid, true, "Signed vaa not valid");
  358. assertEq(reason, "", "Wrong reason");
  359. }
  360. function testShouldFailQuorumOnVMsWithNoSigners() public {
  361. uint32 timestamp = 1000;
  362. uint32 nonce = 1001;
  363. uint16 emitterChainId = 11;
  364. bytes32 emitterAddress = 0x0000000000000000000000000000000000000000000000000000000000000eee;
  365. uint64 sequence = 0;
  366. uint8 consistencyLevel = 2;
  367. uint32 guardianSetIndex = 0;
  368. bytes memory data = hex"aaaaaa";
  369. bytes memory signedMessage = signAndEncodeVM(
  370. timestamp,
  371. nonce,
  372. emitterChainId,
  373. emitterAddress,
  374. sequence,
  375. data,
  376. new uint256[](0),
  377. guardianSetIndex,
  378. consistencyLevel
  379. );
  380. (, bool valid, string memory reason) = proxied.parseAndVerifyVM(
  381. signedMessage
  382. );
  383. assertEq(valid, false, "Signed vaa shouldn't be valid");
  384. assertEq(reason, "no quorum", "Wrong reason");
  385. }
  386. function testShouldFailToVerifyOnVMsWithBadSigner() public {
  387. uint32 timestamp = 1000;
  388. uint32 nonce = 1001;
  389. uint16 emitterChainId = 11;
  390. bytes32 emitterAddress = 0x0000000000000000000000000000000000000000000000000000000000000eee;
  391. uint64 sequence = 0;
  392. uint8 consistencyLevel = 2;
  393. uint32 guardianSetIndex = 0;
  394. bytes memory data = hex"aaaaaa";
  395. bytes memory signedMessage = signAndEncodeVM(
  396. timestamp,
  397. nonce,
  398. emitterChainId,
  399. emitterAddress,
  400. sequence,
  401. data,
  402. uint256Array(testBadSigner1PK),
  403. guardianSetIndex,
  404. consistencyLevel
  405. );
  406. (, bool valid, string memory reason) = proxied.parseAndVerifyVM(
  407. signedMessage
  408. );
  409. assertEq(valid, false, "Signed vaa shouldn't be valid");
  410. assertEq(reason, "VM signature invalid", "Wrong reason");
  411. }
  412. function testShouldErrorOnVMsWithInvalidGuardianSetIndex() public {
  413. uint32 timestamp = 1000;
  414. uint32 nonce = 1001;
  415. uint16 emitterChainId = 11;
  416. bytes32 emitterAddress = 0x0000000000000000000000000000000000000000000000000000000000000eee;
  417. uint64 sequence = 0;
  418. uint8 consistencyLevel = 2;
  419. uint32 guardianSetIndex = 200;
  420. bytes memory data = hex"aaaaaa";
  421. bytes memory signedMessage = signAndEncodeVM(
  422. timestamp,
  423. nonce,
  424. emitterChainId,
  425. emitterAddress,
  426. sequence,
  427. data,
  428. uint256Array(testGuardian),
  429. guardianSetIndex,
  430. consistencyLevel
  431. );
  432. (, bool valid, string memory reason) = proxied
  433. .parseAndVerifyVM(signedMessage);
  434. assertEq(valid, false, "Signed vaa shouldn't be valid");
  435. assertEq(reason, "invalid guardian set", "Wrong reason");
  436. }
  437. function testShouldRevertOnVMsWithDuplicateNonMonotonicSignatureIndexes()
  438. public
  439. {
  440. uint32 timestamp = 1000;
  441. uint32 nonce = 1001;
  442. uint16 emitterChainId = 11;
  443. bytes32 emitterAddress = 0x0000000000000000000000000000000000000000000000000000000000000eee;
  444. uint64 sequence = 0;
  445. uint8 consistencyLevel = 2;
  446. uint32 guardianSetIndex = 0;
  447. bytes memory data = hex"aaaaaa";
  448. uint256[] memory signers = new uint256[](3);
  449. signers[0] = testSigner1;
  450. signers[1] = testSigner2;
  451. signers[2] = testSigner3;
  452. bytes memory signedMessage = signAndEncodeVMFixedIndex(
  453. timestamp,
  454. nonce,
  455. emitterChainId,
  456. emitterAddress,
  457. sequence,
  458. data,
  459. signers,
  460. guardianSetIndex,
  461. consistencyLevel
  462. );
  463. vm.expectRevert("signature indices must be ascending");
  464. proxied.parseAndVerifyVM(signedMessage);
  465. }
  466. function testShouldSetAndEnforceFees() public {
  467. uint32 timestamp = 1000;
  468. uint32 nonce = 1001;
  469. uint256 messageFee = 1111;
  470. bytes memory data = abi.encodePacked(
  471. core,
  472. actionMessageFee,
  473. testChainId,
  474. messageFee
  475. );
  476. bytes memory vaa = signAndEncodeVM(
  477. timestamp,
  478. nonce,
  479. governanceChainId,
  480. governanceContract,
  481. 0,
  482. data,
  483. uint256Array(testGuardian),
  484. 0,
  485. 2
  486. );
  487. uint256 before = proxied.messageFee();
  488. proxied.submitSetMessageFee(vaa);
  489. uint256 afterSettingFee = proxied.messageFee();
  490. assertTrue(before != afterSettingFee, "message fee did not update");
  491. assertEq(afterSettingFee, messageFee, "wrong message fee");
  492. }
  493. function testShouldTransferOutCollectedFees() public {
  494. address receiver = address(0x1234123412341234123412341234123412341234);
  495. uint32 timestamp = 1000;
  496. uint32 nonce = 1001;
  497. uint256 amount = 11;
  498. vm.deal(address(proxied), amount);
  499. bytes memory data = abi.encodePacked(
  500. core,
  501. actionTransferFee,
  502. testChainId,
  503. amount,
  504. addressToBytes32(receiver)
  505. );
  506. bytes memory vaa = signAndEncodeVM(
  507. timestamp,
  508. nonce,
  509. governanceChainId,
  510. governanceContract,
  511. 0,
  512. data,
  513. uint256Array(testGuardian),
  514. 0,
  515. 2
  516. );
  517. uint256 receiverBefore = receiver.balance;
  518. uint256 whBefore = address(proxied).balance;
  519. proxied.submitTransferFees(vaa);
  520. uint256 receiverAfter = receiver.balance;
  521. uint256 whAfter = address(proxied).balance;
  522. assertEq(
  523. receiverAfter - receiverBefore,
  524. amount,
  525. "Receiver balance didn't change correctly"
  526. );
  527. assertEq(
  528. whBefore - whAfter,
  529. amount,
  530. "WH Core balance didn't change correctly"
  531. );
  532. }
  533. function testShouldRevertWhenSubmittingANewGuardianSetWithTheZeroAddress()
  534. public
  535. {
  536. uint32 timestamp = 1000;
  537. uint32 nonce = 1001;
  538. address zeroAddress = address(0x0);
  539. uint32 oldGuardianSetIndex = proxied.getCurrentGuardianSetIndex();
  540. bytes memory data = abi.encodePacked(
  541. core,
  542. actionGuardianSetUpgrade,
  543. testChainId,
  544. oldGuardianSetIndex + 1,
  545. uint8(3),
  546. vm.addr(testSigner1),
  547. vm.addr(testSigner2),
  548. zeroAddress
  549. );
  550. bytes memory vaa = signAndEncodeVM(
  551. timestamp,
  552. nonce,
  553. governanceChainId,
  554. governanceContract,
  555. 0,
  556. data,
  557. uint256Array(testGuardian),
  558. 0,
  559. 2
  560. );
  561. vm.expectRevert("Invalid key");
  562. proxied.submitNewGuardianSet(vaa);
  563. }
  564. function testShouldAcceptANewGuardianSet() public {
  565. uint32 timestamp = 1000;
  566. uint32 nonce = 1001;
  567. uint32 oldGuardianSetIndex = proxied.getCurrentGuardianSetIndex();
  568. bytes memory data = abi.encodePacked(
  569. core,
  570. actionGuardianSetUpgrade,
  571. testChainId,
  572. oldGuardianSetIndex + 1,
  573. uint8(3),
  574. vm.addr(testSigner1),
  575. vm.addr(testSigner2),
  576. vm.addr(testSigner3)
  577. );
  578. bytes memory vaa = signAndEncodeVM(
  579. timestamp,
  580. nonce,
  581. governanceChainId,
  582. governanceContract,
  583. 0,
  584. data,
  585. uint256Array(testGuardian),
  586. 0,
  587. 2
  588. );
  589. proxied.submitNewGuardianSet(vaa);
  590. uint32 newIndex = proxied.getCurrentGuardianSetIndex();
  591. assertEq(
  592. oldGuardianSetIndex + 1,
  593. newIndex,
  594. "New index is one more than old index"
  595. );
  596. IWormhole.GuardianSet memory guardianSet = proxied.getGuardianSet(
  597. newIndex
  598. );
  599. assertEq(guardianSet.expirationTime, 0, "Wrong expiration time");
  600. assertEq(guardianSet.keys[0], vm.addr(testSigner1), "Wrong guardian");
  601. assertEq(guardianSet.keys[1], vm.addr(testSigner2), "Wrong guardian");
  602. assertEq(guardianSet.keys[2], vm.addr(testSigner3), "Wrong guardian");
  603. IWormhole.GuardianSet memory oldGuardianSet = proxied.getGuardianSet(
  604. oldGuardianSetIndex
  605. );
  606. assertTrue(
  607. (oldGuardianSet.expirationTime > block.timestamp + 86000) &&
  608. (oldGuardianSet.expirationTime < block.timestamp + 88000),
  609. "Wrong expiration time"
  610. );
  611. assertEq(
  612. oldGuardianSet.keys[0],
  613. vm.addr(testGuardian),
  614. "Wrong guardian"
  615. );
  616. }
  617. function testShouldAcceptSmartContractUpgrades() public {
  618. uint32 timestamp = 1000;
  619. uint32 nonce = 1001;
  620. MockImplementation mock = new MockImplementation();
  621. bytes memory data = abi.encodePacked(
  622. core,
  623. actionContractUpgrade,
  624. testChainId,
  625. addressToBytes32(address(mock))
  626. );
  627. bytes memory vaa = signAndEncodeVM(
  628. timestamp,
  629. nonce,
  630. governanceChainId,
  631. governanceContract,
  632. 0,
  633. data,
  634. uint256Array(testGuardian),
  635. 0,
  636. 2
  637. );
  638. bytes32 IMPLEMENTATION_STORAGE_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
  639. proxied.submitContractUpgrade(vaa);
  640. bytes32 afterUpgrade = vm.load(
  641. address(proxied),
  642. IMPLEMENTATION_STORAGE_SLOT
  643. );
  644. assertEq(afterUpgrade, addressToBytes32(address(mock)));
  645. assertEq(
  646. MockImplementation(payable(address(proxied)))
  647. .testNewImplementationActive(),
  648. true,
  649. "New implementation not active"
  650. );
  651. }
  652. function testShouldRevertRecoverChainIDGovernancePacketsOnCanonicalChainsNonFork()
  653. public
  654. {
  655. uint32 timestamp = 1000;
  656. uint32 nonce = 1001;
  657. bytes memory data = abi.encodePacked(
  658. core,
  659. actionRecoverChainId,
  660. testEvmChainId,
  661. testChainId
  662. );
  663. bytes memory vaa = signAndEncodeVM(
  664. timestamp,
  665. nonce,
  666. governanceChainId,
  667. governanceContract,
  668. 0,
  669. data,
  670. uint256Array(testGuardian),
  671. 0,
  672. 2
  673. );
  674. vm.expectRevert("not a fork");
  675. proxied.submitRecoverChainId(vaa);
  676. }
  677. function testShouldRevertGovernancePacketsFromOldGuardianSet() public {
  678. uint32 timestamp = 1000;
  679. uint32 nonce = 1001;
  680. // upgrade guardian set
  681. bytes memory data = abi.encodePacked(
  682. core,
  683. actionGuardianSetUpgrade,
  684. testChainId,
  685. uint32(1),
  686. uint8(3),
  687. vm.addr(testSigner1),
  688. vm.addr(testSigner2),
  689. vm.addr(testSigner3)
  690. );
  691. bytes memory vaa = signAndEncodeVM(
  692. timestamp,
  693. nonce,
  694. governanceChainId,
  695. governanceContract,
  696. 0,
  697. data,
  698. uint256Array(testGuardian),
  699. 0,
  700. 2
  701. );
  702. proxied.submitNewGuardianSet(vaa);
  703. data = abi.encodePacked(
  704. core,
  705. actionTransferFee,
  706. testChainId,
  707. uint256(1),
  708. address(0)
  709. );
  710. vaa = signAndEncodeVM(
  711. timestamp,
  712. nonce,
  713. governanceChainId,
  714. governanceContract,
  715. 0,
  716. data,
  717. uint256Array(testGuardian),
  718. 0,
  719. 2
  720. );
  721. vm.expectRevert("not signed by current guardian set");
  722. proxied.submitTransferFees(vaa);
  723. }
  724. function testShouldTimeOutOldGuardians() public {
  725. uint32 timestamp = 1000;
  726. uint32 nonce = 1001;
  727. // upgrade guardian set
  728. bytes memory data = abi.encodePacked(
  729. core,
  730. actionGuardianSetUpgrade,
  731. testChainId,
  732. uint32(1),
  733. uint8(3),
  734. vm.addr(testSigner1),
  735. vm.addr(testSigner2),
  736. vm.addr(testSigner3)
  737. );
  738. bytes memory vaa = signAndEncodeVM(
  739. timestamp,
  740. nonce,
  741. governanceChainId,
  742. governanceContract,
  743. 0,
  744. data,
  745. uint256Array(testGuardian),
  746. 0,
  747. 2
  748. );
  749. proxied.submitNewGuardianSet(vaa);
  750. data = hex"aaaaaa";
  751. vaa = signAndEncodeVM(
  752. timestamp,
  753. nonce,
  754. governanceChainId,
  755. governanceContract,
  756. 0,
  757. data,
  758. uint256Array(testGuardian),
  759. 0,
  760. 2
  761. );
  762. (, bool valid, ) = proxied.parseAndVerifyVM(vaa);
  763. assertEq(valid, true, "Vaa should be valid");
  764. skip(100000);
  765. (, valid, ) = proxied.parseAndVerifyVM(vaa);
  766. assertEq(valid, false, "Vaa should be expired");
  767. }
  768. function testShouldRevertGovernancePacketsFromWrongGovernanceChain()
  769. public
  770. {
  771. uint32 timestamp = 1000;
  772. uint32 nonce = 1001;
  773. bytes memory data = abi.encodePacked(
  774. core,
  775. actionTransferFee,
  776. testChainId,
  777. uint256(1),
  778. address(0)
  779. );
  780. bytes memory vaa = signAndEncodeVM(
  781. timestamp,
  782. nonce,
  783. 999,
  784. governanceContract,
  785. 0,
  786. data,
  787. uint256Array(testGuardian),
  788. 0,
  789. 2
  790. );
  791. vm.expectRevert("wrong governance chain");
  792. proxied.submitTransferFees(vaa);
  793. }
  794. function testShouldRevertGovernancePacketsFromWrongGovernanceContract()
  795. public
  796. {
  797. uint32 timestamp = 1000;
  798. uint32 nonce = 1001;
  799. bytes memory data = abi.encodePacked(
  800. core,
  801. actionTransferFee,
  802. testChainId,
  803. uint256(1),
  804. address(0)
  805. );
  806. bytes memory vaa = signAndEncodeVM(
  807. timestamp,
  808. nonce,
  809. governanceChainId,
  810. core,
  811. 0,
  812. data,
  813. uint256Array(testGuardian),
  814. 0,
  815. 2
  816. );
  817. vm.expectRevert("wrong governance contract");
  818. proxied.submitTransferFees(vaa);
  819. }
  820. function testShouldRevertGovernancePacketsThatAlreadyHaveBeenApplied()
  821. public
  822. {
  823. uint32 timestamp = 1000;
  824. uint32 nonce = 1001;
  825. uint256 amount = 1;
  826. vm.deal(address(proxied), amount);
  827. bytes memory data = abi.encodePacked(
  828. core,
  829. actionTransferFee,
  830. testChainId,
  831. amount,
  832. addressToBytes32(address(0))
  833. );
  834. bytes memory vaa = signAndEncodeVM(
  835. timestamp,
  836. nonce,
  837. governanceChainId,
  838. governanceContract,
  839. 0,
  840. data,
  841. uint256Array(testGuardian),
  842. 0,
  843. 2
  844. );
  845. proxied.submitTransferFees(vaa);
  846. vm.expectRevert("governance action already consumed");
  847. proxied.submitTransferFees(vaa);
  848. }
  849. function addressToBytes32(address input) internal pure returns (bytes32 output) {
  850. return bytes32(uint256(uint160(input)));
  851. }
  852. function testShouldRejectSmartContractUpgradesOnForks() public {
  853. uint32 timestamp = 1000;
  854. uint32 nonce = 1001;
  855. // Perform a successful upgrade
  856. MockImplementation mock = new MockImplementation();
  857. bytes memory data = abi.encodePacked(
  858. core,
  859. actionContractUpgrade,
  860. testChainId,
  861. addressToBytes32(address(mock))
  862. );
  863. bytes memory vaa = signAndEncodeVM(
  864. timestamp,
  865. nonce,
  866. governanceChainId,
  867. governanceContract,
  868. 0,
  869. data,
  870. uint256Array(testGuardian),
  871. 0,
  872. 2
  873. );
  874. bytes32 IMPLEMENTATION_STORAGE_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
  875. proxied.submitContractUpgrade(vaa);
  876. bytes32 afterUpgrade = vm.load(
  877. address(proxied),
  878. IMPLEMENTATION_STORAGE_SLOT
  879. );
  880. assertEq(afterUpgrade, addressToBytes32(address(mock)));
  881. assertEq(
  882. MockImplementation(payable(address(proxied)))
  883. .testNewImplementationActive(),
  884. true,
  885. "New implementation not active"
  886. );
  887. // Overwrite EVM Chain ID
  888. MockImplementation(payable(address(proxied))).testOverwriteEVMChainId(
  889. fakeChainId,
  890. fakeEvmChainId
  891. );
  892. assertEq(
  893. proxied.chainId(),
  894. fakeChainId,
  895. "Overwrite didn't work for chain ID"
  896. );
  897. assertEq(
  898. proxied.evmChainId(),
  899. fakeEvmChainId,
  900. "Overwrite didn't work for evm chain ID"
  901. );
  902. data = abi.encodePacked(
  903. core,
  904. actionContractUpgrade,
  905. testChainId,
  906. addressToBytes32(address(mock))
  907. );
  908. vaa = signAndEncodeVM(
  909. timestamp,
  910. nonce,
  911. governanceChainId,
  912. governanceContract,
  913. 0,
  914. data,
  915. uint256Array(testGuardian),
  916. 0,
  917. 2
  918. );
  919. vm.expectRevert("invalid fork");
  920. proxied.submitContractUpgrade(vaa);
  921. }
  922. function testShouldAllowRecoverChainIDGovernancePacketsForks() public {
  923. uint32 timestamp = 1000;
  924. uint32 nonce = 1001;
  925. // Perform a successful upgrade
  926. MockImplementation mock = new MockImplementation();
  927. bytes memory data = abi.encodePacked(
  928. core,
  929. actionContractUpgrade,
  930. testChainId,
  931. addressToBytes32(address(mock))
  932. );
  933. bytes memory vaa = signAndEncodeVM(
  934. timestamp,
  935. nonce,
  936. governanceChainId,
  937. governanceContract,
  938. 0,
  939. data,
  940. uint256Array(testGuardian),
  941. 0,
  942. 2
  943. );
  944. bytes32 IMPLEMENTATION_STORAGE_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
  945. proxied.submitContractUpgrade(vaa);
  946. bytes32 afterUpgrade = vm.load(
  947. address(proxied),
  948. IMPLEMENTATION_STORAGE_SLOT
  949. );
  950. assertEq(afterUpgrade, addressToBytes32(address(mock)));
  951. assertEq(
  952. MockImplementation(payable(address(proxied)))
  953. .testNewImplementationActive(),
  954. true,
  955. "New implementation not active"
  956. );
  957. // Overwrite EVM Chain ID
  958. MockImplementation(payable(address(proxied))).testOverwriteEVMChainId(
  959. fakeChainId,
  960. fakeEvmChainId
  961. );
  962. assertEq(
  963. proxied.chainId(),
  964. fakeChainId,
  965. "Overwrite didn't work for chain ID"
  966. );
  967. assertEq(
  968. proxied.evmChainId(),
  969. fakeEvmChainId,
  970. "Overwrite didn't work for evm chain ID"
  971. );
  972. // recover chain ID
  973. data = abi.encodePacked(
  974. core,
  975. actionRecoverChainId,
  976. testEvmChainId,
  977. testChainId
  978. );
  979. vaa = signAndEncodeVM(
  980. timestamp,
  981. nonce,
  982. governanceChainId,
  983. governanceContract,
  984. 0,
  985. data,
  986. uint256Array(testGuardian),
  987. 0,
  988. 2
  989. );
  990. proxied.submitRecoverChainId(vaa);
  991. assertEq(
  992. proxied.chainId(),
  993. testChainId,
  994. "Recover didn't work for chain ID"
  995. );
  996. assertEq(
  997. proxied.evmChainId(),
  998. testEvmChainId,
  999. "Recover didn't work for evm chain ID"
  1000. );
  1001. }
  1002. function testShouldAcceptSmartContractUpgradesAfterChainIdHasBeenRecovered()
  1003. public
  1004. {
  1005. uint32 timestamp = 1000;
  1006. uint32 nonce = 1001;
  1007. // Perform a successful upgrade
  1008. MockImplementation mock = new MockImplementation();
  1009. bytes memory data = abi.encodePacked(
  1010. core,
  1011. actionContractUpgrade,
  1012. testChainId,
  1013. addressToBytes32(address(mock))
  1014. );
  1015. bytes memory vaa = signAndEncodeVM(
  1016. timestamp,
  1017. nonce,
  1018. governanceChainId,
  1019. governanceContract,
  1020. 0,
  1021. data,
  1022. uint256Array(testGuardian),
  1023. 0,
  1024. 2
  1025. );
  1026. bytes32 IMPLEMENTATION_STORAGE_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
  1027. bytes32 before = vm.load(address(proxied), IMPLEMENTATION_STORAGE_SLOT);
  1028. proxied.submitContractUpgrade(vaa);
  1029. bytes32 afterUpgrade = vm.load(
  1030. address(proxied),
  1031. IMPLEMENTATION_STORAGE_SLOT
  1032. );
  1033. assertEq(afterUpgrade, addressToBytes32(address(mock)));
  1034. assertEq(
  1035. MockImplementation(payable(address(proxied)))
  1036. .testNewImplementationActive(),
  1037. true,
  1038. "New implementation not active"
  1039. );
  1040. // Overwrite EVM Chain ID
  1041. MockImplementation(payable(address(proxied))).testOverwriteEVMChainId(
  1042. fakeChainId,
  1043. fakeEvmChainId
  1044. );
  1045. assertEq(
  1046. proxied.chainId(),
  1047. fakeChainId,
  1048. "Overwrite didn't work for chain ID"
  1049. );
  1050. assertEq(
  1051. proxied.evmChainId(),
  1052. fakeEvmChainId,
  1053. "Overwrite didn't work for evm chain ID"
  1054. );
  1055. // recover chain ID
  1056. data = abi.encodePacked(
  1057. core,
  1058. actionRecoverChainId,
  1059. testEvmChainId,
  1060. testChainId
  1061. );
  1062. vaa = signAndEncodeVM(
  1063. timestamp,
  1064. nonce,
  1065. governanceChainId,
  1066. governanceContract,
  1067. 0,
  1068. data,
  1069. uint256Array(testGuardian),
  1070. 0,
  1071. 2
  1072. );
  1073. proxied.submitRecoverChainId(vaa);
  1074. assertEq(
  1075. proxied.chainId(),
  1076. testChainId,
  1077. "Recover didn't work for chain ID"
  1078. );
  1079. assertEq(
  1080. proxied.evmChainId(),
  1081. testEvmChainId,
  1082. "Recover didn't work for evm chain ID"
  1083. );
  1084. // Perform a successful upgrade
  1085. mock = new MockImplementation();
  1086. data = abi.encodePacked(
  1087. core,
  1088. actionContractUpgrade,
  1089. testChainId,
  1090. addressToBytes32(address(mock))
  1091. );
  1092. vaa = signAndEncodeVM(
  1093. timestamp,
  1094. nonce,
  1095. governanceChainId,
  1096. governanceContract,
  1097. 0,
  1098. data,
  1099. uint256Array(testGuardian),
  1100. 0,
  1101. 2
  1102. );
  1103. before = vm.load(address(proxied), IMPLEMENTATION_STORAGE_SLOT);
  1104. proxied.submitContractUpgrade(vaa);
  1105. afterUpgrade = vm.load(address(proxied), IMPLEMENTATION_STORAGE_SLOT);
  1106. assertEq(afterUpgrade, addressToBytes32(address(mock)));
  1107. assertEq(
  1108. MockImplementation(payable(address(proxied)))
  1109. .testNewImplementationActive(),
  1110. true,
  1111. "New implementation not active"
  1112. );
  1113. }
  1114. }