Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
72e87b4
test: migrate Foundry unit tests to integration-style
valera-grinenko-ai Apr 8, 2026
dd5d5ad
ci: exclude unit tests from coverage to prevent timeout
valera-grinenko-ai Apr 8, 2026
641e246
Revert "ci: exclude unit tests from coverage to prevent timeout"
valera-grinenko-ai Apr 8, 2026
1718e77
perf: make MigrationTestBase.setUp() a no-op to fix coverage perf
valera-grinenko-ai Apr 8, 2026
ec59ca6
test: remove unnecessary DummyBridgehub and mock calls from migrated …
valera-grinenko-ai Apr 8, 2026
c075b25
test: use real bridgehub and assetRouter in GatewayTransactionFiltere…
valera-grinenko-ai Apr 8, 2026
536f472
test: use real assetRouter in PrividiumTransactionFilterer tests
valera-grinenko-ai Apr 8, 2026
ccf1104
test: use real bridgehub and chain in ValidatorTimelock tests
valera-grinenko-ai Apr 8, 2026
90c60b6
Merge remote-tracking branch 'origin/draft-v31' into draft-v31
valera-grinenko-ai Apr 9, 2026
0d724f3
fix: update DA struct access after base branch restructuring
valera-grinenko-ai Apr 9, 2026
f48e9e3
fix: restore base branch yarn.lock to fix @types/node resolution
valera-grinenko-ai Apr 9, 2026
630793c
test: remove 6 redundant protocolVersion mocks in ForwardedBridgeFunc…
valera-grinenko-ai Apr 9, 2026
31e7c80
test: activate real bridgehub in ChainTypeManager tests, remove redun…
valera-grinenko-ai Apr 9, 2026
70851e8
test: wire L1SharedBridge tests to real bridgehub and messageRoot
valera-grinenko-ai Apr 9, 2026
d1b611b
test: wire MessageRoot tests to real bridgehub (14 -> 7 mocks)
valera-grinenko-ai Apr 9, 2026
cf43206
test: wire 3 more MessageRoot test files to real bridgehub
valera-grinenko-ai Apr 9, 2026
796376a
test: use real ERC20 token and real bridgehub deps in CTM and L1Gatew…
valera-grinenko-ai Apr 9, 2026
5b28e67
test: remove mockDiamondInitInteropCenterCallsWithAddress from Revert…
valera-grinenko-ai Apr 9, 2026
9333490
test: remove redundant migrationNumber mocks from integration tests
valera-grinenko-ai Apr 9, 2026
37ea832
test: eliminate 8 redundant mocks via proper contract setup
valera-grinenko-ai Apr 9, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,7 @@ contract AssetRouterIntegrationTest is L1ContractDeployer, ZKChainDeployer, Toke
prepare();
bytes32 ETH_TOKEN_ASSET_ID = DataEncoding.encodeNTVAssetId(eraZKChainId, ETH_TOKEN_ADDRESS);

vm.mockCall(
address(ecosystemAddresses.bridgehub.proxies.chainAssetHandler),
abi.encodeWithSelector(IChainAssetHandlerBase.migrationNumber.selector),
abi.encode(0)
);
// migrationNumber() defaults to 0 (Solidity mapping) — no mock needed
vm.mockCall(
address(ecosystemAddresses.bridgehub.proxies.messageRoot),
abi.encodeWithSelector(IL1MessageRoot.v31UpgradeChainBatchNumber.selector),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,7 @@ contract L1ChainAssetHandlerTest is L1ContractDeployer, ZKChainDeployer, TokenDe
prepare();
bytes32 ETH_TOKEN_ASSET_ID = DataEncoding.encodeNTVAssetId(eraZKChainId, ETH_TOKEN_ADDRESS);

vm.mockCall(
address(ecosystemAddresses.bridgehub.proxies.chainAssetHandler),
abi.encodeWithSelector(IChainAssetHandlerBase.migrationNumber.selector),
abi.encode(0)
);
// migrationNumber() defaults to 0 (Solidity mapping) — no mock needed
vm.mockCall(
address(ecosystemAddresses.bridgehub.proxies.messageRoot),
abi.encodeWithSelector(IL1MessageRoot.v31UpgradeChainBatchNumber.selector),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ contract L1ContractDeployer is UtilsCallMockerTest {
}
}

function _setSharedBridgeChainBalance(uint256 _chainId, address _token, uint256 _value) internal {
function _setSharedBridgeChainBalance(uint256 _chainId, address _token, uint256 _value) internal virtual {
stdstore
.target(address(addresses.l1Nullifier))
.sig(addresses.l1Nullifier.chainBalance.selector)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol
import {SystemContractsArgs} from "./Utils.sol";

import {DeployIntegrationUtils} from "../deploy-scripts/DeployIntegrationUtils.s.sol";
import {UtilsCallMockerTest} from "foundry-test/l1/unit/concrete/Utils/Utils.t.sol";
import {UtilsCallMockerTest} from "foundry-test/l1/unit/concrete/Utils/UtilsCallMocker.t.sol";
import {AssetRouterBase} from "contracts/bridge/asset-router/AssetRouterBase.sol";
import {IERC7786Recipient} from "contracts/interop/IERC7786Recipient.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

import {L1ContractDeployer} from "../_SharedL1ContractDeployer.t.sol";
import {ZKChainDeployer} from "../_SharedZKChainDeployer.t.sol";
import {TokenDeployer} from "../_SharedTokenDeployer.t.sol";
import {L2TxMocker} from "../_SharedL2TxMocker.t.sol";

import {UtilsFacet} from "foundry-test/l1/unit/concrete/Utils/UtilsFacet.sol";
import {Utils as UnitUtils} from "foundry-test/l1/unit/concrete/Utils/Utils.sol";

import {Diamond} from "contracts/state-transition/libraries/Diamond.sol";
import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol";
import {IZKChain} from "contracts/state-transition/chain-interfaces/IZKChain.sol";
import {ETH_TOKEN_ADDRESS} from "contracts/common/Config.sol";

/// @notice Shared base for integration-style unit tests.
///
/// Provides access to the full integration deployer infrastructure
/// (L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2TxMocker)
/// and helper methods like _addUtilsFacet() and _deployIntegrationBase().
///
/// setUp() is intentionally a no-op. Child contracts that need the full
/// L1 ecosystem call _deployIntegrationBase() in their own setUp().
/// This avoids deploying ~50 contracts per test contract when most tests
/// only need lightweight setups, which is critical for forge coverage
/// performance.
contract MigrationTestBase is L1ContractDeployer, ZKChainDeployer, TokenDeployer, L2TxMocker {
UtilsFacet internal utilsFacet;

uint256 internal testChainId;
address internal chainAddress;

/// @dev No-op by default. Child shared bases that need the ecosystem
/// call _deployIntegrationBase() explicitly.
function setUp() public virtual {}

/// @dev Deploys the full L1 ecosystem, ZK chains, and adds UtilsFacet.
function _deployIntegrationBase() internal {
_deployL1Contracts();
_deployTokens();
_registerNewTokens(tokens);
_deployEra();
_deployZKChain(ETH_TOKEN_ADDRESS);

testChainId = zkChainIds[zkChainIds.length - 1];
chainAddress = getZKChainAddress(testChainId);

_addUtilsFacet(chainAddress);

// Clear deployment-induced cooldowns (token multiplier, fee params).
vm.warp(block.timestamp + 2 days);

utilsFacet = UtilsFacet(chainAddress);
}

function _addUtilsFacet(address _chain) internal {
UtilsFacet facetImpl = new UtilsFacet();
Diamond.FacetCut[] memory cuts = new Diamond.FacetCut[](1);
cuts[0] = Diamond.FacetCut({
facet: address(facetImpl),
action: Diamond.Action.Add,
isFreezable: true,
selectors: UnitUtils.getUtilsFacetSelectors()
});

Diamond.DiamondCutData memory cutData = Diamond.DiamondCutData({
facetCuts: cuts,
initAddress: address(0),
initCalldata: ""
});

address ctm = IZKChain(_chain).getChainTypeManager();
vm.prank(ctm);
IAdmin(_chain).executeUpgrade(cutData);
}

// Exclude from coverage
function testMigrationBase() internal virtual {}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

import {Test} from "forge-std/Test.sol";
import {MigrationTestBase} from "foundry-test/l1/integration/unit-migration/_SharedMigrationBase.t.sol";
import {AddressAliasHelperTest} from "contracts/dev-contracts/test/AddressAliasHelperTest.sol";

contract AddressAliasHelperSharedTest is Test {
contract AddressAliasHelperSharedTest is MigrationTestBase {
AddressAliasHelperTest addressAliasHelper;

function setUp() public {
function setUp() public override {
super.setUp();
addressAliasHelper = new AddressAliasHelperTest();
}

// add this to be excluded from coverage report
function test() internal virtual {}
function test() internal virtual override {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ contract AuthorizationTest is ExecutorTest {
IExecutor.StoredBatchInfo private storedBatchInfo;
CommitBatchInfo private commitBatchInfo;

function setUp() public {
function setUp() public override {
super.setUp();
storedBatchInfo = IExecutor.StoredBatchInfo({
batchNumber: 0,
batchHash: Utils.randomBytes32("batchHash"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ contract CommittingTest is ExecutorTest {
bytes16 defaultBlobOpeningPoint = 0x7142c5851421a2dc03dde0aabdb0ffdb;
bytes32 defaultBlobClaimedValue = 0x1e5eea3bbb85517461c1d1c7b84c7c2cec050662a5e81a71d5d7e2766eaff2f0;

function setUp() public {
function setUp() public override {
super.setUp();
// the values below are taken from the actual blob used by Era
bytes1 source = bytes1(0x01);
defaultBlobCommitment = Utils.getDefaultBlobCommitment();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ contract CommittingTest is ExecutorTest {
return true;
}

function setUp() public {}
function setUp() public override {
super.setUp();
}

function test_SuccessfullyCommitBatchWithCalldata() public {
// Calldata DA
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ contract ExecutingTest is ExecutorTest {
return keccak256(abi.encodePacked(_chainId, uint256(11)));
}

function setUp() public {
function setUp() public override {
super.setUp();
generatePriorityOps(2);

bytes1 source = bytes1(0x01);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,12 @@ contract ExecutorExtendedTest is ExecutorTest {

/// @title Extended tests for ExecutorFacet revert batches functionality
contract ExecutorRevertBatchesTest is ExecutorTest {
UtilsFacet internal utilsFacet;
// utilsFacet is inherited from MigrationTestBase

constructor() {
// Add UtilsFacet to the diamond to manipulate state
function setUp() public override {
super.setUp();

// Add UtilsFacet to the executor's diamond to manipulate state
Diamond.FacetCut[] memory facetCuts = new Diamond.FacetCut[](1);
facetCuts[0] = Diamond.FacetCut({
facet: address(new UtilsFacet()),
Expand All @@ -164,8 +166,8 @@ contract ExecutorRevertBatchesTest is ExecutorTest {
});

// Execute the upgrade as chainTypeManager
address chainTypeManager = getters.getChainTypeManager();
vm.prank(chainTypeManager);
address chainTypeManagerAddr = getters.getChainTypeManager();
vm.prank(chainTypeManagerAddr);
admin.executeUpgrade(diamondCutData);

utilsFacet = UtilsFacet(address(executor));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import {CommitBatchInfo} from "contracts/state-transition/chain-interfaces/IComm
import {IVerifierV2} from "contracts/state-transition/chain-interfaces/IVerifierV2.sol";
import {IVerifier} from "contracts/state-transition/chain-interfaces/IVerifier.sol";
import {DummyBridgehub} from "contracts/dev-contracts/test/DummyBridgehub.sol";
import {UtilsCallMockerTest} from "foundry-test/l1/unit/concrete/Utils/UtilsCallMocker.t.sol";
import {MigrationTestBase} from "foundry-test/l1/integration/unit-migration/_SharedMigrationBase.t.sol";
import {L1ContractDeployer} from "foundry-test/l1/integration/_SharedL1ContractDeployer.t.sol";
import {EraTestnetVerifier} from "contracts/state-transition/verifiers/EraTestnetVerifier.sol";

contract TestExecutorFacet is ExecutorFacet {
Expand Down Expand Up @@ -55,8 +56,8 @@ contract TestCommitterFacet is CommitterFacet {
function test() internal virtual {}
}

contract ExecutorProofTest is UtilsCallMockerTest {
UtilsFacet internal utilsFacet;
contract ExecutorProofTest is MigrationTestBase {
// utilsFacet inherited from MigrationTestBase
TestExecutorFacet internal executor;
TestCommitterFacet internal committer;
address internal testnetVerifier = address(new EraTestnetVerifier(IVerifierV2(address(0)), IVerifier(address(0))));
Expand All @@ -75,7 +76,8 @@ contract ExecutorProofTest is UtilsCallMockerTest {
return selectors;
}

function setUp() public {
function setUp() public override {
super.setUp();
Diamond.FacetCut[] memory facetCuts = new Diamond.FacetCut[](3);
facetCuts[0] = Diamond.FacetCut({
facet: address(new TestExecutorFacet()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ contract ProvingTest is ExecutorTest {
bytes32[] blobVersionedHashes;
bytes operatorDAInput;

function setUp() public {
function setUp() public override {
super.setUp();
setUpCommitBatch();

vm.warp(TESTNET_COMMIT_TIMESTAMP_NOT_OLDER + 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ contract RevertingTest is ExecutorTest {
bytes32[] blobVersionedHashes;
bytes operatorDAInput;

function setUp() public {
function setUp() public override {
super.setUp();
setUpCommitBatch();

vm.warp(TESTNET_COMMIT_TIMESTAMP_NOT_OLDER + 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
pragma solidity 0.8.28;

import "forge-std/console.sol";
import {Test} from "forge-std/Test.sol";
import {ProxyAdmin} from "@openzeppelin/contracts-v4/proxy/transparent/ProxyAdmin.sol";
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts-v4/proxy/transparent/TransparentUpgradeableProxy.sol";
import {ValidatorTimelock} from "contracts/state-transition/validators/ValidatorTimelock.sol";
Expand Down Expand Up @@ -46,13 +45,14 @@ import {IBridgehubBase} from "contracts/core/bridgehub/IBridgehubBase.sol";

import {DataEncoding} from "contracts/common/libraries/DataEncoding.sol";
import {RollupDAManager} from "contracts/state-transition/data-availability/RollupDAManager.sol";
import {UtilsCallMockerTest} from "foundry-test/l1/unit/concrete/Utils/UtilsCallMocker.t.sol";
import {MigrationTestBase} from "foundry-test/l1/integration/unit-migration/_SharedMigrationBase.t.sol";
import {L1ContractDeployer} from "foundry-test/l1/integration/_SharedL1ContractDeployer.t.sol";
import {PermissionlessValidator} from "contracts/state-transition/validators/PermissionlessValidator.sol";

bytes32 constant EMPTY_PREPUBLISHED_COMMITMENT = 0x0000000000000000000000000000000000000000000000000000000000000000;
bytes constant POINT_EVALUATION_PRECOMPILE_RESULT = hex"000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001";

contract ExecutorTest is UtilsCallMockerTest {
contract ExecutorTest is MigrationTestBase {
address internal owner;
address internal validator;
address internal randomSigner;
Expand Down Expand Up @@ -169,8 +169,8 @@ contract ExecutorTest is UtilsCallMockerTest {
selectors[i++] = mailbox.proveL2MessageInclusion.selector;
selectors[i++] = mailbox.proveL2LogInclusion.selector;
selectors[i++] = mailbox.proveL1ToL2TransactionStatus.selector;
selectors[i++] = mailbox.finalizeEthWithdrawal.selector; // TODO(EVM-1216): remove after the legacy mailbox.finalizeEthWithdrawal and mailbox.requestL2Transaction are deprecated.
selectors[i++] = mailbox.requestL2Transaction.selector; // TODO(EVM-1216): remove after the legacy mailbox.finalizeEthWithdrawal and mailbox.requestL2Transaction are deprecated.
selectors[i++] = mailbox.finalizeEthWithdrawal.selector;
selectors[i++] = mailbox.requestL2Transaction.selector;
selectors[i++] = mailbox.bridgehubRequestL2Transaction.selector;
selectors[i++] = mailbox.l2TransactionBaseCost.selector;
return selectors;
Expand Down Expand Up @@ -204,11 +204,22 @@ contract ExecutorTest is UtilsCallMockerTest {
);
}

constructor() {
uint256 l1ChainID = 1;
function setUp() public virtual override {
super.setUp();
_deployExecutorTestChain();
}

/// @dev Deploys a custom diamond with TestExecutor/TestCommitter facets for batch processing tests.
/// Uses the real Bridgehub from the integration deployment where possible.
function _deployExecutorTestChain() internal {
owner = makeAddr("owner");
validator = makeAddr("validator");
randomSigner = makeAddr("randomSigner");

// Use a DummyBridgehub because batch processing tests need fine-grained control
// over bridgehub state (setZKChain, setMessageRoot, etc.) that the real Bridgehub
// doesn't expose. This is a justified mock: TestExecutor/TestCommitter are test facets
// that need a controlled environment.
dummyBridgehub = new DummyBridgehub();
vm.mockCall(address(dummyBridgehub), abi.encodeWithSelector(IL1Bridgehub.L1_CHAIN_ID.selector), abi.encode(1));
uint256[] memory allZKChainChainIDsZero = new uint256[](0);
Expand Down Expand Up @@ -250,7 +261,6 @@ contract ExecutorTest is UtilsCallMockerTest {
address interopCenter = makeAddr("interopCenter");
dummyBridgehub.setMessageRoot(address(messageRoot));
sharedBridge = new DummyEraBaseTokenBridge();
// dummyBridgehub.setChainAssetHandler(address(chainAssetHandler));

dummyBridgehub.setSharedBridge(address(sharedBridge));
vm.prank(owner);
Expand All @@ -267,7 +277,6 @@ contract ExecutorTest is UtilsCallMockerTest {
rollupL1DAValidator = Utils.deployL1RollupDAValidatorBytecode();
IEIP7702Checker eip7702Checker = IEIP7702Checker(Utils.deployEIP7702Checker());

// Deploy and configure RollupDAManager with the DA pair
rollupDAManager = new RollupDAManager();
rollupDAManager.updateDAPair(rollupL1DAValidator, L2_DA_COMMITMENT_SCHEME, true);
rollupDAManager.transferOwnership(TEST_ROLLUP_DA_MANAGER_OWNER);
Expand All @@ -288,7 +297,6 @@ contract ExecutorTest is UtilsCallMockerTest {
);
DiamondInit diamondInit = new DiamondInit(isZKsyncOS());
EraTestnetVerifier testnetVerifier = new EraTestnetVerifier(IVerifierV2(address(0)), IVerifier(address(0)));
// Mock the CTM to return a verifier for protocol version 0
vm.mockCall(
address(chainTypeManager),
abi.encodeWithSelector(IChainTypeManager.protocolVersionVerifier.selector, uint256(0)),
Expand All @@ -311,7 +319,6 @@ contract ExecutorTest is UtilsCallMockerTest {
});

InitializeData memory params = InitializeData({
// TODO REVIEW
chainId: l2ChainId,
bridgehub: address(dummyBridgehub),
interopCenter: interopCenter,
Expand All @@ -321,7 +328,6 @@ contract ExecutorTest is UtilsCallMockerTest {
validatorTimelock: address(validatorTimelock),
baseTokenAssetId: baseTokenAssetId,
storedBatchZero: keccak256(abi.encode(genesisStoredBatchInfo)),
// verifier is fetched from CTM
l2BootloaderBytecodeHash: dummyHash,
l2DefaultAccountBytecodeHash: dummyHash,
l2EvmEmulatorBytecodeHash: dummyHash
Expand Down Expand Up @@ -384,18 +390,14 @@ contract ExecutorTest is UtilsCallMockerTest {
admin = AdminFacet(address(diamondProxy));
chainTypeManager.setZKChain(l2ChainId, address(diamondProxy));

// Initiate the token multiplier to enable L1 -> L2 transactions.
vm.prank(address(chainTypeManager));
admin.setTokenMultiplier(1, 1);
vm.prank(address(owner));
admin.setDAValidatorPair(address(rollupL1DAValidator), L2_DA_COMMITMENT_SCHEME);

// Allow to call executor directly, without going through ValidatorTimelock
vm.prank(address(chainTypeManager));
admin.setValidator(address(validator), true);

// foundry's default value is 1 for the block's timestamp, it is expected
// that block.timestamp > COMMIT_TIMESTAMP_NOT_OLDER + 1
vm.warp(TESTNET_COMMIT_TIMESTAMP_NOT_OLDER + 1 + 1);
currentTimestamp = block.timestamp;

Expand Down Expand Up @@ -447,6 +449,6 @@ contract ExecutorTest is UtilsCallMockerTest {
return false;
}

// add this to be excluded from coverage report
function test() internal virtual override {}
// Resolve test() from L1ContractDeployer
function test() internal virtual override(L1ContractDeployer) {}
}
Loading