github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/test/invariants/Encoding.t.sol (about) 1 // SPDX-License-Identifier: MIT 2 pragma solidity 0.8.15; 3 4 import { Test } from "forge-std/Test.sol"; 5 import { StdInvariant } from "forge-std/StdInvariant.sol"; 6 import { Encoding } from "src/libraries/Encoding.sol"; 7 import { InvariantTest } from "test/invariants/InvariantTest.sol"; 8 9 contract Encoding_Converter { 10 bool public failedRoundtripAToB; 11 bool public failedRoundtripBToA; 12 13 /// @notice Takes a pair of integers to be encoded into a versioned nonce with the 14 /// Encoding library and then decoded and updates the test contract's state 15 /// indicating if the round trip encoding failed. 16 function convertRoundTripAToB(uint240 _nonce, uint16 _version) external { 17 // Encode the nonce and version 18 uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(_nonce, _version); 19 20 // Decode the nonce and version 21 uint240 decodedNonce; 22 uint16 decodedVersion; 23 24 (decodedNonce, decodedVersion) = Encoding.decodeVersionedNonce(encodedVersionedNonce); 25 26 // If our round trip encoding did not return the original result, set our state. 27 if ((decodedNonce != _nonce) || (decodedVersion != _version)) { 28 failedRoundtripAToB = true; 29 } 30 } 31 32 /// @notice Takes an integer representing a packed version and nonce and attempts 33 /// to decode them using the Encoding library before re-encoding and updates 34 /// the test contract's state indicating if the round trip encoding failed. 35 function convertRoundTripBToA(uint256 _versionedNonce) external { 36 // Decode the nonce and version 37 uint240 decodedNonce; 38 uint16 decodedVersion; 39 40 (decodedNonce, decodedVersion) = Encoding.decodeVersionedNonce(_versionedNonce); 41 42 // Encode the nonce and version 43 uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(decodedNonce, decodedVersion); 44 45 // If our round trip encoding did not return the original result, set our state. 46 if (encodedVersionedNonce != _versionedNonce) { 47 failedRoundtripBToA = true; 48 } 49 } 50 } 51 52 contract Encoding_Invariant is StdInvariant, InvariantTest { 53 Encoding_Converter internal actor; 54 55 function setUp() public override { 56 super.setUp(); 57 // Create a converter actor. 58 actor = new Encoding_Converter(); 59 60 targetContract(address(actor)); 61 62 bytes4[] memory selectors = new bytes4[](2); 63 selectors[0] = actor.convertRoundTripAToB.selector; 64 selectors[1] = actor.convertRoundTripBToA.selector; 65 FuzzSelector memory selector = FuzzSelector({ addr: address(actor), selectors: selectors }); 66 targetSelector(selector); 67 } 68 69 /// @custom:invariant `convertRoundTripAToB` never fails. 70 /// 71 /// Asserts that a raw versioned nonce can be encoded / decoded 72 /// to reach the same raw value. 73 function invariant_round_trip_encoding_AToB() external { 74 // ASSERTION: The round trip encoding done in testRoundTripAToB(...) 75 assertEq(actor.failedRoundtripAToB(), false); 76 } 77 78 /// @custom:invariant `convertRoundTripBToA` never fails. 79 /// 80 /// Asserts that an encoded versioned nonce can always be decoded / 81 /// re-encoded to reach the same encoded value. 82 function invariant_round_trip_encoding_BToA() external { 83 // ASSERTION: The round trip encoding done in testRoundTripBToA should never 84 // fail. 85 assertEq(actor.failedRoundtripBToA(), false); 86 } 87 }