Skip to content

Commit

Permalink
Restore loadtest final merge (#61)
Browse files Browse the repository at this point in the history
Clone of matter-labs/era-contracts-private#10,
but targeted towards the gateway release candidate
  • Loading branch information
StanislavBreadless authored Dec 9, 2024
1 parent 502ee80 commit 7d809dd
Show file tree
Hide file tree
Showing 15 changed files with 272 additions and 105 deletions.
51 changes: 51 additions & 0 deletions l1-contracts/contracts/dev-contracts/L2SharedBridgeLegacyDev.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.24;

import {UpgradeableBeacon} from "@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol";

import {BridgedStandardERC20} from "../bridge/BridgedStandardERC20.sol";

import {L2SharedBridgeLegacy} from "../bridge/L2SharedBridgeLegacy.sol";
import {InvalidCaller, ZeroAddress, EmptyBytes32, Unauthorized, AmountMustBeGreaterThanZero, DeployFailed} from "../common/L1ContractErrors.sol";

contract L2SharedBridgeLegacyDev is L2SharedBridgeLegacy {
constructor() L2SharedBridgeLegacy() {}

/// @notice Initializes the bridge contract for later use. Expected to be used in the proxy.
/// @param _legacyBridge The address of the L1 Bridge contract.
/// @param _l1SharedBridge The address of the L1 Bridge contract.
/// @param _l2TokenProxyBytecodeHash The bytecode hash of the proxy for tokens deployed by the bridge.
/// @param _aliasedOwner The address of the governor contract.
function initializeDevBridge(
address _legacyBridge,
address _l1SharedBridge,
bytes32 _l2TokenProxyBytecodeHash,
address _aliasedOwner
) external reinitializer(2) {
if (_l1SharedBridge == address(0)) {
revert ZeroAddress();
}

if (_l2TokenProxyBytecodeHash == bytes32(0)) {
revert EmptyBytes32();
}

if (_aliasedOwner == address(0)) {
revert ZeroAddress();
}

l1SharedBridge = _l1SharedBridge;
l1Bridge = _legacyBridge;

// The following statement is true only in freshly deployed environments. However,
// for those environments we do not need to deploy this contract at all.
// This check is primarily for local testing purposes.
if (l2TokenProxyBytecodeHash == bytes32(0) && address(l2TokenBeacon) == address(0)) {
address l2StandardToken = address(new BridgedStandardERC20{salt: bytes32(0)}());
l2TokenBeacon = new UpgradeableBeacon{salt: bytes32(0)}(l2StandardToken);
l2TokenProxyBytecodeHash = _l2TokenProxyBytecodeHash;
l2TokenBeacon.transferOwnership(_aliasedOwner);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
era_chain_id = 9
owner_address = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
testnet_verifier = true
support_l2_legacy_shared_bridge_test = false

[contracts]
governance_security_council_address = "0x0000000000000000000000000000000000000000"
Expand Down
23 changes: 20 additions & 3 deletions l1-contracts/deploy-scripts/DeployL1.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import {L2ContractsBytecodesLib} from "./L2ContractsBytecodesLib.sol";
import {ValidiumL1DAValidator} from "contracts/state-transition/data-availability/ValidiumL1DAValidator.sol";
import {RollupDAManager} from "contracts/state-transition/data-availability/RollupDAManager.sol";
import {BytecodesSupplier} from "contracts/upgrades/BytecodesSupplier.sol";
import {L2LegacySharedBridgeTestHelper} from "./L2LegacySharedBridgeTestHelper.sol";

import {DeployUtils, GeneratedData, Config, DeployedAddresses, FixedForceDeploymentsData} from "./DeployUtils.s.sol";

Expand Down Expand Up @@ -310,9 +311,15 @@ contract DeployL1Script is Script, DeployUtils {
}

function deployL1NullifierImplementation() internal {
// TODO(EVM-743): allow non-dev nullifier in the local deployment
bytes memory bytecode;
if (config.supportL2LegacySharedBridgeTest) {
bytecode = type(L1NullifierDev).creationCode;
} else {
bytecode = type(L1Nullifier).creationCode;
}

address contractAddress = deployViaCreate2(
type(L1NullifierDev).creationCode,
bytecode,
// solhint-disable-next-line func-named-parameters
abi.encode(addresses.bridgehub.bridgehubProxy, config.eraChainId, addresses.stateTransition.diamondProxy)
);
Expand Down Expand Up @@ -688,6 +695,15 @@ contract DeployL1Script is Script, DeployUtils {
function prepareForceDeploymentsData() internal view returns (bytes memory) {
require(addresses.governance != address(0), "Governance address is not set");

address dangerousTestOnlyForcedBeacon;
if (config.supportL2LegacySharedBridgeTest) {
(dangerousTestOnlyForcedBeacon, ) = L2LegacySharedBridgeTestHelper.calculateTestL2TokenBeaconAddress(
addresses.bridges.erc20BridgeProxy,
addresses.bridges.l1NullifierProxy,
addresses.governance
);
}

FixedForceDeploymentsData memory data = FixedForceDeploymentsData({
l1ChainId: config.l1ChainId,
eraChainId: config.eraChainId,
Expand All @@ -708,7 +724,8 @@ contract DeployL1Script is Script, DeployUtils {
// For newly created chains it it is expected that the following bridges are not present at the moment
// of creation of the chain
l2SharedBridgeLegacyImpl: address(0),
l2BridgedStandardERC20Impl: address(0)
l2BridgedStandardERC20Impl: address(0),
dangerousTestOnlyForcedBeacon: dangerousTestOnlyForcedBeacon
});

return abi.encode(data);
Expand Down
8 changes: 2 additions & 6 deletions l1-contracts/deploy-scripts/DeployL2Contracts.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,10 @@ contract DeployL2Script is Script {
}

function run() public {
deploy(false);
deploy();
}

function runWithLegacyBridge() public {
deploy(true);
}

function deploy(bool legacyBridge) public {
function deploy() public {
initializeConfig();

// Note, that it is important that the first transaction is for setting the L2 DA validator
Expand Down
6 changes: 6 additions & 0 deletions l1-contracts/deploy-scripts/DeployUtils.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ struct FixedForceDeploymentsData {
bytes32 messageRootBytecodeHash;
address l2SharedBridgeLegacyImpl;
address l2BridgedStandardERC20Impl;
// The forced beacon address. It is needed only for internal testing.
// MUST be equal to 0 in production.
// It will be the job of the governance to ensure that this value is set correctly.
address dangerousTestOnlyForcedBeacon;
}

// solhint-disable-next-line gas-struct-packing
Expand Down Expand Up @@ -128,6 +132,7 @@ struct Config {
uint256 eraChainId;
address ownerAddress;
bool testnetVerifier;
bool supportL2LegacySharedBridgeTest;
ContractsConfig contracts;
TokensConfig tokens;
}
Expand Down Expand Up @@ -190,6 +195,7 @@ contract DeployUtils is Script {
config.eraChainId = toml.readUint("$.era_chain_id");
config.ownerAddress = toml.readAddress("$.owner_address");
config.testnetVerifier = toml.readBool("$.testnet_verifier");
config.supportL2LegacySharedBridgeTest = toml.readBool("$.support_l2_legacy_shared_bridge_test");

config.contracts.governanceSecurityCouncilAddress = toml.readAddress(
"$.contracts.governance_security_council_address"
Expand Down
6 changes: 6 additions & 0 deletions l1-contracts/deploy-scripts/L2ContractsBytecodesLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ library L2ContractsBytecodesLib {
return Utils.readZKFoundryBytecodeL1("L2SharedBridgeLegacy.sol", "L2SharedBridgeLegacy");
}

/// @notice Reads the bytecode of the L2SharedBridgeLegacy contract.
/// @return The bytecode of the L2SharedBridgeLegacy contract.
function readL2LegacySharedBridgeDevBytecode() internal view returns (bytes memory) {
return Utils.readZKFoundryBytecodeL1("L2SharedBridgeLegacyDev.sol", "L2SharedBridgeLegacyDev");
}

/// @notice Reads the bytecode of the L2GatewayUpgrade contract.
/// @return The bytecode of the L2GatewayUpgrade contract.
function readGatewayUpgradeBytecode() internal view returns (bytes memory) {
Expand Down
97 changes: 97 additions & 0 deletions l1-contracts/deploy-scripts/L2LegacySharedBridgeTestHelper.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {L2ContractsBytecodesLib} from "./L2ContractsBytecodesLib.sol";
import {L2ContractHelper} from "contracts/common/libraries/L2ContractHelper.sol";
import {Utils} from "./Utils.sol";
import {L2SharedBridgeLegacyDev} from "contracts/dev-contracts/L2SharedBridgeLegacyDev.sol";
import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol";

library L2LegacySharedBridgeTestHelper {
function calculateL2LegacySharedBridgeProxyAddr(
address l1Erc20BridgeProxy,
address l1NullifierProxy,
address ecosystemL1Governance
) internal view returns (address) {
// During local testing, we will deploy `L2SharedBridgeLegacyDev` to each chain
// that supports the legacy bridge.

bytes32 implHash = L2ContractHelper.hashL2Bytecode(
L2ContractsBytecodesLib.readL2LegacySharedBridgeDevBytecode()
);
address implAddress = Utils.getL2AddressViaCreate2Factory(bytes32(0), implHash, hex"");

bytes32 proxyHash = L2ContractHelper.hashL2Bytecode(
L2ContractsBytecodesLib.readTransparentUpgradeableProxyBytecode()
);

return
Utils.getL2AddressViaCreate2Factory(
bytes32(0),
proxyHash,
getLegacySharedBridgeProxyConstructorParams(
implAddress,
l1Erc20BridgeProxy,
l1NullifierProxy,
ecosystemL1Governance
)
);
}

function getLegacySharedBridgeProxyConstructorParams(
address _implAddress,
address _l1Erc20BridgeProxy,
address _l1NullifierProxy,
address _ecosystemL1Governance
) internal view returns (bytes memory) {
bytes32 beaconProxyBytecodeHash = L2ContractHelper.hashL2Bytecode(
L2ContractsBytecodesLib.readBeaconProxyBytecode()
);

bytes memory initializeData = abi.encodeCall(
L2SharedBridgeLegacyDev.initializeDevBridge,
(
_l1Erc20BridgeProxy,
// While the variable is named `sharedBridge`, in reality it will have the same
// address as the nullifier
_l1NullifierProxy,
beaconProxyBytecodeHash,
AddressAliasHelper.applyL1ToL2Alias(_ecosystemL1Governance)
)
);

return abi.encode(_implAddress, AddressAliasHelper.applyL1ToL2Alias(_ecosystemL1Governance), initializeData);
}

function calculateTestL2TokenBeaconAddress(
address l1Erc20BridgeProxy,
address l1NullifierProxy,
address ecosystemL1Governance
) internal view returns (address tokenBeaconAddress, bytes32 tokenBeaconBytecodeHash) {
address l2SharedBridgeAddress = calculateL2LegacySharedBridgeProxyAddr(
l1Erc20BridgeProxy,
l1NullifierProxy,
ecosystemL1Governance
);

bytes32 bridgedL2ERC20Hash = L2ContractHelper.hashL2Bytecode(
L2ContractsBytecodesLib.readStandardERC20Bytecode()
);
address bridgeL2ERC20ImplAddress = L2ContractHelper.computeCreate2Address(
l2SharedBridgeAddress,
bytes32(0),
bridgedL2ERC20Hash,
keccak256(hex"")
);

tokenBeaconBytecodeHash = L2ContractHelper.hashL2Bytecode(
L2ContractsBytecodesLib.readUpgradeableBeaconBytecode()
);
tokenBeaconAddress = L2ContractHelper.computeCreate2Address(
l2SharedBridgeAddress,
bytes32(0),
tokenBeaconBytecodeHash,
keccak256(abi.encode(bridgeL2ERC20ImplAddress))
);
}
}
Loading

0 comments on commit 7d809dd

Please sign in to comment.