github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/test/invariants/Burn.Gas.t.sol (about)

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity 0.8.15;
     3  
     4  import { StdUtils } from "forge-std/StdUtils.sol";
     5  import { Test } from "forge-std/Test.sol";
     6  import { Vm } from "forge-std/Vm.sol";
     7  
     8  import { StdInvariant } from "forge-std/StdInvariant.sol";
     9  import { Burn } from "src/libraries/Burn.sol";
    10  import { InvariantTest } from "test/invariants/InvariantTest.sol";
    11  
    12  contract Burn_GasBurner is StdUtils {
    13      Vm internal vm;
    14      bool public failedGasBurn;
    15  
    16      constructor(Vm _vm) {
    17          vm = _vm;
    18      }
    19  
    20      /// @notice Takes an integer amount of gas to burn through the Burn library and
    21      ///         updates the contract state if at least that amount of gas was not burned
    22      ///         by the library
    23      function burnGas(uint256 _value) external {
    24          // cap the value to the max resource limit
    25          uint256 MAX_RESOURCE_LIMIT = 8_000_000;
    26          uint256 value = bound(_value, 0, MAX_RESOURCE_LIMIT);
    27  
    28          // cache the contract's current remaining gas
    29          uint256 preBurnGas = gasleft();
    30  
    31          // execute the gas burn
    32          Burn.gas(value);
    33  
    34          // cache the remaining gas post burn
    35          uint256 postBurnGas = gasleft();
    36  
    37          // check that at least value gas was burnt (and that there was no underflow)
    38          unchecked {
    39              if (postBurnGas - preBurnGas <= value && preBurnGas - value > preBurnGas) {
    40                  failedGasBurn = true;
    41              }
    42          }
    43      }
    44  }
    45  
    46  contract Burn_BurnGas_Invariant is StdInvariant, InvariantTest {
    47      Burn_GasBurner internal actor;
    48  
    49      function setUp() public override {
    50          super.setUp();
    51          // Create a gas burner actor.
    52          actor = new Burn_GasBurner(vm);
    53  
    54          targetContract(address(actor));
    55  
    56          bytes4[] memory selectors = new bytes4[](1);
    57          selectors[0] = actor.burnGas.selector;
    58          FuzzSelector memory selector = FuzzSelector({ addr: address(actor), selectors: selectors });
    59          targetSelector(selector);
    60      }
    61  
    62      /// @custom:invariant `gas(uint256)` always burns at least the amount of gas passed.
    63      ///
    64      ///                   Asserts that when `Burn.gas(uint256)` is called, it always burns
    65      ///                   at least the amount of gas passed to the function.
    66      function invariant_burn_gas() external {
    67          // ASSERTION: The amount burned should always match the amount passed exactly
    68          assertEq(actor.failedGasBurn(), false);
    69      }
    70  }