Commit a0ff1cc9 authored by Andreas Bigger's avatar Andreas Bigger

Port all remaining test files to triple slash natspec styling.

parent 3c0e8a98
...@@ -5,9 +5,7 @@ import { Test } from "forge-std/Test.sol"; ...@@ -5,9 +5,7 @@ import { Test } from "forge-std/Test.sol";
import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol"; import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol";
contract AddressAliasHelper_applyAndUndo_Test is Test { contract AddressAliasHelper_applyAndUndo_Test is Test {
/** /// @notice Tests that applying and then undoing an alias results in the original address.
* @notice Tests that applying and then undoing an alias results in the original address.
*/
function testFuzz_applyAndUndo_succeeds(address _address) external { function testFuzz_applyAndUndo_succeeds(address _address) external {
address aliased = AddressAliasHelper.applyL1ToL2Alias(_address); address aliased = AddressAliasHelper.applyL1ToL2Alias(_address);
address unaliased = AddressAliasHelper.undoL1ToL2Alias(aliased); address unaliased = AddressAliasHelper.undoL1ToL2Alias(aliased);
......
//SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol"; import { Test } from "forge-std/Test.sol";
...@@ -6,41 +6,32 @@ import { AdminFaucetAuthModule } from "../periphery/faucet/authmodules/AdminFauc ...@@ -6,41 +6,32 @@ import { AdminFaucetAuthModule } from "../periphery/faucet/authmodules/AdminFauc
import { Faucet } from "../periphery/faucet/Faucet.sol"; import { Faucet } from "../periphery/faucet/Faucet.sol";
import { FaucetHelper } from "./Helpers.sol"; import { FaucetHelper } from "./Helpers.sol";
/** /// @title AdminFaucetAuthModuleTest
* @title AdminFaucetAuthModuleTest /// @notice Tests the AdminFaucetAuthModule contract.
* @notice Tests the AdminFaucetAuthModule contract.
*/
contract AdminFaucetAuthModuleTest is Test { contract AdminFaucetAuthModuleTest is Test {
/** /// @notice The admin of the `AdminFaucetAuthModule` contract.
* @notice The admin of the `AdminFaucetAuthModule` contract.
*/
address internal admin; address internal admin;
/**
* @notice Private key of the `admin`. /// @notice Private key of the `admin`.
*/
uint256 internal adminKey; uint256 internal adminKey;
/**
* @notice Not an admin of the `AdminFaucetAuthModule` contract. /// @notice Not an admin of the `AdminFaucetAuthModule` contract.
*/
address internal nonAdmin; address internal nonAdmin;
/**
* @notice Private key of the `nonAdmin`. /// @notice Private key of the `nonAdmin`.
*/
uint256 internal nonAdminKey; uint256 internal nonAdminKey;
/**
* @notice An instance of the `AdminFaucetAuthModule` contract. /// @notice An instance of the `AdminFaucetAuthModule` contract.
*/
AdminFaucetAuthModule internal adminFam; AdminFaucetAuthModule internal adminFam;
/**
* @notice An instance of the `FaucetHelper` contract. /// @notice An instance of the `FaucetHelper` contract.
*/
FaucetHelper internal faucetHelper; FaucetHelper internal faucetHelper;
string internal adminFamName = "AdminFAM"; string internal adminFamName = "AdminFAM";
string internal adminFamVersion = "1"; string internal adminFamVersion = "1";
/** /// @notice Deploy the `AdminFaucetAuthModule` contract.
* @notice Deploy the `AdminFaucetAuthModule` contract.
*/
function setUp() external { function setUp() external {
adminKey = 0xB0B0B0B0; adminKey = 0xB0B0B0B0;
admin = vm.addr(adminKey); admin = vm.addr(adminKey);
...@@ -53,10 +44,7 @@ contract AdminFaucetAuthModuleTest is Test { ...@@ -53,10 +44,7 @@ contract AdminFaucetAuthModuleTest is Test {
faucetHelper = new FaucetHelper(); faucetHelper = new FaucetHelper();
} }
/** /// @notice Get signature as a bytes blob.
* @notice Get signature as a bytes blob.
*
*/
function _getSignature(uint256 _signingPrivateKey, bytes32 _digest) function _getSignature(uint256 _signingPrivateKey, bytes32 _digest)
internal internal
pure pure
...@@ -68,11 +56,9 @@ contract AdminFaucetAuthModuleTest is Test { ...@@ -68,11 +56,9 @@ contract AdminFaucetAuthModuleTest is Test {
return signature; return signature;
} }
/** /// @notice Signs a proof with the given private key and returns the signature using
* @notice Signs a proof with the given private key and returns the signature using /// the given EIP712 domain separator. This assumes that the issuer's address is the
* the given EIP712 domain separator. This assumes that the issuer's address is the /// corresponding public key to _issuerPrivateKey.
* corresponding public key to _issuerPrivateKey.
*/
function issueProofWithEIP712Domain( function issueProofWithEIP712Domain(
uint256 _issuerPrivateKey, uint256 _issuerPrivateKey,
bytes memory _eip712Name, bytes memory _eip712Name,
...@@ -101,9 +87,7 @@ contract AdminFaucetAuthModuleTest is Test { ...@@ -101,9 +87,7 @@ contract AdminFaucetAuthModuleTest is Test {
); );
} }
/** /// @notice Assert that verify returns true for valid proofs signed by admins.
* @notice assert that verify returns true for valid proofs signed by admins.
*/
function test_adminProof_verify_succeeds() external { function test_adminProof_verify_succeeds() external {
bytes32 nonce = faucetHelper.consumeNonce(); bytes32 nonce = faucetHelper.consumeNonce();
address fundsReceiver = makeAddr("fundsReceiver"); address fundsReceiver = makeAddr("fundsReceiver");
...@@ -129,9 +113,7 @@ contract AdminFaucetAuthModuleTest is Test { ...@@ -129,9 +113,7 @@ contract AdminFaucetAuthModuleTest is Test {
); );
} }
/** /// @notice Assert that verify returns false for proofs signed by nonadmins.
* @notice assert that verify returns false for proofs signed by nonadmins.
*/
function test_nonAdminProof_verify_succeeds() external { function test_nonAdminProof_verify_succeeds() external {
bytes32 nonce = faucetHelper.consumeNonce(); bytes32 nonce = faucetHelper.consumeNonce();
address fundsReceiver = makeAddr("fundsReceiver"); address fundsReceiver = makeAddr("fundsReceiver");
...@@ -157,10 +139,8 @@ contract AdminFaucetAuthModuleTest is Test { ...@@ -157,10 +139,8 @@ contract AdminFaucetAuthModuleTest is Test {
); );
} }
/** /// @notice Assert that verify returns false for proofs where the id in the proof is different
* @notice assert that verify returns false for proofs where the id in the proof is different /// than the id in the call to verify.
* than the id in the call to verify.
*/
function test_proofWithWrongId_verify_succeeds() external { function test_proofWithWrongId_verify_succeeds() external {
bytes32 nonce = faucetHelper.consumeNonce(); bytes32 nonce = faucetHelper.consumeNonce();
address fundsReceiver = makeAddr("fundsReceiver"); address fundsReceiver = makeAddr("fundsReceiver");
......
//SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
/* Testing utilities */ // Testing utilities
import { Test } from "forge-std/Test.sol"; import { Test } from "forge-std/Test.sol";
import { TestERC20 } from "./Helpers.sol"; import { TestERC20 } from "./Helpers.sol";
import { TestERC721 } from "./Helpers.sol"; import { TestERC721 } from "./Helpers.sol";
...@@ -53,12 +53,12 @@ contract AssetReceiver_Initializer is Test { ...@@ -53,12 +53,12 @@ contract AssetReceiver_Initializer is Test {
} }
contract AssetReceiverTest is AssetReceiver_Initializer { contract AssetReceiverTest is AssetReceiver_Initializer {
// Tests if the owner was set correctly during deploy /// @notice Tests if the owner was set correctly during deploy.
function test_constructor_succeeds() external { function test_constructor_succeeds() external {
assertEq(address(alice), assetReceiver.owner()); assertEq(address(alice), assetReceiver.owner());
} }
// Tests that receive works as inteded /// @notice Tests that receive works as inteded.
function test_receive_succeeds() external { function test_receive_succeeds() external {
// Check that contract balance is 0 initially // Check that contract balance is 0 initially
assertEq(address(assetReceiver).balance, 0); assertEq(address(assetReceiver).balance, 0);
...@@ -74,7 +74,8 @@ contract AssetReceiverTest is AssetReceiver_Initializer { ...@@ -74,7 +74,8 @@ contract AssetReceiverTest is AssetReceiver_Initializer {
assertEq(address(assetReceiver).balance, 100); assertEq(address(assetReceiver).balance, 100);
} }
// Tests withdrawETH function with only an address as argument, called by owner /// @notice Tests withdrawETH function with only an address
/// as an argument, called by owner.
function test_withdrawETH_succeeds() external { function test_withdrawETH_succeeds() external {
// Check contract initial balance // Check contract initial balance
assertEq(address(assetReceiver).balance, 0); assertEq(address(assetReceiver).balance, 0);
...@@ -96,14 +97,14 @@ contract AssetReceiverTest is AssetReceiver_Initializer { ...@@ -96,14 +97,14 @@ contract AssetReceiverTest is AssetReceiver_Initializer {
assertEq(address(alice).balance, 2 ether); assertEq(address(alice).balance, 2 ether);
} }
// withdrawETH should fail if called by non-owner /// @notice withdrawETH should fail if called by non-owner.
function test_withdrawETH_unauthorized_reverts() external { function test_withdrawETH_unauthorized_reverts() external {
vm.deal(address(assetReceiver), 1 ether); vm.deal(address(assetReceiver), 1 ether);
vm.expectRevert("UNAUTHORIZED"); vm.expectRevert("UNAUTHORIZED");
assetReceiver.withdrawETH(payable(alice)); assetReceiver.withdrawETH(payable(alice));
} }
// Similar as withdrawETH but specify amount to withdraw /// @notice Similar as withdrawETH but specify amount to withdraw.
function test_withdrawETHwithAmount_succeeds() external { function test_withdrawETHwithAmount_succeeds() external {
assertEq(address(assetReceiver).balance, 0); assertEq(address(assetReceiver).balance, 0);
...@@ -124,14 +125,14 @@ contract AssetReceiverTest is AssetReceiver_Initializer { ...@@ -124,14 +125,14 @@ contract AssetReceiverTest is AssetReceiver_Initializer {
assertEq(address(alice).balance, 1.5 ether); assertEq(address(alice).balance, 1.5 ether);
} }
// withdrawETH with address and amount as arguments called by non-owner /// @notice withdrawETH with address and amount as arguments called by non-owner.
function test_withdrawETHwithAmount_unauthorized_reverts() external { function test_withdrawETHwithAmount_unauthorized_reverts() external {
vm.deal(address(assetReceiver), 1 ether); vm.deal(address(assetReceiver), 1 ether);
vm.expectRevert("UNAUTHORIZED"); vm.expectRevert("UNAUTHORIZED");
assetReceiver.withdrawETH(payable(alice), 0.5 ether); assetReceiver.withdrawETH(payable(alice), 0.5 ether);
} }
// Test withdrawERC20 with token and address arguments, from owner /// @notice Test withdrawERC20 with token and address arguments, from owner.
function test_withdrawERC20_succeeds() external { function test_withdrawERC20_succeeds() external {
// check balances before the call // check balances before the call
assertEq(testERC20.balanceOf(address(assetReceiver)), 0); assertEq(testERC20.balanceOf(address(assetReceiver)), 0);
...@@ -152,14 +153,14 @@ contract AssetReceiverTest is AssetReceiver_Initializer { ...@@ -152,14 +153,14 @@ contract AssetReceiverTest is AssetReceiver_Initializer {
assertEq(testERC20.balanceOf(address(assetReceiver)), 0); assertEq(testERC20.balanceOf(address(assetReceiver)), 0);
} }
// Same as withdrawERC20 but call from non-owner /// @notice Same as withdrawERC20 but call from non-owner.
function test_withdrawERC20_unauthorized_reverts() external { function test_withdrawERC20_unauthorized_reverts() external {
deal(address(testERC20), address(assetReceiver), 100_000); deal(address(testERC20), address(assetReceiver), 100_000);
vm.expectRevert("UNAUTHORIZED"); vm.expectRevert("UNAUTHORIZED");
assetReceiver.withdrawERC20(testERC20, alice); assetReceiver.withdrawERC20(testERC20, alice);
} }
// Similar as withdrawERC20 but specify amount to withdraw /// @notice Similar as withdrawERC20 but specify amount to withdraw.
function test_withdrawERC20withAmount_succeeds() external { function test_withdrawERC20withAmount_succeeds() external {
// check balances before the call // check balances before the call
assertEq(testERC20.balanceOf(address(assetReceiver)), 0); assertEq(testERC20.balanceOf(address(assetReceiver)), 0);
...@@ -180,14 +181,14 @@ contract AssetReceiverTest is AssetReceiver_Initializer { ...@@ -180,14 +181,14 @@ contract AssetReceiverTest is AssetReceiver_Initializer {
assertEq(testERC20.balanceOf(address(assetReceiver)), 50_000); assertEq(testERC20.balanceOf(address(assetReceiver)), 50_000);
} }
// Similar as withdrawERC20 with amount but call from non-owner /// @notice Similar as withdrawERC20 with amount but call from non-owner.
function test_withdrawERC20withAmount_unauthorized_reverts() external { function test_withdrawERC20withAmount_unauthorized_reverts() external {
deal(address(testERC20), address(assetReceiver), 100_000); deal(address(testERC20), address(assetReceiver), 100_000);
vm.expectRevert("UNAUTHORIZED"); vm.expectRevert("UNAUTHORIZED");
assetReceiver.withdrawERC20(testERC20, alice, 50_000); assetReceiver.withdrawERC20(testERC20, alice, 50_000);
} }
// Test withdrawERC721 from owner /// @notice Test withdrawERC721 from owner.
function test_withdrawERC721_succeeds() external { function test_withdrawERC721_succeeds() external {
// Check owner of the token before calling withdrawERC721 // Check owner of the token before calling withdrawERC721
assertEq(testERC721.ownerOf(DEFAULT_TOKEN_ID), alice); assertEq(testERC721.ownerOf(DEFAULT_TOKEN_ID), alice);
...@@ -208,7 +209,7 @@ contract AssetReceiverTest is AssetReceiver_Initializer { ...@@ -208,7 +209,7 @@ contract AssetReceiverTest is AssetReceiver_Initializer {
assertEq(testERC721.ownerOf(DEFAULT_TOKEN_ID), alice); assertEq(testERC721.ownerOf(DEFAULT_TOKEN_ID), alice);
} }
// Similar as withdrawERC721 but call from non-owner /// @notice Similar as withdrawERC721 but call from non-owner.
function test_withdrawERC721_unauthorized_reverts() external { function test_withdrawERC721_unauthorized_reverts() external {
vm.prank(alice); vm.prank(alice);
testERC721.transferFrom(alice, address(assetReceiver), DEFAULT_TOKEN_ID); testERC721.transferFrom(alice, address(assetReceiver), DEFAULT_TOKEN_ID);
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
/* Testing utilities */ // Testing utilities
import { Test } from "forge-std/Test.sol"; import { Test } from "forge-std/Test.sol";
import { Vm } from "forge-std/Vm.sol"; import { Vm } from "forge-std/Vm.sol";
import "./CommonTest.t.sol"; import "./CommonTest.t.sol";
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
// Testing utilities // Testing utilities
......
//SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol"; import { Test } from "forge-std/Test.sol";
import { CheckBalanceHigh } from "../periphery/drippie/dripchecks/CheckBalanceHigh.sol"; import { CheckBalanceHigh } from "../periphery/drippie/dripchecks/CheckBalanceHigh.sol";
/** /// @title CheckBalanceHighTest
* @title CheckBalanceHighTest /// @notice Tests the CheckBalanceHigh contract via fuzzing both the success case
* @notice Tests the CheckBalanceHigh contract via fuzzing both the success case /// and the failure case.
* and the failure case.
*/
contract CheckBalanceHighTest is Test { contract CheckBalanceHighTest is Test {
/** /// @notice An instance of the CheckBalanceHigh contract.
* @notice An instance of the CheckBalanceHigh contract.
*/
CheckBalanceHigh c; CheckBalanceHigh c;
/** /// @notice Deploy the `CheckTrue` contract.
* @notice Deploy the `CheckTrue` contract.
*/
function setUp() external { function setUp() external {
c = new CheckBalanceHigh(); c = new CheckBalanceHigh();
} }
/** /// @notice Fuzz the `check` function and assert that it always returns true
* @notice Fuzz the `check` function and assert that it always returns true /// when the target's balance is larger than the threshold.
* when the target's balance is larger than the threshold.
*/
function testFuzz_check_succeeds(address _target, uint256 _threshold) external { function testFuzz_check_succeeds(address _target, uint256 _threshold) external {
CheckBalanceHigh.Params memory p = CheckBalanceHigh.Params({ CheckBalanceHigh.Params memory p = CheckBalanceHigh.Params({
target: _target, target: _target,
...@@ -39,10 +31,8 @@ contract CheckBalanceHighTest is Test { ...@@ -39,10 +31,8 @@ contract CheckBalanceHighTest is Test {
assertEq(c.check(abi.encode(p)), true); assertEq(c.check(abi.encode(p)), true);
} }
/** /// @notice Fuzz the `check` function and assert that it always returns false
* @notice Fuzz the `check` function and assert that it always returns false /// when the target's balance is smaller than the threshold.
* when the target's balance is smaller than the threshold.
*/
function testFuzz_check_lowBalance_fails(address _target, uint256 _threshold) external { function testFuzz_check_lowBalance_fails(address _target, uint256 _threshold) external {
CheckBalanceHigh.Params memory p = CheckBalanceHigh.Params({ CheckBalanceHigh.Params memory p = CheckBalanceHigh.Params({
target: _target, target: _target,
......
//SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol"; import { Test } from "forge-std/Test.sol";
import { CheckBalanceLow } from "../periphery/drippie/dripchecks/CheckBalanceLow.sol"; import { CheckBalanceLow } from "../periphery/drippie/dripchecks/CheckBalanceLow.sol";
/** /// @title CheckBalanceLowTest
* @title CheckBalanceLowTest /// @notice Tests the CheckBalanceLow contract via fuzzing both the success case
* @notice Tests the CheckBalanceLow contract via fuzzing both the success case /// and the failure case.
* and the failure case.
*/
contract CheckBalanceLowTest is Test { contract CheckBalanceLowTest is Test {
/** /// @notice An instance of the CheckBalanceLow contract.
* @notice An instance of the CheckBalanceLow contract.
*/
CheckBalanceLow c; CheckBalanceLow c;
/** /// @notice Deploy the `CheckBalanceLow` contract.
* @notice Deploy the `CheckBalanceLow` contract.
*/
function setUp() external { function setUp() external {
c = new CheckBalanceLow(); c = new CheckBalanceLow();
} }
/** /// @notice Fuzz the `check` function and assert that it always returns true
* @notice Fuzz the `check` function and assert that it always returns true /// when the target's balance is smaller than the threshold.
* when the target's balance is smaller than the threshold.
*/
function testFuzz_check_succeeds(address _target, uint256 _threshold) external { function testFuzz_check_succeeds(address _target, uint256 _threshold) external {
CheckBalanceLow.Params memory p = CheckBalanceLow.Params({ CheckBalanceLow.Params memory p = CheckBalanceLow.Params({
target: _target, target: _target,
...@@ -37,10 +29,8 @@ contract CheckBalanceLowTest is Test { ...@@ -37,10 +29,8 @@ contract CheckBalanceLowTest is Test {
assertEq(c.check(abi.encode(p)), true); assertEq(c.check(abi.encode(p)), true);
} }
/** /// @notice Fuzz the `check` function and assert that it always returns false
* @notice Fuzz the `check` function and assert that it always returns false /// when the target's balance is larger than the threshold.
* when the target's balance is larger than the threshold.
*/
function testFuzz_check_highBalance_fails(address _target, uint256 _threshold) external { function testFuzz_check_highBalance_fails(address _target, uint256 _threshold) external {
CheckBalanceLow.Params memory p = CheckBalanceLow.Params({ CheckBalanceLow.Params memory p = CheckBalanceLow.Params({
target: _target, target: _target,
......
//SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol"; import { Test } from "forge-std/Test.sol";
...@@ -7,11 +7,9 @@ import { ...@@ -7,11 +7,9 @@ import {
IGelatoTreasury IGelatoTreasury
} from "../periphery/drippie/dripchecks/CheckGelatoLow.sol"; } from "../periphery/drippie/dripchecks/CheckGelatoLow.sol";
/** /// @title MockGelatoTreasury
* @title MockGelatoTreasury /// @notice Mocks the Gelato treasury for testing purposes. Allows arbitrary
* @notice Mocks the Gelato treasury for testing purposes. Allows arbitrary /// setting of user balances.
* setting of user balances.
*/
contract MockGelatoTreasury is IGelatoTreasury { contract MockGelatoTreasury is IGelatoTreasury {
mapping(address => mapping(address => uint256)) private tokenBalances; mapping(address => mapping(address => uint256)) private tokenBalances;
...@@ -28,39 +26,27 @@ contract MockGelatoTreasury is IGelatoTreasury { ...@@ -28,39 +26,27 @@ contract MockGelatoTreasury is IGelatoTreasury {
} }
} }
/** /// @title CheckGelatoLowTest
* @title CheckGelatoLowTest /// @notice Tests the CheckBalanceHigh contract via fuzzing both the success case
* @notice Tests the CheckBalanceHigh contract via fuzzing both the success case /// and the failure case.
* and the failure case.
*/
contract CheckGelatoLowTest is Test { contract CheckGelatoLowTest is Test {
/** /// @notice An instance of the CheckGelatoLow contract.
* @notice An instance of the CheckGelatoLow contract.
*/
CheckGelatoLow c; CheckGelatoLow c;
/** /// @notice An instance of the MockGelatoTreasury contract.
* @notice An instance of the MockGelatoTreasury contract.
*/
MockGelatoTreasury gelato; MockGelatoTreasury gelato;
/** /// @notice The account Gelato uses to represent ether
* @notice The account Gelato uses to represent ether
*/
address internal constant eth = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; address internal constant eth = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
/** /// @notice Deploy the `CheckGelatoLow` and `MockGelatoTreasury` contracts.
* @notice Deploy the `CheckGelatoLow` and `MockGelatoTreasury` contracts.
*/
function setUp() external { function setUp() external {
c = new CheckGelatoLow(); c = new CheckGelatoLow();
gelato = new MockGelatoTreasury(); gelato = new MockGelatoTreasury();
} }
/** /// @notice Fuzz the `check` function and assert that it always returns true
* @notice Fuzz the `check` function and assert that it always returns true /// when the user's balance in the treasury is less than the threshold.
* when the user's balance in the treasury is less than the threshold.
*/
function testFuzz_check_succeeds(uint256 _threshold, address _recipient) external { function testFuzz_check_succeeds(uint256 _threshold, address _recipient) external {
CheckGelatoLow.Params memory p = CheckGelatoLow.Params({ CheckGelatoLow.Params memory p = CheckGelatoLow.Params({
treasury: address(gelato), treasury: address(gelato),
...@@ -73,11 +59,9 @@ contract CheckGelatoLowTest is Test { ...@@ -73,11 +59,9 @@ contract CheckGelatoLowTest is Test {
assertEq(c.check(abi.encode(p)), true); assertEq(c.check(abi.encode(p)), true);
} }
/** /// @notice Fuzz the `check` function and assert that it always returns false
* @notice Fuzz the `check` function and assert that it always returns false /// when the user's balance in the treasury is greater than or equal
* when the user's balance in the treasury is greater than or equal /// to the threshold.
* to the threshold.
*/
function testFuzz_check_highBalance_fails(uint256 _threshold, address _recipient) external { function testFuzz_check_highBalance_fails(uint256 _threshold, address _recipient) external {
CheckGelatoLow.Params memory p = CheckGelatoLow.Params({ CheckGelatoLow.Params memory p = CheckGelatoLow.Params({
treasury: address(gelato), treasury: address(gelato),
......
//SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol"; import { Test } from "forge-std/Test.sol";
import { CheckTrue } from "../periphery/drippie/dripchecks/CheckTrue.sol"; import { CheckTrue } from "../periphery/drippie/dripchecks/CheckTrue.sol";
/** /// @title CheckTrueTest
* @title CheckTrueTest /// @notice Ensures that the CheckTrue DripCheck contract always returns true.
* @notice Ensures that the CheckTrue DripCheck contract always returns true.
*/
contract CheckTrueTest is Test { contract CheckTrueTest is Test {
/** /// @notice An instance of the CheckTrue contract.
* @notice An instance of the CheckTrue contract.
*/
CheckTrue c; CheckTrue c;
/** /// @notice Deploy the `CheckTrue` contract.
* @notice Deploy the `CheckTrue` contract.
*/
function setUp() external { function setUp() external {
c = new CheckTrue(); c = new CheckTrue();
} }
/** /// @notice Fuzz the `check` function and assert that it always returns true.
* @notice Fuzz the `check` function and assert that it always returns true.
*/
function testFuzz_always_true_succeeds(bytes memory input) external { function testFuzz_always_true_succeeds(bytes memory input) external {
assertEq(c.check(input), true); assertEq(c.check(input), true);
} }
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
/* Testing utilities */ // Testing utilities
import { Test, StdUtils } from "forge-std/Test.sol"; import { Test, StdUtils } from "forge-std/Test.sol";
import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; import { L2OutputOracle } from "../L1/L2OutputOracle.sol";
import { L2ToL1MessagePasser } from "../L2/L2ToL1MessagePasser.sol"; import { L2ToL1MessagePasser } from "../L2/L2ToL1MessagePasser.sol";
...@@ -766,9 +766,7 @@ contract ConfigurableCaller { ...@@ -766,9 +766,7 @@ contract ConfigurableCaller {
event WhatHappened(bool success, bytes returndata); event WhatHappened(bool success, bytes returndata);
/** /// @notice Call the configured target with the configured payload OR revert.
* @notice Call the configured target with the configured payload OR revert.
*/
function call() external { function call() external {
if (doRevert) { if (doRevert) {
revert("ConfigurableCaller: revert"); revert("ConfigurableCaller: revert");
...@@ -787,31 +785,23 @@ contract ConfigurableCaller { ...@@ -787,31 +785,23 @@ contract ConfigurableCaller {
} }
} }
/** /// @notice Set whether or not to have `call` revert.
* @notice Set whether or not to have `call` revert.
*/
function setDoRevert(bool _doRevert) external { function setDoRevert(bool _doRevert) external {
doRevert = _doRevert; doRevert = _doRevert;
} }
/** /// @notice Set the target for the call made in `call`.
* @notice Set the target for the call made in `call`.
*/
function setTarget(address _target) external { function setTarget(address _target) external {
target = _target; target = _target;
} }
/** /// @notice Set the payload for the call made in `call`.
* @notice Set the payload for the call made in `call`.
*/
function setPayload(bytes calldata _payload) external { function setPayload(bytes calldata _payload) external {
payload = _payload; payload = _payload;
} }
/** /// @notice Fallback function that reverts if `doRevert` is true.
* @notice Fallback function that reverts if `doRevert` is true. /// Otherwise, it does nothing.
* Otherwise, it does nothing.
*/
fallback() external { fallback() external {
if (doRevert) { if (doRevert) {
revert("ConfigurableCaller: revert"); revert("ConfigurableCaller: revert");
......
//SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol"; import { Test } from "forge-std/Test.sol";
...@@ -45,9 +45,7 @@ contract Faucet_Initializer is Test { ...@@ -45,9 +45,7 @@ contract Faucet_Initializer is Test {
_initializeContracts(); _initializeContracts();
} }
/** /// @notice Instantiates a Faucet.
* @notice Instantiates a Faucet.
*/
function _initializeContracts() internal { function _initializeContracts() internal {
faucet = new Faucet(faucetContractAdmin); faucet = new Faucet(faucetContractAdmin);
...@@ -76,10 +74,7 @@ contract Faucet_Initializer is Test { ...@@ -76,10 +74,7 @@ contract Faucet_Initializer is Test {
vm.stopPrank(); vm.stopPrank();
} }
/** /// @notice Get signature as a bytes blob.
* @notice Get signature as a bytes blob.
*
*/
function _getSignature(uint256 _signingPrivateKey, bytes32 _digest) function _getSignature(uint256 _signingPrivateKey, bytes32 _digest)
internal internal
pure pure
...@@ -91,11 +86,9 @@ contract Faucet_Initializer is Test { ...@@ -91,11 +86,9 @@ contract Faucet_Initializer is Test {
return signature; return signature;
} }
/** /// @notice Signs a proof with the given private key and returns the signature using
* @notice Signs a proof with the given private key and returns the signature using /// the given EIP712 domain separator. This assumes that the issuer's address is the
* the given EIP712 domain separator. This assumes that the issuer's address is the /// corresponding public key to _issuerPrivateKey.
* corresponding public key to _issuerPrivateKey.
*/
function issueProofWithEIP712Domain( function issueProofWithEIP712Domain(
uint256 _issuerPrivateKey, uint256 _issuerPrivateKey,
bytes memory _eip712Name, bytes memory _eip712Name,
......
//SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
/* Testing utilities */ // Testing utilities
import { Test } from "forge-std/Test.sol"; import { Test } from "forge-std/Test.sol";
import { AttestationStation } from "../periphery/op-nft/AttestationStation.sol"; import { AttestationStation } from "../periphery/op-nft/AttestationStation.sol";
import { OptimistAllowlist } from "../periphery/op-nft/OptimistAllowlist.sol"; import { OptimistAllowlist } from "../periphery/op-nft/OptimistAllowlist.sol";
...@@ -106,10 +106,7 @@ contract OptimistAllowlist_Initializer is Test { ...@@ -106,10 +106,7 @@ contract OptimistAllowlist_Initializer is Test {
optimistInviter.claimInvite(claimer, claimableInvite, signature); optimistInviter.claimInvite(claimer, claimableInvite, signature);
} }
/** /// @notice Get signature as a bytes blob, since SignatureChecker takes arbitrary signature blobs.
* @notice Get signature as a bytes blob, since SignatureChecker takes arbitrary signature blobs.
*
*/
function _getSignature(uint256 _signingPrivateKey, bytes32 _digest) function _getSignature(uint256 _signingPrivateKey, bytes32 _digest)
internal internal
pure pure
...@@ -149,42 +146,32 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer { ...@@ -149,42 +146,32 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer {
assertEq(optimistAllowlist.version(), "1.0.0"); assertEq(optimistAllowlist.version(), "1.0.0");
} }
/** /// @notice Base case, a account without any relevant attestations should not be able to mint.
* @notice Base case, a account without any relevant attestations should not be able to mint.
*/
function test_isAllowedToMint_withoutAnyAttestations_fails() external { function test_isAllowedToMint_withoutAnyAttestations_fails() external {
assertFalse(optimistAllowlist.isAllowedToMint(bob)); assertFalse(optimistAllowlist.isAllowedToMint(bob));
} }
/** /// @notice After receiving a valid allowlist attestation, the account should be able to mint.
* @notice After receiving a valid allowlist attestation, the account should be able to mint.
*/
function test_isAllowedToMint_fromAllowlistAttestor_succeeds() external { function test_isAllowedToMint_fromAllowlistAttestor_succeeds() external {
attestAllowlist(bob); attestAllowlist(bob);
assertTrue(optimistAllowlist.isAllowedToMint(bob)); assertTrue(optimistAllowlist.isAllowedToMint(bob));
} }
/** /// @notice After receiving a valid attestation from the Coinbase Quest attestor,
* @notice After receiving a valid attestation from the Coinbase Quest attestor, /// the account should be able to mint.
* the account should be able to mint.
*/
function test_isAllowedToMint_fromCoinbaseQuestAttestor_succeeds() external { function test_isAllowedToMint_fromCoinbaseQuestAttestor_succeeds() external {
attestCoinbaseQuest(bob); attestCoinbaseQuest(bob);
assertTrue(optimistAllowlist.isAllowedToMint(bob)); assertTrue(optimistAllowlist.isAllowedToMint(bob));
} }
/** /// @notice Account that received an attestation from the OptimistInviter contract by going
* @notice Account that received an attestation from the OptimistInviter contract by going /// through the claim invite flow should be able to mint.
* through the claim invite flow should be able to mint.
*/
function test_isAllowedToMint_fromInvite_succeeds() external { function test_isAllowedToMint_fromInvite_succeeds() external {
inviteAndClaim(bob); inviteAndClaim(bob);
assertTrue(optimistAllowlist.isAllowedToMint(bob)); assertTrue(optimistAllowlist.isAllowedToMint(bob));
} }
/** /// @notice Attestation from the wrong allowlist attestor should not allow minting.
* @notice Attestation from the wrong allowlist attestor should not allow minting.
*/
function test_isAllowedToMint_fromWrongAllowlistAttestor_fails() external { function test_isAllowedToMint_fromWrongAllowlistAttestor_fails() external {
// Ted is not the allowlist attestor // Ted is not the allowlist attestor
vm.prank(ted); vm.prank(ted);
...@@ -196,9 +183,7 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer { ...@@ -196,9 +183,7 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer {
assertFalse(optimistAllowlist.isAllowedToMint(bob)); assertFalse(optimistAllowlist.isAllowedToMint(bob));
} }
/** /// @notice Coinbase quest attestation from wrong attestor should not allow minting.
* @notice Coinbase quest attestation from wrong attestor should not allow minting.
*/
function test_isAllowedToMint_fromWrongCoinbaseQuestAttestor_fails() external { function test_isAllowedToMint_fromWrongCoinbaseQuestAttestor_fails() external {
// Ted is not the coinbase quest attestor // Ted is not the coinbase quest attestor
vm.prank(ted); vm.prank(ted);
...@@ -210,10 +195,8 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer { ...@@ -210,10 +195,8 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer {
assertFalse(optimistAllowlist.isAllowedToMint(bob)); assertFalse(optimistAllowlist.isAllowedToMint(bob));
} }
/** /// @notice Claiming an invite on the non-official OptimistInviter contract should not allow
* @notice Claiming an invite on the non-official OptimistInviter contract should not allow /// minting.
* minting.
*/
function test_isAllowedToMint_fromWrongOptimistInviter_fails() external { function test_isAllowedToMint_fromWrongOptimistInviter_fails() external {
vm.prank(ted); vm.prank(ted);
attestationStation.attest( attestationStation.attest(
...@@ -224,9 +207,7 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer { ...@@ -224,9 +207,7 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer {
assertFalse(optimistAllowlist.isAllowedToMint(bob)); assertFalse(optimistAllowlist.isAllowedToMint(bob));
} }
/** /// @notice Having multiple signals, even if one is invalid, should still allow minting.
* @notice Having multiple signals, even if one is invalid, should still allow minting.
*/
function test_isAllowedToMint_withMultipleAttestations_succeeds() external { function test_isAllowedToMint_withMultipleAttestations_succeeds() external {
attestAllowlist(bob); attestAllowlist(bob);
attestCoinbaseQuest(bob); attestCoinbaseQuest(bob);
...@@ -246,9 +227,7 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer { ...@@ -246,9 +227,7 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer {
assertTrue(optimistAllowlist.isAllowedToMint(bob)); assertTrue(optimistAllowlist.isAllowedToMint(bob));
} }
/** /// @notice Having falsy attestation value should not allow minting.
* @notice Having falsy attestation value should not allow minting.
*/
function test_isAllowedToMint_fromAllowlistAttestorWithFalsyValue_fails() external { function test_isAllowedToMint_fromAllowlistAttestorWithFalsyValue_fails() external {
// First sends correct attestation // First sends correct attestation
attestAllowlist(bob); attestAllowlist(bob);
...@@ -264,9 +243,7 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer { ...@@ -264,9 +243,7 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer {
assertFalse(optimistAllowlist.isAllowedToMint(bob)); assertFalse(optimistAllowlist.isAllowedToMint(bob));
} }
/** /// @notice Having falsy attestation value from Coinbase attestor should not allow minting.
* @notice Having falsy attestation value from Coinbase attestor should not allow minting.
*/
function test_isAllowedToMint_fromCoinbaseQuestAttestorWithFalsyValue_fails() external { function test_isAllowedToMint_fromCoinbaseQuestAttestorWithFalsyValue_fails() external {
// First sends correct attestation // First sends correct attestation
attestAllowlist(bob); attestAllowlist(bob);
......
...@@ -3,10 +3,8 @@ pragma solidity ^0.8.0; ...@@ -3,10 +3,8 @@ pragma solidity ^0.8.0;
import { Bytes32AddressLib } from "@rari-capital/solmate/src/utils/Bytes32AddressLib.sol"; import { Bytes32AddressLib } from "@rari-capital/solmate/src/utils/Bytes32AddressLib.sol";
/** /// @title LibRLP
* @title LibRLP /// @notice Via https://github.com/Rari-Capital/solmate/issues/207.
* @notice Via https://github.com/Rari-Capital/solmate/issues/207.
*/
library LibRLP { library LibRLP {
using Bytes32AddressLib for bytes32; using Bytes32AddressLib for bytes32;
......
//SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
/* Testing utilities */ // Testing utilities
import { Test } from "forge-std/Test.sol"; import { Test } from "forge-std/Test.sol";
import { CallRecorder } from "./Helpers.sol"; import { CallRecorder } from "./Helpers.sol";
import { Reverter } from "./Helpers.sol"; import { Reverter } from "./Helpers.sol";
...@@ -34,12 +34,12 @@ contract Transactor_Initializer is Test { ...@@ -34,12 +34,12 @@ contract Transactor_Initializer is Test {
} }
contract TransactorTest is Transactor_Initializer { contract TransactorTest is Transactor_Initializer {
// Tests if the owner was set correctly during deploy /// @notice Tests if the owner was set correctly during deploy
function test_constructor_succeeds() external { function test_constructor_succeeds() external {
assertEq(address(alice), transactor.owner()); assertEq(address(alice), transactor.owner());
} }
// Tests CALL, should do a call to target /// @notice Tests CALL, should do a call to target
function test_call_succeeds() external { function test_call_succeeds() external {
// Initialize call data // Initialize call data
bytes memory data = abi.encodeWithSelector(callRecorded.record.selector); bytes memory data = abi.encodeWithSelector(callRecorded.record.selector);
...@@ -49,7 +49,7 @@ contract TransactorTest is Transactor_Initializer { ...@@ -49,7 +49,7 @@ contract TransactorTest is Transactor_Initializer {
transactor.CALL(address(callRecorded), data, 200_000 wei); transactor.CALL(address(callRecorded), data, 200_000 wei);
} }
// It should revert if called by non-owner /// @notice It should revert if called by non-owner
function test_call_unauthorized_reverts() external { function test_call_unauthorized_reverts() external {
// Initialize call data // Initialize call data
bytes memory data = abi.encodeWithSelector(callRecorded.record.selector); bytes memory data = abi.encodeWithSelector(callRecorded.record.selector);
...@@ -59,6 +59,7 @@ contract TransactorTest is Transactor_Initializer { ...@@ -59,6 +59,7 @@ contract TransactorTest is Transactor_Initializer {
transactor.CALL(address(callRecorded), data, 200_000 wei); transactor.CALL(address(callRecorded), data, 200_000 wei);
} }
/// @notice Deletate call succeeds.
function test_delegateCall_succeeds() external { function test_delegateCall_succeeds() external {
// Initialize call data // Initialize call data
bytes memory data = abi.encodeWithSelector(reverter.doRevert.selector); bytes memory data = abi.encodeWithSelector(reverter.doRevert.selector);
...@@ -68,7 +69,7 @@ contract TransactorTest is Transactor_Initializer { ...@@ -68,7 +69,7 @@ contract TransactorTest is Transactor_Initializer {
transactor.DELEGATECALL(address(reverter), data); transactor.DELEGATECALL(address(reverter), data);
} }
// It should revert if called by non-owner /// @notice It should revert if called by non-owner
function test_delegateCall_unauthorized_reverts() external { function test_delegateCall_unauthorized_reverts() external {
// Initialize call data // Initialize call data
bytes memory data = abi.encodeWithSelector(reverter.doRevert.selector); bytes memory data = abi.encodeWithSelector(reverter.doRevert.selector);
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol"; import { Test } from "forge-std/Test.sol";
...@@ -7,9 +8,7 @@ import { AddressAliasHelper } from "../../vendor/AddressAliasHelper.sol"; ...@@ -7,9 +8,7 @@ import { AddressAliasHelper } from "../../vendor/AddressAliasHelper.sol";
contract AddressAliasHelper_Converter { contract AddressAliasHelper_Converter {
bool public failedRoundtrip; bool public failedRoundtrip;
/** /// @dev Allows the actor to convert L1 to L2 addresses and vice versa.
* @dev Allows the actor to convert L1 to L2 addresses and vice versa.
*/
function convertRoundTrip(address addr) external { function convertRoundTrip(address addr) external {
// Alias our address // Alias our address
address aliasedAddr = AddressAliasHelper.applyL1ToL2Alias(addr); address aliasedAddr = AddressAliasHelper.applyL1ToL2Alias(addr);
...@@ -39,12 +38,11 @@ contract AddressAliasHelper_AddressAliasing_Invariant is StdInvariant, Test { ...@@ -39,12 +38,11 @@ contract AddressAliasHelper_AddressAliasing_Invariant is StdInvariant, Test {
targetSelector(selector); targetSelector(selector);
} }
/** /// @custom:invariant Address aliases are always able to be undone.
* @custom:invariant Address aliases are always able to be undone. ///
* /// Asserts that an address that has been aliased with
* Asserts that an address that has been aliased with `applyL1ToL2Alias` can always /// `applyL1ToL2Alias` can always be unaliased with
* be unaliased with `undoL1ToL2Alias`. /// `undoL1ToL2Alias`.
*/
function invariant_round_trip_aliasing() external { function invariant_round_trip_aliasing() external {
// ASSERTION: The round trip aliasing done in testRoundTrip(...) should never fail. // ASSERTION: The round trip aliasing done in testRoundTrip(...) should never fail.
assertEq(actor.failedRoundtrip(), false); assertEq(actor.failedRoundtrip(), false);
......
...@@ -16,10 +16,8 @@ contract Burn_EthBurner is StdUtils { ...@@ -16,10 +16,8 @@ contract Burn_EthBurner is StdUtils {
vm = _vm; vm = _vm;
} }
/** /// @notice Takes an integer amount of eth to burn through the Burn library and
* @notice Takes an integer amount of eth to burn through the Burn library and /// updates the contract state if an incorrect amount of eth moved from the contract
* updates the contract state if an incorrect amount of eth moved from the contract
*/
function burnEth(uint256 _value) external { function burnEth(uint256 _value) external {
uint256 preBurnvalue = bound(_value, 0, type(uint128).max); uint256 preBurnvalue = bound(_value, 0, type(uint128).max);
...@@ -59,12 +57,10 @@ contract Burn_BurnEth_Invariant is StdInvariant, Test { ...@@ -59,12 +57,10 @@ contract Burn_BurnEth_Invariant is StdInvariant, Test {
targetSelector(selector); targetSelector(selector);
} }
/** /// @custom:invariant `eth(uint256)` always burns the exact amount of eth passed.
* @custom:invariant `eth(uint256)` always burns the exact amount of eth passed. ///
* /// Asserts that when `Burn.eth(uint256)` is called, it always
* Asserts that when `Burn.eth(uint256)` is called, it always burns the exact amount /// burns the exact amount of ETH passed to the function.
* of ETH passed to the function.
*/
function invariant_burn_eth() external { function invariant_burn_eth() external {
// ASSERTION: The amount burned should always match the amount passed exactly // ASSERTION: The amount burned should always match the amount passed exactly
assertEq(actor.failedEthBurn(), false); assertEq(actor.failedEthBurn(), false);
......
...@@ -16,11 +16,9 @@ contract Burn_GasBurner is StdUtils { ...@@ -16,11 +16,9 @@ contract Burn_GasBurner is StdUtils {
vm = _vm; vm = _vm;
} }
/** /// @notice Takes an integer amount of gas to burn through the Burn library and
* @notice Takes an integer amount of gas to burn through the Burn library and /// updates the contract state if at least that amount of gas was not burned
* updates the contract state if at least that amount of gas was not burned /// by the library
* by the library
*/
function burnGas(uint256 _value) external { function burnGas(uint256 _value) external {
// cap the value to the max resource limit // cap the value to the max resource limit
uint256 MAX_RESOURCE_LIMIT = 8_000_000; uint256 MAX_RESOURCE_LIMIT = 8_000_000;
...@@ -59,12 +57,10 @@ contract Burn_BurnGas_Invariant is StdInvariant, Test { ...@@ -59,12 +57,10 @@ contract Burn_BurnGas_Invariant is StdInvariant, Test {
targetSelector(selector); targetSelector(selector);
} }
/** /// @custom:invariant `gas(uint256)` always burns at least the amount of gas passed.
* @custom:invariant `gas(uint256)` always burns at least the amount of gas passed. ///
* /// Asserts that when `Burn.gas(uint256)` is called, it always burns
* Asserts that when `Burn.gas(uint256)` is called, it always burns at least the amount /// at least the amount of gas passed to the function.
* of gas passed to the function.
*/
function invariant_burn_gas() external { function invariant_burn_gas() external {
// ASSERTION: The amount burned should always match the amount passed exactly // ASSERTION: The amount burned should always match the amount passed exactly
assertEq(actor.failedGasBurn(), false); assertEq(actor.failedGasBurn(), false);
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { StdUtils } from "forge-std/StdUtils.sol"; import { StdUtils } from "forge-std/StdUtils.sol";
...@@ -36,9 +37,8 @@ contract RelayActor is StdUtils { ...@@ -36,9 +37,8 @@ contract RelayActor is StdUtils {
doFail = _doFail; doFail = _doFail;
} }
/** /// @notice Relays a message to the `L1CrossDomainMessenger` with a random `version`,
* Relays a message to the `L1CrossDomainMessenger` with a random `version`, and `_message`. /// and `_message`.
*/
function relay( function relay(
uint8 _version, uint8 _version,
uint8 _value, uint8 _value,
...@@ -143,21 +143,19 @@ contract XDM_MinGasLimits_Succeeds is XDM_MinGasLimits { ...@@ -143,21 +143,19 @@ contract XDM_MinGasLimits_Succeeds is XDM_MinGasLimits {
super.init(false); super.init(false);
} }
/** /// @custom:invariant A call to `relayMessage` should succeed if at least the minimum gas limit
* @custom:invariant A call to `relayMessage` should succeed if at least the minimum gas limit /// can be supplied to the target context, there is enough gas to complete
* can be supplied to the target context, there is enough gas to complete /// execution of `relayMessage` after the target context's execution is
* execution of `relayMessage` after the target context's execution is /// finished, and the target context did not revert.
* finished, and the target context did not revert. ///
* /// There are two minimum gas limits here:
* There are two minimum gas limits here: ///
* /// - The outer min gas limit is for the call from the `OptimismPortal` to the
* - The outer min gas limit is for the call from the `OptimismPortal` to the /// `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's
* `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function /// `baseGas` function with the `message` and inner limit.
* with the `message` and inner limit. ///
* /// - The inner min gas limit is for the call from the
* - The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target /// `L1CrossDomainMessenger` to the target contract.
* contract.
*/
function invariant_minGasLimits() external { function invariant_minGasLimits() external {
uint256 length = actor.numHashes(); uint256 length = actor.numHashes();
for (uint256 i = 0; i < length; ++i) { for (uint256 i = 0; i < length; ++i) {
...@@ -177,22 +175,20 @@ contract XDM_MinGasLimits_Reverts is XDM_MinGasLimits { ...@@ -177,22 +175,20 @@ contract XDM_MinGasLimits_Reverts is XDM_MinGasLimits {
super.init(true); super.init(true);
} }
/** /// @custom:invariant A call to `relayMessage` should assign the message hash to the
* @custom:invariant A call to `relayMessage` should assign the message hash to the /// `failedMessages` mapping if not enough gas is supplied to forward
* `failedMessages` mapping if not enough gas is supplied to forward /// `minGasLimit` to the target context or if there is not enough gas to
* `minGasLimit` to the target context or if there is not enough gas to /// complete execution of `relayMessage` after the target context's execution
* complete execution of `relayMessage` after the target context's execution /// is finished.
* is finished. ///
* /// There are two minimum gas limits here:
* There are two minimum gas limits here: ///
* /// - The outer min gas limit is for the call from the `OptimismPortal` to the
* - The outer min gas limit is for the call from the `OptimismPortal` to the /// `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's
* `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function /// `baseGas` function with the `message` and inner limit.
* with the `message` and inner limit. ///
* /// - The inner min gas limit is for the call from the
* - The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target /// `L1CrossDomainMessenger` to the target contract.
* contract.
*/
function invariant_minGasLimits() external { function invariant_minGasLimits() external {
uint256 length = actor.numHashes(); uint256 length = actor.numHashes();
for (uint256 i = 0; i < length; ++i) { for (uint256 i = 0; i < length; ++i) {
......
...@@ -9,11 +9,9 @@ contract Encoding_Converter { ...@@ -9,11 +9,9 @@ contract Encoding_Converter {
bool public failedRoundtripAToB; bool public failedRoundtripAToB;
bool public failedRoundtripBToA; bool public failedRoundtripBToA;
/** /// @notice Takes a pair of integers to be encoded into a versioned nonce with the
* @notice Takes a pair of integers to be encoded into a versioned nonce with the /// Encoding library and then decoded and updates the test contract's state
* Encoding library and then decoded and updates the test contract's state /// indicating if the round trip encoding failed.
* indicating if the round trip encoding failed.
*/
function convertRoundTripAToB(uint240 _nonce, uint16 _version) external { function convertRoundTripAToB(uint240 _nonce, uint16 _version) external {
// Encode the nonce and version // Encode the nonce and version
uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(_nonce, _version); uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(_nonce, _version);
...@@ -30,11 +28,9 @@ contract Encoding_Converter { ...@@ -30,11 +28,9 @@ contract Encoding_Converter {
} }
} }
/** /// @notice Takes an integer representing a packed version and nonce and attempts
* @notice Takes an integer representing a packed version and nonce and attempts /// to decode them using the Encoding library before re-encoding and updates
* to decode them using the Encoding library before re-encoding and updates /// the test contract's state indicating if the round trip encoding failed.
* the test contract's state indicating if the round trip encoding failed.
*/
function convertRoundTripBToA(uint256 _versionedNonce) external { function convertRoundTripBToA(uint256 _versionedNonce) external {
// Decode the nonce and version // Decode the nonce and version
uint240 decodedNonce; uint240 decodedNonce;
...@@ -68,22 +64,19 @@ contract Encoding_Invariant is StdInvariant, Test { ...@@ -68,22 +64,19 @@ contract Encoding_Invariant is StdInvariant, Test {
targetSelector(selector); targetSelector(selector);
} }
/** /// @custom:invariant `convertRoundTripAToB` never fails.
* @custom:invariant `convertRoundTripAToB` never fails. ///
* /// Asserts that a raw versioned nonce can be encoded / decoded
* Asserts that a raw versioned nonce can be encoded / decoded to reach the same raw value. /// to reach the same raw value.
*/
function invariant_round_trip_encoding_AToB() external { function invariant_round_trip_encoding_AToB() external {
// ASSERTION: The round trip encoding done in testRoundTripAToB(...) // ASSERTION: The round trip encoding done in testRoundTripAToB(...)
assertEq(actor.failedRoundtripAToB(), false); assertEq(actor.failedRoundtripAToB(), false);
} }
/** /// @custom:invariant `convertRoundTripBToA` never fails.
* @custom:invariant `convertRoundTripBToA` never fails. ///
* /// Asserts that an encoded versioned nonce can always be decoded /
* Asserts that an encoded versioned nonce can always be decoded / re-encoded to reach /// re-encoded to reach the same encoded value.
* the same encoded value.
*/
function invariant_round_trip_encoding_BToA() external { function invariant_round_trip_encoding_BToA() external {
// ASSERTION: The round trip encoding done in testRoundTripBToA should never // ASSERTION: The round trip encoding done in testRoundTripBToA should never
// fail. // fail.
......
...@@ -11,10 +11,9 @@ contract Hash_CrossDomainHasher { ...@@ -11,10 +11,9 @@ contract Hash_CrossDomainHasher {
bool public failedCrossDomainHashV0; bool public failedCrossDomainHashV0;
bool public failedCrossDomainHashV1; bool public failedCrossDomainHashV1;
/** /// @notice Takes the necessary parameters to perform a cross domain hash with a randomly
* @notice Takes the necessary parameters to perform a cross domain hash with a randomly /// generated version. Only schema versions 0 and 1 are supported and all others
* generated version. Only schema versions 0 and 1 are supported and all others should revert. /// should revert.
*/
function hashCrossDomainMessageHighVersion( function hashCrossDomainMessageHighVersion(
uint16 _version, uint16 _version,
uint240 _nonce, uint240 _nonce,
...@@ -37,10 +36,9 @@ contract Hash_CrossDomainHasher { ...@@ -37,10 +36,9 @@ contract Hash_CrossDomainHasher {
} }
} }
/** /// @notice Takes the necessary parameters to perform a cross domain hash using the v0 schema
* @notice Takes the necessary parameters to perform a cross domain hash using the v0 schema /// and compares the output of a call to the unversioned function to the v0 function
* and compares the output of a call to the unversioned function to the v0 function directly /// directly.
*/
function hashCrossDomainMessageV0( function hashCrossDomainMessageV0(
uint240 _nonce, uint240 _nonce,
address _sender, address _sender,
...@@ -75,10 +73,9 @@ contract Hash_CrossDomainHasher { ...@@ -75,10 +73,9 @@ contract Hash_CrossDomainHasher {
} }
} }
/** /// @notice Takes the necessary parameters to perform a cross domain hash using the v1 schema
* @notice Takes the necessary parameters to perform a cross domain hash using the v1 schema /// and compares the output of a call to the unversioned function to the v1 function
* and compares the output of a call to the unversioned function to the v1 function directly /// directly.
*/
function hashCrossDomainMessageV1( function hashCrossDomainMessageV1(
uint240 _nonce, uint240 _nonce,
address _sender, address _sender,
...@@ -133,36 +130,31 @@ contract Hashing_Invariant is StdInvariant, Test { ...@@ -133,36 +130,31 @@ contract Hashing_Invariant is StdInvariant, Test {
targetSelector(selector); targetSelector(selector);
} }
/** /// @custom:invariant `hashCrossDomainMessage` reverts if `version` is > `1`.
* @custom:invariant `hashCrossDomainMessage` reverts if `version` is > `1`. ///
* /// The `hashCrossDomainMessage` function should always revert if
* The `hashCrossDomainMessage` function should always revert if the `version` passed is > `1`. /// the `version` passed is > `1`.
*/
function invariant_hash_xdomain_msg_high_version() external { function invariant_hash_xdomain_msg_high_version() external {
// ASSERTION: The round trip aliasing done in testRoundTrip(...) should never fail. // ASSERTION: The round trip aliasing done in testRoundTrip(...) should never fail.
assertFalse(actor.failedCrossDomainHashHighVersion()); assertFalse(actor.failedCrossDomainHashHighVersion());
} }
/** /// @custom:invariant `version` = `0`: `hashCrossDomainMessage` and `hashCrossDomainMessageV0`
* @custom:invariant `version` = `0`: `hashCrossDomainMessage` and `hashCrossDomainMessageV0` /// are equivalent.
* are equivalent. ///
* /// If the version passed is 0, `hashCrossDomainMessage` and
* If the version passed is 0, `hashCrossDomainMessage` and `hashCrossDomainMessageV0` should be /// `hashCrossDomainMessageV0` should be equivalent.
* equivalent.
*/
function invariant_hash_xdomain_msg_0() external { function invariant_hash_xdomain_msg_0() external {
// ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV0 // ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV0
// should always match when the version passed is 0 // should always match when the version passed is 0
assertFalse(actor.failedCrossDomainHashV0()); assertFalse(actor.failedCrossDomainHashV0());
} }
/** /// @custom:invariant `version` = `1`: `hashCrossDomainMessage` and `hashCrossDomainMessageV1`
* @custom:invariant `version` = `1`: `hashCrossDomainMessage` and `hashCrossDomainMessageV1` /// are equivalent.
* are equivalent. ///
* /// If the version passed is 1, `hashCrossDomainMessage` and
* If the version passed is 1, `hashCrossDomainMessage` and `hashCrossDomainMessageV1` should be /// `hashCrossDomainMessageV1` should be equivalent.
* equivalent.
*/
function invariant_hash_xdomain_msg_1() external { function invariant_hash_xdomain_msg_1() external {
// ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV1 // ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV1
// should always match when the version passed is 1 // should always match when the version passed is 1
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { L2OutputOracle_Initializer } from "../CommonTest.t.sol"; import { L2OutputOracle_Initializer } from "../CommonTest.t.sol";
...@@ -13,9 +14,7 @@ contract L2OutputOracle_Proposer { ...@@ -13,9 +14,7 @@ contract L2OutputOracle_Proposer {
vm = _vm; vm = _vm;
} }
/** /// @dev Allows the actor to propose an L2 output to the `L2OutputOracle`
* @dev Allows the actor to propose an L2 output to the `L2OutputOracle`
*/
function proposeL2Output( function proposeL2Output(
bytes32 _outputRoot, bytes32 _outputRoot,
uint256 _l2BlockNumber, uint256 _l2BlockNumber,
...@@ -49,13 +48,11 @@ contract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is L2OutputOracle_In ...@@ -49,13 +48,11 @@ contract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is L2OutputOracle_In
targetSelector(selector); targetSelector(selector);
} }
/** /// @custom:invariant The block number of the output root proposals should monotonically
* @custom:invariant The block number of the output root proposals should monotonically /// increase.
* increase. ///
* /// When a new output is submitted, it should never be allowed to
* When a new output is submitted, it should never be allowed to correspond to a block /// correspond to a block number that is less than the current output.
* number that is less than the current output.
*/
function invariant_monotonicBlockNumIncrease() external { function invariant_monotonicBlockNumIncrease() external {
// Assert that the block number of proposals must monotonically increase. // Assert that the block number of proposals must monotonically increase.
assertTrue(oracle.nextBlockNumber() >= oracle.latestBlockNumber()); assertTrue(oracle.nextBlockNumber() >= oracle.latestBlockNumber());
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { StdUtils } from "forge-std/Test.sol"; import { StdUtils } from "forge-std/Test.sol";
...@@ -148,13 +149,11 @@ contract OptimismPortal_Deposit_Invariant is Portal_Initializer { ...@@ -148,13 +149,11 @@ contract OptimismPortal_Deposit_Invariant is Portal_Initializer {
targetSelector(selector); targetSelector(selector);
} }
/** /// @custom:invariant Deposits of any value should always succeed unless
* @custom:invariant Deposits of any value should always succeed unless /// `_to` = `address(0)` or `_isCreation` = `true`.
* `_to` = `address(0)` or `_isCreation` = `true`. ///
* /// All deposits, barring creation transactions and transactions
* All deposits, barring creation transactions and transactions sent to `address(0)`, /// sent to `address(0)`, should always succeed.
* should always succeed.
*/
function invariant_deposit_completes() external { function invariant_deposit_completes() external {
assertEq(actor.failedToComplete(), false); assertEq(actor.failedToComplete(), false);
} }
...@@ -178,13 +177,11 @@ contract OptimismPortal_CannotTimeTravel is OptimismPortal_Invariant_Harness { ...@@ -178,13 +177,11 @@ contract OptimismPortal_CannotTimeTravel is OptimismPortal_Invariant_Harness {
excludeSender(address(multisig)); excludeSender(address(multisig));
} }
/** /// @custom:invariant `finalizeWithdrawalTransaction` should revert if the finalization
* @custom:invariant `finalizeWithdrawalTransaction` should revert if the finalization /// period has not elapsed.
* period has not elapsed. ///
* /// A withdrawal that has been proven should not be able to be finalized
* A withdrawal that has been proven should not be able to be finalized until after /// until after the finalization period has elapsed.
* the finalization period has elapsed.
*/
function invariant_cannotFinalizeBeforePeriodHasPassed() external { function invariant_cannotFinalizeBeforePeriodHasPassed() external {
vm.expectRevert("OptimismPortal: proven withdrawal finalization period has not elapsed"); vm.expectRevert("OptimismPortal: proven withdrawal finalization period has not elapsed");
op.finalizeWithdrawalTransaction(_defaultTx); op.finalizeWithdrawalTransaction(_defaultTx);
...@@ -215,13 +212,11 @@ contract OptimismPortal_CannotFinalizeTwice is OptimismPortal_Invariant_Harness ...@@ -215,13 +212,11 @@ contract OptimismPortal_CannotFinalizeTwice is OptimismPortal_Invariant_Harness
excludeSender(address(multisig)); excludeSender(address(multisig));
} }
/** /// @custom:invariant `finalizeWithdrawalTransaction` should revert if the withdrawal
* @custom:invariant `finalizeWithdrawalTransaction` should revert if the withdrawal /// has already been finalized.
* has already been finalized. ///
* /// Ensures that there is no chain of calls that can be made that
* Ensures that there is no chain of calls that can be made that allows a withdrawal /// allows a withdrawal to be finalized twice.
* to be finalized twice.
*/
function invariant_cannotFinalizeTwice() external { function invariant_cannotFinalizeTwice() external {
vm.expectRevert("OptimismPortal: withdrawal has already been finalized"); vm.expectRevert("OptimismPortal: withdrawal has already been finalized");
op.finalizeWithdrawalTransaction(_defaultTx); op.finalizeWithdrawalTransaction(_defaultTx);
...@@ -249,14 +244,13 @@ contract OptimismPortal_CanAlwaysFinalizeAfterWindow is OptimismPortal_Invariant ...@@ -249,14 +244,13 @@ contract OptimismPortal_CanAlwaysFinalizeAfterWindow is OptimismPortal_Invariant
excludeSender(address(multisig)); excludeSender(address(multisig));
} }
/** /// @custom:invariant A withdrawal should **always** be able to be finalized
* @custom:invariant A withdrawal should **always** be able to be finalized /// `FINALIZATION_PERIOD_SECONDS` after it was successfully proven.
* `FINALIZATION_PERIOD_SECONDS` after it was successfully proven. ///
* /// This invariant asserts that there is no chain of calls that can
* This invariant asserts that there is no chain of calls that can be made that /// be made that will prevent a withdrawal from being finalized
* will prevent a withdrawal from being finalized exactly `FINALIZATION_PERIOD_SECONDS` /// exactly `FINALIZATION_PERIOD_SECONDS` after it was successfully
* after it was successfully proven. /// proven.
*/
function invariant_canAlwaysFinalize() external { function invariant_canAlwaysFinalize() external {
uint256 bobBalanceBefore = address(bob).balance; uint256 bobBalanceBefore = address(bob).balance;
......
...@@ -45,10 +45,8 @@ contract ResourceMetering_User is StdUtils, ResourceMetering { ...@@ -45,10 +45,8 @@ contract ResourceMetering_User is StdUtils, ResourceMetering {
return rcfg; return rcfg;
} }
/** /// @notice Takes the necessary parameters to allow us to burn arbitrary amounts of gas to test
* @notice Takes the necessary parameters to allow us to burn arbitrary amounts of gas to test /// the underlying resource metering/gas market logic
* the underlying resource metering/gas market logic
*/
function burn(uint256 _gasToBurn, bool _raiseBaseFee) public { function burn(uint256 _gasToBurn, bool _raiseBaseFee) public {
// Part 1: we cache the current param values and do some basic checks on them. // Part 1: we cache the current param values and do some basic checks on them.
uint256 cachedPrevBaseFee = uint256(params.prevBaseFee); uint256 cachedPrevBaseFee = uint256(params.prevBaseFee);
...@@ -169,78 +167,67 @@ contract ResourceMetering_Invariant is StdInvariant, Test { ...@@ -169,78 +167,67 @@ contract ResourceMetering_Invariant is StdInvariant, Test {
targetSelector(selector); targetSelector(selector);
} }
/** /// @custom:invariant The base fee should increase if the last block used more
* @custom:invariant The base fee should increase if the last block used more /// than the target amount of gas.
* than the target amount of gas ///
* /// If the last block used more than the target amount of gas
* If the last block used more than the target amount of gas (and there were no /// (and there were no empty blocks in between), ensure this
* empty blocks in between), ensure this block's baseFee increased, but not by /// block's baseFee increased, but not by more than the max amount
* more than the max amount per block. /// per block.
*/
function invariant_high_usage_raise_baseFee() external { function invariant_high_usage_raise_baseFee() external {
assertFalse(actor.failedRaiseBaseFee()); assertFalse(actor.failedRaiseBaseFee());
} }
/** /// @custom:invariant The base fee should decrease if the last block used less
* @custom:invariant The base fee should decrease if the last block used less /// than the target amount of gas.
* than the target amount of gas ///
* /// If the previous block used less than the target amount of gas,
* If the previous block used less than the target amount of gas, the base fee should decrease, /// the base fee should decrease, but not more than the max amount.
* but not more than the max amount.
*/
function invariant_low_usage_lower_baseFee() external { function invariant_low_usage_lower_baseFee() external {
assertFalse(actor.failedLowerBaseFee()); assertFalse(actor.failedLowerBaseFee());
} }
/** /// @custom:invariant A block's base fee should never be below `MINIMUM_BASE_FEE`.
* @custom:invariant A block's base fee should never be below `MINIMUM_BASE_FEE` ///
* /// This test asserts that a block's base fee can never drop
* This test asserts that a block's base fee can never drop below the /// below the `MINIMUM_BASE_FEE` threshold.
* `MINIMUM_BASE_FEE` threshold.
*/
function invariant_never_below_min_baseFee() external { function invariant_never_below_min_baseFee() external {
assertFalse(actor.failedNeverBelowMinBaseFee()); assertFalse(actor.failedNeverBelowMinBaseFee());
} }
/** /// @custom:invariant A block can never consume more than `MAX_RESOURCE_LIMIT` gas.
* @custom:invariant A block can never consume more than `MAX_RESOURCE_LIMIT` gas. ///
* /// This test asserts that a block can never consume more than
* This test asserts that a block can never consume more than the `MAX_RESOURCE_LIMIT` /// the `MAX_RESOURCE_LIMIT` gas threshold.
* gas threshold.
*/
function invariant_never_above_max_gas_limit() external { function invariant_never_above_max_gas_limit() external {
assertFalse(actor.failedMaxGasPerBlock()); assertFalse(actor.failedMaxGasPerBlock());
} }
/** /// @custom:invariant The base fee can never be raised more than the max base fee change.
* @custom:invariant The base fee can never be raised more than the max base fee change. ///
* /// After a block consumes more gas than the target gas, the base fee
* After a block consumes more gas than the target gas, the base fee cannot be raised /// cannot be raised more than the maximum amount allowed. The max base
* more than the maximum amount allowed. The max base fee change (per-block) is derived /// fee change (per-block) is derived as follows:
* as follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR` /// `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`
*/
function invariant_never_exceed_max_increase() external { function invariant_never_exceed_max_increase() external {
assertFalse(actor.failedMaxRaiseBaseFeePerBlock()); assertFalse(actor.failedMaxRaiseBaseFeePerBlock());
} }
/** /// @custom:invariant The base fee can never be lowered more than the max base fee change.
* @custom:invariant The base fee can never be lowered more than the max base fee change. ///
* /// After a block consumes less than the target gas, the base fee cannot
* After a block consumes less than the target gas, the base fee cannot be lowered more /// be lowered more than the maximum amount allowed. The max base fee
* than the maximum amount allowed. The max base fee change (per-block) is derived as /// change (per-block) is derived as follows:
*follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR` /// `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`
*/
function invariant_never_exceed_max_decrease() external { function invariant_never_exceed_max_decrease() external {
assertFalse(actor.failedMaxLowerBaseFeePerBlock()); assertFalse(actor.failedMaxLowerBaseFeePerBlock());
} }
/** /// @custom:invariant The `maxBaseFeeChange` calculation over multiple blocks can never
* @custom:invariant The `maxBaseFeeChange` calculation over multiple blocks can never /// underflow.
* underflow. ///
* /// When calculating the `maxBaseFeeChange` after multiple empty blocks,
* When calculating the `maxBaseFeeChange` after multiple empty blocks, the calculation /// the calculation should never be allowed to underflow.
* should never be allowed to underflow.
*/
function invariant_never_underflow() external { function invariant_never_underflow() external {
assertFalse(actor.underflow()); assertFalse(actor.underflow());
} }
......
...@@ -23,13 +23,11 @@ contract SafeCall_Succeeds_Invariants is Test { ...@@ -23,13 +23,11 @@ contract SafeCall_Succeeds_Invariants is Test {
vm.deal(address(actor), type(uint128).max); vm.deal(address(actor), type(uint128).max);
} }
/** /// @custom:invariant If `callWithMinGas` performs a call, then it must always
* @custom:invariant If `callWithMinGas` performs a call, then it must always /// provide at least the specified minimum gas limit to the subcontext.
* provide at least the specified minimum gas limit to the subcontext. ///
* /// If the check for remaining gas in `SafeCall.callWithMinGas` passes, the
* If the check for remaining gas in `SafeCall.callWithMinGas` passes, the /// subcontext of the call below it must be provided at least `minGas` gas.
* subcontext of the call below it must be provided at least `minGas` gas.
*/
function invariant_callWithMinGas_alwaysForwardsMinGas_succeeds() public { function invariant_callWithMinGas_alwaysForwardsMinGas_succeeds() public {
assertEq(actor.numCalls(), 0, "no failed calls allowed"); assertEq(actor.numCalls(), 0, "no failed calls allowed");
} }
...@@ -56,14 +54,12 @@ contract SafeCall_Fails_Invariants is Test { ...@@ -56,14 +54,12 @@ contract SafeCall_Fails_Invariants is Test {
vm.deal(address(actor), type(uint128).max); vm.deal(address(actor), type(uint128).max);
} }
/** /// @custom:invariant `callWithMinGas` reverts if there is not enough gas to pass
* @custom:invariant `callWithMinGas` reverts if there is not enough gas to pass /// to the subcontext.
* to the subcontext. ///
* /// If there is not enough gas in the callframe to ensure that
* If there is not enough gas in the callframe to ensure that `callWithMinGas` /// `callWithMinGas` can provide the specified minimum gas limit
* can provide the specified minimum gas limit to the subcontext of the call, /// to the subcontext of the call, then `callWithMinGas` must revert.
* then `callWithMinGas` must revert.
*/
function invariant_callWithMinGas_neverForwardsMinGas_reverts() public { function invariant_callWithMinGas_neverForwardsMinGas_reverts() public {
assertEq(actor.numCalls(), 0, "no successful calls allowed"); assertEq(actor.numCalls(), 0, "no successful calls allowed");
} }
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol"; import { Test } from "forge-std/Test.sol";
...@@ -37,10 +38,8 @@ contract SystemConfig_GasLimitLowerBound_Invariant is Test { ...@@ -37,10 +38,8 @@ contract SystemConfig_GasLimitLowerBound_Invariant is Test {
targetSelector(selector); targetSelector(selector);
} }
/** /// @custom:invariant The gas limit of the `SystemConfig` contract can never be lower
* @custom:invariant The gas limit of the `SystemConfig` contract can never be lower /// than the hard-coded lower bound.
* than the hard-coded lower bound.
*/
function invariant_gasLimitLowerBound() external { function invariant_gasLimitLowerBound() external {
assertTrue(config.gasLimit() >= config.minimumGasLimit()); assertTrue(config.gasLimit() >= config.minimumGasLimit());
} }
......
# `AddressAliasHelper` Invariants # `AddressAliasHelper` Invariants
## Address aliases are always able to be undone. ## Address aliases are always able to be undone.
**Test:** [`AddressAliasHelper.t.sol#L48`](../contracts/test/invariants/AddressAliasHelper.t.sol#L48) **Test:** [`AddressAliasHelper.t.sol#L46`](../contracts/test/invariants/AddressAliasHelper.t.sol#L46)
Asserts that an address that has been aliased with `applyL1ToL2Alias` can always be unaliased with `undoL1ToL2Alias`. Asserts that an address that has been aliased with `applyL1ToL2Alias` can always be unaliased with `undoL1ToL2Alias`.
\ No newline at end of file
# `Burn.Eth` Invariants # `Burn.Eth` Invariants
## `eth(uint256)` always burns the exact amount of eth passed. ## `eth(uint256)` always burns the exact amount of eth passed.
**Test:** [`Burn.Eth.t.sol#L68`](../contracts/test/invariants/Burn.Eth.t.sol#L68) **Test:** [`Burn.Eth.t.sol#L64`](../contracts/test/invariants/Burn.Eth.t.sol#L64)
Asserts that when `Burn.eth(uint256)` is called, it always burns the exact amount of ETH passed to the function. Asserts that when `Burn.eth(uint256)` is called, it always burns the exact amount of ETH passed to the function.
\ No newline at end of file
# `Burn.Gas` Invariants # `Burn.Gas` Invariants
## `gas(uint256)` always burns at least the amount of gas passed. ## `gas(uint256)` always burns at least the amount of gas passed.
**Test:** [`Burn.Gas.t.sol#L68`](../contracts/test/invariants/Burn.Gas.t.sol#L68) **Test:** [`Burn.Gas.t.sol#L64`](../contracts/test/invariants/Burn.Gas.t.sol#L64)
Asserts that when `Burn.gas(uint256)` is called, it always burns at least the amount of gas passed to the function. Asserts that when `Burn.gas(uint256)` is called, it always burns at least the amount of gas passed to the function.
\ No newline at end of file
# `CrossDomainMessenger` Invariants # `CrossDomainMessenger` Invariants
## A call to `relayMessage` should succeed if at least the minimum gas limit can be supplied to the target context, there is enough gas to complete execution of `relayMessage` after the target context's execution is finished, and the target context did not revert. ## A call to `relayMessage` should succeed if at least the minimum gas limit can be supplied to the target context, there is enough gas to complete execution of `relayMessage` after the target context's execution is finished, and the target context did not revert.
**Test:** [`CrossDomainMessenger.t.sol#L161`](../contracts/test/invariants/CrossDomainMessenger.t.sol#L161) **Test:** [`CrossDomainMessenger.t.sol#L159`](../contracts/test/invariants/CrossDomainMessenger.t.sol#L159)
There are two minimum gas limits here: There are two minimum gas limits here:
- The outer min gas limit is for the call from the `OptimismPortal` to the `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function with the `message` and inner limit. - The outer min gas limit is for the call from the `OptimismPortal` to the `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function with the `message` and inner limit.
- The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target contract. - The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target contract.
## A call to `relayMessage` should assign the message hash to the `failedMessages` mapping if not enough gas is supplied to forward `minGasLimit` to the target context or if there is not enough gas to complete execution of `relayMessage` after the target context's execution is finished. ## A call to `relayMessage` should assign the message hash to the `failedMessages` mapping if not enough gas is supplied to forward `minGasLimit` to the target context or if there is not enough gas to complete execution of `relayMessage` after the target context's execution is finished.
**Test:** [`CrossDomainMessenger.t.sol#L196`](../contracts/test/invariants/CrossDomainMessenger.t.sol#L196) **Test:** [`CrossDomainMessenger.t.sol#L192`](../contracts/test/invariants/CrossDomainMessenger.t.sol#L192)
There are two minimum gas limits here: There are two minimum gas limits here:
- The outer min gas limit is for the call from the `OptimismPortal` to the `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function with the `message` and inner limit. - The outer min gas limit is for the call from the `OptimismPortal` to the `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function with the `message` and inner limit.
......
# `Encoding` Invariants # `Encoding` Invariants
## `convertRoundTripAToB` never fails. ## `convertRoundTripAToB` never fails.
**Test:** [`Encoding.t.sol#L76`](../contracts/test/invariants/Encoding.t.sol#L76) **Test:** [`Encoding.t.sol#L71`](../contracts/test/invariants/Encoding.t.sol#L71)
Asserts that a raw versioned nonce can be encoded / decoded to reach the same raw value. Asserts that a raw versioned nonce can be encoded / decoded to reach the same raw value.
## `convertRoundTripBToA` never fails. ## `convertRoundTripBToA` never fails.
**Test:** [`Encoding.t.sol#L87`](../contracts/test/invariants/Encoding.t.sol#L87) **Test:** [`Encoding.t.sol#L80`](../contracts/test/invariants/Encoding.t.sol#L80)
Asserts that an encoded versioned nonce can always be decoded / re-encoded to reach the same encoded value. Asserts that an encoded versioned nonce can always be decoded / re-encoded to reach the same encoded value.
\ No newline at end of file
# `Hashing` Invariants # `Hashing` Invariants
## `hashCrossDomainMessage` reverts if `version` is > `1`. ## `hashCrossDomainMessage` reverts if `version` is > `1`.
**Test:** [`Hashing.t.sol#L141`](../contracts/test/invariants/Hashing.t.sol#L141) **Test:** [`Hashing.t.sol#L137`](../contracts/test/invariants/Hashing.t.sol#L137)
The `hashCrossDomainMessage` function should always revert if the `version` passed is > `1`. The `hashCrossDomainMessage` function should always revert if the `version` passed is > `1`.
## `version` = `0`: `hashCrossDomainMessage` and `hashCrossDomainMessageV0` are equivalent. ## `version` = `0`: `hashCrossDomainMessage` and `hashCrossDomainMessageV0` are equivalent.
**Test:** [`Hashing.t.sol#L153`](../contracts/test/invariants/Hashing.t.sol#L153) **Test:** [`Hashing.t.sol#L147`](../contracts/test/invariants/Hashing.t.sol#L147)
If the version passed is 0, `hashCrossDomainMessage` and `hashCrossDomainMessageV0` should be equivalent. If the version passed is 0, `hashCrossDomainMessage` and `hashCrossDomainMessageV0` should be equivalent.
## `version` = `1`: `hashCrossDomainMessage` and `hashCrossDomainMessageV1` are equivalent. ## `version` = `1`: `hashCrossDomainMessage` and `hashCrossDomainMessageV1` are equivalent.
**Test:** [`Hashing.t.sol#L166`](../contracts/test/invariants/Hashing.t.sol#L166) **Test:** [`Hashing.t.sol#L158`](../contracts/test/invariants/Hashing.t.sol#L158)
If the version passed is 1, `hashCrossDomainMessage` and `hashCrossDomainMessageV1` should be equivalent. If the version passed is 1, `hashCrossDomainMessage` and `hashCrossDomainMessageV1` should be equivalent.
\ No newline at end of file
# `L2OutputOracle` Invariants # `L2OutputOracle` Invariants
## The block number of the output root proposals should monotonically increase. ## The block number of the output root proposals should monotonically increase.
**Test:** [`L2OutputOracle.t.sol#L59`](../contracts/test/invariants/L2OutputOracle.t.sol#L59) **Test:** [`L2OutputOracle.t.sol#L56`](../contracts/test/invariants/L2OutputOracle.t.sol#L56)
When a new output is submitted, it should never be allowed to correspond to a block number that is less than the current output. When a new output is submitted, it should never be allowed to correspond to a block number that is less than the current output.
\ No newline at end of file
# `OptimismPortal` Invariants # `OptimismPortal` Invariants
## Deposits of any value should always succeed unless `_to` = `address(0)` or `_isCreation` = `true`. ## Deposits of any value should always succeed unless `_to` = `address(0)` or `_isCreation` = `true`.
**Test:** [`OptimismPortal.t.sol#L158`](../contracts/test/invariants/OptimismPortal.t.sol#L158) **Test:** [`OptimismPortal.t.sol#L157`](../contracts/test/invariants/OptimismPortal.t.sol#L157)
All deposits, barring creation transactions and transactions sent to `address(0)`, should always succeed. All deposits, barring creation transactions and transactions sent to `address(0)`, should always succeed.
## `finalizeWithdrawalTransaction` should revert if the finalization period has not elapsed. ## `finalizeWithdrawalTransaction` should revert if the finalization period has not elapsed.
**Test:** [`OptimismPortal.t.sol#L188`](../contracts/test/invariants/OptimismPortal.t.sol#L188) **Test:** [`OptimismPortal.t.sol#L185`](../contracts/test/invariants/OptimismPortal.t.sol#L185)
A withdrawal that has been proven should not be able to be finalized until after the finalization period has elapsed. A withdrawal that has been proven should not be able to be finalized until after the finalization period has elapsed.
## `finalizeWithdrawalTransaction` should revert if the withdrawal has already been finalized. ## `finalizeWithdrawalTransaction` should revert if the withdrawal has already been finalized.
**Test:** [`OptimismPortal.t.sol#L225`](../contracts/test/invariants/OptimismPortal.t.sol#L225) **Test:** [`OptimismPortal.t.sol#L220`](../contracts/test/invariants/OptimismPortal.t.sol#L220)
Ensures that there is no chain of calls that can be made that allows a withdrawal to be finalized twice. Ensures that there is no chain of calls that can be made that allows a withdrawal to be finalized twice.
## A withdrawal should **always** be able to be finalized `FINALIZATION_PERIOD_SECONDS` after it was successfully proven. ## A withdrawal should **always** be able to be finalized `FINALIZATION_PERIOD_SECONDS` after it was successfully proven.
**Test:** [`OptimismPortal.t.sol#L260`](../contracts/test/invariants/OptimismPortal.t.sol#L260) **Test:** [`OptimismPortal.t.sol#L254`](../contracts/test/invariants/OptimismPortal.t.sol#L254)
This invariant asserts that there is no chain of calls that can be made that will prevent a withdrawal from being finalized exactly `FINALIZATION_PERIOD_SECONDS` after it was successfully proven. This invariant asserts that there is no chain of calls that can be made that will prevent a withdrawal from being finalized exactly `FINALIZATION_PERIOD_SECONDS` after it was successfully proven.
\ No newline at end of file
# `ResourceMetering` Invariants # `ResourceMetering` Invariants
## The base fee should increase if the last block used more than the target amount of gas ## The base fee should increase if the last block used more than the target amount of gas.
**Test:** [`ResourceMetering.t.sol#L180`](../contracts/test/invariants/ResourceMetering.t.sol#L180) **Test:** [`ResourceMetering.t.sol#L177`](../contracts/test/invariants/ResourceMetering.t.sol#L177)
If the last block used more than the target amount of gas (and there were no empty blocks in between), ensure this block's baseFee increased, but not by more than the max amount per block. If the last block used more than the target amount of gas (and there were no empty blocks in between), ensure this block's baseFee increased, but not by more than the max amount per block.
## The base fee should decrease if the last block used less than the target amount of gas.
## The base fee should decrease if the last block used less than the target amount of gas **Test:** [`ResourceMetering.t.sol#L186`](../contracts/test/invariants/ResourceMetering.t.sol#L186)
**Test:** [`ResourceMetering.t.sol#L191`](../contracts/test/invariants/ResourceMetering.t.sol#L191)
If the previous block used less than the target amount of gas, the base fee should decrease, but not more than the max amount. If the previous block used less than the target amount of gas, the base fee should decrease, but not more than the max amount.
## A block's base fee should never be below `MINIMUM_BASE_FEE`.
## A block's base fee should never be below `MINIMUM_BASE_FEE` **Test:** [`ResourceMetering.t.sol#L194`](../contracts/test/invariants/ResourceMetering.t.sol#L194)
**Test:** [`ResourceMetering.t.sol#L201`](../contracts/test/invariants/ResourceMetering.t.sol#L201)
This test asserts that a block's base fee can never drop below the `MINIMUM_BASE_FEE` threshold. This test asserts that a block's base fee can never drop below the `MINIMUM_BASE_FEE` threshold.
## A block can never consume more than `MAX_RESOURCE_LIMIT` gas. ## A block can never consume more than `MAX_RESOURCE_LIMIT` gas.
**Test:** [`ResourceMetering.t.sol#L211`](../contracts/test/invariants/ResourceMetering.t.sol#L211) **Test:** [`ResourceMetering.t.sol#L202`](../contracts/test/invariants/ResourceMetering.t.sol#L202)
This test asserts that a block can never consume more than the `MAX_RESOURCE_LIMIT` gas threshold. This test asserts that a block can never consume more than the `MAX_RESOURCE_LIMIT` gas threshold.
## The base fee can never be raised more than the max base fee change. ## The base fee can never be raised more than the max base fee change.
**Test:** [`ResourceMetering.t.sol#L222`](../contracts/test/invariants/ResourceMetering.t.sol#L222) **Test:** [`ResourceMetering.t.sol#L212`](../contracts/test/invariants/ResourceMetering.t.sol#L212)
After a block consumes more gas than the target gas, the base fee cannot be raised more than the maximum amount allowed. The max base fee change (per-block) is derived as follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR` After a block consumes more gas than the target gas, the base fee cannot be raised more than the maximum amount allowed. The max base fee change (per-block) is derived as follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`
## The base fee can never be lowered more than the max base fee change. ## The base fee can never be lowered more than the max base fee change.
**Test:** [`ResourceMetering.t.sol#L233`](../contracts/test/invariants/ResourceMetering.t.sol#L233) **Test:** [`ResourceMetering.t.sol#L222`](../contracts/test/invariants/ResourceMetering.t.sol#L222)
After a block consumes less than the target gas, the base fee cannot be lowered more than the maximum amount allowed. The max base fee change (per-block) is derived as follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR` After a block consumes less than the target gas, the base fee cannot be lowered more than the maximum amount allowed. The max base fee change (per-block) is derived as follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`
## The `maxBaseFeeChange` calculation over multiple blocks can never underflow. ## The `maxBaseFeeChange` calculation over multiple blocks can never underflow.
**Test:** [`ResourceMetering.t.sol#L244`](../contracts/test/invariants/ResourceMetering.t.sol#L244) **Test:** [`ResourceMetering.t.sol#L231`](../contracts/test/invariants/ResourceMetering.t.sol#L231)
When calculating the `maxBaseFeeChange` after multiple empty blocks, the calculation should never be allowed to underflow. When calculating the `maxBaseFeeChange` after multiple empty blocks, the calculation should never be allowed to underflow.
\ No newline at end of file
# `SafeCall` Invariants # `SafeCall` Invariants
## If `callWithMinGas` performs a call, then it must always provide at least the specified minimum gas limit to the subcontext. ## If `callWithMinGas` performs a call, then it must always provide at least the specified minimum gas limit to the subcontext.
**Test:** [`SafeCall.t.sol#L33`](../contracts/test/invariants/SafeCall.t.sol#L33) **Test:** [`SafeCall.t.sol#L31`](../contracts/test/invariants/SafeCall.t.sol#L31)
If the check for remaining gas in `SafeCall.callWithMinGas` passes, the subcontext of the call below it must be provided at least `minGas` gas. If the check for remaining gas in `SafeCall.callWithMinGas` passes, the subcontext of the call below it must be provided at least `minGas` gas.
## `callWithMinGas` reverts if there is not enough gas to pass to the subcontext. ## `callWithMinGas` reverts if there is not enough gas to pass to the subcontext.
**Test:** [`SafeCall.t.sol#L67`](../contracts/test/invariants/SafeCall.t.sol#L67) **Test:** [`SafeCall.t.sol#L63`](../contracts/test/invariants/SafeCall.t.sol#L63)
If there is not enough gas in the callframe to ensure that `callWithMinGas` can provide the specified minimum gas limit to the subcontext of the call, then `callWithMinGas` must revert. If there is not enough gas in the callframe to ensure that `callWithMinGas` can provide the specified minimum gas limit to the subcontext of the call, then `callWithMinGas` must revert.
\ No newline at end of file
...@@ -11,8 +11,6 @@ const BASE_INVARIANTS_DIR = path.join( ...@@ -11,8 +11,6 @@ const BASE_INVARIANTS_DIR = path.join(
const BASE_DOCS_DIR = path.join(__dirname, '..', 'invariant-docs') const BASE_DOCS_DIR = path.join(__dirname, '..', 'invariant-docs')
const BASE_INVARIANT_GH_URL = '../contracts/test/invariants/' const BASE_INVARIANT_GH_URL = '../contracts/test/invariants/'
const NATSPEC_INV = '@custom:invariant' const NATSPEC_INV = '@custom:invariant'
const BLOCK_COMMENT_PREFIX_REGEX = /\*(\/)?/
const BLOCK_COMMENT_HEADER_REGEX = /\*\s(.)+/
// Represents an invariant test contract // Represents an invariant test contract
type Contract = { type Contract = {
...@@ -30,10 +28,8 @@ type InvariantDoc = { ...@@ -30,10 +28,8 @@ type InvariantDoc = {
const writtenFiles = [] const writtenFiles = []
/** // Lazy-parses all test files in the `contracts/test/invariants` directory
* Lazy-parses all test files in the `contracts/test/invariants` directory to generate documentation // to generate documentation on all invariant tests.
* on all invariant tests.
*/
const docGen = (dir: string): void => { const docGen = (dir: string): void => {
// Grab all files within the invariants test dir // Grab all files within the invariants test dir
const files = fs.readdirSync(dir) const files = fs.readdirSync(dir)
...@@ -58,33 +54,25 @@ const docGen = (dir: string): void => { ...@@ -58,33 +54,25 @@ const docGen = (dir: string): void => {
for (let i = 0; i < lines.length; i++) { for (let i = 0; i < lines.length; i++) {
let line = lines[i] let line = lines[i]
if (line.startsWith('/**')) {
// We are at the beginning of a new doc comment. Reset the `currentDoc`.
currentDoc = {}
// Move on to the next line
line = lines[++i]
// We have an invariant doc // We have an invariant doc
if (line.startsWith(`* ${NATSPEC_INV}`)) { if (line.startsWith(`/// ${NATSPEC_INV}`)) {
// Assign the header of the invariant doc. // Assign the header of the invariant doc.
// TODO: Handle ambiguous case for `INVARIANT: ` prefix. // TODO: Handle ambiguous case for `INVARIANT: ` prefix.
// TODO: Handle multi-line headers.
currentDoc = { currentDoc = {
header: line.replace(`* ${NATSPEC_INV}`, '').trim(), header: line.replace(`/// ${NATSPEC_INV}`, '').trim(),
desc: '', desc: '',
} }
// If the header is multi-line, continue appending to the `currentDoc`'s header. // If the header is multi-line, continue appending to the `currentDoc`'s header.
while (BLOCK_COMMENT_HEADER_REGEX.test((line = lines[++i]))) { line = lines[++i]
currentDoc.header += ` ${line while (line.startsWith(`///`) && line.trim() !== '///') {
.replace(BLOCK_COMMENT_PREFIX_REGEX, '') currentDoc.header += ` ${line.replace(`///`, '').trim()}`
.trim()}` line = lines[++i]
} }
// Process the description // Process the description
while ((line = lines[++i]).startsWith('*')) { while ((line = lines[++i]).startsWith('///')) {
line = line.replace(BLOCK_COMMENT_PREFIX_REGEX, '').trim() line = line.replace('///', '').trim()
// If the line has any contents, insert it into the desc. // If the line has any contents, insert it into the desc.
// Otherwise, consider it a linebreak. // Otherwise, consider it a linebreak.
...@@ -98,7 +86,6 @@ const docGen = (dir: string): void => { ...@@ -98,7 +86,6 @@ const docGen = (dir: string): void => {
contract.docs.push(currentDoc) contract.docs.push(currentDoc)
} }
} }
}
// Add the contract to the array of docs // Add the contract to the array of docs
docs.push(contract) docs.push(contract)
...@@ -133,9 +120,7 @@ const docGen = (dir: string): void => { ...@@ -133,9 +120,7 @@ const docGen = (dir: string): void => {
) )
} }
/** // Generate a table of contents for all invariant docs and place it in the README.
* Generate a table of contents for all invariant docs and place it in the README.
*/
const tocGen = (): void => { const tocGen = (): void => {
const autoTOCPrefix = '<!-- START autoTOC -->\n' const autoTOCPrefix = '<!-- START autoTOC -->\n'
const autoTOCPostfix = '<!-- END autoTOC -->\n' const autoTOCPostfix = '<!-- END autoTOC -->\n'
...@@ -165,9 +150,7 @@ const tocGen = (): void => { ...@@ -165,9 +150,7 @@ const tocGen = (): void => {
) )
} }
/** // Render a `Contract` object into valid markdown.
* Render a `Contract` object into valid markdown.
*/
const renderContractDoc = (contract: Contract, header: boolean): string => { const renderContractDoc = (contract: Contract, header: boolean): string => {
const _header = header ? `# \`${contract.name}\` Invariants\n` : '' const _header = header ? `# \`${contract.name}\` Invariants\n` : ''
const docs = contract.docs const docs = contract.docs
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment