Skip to content

Commit

Permalink
Merge pull request #817 from matter-labs/sb-sync-stable-with-main-2
Browse files Browse the repository at this point in the history
Sync-layer-stable with main
  • Loading branch information
StanislavBreadless committed Sep 22, 2024
2 parents b3c30ae + 4568e1f commit de3f407
Show file tree
Hide file tree
Showing 4 changed files with 266 additions and 9 deletions.
1 change: 1 addition & 0 deletions .solhintignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ l1-contracts-foundry/lib
# l2-contracts
l2-contracts/cache-zk
l2-contracts/node_modules
l2-contracts/contracts/dev-contracts
l2-contracts/test

# system-contracts
Expand Down
20 changes: 19 additions & 1 deletion l1-contracts/deploy-scripts/DeployL2Contracts.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ contract DeployL2Script is Script {
address forceDeployUpgraderAddress;
address consensusRegistryImplementation;
address consensusRegistryProxy;
address multicall3;
}

function run() public {
Expand All @@ -53,6 +54,7 @@ contract DeployL2Script is Script {
deployForceDeployer();
deployConsensusRegistry();
deployConsensusRegistryProxy();
deployMulticall3();

saveOutput();
}
Expand Down Expand Up @@ -104,7 +106,7 @@ contract DeployL2Script is Script {

function saveOutput() internal {
vm.serializeAddress("root", "l2_da_validator_address", deployed.l2DaValidatorAddress);

vm.serializeAddress("root", "multicall3", deployed.multicall3);
vm.serializeAddress("root", "consensus_registry_implementation", deployed.consensusRegistryImplementation);
vm.serializeAddress("root", "consensus_registry_proxy", deployed.consensusRegistryProxy);
string memory toml = vm.serializeAddress("root", "l2_default_upgrader", deployed.forceDeployUpgraderAddress);
Expand Down Expand Up @@ -165,6 +167,22 @@ contract DeployL2Script is Script {
});
}

function deployMulticall3() internal {
// Multicall3 doesn't have a constructor.
bytes memory constructorData = "";

deployed.multicall3 = Utils.deployThroughL1({
bytecode: L2ContractsBytecodesLib.readMulticall3Bytecode(),
constructorargs: constructorData,
create2salt: "",
l2GasLimit: Utils.MAX_PRIORITY_TX_GAS,
factoryDeps: new bytes[](0),
chainId: config.chainId,
bridgehubAddress: config.bridgehubAddress,
l1SharedBridgeProxy: config.l1SharedBridgeProxy
});
}

// Deploy a transparent upgradable proxy for the already deployed consensus registry
// implementation and save its address into the config.
function deployConsensusRegistryProxy() internal {
Expand Down
17 changes: 9 additions & 8 deletions l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.0;
import {Script} from "forge-std/Script.sol";
import {stdToml} from "forge-std/StdToml.sol";
import {Utils} from "./../Utils.sol";
import {L2ContractsBytecodesLib} from "../L2ContractsBytecodesLib.sol";
import {L1SharedBridge} from "contracts/bridge/L1SharedBridge.sol";
import {DummyL1ERC20Bridge} from "contracts/dev-contracts/DummyL1ERC20Bridge.sol";
import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
Expand Down Expand Up @@ -104,30 +105,30 @@ contract SetupLegacyBridge is Script {
function setParamsForDummyBridge() internal {
(address l2TokenBeacon, bytes32 l2TokenBeaconHash) = calculateTokenBeaconAddress();
DummyL1ERC20Bridge bridge = DummyL1ERC20Bridge(addresses.erc20BridgeProxy);
vm.broadcast();
bridge.setValues(config.l2SharedBridgeAddress, l2TokenBeacon, l2TokenBeaconHash);
}

function calculateTokenBeaconAddress()
internal
returns (address tokenBeaconAddress, bytes32 tokenBeaconBytecodeHash)
{
bytes memory l2StandardTokenCode = Utils.readHardhatBytecode(
"/../l2-contracts/artifacts-zk/contracts/bridge/L2StandardERC20.sol/L2StandardERC20.json"
);
bytes memory l2StandardTokenCode = L2ContractsBytecodesLib.readStandardERC20Bytecode();
(address l2StandardToken, ) = calculateL2Create2Address(
config.l2SharedBridgeAddress,
l2StandardTokenCode,
bytes32(0),
""
);

bytes memory beaconProxy = Utils.readHardhatBytecode(
"/../l2-contracts/artifacts-zk/@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol/BeaconProxy.json"
);
bytes memory beaconProxy = L2ContractsBytecodesLib.readBeaconProxyBytecode();
tokenBeaconBytecodeHash = L2ContractHelper.hashL2Bytecode(beaconProxy);

bytes memory upgradableBeacon = L2ContractsBytecodesLib.readUpgradeableBeaconBytecode();

(tokenBeaconAddress, tokenBeaconBytecodeHash) = calculateL2Create2Address(
(tokenBeaconAddress, ) = calculateL2Create2Address(
config.l2SharedBridgeAddress,
beaconProxy,
upgradableBeacon,
bytes32(0),
abi.encode(l2StandardToken)
);
Expand Down
237 changes: 237 additions & 0 deletions l2-contracts/contracts/dev-contracts/Multicall3.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

/// @title Multicall3
/// @notice Aggregate results from multiple function calls
/// @dev Multicall & Multicall2 backwards-compatible
/// @dev Aggregate methods are marked `payable` to save 24 gas per call
/// @author Michael Elliot <[email protected]>
/// @author Joshua Levine <[email protected]>
/// @author Nick Johnson <[email protected]>
/// @author Andreas Bigger <[email protected]>
/// @author Matt Solomon <[email protected]>
contract Multicall3 {
// add this to be excluded from coverage report
function test() internal virtual {}

struct Call {
address target;
bytes callData;
}

struct Call3 {
address target;
bool allowFailure;
bytes callData;
}

struct Call3Value {
address target;
bool allowFailure;
uint256 value;
bytes callData;
}

struct Result {
bool success;
bytes returnData;
}

/// @notice Backwards-compatible call aggregation with Multicall
/// @param calls An array of Call structs
/// @return blockNumber The block number where the calls were executed
/// @return returnData An array of bytes containing the responses
function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) {
blockNumber = block.number;
uint256 length = calls.length;
returnData = new bytes[](length);
Call calldata call;
for (uint256 i = 0; i < length; ) {
bool success;
call = calls[i];
(success, returnData[i]) = call.target.call(call.callData);
require(success, "Multicall3: call failed");
unchecked {
++i;
}
}
}

/// @notice Backwards-compatible with Multicall2
/// @notice Aggregate calls without requiring success
/// @param requireSuccess If true, require all calls to succeed
/// @param calls An array of Call structs
/// @return returnData An array of Result structs
function tryAggregate(
bool requireSuccess,
Call[] calldata calls
) public payable returns (Result[] memory returnData) {
uint256 length = calls.length;
returnData = new Result[](length);
Call calldata call;
for (uint256 i = 0; i < length; ) {
Result memory result = returnData[i];
call = calls[i];
(result.success, result.returnData) = call.target.call(call.callData);
if (requireSuccess) require(result.success, "Multicall3: call failed");
unchecked {
++i;
}
}
}

/// @notice Backwards-compatible with Multicall2
/// @notice Aggregate calls and allow failures using tryAggregate
/// @param calls An array of Call structs
/// @return blockNumber The block number where the calls were executed
/// @return blockHash The hash of the block where the calls were executed
/// @return returnData An array of Result structs
function tryBlockAndAggregate(
bool requireSuccess,
Call[] calldata calls
) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {
blockNumber = block.number;
blockHash = blockhash(block.number);
returnData = tryAggregate(requireSuccess, calls);
}

/// @notice Backwards-compatible with Multicall2
/// @notice Aggregate calls and allow failures using tryAggregate
/// @param calls An array of Call structs
/// @return blockNumber The block number where the calls were executed
/// @return blockHash The hash of the block where the calls were executed
/// @return returnData An array of Result structs
function blockAndAggregate(
Call[] calldata calls
) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) {
(blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);
}

/// @notice Aggregate calls, ensuring each returns success if required
/// @param calls An array of Call3 structs
/// @return returnData An array of Result structs
function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) {
uint256 length = calls.length;
returnData = new Result[](length);
Call3 calldata calli;
for (uint256 i = 0; i < length; ) {
Result memory result = returnData[i];
calli = calls[i];
(result.success, result.returnData) = calli.target.call(calli.callData);
assembly {
// Revert if the call fails and failure is not allowed
// `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`
if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {
// set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)")))
mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)
// set data offset
mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)
// set length of revert string
mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)
// set revert string: bytes32(abi.encodePacked("Multicall3: call failed"))
mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)
revert(0x00, 0x64)
}
}
unchecked {
++i;
}
}
}

/// @notice Aggregate calls with a msg value
/// @notice Reverts if msg.value is less than the sum of the call values
/// @param calls An array of Call3Value structs
/// @return returnData An array of Result structs
function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) {
uint256 valAccumulator;
uint256 length = calls.length;
returnData = new Result[](length);
Call3Value calldata calli;
for (uint256 i = 0; i < length; ) {
Result memory result = returnData[i];
calli = calls[i];
uint256 val = calli.value;
// Humanity will be a Type V Kardashev Civilization before this overflows - andreas
// ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256
unchecked {
valAccumulator += val;
}
(result.success, result.returnData) = calli.target.call{value: val}(calli.callData);
assembly {
// Revert if the call fails and failure is not allowed
// `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`
if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {
// set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)")))
mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)
// set data offset
mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)
// set length of revert string
mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)
// set revert string: bytes32(abi.encodePacked("Multicall3: call failed"))
mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)
revert(0x00, 0x84)
}
}
unchecked {
++i;
}
}
// Finally, make sure the msg.value = SUM(call[0...i].value)
require(msg.value == valAccumulator, "Multicall3: value mismatch");
}

/// @notice Returns the block hash for the given block number
/// @param blockNumber The block number
function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {
blockHash = blockhash(blockNumber);
}

/// @notice Returns the block number
function getBlockNumber() public view returns (uint256 blockNumber) {
blockNumber = block.number;
}

/// @notice Returns the block coinbase
function getCurrentBlockCoinbase() public view returns (address coinbase) {
coinbase = block.coinbase;
}

/// @notice Returns the block difficulty
function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {
difficulty = block.prevrandao;
}

/// @notice Returns the block gas limit
function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {
gaslimit = block.gaslimit;
}

/// @notice Returns the block timestamp
function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {
timestamp = block.timestamp;
}

/// @notice Returns the (ETH) balance of a given address
function getEthBalance(address addr) public view returns (uint256 balance) {
balance = addr.balance;
}

/// @notice Returns the block hash of the last block
function getLastBlockHash() public view returns (bytes32 blockHash) {
unchecked {
blockHash = blockhash(block.number - 1);
}
}

/// @notice Gets the base fee of the given block
/// @notice Can revert if the BASEFEE opcode is not implemented by the given chain
function getBasefee() public view returns (uint256 basefee) {
basefee = block.basefee;
}

/// @notice Returns the chain id
function getChainId() public view returns (uint256 chainid) {
chainid = block.chainid;
}
}

0 comments on commit de3f407

Please sign in to comment.