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 }