Commit 6958ad7f authored by Maurelian's avatar Maurelian Committed by GitHub

Proxies and Gas benchmark tests (#2901)

* bedrock: Add delegateProxy to forge tests

* bedrock: Add chugsplash proxy to bridge tests

* test(ctb): add gas benchmark tests

* test(ctb): Benchmark deposits at INITIAL_BASE_FEE
Co-authored-by: default avatarmergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
parent 0fea4f52
This diff is collapsed.
//SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
/* Testing utilities */
import { Test } from "forge-std/Test.sol";
import { Vm } from "forge-std/Vm.sol";
import "./CommonTest.t.sol";
import { CrossDomainMessenger } from "../universal/CrossDomainMessenger.sol";
import { ResourceMetering } from "../L1/ResourceMetering.sol";
uint128 constant INITIAL_BASE_FEE = 1_000_000_000;
// Free function for setting the prevBaseFee param in the OptimismPortal.
function setPrevBaseFee(
Vm _vm,
address _op,
uint128 _prevBaseFee
) {
_vm.store(
address(_op),
bytes32(uint256(1)),
bytes32(
abi.encode(
ResourceMetering.ResourceParams({
prevBaseFee: _prevBaseFee,
prevBoughtGas: 0,
prevBlockNum: uint64(block.number)
})
)
)
);
}
// Tests for obtaining pure gas cost estimates for commonly used functions.
// The objective with these benchmarks is to strip down the actual test functions
// so that they are nothing more than the call we want measure the gas cost of.
// In order to achieve this we make no assertions, and handle everything else in the setUp()
// function.
contract GasBenchMark_OptimismPortal is Portal_Initializer {
function test_depositTransaction_benchmark() external {
op.depositTransaction{ value: NON_ZERO_VALUE }(
NON_ZERO_ADDRESS,
ZERO_VALUE,
NON_ZERO_GASLIMIT,
false,
NON_ZERO_DATA
);
}
function test_depositTransaction_benchmark_1() external {
setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE);
op.depositTransaction{ value: NON_ZERO_VALUE }(
NON_ZERO_ADDRESS,
ZERO_VALUE,
NON_ZERO_GASLIMIT,
false,
NON_ZERO_DATA
);
}
}
contract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer {
function test_L1MessengerSendMessage_benchmark_0() external {
// The amount of data typically sent during a bridge deposit.
bytes
memory data = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
L1Messenger.sendMessage(bob, data, uint32(100));
}
function test_L1MessengerSendMessage_benchmark_1() external {
setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE);
// The amount of data typically sent during a bridge deposit.
bytes
memory data = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
L1Messenger.sendMessage(bob, data, uint32(100));
}
}
contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {
function setUp() public virtual override {
super.setUp();
deal(address(L1Token), alice, 100000, true);
vm.startPrank(alice, alice);
}
function test_depositETH_benchmark_0() external {
L1Bridge.depositETH{ value: 500 }(50000, hex"");
}
function test_depositETH_benchmark_1() external {
setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE);
L1Bridge.depositETH{ value: 500 }(50000, hex"");
}
function test_depositERC20_benchmark_0() external {
L1Bridge.depositETH{ value: 500 }(50000, hex"");
}
function test_depositERC20_benchmark_1() external {
setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE);
L1Bridge.depositETH{ value: 500 }(50000, hex"");
}
}
contract GasBenchMark_L1StandardBridge_Finalize is Bridge_Initializer {
function setUp() public virtual override {
super.setUp();
deal(address(L1Token), address(L1Bridge), 100, true);
vm.mockCall(
address(L1Bridge.messenger()),
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(L1Bridge.otherBridge()))
);
vm.startPrank(address(L1Bridge.messenger()));
vm.deal(address(L1Bridge.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"");
}
}
contract GasBenchMark_L2OutputOracle is L2OutputOracle_Initializer {
uint256 nextBlockNumber;
function setUp() public override {
super.setUp();
nextBlockNumber = oracle.nextBlockNumber();
warpToAppendTime(nextBlockNumber);
vm.startPrank(sequencer);
}
function test_appendL2Output_benchmark() external {
oracle.appendL2Output(nonZeroHash, nextBlockNumber, 0, 0);
}
}
...@@ -19,10 +19,15 @@ import { Lib_PredeployAddresses } from "../libraries/Lib_PredeployAddresses.sol" ...@@ -19,10 +19,15 @@ import { Lib_PredeployAddresses } from "../libraries/Lib_PredeployAddresses.sol"
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { Proxy } from "../universal/Proxy.sol"; import { Proxy } from "../universal/Proxy.sol";
import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import { Lib_ResolvedDelegateProxy } from "../legacy/Lib_ResolvedDelegateProxy.sol";
import { Lib_AddressManager } from "../legacy/Lib_AddressManager.sol";
import { L1ChugSplashProxy } from "../legacy/L1ChugSplashProxy.sol";
import { iL1ChugSplashDeployer } from "../legacy/L1ChugSplashProxy.sol";
contract CommonTest is Test { contract CommonTest is Test {
address alice = address(128); address alice = address(128);
address bob = address(256); address bob = address(256);
address multisig = address(512);
address immutable ZERO_ADDRESS = address(0); address immutable ZERO_ADDRESS = address(0);
address immutable NON_ZERO_ADDRESS = address(1); address immutable NON_ZERO_ADDRESS = address(1);
...@@ -36,9 +41,11 @@ contract CommonTest is Test { ...@@ -36,9 +41,11 @@ contract CommonTest is Test {
// Give alice and bob some ETH // Give alice and bob some ETH
vm.deal(alice, 1 << 16); vm.deal(alice, 1 << 16);
vm.deal(bob, 1 << 16); vm.deal(bob, 1 << 16);
vm.deal(multisig, 1 << 16);
vm.label(alice, "alice"); vm.label(alice, "alice");
vm.label(bob, "bob"); vm.label(bob, "bob");
vm.label(multisig, "multisig");
// Make sure we have a non-zero base fee // Make sure we have a non-zero base fee
vm.fee(1000000000); vm.fee(1000000000);
...@@ -63,6 +70,11 @@ contract L2OutputOracle_Initializer is CommonTest { ...@@ -63,6 +70,11 @@ contract L2OutputOracle_Initializer is CommonTest {
// Test data // Test data
uint256 initL1Time; uint256 initL1Time;
// Advance the evm's time to meet the L2OutputOracle's requirements for appendL2Output
function warpToAppendTime(uint256 _nextBlockNumber) public {
vm.warp(oracle.computeL2Timestamp(_nextBlockNumber) + 1);
}
function setUp() public virtual { function setUp() public virtual {
_setUp(); _setUp();
...@@ -82,8 +94,8 @@ contract L2OutputOracle_Initializer is CommonTest { ...@@ -82,8 +94,8 @@ contract L2OutputOracle_Initializer is CommonTest {
sequencer, sequencer,
owner owner
); );
Proxy proxy = new Proxy(alice); Proxy proxy = new Proxy(multisig);
vm.prank(alice); vm.prank(multisig);
proxy.upgradeToAndCall( proxy.upgradeToAndCall(
address(oracleImpl), address(oracleImpl),
abi.encodeWithSelector( abi.encodeWithSelector(
...@@ -103,16 +115,14 @@ contract Portal_Initializer is L2OutputOracle_Initializer { ...@@ -103,16 +115,14 @@ contract Portal_Initializer is L2OutputOracle_Initializer {
OptimismPortal opImpl; OptimismPortal opImpl;
OptimismPortal op; OptimismPortal op;
function setUp() public override virtual { function setUp() public virtual override {
L2OutputOracle_Initializer.setUp(); L2OutputOracle_Initializer.setUp();
opImpl = new OptimismPortal(oracle, 7 days); opImpl = new OptimismPortal(oracle, 7 days);
Proxy proxy = new Proxy(alice); Proxy proxy = new Proxy(multisig);
vm.prank(alice); vm.prank(multisig);
proxy.upgradeToAndCall( proxy.upgradeToAndCall(
address(opImpl), address(opImpl),
abi.encodeWithSelector( abi.encodeWithSelector(OptimismPortal.initialize.selector)
OptimismPortal.initialize.selector
)
); );
op = OptimismPortal(payable(address(proxy))); op = OptimismPortal(payable(address(proxy)));
} }
...@@ -120,6 +130,7 @@ contract Portal_Initializer is L2OutputOracle_Initializer { ...@@ -120,6 +130,7 @@ contract Portal_Initializer is L2OutputOracle_Initializer {
contract Messenger_Initializer is L2OutputOracle_Initializer { contract Messenger_Initializer is L2OutputOracle_Initializer {
OptimismPortal op; OptimismPortal op;
Lib_AddressManager addressManager;
L1CrossDomainMessenger L1Messenger; L1CrossDomainMessenger L1Messenger;
L2CrossDomainMessenger L2Messenger = L2CrossDomainMessenger L2Messenger =
L2CrossDomainMessenger(Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER); L2CrossDomainMessenger(Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER);
...@@ -164,7 +175,22 @@ contract Messenger_Initializer is L2OutputOracle_Initializer { ...@@ -164,7 +175,22 @@ contract Messenger_Initializer is L2OutputOracle_Initializer {
op = new OptimismPortal(oracle, 7 days); op = new OptimismPortal(oracle, 7 days);
vm.label(address(op), "OptimismPortal"); vm.label(address(op), "OptimismPortal");
L1Messenger = new L1CrossDomainMessenger(op); // Deploy the address manager
vm.prank(multisig);
addressManager = new Lib_AddressManager();
// Setup implementation
L1CrossDomainMessenger L1MessengerImpl = new L1CrossDomainMessenger(op);
// Setup the address manager and proxy
vm.prank(multisig);
addressManager.setAddress("OVM_L1CrossDomainMessenger", address(L1MessengerImpl));
Lib_ResolvedDelegateProxy proxy = new Lib_ResolvedDelegateProxy(
address(addressManager),
"OVM_L1CrossDomainMessenger"
);
L1Messenger = L1CrossDomainMessenger(address(proxy));
L1Messenger.initialize(op);
vm.etch( vm.etch(
Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER, Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER,
...@@ -178,13 +204,13 @@ contract Messenger_Initializer is L2OutputOracle_Initializer { ...@@ -178,13 +204,13 @@ contract Messenger_Initializer is L2OutputOracle_Initializer {
Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER, Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER,
address(new L2ToL1MessagePasser()).code address(new L2ToL1MessagePasser()).code
); );
vm.label(address(addressManager), "AddressManager");
vm.label(address(L1MessengerImpl), "L1CrossDomainMessenger_Impl");
vm.label(address(L1Messenger), "L1CrossDomainMessenger_Proxy");
vm.label(Lib_PredeployAddresses.OVM_ETH, "OVM_ETH");
vm.label(Lib_PredeployAddresses.OVM_ETH, "OVM_ETH"); vm.label(Lib_PredeployAddresses.OVM_ETH, "OVM_ETH");
vm.label(Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER, "L2ToL1MessagePasser"); vm.label(Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER, "L2ToL1MessagePasser");
vm.label(Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER, "L2CrossDomainMessenger"); vm.label(Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER, "L2CrossDomainMessenger");
vm.label( vm.label(
AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)), AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)),
"L1CrossDomainMessenger_aliased" "L1CrossDomainMessenger_aliased"
...@@ -310,8 +336,23 @@ contract Bridge_Initializer is Messenger_Initializer { ...@@ -310,8 +336,23 @@ contract Bridge_Initializer is Messenger_Initializer {
// Deploy the L1 bridge and initialize it with the address of the // Deploy the L1 bridge and initialize it with the address of the
// L1CrossDomainMessenger // L1CrossDomainMessenger
L1Bridge = new L1StandardBridge(payable(address(L1Messenger))); L1ChugSplashProxy proxy = new L1ChugSplashProxy(multisig);
vm.label(address(L1Bridge), "L1StandardBridge"); vm.mockCall(
multisig,
abi.encodeWithSelector(iL1ChugSplashDeployer.isUpgrading.selector),
abi.encode(true)
);
vm.startPrank(multisig);
proxy.setCode(type(L1StandardBridge).runtimeCode);
vm.clearMockedCalls();
address L1Bridge_Impl = proxy.getImplementation();
vm.stopPrank();
L1Bridge = L1StandardBridge(payable(address(proxy)));
L1Bridge.initialize(payable(address(L1Messenger)));
vm.label(address(proxy), "L1StandardBridge_Proxy");
vm.label(address(L1Bridge_Impl), "L1StandardBridge_Impl");
// Deploy the L2StandardBridge, move it to the correct predeploy // Deploy the L2StandardBridge, move it to the correct predeploy
// address and then initialize it // address and then initialize it
......
...@@ -13,11 +13,6 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer { ...@@ -13,11 +13,6 @@ contract L2OutputOracleTest is L2OutputOracle_Initializer {
super.setUp(); super.setUp();
} }
// Advance the evm's time to meet the L2OutputOracle's requirements for appendL2Output
function warpToAppendTime(uint256 _nextBlockNumber) public {
vm.warp(oracle.computeL2Timestamp(_nextBlockNumber) + 1);
}
function test_constructor() external { function test_constructor() external {
assertEq(oracle.owner(), owner); assertEq(oracle.owner(), owner);
assertEq(oracle.SUBMISSION_INTERVAL(), submissionInterval); assertEq(oracle.SUBMISSION_INTERVAL(), submissionInterval);
...@@ -376,7 +371,7 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer { ...@@ -376,7 +371,7 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer {
assertEq(bytes32(0), slot21Before); assertEq(bytes32(0), slot21Before);
NextImpl nextImpl = new NextImpl(); NextImpl nextImpl = new NextImpl();
vm.startPrank(alice); vm.startPrank(multisig);
proxy.upgradeToAndCall( proxy.upgradeToAndCall(
address(nextImpl), address(nextImpl),
abi.encodeWithSelector(NextImpl.initialize.selector) abi.encodeWithSelector(NextImpl.initialize.selector)
......
...@@ -348,7 +348,7 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer { ...@@ -348,7 +348,7 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer {
assertEq(bytes32(0), slot21Before); assertEq(bytes32(0), slot21Before);
NextImpl nextImpl = new NextImpl(); NextImpl nextImpl = new NextImpl();
vm.startPrank(alice); vm.startPrank(multisig);
proxy.upgradeToAndCall( proxy.upgradeToAndCall(
address(nextImpl), address(nextImpl),
abi.encodeWithSelector(NextImpl.initialize.selector) abi.encodeWithSelector(NextImpl.initialize.selector)
......
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