Skip to content

Commit

Permalink
merge from Bence's commits
Browse files Browse the repository at this point in the history
  • Loading branch information
kelemeno committed Jan 15, 2024
1 parent dd13aa7 commit 8d2fb4b
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 38 deletions.
65 changes: 42 additions & 23 deletions l1-contracts/contracts/bridge/L1ERC20Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol

import {IL1BridgeDeprecated} from "./interfaces/IL1BridgeDeprecated.sol";
import {IL1BridgeLegacy} from "./interfaces/IL1BridgeLegacy.sol";
import {IL1Bridge} from "./interfaces/IL1Bridge.sol";
import {IL1Bridge, ConfirmL2TxStatus} from "./interfaces/IL1Bridge.sol";
import {IL2Bridge} from "./interfaces/IL2Bridge.sol";
import {IL2ERC20Bridge} from "./interfaces/IL2ERC20Bridge.sol";
import {ConfirmL2TxStatus} from "./interfaces/IL1Bridge.sol";
Expand Down Expand Up @@ -48,7 +48,7 @@ contract L1ERC20Bridge is
/// @dev Used to indicate that L2 -> L1 message was already processed
/// @dev this is just used for ERA for backwards compatibility reasons
mapping(uint256 l2BatchNumber => mapping(uint256 l2ToL1MessageNumber => bool isFinalized))
public isWithdrawalFinalizedEra;
internal isWithdrawalFinalizedEra;

/// @dev A mapping account => L1 token address => L2 deposit transaction hash => amount
/// @dev Used for saving the number of deposited funds, to claim them in case the deposit transaction will fail
Expand Down Expand Up @@ -94,7 +94,7 @@ contract L1ERC20Bridge is

/// @dev A mapping chainId => keccak256(account, tokenAddress, amount) => L2 deposit transaction hash => true
/// @dev Used for saving the number of deposited funds, to claim them in case the deposit transaction will fail
mapping(uint256 => mapping(bytes32 => mapping(bytes32 => bool))) internal deposited;
mapping(uint256 => mapping(bytes32 => mapping(bytes32 => bool))) internal depositHappened;

/// @dev used for extra security until hyperbridging is implemented.
mapping(uint256 => mapping(address => uint256)) public chainBalance;
Expand Down Expand Up @@ -227,16 +227,16 @@ contract L1ERC20Bridge is
// Prepare the proxy constructor data
bytes memory l2BridgeProxyConstructorData;
{
address proxyAdmin = readProxyAdmin();
address l2ProxyAdmin = AddressAliasHelper.applyL1ToL2Alias(proxyAdmin);
address owner = owner();
address l2Owner = AddressAliasHelper.applyL1ToL2Alias(owner);
// Data to be used in delegate call to initialize the proxy
bytes memory proxyInitializationParams = abi.encodeCall(
IL2ERC20Bridge.initialize,
(address(this), l2TokenProxyBytecodeHash, l2ProxyAdmin)
(address(this), l2TokenProxyBytecodeHash, owner)
);
l2BridgeProxyConstructorData = abi.encode(
bridgeImplementationAddr,
l2ProxyAdmin,
owner,
proxyInitializationParams
);
}
Expand Down Expand Up @@ -284,6 +284,8 @@ contract L1ERC20Bridge is
),
"L1EB: bridge impl tx not conf" // not confirmed
);
delete bridgeImplDeployOnL2TxHash[_chainId];

require(
bridgehub.proveL1ToL2TransactionStatus(
_chainId,
Expand All @@ -296,7 +298,6 @@ contract L1ERC20Bridge is
),
"L1EB: bridge proxy tx not conf" // not confirmed
);
delete bridgeImplDeployOnL2TxHash[_chainId];
delete bridgeProxyDeployOnL2TxHash[_chainId];
if (_bridgeProxyTxStatus.succeeded) {
l2BridgeAddress[_chainId] = l2BridgeStandardAddress;
Expand Down Expand Up @@ -436,7 +437,7 @@ contract L1ERC20Bridge is

// Save the deposited amount to claim funds on L1 if the deposit failed on L2
bytes32 txDataHash = keccak256(abi.encode(msg.sender, _l1Token, _amount));
deposited[_chainId][txDataHash][l2TxHash] = true;
depositHappened[_chainId][txDataHash][l2TxHash] = true;

emit DepositInitiatedSharedBridge(_chainId, txDataHash, msg.sender, _l2Receiver, _l1Token, _amount);
if (_chainId == ERA_CHAIN_ID) {
Expand Down Expand Up @@ -554,8 +555,8 @@ contract L1ERC20Bridge is
bytes32 _txDataHash,
bytes32 _txHash
) external override onlyBridgehub {
require(!deposited[_chainId][_txDataHash][_txHash], "L1EB: tx already happened");
deposited[_chainId][_txDataHash][_txHash] = true;
require(!depositHappened[_chainId][_txDataHash][_txHash], "L1EB: tx already happened");
depositHappened[_chainId][_txDataHash][_txHash] = true;
emit BridgehubDepositFinalized(_chainId, _txDataHash, _txHash);
}

Expand Down Expand Up @@ -631,6 +632,7 @@ contract L1ERC20Bridge is
uint16 _l2TxNumberInBatch,
bytes32[] calldata _merkleProof
) public nonReentrant {

{
bool proofValid = bridgehub.proveL1ToL2TransactionStatus(
_chainId,
Expand All @@ -642,24 +644,16 @@ contract L1ERC20Bridge is
TxStatus.Failure
);
require(proofValid, "yn");
require(_amount > 0, "y1");
}

bytes32 txDataHash = keccak256(abi.encode(msg.sender, _l1Token, _amount));
bool usingLegacyDepositAmountStorageVar = _checkDeposited(_chainId, _depositSender, _l1Token, txDataHash, _l2TxHash, _amount);

if (_chainId == ERA_CHAIN_ID) {
uint256 amount = 0;
amount = depositAmountEra[_depositSender][_l1Token][_l2TxHash];
require(_amount == amount, "L1EB: amount mismatch");
} else {
bool depositHappened = deposited[_chainId][txDataHash][_l2TxHash];
require(depositHappened, "L1EB: deposit did not happen");
}
require(_amount > 0, "y1");

if (_chainId == ERA_CHAIN_ID) {
if ((_chainId == ERA_CHAIN_ID) && usingLegacyDepositAmountStorageVar) {
delete depositAmountEra[_depositSender][_l1Token][_l2TxHash];
} else {
delete deposited[_chainId][txDataHash][_l2TxHash];
delete depositHappened[_chainId][txDataHash][_l2TxHash];
}
if (!hyperbridgingEnabled[_chainId]) {
// check that the chain has sufficient balance
Expand All @@ -675,6 +669,31 @@ contract L1ERC20Bridge is
}
}

function _checkDeposited(
uint256 _chainId,
address _depositSender,
address _l1Token,
bytes32 _txDataHash,
bytes32 _l2TxHash,
uint256 _amount
) internal returns (bool usingLegacyDepositAmountStorageVar) {
uint256 amount = 0;
if (_chainId == ERA_CHAIN_ID) {
{ amount = depositAmountEra[_depositSender][_l1Token][_l2TxHash];}
if (amount > 0){
usingLegacyDepositAmountStorageVar = true;
require(_amount == amount, "L1EB: amount mismatch");
} else {
bool deposited;
{deposited = depositHappened[_chainId][_txDataHash][_l2TxHash];}
require(deposited, "L1EB: deposit did not happen");
}
} else {
bool deposited = depositHappened[_chainId][_txDataHash][_l2TxHash];
require(deposited, "L1EB: deposit did not happen");
}
}

/// @notice Finalize the withdrawal and release funds
/// @param _l2BatchNumber The L2 batch number where the withdrawal was processed
/// @param _l2MessageIndex The position in the L2 logs Merkle tree of the l2Log that was sent with the message
Expand Down
14 changes: 7 additions & 7 deletions l1-contracts/contracts/bridge/L1WethBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pragma solidity 0.8.20;
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import {IL1Bridge} from "./interfaces/IL1Bridge.sol";
import {IL1Bridge, ConfirmL2TxStatus} from "./interfaces/IL1Bridge.sol";
import {IL2WethBridge} from "./interfaces/IL2WethBridge.sol";
import {IL2Bridge} from "./interfaces/IL2Bridge.sol";
import {IWETH9} from "./interfaces/IWETH9.sol";
Expand Down Expand Up @@ -86,7 +86,7 @@ contract L1WethBridge is IL1Bridge, ReentrancyGuard, Initializable, Ownable2Step
/// @dev A mapping chainId => keccak256(account, amount) => L2 deposit transaction hash => amount
/// @dev Used for saving the number of deposited funds, to claim them in case the deposit transaction will fail
/// @dev only used when it is not the base token, as then it is sent to refund recipient
mapping(uint256 => mapping(bytes32 => mapping(bytes32 => bool))) internal deposited;
mapping(uint256 => mapping(bytes32 => mapping(bytes32 => bool))) internal depositHappened;

/// @dev A mapping L2 chainId => Batch number => message number => flag
/// @dev Used to indicate that L2 -> L1 WETH message was already processed
Expand Down Expand Up @@ -483,8 +483,8 @@ contract L1WethBridge is IL1Bridge, ReentrancyGuard, Initializable, Ownable2Step
bytes32 _txDataHash,
bytes32 _txHash
) external override onlyBridgehub {
require(!deposited[_chainId][_txDataHash][_txHash], "L1WETHBridge: tx already happened");
deposited[_chainId][_txDataHash][_txHash] = true;
require(!depositHappened[_chainId][_txDataHash][_txHash], "L1WETHBridge: tx already happened");
depositHappened[_chainId][_txDataHash][_txHash] = true;
emit BridgehubDepositFinalized(_chainId, _txDataHash, _txHash);
}

Expand Down Expand Up @@ -526,13 +526,13 @@ contract L1WethBridge is IL1Bridge, ReentrancyGuard, Initializable, Ownable2Step
);
require(proofValid, "L1WB: Invalid L2 transaction status proof");

bool depositHappened = deposited[_chainId][keccak256(abi.encode(_depositSender, _amount))][_l2TxHash];
require(((_amount > 0) && (depositHappened)), "L1WB: _amount is zero or deposit did not happen");
bool deposited = depositHappened[_chainId][keccak256(abi.encode(_depositSender, _amount))][_l2TxHash];
require(((_amount > 0) && (deposited)), "L1WB: _amount is zero or deposit did not happen");
if (!hyperbridgingEnabled[_chainId]) {
require(chainBalance[_chainId] >= _amount, "L1WB: chainBalance is too low");
chainBalance[_chainId] -= _amount;
}
delete deposited[_chainId][keccak256(abi.encode(_depositSender, _amount))][_l2TxHash];
delete depositHappened[_chainId][keccak256(abi.encode(_depositSender, _amount))][_l2TxHash];

// Withdraw funds
// Wrap ETH to WETH tokens (smart contract address receives the equivalent _amount of WETH)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ pragma solidity 0.8.20;

/// @author Matter Labs
interface IL2ERC20Bridge {
function initialize(address _l1Bridge, bytes32 _l2TokenProxyBytecodeHash, address _proxyAdmin) external;
function initialize(address _l1Bridge, bytes32 _l2TokenProxyBytecodeHash, address _aliasedOwner) external;
}
2 changes: 1 addition & 1 deletion l1-contracts/contracts/bridge/interfaces/IL2WethBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
pragma solidity 0.8.20;

interface IL2WethBridge {
function initialize(address _l1Bridge, address _l1WethAddress, address _proxyAdmin, bool _ethIsBaseToken) external;
function initialize(address _l1Bridge, address _l1WethAddress, address _aliasedOwner, bool _ethIsBaseToken) external;
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,6 @@ interface IStateTransitionManager {
) external;

function setUpgradeDiamondCut(Diamond.DiamondCutData calldata _cutData, uint256 _oldProtocolVersion) external;

function freezeChain(uint256 _chainId) external;
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own
upgradeCutHash[_oldProtocolVersion] = keccak256(abi.encode(_cutData));
}

/// @dev freezes the specified chain
function freezeChain(uint256 _chainId) external onlyOwner {
IZkSyncStateTransition(stateTransition[_chainId]).freezeDiamond();
}

/// registration

/// @dev we have to set the chainId at genesis, as blockhashzero is the same for all chains with the same chainId
Expand Down
8 changes: 4 additions & 4 deletions l2-contracts/contracts/bridge/L2ERC20Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,22 @@ contract L2ERC20Bridge is IL2Bridge, Initializable {
/// @notice Initializes the bridge contract for later use. Expected to be used in the proxy.
/// @param _l1Bridge The address of the L1 Bridge contract.
/// @param _l2TokenProxyBytecodeHash The bytecode hash of the proxy for tokens deployed by the bridge.
/// @param _proxyAdmin The address of the governor contract.
/// @param _aliasedOwner The address of the governor contract.
function initialize(
address _l1Bridge,
bytes32 _l2TokenProxyBytecodeHash,
address _proxyAdmin
address _aliasedOwner
) external initializer {
require(_l1Bridge != address(0), "bf");
require(_l2TokenProxyBytecodeHash != bytes32(0), "df");
require(_proxyAdmin != address(0), "sf");
require(_aliasedOwner != address(0), "sf");

l1Bridge = _l1Bridge;

l2TokenProxyBytecodeHash = _l2TokenProxyBytecodeHash;
address l2StandardToken = address(new L2StandardERC20{salt: bytes32(0)}());
l2TokenBeacon = new UpgradeableBeacon{salt: bytes32(0)}(l2StandardToken);
l2TokenBeacon.transferOwnership(_proxyAdmin);
l2TokenBeacon.transferOwnership(_aliasedOwner);
}

/// @notice Finalize the deposit and mint funds
Expand Down
4 changes: 2 additions & 2 deletions l2-contracts/contracts/bridge/L2WethBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ contract L2WethBridge is IL2Bridge, Initializable {
function initialize(
address _l1Bridge,
address _l1WethAddress,
address _proxyAdmin,
address _aliasedOwner,
bool _isEthBaseToken
) external initializer {
require(_l1Bridge != address(0), "L1 WETH bridge address cannot be zero");
Expand All @@ -63,7 +63,7 @@ contract L2WethBridge is IL2Bridge, Initializable {
bytes memory initData = abi.encodeWithSelector(L2Weth.initialize.selector, "Wrapped Ether", "WETH");
TransparentUpgradeableProxy l2Weth = new TransparentUpgradeableProxy{salt: bytes32(0)}(
l2WethImplementation,
_proxyAdmin,
_aliasedOwner,
initData
);
L2Weth(payable(address(l2Weth))).initializeV2(address(this), l1WethAddress, _isEthBaseToken);
Expand Down

0 comments on commit 8d2fb4b

Please sign in to comment.