Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
bcdc27a
Merge pull request #18 from defi-wonderland/chore/sync
0xDiscotech Sep 30, 2025
31e3d01
feat: add Revenue Share Upgrade Path (#8)
0xiamflux Sep 30, 2025
9310434
feat: Deploy FeesDepositor (#15)
0xiamflux Sep 30, 2025
129528c
feat: late opt-in template (#21)
0xiamflux Oct 6, 2025
47d480c
refactor: contracts update creationcode (#23)
0xiamflux Oct 6, 2025
e87344f
fix: sync (#24)
0xiamflux Oct 6, 2025
a8f4c70
test: add require tests for fields on Revenue Sharing templates (#26)
0xiamflux Oct 9, 2025
faee280
fix: L2 target ProxyAdmin (#27)
0xiamflux Oct 9, 2025
a65cb39
chore: update cost of upgrades and deployments (#29)
0xiamflux Oct 9, 2025
727e2dc
test: revenue sharing upgrade unit tests (#22)
0xChin Oct 15, 2025
9c5f1a2
test: add basic validation for fees depositor template (#32)
0xiamflux Oct 16, 2025
3a9fb15
chore: updates the bytecode for vaults, using initialize (#31)
0xiamflux Oct 16, 2025
944db58
test: integration supersim revshare (#30)
0xChin Oct 16, 2025
4e6f269
Merge branch 'main' into chore/sync-branch-revshare
Oct 17, 2025
5d968de
fix: broken simulations
Oct 17, 2025
bd67ee1
fix: wrong location of synced regression tests
Oct 17, 2025
4525ada
Merge pull request #37 from defi-wonderland/chore/sync-branch-revshare
0xDiscotech Oct 17, 2025
cf494c8
test: integration revshare late opt in (#33)
0xChin Oct 17, 2025
430b335
fix: ir fixes (#38)
0xDiscotech Oct 17, 2025
79c574a
Merge branch 'main' into chore/sync-branch-revshare
Oct 20, 2025
2448164
Merge pull request #42 from defi-wonderland/chore/sync-branch-revshare
0xDiscotech Oct 20, 2025
fe00ae7
chore: gas costs (#39)
0xChin Oct 20, 2025
a6ca033
fix: minors (#46)
0xChin Oct 24, 2025
143ba2e
fix: remove vm usage for getCreate2Address utils function (#48)
0xChin Oct 27, 2025
5d23831
feat: descope late opt in (#51)
0xChin Oct 28, 2025
300e54e
Merge branch 'main' into chore/sync-branch-revshare-v500
0xChin Nov 4, 2025
bd2ce05
Merge pull request #52 from defi-wonderland/chore/sync-branch-revshar…
0xDiscotech Nov 4, 2025
91a73ea
feat: add rev share upgrader (#53)
0xChin Nov 11, 2025
adf3de0
fix: bash on comment
0xDiscotech Nov 11, 2025
5361ed2
Merge branch 'main' into sc-feat/revshare-setup
0xDiscotech Nov 12, 2025
0666a5d
fix: forge fmt
0xDiscotech Nov 12, 2025
265d38e
refactor: reduce code size by splitting logic between lib and contrac…
0xDiscotech Nov 12, 2025
69b857c
refactor: split library (#60)
0xDiscotech Nov 12, 2025
09ad923
Merge branch 'main' into sc-feat/revshare-setup
0xDiscotech Nov 12, 2025
5142d69
feat: regression tests (#61)
0xChin Nov 12, 2025
6464067
fix: relay typo
0xDiscotech Nov 12, 2025
51d0459
fix: improve template validation checks (#62)
0xChin Nov 12, 2025
a5f7f3d
fix: wrong fee splitter bytecode (#63)
0xChin Nov 12, 2025
26ca8d6
Merge branch 'main' into sc-feat/revshare-setup
0xDiscotech Nov 12, 2025
a6e7094
fix: skip comment
0xDiscotech Nov 12, 2025
7373b09
fix: rename test create two deployer
0xDiscotech Nov 12, 2025
21dc253
chore: add commit
0xDiscotech Nov 12, 2025
79cbf92
feat: add upgrader deployment script (#64)
0xChin Nov 13, 2025
0c155c0
chore: update gas limits
0xChin Nov 13, 2025
a2d749d
refactor: use create two to get a deterministic deployment of the upg…
0xDiscotech Nov 13, 2025
fcc615d
chore: add todos (#66)
0xChin Nov 14, 2025
8b6d074
chore: remove tenderly simulations (#65)
0xChin Nov 14, 2025
c8d6eea
chore: deploy and update new contract (#67)
0xChin Nov 14, 2025
20e4142
fix: forge fmt (#69)
0xDiscotech Nov 14, 2025
0fb035c
chore: fuzz init code on get create2 test (#70)
0xDiscotech Nov 14, 2025
15fd88b
Merge branch 'main' into sc-feat/revshare-setup
0xDiscotech Nov 14, 2025
b992a83
feat: add (broken) template
0xChin Nov 17, 2025
54b5bdf
feat: deploy revshare mainnet (#71)
0xChin Nov 17, 2025
b7e519d
fix: forge fmt (#72)
0xDiscotech Nov 17, 2025
70c7088
chore: add todo comments (#73)
0xChin Nov 17, 2025
8ed9248
Merge branch 'sc-feat/revshare-setup' into test/setuprevshare-integra…
0xChin Nov 17, 2025
711d285
test: add revsharesetup template and tests
0xChin Nov 17, 2025
c8a8d32
test: update integration test for setup revshare
0xChin Nov 17, 2025
070650a
test: improve integration (#78)
0xChin Nov 18, 2025
11bbede
Merge branch 'main' into sc-feat/revshare-setup
0xDiscotech Nov 18, 2025
cce1033
Merge branch 'main' into sc-feat/revshare-setup
0xDiscotech Nov 19, 2025
78f4771
Merge branch 'sc-feat/revshare-setup' into test/setuprevshare-integra…
0xChin Nov 20, 2025
f64352a
test: fix vaults deployment
0xChin Nov 20, 2025
961b7b5
test: add fee disursement
0xChin Nov 20, 2025
73bff1b
fix: wrong template for revsharesetup tests
0xChin Nov 20, 2025
c39a7a4
chore: wrong rpc url
0xChin Nov 20, 2025
63c0ea7
refactor: improve tests function ordering
0xChin Nov 20, 2025
fcd71cb
Merge branch 'main' into test/setuprevshare-integration
0xChin Nov 20, 2025
42134c7
refactor: put reused code in integration base
0xChin Nov 20, 2025
9485bb9
fix: undo submodule update
0xDiscotech Nov 20, 2025
cdfba63
fix: typo
0xDiscotech Nov 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 201 additions & 0 deletions src/template/RevShareSetup.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

import {VmSafe} from "forge-std/Vm.sol";
import {stdToml} from "forge-std/StdToml.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

import {OPCMTaskBase} from "src/tasks/types/OPCMTaskBase.sol";
import {Action} from "src/libraries/MultisigTypes.sol";
import {MultisigTaskPrinter} from "src/libraries/MultisigTaskPrinter.sol";
import {RevShareContractsUpgrader} from "src/RevShareContractsUpgrader.sol";
import {FeeSplitterSetup} from "src/libraries/FeeSplitterSetup.sol";

/// @notice Task for setting up revenue sharing on OP Stack chains after predeploys upgrade.
contract RevShareSetup is OPCMTaskBase {
using stdToml for string;
using EnumerableSet for EnumerableSet.AddressSet;

/// @notice RevShareContractsUpgrader address
address public REV_SHARE_UPGRADER;

/// @notice RevShare configurations
RevShareContractsUpgrader.RevShareConfig[] internal revShareConfigs;

/// @notice Names in the SimpleAddressRegistry that are expected to be written during this task.
function _taskStorageWrites() internal pure virtual override returns (string[] memory) {
return new string[](0);
}

/// @notice Returns an array of strings that refer to contract names in the address registry.
function _taskBalanceChanges() internal view virtual override returns (string[] memory) {
return new string[](0);
}

/// @notice Sets the allowed storage accesses - override to add portal addresses
function _setAllowedStorageAccesses() internal virtual override {
super._setAllowedStorageAccesses();
// Add portal addresses as they will have storage writes from depositTransaction calls
for (uint256 i; i < revShareConfigs.length; i++) {
_allowedStorageAccesses.add(revShareConfigs[i].portal);
}
}

/// @notice Sets up the template with configurations from a TOML file.
function _templateSetup(string memory taskConfigFilePath, address) internal override {
string memory tomlContent = vm.readFile(taskConfigFilePath);

// Load RevShareContractsUpgrader address from TOML
REV_SHARE_UPGRADER = tomlContent.readAddress(".revShareUpgrader");
require(REV_SHARE_UPGRADER != address(0), "RevShareContractsUpgrader address cannot be zero");
require(REV_SHARE_UPGRADER.code.length > 0, "RevShareContractsUpgrader has no code");
vm.label(REV_SHARE_UPGRADER, "RevShareContractsUpgrader");

// Set RevShareContractsUpgrader as the allowed target for delegatecall
OPCM_TARGETS.push(REV_SHARE_UPGRADER);

// Load flattened arrays from TOML
address[] memory portals = abi.decode(tomlContent.parseRaw(".portals"), (address[]));
address[] memory chainFeesRecipients = abi.decode(tomlContent.parseRaw(".chainFeesRecipients"), (address[]));
uint256[] memory minWithdrawalAmounts =
abi.decode(tomlContent.parseRaw(".l1WithdrawerMinWithdrawalAmounts"), (uint256[]));
address[] memory l1WithdrawerRecipients =
abi.decode(tomlContent.parseRaw(".l1WithdrawerRecipients"), (address[]));
uint256[] memory gasLimits = abi.decode(tomlContent.parseRaw(".l1WithdrawerGasLimits"), (uint256[]));

// Validate all arrays have the same length
require(portals.length > 0, "No configs found");
require(
portals.length == chainFeesRecipients.length && portals.length == minWithdrawalAmounts.length
&& portals.length == l1WithdrawerRecipients.length && portals.length == gasLimits.length,
"Config arrays length mismatch"
);

// Validate individual configuration values and check for duplicates
for (uint256 i; i < portals.length; i++) {
// Validate portal address
require(portals[i] != address(0), string.concat("Portal address cannot be zero at index ", vm.toString(i)));
require(portals[i].code.length > 0, string.concat("Portal has no code at index ", vm.toString(i)));

// Check for duplicate portals
for (uint256 j; j < i; j++) {
require(portals[i] != portals[j], string.concat("Duplicate portal address at index ", vm.toString(i)));
}

// Validate chain fees recipient
require(
chainFeesRecipients[i] != address(0),
string.concat("Chain fees recipient cannot be zero at index ", vm.toString(i))
);

// Validate L1 withdrawer recipient
require(
l1WithdrawerRecipients[i] != address(0),
string.concat("L1 withdrawer recipient cannot be zero at index ", vm.toString(i))
);

// Validate gas limit bounds
require(gasLimits[i] > 0, string.concat("Gas limit must be greater than 0 at index ", vm.toString(i)));
require(
gasLimits[i] <= type(uint32).max,
string.concat("Gas limit exceeds uint32 max at index ", vm.toString(i))
);
}

// Construct RevShare configs array from flattened arrays
for (uint256 i; i < portals.length; i++) {
revShareConfigs.push(
RevShareContractsUpgrader.RevShareConfig({
portal: portals[i],
l1WithdrawerConfig: FeeSplitterSetup.L1WithdrawerConfig({
minWithdrawalAmount: minWithdrawalAmounts[i],
recipient: l1WithdrawerRecipients[i],
gasLimit: uint32(gasLimits[i])
}),
chainFeesRecipient: chainFeesRecipients[i]
})
);
}
}

/// @notice Builds the actions for executing the operations.
function _build(address) internal override {
// Delegatecall into RevShareContractsUpgrader
// OPCMTaskBase uses Multicall3Delegatecall, so this delegatecall will be captured as an action
(bool success,) =
REV_SHARE_UPGRADER.delegatecall(abi.encodeCall(RevShareContractsUpgrader.setupRevShare, (revShareConfigs)));
require(success, "RevShareSetup: Delegatecall failed");
}

/// @notice This method performs all validations and assertions that verify the calls executed as expected.
function _validate(VmSafe.AccountAccess[] memory, Action[] memory _actions, address) internal view override {
MultisigTaskPrinter.printTitle("Validating delegatecall to RevShareContractsUpgrader");

// For OPCM tasks using delegatecall, we validate that the delegatecall was made correctly.
// The actual portal calls happen inside the delegatecall and are validated by integration tests.

require(_actions.length == 1, "Expected exactly one action");

Action memory action = _actions[0];
require(action.target == REV_SHARE_UPGRADER, "Delegatecall to RevShareContractsUpgrader not found");
require(action.value == 0, "Call value must be 0 for delegatecall");

// Verify it's calling setupRevShare
bytes4 selector = bytes4(action.arguments);
require(
selector == RevShareContractsUpgrader.setupRevShare.selector, "Wrong function selector for delegatecall"
);

// Decode and validate the revShareConfigs argument
// Skip the first 4 bytes (function selector) and decode the rest
RevShareContractsUpgrader.RevShareConfig[] memory configs;
{
bytes memory args = action.arguments;
bytes memory argsWithoutSelector = new bytes(args.length - 4);
for (uint256 j = 4; j < args.length; j++) {
argsWithoutSelector[j - 4] = args[j];
}
configs = abi.decode(argsWithoutSelector, (RevShareContractsUpgrader.RevShareConfig[]));
}

// Validate each config
require(configs.length > 0, "No configs provided");
require(configs.length == revShareConfigs.length, "Config length mismatch");

for (uint256 i; i < configs.length; i++) {
RevShareContractsUpgrader.RevShareConfig memory config = configs[i];

// Validate portal address is not zero
require(config.portal != address(0), "Portal address cannot be zero");

// Validate L1 withdrawer config
require(config.l1WithdrawerConfig.recipient != address(0), "L1 withdrawer recipient cannot be zero");
require(config.l1WithdrawerConfig.gasLimit > 0, "Gas limit must be greater than 0");

// Validate chain fees recipient
require(config.chainFeesRecipient != address(0), "Chain fees recipient cannot be zero");

// Validate config matches the expected config from template setup
require(config.portal == revShareConfigs[i].portal, "Portal address mismatch");
require(
config.l1WithdrawerConfig.minWithdrawalAmount
== revShareConfigs[i].l1WithdrawerConfig.minWithdrawalAmount,
"Min withdrawal amount mismatch"
);
require(
config.l1WithdrawerConfig.recipient == revShareConfigs[i].l1WithdrawerConfig.recipient,
"L1 withdrawer recipient mismatch"
);
require(
config.l1WithdrawerConfig.gasLimit == revShareConfigs[i].l1WithdrawerConfig.gasLimit,
"Gas limit mismatch"
);
require(config.chainFeesRecipient == revShareConfigs[i].chainFeesRecipient, "Chain fees recipient mismatch");
}
}

/// @notice Override to return a list of addresses that should not be checked for code length.
function _getCodeExceptions() internal view virtual override returns (address[] memory) {
return new address[](0);
}
}
174 changes: 174 additions & 0 deletions test/integration/IntegrationBase.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,60 @@ import {Test} from "forge-std/Test.sol";
import {Vm} from "forge-std/Vm.sol";
import {console2} from "forge-std/console2.sol";
import {AddressAliasHelper} from "@eth-optimism-bedrock/src/vendor/AddressAliasHelper.sol";
import {RevShareContractsUpgrader} from "src/RevShareContractsUpgrader.sol";
import {Predeploys} from "@eth-optimism-bedrock/src/libraries/Predeploys.sol";
import {IFeeSplitter} from "src/interfaces/IFeeSplitter.sol";
import {IFeeVault} from "src/interfaces/IFeeVault.sol";
import {IL1Withdrawer} from "src/interfaces/IL1Withdrawer.sol";
import {ISuperchainRevSharesCalculator} from "src/interfaces/ISuperchainRevSharesCalculator.sol";

/// @title IntegrationBase
/// @notice Base contract for integration tests with L1->L2 deposit transaction relay functionality
abstract contract IntegrationBase is Test {
// Events for testing
event WithdrawalInitiated(address indexed recipient, uint256 amount);

// Fork IDs
uint256 internal _mainnetForkId;
uint256 internal _opMainnetForkId;
uint256 internal _inkMainnetForkId;

// Shared upgrader contract
RevShareContractsUpgrader public revShareUpgrader;

// L1 addresses
address internal constant PROXY_ADMIN_OWNER = 0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A;
address internal constant OP_MAINNET_PORTAL = 0xbEb5Fc579115071764c7423A4f12eDde41f106Ed;
address internal constant INK_MAINNET_PORTAL = 0x5d66C1782664115999C47c9fA5cd031f495D3e4F;
address internal constant REV_SHARE_UPGRADER_ADDRESS = 0x0000000000000000000000000000000000001337;

// L2 predeploys (same across all OP Stack chains)
address internal constant SEQUENCER_FEE_VAULT = 0x4200000000000000000000000000000000000011;
address internal constant OPERATOR_FEE_VAULT = 0x420000000000000000000000000000000000001b;
address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019;
address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A;
address internal constant FEE_SPLITTER = 0x420000000000000000000000000000000000002B;

// Expected deployed contracts (deterministic CREATE2 addresses)
address internal constant OP_L1_WITHDRAWER = 0xB3AeB34b88D73Fb4832f65BEa5Bd865017fB5daC;
address internal constant OP_REV_SHARE_CALCULATOR = 0x3E806Fd8592366E850197FEC8D80608b5526Bba2;

address internal constant INK_L1_WITHDRAWER = 0x70e26B12a578176BccCD3b7e7f58f605871c5eF7;
address internal constant INK_REV_SHARE_CALCULATOR = 0xd7a5307B4Ce92B0269903191007b95dF42552Dfa;

// Test configuration - OP Mainnet
uint256 internal constant OP_MIN_WITHDRAWAL_AMOUNT = 350000;
address internal constant OP_L1_WITHDRAWAL_RECIPIENT = 0x0000000000000000000000000000000000000001;
uint32 internal constant OP_WITHDRAWAL_GAS_LIMIT = 800000;
address internal constant OP_CHAIN_FEES_RECIPIENT = 0x0000000000000000000000000000000000000001;

// Test configuration - Ink Mainnet
uint256 internal constant INK_MIN_WITHDRAWAL_AMOUNT = 500000;
address internal constant INK_L1_WITHDRAWAL_RECIPIENT = 0x0000000000000000000000000000000000000002;
uint32 internal constant INK_WITHDRAWAL_GAS_LIMIT = 1000000;
address internal constant INK_CHAIN_FEES_RECIPIENT = 0x0000000000000000000000000000000000000002;

bool internal constant IS_SIMULATE = true;
/// @notice Relay all deposit transactions from L1 to multiple L2s
/// @param _forkIds Array of fork IDs for each L2 chain
/// @param _isSimulate If true, only process the second half of logs to avoid duplicates.
Expand Down Expand Up @@ -123,4 +173,128 @@ abstract contract IntegrationBase is Test {
}
return _result;
}

/// @notice Fund all fee vaults with specified amount
/// @param _amount Amount to fund each vault with
/// @param _forkId Fork ID to execute on
function _fundVaults(uint256 _amount, uint256 _forkId) internal {
vm.selectFork(_forkId);
vm.deal(SEQUENCER_FEE_VAULT, _amount);
vm.deal(OPERATOR_FEE_VAULT, _amount);
vm.deal(BASE_FEE_VAULT, _amount);
vm.deal(L1_FEE_VAULT, _amount);
}

/// @notice Assert the state of all L2 contracts after upgrade
/// @param _l1Withdrawer Expected L1Withdrawer address
/// @param _revShareCalculator Expected RevShareCalculator address
/// @param _minWithdrawalAmount Expected minimum withdrawal amount for L1Withdrawer
/// @param _l1Recipient Expected recipient address for L1Withdrawer
/// @param _gasLimit Expected gas limit for L1Withdrawer
/// @param _chainFeesRecipient Expected chain fees recipient (remainder recipient)
function _assertL2State(
address _l1Withdrawer,
address _revShareCalculator,
uint256 _minWithdrawalAmount,
address _l1Recipient,
uint32 _gasLimit,
address _chainFeesRecipient
) internal view {
// L1Withdrawer: check configuration
assertEq(
IL1Withdrawer(_l1Withdrawer).minWithdrawalAmount(),
_minWithdrawalAmount,
"L1Withdrawer minWithdrawalAmount mismatch"
);
assertEq(IL1Withdrawer(_l1Withdrawer).recipient(), _l1Recipient, "L1Withdrawer recipient mismatch");
assertEq(IL1Withdrawer(_l1Withdrawer).withdrawalGasLimit(), _gasLimit, "L1Withdrawer gasLimit mismatch");

// Rev Share Calculator: check it's linked correctly
assertEq(
ISuperchainRevSharesCalculator(_revShareCalculator).shareRecipient(),
_l1Withdrawer,
"Calculator shareRecipient should be L1Withdrawer"
);
assertEq(
ISuperchainRevSharesCalculator(_revShareCalculator).remainderRecipient(),
_chainFeesRecipient,
"Calculator remainderRecipient mismatch"
);

// Fee Splitter: check calculator is set
assertEq(
IFeeSplitter(FEE_SPLITTER).sharesCalculator(),
_revShareCalculator,
"FeeSplitter calculator should be set to RevShareCalculator"
);

// Vaults: recipient should be fee splitter, withdrawal network should be L2, min withdrawal amount 0
_assertFeeVaultsState();
}

/// @notice Assert the configuration of all fee vaults
function _assertFeeVaultsState() internal view {
_assertVaultGetters(SEQUENCER_FEE_VAULT, FEE_SPLITTER, IFeeVault.WithdrawalNetwork.L2, 0);
_assertVaultGetters(OPERATOR_FEE_VAULT, FEE_SPLITTER, IFeeVault.WithdrawalNetwork.L2, 0);
_assertVaultGetters(BASE_FEE_VAULT, FEE_SPLITTER, IFeeVault.WithdrawalNetwork.L2, 0);
_assertVaultGetters(L1_FEE_VAULT, FEE_SPLITTER, IFeeVault.WithdrawalNetwork.L2, 0);
}

/// @notice Assert the configuration of a single fee vault
/// @param _vault The address of the fee vault
/// @param _recipient The expected recipient of the fee vault
/// @param _withdrawalNetwork The expected withdrawal network
/// @param _minWithdrawalAmount The expected minimum withdrawal amount
/// @dev Ensures both the legacy and the new getters return the same value
function _assertVaultGetters(
address _vault,
address _recipient,
IFeeVault.WithdrawalNetwork _withdrawalNetwork,
uint256 _minWithdrawalAmount
) internal view {
// Check new getters
assertEq(IFeeVault(_vault).recipient(), _recipient, "Vault recipient mismatch");
assertEq(
uint256(IFeeVault(_vault).withdrawalNetwork()),
uint256(_withdrawalNetwork),
"Vault withdrawalNetwork mismatch"
);
assertEq(IFeeVault(_vault).minWithdrawalAmount(), _minWithdrawalAmount, "Vault minWithdrawalAmount mismatch");

// Check legacy getters (should return same values)
assertEq(IFeeVault(_vault).RECIPIENT(), _recipient, "Vault RECIPIENT (legacy) mismatch");
assertEq(
uint256(IFeeVault(_vault).WITHDRAWAL_NETWORK()),
uint256(_withdrawalNetwork),
"Vault WITHDRAWAL_NETWORK (legacy) mismatch"
);
assertEq(
IFeeVault(_vault).MIN_WITHDRAWAL_AMOUNT(),
_minWithdrawalAmount,
"Vault MIN_WITHDRAWAL_AMOUNT (legacy) mismatch"
);
}

/// @notice Execute disburseFees and assert that it triggers a withdrawal with the expected amount
/// @param _forkId The fork ID of the chain to test
/// @param _l1WithdrawalRecipient The expected recipient of the withdrawal
/// @param _expectedWithdrawalAmount The expected withdrawal amount
function _executeDisburseAndAssertWithdrawal(
uint256 _forkId,
address _l1WithdrawalRecipient,
uint256 _expectedWithdrawalAmount
) internal {
vm.selectFork(_forkId);
vm.warp(block.timestamp + IFeeSplitter(FEE_SPLITTER).feeDisbursementInterval() + 1);

uint256 balanceBefore = Predeploys.L2_TO_L1_MESSAGE_PASSER.balance;

vm.expectEmit(true, true, true, true);
emit WithdrawalInitiated(_l1WithdrawalRecipient, _expectedWithdrawalAmount);
IFeeSplitter(FEE_SPLITTER).disburseFees();

uint256 balanceAfter = Predeploys.L2_TO_L1_MESSAGE_PASSER.balance;

assertEq(balanceAfter - balanceBefore, _expectedWithdrawalAmount);
}
}
Loading