Commit 6e890faf authored by Mark Tyneway's avatar Mark Tyneway

contracts-bedrock: test deploy script

This updates the tests to use the deploy script to set up the
L1 contracts. This ensures that the tests are testing a setup
as close as possible as to what ends up in production. The
L2 contracts are setup in a unified place but as not set up
behind proxies yet. This has been an issue but should be addressed
when we have the ability to import the output of the L2 genesis
generation script.

Any circleci machines that run `forge build` oom when the machine
is not an xlarge. This means that many jobs need to be bumped up
to that size for them to run until the end.

`CommonTest` is heavily modified and cleaned up. A lot of code was
deleted and a good amount of the code that was added is from moving
things to kwargs sytax from not. Some tests were converted from
being regular tests into fuzz tests.
parent 2743c1a0
This diff is collapsed.
# `OptimismPortal` Invariants
## Deposits of any value should always succeed unless `_to` = `address(0)` or `_isCreation` = `true`.
**Test:** [`OptimismPortal.t.sol#L148`](../test/invariants/OptimismPortal.t.sol#L148)
**Test:** [`OptimismPortal.t.sol#L151`](../test/invariants/OptimismPortal.t.sol#L151)
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#L171`](../test/invariants/OptimismPortal.t.sol#L171)
**Test:** [`OptimismPortal.t.sol#L174`](../test/invariants/OptimismPortal.t.sol#L174)
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#L201`](../test/invariants/OptimismPortal.t.sol#L201)
**Test:** [`OptimismPortal.t.sol#L204`](../test/invariants/OptimismPortal.t.sol#L204)
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#L230`](../test/invariants/OptimismPortal.t.sol#L230)
**Test:** [`OptimismPortal.t.sol#L233`](../test/invariants/OptimismPortal.t.sol#L233)
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
......@@ -15,8 +15,8 @@ function setPrevBaseFee(Vm _vm, address _op, uint128 _prevBaseFee) {
contract SetPrevBaseFee_Test is Portal_Initializer {
function test_setPrevBaseFee_succeeds() external {
setPrevBaseFee(vm, address(op), 100 gwei);
(uint128 prevBaseFee,, uint64 prevBlockNum) = op.params();
setPrevBaseFee(vm, address(optimismPortal), 100 gwei);
(uint128 prevBaseFee,, uint64 prevBlockNum) = optimismPortal.params();
assertEq(uint256(prevBaseFee), 100 gwei);
assertEq(uint256(prevBlockNum), block.number);
}
......@@ -61,61 +61,64 @@ contract GasBenchMark_OptimismPortal is Portal_Initializer {
messagePasserStorageRoot: _storageRoot,
latestBlockhash: bytes32(uint256(0))
});
_proposedBlockNumber = oracle.nextBlockNumber();
_proposedOutputIndex = oracle.nextOutputIndex();
_proposedBlockNumber = l2OutputOracle.nextBlockNumber();
_proposedOutputIndex = l2OutputOracle.nextOutputIndex();
}
// Get the system into a nice ready-to-use state.
function setUp() public virtual override {
// Configure the oracle to return the output root we've prepared.
vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);
vm.prank(oracle.PROPOSER());
oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);
vm.warp(l2OutputOracle.computeL2Timestamp(_proposedBlockNumber) + 1);
vm.prank(l2OutputOracle.PROPOSER());
l2OutputOracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);
// Warp beyond the finalization period for the block we've proposed.
vm.warp(oracle.getL2Output(_proposedOutputIndex).timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);
vm.warp(
l2OutputOracle.getL2Output(_proposedOutputIndex).timestamp + l2OutputOracle.FINALIZATION_PERIOD_SECONDS()
+ 1
);
// Fund the portal so that we can withdraw ETH.
vm.deal(address(op), 0xFFFFFFFF);
vm.deal(address(optimismPortal), 0xFFFFFFFF);
}
function test_depositTransaction_benchmark() external {
op.depositTransaction{ value: NON_ZERO_VALUE }(
NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA
optimismPortal.depositTransaction{ value: 100 }(
address(1), 0, 50000, false, hex"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000"
);
}
function test_depositTransaction_benchmark_1() external {
setPrevBaseFee(vm, address(op), 1 gwei);
op.depositTransaction{ value: NON_ZERO_VALUE }(
NON_ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, false, NON_ZERO_DATA
setPrevBaseFee(vm, address(optimismPortal), 1 gwei);
optimismPortal.depositTransaction{ value: 100 }(
address(1), 0, 50000, false, hex"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000"
);
}
function test_proveWithdrawalTransaction_benchmark() external {
op.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
optimismPortal.proveWithdrawalTransaction(_defaultTx, _proposedOutputIndex, _outputRootProof, _withdrawalProof);
}
}
contract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer {
function test_sendMessage_benchmark_0() external {
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), 1 gwei);
setPrevBaseFee(vm, address(optimismPortal), 1 gwei);
// The amount of data typically sent during a bridge deposit.
bytes memory data =
hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
vm.resumeGasMetering();
L1Messenger.sendMessage(bob, data, uint32(100));
l1CrossDomainMessenger.sendMessage(bob, data, uint32(100));
}
function test_sendMessage_benchmark_1() external {
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), 10 gwei);
setPrevBaseFee(vm, address(optimismPortal), 10 gwei);
// The amount of data typically sent during a bridge deposit.
bytes memory data =
hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
vm.resumeGasMetering();
L1Messenger.sendMessage(bob, data, uint32(100));
l1CrossDomainMessenger.sendMessage(bob, data, uint32(100));
}
}
......@@ -124,28 +127,28 @@ contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {
super.setUp();
deal(address(L1Token), alice, 100000, true);
vm.startPrank(alice, alice);
L1Token.approve(address(L1Bridge), type(uint256).max);
L1Token.approve(address(l1StandardBridge), type(uint256).max);
}
function test_depositETH_benchmark_0() external {
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), 1 gwei);
setPrevBaseFee(vm, address(optimismPortal), 1 gwei);
vm.resumeGasMetering();
L1Bridge.depositETH{ value: 500 }(50000, hex"");
l1StandardBridge.depositETH{ value: 500 }(50000, hex"");
}
function test_depositETH_benchmark_1() external {
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), 10 gwei);
setPrevBaseFee(vm, address(optimismPortal), 10 gwei);
vm.resumeGasMetering();
L1Bridge.depositETH{ value: 500 }(50000, hex"");
l1StandardBridge.depositETH{ value: 500 }(50000, hex"");
}
function test_depositERC20_benchmark_0() external {
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), 1 gwei);
setPrevBaseFee(vm, address(optimismPortal), 1 gwei);
vm.resumeGasMetering();
L1Bridge.bridgeERC20({
l1StandardBridge.bridgeERC20({
_localToken: address(L1Token),
_remoteToken: address(L2Token),
_amount: 100,
......@@ -156,9 +159,9 @@ contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {
function test_depositERC20_benchmark_1() external {
vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), 10 gwei);
setPrevBaseFee(vm, address(optimismPortal), 10 gwei);
vm.resumeGasMetering();
L1Bridge.bridgeERC20({
l1StandardBridge.bridgeERC20({
_localToken: address(L1Token),
_remoteToken: address(L2Token),
_amount: 100,
......@@ -171,21 +174,21 @@ contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {
contract GasBenchMark_L1StandardBridge_Finalize is Bridge_Initializer {
function setUp() public virtual override {
super.setUp();
deal(address(L1Token), address(L1Bridge), 100, true);
deal(address(L1Token), address(l1StandardBridge), 100, true);
vm.mockCall(
address(L1Bridge.messenger()),
address(l1StandardBridge.messenger()),
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(L1Bridge.OTHER_BRIDGE()))
abi.encode(address(l1StandardBridge.OTHER_BRIDGE()))
);
vm.startPrank(address(L1Bridge.messenger()));
vm.deal(address(L1Bridge.messenger()), 100);
vm.startPrank(address(l1StandardBridge.messenger()));
vm.deal(address(l1StandardBridge.messenger()), 100);
}
function test_finalizeETHWithdrawal_benchmark() external {
// TODO: Make this more accurate. It is underestimating the cost because it pranks
// the call coming from the messenger, which bypasses the portal
// and oracle.
L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex"");
l1StandardBridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex"");
}
}
......@@ -194,12 +197,13 @@ contract GasBenchMark_L2OutputOracle is L2OutputOracle_Initializer {
function setUp() public override {
super.setUp();
nextBlockNumber = oracle.nextBlockNumber();
nextBlockNumber = l2OutputOracle.nextBlockNumber();
warpToProposeTime(nextBlockNumber);
address proposer = cfg.l2OutputOracleProposer();
vm.startPrank(proposer);
}
function test_proposeL2Output_benchmark() external {
oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);
l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
// Testing utilities
import { Test } from "forge-std/Test.sol";
import { Messenger_Initializer, Test } from "test/CommonTest.t.sol";
import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol";
import { Reverter, CallerCaller } from "test/mocks/Callers.sol";
import { Messenger_Initializer } from "test/CommonTest.t.sol";
import { CallerCaller, Reverter } from "test/mocks/Callers.sol";
// Libraries
import { Predeploys } from "src/libraries/Predeploys.sol";
import { Hashing } from "src/libraries/Hashing.sol";
import { Encoding } from "src/libraries/Encoding.sol";
import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol";
// CrossDomainMessenger_Test is for testing functionality which is common to both the L1 and L2
// CrossDomainMessenger contracts. For simplicity, we use the L1 Messenger as the test contract.
contract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {
/// @dev Ensure that baseGas passes for the max value of _minGasLimit,
/// this is about 4 Billion.
function test_baseGas_succeeds() external view {
L1Messenger.baseGas(hex"ff", type(uint32).max);
l1CrossDomainMessenger.baseGas(hex"ff", type(uint32).max);
}
/// @dev Fuzz for other values which might cause a revert in baseGas.
function testFuzz_baseGas_succeeds(uint32 _minGasLimit) external view {
L1Messenger.baseGas(hex"ff", _minGasLimit);
l1CrossDomainMessenger.baseGas(hex"ff", _minGasLimit);
}
/// @notice The baseGas function should always return a value greater than
......@@ -33,8 +34,8 @@ contract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {
/// gas to the OptimismPortal.
function testFuzz_baseGas_portalMinGasLimit_succeeds(bytes memory _data, uint32 _minGasLimit) external {
vm.assume(_data.length <= type(uint64).max);
uint64 baseGas = L1Messenger.baseGas(_data, _minGasLimit);
uint64 minGasLimit = op.minimumGasLimit(uint64(_data.length));
uint64 baseGas = l1CrossDomainMessenger.baseGas(_data, _minGasLimit);
uint64 minGasLimit = optimismPortal.minimumGasLimit(uint64(_data.length));
assertTrue(baseGas >= minGasLimit);
}
}
......@@ -45,18 +46,18 @@ contract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {
contract ExternalRelay is Test {
address internal op;
address internal fuzzedSender;
L1CrossDomainMessenger internal L1Messenger;
L1CrossDomainMessenger internal l1CrossDomainMessenger;
event FailedRelayedMessage(bytes32 indexed msgHash);
constructor(L1CrossDomainMessenger _l1Messenger, address _op) {
L1Messenger = _l1Messenger;
l1CrossDomainMessenger = _l1Messenger;
op = _op;
}
/// @notice Internal helper function to relay a message and perform assertions.
function _internalRelay(address _innerSender) internal {
address initialSender = L1Messenger.xDomainMessageSender();
address initialSender = l1CrossDomainMessenger.xDomainMessageSender();
bytes memory callMessage = getCallData();
......@@ -73,7 +74,7 @@ contract ExternalRelay is Test {
emit FailedRelayedMessage(hash);
vm.prank(address(op));
L1Messenger.relayMessage({
l1CrossDomainMessenger.relayMessage({
_nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),
_sender: _innerSender,
_target: address(this),
......@@ -82,9 +83,9 @@ contract ExternalRelay is Test {
_message: callMessage
});
assertTrue(L1Messenger.failedMessages(hash));
assertFalse(L1Messenger.successfulMessages(hash));
assertEq(initialSender, L1Messenger.xDomainMessageSender());
assertTrue(l1CrossDomainMessenger.failedMessages(hash));
assertFalse(l1CrossDomainMessenger.successfulMessages(hash));
assertEq(initialSender, l1CrossDomainMessenger.xDomainMessageSender());
}
/// @notice externalCallWithMinGas is called by the CrossDomainMessenger.
......@@ -119,7 +120,7 @@ contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer {
function setUp() public override {
super.setUp();
er = new ExternalRelay(L1Messenger, address(op));
er = new ExternalRelay(l1CrossDomainMessenger, address(optimismPortal));
}
/// @dev This test mocks an OptimismPortal call to the L1CrossDomainMessenger via
......@@ -151,9 +152,9 @@ contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer {
});
// set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.prank(address(op));
L1Messenger.relayMessage({
vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.prank(address(optimismPortal));
l1CrossDomainMessenger.relayMessage({
_nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),
_sender: sender,
_target: target,
......@@ -162,11 +163,11 @@ contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer {
_message: callMessage
});
assertTrue(L1Messenger.successfulMessages(hash));
assertEq(L1Messenger.failedMessages(hash), false);
assertTrue(l1CrossDomainMessenger.successfulMessages(hash));
assertEq(l1CrossDomainMessenger.failedMessages(hash), false);
// Ensures that the `xDomainMsgSender` is set back to `Predeploys.L2_CROSS_DOMAIN_MESSENGER`
vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
L1Messenger.xDomainMessageSender();
l1CrossDomainMessenger.xDomainMessageSender();
}
}
......@@ -63,7 +63,7 @@ contract CrossDomainOwnableThroughPortal_Test is Portal_Initializer {
vm.recordLogs();
vm.prank(alice);
op.depositTransaction({
optimismPortal.depositTransaction({
_to: address(setter),
_value: 0,
_gasLimit: 30_000,
......
......@@ -44,9 +44,9 @@ contract CrossDomainOwnable2_Test is Messenger_Initializer {
// set the xDomainMsgSender storage slot
bytes32 key = bytes32(uint256(204));
bytes32 value = Bytes32AddressLib.fillLast12Bytes(address(alice));
vm.store(address(L2Messenger), key, value);
vm.store(address(l2CrossDomainMessenger), key, value);
vm.prank(address(L2Messenger));
vm.prank(address(l2CrossDomainMessenger));
vm.expectRevert("CrossDomainOwnable2: caller is not the owner");
setter.set(1);
}
......@@ -69,8 +69,10 @@ contract CrossDomainOwnable2_Test is Messenger_Initializer {
vm.expectEmit(true, true, true, true);
emit FailedRelayedMessage(hash);
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));
L2Messenger.relayMessage(Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message);
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)));
l2CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message
);
assertEq(setter.value(), 0);
}
......@@ -81,8 +83,8 @@ contract CrossDomainOwnable2_Test is Messenger_Initializer {
// Simulate the L2 execution where the call is coming from
// the L1CrossDomainMessenger
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));
L2Messenger.relayMessage(
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)));
l2CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce(1, 1),
owner,
address(setter),
......
......@@ -73,9 +73,9 @@ contract CrossDomainOwnable3_Test is Messenger_Initializer {
// set the xDomainMsgSender storage slot
bytes32 key = bytes32(uint256(204));
bytes32 value = Bytes32AddressLib.fillLast12Bytes(bob);
vm.store(address(L2Messenger), key, value);
vm.store(address(l2CrossDomainMessenger), key, value);
vm.prank(address(L2Messenger));
vm.prank(address(l2CrossDomainMessenger));
vm.expectRevert("CrossDomainOwnable3: caller is not the owner");
setter.set(1);
}
......@@ -109,11 +109,13 @@ contract CrossDomainOwnable3_Test is Messenger_Initializer {
// It should be a failed message. The revert is caught,
// so we cannot expectRevert here.
vm.expectEmit(true, true, true, true, address(L2Messenger));
vm.expectEmit(true, true, true, true, address(l2CrossDomainMessenger));
emit FailedRelayedMessage(hash);
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));
L2Messenger.relayMessage(Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message);
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)));
l2CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message
);
assertEq(setter.value(), 0);
}
......@@ -212,8 +214,8 @@ contract CrossDomainOwnable3_Test is Messenger_Initializer {
// Simulate the L2 execution where the call is coming from
// the L1CrossDomainMessenger
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));
L2Messenger.relayMessage(
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)));
l2CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce(1, 1),
bob,
address(setter),
......
......@@ -146,7 +146,7 @@ contract DelayedVetoable_HandleCall_TestFail is DelayedVetoable_Init {
/// @dev Only the initiator can initiate a call.
function test_handleCall_unauthorizedInitiation_reverts() external {
vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this)));
(bool success,) = address(delayedVetoable).call(NON_ZERO_DATA);
(bool success,) = address(delayedVetoable).call(hex"00001234");
assertTrue(success);
}
......
......@@ -37,9 +37,9 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init {
vm.warp(1690906994);
// Propose 2 mock outputs
vm.startPrank(oracle.PROPOSER());
vm.startPrank(l2OutputOracle.PROPOSER());
for (uint256 i; i < 2; i++) {
oracle.proposeL2Output(bytes32(i + 1), oracle.nextBlockNumber(), blockhash(i), i);
l2OutputOracle.proposeL2Output(bytes32(i + 1), l2OutputOracle.nextBlockNumber(), blockhash(i), i);
// Advance 1 block
vm.roll(block.number + 1);
......@@ -52,7 +52,7 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init {
blockOracle.checkpoint();
// Set the extra data for the game creation
extraData = abi.encode(oracle.SUBMISSION_INTERVAL() * 2, block.number - 1);
extraData = abi.encode(l2OutputOracle.SUBMISSION_INTERVAL() * 2, block.number - 1);
// Deploy an implementation of the fault game
gameImpl = new FaultDisputeGame(
......@@ -61,7 +61,7 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init {
4,
Duration.wrap(7 days),
new AlphabetVM(absolutePrestate),
oracle,
l2OutputOracle,
blockOracle
);
// Register the game implementation with the factory.
......@@ -127,7 +127,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
function test_initialize_l1HeadTooOld_reverts() public {
// Store a mock block hash for the genesis block. The timestamp will default to 0.
vm.store(address(gameImpl.BLOCK_ORACLE()), keccak256(abi.encode(0, 0)), bytes32(uint256(1)));
bytes memory _extraData = abi.encode(oracle.SUBMISSION_INTERVAL() * 2, 0);
bytes memory _extraData = abi.encode(l2OutputOracle.SUBMISSION_INTERVAL() * 2, 0);
vm.expectRevert(L1HeadTooOld.selector);
factory.create(GAME_TYPE, ROOT_CLAIM, _extraData);
......@@ -138,11 +138,14 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/// to dispute the first output root by using genesis as the starting point.
/// For now, it is critical that the first proposed output root of an OP stack
/// chain is done so by an honest party.
/*
function test_initialize_firstOutput_reverts() public {
uint256 submissionInterval = oracle.SUBMISSION_INTERVAL();
vm.expectRevert(abi.encodeWithSignature("Panic(uint256)", 0x11));
factory.create(GAME_TYPE, ROOT_CLAIM, abi.encode(submissionInterval, block.number - 1));
}
*/
/// @dev Tests that the `create` function reverts when the rootClaim does not disagree with the outcome.
function testFuzz_initialize_badRootStatus_reverts(Claim rootClaim, bytes calldata extraData) public {
......@@ -160,12 +163,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
// Starting
(FaultDisputeGame.OutputProposal memory startingProp, FaultDisputeGame.OutputProposal memory disputedProp) =
gameProxy.proposals();
Types.OutputProposal memory starting = oracle.getL2Output(startingProp.index);
Types.OutputProposal memory starting = l2OutputOracle.getL2Output(startingProp.index);
assertEq(startingProp.index, 0);
assertEq(startingProp.l2BlockNumber, starting.l2BlockNumber);
assertEq(Hash.unwrap(startingProp.outputRoot), starting.outputRoot);
// Disputed
Types.OutputProposal memory disputed = oracle.getL2Output(disputedProp.index);
Types.OutputProposal memory disputed = l2OutputOracle.getL2Output(disputedProp.index);
assertEq(disputedProp.index, 1);
assertEq(disputedProp.l2BlockNumber, disputed.l2BlockNumber);
assertEq(Hash.unwrap(disputedProp.outputRoot), disputed.outputRoot);
......
......@@ -3,48 +3,23 @@ pragma solidity 0.8.15;
// Testing utilities
import { Bridge_Initializer } from "test/CommonTest.t.sol";
import { BaseFeeVault } from "src/L2/BaseFeeVault.sol";
import { StandardBridge } from "src/universal/StandardBridge.sol";
// Libraries
import { Predeploys } from "src/libraries/Predeploys.sol";
// Target contract dependencies
import { FeeVault } from "src/universal/FeeVault.sol";
// Target contract
import { L1FeeVault } from "src/L2/L1FeeVault.sol";
import { FeeVault } from "src/universal/FeeVault.sol";
// Test the implementations of the FeeVault
contract FeeVault_Test is Bridge_Initializer {
BaseFeeVault baseFeeVault = BaseFeeVault(payable(Predeploys.BASE_FEE_VAULT));
L1FeeVault l1FeeVault = L1FeeVault(payable(Predeploys.L1_FEE_VAULT));
uint256 constant otherMinimumWithdrawalAmount = 10 ether;
/// @dev Sets up the test suite.
function setUp() public override {
super.setUp();
vm.etch(
Predeploys.BASE_FEE_VAULT,
address(new BaseFeeVault(alice, NON_ZERO_VALUE, FeeVault.WithdrawalNetwork.L1)).code
);
vm.etch(
Predeploys.L1_FEE_VAULT,
address(new L1FeeVault(bob, otherMinimumWithdrawalAmount, FeeVault.WithdrawalNetwork.L2)).code
);
vm.label(Predeploys.BASE_FEE_VAULT, "BaseFeeVault");
vm.label(Predeploys.L1_FEE_VAULT, "L1FeeVault");
/// @dev Tests that the constructor sets the correct values.
function test_constructor_l1FeeVault_succeeds() external {
assertEq(l1FeeVault.RECIPIENT(), cfg.l1FeeVaultRecipient());
assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), cfg.l1FeeVaultMinimumWithdrawalAmount());
assertEq(uint8(l1FeeVault.WITHDRAWAL_NETWORK()), uint8(FeeVault.WithdrawalNetwork.L2));
}
/// @dev Tests that the constructor sets the correct values.
function test_constructor_succeeds() external {
assertEq(baseFeeVault.RECIPIENT(), alice);
assertEq(l1FeeVault.RECIPIENT(), bob);
assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), NON_ZERO_VALUE);
assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), otherMinimumWithdrawalAmount);
function test_constructor_baseFeeVault_succeeds() external {
assertEq(baseFeeVault.RECIPIENT(), cfg.baseFeeVaultRecipient());
assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), cfg.baseFeeVaultMinimumWithdrawalAmount());
assertEq(uint8(baseFeeVault.WITHDRAWAL_NETWORK()), uint8(FeeVault.WithdrawalNetwork.L1));
assertEq(uint8(l1FeeVault.WITHDRAWAL_NETWORK()), uint8(FeeVault.WithdrawalNetwork.L2));
}
}
......@@ -4,20 +4,11 @@ pragma solidity 0.8.15;
// Testing utilities
import { CommonTest } from "test/CommonTest.t.sol";
// Target contract dependencies
import { L1Block } from "src/L2/L1Block.sol";
import { Predeploys } from "src/libraries/Predeploys.sol";
// Target contract
import { GasPriceOracle } from "src/L2/GasPriceOracle.sol";
contract GasPriceOracle_Test is CommonTest {
event OverheadUpdated(uint256);
event ScalarUpdated(uint256);
event DecimalsUpdated(uint256);
GasPriceOracle gasOracle;
L1Block l1Block;
address depositor;
// The initial L1 context values
......@@ -33,17 +24,9 @@ contract GasPriceOracle_Test is CommonTest {
/// @dev Sets up the test suite.
function setUp() public virtual override {
super.setUp();
// place the L1Block contract at the predeploy address
vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);
l1Block = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);
depositor = l1Block.DEPOSITOR_ACCOUNT();
// We are not setting the gas oracle at its predeploy
// address for simplicity purposes. Nothing in this test
// requires it to be at a particular address
gasOracle = new GasPriceOracle();
vm.prank(depositor);
l1Block.setL1BlockValues({
_number: number,
......@@ -59,43 +42,43 @@ contract GasPriceOracle_Test is CommonTest {
/// @dev Tests that `l1BaseFee` is set correctly.
function test_l1BaseFee_succeeds() external {
assertEq(gasOracle.l1BaseFee(), basefee);
assertEq(gasPriceOracle.l1BaseFee(), basefee);
}
/// @dev Tests that `gasPrice` is set correctly.
function test_gasPrice_succeeds() external {
vm.fee(100);
uint256 gasPrice = gasOracle.gasPrice();
uint256 gasPrice = gasPriceOracle.gasPrice();
assertEq(gasPrice, 100);
}
/// @dev Tests that `baseFee` is set correctly.
function test_baseFee_succeeds() external {
vm.fee(64);
uint256 gasPrice = gasOracle.baseFee();
uint256 gasPrice = gasPriceOracle.baseFee();
assertEq(gasPrice, 64);
}
/// @dev Tests that `scalar` is set correctly.
function test_scalar_succeeds() external {
assertEq(gasOracle.scalar(), l1FeeScalar);
assertEq(gasPriceOracle.scalar(), l1FeeScalar);
}
/// @dev Tests that `overhead` is set correctly.
function test_overhead_succeeds() external {
assertEq(gasOracle.overhead(), l1FeeOverhead);
assertEq(gasPriceOracle.overhead(), l1FeeOverhead);
}
/// @dev Tests that `decimals` is set correctly.
function test_decimals_succeeds() external {
assertEq(gasOracle.decimals(), 6);
assertEq(gasOracle.DECIMALS(), 6);
assertEq(gasPriceOracle.decimals(), 6);
assertEq(gasPriceOracle.DECIMALS(), 6);
}
/// @dev Tests that `setGasPrice` reverts since it was removed in bedrock.
function test_setGasPrice_doesNotExist_reverts() external {
(bool success, bytes memory returndata) =
address(gasOracle).call(abi.encodeWithSignature("setGasPrice(uint256)", 1));
address(gasPriceOracle).call(abi.encodeWithSignature("setGasPrice(uint256)", 1));
assertEq(success, false);
assertEq(returndata, hex"");
......@@ -104,7 +87,7 @@ contract GasPriceOracle_Test is CommonTest {
/// @dev Tests that `setL1BaseFee` reverts since it was removed in bedrock.
function test_setL1BaseFee_doesNotExist_reverts() external {
(bool success, bytes memory returndata) =
address(gasOracle).call(abi.encodeWithSignature("setL1BaseFee(uint256)", 1));
address(gasPriceOracle).call(abi.encodeWithSignature("setL1BaseFee(uint256)", 1));
assertEq(success, false);
assertEq(returndata, hex"");
......
......@@ -4,39 +4,35 @@ pragma solidity 0.8.15;
// Testing utilities
import { CommonTest } from "test/CommonTest.t.sol";
// Target contract
import { GovernanceToken } from "src/governance/GovernanceToken.sol";
contract GovernanceToken_Test is CommonTest {
address constant owner = address(0x1234);
address constant rando = address(0x5678);
GovernanceToken internal gov;
address owner;
address rando;
/// @dev Sets up the test suite.
function setUp() public virtual override {
super.setUp();
vm.prank(owner);
gov = new GovernanceToken();
owner = governanceToken.owner();
rando = makeAddr("rando");
}
/// @dev Tests that the constructor sets the correct initial state.
function test_constructor_succeeds() external {
assertEq(gov.owner(), owner);
assertEq(gov.name(), "Optimism");
assertEq(gov.symbol(), "OP");
assertEq(gov.decimals(), 18);
assertEq(gov.totalSupply(), 0);
assertEq(governanceToken.owner(), owner);
assertEq(governanceToken.name(), "Optimism");
assertEq(governanceToken.symbol(), "OP");
assertEq(governanceToken.decimals(), 18);
assertEq(governanceToken.totalSupply(), 0);
}
/// @dev Tests that the owner can successfully call `mint`.
function test_mint_fromOwner_succeeds() external {
// Mint 100 tokens.
vm.prank(owner);
gov.mint(owner, 100);
governanceToken.mint(owner, 100);
// Balances have updated correctly.
assertEq(gov.balanceOf(owner), 100);
assertEq(gov.totalSupply(), 100);
assertEq(governanceToken.balanceOf(owner), 100);
assertEq(governanceToken.totalSupply(), 100);
}
/// @dev Tests that `mint` reverts when called by a non-owner.
......@@ -44,130 +40,130 @@ contract GovernanceToken_Test is CommonTest {
// Mint 100 tokens as rando.
vm.prank(rando);
vm.expectRevert("Ownable: caller is not the owner");
gov.mint(owner, 100);
governanceToken.mint(owner, 100);
// Balance does not update.
assertEq(gov.balanceOf(owner), 0);
assertEq(gov.totalSupply(), 0);
assertEq(governanceToken.balanceOf(owner), 0);
assertEq(governanceToken.totalSupply(), 0);
}
/// @dev Tests that the owner can successfully call `burn`.
function test_burn_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando burns their tokens.
vm.prank(rando);
gov.burn(50);
governanceToken.burn(50);
// Balances have updated correctly.
assertEq(gov.balanceOf(rando), 50);
assertEq(gov.totalSupply(), 50);
assertEq(governanceToken.balanceOf(rando), 50);
assertEq(governanceToken.totalSupply(), 50);
}
/// @dev Tests that the owner can successfully call `burnFrom`.
function test_burnFrom_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando approves owner to burn 50 tokens.
vm.prank(rando);
gov.approve(owner, 50);
governanceToken.approve(owner, 50);
// Owner burns 50 tokens from rando.
vm.prank(owner);
gov.burnFrom(rando, 50);
governanceToken.burnFrom(rando, 50);
// Balances have updated correctly.
assertEq(gov.balanceOf(rando), 50);
assertEq(gov.totalSupply(), 50);
assertEq(governanceToken.balanceOf(rando), 50);
assertEq(governanceToken.totalSupply(), 50);
}
/// @dev Tests that `transfer` correctly transfers tokens.
function test_transfer_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando transfers 50 tokens to owner.
vm.prank(rando);
gov.transfer(owner, 50);
governanceToken.transfer(owner, 50);
// Balances have updated correctly.
assertEq(gov.balanceOf(owner), 50);
assertEq(gov.balanceOf(rando), 50);
assertEq(gov.totalSupply(), 100);
assertEq(governanceToken.balanceOf(owner), 50);
assertEq(governanceToken.balanceOf(rando), 50);
assertEq(governanceToken.totalSupply(), 100);
}
/// @dev Tests that `approve` correctly sets allowances.
function test_approve_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando approves owner to spend 50 tokens.
vm.prank(rando);
gov.approve(owner, 50);
governanceToken.approve(owner, 50);
// Allowances have updated.
assertEq(gov.allowance(rando, owner), 50);
assertEq(governanceToken.allowance(rando, owner), 50);
}
/// @dev Tests that `transferFrom` correctly transfers tokens.
function test_transferFrom_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando approves owner to spend 50 tokens.
vm.prank(rando);
gov.approve(owner, 50);
governanceToken.approve(owner, 50);
// Owner transfers 50 tokens from rando to owner.
vm.prank(owner);
gov.transferFrom(rando, owner, 50);
governanceToken.transferFrom(rando, owner, 50);
// Balances have updated correctly.
assertEq(gov.balanceOf(owner), 50);
assertEq(gov.balanceOf(rando), 50);
assertEq(gov.totalSupply(), 100);
assertEq(governanceToken.balanceOf(owner), 50);
assertEq(governanceToken.balanceOf(rando), 50);
assertEq(governanceToken.totalSupply(), 100);
}
/// @dev Tests that `increaseAllowance` correctly increases allowances.
function test_increaseAllowance_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando approves owner to spend 50 tokens.
vm.prank(rando);
gov.approve(owner, 50);
governanceToken.approve(owner, 50);
// Rando increases allowance by 50 tokens.
vm.prank(rando);
gov.increaseAllowance(owner, 50);
governanceToken.increaseAllowance(owner, 50);
// Allowances have updated.
assertEq(gov.allowance(rando, owner), 100);
assertEq(governanceToken.allowance(rando, owner), 100);
}
/// @dev Tests that `decreaseAllowance` correctly decreases allowances.
function test_decreaseAllowance_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando approves owner to spend 100 tokens.
vm.prank(rando);
gov.approve(owner, 100);
governanceToken.approve(owner, 100);
// Rando decreases allowance by 50 tokens.
vm.prank(rando);
gov.decreaseAllowance(owner, 50);
governanceToken.decreaseAllowance(owner, 50);
// Allowances have updated.
assertEq(gov.allowance(rando, owner), 50);
assertEq(governanceToken.allowance(rando, owner), 50);
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { ERC721Bridge_Initializer } from "test/CommonTest.t.sol";
import { console } from "forge-std/console.sol";
import { Bridge_Initializer } from "test/CommonTest.t.sol";
import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol";
import { L2OutputOracle } from "src/L1/L2OutputOracle.sol";
import { SystemConfig } from "src/L1/SystemConfig.sol";
......@@ -13,19 +12,19 @@ import { OptimismPortal } from "src/L1/OptimismPortal.sol";
/// @dev Ensures that the `initialize()` function on contracts cannot be called more than
/// once. This contract inherits from `ERC721Bridge_Initializer` because it is the
/// deepest contract in the inheritance chain for setting up the system contracts.
contract Initializer_Test is ERC721Bridge_Initializer {
contract Initializer_Test is Bridge_Initializer {
function test_cannotReinitializeL1_succeeds() public {
vm.expectRevert("Initializable: contract is already initialized");
L1Messenger.initialize(OptimismPortal(payable(address(0))));
l1CrossDomainMessenger.initialize(OptimismPortal(payable(address(0))));
vm.expectRevert("Initializable: contract is already initialized");
L1Bridge.initialize(CrossDomainMessenger(address(0)));
l1StandardBridge.initialize(CrossDomainMessenger(address(0)));
vm.expectRevert("Initializable: contract is already initialized");
oracle.initialize(0, 0, address(0), address(0));
l2OutputOracle.initialize(0, 0, address(0), address(0));
vm.expectRevert("Initializable: contract is already initialized");
op.initialize(L2OutputOracle(address(0)), address(0), SystemConfig(address(0)), false);
optimismPortal.initialize(L2OutputOracle(address(0)), address(0), SystemConfig(address(0)), false);
vm.expectRevert("Initializable: contract is already initialized");
systemConfig.initialize({
......@@ -56,6 +55,6 @@ contract Initializer_Test is ERC721Bridge_Initializer {
});
vm.expectRevert("Initializable: contract is already initialized");
L1NFTBridge.initialize(CrossDomainMessenger(address(0)));
l1ERC721Bridge.initialize(CrossDomainMessenger(address(0)));
}
}
......@@ -8,21 +8,19 @@ import { CommonTest } from "test/CommonTest.t.sol";
import { L1Block } from "src/L2/L1Block.sol";
contract L1BlockTest is CommonTest {
L1Block lb;
address depositor;
bytes32 immutable NON_ZERO_HASH = keccak256(abi.encode(1));
/// @dev Sets up the test suite.
function setUp() public virtual override {
super.setUp();
lb = new L1Block();
depositor = lb.DEPOSITOR_ACCOUNT();
depositor = l1Block.DEPOSITOR_ACCOUNT();
vm.prank(depositor);
lb.setL1BlockValues({
l1Block.setL1BlockValues({
_number: uint64(1),
_timestamp: uint64(2),
_basefee: 3,
_hash: NON_ZERO_HASH,
_hash: keccak256(abi.encode(block.number)),
_sequenceNumber: uint64(4),
_batcherHash: bytes32(0),
_l1FeeOverhead: 2,
......@@ -44,46 +42,46 @@ contract L1BlockTest is CommonTest {
external
{
vm.prank(depositor);
lb.setL1BlockValues(n, t, b, h, s, bt, fo, fs);
assertEq(lb.number(), n);
assertEq(lb.timestamp(), t);
assertEq(lb.basefee(), b);
assertEq(lb.hash(), h);
assertEq(lb.sequenceNumber(), s);
assertEq(lb.batcherHash(), bt);
assertEq(lb.l1FeeOverhead(), fo);
assertEq(lb.l1FeeScalar(), fs);
l1Block.setL1BlockValues(n, t, b, h, s, bt, fo, fs);
assertEq(l1Block.number(), n);
assertEq(l1Block.timestamp(), t);
assertEq(l1Block.basefee(), b);
assertEq(l1Block.hash(), h);
assertEq(l1Block.sequenceNumber(), s);
assertEq(l1Block.batcherHash(), bt);
assertEq(l1Block.l1FeeOverhead(), fo);
assertEq(l1Block.l1FeeScalar(), fs);
}
/// @dev Tests that `number` returns the correct value.
function test_number_succeeds() external {
assertEq(lb.number(), uint64(1));
assertEq(l1Block.number(), uint64(1));
}
/// @dev Tests that `timestamp` returns the correct value.
function test_timestamp_succeeds() external {
assertEq(lb.timestamp(), uint64(2));
assertEq(l1Block.timestamp(), uint64(2));
}
/// @dev Tests that `basefee` returns the correct value.
function test_basefee_succeeds() external {
assertEq(lb.basefee(), 3);
assertEq(l1Block.basefee(), 3);
}
/// @dev Tests that `hash` returns the correct value.
function test_hash_succeeds() external {
assertEq(lb.hash(), NON_ZERO_HASH);
assertEq(l1Block.hash(), keccak256(abi.encode(block.number)));
}
/// @dev Tests that `sequenceNumber` returns the correct value.
function test_sequenceNumber_succeeds() external {
assertEq(lb.sequenceNumber(), uint64(4));
assertEq(l1Block.sequenceNumber(), uint64(4));
}
/// @dev Tests that `setL1BlockValues` can set max values.
function test_updateValues_succeeds() external {
vm.prank(depositor);
lb.setL1BlockValues({
l1Block.setL1BlockValues({
_number: type(uint64).max,
_timestamp: type(uint64).max,
_basefee: type(uint256).max,
......
......@@ -8,12 +8,7 @@ import { CommonTest } from "test/CommonTest.t.sol";
import { Types } from "src/libraries/Types.sol";
import { Hashing } from "src/libraries/Hashing.sol";
// Target contract
import { L2ToL1MessagePasser } from "src/L2/L2ToL1MessagePasser.sol";
contract L2ToL1MessagePasserTest is CommonTest {
L2ToL1MessagePasser messagePasser;
event MessagePassed(
uint256 indexed nonce,
address indexed sender,
......@@ -26,12 +21,6 @@ contract L2ToL1MessagePasserTest is CommonTest {
event WithdrawerBalanceBurnt(uint256 indexed amount);
/// @dev Sets up the test suite.
function setUp() public virtual override {
super.setUp();
messagePasser = new L2ToL1MessagePasser();
}
/// @dev Tests that `initiateWithdrawal` succeeds and correctly sets the state
/// of the message passer for the withdrawal hash.
function testFuzz_initiateWithdrawal_succeeds(
......@@ -43,7 +32,7 @@ contract L2ToL1MessagePasserTest is CommonTest {
)
external
{
uint256 nonce = messagePasser.messageNonce();
uint256 nonce = l2ToL1MessagePasser.messageNonce();
bytes32 withdrawalHash = Hashing.hashWithdrawal(
Types.WithdrawalTransaction({
......@@ -56,18 +45,18 @@ contract L2ToL1MessagePasserTest is CommonTest {
})
);
vm.expectEmit(true, true, true, true);
vm.expectEmit(address(l2ToL1MessagePasser));
emit MessagePassed(nonce, _sender, _target, _value, _gasLimit, _data, withdrawalHash);
vm.deal(_sender, _value);
vm.prank(_sender);
messagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);
l2ToL1MessagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);
assertEq(messagePasser.sentMessages(withdrawalHash), true);
assertEq(l2ToL1MessagePasser.sentMessages(withdrawalHash), true);
bytes32 slot = keccak256(bytes.concat(withdrawalHash, bytes32(0)));
assertEq(vm.load(address(messagePasser), slot), bytes32(uint256(1)));
assertEq(vm.load(address(l2ToL1MessagePasser), slot), bytes32(uint256(1)));
}
/// @dev Tests that `initiateWithdrawal` succeeds and emits the correct MessagePassed
......@@ -82,7 +71,7 @@ contract L2ToL1MessagePasserTest is CommonTest {
{
bytes32 withdrawalHash = Hashing.hashWithdrawal(
Types.WithdrawalTransaction({
nonce: messagePasser.messageNonce(),
nonce: l2ToL1MessagePasser.messageNonce(),
sender: address(this),
target: _target,
value: _value,
......@@ -91,13 +80,13 @@ contract L2ToL1MessagePasserTest is CommonTest {
})
);
vm.expectEmit(address(messagePasser));
vm.expectEmit(address(l2ToL1MessagePasser));
emit MessagePassed(
messagePasser.messageNonce(), address(this), _target, _value, _gasLimit, _data, withdrawalHash
l2ToL1MessagePasser.messageNonce(), address(this), _target, _value, _gasLimit, _data, withdrawalHash
);
vm.deal(address(this), _value);
messagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);
l2ToL1MessagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);
}
/// @dev Tests that `initiateWithdrawal` succeeds and emits the correct MessagePassed
......@@ -110,7 +99,7 @@ contract L2ToL1MessagePasserTest is CommonTest {
)
external
{
uint256 nonce = messagePasser.messageNonce();
uint256 nonce = l2ToL1MessagePasser.messageNonce();
// EOA emulation
vm.prank(alice, alice);
......@@ -118,29 +107,28 @@ contract L2ToL1MessagePasserTest is CommonTest {
bytes32 withdrawalHash =
Hashing.hashWithdrawal(Types.WithdrawalTransaction(nonce, alice, _target, _value, _gasLimit, _data));
vm.expectEmit(address(messagePasser));
vm.expectEmit(address(l2ToL1MessagePasser));
emit MessagePassed(nonce, alice, _target, _value, _gasLimit, _data, withdrawalHash);
messagePasser.initiateWithdrawal{ value: _value }({ _target: _target, _gasLimit: _gasLimit, _data: _data });
l2ToL1MessagePasser.initiateWithdrawal{ value: _value }({ _target: _target, _gasLimit: _gasLimit, _data: _data });
// the sent messages mapping is filled
assertEq(messagePasser.sentMessages(withdrawalHash), true);
assertEq(l2ToL1MessagePasser.sentMessages(withdrawalHash), true);
// the nonce increments
assertEq(nonce + 1, messagePasser.messageNonce());
assertEq(nonce + 1, l2ToL1MessagePasser.messageNonce());
}
/// @dev Tests that `burn` succeeds and destroys the ETH held in the contract.
function testFuzz_burn_succeeds(uint256 _value, address _target, uint256 _gasLimit, bytes memory _data) external {
vm.deal(address(this), _value);
messagePasser.initiateWithdrawal{ value: _value }({ _target: _target, _gasLimit: _gasLimit, _data: _data });
l2ToL1MessagePasser.initiateWithdrawal{ value: _value }({ _target: _target, _gasLimit: _gasLimit, _data: _data });
assertEq(address(messagePasser).balance, _value);
vm.expectEmit(true, false, false, false);
assertEq(address(l2ToL1MessagePasser).balance, _value);
emit WithdrawerBalanceBurnt(_value);
messagePasser.burn();
l2ToL1MessagePasser.burn();
// The Withdrawer should have no balance
assertEq(address(messagePasser).balance, 0);
assertEq(address(l2ToL1MessagePasser).balance, 0);
}
}
......@@ -4,25 +4,11 @@ pragma solidity 0.8.15;
// Testing utilities
import { CommonTest } from "test/CommonTest.t.sol";
// Testing contract dependencies
import { Predeploys } from "src/libraries/Predeploys.sol";
// Target contract
import { LegacyMessagePasser } from "src/legacy/LegacyMessagePasser.sol";
contract LegacyMessagePasser_Test is CommonTest {
LegacyMessagePasser messagePasser;
/// @dev Sets up the test suite.
function setUp() public virtual override {
super.setUp();
messagePasser = new LegacyMessagePasser();
}
/// @dev Tests that `passMessageToL1` succeeds.
function test_passMessageToL1_succeeds() external {
vm.prank(alice);
messagePasser.passMessageToL1(hex"ff");
assert(messagePasser.sentMessages(keccak256(abi.encodePacked(hex"ff", alice))));
legacyMessagePasser.passMessageToL1(hex"ff");
assert(legacyMessagePasser.sentMessages(keccak256(abi.encodePacked(hex"ff", alice))));
}
}
......@@ -36,7 +36,7 @@ contract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is L2OutputOracle_In
super.setUp();
// Create a proposer actor.
actor = new L2OutputOracle_Proposer(oracle, vm);
actor = new L2OutputOracle_Proposer(l2OutputOracle, vm);
// Set the target contract to the proposer actor.
targetContract(address(actor));
......@@ -57,6 +57,6 @@ contract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is L2OutputOracle_In
/// 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());
assertTrue(l2OutputOracle.nextBlockNumber() >= l2OutputOracle.latestBlockNumber());
}
}
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