Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SC-473] Refactor integration tests to make it easier to add many domains #22

Merged
merged 1 commit into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
42 changes: 10 additions & 32 deletions test/ArbitrumOneCrosschainTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,55 +7,33 @@ import { ArbitrumBridgeTesting } from 'lib/xchain-helpers/src/testing/bridges/Ar
import { ArbitrumForwarder } from 'lib/xchain-helpers/src/forwarders/ArbitrumForwarder.sol';
import { ArbitrumReceiver } from 'lib/xchain-helpers/src/receivers/ArbitrumReceiver.sol';

contract ArbitrumOneCrosschainPayload is CrosschainPayload {

constructor(IPayload _targetPayload, address _bridgeReceiver)
CrosschainPayload(_targetPayload, _bridgeReceiver) {}

function execute() external override {
ArbitrumForwarder.sendMessageL1toL2(
ArbitrumForwarder.L1_CROSS_DOMAIN_ARBITRUM_ONE,
bridgeReceiver,
encodeCrosschainExecutionMessage(),
1_000_000,
1 gwei,
block.basefee + 10 gwei
);
}

}
import { ArbitrumCrosschainPayload } from './payloads/ArbitrumCrosschainPayload.sol';

contract ArbitrumOneCrosschainTest is CrosschainTestBase {

using DomainHelpers for *;
using ArbitrumBridgeTesting for *;

function deployCrosschainPayload(IPayload targetPayload, address bridgeReceiver)
public override returns (IPayload)
internal override returns (IPayload)
{
return IPayload(new ArbitrumOneCrosschainPayload(targetPayload, bridgeReceiver));
return IPayload(new ArbitrumCrosschainPayload(ArbitrumForwarder.L1_CROSS_DOMAIN_ARBITRUM_ONE, targetPayload, bridgeReceiver));
}

function setUp() public {
function setupDomain() internal override {
remote = getChain('arbitrum_one').createFork();
bridge = ArbitrumBridgeTesting.createNativeBridge(
getChain('mainnet').createFork(),
getChain('arbitrum_one').createFork()
mainnet,
remote
);

bridge.destination.selectFork();
bridgeExecutor = new Executor(
defaultL2BridgeExecutorArgs.delay,
defaultL2BridgeExecutorArgs.gracePeriod
);
remote.selectFork();
bridgeReceiver = address(new ArbitrumReceiver(
defaultL2BridgeExecutorArgs.ethereumGovernanceExecutor,
address(bridgeExecutor)
vm.computeCreateAddress(address(this), 3)
));
bridgeExecutor.grantRole(bridgeExecutor.SUBMISSION_ROLE(), bridgeReceiver);
bridgeExecutor.grantRole(bridgeExecutor.GUARDIAN_ROLE(), defaultL2BridgeExecutorArgs.guardian);
bridgeExecutor.revokeRole(bridgeExecutor.DEFAULT_ADMIN_ROLE(), address(this));

bridge.source.selectFork();
mainnet.selectFork();
vm.deal(L1_EXECUTOR, 0.01 ether);
}

Expand Down
40 changes: 9 additions & 31 deletions test/BaseChainCrosschainTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,53 +7,31 @@ import { OptimismBridgeTesting } from 'lib/xchain-helpers/src/testing/bridges/Op
import { OptimismForwarder } from 'lib/xchain-helpers/src/forwarders/OptimismForwarder.sol';
import { OptimismReceiver } from 'lib/xchain-helpers/src/receivers/OptimismReceiver.sol';

contract BaseChainCrosschainPayload is CrosschainPayload {

constructor(IPayload _targetPayload, address _bridgeReceiver)
CrosschainPayload(_targetPayload, _bridgeReceiver) {}

function execute() external override {
OptimismForwarder.sendMessageL1toL2(
OptimismForwarder.L1_CROSS_DOMAIN_BASE,
bridgeReceiver,
encodeCrosschainExecutionMessage(),
1_000_000
);
}

}
import { OptimismCrosschainPayload } from './payloads/OptimismCrosschainPayload.sol';

contract BaseChainCrosschainTest is CrosschainTestBase {

using DomainHelpers for *;
using OptimismBridgeTesting for *;

function deployCrosschainPayload(IPayload targetPayload, address bridgeReceiver)
public override returns (IPayload)
internal override returns (IPayload)
{
return IPayload(new BaseChainCrosschainPayload(targetPayload, bridgeReceiver));
return IPayload(new OptimismCrosschainPayload(OptimismForwarder.L1_CROSS_DOMAIN_BASE, targetPayload, bridgeReceiver));
}

function setUp() public {
function setupDomain() internal override {
remote = getChain('base').createFork();
bridge = OptimismBridgeTesting.createNativeBridge(
getChain('mainnet').createFork(),
getChain('base').createFork()
mainnet,
remote
);

bridge.destination.selectFork();
bridgeExecutor = new Executor(
defaultL2BridgeExecutorArgs.delay,
defaultL2BridgeExecutorArgs.gracePeriod
);
remote.selectFork();
bridgeReceiver = address(new OptimismReceiver(
defaultL2BridgeExecutorArgs.ethereumGovernanceExecutor,
address(bridgeExecutor)
vm.computeCreateAddress(address(this), 2)
));
bridgeExecutor.grantRole(bridgeExecutor.SUBMISSION_ROLE(), bridgeReceiver);
bridgeExecutor.grantRole(bridgeExecutor.GUARDIAN_ROLE(), defaultL2BridgeExecutorArgs.guardian);
bridgeExecutor.revokeRole(bridgeExecutor.DEFAULT_ADMIN_ROLE(), address(this));

bridge.source.selectFork();
}

function relayMessagesAcrossBridge() internal override {
Expand Down
92 changes: 41 additions & 51 deletions test/CrosschainTestBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,92 +3,82 @@ pragma solidity ^0.8.0;

import 'forge-std/Test.sol';

import { Domain } from 'lib/xchain-helpers/src/testing/Domain.sol';
import { Bridge } from 'lib/xchain-helpers/src/testing/Bridge.sol';
import { DomainHelpers } from 'lib/xchain-helpers/src/testing/Domain.sol';

import { IExecutor } from 'src/interfaces/IExecutor.sol';
import { Executor } from 'src/Executor.sol';

import { IL1Executor } from './interfaces/IL1Executor.sol';
import { IPayload } from './interfaces/IPayload.sol';
import { IPayload } from './payloads/IPayload.sol';

import { PayloadWithEmit } from './mocks/PayloadWithEmit.sol';
import { ReconfigurationPayload } from './mocks/ReconfigurationPayload.sol';

interface IL1Executor {
function exec(address target, bytes calldata args)
external
payable
returns (bytes memory out);
}

struct L2BridgeExecutorArguments {
address ethereumGovernanceExecutor;
uint256 delay;
uint256 gracePeriod;
address guardian;
}

abstract contract CrosschainPayload is IPayload {

IPayload immutable targetPayload;
address immutable bridgeReceiver;

constructor(IPayload _targetPayload, address _bridgeReceiver) {
targetPayload = _targetPayload;
bridgeReceiver = _bridgeReceiver;
}

function execute() external virtual;

function encodeCrosschainExecutionMessage() internal view returns (bytes memory) {
address[] memory targets = new address[](1);
targets[0] = address(targetPayload);
uint256[] memory values = new uint256[](1);
values[0] = 0;
string[] memory signatures = new string[](1);
signatures[0] = 'execute()';
bytes[] memory calldatas = new bytes[](1);
calldatas[0] = '';
bool[] memory withDelegatecalls = new bool[](1);
withDelegatecalls[0] = true;

return abi.encodeWithSelector(
IExecutor.queue.selector,
targets,
values,
signatures,
calldatas,
withDelegatecalls
);
}

}

abstract contract CrosschainTestBase is Test {

using DomainHelpers for *;

event TestEvent();

address public constant L1_EXECUTOR = 0x3300f198988e4C9C63F75dF86De36421f06af8c4;
address public constant L1_PAUSE_PROXY = 0xBE8E3e3618f7474F8cB1d074A26afFef007E98FB;
address public GUARDIAN = makeAddr('guardian');
address constant L1_EXECUTOR = 0x3300f198988e4C9C63F75dF86De36421f06af8c4;
address constant L1_PAUSE_PROXY = 0xBE8E3e3618f7474F8cB1d074A26afFef007E98FB;
address GUARDIAN = makeAddr('guardian');

L2BridgeExecutorArguments public defaultL2BridgeExecutorArgs = L2BridgeExecutorArguments({
L2BridgeExecutorArguments defaultL2BridgeExecutorArgs = L2BridgeExecutorArguments({
ethereumGovernanceExecutor: L1_EXECUTOR,
delay: 600,
gracePeriod: 1200,
guardian: GUARDIAN
});

Bridge public bridge;
Domain mainnet;
Domain remote;
Bridge bridge;

Executor bridgeExecutor;
address bridgeReceiver;

function setUp() public {
mainnet = getChain("mainnet").createFork();

setupDomain();

remote.selectFork();

Executor public bridgeExecutor;
address public bridgeReceiver;
bridgeExecutor = new Executor(
defaultL2BridgeExecutorArgs.delay,
defaultL2BridgeExecutorArgs.gracePeriod
);
bridgeExecutor.grantRole(bridgeExecutor.SUBMISSION_ROLE(), bridgeReceiver);
bridgeExecutor.grantRole(bridgeExecutor.GUARDIAN_ROLE(), defaultL2BridgeExecutorArgs.guardian);
bridgeExecutor.revokeRole(bridgeExecutor.DEFAULT_ADMIN_ROLE(), address(this));
}

function deployCrosschainPayload(IPayload targetPayload, address bridgeReceiver) public virtual returns (IPayload);
function deployCrosschainPayload(IPayload targetPayload, address bridgeReceiver) internal virtual returns (IPayload);
function relayMessagesAcrossBridge() internal virtual;
function setupDomain() internal virtual;

function preparePayloadExecution() public {
bridge.destination.selectFork();
function preparePayloadExecution() internal {
remote.selectFork();

IPayload targetPayload = IPayload(new PayloadWithEmit());

bridge.source.selectFork();
mainnet.selectFork();

IPayload crosschainPayload = deployCrosschainPayload(
targetPayload,
Expand Down Expand Up @@ -304,7 +294,7 @@ abstract contract CrosschainTestBase is Test {
}

function test_selfReconfiguration() public {
bridge.destination.selectFork();
remote.selectFork();

L2BridgeExecutorArguments memory newL2BridgeExecutorParams = L2BridgeExecutorArguments({
ethereumGovernanceExecutor: defaultL2BridgeExecutorArgs.ethereumGovernanceExecutor,
Expand Down Expand Up @@ -337,7 +327,7 @@ abstract contract CrosschainTestBase is Test {
newL2BridgeExecutorParams.guardian
));

bridge.source.selectFork();
mainnet.selectFork();

IPayload crosschainPayload = deployCrosschainPayload(
reconfigurationPayload,
Expand Down
38 changes: 8 additions & 30 deletions test/GnosisCrosschainTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,57 +4,35 @@ pragma solidity ^0.8.0;
import './CrosschainTestBase.sol';

import { AMBBridgeTesting } from 'lib/xchain-helpers/src/testing/bridges/AMBBridgeTesting.sol';
import { AMBForwarder } from 'lib/xchain-helpers/src/forwarders/AMBForwarder.sol';
import { AMBReceiver } from 'lib/xchain-helpers/src/receivers/AMBReceiver.sol';

contract GnosisCrosschainPayload is CrosschainPayload {

constructor(IPayload _targetPayload, address _bridgeReceiver)
CrosschainPayload(_targetPayload, _bridgeReceiver) {}

function execute() external override {
AMBForwarder.sendMessageEthereumToGnosisChain(
bridgeReceiver,
encodeCrosschainExecutionMessage(),
1_000_000
);
}

}
import { GnosisCrosschainPayload } from './payloads/GnosisCrosschainPayload.sol';

contract GnosisCrosschainTest is CrosschainTestBase {

using DomainHelpers for *;
using AMBBridgeTesting for *;

function deployCrosschainPayload(IPayload targetPayload, address bridgeReceiver)
public override returns (IPayload)
internal override returns (IPayload)
{
return IPayload(new GnosisCrosschainPayload(targetPayload, bridgeReceiver));
}

function setUp() public {
function setupDomain() internal override {
remote = getChain('gnosis_chain').createFork();
bridge = AMBBridgeTesting.createGnosisBridge(
getChain('mainnet').createFork(),
getChain('gnosis_chain').createFork()
mainnet,
remote
);

bridge.destination.selectFork();
bridgeExecutor = new Executor(
defaultL2BridgeExecutorArgs.delay,
defaultL2BridgeExecutorArgs.gracePeriod
);
remote.selectFork();
bridgeReceiver = address(new AMBReceiver(
AMBBridgeTesting.getGnosisMessengerFromChainAlias(bridge.destination.chain.chainAlias),
bytes32(uint256(1)), // Ethereum chainid
defaultL2BridgeExecutorArgs.ethereumGovernanceExecutor,
address(bridgeExecutor)
vm.computeCreateAddress(address(this), 2)
));
bridgeExecutor.grantRole(bridgeExecutor.SUBMISSION_ROLE(), bridgeReceiver);
bridgeExecutor.grantRole(bridgeExecutor.GUARDIAN_ROLE(), defaultL2BridgeExecutorArgs.guardian);
bridgeExecutor.revokeRole(bridgeExecutor.DEFAULT_ADMIN_ROLE(), address(this));

bridge.source.selectFork();
}

function relayMessagesAcrossBridge() internal override {
Expand Down
Loading
Loading