Skip to content

Commit

Permalink
Release new verifier and token bridge fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
julien-marchand committed Jul 30, 2023
1 parent f08c190 commit bb3691b
Show file tree
Hide file tree
Showing 58 changed files with 7,914 additions and 13,821 deletions.
10 changes: 8 additions & 2 deletions common.ts
Expand Up @@ -112,6 +112,12 @@ function getRollupJsonPath(): string {
}

export {
MAX_GAS_LIMIT, getBatchType, getBatchTypeFromFileName, getBlockchainNode, getContractOwnerPrivateKey, getL2BlockchainNode, getRollupContractConfigPath,
getRollupJsonPath
MAX_GAS_LIMIT,
getBatchType,
getBatchTypeFromFileName,
getBlockchainNode,
getContractOwnerPrivateKey,
getL2BlockchainNode,
getRollupContractConfigPath,
getRollupJsonPath,
};
64 changes: 41 additions & 23 deletions contracts/ZkEvmV2.sol
Expand Up @@ -96,12 +96,13 @@ contract ZkEvmV2 is IZkEvmV2, Initializable, AccessControlUpgradeable, L1Message
/**
* @notice Finalizes blocks without using a proof.
* @dev DEFAULT_ADMIN_ROLE is required to execute.
* @dev _blocksData[0].fromAddresses is a temporary workaround to pass bytes calldata
* @param _blocksData The full BlockData collection - block, transaction and log data.
**/
function finalizeBlocksWithoutProof(
BlockData[] calldata _blocksData
) external whenTypeNotPaused(GENERAL_PAUSE_TYPE) onlyRole(DEFAULT_ADMIN_ROLE) {
_finalizeBlocks(_blocksData, new bytes(0), 0, bytes32(0), false);
_finalizeBlocks(_blocksData, _blocksData[0].fromAddresses, 0, bytes32(0), false);
}

/**
Expand Down Expand Up @@ -141,17 +142,25 @@ contract ZkEvmV2 is IZkEvmV2, Initializable, AccessControlUpgradeable, L1Message
**/
function _finalizeBlocks(
BlockData[] calldata _blocksData,
bytes memory _proof,
bytes calldata _proof,
uint256 _proofType,
bytes32 _parentStateRootHash,
bool _shouldProve
) private {
uint256 currentBlockNumberTemp = currentL2BlockNumber;
uint256 firstBlockNumber = currentBlockNumberTemp + 1;

uint256 firstBlockNumber;
unchecked {
firstBlockNumber = currentBlockNumberTemp + 1;
}

uint256[] memory timestamps = new uint256[](_blocksData.length);
bytes32[] memory blockHashes = new bytes32[](_blocksData.length);
bytes32[] memory hashOfRootHashes = new bytes32[](_blocksData.length + 1);
bytes32[] memory hashOfRootHashes;

unchecked {
hashOfRootHashes = new bytes32[](_blocksData.length + 1);
}

hashOfRootHashes[0] = _parentStateRootHash;

Expand All @@ -168,7 +177,9 @@ contract ZkEvmV2 is IZkEvmV2, Initializable, AccessControlUpgradeable, L1Message
hashOfTxHashes = _processBlockTransactions(blockInfo.transactions, blockInfo.batchReceptionIndices);
hashOfMessageHashes = _processMessageHashes(blockInfo.l2ToL1MsgHashes);

++currentBlockNumberTemp;
unchecked {
++currentBlockNumberTemp;
}

blockHashes[i] = keccak256(
abi.encodePacked(
Expand All @@ -180,7 +191,10 @@ contract ZkEvmV2 is IZkEvmV2, Initializable, AccessControlUpgradeable, L1Message
);

timestamps[i] = blockInfo.l2BlockTimestamp;
hashOfRootHashes[i + 1] = blockInfo.blockRootHash;

unchecked {
hashOfRootHashes[i + 1] = blockInfo.blockRootHash;
}

emit BlockFinalized(currentBlockNumberTemp, blockInfo.blockRootHash);

Expand All @@ -189,26 +203,30 @@ contract ZkEvmV2 is IZkEvmV2, Initializable, AccessControlUpgradeable, L1Message
}
}

stateRootHashes[currentBlockNumberTemp] = _blocksData[_blocksData.length - 1].blockRootHash;
currentTimestamp = _blocksData[_blocksData.length - 1].l2BlockTimestamp;
currentL2BlockNumber = currentBlockNumberTemp;
unchecked {
uint256 arrayIndex = _blocksData.length - 1;
stateRootHashes[currentBlockNumberTemp] = _blocksData[arrayIndex].blockRootHash;
currentTimestamp = _blocksData[arrayIndex].l2BlockTimestamp;
currentL2BlockNumber = currentBlockNumberTemp;
}

if (_shouldProve) {
_verifyProof(
uint256(
keccak256(
abi.encode(
keccak256(abi.encodePacked(blockHashes)),
firstBlockNumber,
keccak256(abi.encodePacked(timestamps)),
keccak256(abi.encodePacked(hashOfRootHashes))
)
uint256 publicInput = uint256(
keccak256(
abi.encode(
keccak256(abi.encodePacked(blockHashes)),
firstBlockNumber,
keccak256(abi.encodePacked(timestamps)),
keccak256(abi.encodePacked(hashOfRootHashes))
)
) % MODULO_R,
_proofType,
_proof,
_parentStateRootHash
)
);

assembly {
publicInput := mod(publicInput, MODULO_R)
}

_verifyProof(publicInput, _proofType, _proof, _parentStateRootHash);
}
}

Expand Down Expand Up @@ -275,7 +293,7 @@ contract ZkEvmV2 is IZkEvmV2, Initializable, AccessControlUpgradeable, L1Message
function _verifyProof(
uint256 _publicInputHash,
uint256 _proofType,
bytes memory _proof,
bytes calldata _proof,
bytes32 _parentStateRootHash
) private {
uint256[] memory input = new uint256[](1);
Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/IPlonkVerifier.sol
Expand Up @@ -11,5 +11,5 @@ interface IPlonkVerifier {
* @param _proof The proof used to verify.
* @param _public_inputs The computed public inputs for the proof verification.
*/
function Verify(bytes memory _proof, uint256[] memory _public_inputs) external returns (bool);
function Verify(bytes calldata _proof, uint256[] calldata _public_inputs) external returns (bool);
}
6 changes: 5 additions & 1 deletion contracts/messageService/l1/L1MessageManager.sol
Expand Up @@ -26,7 +26,11 @@ abstract contract L1MessageManager is IL1MessageManager {
mapping(bytes32 => uint256) public inboxL2L1MessageStatus;

/// @dev Keep free storage slots for future implementation updates to avoid storage collision.
uint256[50] private __gap;
// *******************************************************************************************
// NB: THIS GAP HAS BEEN PUSHED OUT IN FAVOUR OF THE GAP INSIDE THE REENTRANCY CODE
//uint256[50] private __gap;
// NB: DO NOT USE THIS GAP
// *******************************************************************************************

/**
* @notice Add a cross-chain L2->L1 message hash in storage.
Expand Down
12 changes: 8 additions & 4 deletions contracts/messageService/l1/L1MessageService.sol
Expand Up @@ -2,6 +2,8 @@
pragma solidity ^0.8.19;

import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";

import { IMessageService } from "../../interfaces/IMessageService.sol";
import { IGenericErrors } from "../../interfaces/IGenericErrors.sol";
import { PauseManager } from "../lib/PauseManager.sol";
Expand All @@ -16,6 +18,7 @@ abstract contract L1MessageService is
Initializable,
RateLimiter,
L1MessageManager,
ReentrancyGuardUpgradeable,
PauseManager,
IMessageService,
IGenericErrors
Expand All @@ -29,7 +32,7 @@ abstract contract L1MessageService is
uint256[50] private __gap;

// @dev adding these should not affect storage as they are constants and are store in bytecode
uint256 private constant REFUND_OVERHEAD_IN_GAS = 40000;
uint256 private constant REFUND_OVERHEAD_IN_GAS = 42000;

/**
* @notice Initialises underlying message service dependencies.
Expand Down Expand Up @@ -120,7 +123,7 @@ abstract contract L1MessageService is
address payable _feeRecipient,
bytes calldata _calldata,
uint256 _nonce
) external distributeFees(_fee, _to, _calldata, _feeRecipient) {
) external nonReentrant distributeFees(_fee, _to, _calldata, _feeRecipient) {
_requireTypeNotPaused(L2_L1_PAUSE_TYPE);
_requireTypeNotPaused(GENERAL_PAUSE_TYPE);

Expand Down Expand Up @@ -199,15 +202,16 @@ abstract contract L1MessageService is
deliveryFee = (startingGas + REFUND_OVERHEAD_IN_GAS - gasleft()) * tx.gasprice;

if (_feeInWei > deliveryFee) {
_to.call{ value: (_feeInWei - deliveryFee) }("");
payable(_to).send(_feeInWei - deliveryFee);
} else {
deliveryFee = _feeInWei;
}
}
}

address feeReceiver = _feeRecipient == address(0) ? msg.sender : _feeRecipient;
(bool callSuccess, ) = feeReceiver.call{ value: deliveryFee }("");

bool callSuccess = payable(feeReceiver).send(deliveryFee);
if (!callSuccess) {
revert FeePaymentFailed(feeReceiver);
}
Expand Down
6 changes: 5 additions & 1 deletion contracts/messageService/l2/L2MessageManager.sol
Expand Up @@ -25,7 +25,11 @@ abstract contract L2MessageManager is Initializable, PauseManager, IL2MessageMan
mapping(bytes32 => uint256) public inboxL1L2MessageStatus;

/// @dev Keep free storage slots for future implementation updates to avoid storage collision.
uint256[50] private __gap;
// *******************************************************************************************
// NB: THIS GAP HAS BEEN PUSHED OUT IN FAVOUR OF THE GAP INSIDE THE REENTRANCY CODE
//uint256[50] private __gap;
// NB: DO NOT USE THIS GAP
// *******************************************************************************************

/**
* @notice Initialises L2 message manager contract.
Expand Down
19 changes: 14 additions & 5 deletions contracts/messageService/l2/L2MessageService.sol
Expand Up @@ -2,6 +2,7 @@
pragma solidity ^0.8.19;

import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import { CodecV2 } from "../lib/Codec.sol";
import { IMessageService } from "../../interfaces/IMessageService.sol";
import { IGenericErrors } from "../../interfaces/IGenericErrors.sol";
Expand All @@ -12,7 +13,14 @@ import { L2MessageManager } from "./L2MessageManager.sol";
* @title Contract to manage cross-chain messaging on L2.
* @author ConsenSys Software Inc.
*/
contract L2MessageService is Initializable, RateLimiter, L2MessageManager, IMessageService, IGenericErrors {
contract L2MessageService is
Initializable,
RateLimiter,
L2MessageManager,
ReentrancyGuardUpgradeable,
IMessageService,
IGenericErrors
{
// Keep free storage slots for future implementation updates to avoid storage collision.
uint256[50] private __gap_L2MessageService;

Expand All @@ -27,7 +35,7 @@ contract L2MessageService is Initializable, RateLimiter, L2MessageManager, IMess
uint256 public minimumFeeInWei;

// @dev adding these should not affect storage as they are constants and are store in bytecode
uint256 private constant REFUND_OVERHEAD_IN_GAS = 45000;
uint256 private constant REFUND_OVERHEAD_IN_GAS = 47500;

/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
Expand Down Expand Up @@ -140,7 +148,7 @@ contract L2MessageService is Initializable, RateLimiter, L2MessageManager, IMess
address payable _feeRecipient,
bytes calldata _calldata,
uint256 _nonce
) external distributeFees(_fee, _to, _calldata, _feeRecipient) {
) external nonReentrant distributeFees(_fee, _to, _calldata, _feeRecipient) {
_requireTypeNotPaused(L1_L2_PAUSE_TYPE);
_requireTypeNotPaused(GENERAL_PAUSE_TYPE);

Expand Down Expand Up @@ -224,15 +232,16 @@ contract L2MessageService is Initializable, RateLimiter, L2MessageManager, IMess
deliveryFee = (startingGas + REFUND_OVERHEAD_IN_GAS - gasleft()) * tx.gasprice;

if (_feeInWei > deliveryFee) {
_to.call{ value: (_feeInWei - deliveryFee) }("");
payable(_to).send(_feeInWei - deliveryFee);
} else {
deliveryFee = _feeInWei;
}
}
}

address feeReceiver = _feeRecipient == address(0) ? msg.sender : _feeRecipient;
(bool callSuccess, ) = feeReceiver.call{ value: deliveryFee }("");

bool callSuccess = payable(feeReceiver).send(deliveryFee);
if (!callSuccess) {
revert FeePaymentFailed(feeReceiver);
}
Expand Down
4 changes: 2 additions & 2 deletions contracts/tokenBridge/BridgedToken.sol
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.19;
pragma solidity 0.8.19;

import { ERC20PermitUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol";

Expand Down Expand Up @@ -28,7 +28,7 @@ contract BridgedToken is ERC20PermitUpgradeable {

function initialize(string memory _tokenName, string memory _tokenSymbol, uint8 _tokenDecimals) external initializer {
__ERC20_init(_tokenName, _tokenSymbol);
__EIP712_init(_tokenName, "1");
__ERC20Permit_init(_tokenName);
bridge = msg.sender;
_decimals = _tokenDecimals;
}
Expand Down

0 comments on commit bb3691b

Please sign in to comment.