Commit 01fbb00a authored by Andreas Bigger's avatar Andreas Bigger

More styling fixes

parent 26f536dc
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
// Testing utilities
import { stdError } from "forge-std/Test.sol"; import { stdError } from "forge-std/Test.sol";
import { Portal_Initializer, CommonTest, NextImpl } from "./CommonTest.t.sol"; import { Portal_Initializer, CommonTest, NextImpl } from "./CommonTest.t.sol";
import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol";
import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; // Libraries
import { OptimismPortal } from "../L1/OptimismPortal.sol";
import { Types } from "../libraries/Types.sol"; import { Types } from "../libraries/Types.sol";
import { Hashing } from "../libraries/Hashing.sol"; import { Hashing } from "../libraries/Hashing.sol";
// Target contract dependencies
import { Proxy } from "../universal/Proxy.sol"; import { Proxy } from "../universal/Proxy.sol";
import { ResourceMetering } from "../L1/ResourceMetering.sol"; import { ResourceMetering } from "../L1/ResourceMetering.sol";
import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol";
import { L2OutputOracle } from "../L1/L2OutputOracle.sol";
// Target contract
import { OptimismPortal } from "../L1/OptimismPortal.sol";
contract OptimismPortal_Test is Portal_Initializer { contract OptimismPortal_Test is Portal_Initializer {
event Paused(address); event Paused(address);
event Unpaused(address); event Unpaused(address);
/// @dev Tests that the constructor sets the correct values.
function test_constructor_succeeds() external { function test_constructor_succeeds() external {
assertEq(address(op.L2_ORACLE()), address(oracle)); assertEq(address(op.L2_ORACLE()), address(oracle));
assertEq(op.l2Sender(), 0x000000000000000000000000000000000000dEaD); assertEq(op.l2Sender(), 0x000000000000000000000000000000000000dEaD);
assertEq(op.paused(), false); assertEq(op.paused(), false);
} }
/** /// @dev Tests that `pause` successfully pauses
* @notice The OptimismPortal can be paused by the GUARDIAN /// when called by the GUARDIAN.
*/
function test_pause_succeeds() external { function test_pause_succeeds() external {
address guardian = op.GUARDIAN(); address guardian = op.GUARDIAN();
...@@ -38,10 +45,7 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -38,10 +45,7 @@ contract OptimismPortal_Test is Portal_Initializer {
assertEq(op.paused(), true); assertEq(op.paused(), true);
} }
/** /// @dev Tests that `pause` reverts when called by a non-GUARDIAN.
* @notice The OptimismPortal reverts when an account that is not the
* GUARDIAN calls `pause()`
*/
function test_pause_onlyGuardian_reverts() external { function test_pause_onlyGuardian_reverts() external {
assertEq(op.paused(), false); assertEq(op.paused(), false);
...@@ -53,9 +57,8 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -53,9 +57,8 @@ contract OptimismPortal_Test is Portal_Initializer {
assertEq(op.paused(), false); assertEq(op.paused(), false);
} }
/** /// @dev Tests that `unpause` successfully unpauses
* @notice The OptimismPortal can be unpaused by the GUARDIAN /// when called by the GUARDIAN.
*/
function test_unpause_succeeds() external { function test_unpause_succeeds() external {
address guardian = op.GUARDIAN(); address guardian = op.GUARDIAN();
...@@ -71,10 +74,7 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -71,10 +74,7 @@ contract OptimismPortal_Test is Portal_Initializer {
assertEq(op.paused(), false); assertEq(op.paused(), false);
} }
/** /// @dev Tests that `unpause` reverts when called by a non-GUARDIAN.
* @notice The OptimismPortal reverts when an account that is not
* the GUARDIAN calls `unpause()`
*/
function test_unpause_onlyGuardian_reverts() external { function test_unpause_onlyGuardian_reverts() external {
address guardian = op.GUARDIAN(); address guardian = op.GUARDIAN();
...@@ -90,6 +90,7 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -90,6 +90,7 @@ contract OptimismPortal_Test is Portal_Initializer {
assertEq(op.paused(), true); assertEq(op.paused(), true);
} }
/// @dev Tests that `receive` successdully deposits ETH.
function test_receive_succeeds() external { function test_receive_succeeds() external {
vm.expectEmit(true, true, false, true); vm.expectEmit(true, true, false, true);
emitTransactionDeposited(alice, alice, 100, 100, 100_000, false, hex""); emitTransactionDeposited(alice, alice, 100, 100, 100_000, false, hex"");
...@@ -103,17 +104,16 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -103,17 +104,16 @@ contract OptimismPortal_Test is Portal_Initializer {
assertEq(address(op).balance, 100); assertEq(address(op).balance, 100);
} }
// Test: depositTransaction fails when contract creation has a non-zero destination address /// @dev Tests that `depositTransaction` reverts when the destination address is non-zero
/// for a contract creation deposit.
function test_depositTransaction_contractCreation_reverts() external { function test_depositTransaction_contractCreation_reverts() external {
// contract creation must have a target of address(0) // contract creation must have a target of address(0)
vm.expectRevert("OptimismPortal: must send to address(0) when creating a contract"); vm.expectRevert("OptimismPortal: must send to address(0) when creating a contract");
op.depositTransaction(address(1), 1, 0, true, hex""); op.depositTransaction(address(1), 1, 0, true, hex"");
} }
/** /// @dev Tests that `depositTransaction` reverts when the data is too large.
* @notice Prevent deposits from being too large to have a sane upper bound /// This places an upper bound on unsafe blocks sent over p2p.
* on unsafe blocks sent over the p2p network.
*/
function test_depositTransaction_largeData_reverts() external { function test_depositTransaction_largeData_reverts() external {
uint256 size = 120_001; uint256 size = 120_001;
uint64 gasLimit = op.minimumGasLimit(uint64(size)); uint64 gasLimit = op.minimumGasLimit(uint64(size));
...@@ -127,10 +127,7 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -127,10 +127,7 @@ contract OptimismPortal_Test is Portal_Initializer {
}); });
} }
/** /// @dev Tests that `depositTransaction` reverts when the gas limit is too small.
* @notice Prevent gasless deposits from being force processed in L2 by
* ensuring that they have a large enough gas limit set.
*/
function test_depositTransaction_smallGasLimit_reverts() external { function test_depositTransaction_smallGasLimit_reverts() external {
vm.expectRevert("OptimismPortal: gas limit too small"); vm.expectRevert("OptimismPortal: gas limit too small");
op.depositTransaction({ op.depositTransaction({
...@@ -142,9 +139,8 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -142,9 +139,8 @@ contract OptimismPortal_Test is Portal_Initializer {
}); });
} }
/** /// @dev Tests that `depositTransaction` succeeds for small,
* @notice Fuzz for too small of gas limits /// but sufficient, gas limits.
*/
function testFuzz_depositTransaction_smallGasLimit_succeeds( function testFuzz_depositTransaction_smallGasLimit_succeeds(
bytes memory _data, bytes memory _data,
bool _shouldFail bool _shouldFail
...@@ -166,17 +162,16 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -166,17 +162,16 @@ contract OptimismPortal_Test is Portal_Initializer {
}); });
} }
/** /// @dev Tests that `minimumGasLimit` succeeds for small calldata sizes.
* @notice Ensure that the 0 calldata case is covered and there is a linearly /// The gas limit should be 21k for 0 calldata and increase linearly
* increasing gas limit for larger calldata sizes. /// for larger calldata sizes.
*/
function test_minimumGasLimit_succeeds() external { function test_minimumGasLimit_succeeds() external {
assertEq(op.minimumGasLimit(0), 21_000); assertEq(op.minimumGasLimit(0), 21_000);
assertTrue(op.minimumGasLimit(2) > op.minimumGasLimit(1)); assertTrue(op.minimumGasLimit(2) > op.minimumGasLimit(1));
assertTrue(op.minimumGasLimit(3) > op.minimumGasLimit(2)); assertTrue(op.minimumGasLimit(3) > op.minimumGasLimit(2));
} }
// Test: depositTransaction should emit the correct log when an EOA deposits a tx with 0 value /// @dev Tests that `depositTransaction` succeeds for an EOA depositing a tx with 0 value.
function test_depositTransaction_noValueEOA_succeeds() external { function test_depositTransaction_noValueEOA_succeeds() external {
// EOA emulation // EOA emulation
vm.prank(address(this), address(this)); vm.prank(address(this), address(this));
...@@ -200,7 +195,7 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -200,7 +195,7 @@ contract OptimismPortal_Test is Portal_Initializer {
); );
} }
// Test: depositTransaction should emit the correct log when a contract deposits a tx with 0 value /// @dev Tests that `depositTransaction` succeeds for a contract depositing a tx with 0 value.
function test_depositTransaction_noValueContract_succeeds() external { function test_depositTransaction_noValueContract_succeeds() external {
vm.expectEmit(true, true, false, true); vm.expectEmit(true, true, false, true);
emitTransactionDeposited( emitTransactionDeposited(
...@@ -222,7 +217,8 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -222,7 +217,8 @@ contract OptimismPortal_Test is Portal_Initializer {
); );
} }
// Test: depositTransaction should emit the correct log when an EOA deposits a contract creation with 0 value /// @dev Tests that `depositTransaction` succeeds for an EOA
/// depositing a contract creation with 0 value.
function test_depositTransaction_createWithZeroValueForEOA_succeeds() external { function test_depositTransaction_createWithZeroValueForEOA_succeeds() external {
// EOA emulation // EOA emulation
vm.prank(address(this), address(this)); vm.prank(address(this), address(this));
...@@ -241,7 +237,8 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -241,7 +237,8 @@ contract OptimismPortal_Test is Portal_Initializer {
op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA);
} }
// Test: depositTransaction should emit the correct log when a contract deposits a contract creation with 0 value /// @dev Tests that `depositTransaction` succeeds for a contract
/// depositing a contract creation with 0 value.
function test_depositTransaction_createWithZeroValueForContract_succeeds() external { function test_depositTransaction_createWithZeroValueForContract_succeeds() external {
vm.expectEmit(true, true, false, true); vm.expectEmit(true, true, false, true);
emitTransactionDeposited( emitTransactionDeposited(
...@@ -257,7 +254,7 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -257,7 +254,7 @@ contract OptimismPortal_Test is Portal_Initializer {
op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA); op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA);
} }
// Test: depositTransaction should increase its eth balance when an EOA deposits a transaction with ETH /// @dev Tests that `depositTransaction` succeeds for an EOA depositing a tx with ETH.
function test_depositTransaction_withEthValueFromEOA_succeeds() external { function test_depositTransaction_withEthValueFromEOA_succeeds() external {
// EOA emulation // EOA emulation
vm.prank(address(this), address(this)); vm.prank(address(this), address(this));
...@@ -283,7 +280,7 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -283,7 +280,7 @@ contract OptimismPortal_Test is Portal_Initializer {
assertEq(address(op).balance, NON_ZERO_VALUE); assertEq(address(op).balance, NON_ZERO_VALUE);
} }
// Test: depositTransaction should increase its eth balance when a contract deposits a transaction with ETH /// @dev Tests that `depositTransaction` succeeds for a contract depositing a tx with ETH.
function test_depositTransaction_withEthValueFromContract_succeeds() external { function test_depositTransaction_withEthValueFromContract_succeeds() external {
vm.expectEmit(true, true, false, true); vm.expectEmit(true, true, false, true);
emitTransactionDeposited( emitTransactionDeposited(
...@@ -305,7 +302,7 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -305,7 +302,7 @@ contract OptimismPortal_Test is Portal_Initializer {
); );
} }
// Test: depositTransaction should increase its eth balance when an EOA deposits a contract creation with ETH /// @dev Tests that `depositTransaction` succeeds for an EOA depositing a contract creation with ETH.
function test_depositTransaction_withEthValueAndEOAContractCreation_succeeds() external { function test_depositTransaction_withEthValueAndEOAContractCreation_succeeds() external {
// EOA emulation // EOA emulation
vm.prank(address(this), address(this)); vm.prank(address(this), address(this));
...@@ -331,7 +328,7 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -331,7 +328,7 @@ contract OptimismPortal_Test is Portal_Initializer {
assertEq(address(op).balance, NON_ZERO_VALUE); assertEq(address(op).balance, NON_ZERO_VALUE);
} }
// Test: depositTransaction should increase its eth balance when a contract deposits a contract creation with ETH /// @dev Tests that `depositTransaction` succeeds for a contract depositing a contract creation with ETH.
function test_depositTransaction_withEthValueAndContractContractCreation_succeeds() external { function test_depositTransaction_withEthValueAndContractContractCreation_succeeds() external {
vm.expectEmit(true, true, false, true); vm.expectEmit(true, true, false, true);
emitTransactionDeposited( emitTransactionDeposited(
...@@ -354,6 +351,7 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -354,6 +351,7 @@ contract OptimismPortal_Test is Portal_Initializer {
assertEq(address(op).balance, NON_ZERO_VALUE); assertEq(address(op).balance, NON_ZERO_VALUE);
} }
/// @dev Tests that `isOutputFinalized` succeeds for an EOA depositing a tx with ETH and data.
function test_simple_isOutputFinalized_succeeds() external { function test_simple_isOutputFinalized_succeeds() external {
uint256 ts = block.timestamp; uint256 ts = block.timestamp;
vm.mockCall( vm.mockCall(
...@@ -373,6 +371,7 @@ contract OptimismPortal_Test is Portal_Initializer { ...@@ -373,6 +371,7 @@ contract OptimismPortal_Test is Portal_Initializer {
assertEq(op.isOutputFinalized(0), true); assertEq(op.isOutputFinalized(0), true);
} }
/// @dev Tests `isOutputFinalized` for a finalized output.
function test_isOutputFinalized_succeeds() external { function test_isOutputFinalized_succeeds() external {
uint256 checkpoint = oracle.nextBlockNumber(); uint256 checkpoint = oracle.nextBlockNumber();
uint256 nextOutputIndex = oracle.nextOutputIndex(); uint256 nextOutputIndex = oracle.nextOutputIndex();
...@@ -439,7 +438,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -439,7 +438,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
_proposedOutputIndex = oracle.nextOutputIndex(); _proposedOutputIndex = oracle.nextOutputIndex();
} }
// Get the system into a nice ready-to-use state. /// @dev Setup the system for a ready-to-use state.
function setUp() public override { function setUp() public override {
// Configure the oracle to return the output root we've prepared. // Configure the oracle to return the output root we've prepared.
vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1); vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);
...@@ -456,8 +455,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -456,8 +455,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
vm.deal(address(op), 0xFFFFFFFF); vm.deal(address(op), 0xFFFFFFFF);
} }
// Utility function used in the subsequent test. This is necessary to assert that the /// @dev Asserts that the reentrant call will revert.
// reentrant call will revert.
function callPortalAndExpectRevert() external payable { function callPortalAndExpectRevert() external payable {
vm.expectRevert("OptimismPortal: can only trigger one withdrawal per transaction"); vm.expectRevert("OptimismPortal: can only trigger one withdrawal per transaction");
// Arguments here don't matter, as the require check is the first thing that happens. // Arguments here don't matter, as the require check is the first thing that happens.
...@@ -467,9 +465,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -467,9 +465,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
assertFalse(op.finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx))); assertFalse(op.finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx)));
} }
/** /// @dev Tests that `proveWithdrawalTransaction` reverts when paused.
* @notice Proving withdrawal transactions should revert when paused
*/
function test_proveWithdrawalTransaction_paused_reverts() external { function test_proveWithdrawalTransaction_paused_reverts() external {
vm.prank(op.GUARDIAN()); vm.prank(op.GUARDIAN());
op.pause(); op.pause();
...@@ -483,7 +479,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -483,7 +479,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
}); });
} }
// Test: proveWithdrawalTransaction cannot prove a withdrawal with itself (the OptimismPortal) as the target. /// @dev Tests that `proveWithdrawalTransaction` reverts when the target is the portal contract.
function test_proveWithdrawalTransaction_onSelfCall_reverts() external { function test_proveWithdrawalTransaction_onSelfCall_reverts() external {
_defaultTx.target = address(op); _defaultTx.target = address(op);
vm.expectRevert("OptimismPortal: you cannot send messages to the portal contract"); vm.expectRevert("OptimismPortal: you cannot send messages to the portal contract");
...@@ -495,7 +491,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -495,7 +491,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
); );
} }
// Test: proveWithdrawalTransaction reverts if the outputRootProof does not match the output root /// @dev Tests that `proveWithdrawalTransaction` reverts when
/// the outputRootProof does not match the output root
function test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() external { function test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() external {
// Modify the version to invalidate the withdrawal proof. // Modify the version to invalidate the withdrawal proof.
_outputRootProof.version = bytes32(uint256(1)); _outputRootProof.version = bytes32(uint256(1));
...@@ -508,8 +505,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -508,8 +505,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
); );
} }
// Test: proveWithdrawalTransaction reverts if the proof is invalid due to non-existence of /// @dev Tests that `proveWithdrawalTransaction` reverts when the withdrawal is missing.
// the withdrawal.
function test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() external { function test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() external {
// modify the default test values to invalidate the proof. // modify the default test values to invalidate the proof.
_defaultTx.data = hex"abcd"; _defaultTx.data = hex"abcd";
...@@ -522,8 +518,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -522,8 +518,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
); );
} }
// Test: proveWithdrawalTransaction reverts if the passed transaction's withdrawalHash has /// @dev Tests that `proveWithdrawalTransaction` reverts when the withdrawal has already
// already been proven. /// been proven.
function test_proveWithdrawalTransaction_replayProve_reverts() external { function test_proveWithdrawalTransaction_replayProve_reverts() external {
vm.expectEmit(true, true, true, true); vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob); emit WithdrawalProven(_withdrawalHash, alice, bob);
...@@ -543,8 +539,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -543,8 +539,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
); );
} }
// Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has /// @dev Tests that `proveWithdrawalTransaction` succeeds when the withdrawal has already
// already been proven AND the output root has changed AND the l2BlockNumber stays the same. /// been proven and the output root has changed and the l2BlockNumber stays the same.
function test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() external { function test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() external {
vm.expectEmit(true, true, true, true); vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob); emit WithdrawalProven(_withdrawalHash, alice, bob);
...@@ -587,8 +583,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -587,8 +583,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
assertEq(timestamp, block.timestamp); assertEq(timestamp, block.timestamp);
} }
// Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has /// @dev Tests that `proveWithdrawalTransaction` succeeds when the withdrawal has already
// already been proven AND the output root + output index + l2BlockNumber changes. /// been proven and the output root, output index, and l2BlockNumber have changed.
function test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds() function test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds()
external external
{ {
...@@ -646,7 +642,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -646,7 +642,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
assertEq(timestamp, block.timestamp); assertEq(timestamp, block.timestamp);
} }
// Test: proveWithdrawalTransaction succeeds and emits the WithdrawalProven event. /// @dev Tests that `proveWithdrawalTransaction` succeeds.
function test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() external { function test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() external {
vm.expectEmit(true, true, true, true); vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob); emit WithdrawalProven(_withdrawalHash, alice, bob);
...@@ -658,7 +654,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -658,7 +654,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
); );
} }
// Test: finalizeWithdrawalTransaction succeeds and emits the WithdrawalFinalized event. /// @dev Tests that `finalizeWithdrawalTransaction` succeeds.
function test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() external { function test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() external {
uint256 bobBalanceBefore = address(bob).balance; uint256 bobBalanceBefore = address(bob).balance;
...@@ -679,9 +675,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -679,9 +675,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
assert(address(bob).balance == bobBalanceBefore + 100); assert(address(bob).balance == bobBalanceBefore + 100);
} }
/** /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the contract is paused.
* @notice Finalizing withdrawal transactions should revert when paused
*/
function test_finalizeWithdrawalTransaction_paused_reverts() external { function test_finalizeWithdrawalTransaction_paused_reverts() external {
vm.prank(op.GUARDIAN()); vm.prank(op.GUARDIAN());
op.pause(); op.pause();
...@@ -690,7 +684,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -690,7 +684,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
op.finalizeWithdrawalTransaction(_defaultTx); op.finalizeWithdrawalTransaction(_defaultTx);
} }
// Test: finalizeWithdrawalTransaction reverts if the withdrawal has not been proven. /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal has not been
function test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() external { function test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() external {
uint256 bobBalanceBefore = address(bob).balance; uint256 bobBalanceBefore = address(bob).balance;
...@@ -700,7 +694,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -700,7 +694,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
assert(address(bob).balance == bobBalanceBefore); assert(address(bob).balance == bobBalanceBefore);
} }
// Test: finalizeWithdrawalTransaction reverts if withdrawal not proven long enough ago. /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal has not been
/// proven long enough ago.
function test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() external { function test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() external {
uint256 bobBalanceBefore = address(bob).balance; uint256 bobBalanceBefore = address(bob).balance;
...@@ -727,8 +722,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -727,8 +722,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
assert(address(bob).balance == bobBalanceBefore); assert(address(bob).balance == bobBalanceBefore);
} }
// Test: finalizeWithdrawalTransaction reverts if the provenWithdrawal's timestamp is less /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the provenWithdrawal's timestamp
// than the L2 output oracle's starting timestamp /// is less than the L2 output oracle's starting timestamp.
function test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() external { function test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() external {
uint256 bobBalanceBefore = address(bob).balance; uint256 bobBalanceBefore = address(bob).balance;
...@@ -762,8 +757,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -762,8 +757,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
assertEq(bobBalanceBefore, address(bob).balance); assertEq(bobBalanceBefore, address(bob).balance);
} }
// Test: finalizeWithdrawalTransaction reverts if the output root proven is not the same as the /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the output root proven is not the
// output root at the time of finalization. /// same as the output root at the time of finalization.
function test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() external { function test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() external {
uint256 bobBalanceBefore = address(bob).balance; uint256 bobBalanceBefore = address(bob).balance;
...@@ -804,8 +799,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -804,8 +799,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
assertEq(bobBalanceBefore, address(bob).balance); assertEq(bobBalanceBefore, address(bob).balance);
} }
// Test: finalizeWithdrawalTransaction reverts if the output proposal's timestamp has /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the output proposal's timestamp
// not passed the finalization period. /// has not passed the finalization period.
function test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() external { function test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() external {
uint256 bobBalanceBefore = address(bob).balance; uint256 bobBalanceBefore = address(bob).balance;
...@@ -844,8 +839,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -844,8 +839,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
assertEq(bobBalanceBefore, address(bob).balance); assertEq(bobBalanceBefore, address(bob).balance);
} }
// Test: finalizeWithdrawalTransaction fails because the target reverts, /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the target reverts.
// and emits the WithdrawalFinalized event with success=false.
function test_finalizeWithdrawalTransaction_targetFails_fails() external { function test_finalizeWithdrawalTransaction_targetFails_fails() external {
uint256 bobBalanceBefore = address(bob).balance; uint256 bobBalanceBefore = address(bob).balance;
vm.etch(bob, hex"fe"); // Contract with just the invalid opcode. vm.etch(bob, hex"fe"); // Contract with just the invalid opcode.
...@@ -867,7 +861,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -867,7 +861,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
assert(address(bob).balance == bobBalanceBefore); assert(address(bob).balance == bobBalanceBefore);
} }
// Test: finalizeWithdrawalTransaction reverts if the finalization period has not yet passed. /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the finalization period
/// has not yet passed.
function test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() external { function test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() external {
// Setup the Oracle to return an output with a recent timestamp // Setup the Oracle to return an output with a recent timestamp
uint256 recentTimestamp = block.timestamp - 1000; uint256 recentTimestamp = block.timestamp - 1000;
...@@ -894,7 +889,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -894,7 +889,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
op.finalizeWithdrawalTransaction(_defaultTx); op.finalizeWithdrawalTransaction(_defaultTx);
} }
// Test: finalizeWithdrawalTransaction reverts if the withdrawal has already been finalized. /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal has already been
/// finalized.
function test_finalizeWithdrawalTransaction_onReplay_reverts() external { function test_finalizeWithdrawalTransaction_onReplay_reverts() external {
vm.expectEmit(true, true, true, true); vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob); emit WithdrawalProven(_withdrawalHash, alice, bob);
...@@ -914,7 +910,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -914,7 +910,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
op.finalizeWithdrawalTransaction(_defaultTx); op.finalizeWithdrawalTransaction(_defaultTx);
} }
// Test: finalizeWithdrawalTransaction reverts if insufficient gas is supplied. /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal transaction
/// does not have enough gas to execute.
function test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() external { function test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() external {
// This number was identified through trial and error. // This number was identified through trial and error.
uint256 gasLimit = 150_000; uint256 gasLimit = 150_000;
...@@ -961,8 +958,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -961,8 +958,8 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
op.finalizeWithdrawalTransaction{ gas: gasLimit }(insufficientGasTx); op.finalizeWithdrawalTransaction{ gas: gasLimit }(insufficientGasTx);
} }
// Test: finalizeWithdrawalTransaction reverts if a sub-call attempts to finalize another /// @dev Tests that `finalizeWithdrawalTransaction` reverts if a sub-call attempts to finalize
// withdrawal. /// another withdrawal.
function test_finalizeWithdrawalTransaction_onReentrancy_reverts() external { function test_finalizeWithdrawalTransaction_onReentrancy_reverts() external {
uint256 bobBalanceBefore = address(bob).balance; uint256 bobBalanceBefore = address(bob).balance;
...@@ -1020,6 +1017,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer { ...@@ -1020,6 +1017,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
assert(address(bob).balance == bobBalanceBefore); assert(address(bob).balance == bobBalanceBefore);
} }
/// @dev Tests that `finalizeWithdrawalTransaction` succeeds.
function testDiff_finalizeWithdrawalTransaction_succeeds( function testDiff_finalizeWithdrawalTransaction_succeeds(
address _sender, address _sender,
address _target, address _target,
...@@ -1101,12 +1099,14 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer { ...@@ -1101,12 +1099,14 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer {
Proxy internal proxy; Proxy internal proxy;
uint64 initialBlockNum; uint64 initialBlockNum;
/// @dev Sets up the test.
function setUp() public override { function setUp() public override {
super.setUp(); super.setUp();
initialBlockNum = uint64(block.number); initialBlockNum = uint64(block.number);
proxy = Proxy(payable(address(op))); proxy = Proxy(payable(address(op)));
} }
/// @dev Tests that the proxy is initialized correctly.
function test_params_initValuesOnProxy_succeeds() external { function test_params_initValuesOnProxy_succeeds() external {
OptimismPortal p = OptimismPortal(payable(address(proxy))); OptimismPortal p = OptimismPortal(payable(address(proxy)));
...@@ -1118,16 +1118,19 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer { ...@@ -1118,16 +1118,19 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer {
assertEq(prevBlockNum, initialBlockNum); assertEq(prevBlockNum, initialBlockNum);
} }
/// @dev Tests that the proxy cannot be initialized twice.
function test_initialize_cannotInitProxy_reverts() external { function test_initialize_cannotInitProxy_reverts() external {
vm.expectRevert("Initializable: contract is already initialized"); vm.expectRevert("Initializable: contract is already initialized");
OptimismPortal(payable(proxy)).initialize(false); OptimismPortal(payable(proxy)).initialize(false);
} }
/// @dev Tests that the implementation cannot be initialized twice.
function test_initialize_cannotInitImpl_reverts() external { function test_initialize_cannotInitImpl_reverts() external {
vm.expectRevert("Initializable: contract is already initialized"); vm.expectRevert("Initializable: contract is already initialized");
OptimismPortal(opImpl).initialize(false); OptimismPortal(opImpl).initialize(false);
} }
/// @dev Tests that the proxy can be upgraded.
function test_upgradeToAndCall_upgrading_succeeds() external { function test_upgradeToAndCall_upgrading_succeeds() external {
// Check an unused slot before upgrading. // Check an unused slot before upgrading.
bytes32 slot21Before = vm.load(address(op), bytes32(uint256(21))); bytes32 slot21Before = vm.load(address(op), bytes32(uint256(21)));
...@@ -1148,21 +1151,16 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer { ...@@ -1148,21 +1151,16 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer {
} }
} }
/** /// @title OptimismPortalResourceFuzz_Test
* @title OptimismPortalResourceFuzz_Test /// @dev Test various values of the resource metering config to ensure that deposits cannot be
* @dev Test various values of the resource metering config to ensure that deposits cannot be /// broken by changing the config.
* broken by changing the config.
*/
contract OptimismPortalResourceFuzz_Test is Portal_Initializer { contract OptimismPortalResourceFuzz_Test is Portal_Initializer {
/**
* @dev The max gas limit observed throughout this test. Setting this too high can cause /// @dev The max gas limit observed throughout this test. Setting this too high can cause
* the test to take too long to run. /// the test to take too long to run.
*/
uint256 constant MAX_GAS_LIMIT = 30_000_000; uint256 constant MAX_GAS_LIMIT = 30_000_000;
/** /// @dev Test that various values of the resource metering config will not break deposits.
* @dev Test that various values of the resource metering config will not break deposits.
*/
function testFuzz_systemConfigDeposit_succeeds( function testFuzz_systemConfigDeposit_succeeds(
uint32 _maxResourceLimit, uint32 _maxResourceLimit,
uint8 _elasticityMultiplier, uint8 _elasticityMultiplier,
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
// Testing utilities
import { Test } from "forge-std/Test.sol"; import { Test } from "forge-std/Test.sol";
import { ResourceMetering } from "../L1/ResourceMetering.sol";
import { Proxy } from "../universal/Proxy.sol"; // Libraries
import { Constants } from "../libraries/Constants.sol"; import { Constants } from "../libraries/Constants.sol";
// Target contract dependencies
import { Proxy } from "../universal/Proxy.sol";
// Target contract
import { ResourceMetering } from "../L1/ResourceMetering.sol";
contract MeterUser is ResourceMetering { contract MeterUser is ResourceMetering {
ResourceMetering.ResourceConfig public innerConfig; ResourceMetering.ResourceConfig public innerConfig;
...@@ -50,20 +57,20 @@ contract MeterUser is ResourceMetering { ...@@ -50,20 +57,20 @@ contract MeterUser is ResourceMetering {
} }
} }
/** /// @title ResourceMetering_Test
* @title ResourceConfig /// @dev Tests are based on the default config values.
* @notice The tests are based on the default config values. It is expected that /// It is expected that these config values are used in production.
* the config values used in these tests are ran in production.
*/
contract ResourceMetering_Test is Test { contract ResourceMetering_Test is Test {
MeterUser internal meter; MeterUser internal meter;
uint64 initialBlockNum; uint64 initialBlockNum;
/// @dev Sets up the test contract.
function setUp() public { function setUp() public {
meter = new MeterUser(); meter = new MeterUser();
initialBlockNum = uint64(block.number); initialBlockNum = uint64(block.number);
} }
/// @dev Tests that the initial resource params are set correctly.
function test_meter_initialResourceParams_succeeds() external { function test_meter_initialResourceParams_succeeds() external {
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params(); (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();
ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig(); ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();
...@@ -73,6 +80,7 @@ contract ResourceMetering_Test is Test { ...@@ -73,6 +80,7 @@ contract ResourceMetering_Test is Test {
assertEq(prevBlockNum, initialBlockNum); assertEq(prevBlockNum, initialBlockNum);
} }
/// @dev Tests that updating the resource params to the same values works correctly.
function test_meter_updateParamsNoChange_succeeds() external { function test_meter_updateParamsNoChange_succeeds() external {
meter.use(0); // equivalent to just updating the base fee and block number meter.use(0); // equivalent to just updating the base fee and block number
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params(); (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();
...@@ -84,6 +92,7 @@ contract ResourceMetering_Test is Test { ...@@ -84,6 +92,7 @@ contract ResourceMetering_Test is Test {
assertEq(postBlockNum, prevBlockNum); assertEq(postBlockNum, prevBlockNum);
} }
/// @dev Tests that updating the initial block number sets the meter params correctly.
function test_meter_updateOneEmptyBlock_succeeds() external { function test_meter_updateOneEmptyBlock_succeeds() external {
vm.roll(initialBlockNum + 1); vm.roll(initialBlockNum + 1);
meter.use(0); meter.use(0);
...@@ -94,6 +103,7 @@ contract ResourceMetering_Test is Test { ...@@ -94,6 +103,7 @@ contract ResourceMetering_Test is Test {
assertEq(prevBlockNum, initialBlockNum + 1); assertEq(prevBlockNum, initialBlockNum + 1);
} }
/// @dev Tests that updating the initial block number sets the meter params correctly.
function test_meter_updateTwoEmptyBlocks_succeeds() external { function test_meter_updateTwoEmptyBlocks_succeeds() external {
vm.roll(initialBlockNum + 2); vm.roll(initialBlockNum + 2);
meter.use(0); meter.use(0);
...@@ -104,6 +114,7 @@ contract ResourceMetering_Test is Test { ...@@ -104,6 +114,7 @@ contract ResourceMetering_Test is Test {
assertEq(prevBlockNum, initialBlockNum + 2); assertEq(prevBlockNum, initialBlockNum + 2);
} }
/// @dev Tests that updating the initial block number sets the meter params correctly.
function test_meter_updateTenEmptyBlocks_succeeds() external { function test_meter_updateTenEmptyBlocks_succeeds() external {
vm.roll(initialBlockNum + 10); vm.roll(initialBlockNum + 10);
meter.use(0); meter.use(0);
...@@ -114,6 +125,7 @@ contract ResourceMetering_Test is Test { ...@@ -114,6 +125,7 @@ contract ResourceMetering_Test is Test {
assertEq(prevBlockNum, initialBlockNum + 10); assertEq(prevBlockNum, initialBlockNum + 10);
} }
/// @dev Tests that updating the gas delta sets the meter params correctly.
function test_meter_updateNoGasDelta_succeeds() external { function test_meter_updateNoGasDelta_succeeds() external {
ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig(); ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();
uint256 target = uint256(rcfg.maxResourceLimit) / uint256(rcfg.elasticityMultiplier); uint256 target = uint256(rcfg.maxResourceLimit) / uint256(rcfg.elasticityMultiplier);
...@@ -125,6 +137,7 @@ contract ResourceMetering_Test is Test { ...@@ -125,6 +137,7 @@ contract ResourceMetering_Test is Test {
assertEq(prevBlockNum, initialBlockNum); assertEq(prevBlockNum, initialBlockNum);
} }
/// @dev Tests that the meter params are set correctly for the maximum gas delta.
function test_meter_useMax_succeeds() external { function test_meter_useMax_succeeds() external {
ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig(); ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();
uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier); uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);
...@@ -141,15 +154,9 @@ contract ResourceMetering_Test is Test { ...@@ -141,15 +154,9 @@ contract ResourceMetering_Test is Test {
assertEq(postBaseFee, 2125000000); assertEq(postBaseFee, 2125000000);
} }
/** /// @dev Tests that the metered modifier reverts if the baseFeeMaxChangeDenominator is set to 1.
* @notice This tests that the metered modifier reverts if /// Since the metered modifier internally calls solmate's powWad function, it will revert
* the ResourceConfig baseFeeMaxChangeDenominator /// with the error string "UNDEFINED" since the first parameter will be computed as 0.
* is set to 1.
* Since the metered modifier internally calls
* solmate's powWad function, it will revert
* with the error string "UNDEFINED" since the
* first parameter will be computed as 0.
*/
function test_meter_denominatorEq1_reverts() external { function test_meter_denominatorEq1_reverts() external {
ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig(); ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();
uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier); uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);
...@@ -167,6 +174,7 @@ contract ResourceMetering_Test is Test { ...@@ -167,6 +174,7 @@ contract ResourceMetering_Test is Test {
meter.use(0); meter.use(0);
} }
/// @dev Tests that the metered modifier reverts if the value is greater than allowed.
function test_meter_useMoreThanMax_reverts() external { function test_meter_useMoreThanMax_reverts() external {
ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig(); ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();
uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier); uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);
...@@ -176,8 +184,7 @@ contract ResourceMetering_Test is Test { ...@@ -176,8 +184,7 @@ contract ResourceMetering_Test is Test {
meter.use(target * elasticityMultiplier + 1); meter.use(target * elasticityMultiplier + 1);
} }
// Demonstrates that the resource metering arithmetic can tolerate very large gaps between /// @dev Tests that resource metering can handle large gaps between deposits.
// deposits.
function testFuzz_meter_largeBlockDiff_succeeds(uint64 _amount, uint256 _blockDiff) external { function testFuzz_meter_largeBlockDiff_succeeds(uint64 _amount, uint256 _blockDiff) external {
// This test fails if the following line is commented out. // This test fails if the following line is commented out.
// At 12 seconds per block, this number is effectively unreachable. // At 12 seconds per block, this number is effectively unreachable.
...@@ -193,11 +200,9 @@ contract ResourceMetering_Test is Test { ...@@ -193,11 +200,9 @@ contract ResourceMetering_Test is Test {
} }
} }
/** /// @title CustomMeterUser
* @title CustomMeterUser /// @notice A simple wrapper around `ResourceMetering` that allows the initial
* @notice A simple wrapper around `ResourceMetering` that allows the initial /// params to be set in the constructor.
* params to be set in the constructor.
*/
contract CustomMeterUser is ResourceMetering { contract CustomMeterUser is ResourceMetering {
uint256 public startGas; uint256 public startGas;
uint256 public endGas; uint256 public endGas;
...@@ -230,15 +235,13 @@ contract CustomMeterUser is ResourceMetering { ...@@ -230,15 +235,13 @@ contract CustomMeterUser is ResourceMetering {
} }
} }
/** /// @title ArtifactResourceMetering_Test
* @title ArtifactResourceMetering_Test /// @notice A table test that sets the state of the ResourceParams and then requests
* @notice A table test that sets the state of the ResourceParams and then requests /// various amounts of gas. This test ensures that a wide range of values
* various amounts of gas. This test ensures that a wide range of values /// can safely be used with the `ResourceMetering` contract.
* can safely be used with the `ResourceMetering` contract. /// It also writes a CSV file to disk that includes useful information
* It also writes a CSV file to disk that includes useful information /// about how much gas is used and how expensive it is in USD terms to
* about how much gas is used and how expensive it is in USD terms to /// purchase the deposit gas.
* purchase the deposit gas.
*/
contract ArtifactResourceMetering_Test is Test { contract ArtifactResourceMetering_Test is Test {
uint128 internal minimumBaseFee; uint128 internal minimumBaseFee;
uint128 internal maximumBaseFee; uint128 internal maximumBaseFee;
...@@ -257,10 +260,7 @@ contract ArtifactResourceMetering_Test is Test { ...@@ -257,10 +260,7 @@ contract ArtifactResourceMetering_Test is Test {
bytes32 internal emptyReturnData = bytes32 internal emptyReturnData =
0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
/** /// @dev Sets up the tests with constants from the ResourceMetering contract.
* @notice Sets up the tests by getting constants from the ResourceMetering
* contract.
*/
function setUp() public { function setUp() public {
vm.roll(1_000_000); vm.roll(1_000_000);
...@@ -275,11 +275,8 @@ contract ArtifactResourceMetering_Test is Test { ...@@ -275,11 +275,8 @@ contract ArtifactResourceMetering_Test is Test {
try vm.removeFile(outfile) {} catch {} try vm.removeFile(outfile) {} catch {}
} }
/** /// @dev Generates a CSV file. No more than the L1 block gas limit should
* @notice Generate a CSV file. The call to `meter` should be called with at /// be supplied to the `meter` function to avoid long execution time.
* most the L1 block gas limit. Without specifying the amount of
* gas, it can take very long to execute.
*/
function test_meter_generateArtifact_succeeds() external { function test_meter_generateArtifact_succeeds() external {
vm.writeLine( vm.writeLine(
outfile, outfile,
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
// Testing utilities
import { CommonTest } from "./CommonTest.t.sol"; import { CommonTest } from "./CommonTest.t.sol";
import { SystemConfig } from "../L1/SystemConfig.sol";
import { ResourceMetering } from "../L1/ResourceMetering.sol"; // Libraries
import { Constants } from "../libraries/Constants.sol"; import { Constants } from "../libraries/Constants.sol";
// Target contract dependencies
import { ResourceMetering } from "../L1/ResourceMetering.sol";
// Target contract
import { SystemConfig } from "../L1/SystemConfig.sol";
contract SystemConfig_Init is CommonTest { contract SystemConfig_Init is CommonTest {
SystemConfig sysConf; SystemConfig sysConf;
...@@ -34,6 +41,8 @@ contract SystemConfig_Init is CommonTest { ...@@ -34,6 +41,8 @@ contract SystemConfig_Init is CommonTest {
} }
contract SystemConfig_Initialize_TestFail is SystemConfig_Init { contract SystemConfig_Initialize_TestFail is SystemConfig_Init {
/// @dev Tests that initialization reverts if the gas limit is too low.
function test_initialize_lowGasLimit_reverts() external { function test_initialize_lowGasLimit_reverts() external {
uint64 minimumGasLimit = sysConf.minimumGasLimit(); uint64 minimumGasLimit = sysConf.minimumGasLimit();
...@@ -60,32 +69,40 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Init { ...@@ -60,32 +69,40 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Init {
} }
contract SystemConfig_Setters_TestFail is SystemConfig_Init { contract SystemConfig_Setters_TestFail is SystemConfig_Init {
/// @dev Tests that `setBatcherHash` reverts if the caller is not the owner.
function test_setBatcherHash_notOwner_reverts() external { function test_setBatcherHash_notOwner_reverts() external {
vm.expectRevert("Ownable: caller is not the owner"); vm.expectRevert("Ownable: caller is not the owner");
sysConf.setBatcherHash(bytes32(hex"")); sysConf.setBatcherHash(bytes32(hex""));
} }
/// @dev Tests that `setGasConfig` reverts if the caller is not the owner.
function test_setGasConfig_notOwner_reverts() external { function test_setGasConfig_notOwner_reverts() external {
vm.expectRevert("Ownable: caller is not the owner"); vm.expectRevert("Ownable: caller is not the owner");
sysConf.setGasConfig(0, 0); sysConf.setGasConfig(0, 0);
} }
/// @dev Tests that `setGasLimit` reverts if the caller is not the owner.
function test_setGasLimit_notOwner_reverts() external { function test_setGasLimit_notOwner_reverts() external {
vm.expectRevert("Ownable: caller is not the owner"); vm.expectRevert("Ownable: caller is not the owner");
sysConf.setGasLimit(0); sysConf.setGasLimit(0);
} }
/// @dev Tests that `setUnsafeBlockSigner` reverts if the caller is not the owner.
function test_setUnsafeBlockSigner_notOwner_reverts() external { function test_setUnsafeBlockSigner_notOwner_reverts() external {
vm.expectRevert("Ownable: caller is not the owner"); vm.expectRevert("Ownable: caller is not the owner");
sysConf.setUnsafeBlockSigner(address(0x20)); sysConf.setUnsafeBlockSigner(address(0x20));
} }
/// @dev Tests that `setResourceConfig` reverts if the caller is not the owner.
function test_setResourceConfig_notOwner_reverts() external { function test_setResourceConfig_notOwner_reverts() external {
ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG(); ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG();
vm.expectRevert("Ownable: caller is not the owner"); vm.expectRevert("Ownable: caller is not the owner");
sysConf.setResourceConfig(config); sysConf.setResourceConfig(config);
} }
/// @dev Tests that `setResourceConfig` reverts if the min base fee
/// is greater than the maximum allowed base fee.
function test_setResourceConfig_badMinMax_reverts() external { function test_setResourceConfig_badMinMax_reverts() external {
ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({
maxResourceLimit: 20_000_000, maxResourceLimit: 20_000_000,
...@@ -100,6 +117,8 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init { ...@@ -100,6 +117,8 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init {
sysConf.setResourceConfig(config); sysConf.setResourceConfig(config);
} }
/// @dev Tests that `setResourceConfig` reverts if the baseFeeMaxChangeDenominator
/// is zero.
function test_setResourceConfig_zeroDenominator_reverts() external { function test_setResourceConfig_zeroDenominator_reverts() external {
ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({
maxResourceLimit: 20_000_000, maxResourceLimit: 20_000_000,
...@@ -114,6 +133,7 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init { ...@@ -114,6 +133,7 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init {
sysConf.setResourceConfig(config); sysConf.setResourceConfig(config);
} }
/// @dev Tests that `setResourceConfig` reverts if the gas limit is too low.
function test_setResourceConfig_lowGasLimit_reverts() external { function test_setResourceConfig_lowGasLimit_reverts() external {
uint64 gasLimit = sysConf.gasLimit(); uint64 gasLimit = sysConf.gasLimit();
...@@ -130,6 +150,8 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init { ...@@ -130,6 +150,8 @@ contract SystemConfig_Setters_TestFail is SystemConfig_Init {
sysConf.setResourceConfig(config); sysConf.setResourceConfig(config);
} }
/// @dev Tests that `setResourceConfig` reverts if the elasticity multiplier
/// and max resource limit are configured such that there is a loss of precision.
function test_setResourceConfig_badPrecision_reverts() external { function test_setResourceConfig_badPrecision_reverts() external {
ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({
maxResourceLimit: 20_000_000, maxResourceLimit: 20_000_000,
...@@ -152,6 +174,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { ...@@ -152,6 +174,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init {
bytes data bytes data
); );
/// @dev Tests that `setBatcherHash` updates the batcher hash successfully.
function testFuzz_setBatcherHash_succeeds(bytes32 newBatcherHash) external { function testFuzz_setBatcherHash_succeeds(bytes32 newBatcherHash) external {
vm.expectEmit(true, true, true, true); vm.expectEmit(true, true, true, true);
emit ConfigUpdate(0, SystemConfig.UpdateType.BATCHER, abi.encode(newBatcherHash)); emit ConfigUpdate(0, SystemConfig.UpdateType.BATCHER, abi.encode(newBatcherHash));
...@@ -161,6 +184,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { ...@@ -161,6 +184,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init {
assertEq(sysConf.batcherHash(), newBatcherHash); assertEq(sysConf.batcherHash(), newBatcherHash);
} }
/// @dev Tests that `setGasConfig` updates the overhead and scalar successfully.
function testFuzz_setGasConfig_succeeds(uint256 newOverhead, uint256 newScalar) external { function testFuzz_setGasConfig_succeeds(uint256 newOverhead, uint256 newScalar) external {
vm.expectEmit(true, true, true, true); vm.expectEmit(true, true, true, true);
emit ConfigUpdate( emit ConfigUpdate(
...@@ -175,6 +199,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { ...@@ -175,6 +199,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init {
assertEq(sysConf.scalar(), newScalar); assertEq(sysConf.scalar(), newScalar);
} }
/// @dev Tests that `setGasLimit` updates the gas limit successfully.
function testFuzz_setGasLimit_succeeds(uint64 newGasLimit) external { function testFuzz_setGasLimit_succeeds(uint64 newGasLimit) external {
uint64 minimumGasLimit = sysConf.minimumGasLimit(); uint64 minimumGasLimit = sysConf.minimumGasLimit();
newGasLimit = uint64( newGasLimit = uint64(
...@@ -189,6 +214,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { ...@@ -189,6 +214,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init {
assertEq(sysConf.gasLimit(), newGasLimit); assertEq(sysConf.gasLimit(), newGasLimit);
} }
/// @dev Tests that `setUnsafeBlockSigner` updates the block signer successfully.
function testFuzz_setUnsafeBlockSigner_succeeds(address newUnsafeSigner) external { function testFuzz_setUnsafeBlockSigner_succeeds(address newUnsafeSigner) external {
vm.expectEmit(true, true, true, true); vm.expectEmit(true, true, true, true);
emit ConfigUpdate( emit ConfigUpdate(
......
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