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";
import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol";
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 {
address aliased = AddressAliasHelper.applyL1ToL2Alias(_address);
address unaliased = AddressAliasHelper.undoL1ToL2Alias(aliased);
......
//SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol";
......@@ -6,41 +6,32 @@ import { AdminFaucetAuthModule } from "../periphery/faucet/authmodules/AdminFauc
import { Faucet } from "../periphery/faucet/Faucet.sol";
import { FaucetHelper } from "./Helpers.sol";
/**
* @title AdminFaucetAuthModuleTest
* @notice Tests the AdminFaucetAuthModule contract.
*/
/// @title AdminFaucetAuthModuleTest
/// @notice Tests the AdminFaucetAuthModule contract.
contract AdminFaucetAuthModuleTest is Test {
/**
* @notice The admin of the `AdminFaucetAuthModule` contract.
*/
/// @notice The admin of the `AdminFaucetAuthModule` contract.
address internal admin;
/**
* @notice Private key of the `admin`.
*/
/// @notice Private key of the `admin`.
uint256 internal adminKey;
/**
* @notice Not an admin of the `AdminFaucetAuthModule` contract.
*/
/// @notice Not an admin of the `AdminFaucetAuthModule` contract.
address internal nonAdmin;
/**
* @notice Private key of the `nonAdmin`.
*/
/// @notice Private key of the `nonAdmin`.
uint256 internal nonAdminKey;
/**
* @notice An instance of the `AdminFaucetAuthModule` contract.
*/
/// @notice An instance of the `AdminFaucetAuthModule` contract.
AdminFaucetAuthModule internal adminFam;
/**
* @notice An instance of the `FaucetHelper` contract.
*/
/// @notice An instance of the `FaucetHelper` contract.
FaucetHelper internal faucetHelper;
string internal adminFamName = "AdminFAM";
string internal adminFamVersion = "1";
/**
* @notice Deploy the `AdminFaucetAuthModule` contract.
*/
/// @notice Deploy the `AdminFaucetAuthModule` contract.
function setUp() external {
adminKey = 0xB0B0B0B0;
admin = vm.addr(adminKey);
......@@ -53,10 +44,7 @@ contract AdminFaucetAuthModuleTest is Test {
faucetHelper = new FaucetHelper();
}
/**
* @notice Get signature as a bytes blob.
*
*/
/// @notice Get signature as a bytes blob.
function _getSignature(uint256 _signingPrivateKey, bytes32 _digest)
internal
pure
......@@ -68,11 +56,9 @@ contract AdminFaucetAuthModuleTest is Test {
return signature;
}
/**
* @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
* corresponding public key to _issuerPrivateKey.
*/
/// @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
/// corresponding public key to _issuerPrivateKey.
function issueProofWithEIP712Domain(
uint256 _issuerPrivateKey,
bytes memory _eip712Name,
......@@ -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 {
bytes32 nonce = faucetHelper.consumeNonce();
address fundsReceiver = makeAddr("fundsReceiver");
......@@ -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 {
bytes32 nonce = faucetHelper.consumeNonce();
address fundsReceiver = makeAddr("fundsReceiver");
......@@ -157,10 +139,8 @@ contract AdminFaucetAuthModuleTest is Test {
);
}
/**
* @notice assert that verify returns false for proofs where the id in the proof is different
* than the id in the call to verify.
*/
/// @notice Assert that verify returns false for proofs where the id in the proof is different
/// than the id in the call to verify.
function test_proofWithWrongId_verify_succeeds() external {
bytes32 nonce = faucetHelper.consumeNonce();
address fundsReceiver = makeAddr("fundsReceiver");
......
//SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
/* Testing utilities */
// Testing utilities
import { Test } from "forge-std/Test.sol";
import { TestERC20 } from "./Helpers.sol";
import { TestERC721 } from "./Helpers.sol";
......@@ -53,12 +53,12 @@ contract AssetReceiver_Initializer is Test {
}
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 {
assertEq(address(alice), assetReceiver.owner());
}
// Tests that receive works as inteded
/// @notice Tests that receive works as inteded.
function test_receive_succeeds() external {
// Check that contract balance is 0 initially
assertEq(address(assetReceiver).balance, 0);
......@@ -74,7 +74,8 @@ contract AssetReceiverTest is AssetReceiver_Initializer {
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 {
// Check contract initial balance
assertEq(address(assetReceiver).balance, 0);
......@@ -96,14 +97,14 @@ contract AssetReceiverTest is AssetReceiver_Initializer {
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 {
vm.deal(address(assetReceiver), 1 ether);
vm.expectRevert("UNAUTHORIZED");
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 {
assertEq(address(assetReceiver).balance, 0);
......@@ -124,14 +125,14 @@ contract AssetReceiverTest is AssetReceiver_Initializer {
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 {
vm.deal(address(assetReceiver), 1 ether);
vm.expectRevert("UNAUTHORIZED");
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 {
// check balances before the call
assertEq(testERC20.balanceOf(address(assetReceiver)), 0);
......@@ -152,14 +153,14 @@ contract AssetReceiverTest is AssetReceiver_Initializer {
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 {
deal(address(testERC20), address(assetReceiver), 100_000);
vm.expectRevert("UNAUTHORIZED");
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 {
// check balances before the call
assertEq(testERC20.balanceOf(address(assetReceiver)), 0);
......@@ -180,14 +181,14 @@ contract AssetReceiverTest is AssetReceiver_Initializer {
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 {
deal(address(testERC20), address(assetReceiver), 100_000);
vm.expectRevert("UNAUTHORIZED");
assetReceiver.withdrawERC20(testERC20, alice, 50_000);
}
// Test withdrawERC721 from owner
/// @notice Test withdrawERC721 from owner.
function test_withdrawERC721_succeeds() external {
// Check owner of the token before calling withdrawERC721
assertEq(testERC721.ownerOf(DEFAULT_TOKEN_ID), alice);
......@@ -208,7 +209,7 @@ contract AssetReceiverTest is AssetReceiver_Initializer {
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 {
vm.prank(alice);
testERC721.transferFrom(alice, address(assetReceiver), DEFAULT_TOKEN_ID);
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
/* Testing utilities */
// Testing utilities
import { Test } from "forge-std/Test.sol";
import { Vm } from "forge-std/Vm.sol";
import "./CommonTest.t.sol";
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
// Testing utilities
......
//SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol";
import { CheckBalanceHigh } from "../periphery/drippie/dripchecks/CheckBalanceHigh.sol";
/**
* @title CheckBalanceHighTest
* @notice Tests the CheckBalanceHigh contract via fuzzing both the success case
* and the failure case.
*/
/// @title CheckBalanceHighTest
/// @notice Tests the CheckBalanceHigh contract via fuzzing both the success case
/// and the failure case.
contract CheckBalanceHighTest is Test {
/**
* @notice An instance of the CheckBalanceHigh contract.
*/
/// @notice An instance of the CheckBalanceHigh contract.
CheckBalanceHigh c;
/**
* @notice Deploy the `CheckTrue` contract.
*/
/// @notice Deploy the `CheckTrue` contract.
function setUp() external {
c = new CheckBalanceHigh();
}
/**
* @notice Fuzz the `check` function and assert that it always returns true
* when the target's balance is larger than the threshold.
*/
/// @notice Fuzz the `check` function and assert that it always returns true
/// when the target's balance is larger than the threshold.
function testFuzz_check_succeeds(address _target, uint256 _threshold) external {
CheckBalanceHigh.Params memory p = CheckBalanceHigh.Params({
target: _target,
......@@ -39,10 +31,8 @@ contract CheckBalanceHighTest is Test {
assertEq(c.check(abi.encode(p)), true);
}
/**
* @notice Fuzz the `check` function and assert that it always returns false
* when the target's balance is smaller than the threshold.
*/
/// @notice Fuzz the `check` function and assert that it always returns false
/// when the target's balance is smaller than the threshold.
function testFuzz_check_lowBalance_fails(address _target, uint256 _threshold) external {
CheckBalanceHigh.Params memory p = CheckBalanceHigh.Params({
target: _target,
......
//SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol";
import { CheckBalanceLow } from "../periphery/drippie/dripchecks/CheckBalanceLow.sol";
/**
* @title CheckBalanceLowTest
* @notice Tests the CheckBalanceLow contract via fuzzing both the success case
* and the failure case.
*/
/// @title CheckBalanceLowTest
/// @notice Tests the CheckBalanceLow contract via fuzzing both the success case
/// and the failure case.
contract CheckBalanceLowTest is Test {
/**
* @notice An instance of the CheckBalanceLow contract.
*/
/// @notice An instance of the CheckBalanceLow contract.
CheckBalanceLow c;
/**
* @notice Deploy the `CheckBalanceLow` contract.
*/
/// @notice Deploy the `CheckBalanceLow` contract.
function setUp() external {
c = new CheckBalanceLow();
}
/**
* @notice Fuzz the `check` function and assert that it always returns true
* when the target's balance is smaller than the threshold.
*/
/// @notice Fuzz the `check` function and assert that it always returns true
/// when the target's balance is smaller than the threshold.
function testFuzz_check_succeeds(address _target, uint256 _threshold) external {
CheckBalanceLow.Params memory p = CheckBalanceLow.Params({
target: _target,
......@@ -37,10 +29,8 @@ contract CheckBalanceLowTest is Test {
assertEq(c.check(abi.encode(p)), true);
}
/**
* @notice Fuzz the `check` function and assert that it always returns false
* when the target's balance is larger than the threshold.
*/
/// @notice Fuzz the `check` function and assert that it always returns false
/// when the target's balance is larger than the threshold.
function testFuzz_check_highBalance_fails(address _target, uint256 _threshold) external {
CheckBalanceLow.Params memory p = CheckBalanceLow.Params({
target: _target,
......
//SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol";
......@@ -7,11 +7,9 @@ import {
IGelatoTreasury
} from "../periphery/drippie/dripchecks/CheckGelatoLow.sol";
/**
* @title MockGelatoTreasury
* @notice Mocks the Gelato treasury for testing purposes. Allows arbitrary
* setting of user balances.
*/
/// @title MockGelatoTreasury
/// @notice Mocks the Gelato treasury for testing purposes. Allows arbitrary
/// setting of user balances.
contract MockGelatoTreasury is IGelatoTreasury {
mapping(address => mapping(address => uint256)) private tokenBalances;
......@@ -28,39 +26,27 @@ contract MockGelatoTreasury is IGelatoTreasury {
}
}
/**
* @title CheckGelatoLowTest
* @notice Tests the CheckBalanceHigh contract via fuzzing both the success case
* and the failure case.
*/
/// @title CheckGelatoLowTest
/// @notice Tests the CheckBalanceHigh contract via fuzzing both the success case
/// and the failure case.
contract CheckGelatoLowTest is Test {
/**
* @notice An instance of the CheckGelatoLow contract.
*/
/// @notice An instance of the CheckGelatoLow contract.
CheckGelatoLow c;
/**
* @notice An instance of the MockGelatoTreasury contract.
*/
/// @notice An instance of the MockGelatoTreasury contract.
MockGelatoTreasury gelato;
/**
* @notice The account Gelato uses to represent ether
*/
/// @notice The account Gelato uses to represent ether
address internal constant eth = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
/**
* @notice Deploy the `CheckGelatoLow` and `MockGelatoTreasury` contracts.
*/
/// @notice Deploy the `CheckGelatoLow` and `MockGelatoTreasury` contracts.
function setUp() external {
c = new CheckGelatoLow();
gelato = new MockGelatoTreasury();
}
/**
* @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.
*/
/// @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.
function testFuzz_check_succeeds(uint256 _threshold, address _recipient) external {
CheckGelatoLow.Params memory p = CheckGelatoLow.Params({
treasury: address(gelato),
......@@ -73,11 +59,9 @@ contract CheckGelatoLowTest is Test {
assertEq(c.check(abi.encode(p)), true);
}
/**
* @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
* to the threshold.
*/
/// @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
/// to the threshold.
function testFuzz_check_highBalance_fails(uint256 _threshold, address _recipient) external {
CheckGelatoLow.Params memory p = CheckGelatoLow.Params({
treasury: address(gelato),
......
//SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol";
import { CheckTrue } from "../periphery/drippie/dripchecks/CheckTrue.sol";
/**
* @title CheckTrueTest
* @notice Ensures that the CheckTrue DripCheck contract always returns true.
*/
/// @title CheckTrueTest
/// @notice Ensures that the CheckTrue DripCheck contract always returns true.
contract CheckTrueTest is Test {
/**
* @notice An instance of the CheckTrue contract.
*/
/// @notice An instance of the CheckTrue contract.
CheckTrue c;
/**
* @notice Deploy the `CheckTrue` contract.
*/
/// @notice Deploy the `CheckTrue` contract.
function setUp() external {
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 {
assertEq(c.check(input), true);
}
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
/* Testing utilities */
// Testing utilities
import { Test, StdUtils } from "forge-std/Test.sol";
import { L2OutputOracle } from "../L1/L2OutputOracle.sol";
import { L2ToL1MessagePasser } from "../L2/L2ToL1MessagePasser.sol";
......@@ -766,9 +766,7 @@ contract ConfigurableCaller {
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 {
if (doRevert) {
revert("ConfigurableCaller: revert");
......@@ -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 {
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 {
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 {
payload = _payload;
}
/**
* @notice Fallback function that reverts if `doRevert` is true.
* Otherwise, it does nothing.
*/
/// @notice Fallback function that reverts if `doRevert` is true.
/// Otherwise, it does nothing.
fallback() external {
if (doRevert) {
revert("ConfigurableCaller: revert");
......
//SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol";
......@@ -45,9 +45,7 @@ contract Faucet_Initializer is Test {
_initializeContracts();
}
/**
* @notice Instantiates a Faucet.
*/
/// @notice Instantiates a Faucet.
function _initializeContracts() internal {
faucet = new Faucet(faucetContractAdmin);
......@@ -76,10 +74,7 @@ contract Faucet_Initializer is Test {
vm.stopPrank();
}
/**
* @notice Get signature as a bytes blob.
*
*/
/// @notice Get signature as a bytes blob.
function _getSignature(uint256 _signingPrivateKey, bytes32 _digest)
internal
pure
......@@ -91,11 +86,9 @@ contract Faucet_Initializer is Test {
return signature;
}
/**
* @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
* corresponding public key to _issuerPrivateKey.
*/
/// @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
/// corresponding public key to _issuerPrivateKey.
function issueProofWithEIP712Domain(
uint256 _issuerPrivateKey,
bytes memory _eip712Name,
......
//SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
/* Testing utilities */
// Testing utilities
import { Test } from "forge-std/Test.sol";
import { AttestationStation } from "../periphery/op-nft/AttestationStation.sol";
import { OptimistAllowlist } from "../periphery/op-nft/OptimistAllowlist.sol";
......@@ -106,10 +106,7 @@ contract OptimistAllowlist_Initializer is Test {
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)
internal
pure
......@@ -149,42 +146,32 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer {
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 {
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 {
attestAllowlist(bob);
assertTrue(optimistAllowlist.isAllowedToMint(bob));
}
/**
* @notice After receiving a valid attestation from the Coinbase Quest attestor,
* the account should be able to mint.
*/
/// @notice After receiving a valid attestation from the Coinbase Quest attestor,
/// the account should be able to mint.
function test_isAllowedToMint_fromCoinbaseQuestAttestor_succeeds() external {
attestCoinbaseQuest(bob);
assertTrue(optimistAllowlist.isAllowedToMint(bob));
}
/**
* @notice Account that received an attestation from the OptimistInviter contract by going
* through the claim invite flow should be able to mint.
*/
/// @notice Account that received an attestation from the OptimistInviter contract by going
/// through the claim invite flow should be able to mint.
function test_isAllowedToMint_fromInvite_succeeds() external {
inviteAndClaim(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 {
// Ted is not the allowlist attestor
vm.prank(ted);
......@@ -196,9 +183,7 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer {
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 {
// Ted is not the coinbase quest attestor
vm.prank(ted);
......@@ -210,10 +195,8 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer {
assertFalse(optimistAllowlist.isAllowedToMint(bob));
}
/**
* @notice Claiming an invite on the non-official OptimistInviter contract should not allow
* minting.
*/
/// @notice Claiming an invite on the non-official OptimistInviter contract should not allow
/// minting.
function test_isAllowedToMint_fromWrongOptimistInviter_fails() external {
vm.prank(ted);
attestationStation.attest(
......@@ -224,9 +207,7 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer {
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 {
attestAllowlist(bob);
attestCoinbaseQuest(bob);
......@@ -246,9 +227,7 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer {
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 {
// First sends correct attestation
attestAllowlist(bob);
......@@ -264,9 +243,7 @@ contract OptimistAllowlistTest is OptimistAllowlist_Initializer {
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 {
// First sends correct attestation
attestAllowlist(bob);
......
......@@ -3,10 +3,8 @@ pragma solidity ^0.8.0;
import { Bytes32AddressLib } from "@rari-capital/solmate/src/utils/Bytes32AddressLib.sol";
/**
* @title LibRLP
* @notice Via https://github.com/Rari-Capital/solmate/issues/207.
*/
/// @title LibRLP
/// @notice Via https://github.com/Rari-Capital/solmate/issues/207.
library LibRLP {
using Bytes32AddressLib for bytes32;
......
//SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
/* Testing utilities */
// Testing utilities
import { Test } from "forge-std/Test.sol";
import { CallRecorder } from "./Helpers.sol";
import { Reverter } from "./Helpers.sol";
......@@ -34,12 +34,12 @@ contract Transactor_Initializer is Test {
}
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 {
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 {
// Initialize call data
bytes memory data = abi.encodeWithSelector(callRecorded.record.selector);
......@@ -49,7 +49,7 @@ contract TransactorTest is Transactor_Initializer {
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 {
// Initialize call data
bytes memory data = abi.encodeWithSelector(callRecorded.record.selector);
......@@ -59,6 +59,7 @@ contract TransactorTest is Transactor_Initializer {
transactor.CALL(address(callRecorded), data, 200_000 wei);
}
/// @notice Deletate call succeeds.
function test_delegateCall_succeeds() external {
// Initialize call data
bytes memory data = abi.encodeWithSelector(reverter.doRevert.selector);
......@@ -68,7 +69,7 @@ contract TransactorTest is Transactor_Initializer {
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 {
// Initialize call data
bytes memory data = abi.encodeWithSelector(reverter.doRevert.selector);
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol";
......@@ -7,9 +8,7 @@ import { AddressAliasHelper } from "../../vendor/AddressAliasHelper.sol";
contract AddressAliasHelper_Converter {
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 {
// Alias our address
address aliasedAddr = AddressAliasHelper.applyL1ToL2Alias(addr);
......@@ -39,12 +38,11 @@ contract AddressAliasHelper_AddressAliasing_Invariant is StdInvariant, Test {
targetSelector(selector);
}
/**
* @custom:invariant Address aliases are always able to be undone.
*
* Asserts that an address that has been aliased with `applyL1ToL2Alias` can always
* be unaliased with `undoL1ToL2Alias`.
*/
/// @custom:invariant Address aliases are always able to be undone.
///
/// Asserts that an address that has been aliased with
/// `applyL1ToL2Alias` can always be unaliased with
/// `undoL1ToL2Alias`.
function invariant_round_trip_aliasing() external {
// ASSERTION: The round trip aliasing done in testRoundTrip(...) should never fail.
assertEq(actor.failedRoundtrip(), false);
......
......@@ -16,10 +16,8 @@ contract Burn_EthBurner is StdUtils {
vm = _vm;
}
/**
* @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
*/
/// @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
function burnEth(uint256 _value) external {
uint256 preBurnvalue = bound(_value, 0, type(uint128).max);
......@@ -59,12 +57,10 @@ contract Burn_BurnEth_Invariant is StdInvariant, Test {
targetSelector(selector);
}
/**
* @custom:invariant `eth(uint256)` always burns the exact amount of eth passed.
*
* Asserts that when `Burn.eth(uint256)` is called, it always burns the exact amount
* of ETH passed to the function.
*/
/// @custom:invariant `eth(uint256)` always burns the exact amount of eth passed.
///
/// Asserts that when `Burn.eth(uint256)` is called, it always
/// burns the exact amount of ETH passed to the function.
function invariant_burn_eth() external {
// ASSERTION: The amount burned should always match the amount passed exactly
assertEq(actor.failedEthBurn(), false);
......
......@@ -16,11 +16,9 @@ contract Burn_GasBurner is StdUtils {
vm = _vm;
}
/**
* @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
* by the library
*/
/// @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
/// by the library
function burnGas(uint256 _value) external {
// cap the value to the max resource limit
uint256 MAX_RESOURCE_LIMIT = 8_000_000;
......@@ -59,12 +57,10 @@ contract Burn_BurnGas_Invariant is StdInvariant, Test {
targetSelector(selector);
}
/**
* @custom:invariant `gas(uint256)` always burns at least the amount of gas passed.
*
* Asserts that when `Burn.gas(uint256)` is called, it always burns at least the amount
* of gas passed to the function.
*/
/// @custom:invariant `gas(uint256)` always burns at least the amount of gas passed.
///
/// Asserts that when `Burn.gas(uint256)` is called, it always burns
/// at least the amount of gas passed to the function.
function invariant_burn_gas() external {
// ASSERTION: The amount burned should always match the amount passed exactly
assertEq(actor.failedGasBurn(), false);
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { StdUtils } from "forge-std/StdUtils.sol";
......@@ -36,9 +37,8 @@ contract RelayActor is StdUtils {
doFail = _doFail;
}
/**
* Relays a message to the `L1CrossDomainMessenger` with a random `version`, and `_message`.
*/
/// @notice Relays a message to the `L1CrossDomainMessenger` with a random `version`,
/// and `_message`.
function relay(
uint8 _version,
uint8 _value,
......@@ -143,21 +143,19 @@ contract XDM_MinGasLimits_Succeeds is XDM_MinGasLimits {
super.init(false);
}
/**
* @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
* execution of `relayMessage` after the target context's execution is
* finished, and the target context did not revert.
*
* 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 inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target
* contract.
*/
/// @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
/// execution of `relayMessage` after the target context's execution is
/// finished, and the target context did not revert.
///
/// 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 inner min gas limit is for the call from the
/// `L1CrossDomainMessenger` to the target contract.
function invariant_minGasLimits() external {
uint256 length = actor.numHashes();
for (uint256 i = 0; i < length; ++i) {
......@@ -177,22 +175,20 @@ contract XDM_MinGasLimits_Reverts is XDM_MinGasLimits {
super.init(true);
}
/**
* @custom:invariant 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.
*
* 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 inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target
* contract.
*/
/// @custom:invariant 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.
///
/// 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 inner min gas limit is for the call from the
/// `L1CrossDomainMessenger` to the target contract.
function invariant_minGasLimits() external {
uint256 length = actor.numHashes();
for (uint256 i = 0; i < length; ++i) {
......
......@@ -9,11 +9,9 @@ contract Encoding_Converter {
bool public failedRoundtripAToB;
bool public failedRoundtripBToA;
/**
* @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
* indicating if the round trip encoding failed.
*/
/// @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
/// indicating if the round trip encoding failed.
function convertRoundTripAToB(uint240 _nonce, uint16 _version) external {
// Encode the nonce and version
uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(_nonce, _version);
......@@ -30,11 +28,9 @@ contract Encoding_Converter {
}
}
/**
* @notice Takes an integer representing a packed version and nonce and attempts
* to decode them using the Encoding library before re-encoding and updates
* the test contract's state indicating if the round trip encoding failed.
*/
/// @notice Takes an integer representing a packed version and nonce and attempts
/// to decode them using the Encoding library before re-encoding and updates
/// the test contract's state indicating if the round trip encoding failed.
function convertRoundTripBToA(uint256 _versionedNonce) external {
// Decode the nonce and version
uint240 decodedNonce;
......@@ -68,22 +64,19 @@ contract Encoding_Invariant is StdInvariant, Test {
targetSelector(selector);
}
/**
* @custom:invariant `convertRoundTripAToB` never fails.
*
* Asserts that a raw versioned nonce can be encoded / decoded to reach the same raw value.
*/
/// @custom:invariant `convertRoundTripAToB` never fails.
///
/// Asserts that a raw versioned nonce can be encoded / decoded
/// to reach the same raw value.
function invariant_round_trip_encoding_AToB() external {
// ASSERTION: The round trip encoding done in testRoundTripAToB(...)
assertEq(actor.failedRoundtripAToB(), false);
}
/**
* @custom:invariant `convertRoundTripBToA` never fails.
*
* Asserts that an encoded versioned nonce can always be decoded / re-encoded to reach
* the same encoded value.
*/
/// @custom:invariant `convertRoundTripBToA` never fails.
///
/// Asserts that an encoded versioned nonce can always be decoded /
/// re-encoded to reach the same encoded value.
function invariant_round_trip_encoding_BToA() external {
// ASSERTION: The round trip encoding done in testRoundTripBToA should never
// fail.
......
......@@ -11,10 +11,9 @@ contract Hash_CrossDomainHasher {
bool public failedCrossDomainHashV0;
bool public failedCrossDomainHashV1;
/**
* @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 should revert.
*/
/// @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
/// should revert.
function hashCrossDomainMessageHighVersion(
uint16 _version,
uint240 _nonce,
......@@ -37,10 +36,9 @@ contract Hash_CrossDomainHasher {
}
}
/**
* @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 directly
*/
/// @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
/// directly.
function hashCrossDomainMessageV0(
uint240 _nonce,
address _sender,
......@@ -75,10 +73,9 @@ contract Hash_CrossDomainHasher {
}
}
/**
* @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 directly
*/
/// @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
/// directly.
function hashCrossDomainMessageV1(
uint240 _nonce,
address _sender,
......@@ -133,36 +130,31 @@ contract Hashing_Invariant is StdInvariant, Test {
targetSelector(selector);
}
/**
* @custom:invariant `hashCrossDomainMessage` reverts if `version` is > `1`.
*
* The `hashCrossDomainMessage` function should always revert if the `version` passed is > `1`.
*/
/// @custom:invariant `hashCrossDomainMessage` reverts if `version` is > `1`.
///
/// The `hashCrossDomainMessage` function should always revert if
/// the `version` passed is > `1`.
function invariant_hash_xdomain_msg_high_version() external {
// ASSERTION: The round trip aliasing done in testRoundTrip(...) should never fail.
assertFalse(actor.failedCrossDomainHashHighVersion());
}
/**
* @custom:invariant `version` = `0`: `hashCrossDomainMessage` and `hashCrossDomainMessageV0`
* are equivalent.
*
* If the version passed is 0, `hashCrossDomainMessage` and `hashCrossDomainMessageV0` should be
* equivalent.
*/
/// @custom:invariant `version` = `0`: `hashCrossDomainMessage` and `hashCrossDomainMessageV0`
/// are equivalent.
///
/// If the version passed is 0, `hashCrossDomainMessage` and
/// `hashCrossDomainMessageV0` should be equivalent.
function invariant_hash_xdomain_msg_0() external {
// ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV0
// should always match when the version passed is 0
assertFalse(actor.failedCrossDomainHashV0());
}
/**
* @custom:invariant `version` = `1`: `hashCrossDomainMessage` and `hashCrossDomainMessageV1`
* are equivalent.
*
* If the version passed is 1, `hashCrossDomainMessage` and `hashCrossDomainMessageV1` should be
* equivalent.
*/
/// @custom:invariant `version` = `1`: `hashCrossDomainMessage` and `hashCrossDomainMessageV1`
/// are equivalent.
///
/// If the version passed is 1, `hashCrossDomainMessage` and
/// `hashCrossDomainMessageV1` should be equivalent.
function invariant_hash_xdomain_msg_1() external {
// ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV1
// should always match when the version passed is 1
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { L2OutputOracle_Initializer } from "../CommonTest.t.sol";
......@@ -13,9 +14,7 @@ contract L2OutputOracle_Proposer {
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(
bytes32 _outputRoot,
uint256 _l2BlockNumber,
......@@ -49,13 +48,11 @@ contract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is L2OutputOracle_In
targetSelector(selector);
}
/**
* @custom:invariant The block number of the output root proposals should monotonically
* increase.
*
* When a new output is submitted, it should never be allowed to correspond to a block
* number that is less than the current output.
*/
/// @custom:invariant The block number of the output root proposals should monotonically
/// increase.
///
/// When a new output is submitted, it should never be allowed to
/// correspond to a block number that is less than the current output.
function invariant_monotonicBlockNumIncrease() external {
// Assert that the block number of proposals must monotonically increase.
assertTrue(oracle.nextBlockNumber() >= oracle.latestBlockNumber());
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { StdUtils } from "forge-std/Test.sol";
......@@ -148,13 +149,11 @@ contract OptimismPortal_Deposit_Invariant is Portal_Initializer {
targetSelector(selector);
}
/**
* @custom:invariant Deposits of any value should always succeed unless
* `_to` = `address(0)` or `_isCreation` = `true`.
*
* All deposits, barring creation transactions and transactions sent to `address(0)`,
* should always succeed.
*/
/// @custom:invariant Deposits of any value should always succeed unless
/// `_to` = `address(0)` or `_isCreation` = `true`.
///
/// All deposits, barring creation transactions and transactions
/// sent to `address(0)`, should always succeed.
function invariant_deposit_completes() external {
assertEq(actor.failedToComplete(), false);
}
......@@ -178,13 +177,11 @@ contract OptimismPortal_CannotTimeTravel is OptimismPortal_Invariant_Harness {
excludeSender(address(multisig));
}
/**
* @custom:invariant `finalizeWithdrawalTransaction` should revert if the finalization
* period has not elapsed.
*
* A withdrawal that has been proven should not be able to be finalized until after
* the finalization period has elapsed.
*/
/// @custom:invariant `finalizeWithdrawalTransaction` should revert if the finalization
/// period has not elapsed.
///
/// A withdrawal that has been proven should not be able to be finalized
/// until after the finalization period has elapsed.
function invariant_cannotFinalizeBeforePeriodHasPassed() external {
vm.expectRevert("OptimismPortal: proven withdrawal finalization period has not elapsed");
op.finalizeWithdrawalTransaction(_defaultTx);
......@@ -215,13 +212,11 @@ contract OptimismPortal_CannotFinalizeTwice is OptimismPortal_Invariant_Harness
excludeSender(address(multisig));
}
/**
* @custom:invariant `finalizeWithdrawalTransaction` should revert if the withdrawal
* has already been finalized.
*
* Ensures that there is no chain of calls that can be made that allows a withdrawal
* to be finalized twice.
*/
/// @custom:invariant `finalizeWithdrawalTransaction` should revert if the withdrawal
/// has already been finalized.
///
/// Ensures that there is no chain of calls that can be made that
/// allows a withdrawal to be finalized twice.
function invariant_cannotFinalizeTwice() external {
vm.expectRevert("OptimismPortal: withdrawal has already been finalized");
op.finalizeWithdrawalTransaction(_defaultTx);
......@@ -249,14 +244,13 @@ contract OptimismPortal_CanAlwaysFinalizeAfterWindow is OptimismPortal_Invariant
excludeSender(address(multisig));
}
/**
* @custom:invariant A withdrawal should **always** be able to be finalized
* `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.
*/
/// @custom:invariant A withdrawal should **always** be able to be finalized
/// `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.
function invariant_canAlwaysFinalize() external {
uint256 bobBalanceBefore = address(bob).balance;
......
......@@ -45,10 +45,8 @@ contract ResourceMetering_User is StdUtils, ResourceMetering {
return rcfg;
}
/**
* @notice Takes the necessary parameters to allow us to burn arbitrary amounts of gas to test
* the underlying resource metering/gas market logic
*/
/// @notice Takes the necessary parameters to allow us to burn arbitrary amounts of gas to test
/// the underlying resource metering/gas market logic
function burn(uint256 _gasToBurn, bool _raiseBaseFee) public {
// Part 1: we cache the current param values and do some basic checks on them.
uint256 cachedPrevBaseFee = uint256(params.prevBaseFee);
......@@ -169,78 +167,67 @@ contract ResourceMetering_Invariant is StdInvariant, Test {
targetSelector(selector);
}
/**
* @custom:invariant The base fee should increase 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
* empty blocks in between), ensure this block's baseFee increased, but not by
* more than the max amount per block.
*/
/// @custom:invariant The base fee should increase 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 empty blocks in between), ensure this
/// block's baseFee increased, but not by more than the max amount
/// per block.
function invariant_high_usage_raise_baseFee() external {
assertFalse(actor.failedRaiseBaseFee());
}
/**
* @custom:invariant The base fee should decrease if the last 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,
* but not more than the max amount.
*/
/// @custom:invariant The base fee should decrease if the last 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, but not more than the max amount.
function invariant_low_usage_lower_baseFee() external {
assertFalse(actor.failedLowerBaseFee());
}
/**
* @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 below the
* `MINIMUM_BASE_FEE` threshold.
*/
/// @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
/// below the `MINIMUM_BASE_FEE` threshold.
function invariant_never_below_min_baseFee() external {
assertFalse(actor.failedNeverBelowMinBaseFee());
}
/**
* @custom:invariant A block can never consume more than `MAX_RESOURCE_LIMIT` gas.
*
* This test asserts that a block can never consume more than the `MAX_RESOURCE_LIMIT`
* gas threshold.
*/
/// @custom:invariant A block can never consume more than `MAX_RESOURCE_LIMIT` gas.
///
/// This test asserts that a block can never consume more than
/// the `MAX_RESOURCE_LIMIT` gas threshold.
function invariant_never_above_max_gas_limit() external {
assertFalse(actor.failedMaxGasPerBlock());
}
/**
* @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 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`
*/
/// @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
/// 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`
function invariant_never_exceed_max_increase() external {
assertFalse(actor.failedMaxRaiseBaseFeePerBlock());
}
/**
* @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 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`
*/
/// @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
/// 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`
function invariant_never_exceed_max_decrease() external {
assertFalse(actor.failedMaxLowerBaseFeePerBlock());
}
/**
* @custom:invariant The `maxBaseFeeChange` calculation over multiple blocks can never
* underflow.
*
* When calculating the `maxBaseFeeChange` after multiple empty blocks, the calculation
* should never be allowed to underflow.
*/
/// @custom:invariant The `maxBaseFeeChange` calculation over multiple blocks can never
/// underflow.
///
/// When calculating the `maxBaseFeeChange` after multiple empty blocks,
/// the calculation should never be allowed to underflow.
function invariant_never_underflow() external {
assertFalse(actor.underflow());
}
......
......@@ -23,13 +23,11 @@ contract SafeCall_Succeeds_Invariants is Test {
vm.deal(address(actor), type(uint128).max);
}
/**
* @custom:invariant If `callWithMinGas` performs a call, then it must always
* provide at least the specified minimum gas limit to the subcontext.
*
* If the check for remaining gas in `SafeCall.callWithMinGas` passes, the
* subcontext of the call below it must be provided at least `minGas` gas.
*/
/// @custom:invariant If `callWithMinGas` performs a call, then it must always
/// provide at least the specified minimum gas limit to the subcontext.
///
/// If the check for remaining gas in `SafeCall.callWithMinGas` passes, the
/// subcontext of the call below it must be provided at least `minGas` gas.
function invariant_callWithMinGas_alwaysForwardsMinGas_succeeds() public {
assertEq(actor.numCalls(), 0, "no failed calls allowed");
}
......@@ -56,14 +54,12 @@ contract SafeCall_Fails_Invariants is Test {
vm.deal(address(actor), type(uint128).max);
}
/**
* @custom:invariant `callWithMinGas` reverts if there is not enough gas to pass
* to the subcontext.
*
* 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.
*/
/// @custom:invariant `callWithMinGas` reverts if there is not enough gas to pass
/// to the subcontext.
///
/// 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.
function invariant_callWithMinGas_neverForwardsMinGas_reverts() public {
assertEq(actor.numCalls(), 0, "no successful calls allowed");
}
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol";
......@@ -37,10 +38,8 @@ contract SystemConfig_GasLimitLowerBound_Invariant is Test {
targetSelector(selector);
}
/**
* @custom:invariant The gas limit of the `SystemConfig` contract can never be lower
* than the hard-coded lower bound.
*/
/// @custom:invariant The gas limit of the `SystemConfig` contract can never be lower
/// than the hard-coded lower bound.
function invariant_gasLimitLowerBound() external {
assertTrue(config.gasLimit() >= config.minimumGasLimit());
}
......
# `AddressAliasHelper` Invariants
## 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`.
\ No newline at end of file
# `Burn.Eth` Invariants
## `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.
\ No newline at end of file
# `Burn.Gas` Invariants
## `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.
\ No newline at end of file
# `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.
**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:
- 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.
## 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:
- 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
## `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.
## `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.
\ No newline at end of file
# `Hashing` Invariants
## `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`.
## `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.
## `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.
\ No newline at end of file
# `L2OutputOracle` Invariants
## 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.
\ No newline at end of file
# `OptimismPortal` Invariants
## 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.
## `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.
## `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.
## 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.
\ No newline at end of file
# `ResourceMetering` Invariants
## 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)
## The base fee should increase if the last block used more than the target amount of gas.
**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.
## The base fee should decrease if the last block used less than the target amount of gas
**Test:** [`ResourceMetering.t.sol#L191`](../contracts/test/invariants/ResourceMetering.t.sol#L191)
## 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)
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`
**Test:** [`ResourceMetering.t.sol#L201`](../contracts/test/invariants/ResourceMetering.t.sol#L201)
## A block's base fee should never be below `MINIMUM_BASE_FEE`.
**Test:** [`ResourceMetering.t.sol#L194`](../contracts/test/invariants/ResourceMetering.t.sol#L194)
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.
**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.
## 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`
## 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`
## 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.
\ No newline at end of file
# `SafeCall` Invariants
## 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.
## `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.
\ No newline at end of file
......@@ -11,8 +11,6 @@ const BASE_INVARIANTS_DIR = path.join(
const BASE_DOCS_DIR = path.join(__dirname, '..', 'invariant-docs')
const BASE_INVARIANT_GH_URL = '../contracts/test/invariants/'
const NATSPEC_INV = '@custom:invariant'
const BLOCK_COMMENT_PREFIX_REGEX = /\*(\/)?/
const BLOCK_COMMENT_HEADER_REGEX = /\*\s(.)+/
// Represents an invariant test contract
type Contract = {
......@@ -30,10 +28,8 @@ type InvariantDoc = {
const writtenFiles = []
/**
* Lazy-parses all test files in the `contracts/test/invariants` directory to generate documentation
* on all invariant tests.
*/
// Lazy-parses all test files in the `contracts/test/invariants` directory
// to generate documentation on all invariant tests.
const docGen = (dir: string): void => {
// Grab all files within the invariants test dir
const files = fs.readdirSync(dir)
......@@ -58,33 +54,25 @@ const docGen = (dir: string): void => {
for (let i = 0; i < lines.length; 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
if (line.startsWith(`* ${NATSPEC_INV}`)) {
if (line.startsWith(`/// ${NATSPEC_INV}`)) {
// Assign the header of the invariant doc.
// TODO: Handle ambiguous case for `INVARIANT: ` prefix.
// TODO: Handle multi-line headers.
currentDoc = {
header: line.replace(`* ${NATSPEC_INV}`, '').trim(),
header: line.replace(`/// ${NATSPEC_INV}`, '').trim(),
desc: '',
}
// If the header is multi-line, continue appending to the `currentDoc`'s header.
while (BLOCK_COMMENT_HEADER_REGEX.test((line = lines[++i]))) {
currentDoc.header += ` ${line
.replace(BLOCK_COMMENT_PREFIX_REGEX, '')
.trim()}`
line = lines[++i]
while (line.startsWith(`///`) && line.trim() !== '///') {
currentDoc.header += ` ${line.replace(`///`, '').trim()}`
line = lines[++i]
}
// Process the description
while ((line = lines[++i]).startsWith('*')) {
line = line.replace(BLOCK_COMMENT_PREFIX_REGEX, '').trim()
while ((line = lines[++i]).startsWith('///')) {
line = line.replace('///', '').trim()
// If the line has any contents, insert it into the desc.
// Otherwise, consider it a linebreak.
......@@ -98,7 +86,6 @@ const docGen = (dir: string): void => {
contract.docs.push(currentDoc)
}
}
}
// Add the contract to the array of docs
docs.push(contract)
......@@ -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 autoTOCPrefix = '<!-- START autoTOC -->\n'
const autoTOCPostfix = '<!-- END autoTOC -->\n'
......@@ -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 _header = header ? `# \`${contract.name}\` Invariants\n` : ''
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