From 93a52175245ee740c7101595503a668f3f28b20c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Paradelo?= Date: Fri, 17 Oct 2025 18:48:33 -0300 Subject: [PATCH 01/14] Revert "feat(l2): custom native token (#4622)" This reverts commit f6ccc00c8ea3eb5ac955b206e8f994429ca58580. --- .github/workflows/pr-main_l2.yaml | 60 +--- cmd/ethrex/l2/deployer.rs | 114 +------ crates/l2/contracts/src/l1/CommonBridge.sol | 139 ++------- .../src/l1/interfaces/ICommonBridge.sol | 10 +- crates/l2/contracts/src/l2/CommonBridgeL2.sol | 11 +- crates/l2/docker-compose.yaml | 1 - crates/l2/tests/tests.rs | 290 ++++-------------- docs/l2/fundamentals/contracts.md | 2 +- docs/l2/fundamentals/native_tokens.md | 21 -- fixtures/contracts/ERC20/NativeTokenTest.bin | 1 - 10 files changed, 111 insertions(+), 538 deletions(-) delete mode 100644 docs/l2/fundamentals/native_tokens.md delete mode 100644 fixtures/contracts/ERC20/NativeTokenTest.bin diff --git a/.github/workflows/pr-main_l2.yaml b/.github/workflows/pr-main_l2.yaml index 08b9e7eb51c..c1875f00548 100644 --- a/.github/workflows/pr-main_l2.yaml +++ b/.github/workflows/pr-main_l2.yaml @@ -123,34 +123,16 @@ jobs: - name: "Validium" validium: true web3signer: false - use_native_token: false - based: false compose_targets: [docker-compose.yaml] - name: "Vanilla" validium: false web3signer: false - use_native_token: false - based: false compose_targets: [docker-compose.yaml] - name: "Vanilla with Web3signer" validium: false web3signer: true - use_native_token: false - based: false compose_targets: [docker-compose.yaml, docker-compose-l2-web3signer.yaml] - - name: "ERC20 as Native Token" - validium: false - web3signer: false - use_native_token: true - based: false - compose_targets: [docker-compose.yaml] - - name: "Based" - validium: false - web3signer: false - use_native_token: false - based: true - compose_targets: [docker-compose.yaml] steps: - name: Checkout sources uses: actions/checkout@v4 @@ -190,37 +172,7 @@ jobs: run: | docker load --input /tmp/ethrex_image.tar - - name: Download ethrex L2 image artifact - uses: actions/download-artifact@v4 - with: - name: ethrex_image_l2 - path: /tmp - - - name: Load ethrex L2 image - run: | - docker load --input /tmp/ethrex_image_l2.tar - - - name: Start L1 - run: | - cd crates/l2 - docker compose up --detach ethrex_l1 - - - name: Install rex - if: ${{ matrix.use_native_token || matrix.based }} - run: | - cd .. - git clone https://github.com/lambdaclass/rex.git - cd rex - git checkout 18466ec1c3dbcbbf22a68fc1f850d660cb2fbf1f - make cli - echo "rex install successfully at $(which rex)" - - - name: Deploy native token - if: matrix.use_native_token - run: | - rex deploy $(cat fixtures/contracts/ERC20/NativeTokenTest.bin) 0 0xbcdf20249abf0ed6d944c0288fad489e33f66b3960d9e6229c1cd214ed3bbe31 - - - name: Deploy contracts + - name: Start L1 & Deploy contracts run: | # # If this job fails due to connection refused to ethrex_l1 consider increasing the failure retries @@ -228,22 +180,12 @@ jobs: # touch cmd/.env cd crates/l2 - if [ "${{ matrix.use_native_token }}" = true ]; then - export ETHREX_NATIVE_TOKEN_L1_ADDRESS=0xb4b46bdaa835f8e4b4d8e208b6559cd267851051 - else - export ETHREX_NATIVE_TOKEN_L1_ADDRESS=0x0000000000000000000000000000000000000000 - fi - if [ "${{ matrix.based }}" = true ]; then - export ETHREX_DEPLOYER_DEPLOY_BASED_CONTRACTS=true - export COMPILE_CONTRACTS=true - fi DOCKER_ETHREX_WORKDIR=/usr/local/bin \ ETHREX_DEPLOYER_DEPLOY_RICH=true \ ETHREX_DEPLOYER_PICO_CONTRACT_ADDRESS=0x00000000000000000000000000000000000000aa \ ETHREX_DEPLOYER_SP1_CONTRACT_ADDRESS=0x00000000000000000000000000000000000000aa \ ETHREX_DEPLOYER_RISC0_CONTRACT_ADDRESS=0x00000000000000000000000000000000000000aa \ ETHREX_L2_VALIDIUM=${{ matrix.validium }} \ - ETHREX_NATIVE_TOKEN_L1_ADDRESS=$ETHREX_NATIVE_TOKEN_L1_ADDRESS \ docker compose up contract_deployer DEPLOYER_EXIT_CODE=$(docker inspect -f '{{.State.ExitCode}}' contract_deployer) diff --git a/cmd/ethrex/l2/deployer.rs b/cmd/ethrex/l2/deployer.rs index ffb86e50717..9e8d75f26ae 100644 --- a/cmd/ethrex/l2/deployer.rs +++ b/cmd/ethrex/l2/deployer.rs @@ -324,15 +324,6 @@ pub struct DeployerOptions { help = "Genesis data is extracted at compile time, used for development" )] pub use_compiled_genesis: bool, - #[arg( - long, - value_name = "ADDRESS", - default_value = "0x0000000000000000000000000000000000000000", - env = "ETHREX_NATIVE_TOKEN_L1_ADDRESS", - help_heading = "Deployer options", - help = "The L1 address of the L2 native token (e.g., USDC, USDT, DAI, etc. Use address(0) for ETH)" - )] - pub native_token_l1_address: Address, } impl Default for DeployerOptions { @@ -415,7 +406,6 @@ impl Default for DeployerOptions { sequencer_registry_owner: None, inclusion_max_wait: 3000, use_compiled_genesis: true, - native_token_l1_address: H160::zero(), } } } @@ -500,15 +490,9 @@ const INITIALIZE_ON_CHAIN_PROPOSER_SIGNATURE: &str = "initialize(bool,address,ad const INITIALIZE_BRIDGE_ADDRESS_SIGNATURE: &str = "initializeBridgeAddress(address)"; const TRANSFER_OWNERSHIP_SIGNATURE: &str = "transferOwnership(address)"; const ACCEPT_OWNERSHIP_SIGNATURE: &str = "acceptOwnership()"; -const BRIDGE_INITIALIZER_SIGNATURE: &str = "initialize(address,address,uint256,address)"; +const BRIDGE_INITIALIZER_SIGNATURE: &str = "initialize(address,address,uint256)"; -// deposit(uint256 _amount, address _l2Recipient) -const NATIVE_TOKEN_DEPOSIT_SIGNATURE: &str = "deposit(uint256,address)"; - -// approve(address spender, uint256 amount) -const APPROVE_SIGNATURE: &str = "approve(address,uint256)"; - -#[derive(Clone, Copy, Default)] +#[derive(Clone, Copy)] pub struct ContractAddresses { pub on_chain_proposer_address: Address, pub bridge_address: Address, @@ -540,12 +524,6 @@ pub async fn deploy_l1_contracts( initialize_contracts(contract_addresses, ð_client, &opts, &signer).await?; if opts.deposit_rich { - if opts.native_token_l1_address != Address::zero() { - info!( - "Begging deposits with {} ERC20 as the native tokens", - opts.native_token_l1_address - ); - } let _ = make_deposits(contract_addresses.bridge_address, ð_client, &opts) .await .inspect_err(|err| { @@ -553,11 +531,7 @@ pub async fn deploy_l1_contracts( }); } - write_contract_addresses_to_env( - contract_addresses, - opts.native_token_l1_address, - opts.env_file_path, - )?; + write_contract_addresses_to_env(contract_addresses, opts.env_file_path)?; info!("Deployer binary finished successfully"); Ok(contract_addresses) } @@ -935,7 +909,6 @@ async fn initialize_contracts( Value::Address(opts.bridge_owner), Value::Address(contract_addresses.on_chain_proposer_address), Value::Uint(opts.inclusion_max_wait.into()), - Value::Address(opts.native_token_l1_address), ]; let bridge_initialization_calldata = encode_calldata(BRIDGE_INITIALIZER_SIGNATURE, &calldata_values)?; @@ -1004,84 +977,13 @@ async fn make_deposits( let get_balance = eth_client .get_balance(signer.address(), BlockIdentifier::Tag(BlockTag::Latest)) .await?; - let value_to_deposit = get_balance .checked_div(U256::from_str("2").unwrap_or(U256::zero())) .unwrap_or(U256::zero()); - let native_token_is_eth = opts.native_token_l1_address == Address::zero(); - let nonce = eth_client - .get_nonce(signer.address(), BlockIdentifier::Tag(BlockTag::Latest)) - .await?; - - // approve the transfer in the L1 token contract if not ETH - if !native_token_is_eth { - let mint_tx = build_generic_tx( - eth_client, - TxType::EIP1559, - opts.native_token_l1_address, - signer.address(), - encode_calldata("freeMint()", &[])?.into(), - Default::default(), - ) - .await?; - if let Err(e) = send_generic_transaction(eth_client, mint_tx, &signer).await { - error!(address =? signer.address(), "Failed to mint {e}"); - continue; - } - - let calldata = encode_calldata( - APPROVE_SIGNATURE, - &[Value::Address(bridge), Value::Uint(value_to_deposit * 2)], - )?; - let approve_tx = build_generic_tx( - eth_client, - TxType::EIP1559, - opts.native_token_l1_address, - signer.address(), - calldata.into(), - Overrides { - from: Some(signer.address()), - // We set the nonce and gas limit manually to avoid the estimation step and having nonce issues. - // We do nonce + 1 because the mint transaction is sent just before. - nonce: Some(nonce + 1), - gas_limit: Some(1_000_000u64), - ..Default::default() - }, - ) - .await?; - if let Err(e) = send_generic_transaction(eth_client, approve_tx, &signer).await { - error!(address =? signer.address(), "Failed to approve {e}"); - continue; - } - } - - let calldata_values = vec![ - // uint256 _amount: amount of ERC20 to deposit - Value::Uint(if native_token_is_eth { - U256::zero() - } else { - value_to_deposit - }), - // address l2Recipient: the address on L2 to receive the funds - Value::Address(signer.address()), - ]; - - let native_token_deposit_calldata = - encode_calldata(NATIVE_TOKEN_DEPOSIT_SIGNATURE, &calldata_values)?; - let overrides = Overrides { - value: native_token_is_eth.then_some(value_to_deposit).or(None), + value: Some(value_to_deposit), from: Some(signer.address()), - // When doing the deposits for ERC20 as the native token, we previously did an approve and mint. - // So to make the deposits fast and not wait for the node to have the nonce updated, we set it manually. - // Also we set the gas limit manually to avoid the estimation step and having nonce issues. - nonce: if !native_token_is_eth { - Some(nonce + 2) - } else { - None - }, - gas_limit: Some(1_000_000u64), ..Overrides::default() }; @@ -1090,7 +992,7 @@ async fn make_deposits( TxType::EIP1559, bridge, signer.address(), - native_token_deposit_calldata.into(), + Bytes::new(), overrides, ) .await?; @@ -1116,7 +1018,6 @@ async fn make_deposits( fn write_contract_addresses_to_env( contract_addresses: ContractAddresses, - native_token_l1_address: Address, env_file_path: Option, ) -> Result<(), DeployerError> { trace!("Writing contract addresses to .env file"); @@ -1194,11 +1095,6 @@ fn write_contract_addresses_to_env( "ETHREX_DEPLOYER_SEQUENCER_REGISTRY_ADDRESS={:#x}", contract_addresses.sequencer_registry_address )?; - writeln!( - writer, - "ETHREX_NATIVE_TOKEN_L1_ADDRESS={:#x}", - native_token_l1_address - )?; trace!(?env_file_path, "Contract addresses written to .env"); Ok(()) } diff --git a/crates/l2/contracts/src/l1/CommonBridge.sol b/crates/l2/contracts/src/l1/CommonBridge.sol index 0026ebfeb9c..b6408b8c40f 100644 --- a/crates/l2/contracts/src/l1/CommonBridge.sol +++ b/crates/l2/contracts/src/l1/CommonBridge.sol @@ -62,16 +62,15 @@ contract CommonBridge is /// @notice How much of each L1 token was deposited to each L2 token. /// @dev Stored as L1 -> L2 -> amount /// @dev Prevents L2 tokens from faking their L1 address and stealing tokens - /// @dev The token can take the value {NATIVE_TOKEN_L2} to represent the token of the L2 + /// @dev The token can take the value {ETH_TOKEN} to represent ETH mapping(address => mapping(address => uint256)) public deposits; - /// @notice Token address used to represent the token of the L2 - address public constant NATIVE_TOKEN_L2 = + /// @notice Token address used to represent ETH + address public constant ETH_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; /// @notice Owner of the L2 system contract proxies - address public constant L2_PROXY_ADMIN = - 0x000000000000000000000000000000000000f000; + address public constant L2_PROXY_ADMIN = 0x000000000000000000000000000000000000f000; /// @notice Mapping of unclaimed withdrawals. A withdrawal is claimed if /// there is a non-zero value in the mapping for the message id @@ -87,11 +86,6 @@ contract CommonBridge is /// @notice Deadline for the sequencer to include the transaction. mapping(bytes32 => uint256) public privilegedTxDeadline; - /// @notice The L1 token address that is treated as the one to be bridged to the L2. - /// @dev If set to address(0), ETH is considered the native token. - /// Otherwise, this address is used for native token deposits and withdrawals. - address public NATIVE_TOKEN_L1; - modifier onlyOnChainProposer() { require( msg.sender == ON_CHAIN_PROPOSER, @@ -105,13 +99,10 @@ contract CommonBridge is /// @dev It sets the OnChainProposer address. /// @param owner the address of the owner who can perform upgrades. /// @param onChainProposer the address of the OnChainProposer contract. - /// @param inclusionMaxWait the maximum time the sequencer is allowed to take without processing a privileged transaction. - /// @param _nativeToken the address of the native token on L1, or address(0) if ETH is the native token. function initialize( address owner, address onChainProposer, - uint256 inclusionMaxWait, - address _nativeToken + uint256 inclusionMaxWait ) public initializer { require( onChainProposer != address(0), @@ -124,8 +115,6 @@ contract CommonBridge is PRIVILEGED_TX_MAX_WAIT_BEFORE_INCLUSION = inclusionMaxWait; - NATIVE_TOKEN_L1 = _nativeToken; - OwnableUpgradeable.__Ownable_init(owner); ReentrancyGuardUpgradeable.__ReentrancyGuard_init(); } @@ -145,6 +134,7 @@ contract CommonBridge is while (startingGas - gasleft() < amount) {} } + /// EIP-7702 delegated accounts have code beginning with this. bytes3 internal constant EIP7702_PREFIX = 0xef0100; /// Code size in bytes of an EIP-7702 delegated account @@ -152,8 +142,7 @@ contract CommonBridge is uint256 internal constant EIP7702_CODE_LENGTH = 23; /// This is intentionally different from the constant Optimism uses, but arbitrary. - uint256 internal constant ADDRESS_ALIASING = - uint256(uint160(0xEe110000000000000000000000000000000011Ff)); + uint256 internal constant ADDRESS_ALIASING = uint256(uint160(0xEe110000000000000000000000000000000011Ff)); /// @notice This implements address aliasing, inspired by [Optimism](https://docs.optimism.io/stack/differences#address-aliasing) /// @dev The purpose of this is to prevent L2 contracts from being impersonated by malicious L1 contracts at the same address @@ -170,8 +159,7 @@ contract CommonBridge is return msg.sender; } } - return - address(uint160(uint256(uint160(msg.sender)) + ADDRESS_ALIASING)); + return address(uint160(uint256(uint160(msg.sender)) + ADDRESS_ALIASING)); } function _sendToL2(address from, SendValues memory sendValues) private { @@ -206,72 +194,32 @@ contract CommonBridge is } /// @inheritdoc ICommonBridge - function sendToL2( - SendValues calldata sendValues - ) public override whenNotPaused { + function sendToL2(SendValues calldata sendValues) public override whenNotPaused { _sendToL2(_getSenderAlias(), sendValues); } /// @inheritdoc ICommonBridge - function deposit( - uint256 _amount, - address l2Recipient - ) public payable override whenNotPaused { - uint256 value; - - // Here we define value depending on whether the native token is ETH or an ERC20 - if (NATIVE_TOKEN_L1 == address(0)) { - require( - msg.value > 0, - "CommonBridge: the native token is ETH, msg.value must be greater than zero" - ); - - require( - _amount == 0, - "CommonBridge: the native token is ETH, _amount must be zero" - ); - - value = msg.value; - } else { - require( - msg.value == 0, - "CommonBridge: the native token is an ERC20, msg.value must be zero" - ); - - require( - _amount > 0, - "CommonBridge: the native token is an ERC20, _amount must be greater than zero" - ); - - value = _amount; - - // We lock the tokens in the bridge contract - IERC20(NATIVE_TOKEN_L1).transferFrom( - msg.sender, - address(this), - value - ); - } - - deposits[NATIVE_TOKEN_L2][NATIVE_TOKEN_L2] += value; + function deposit(address l2Recipient) public payable override whenNotPaused { + _deposit(l2Recipient); + } + function _deposit(address l2Recipient) private { + deposits[ETH_TOKEN][ETH_TOKEN] += msg.value; bytes memory callData = abi.encodeCall( ICommonBridgeL2.mintETH, (l2Recipient) ); - SendValues memory sendValues = SendValues({ to: L2_BRIDGE_ADDRESS, gasLimit: 21000 * 5, - value: value, + value: msg.value, data: callData }); - _sendToL2(L2_BRIDGE_ADDRESS, sendValues); } receive() external payable whenNotPaused { - deposit(0, msg.sender); + _deposit(msg.sender); } function depositERC20( @@ -281,10 +229,6 @@ contract CommonBridge is uint256 amount ) external whenNotPaused { require(amount > 0, "CommonBridge: amount to deposit is zero"); - require( - tokenL1 != NATIVE_TOKEN_L1, - "CommonBridge: tokenL1 is the native token address, use deposit() instead" - ); deposits[tokenL1][tokenL2] += amount; IERC20(tokenL1).safeTransferFrom(msg.sender, address(this), amount); @@ -381,23 +325,15 @@ contract CommonBridge is bytes32[] calldata withdrawalProof ) public override whenNotPaused { _claimWithdrawal( - NATIVE_TOKEN_L2, - NATIVE_TOKEN_L2, + ETH_TOKEN, + ETH_TOKEN, claimedAmount, withdrawalBatchNumber, withdrawalMessageId, withdrawalProof ); - - if (NATIVE_TOKEN_L1 == address(0)) { - (bool success, ) = payable(msg.sender).call{value: claimedAmount}( - "" - ); - - require(success, "CommonBridge: failed to send the claimed amount"); - } else { - IERC20(NATIVE_TOKEN_L1).safeTransfer(msg.sender, claimedAmount); - } + (bool success, ) = payable(msg.sender).call{value: claimedAmount}(""); + require(success, "CommonBridge: failed to send the claimed amount"); } /// @inheritdoc ICommonBridge @@ -408,17 +344,7 @@ contract CommonBridge is uint256 withdrawalBatchNumber, uint256 withdrawalMessageId, bytes32[] calldata withdrawalProof - ) public override nonReentrant whenNotPaused { - require( - tokenL1 != NATIVE_TOKEN_L2, - "CommonBridge: attempted to withdraw ETH as if it were ERC20, use claimWithdrawal()" - ); - - require( - tokenL1 != NATIVE_TOKEN_L1, - "CommonBridge: attempted to withdraw the native token as if it were ERC20, use claimWithdrawal() instead" - ); - + ) public nonReentrant override whenNotPaused { _claimWithdrawal( tokenL1, tokenL2, @@ -427,7 +353,10 @@ contract CommonBridge is withdrawalMessageId, withdrawalProof ); - + require( + tokenL1 != ETH_TOKEN, + "CommonBridge: attempted to withdraw ETH as if it were ERC20, use claimWithdrawal()" + ); IERC20(tokenL1).safeTransfer(msg.sender, claimedAmount); } @@ -480,7 +409,11 @@ contract CommonBridge is bytes32[] calldata withdrawalProof ) internal view returns (bool) { bytes32 withdrawalLeaf = keccak256( - abi.encodePacked(L2_BRIDGE_ADDRESS, msgHash, withdrawalMessageId) + abi.encodePacked( + L2_BRIDGE_ADDRESS, + msgHash, + withdrawalMessageId + ) ); return MerkleProof.verify( @@ -490,16 +423,8 @@ contract CommonBridge is ); } - function upgradeL2Contract( - address l2Contract, - address newImplementation, - uint256 gasLimit, - bytes calldata data - ) public onlyOwner { - bytes memory callData = abi.encodeCall( - ITransparentUpgradeableProxy.upgradeToAndCall, - (newImplementation, data) - ); + function upgradeL2Contract(address l2Contract, address newImplementation, uint256 gasLimit, bytes calldata data) public onlyOwner { + bytes memory callData = abi.encodeCall(ITransparentUpgradeableProxy.upgradeToAndCall, (newImplementation, data)); SendValues memory sendValues = SendValues({ to: l2Contract, gasLimit: gasLimit, diff --git a/crates/l2/contracts/src/l1/interfaces/ICommonBridge.sol b/crates/l2/contracts/src/l1/interfaces/ICommonBridge.sol index db1ec114c8e..ab44c84d4e9 100644 --- a/crates/l2/contracts/src/l1/interfaces/ICommonBridge.sol +++ b/crates/l2/contracts/src/l1/interfaces/ICommonBridge.sol @@ -15,7 +15,7 @@ interface ICommonBridge { /// @param value the value of the transaction. /// @param gasLimit the gas limit for the deposit transaction. /// @param data The calldata of the deposit transaction. - event PrivilegedTxSent( + event PrivilegedTxSent ( address indexed l1From, address from, address to, @@ -49,10 +49,7 @@ interface ICommonBridge { /// @notice Method to retrieve all the pending transaction hashes. /// @dev This method is used by the L2 L1_Watcher to get the pending /// privileged transactions to be processed. - function getPendingTransactionHashes() - external - view - returns (bytes32[] memory); + function getPendingTransactionHashes() external view returns (bytes32[] memory); /// @notice Method that sends a transaction to L2. /// @dev The deposit process starts here by emitting a L1ToL2Message @@ -65,9 +62,8 @@ interface ICommonBridge { /// @dev The deposit process starts here by emitting a L1ToL2Message /// event. This event will later be intercepted by the L2 operator to /// finalize the deposit. - /// @param _amount the amount of tokens to be deposited. /// @param l2Recipient the address on L2 that will receive the deposit. - function deposit(uint256 _amount, address l2Recipient) external payable; + function deposit(address l2Recipient) external payable; /// @notice Method to retrieve the versioned hash of the first `number` /// pending privileged transactions. diff --git a/crates/l2/contracts/src/l2/CommonBridgeL2.sol b/crates/l2/contracts/src/l2/CommonBridgeL2.sol index 57f52c5fe06..671cb47d4d6 100644 --- a/crates/l2/contracts/src/l2/CommonBridgeL2.sol +++ b/crates/l2/contracts/src/l2/CommonBridgeL2.sol @@ -12,8 +12,8 @@ contract CommonBridgeL2 is ICommonBridgeL2 { 0x000000000000000000000000000000000000FFFE; address public constant BURN_ADDRESS = 0x0000000000000000000000000000000000000000; - /// @notice Token address used to represent the token of the L2 - address public constant NATIVE_TOKEN_L2 = + /// @notice Token address used to represent ETH + address public constant ETH_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; // Some calls come as a privileged transaction, whose sender is the bridge itself. @@ -35,12 +35,7 @@ contract CommonBridgeL2 is ICommonBridgeL2 { IL2ToL1Messenger(L1_MESSENGER).sendMessageToL1( keccak256( - abi.encodePacked( - NATIVE_TOKEN_L2, - NATIVE_TOKEN_L2, - _receiverOnL1, - msg.value - ) + abi.encodePacked(ETH_TOKEN, ETH_TOKEN, _receiverOnL1, msg.value) ) ); } diff --git a/crates/l2/docker-compose.yaml b/crates/l2/docker-compose.yaml index 92bba68ff27..bbd54be56b0 100644 --- a/crates/l2/docker-compose.yaml +++ b/crates/l2/docker-compose.yaml @@ -55,7 +55,6 @@ services: - ETHREX_DEPLOYER_SEQUENCER_REGISTRY_OWNER=0x4417092b70a3e5f10dc504d0947dd256b965fc62 - ETHREX_DEPLOYER_DEPLOY_BASED_CONTRACTS=${ETHREX_DEPLOYER_DEPLOY_BASED_CONTRACTS:-false} - ETHREX_L2_VALIDIUM=${ETHREX_L2_VALIDIUM:-false} - - ETHREX_NATIVE_TOKEN_L1_ADDRESS=${ETHREX_NATIVE_TOKEN_L1_ADDRESS:-0x0000000000000000000000000000000000000000} - COMPILE_CONTRACTS=true depends_on: - ethrex_l1 diff --git a/crates/l2/tests/tests.rs b/crates/l2/tests/tests.rs index 97b0071e755..aa16eccff1a 100644 --- a/crates/l2/tests/tests.rs +++ b/crates/l2/tests/tests.rs @@ -110,17 +110,8 @@ async fn l2_integration_test() -> Result<(), Box> { .map(|amount| amount.parse().expect("Invalid withdrawal amount value")) .unwrap_or(5); - let native_token_l1_address = std::env::var("ETHREX_NATIVE_TOKEN_L1_ADDRESS") - .map(|address| address.parse().expect("Invalid native token L1 address")) - .unwrap_or(Address::zero()); - // Not thread-safe (coinbase and bridge balance checks). - test_deposit( - &l1_client, - &l2_client, - &private_keys.pop().unwrap(), - native_token_l1_address, - ) - .await?; + // Not thread-safe (fee vault and bridge balance checks). + test_deposit(&l1_client, &l2_client, &private_keys.pop().unwrap()).await?; let coinbase_balance_before_tests = l2_client .get_balance(coinbase(), BlockIdentifier::Tag(BlockTag::Latest)) @@ -193,7 +184,6 @@ async fn l2_integration_test() -> Result<(), Box> { l1_client.clone(), l2_client.clone(), private_keys.pop().unwrap(), - native_token_l1_address, )); set.spawn(test_erc20_roundtrip( @@ -240,12 +230,11 @@ async fn l2_integration_test() -> Result<(), Box> { &l2_client, &private_keys.pop().unwrap(), withdrawals_count, - native_token_l1_address, ) .await?; if std::env::var("INTEGRATION_TEST_SKIP_TEST_TOTAL_ETH").is_err() { - test_total_balance_l2(&l1_client, &l2_client, native_token_l1_address).await?; + test_total_eth_l2(&l1_client, &l2_client).await?; } clean_contracts_dir(); @@ -850,21 +839,11 @@ async fn test_forced_withdrawal( l1_client: EthClient, l2_client: EthClient, rich_wallet_private_key: SecretKey, - native_token_l1_address: Address, ) -> Result { - let native_token_is_eth = native_token_l1_address == Address::zero(); println!("forced_withdrawal: Testing forced withdrawal"); let rich_address = get_address_from_secret_key(&rich_wallet_private_key).expect("Failed to get address"); - let l1_initial_native_balance = if native_token_is_eth { - l1_client - .get_balance(rich_address, BlockIdentifier::Tag(BlockTag::Latest)) - .await? - } else { - test_balance_of(&l1_client, native_token_l1_address, rich_address).await - }; - // If native token is ETH, it will match `l1_initial_native_balance` - let initial_l1_eth_balance = l1_client + let l1_initial_balance = l1_client .get_balance(rich_address, BlockIdentifier::Tag(BlockTag::Latest)) .await?; let l2_initial_balance = l2_client @@ -966,28 +945,13 @@ async fn test_forced_withdrawal( } ); - let l1_final_native_balance = if native_token_is_eth { - l1_client - .get_balance(rich_address, BlockIdentifier::Tag(BlockTag::Latest)) - .await? - } else { - test_balance_of(&l1_client, native_token_l1_address, rich_address).await - }; - if native_token_is_eth { - assert_eq!( - l1_initial_native_balance + transfer_value - l1_gas_costs, - l1_final_native_balance - ); - } else { - let l1_final_eth_balance = l1_client - .get_balance(rich_address, BlockIdentifier::Tag(BlockTag::Latest)) - .await?; - assert_eq!( - l1_initial_native_balance + transfer_value, - l1_final_native_balance - ); - assert_eq!(initial_l1_eth_balance - l1_gas_costs, l1_final_eth_balance); - } + let l1_final_balance = l1_client + .get_balance(rich_address, BlockIdentifier::Tag(BlockTag::Latest)) + .await?; + assert_eq!( + l1_initial_balance + transfer_value - l1_gas_costs, + l1_final_balance + ); assert_eq!(l2_initial_balance - transfer_value, l2_final_balance); Ok(FeesDetails::default()) } @@ -1041,10 +1005,7 @@ async fn test_deposit( l1_client: &EthClient, l2_client: &EthClient, rich_wallet_private_key: &SecretKey, - native_token_l1_address: Address, ) -> Result<(), Box> { - let native_token_is_eth = native_token_l1_address == Address::zero(); - println!("test_deposit: Fetching initial balances on L1 and L2"); let rich_wallet_address = get_address_from_secret_key(rich_wallet_private_key) .expect("Failed to get address from l1 rich wallet pk"); @@ -1053,21 +1014,12 @@ async fn test_deposit( .map(|value| U256::from_dec_str(&value).expect("Invalid deposit value")) .unwrap_or(U256::from(1000000000000000000000u128)); - let l1_initial_native_balance = if native_token_is_eth { - l1_client - .get_balance(rich_wallet_address, BlockIdentifier::Tag(BlockTag::Latest)) - .await? - } else { - test_balance_of(l1_client, native_token_l1_address, rich_wallet_address).await - }; - // This is the ETH balance of the depositor, we want to track this for the fees paid in case the native - // token is not ETH. - let initial_eth_balance = l1_client + let depositor_l1_initial_balance = l1_client .get_balance(rich_wallet_address, BlockIdentifier::Tag(BlockTag::Latest)) .await?; assert!( - l1_initial_native_balance >= deposit_value, + depositor_l1_initial_balance >= deposit_value, "L1 depositor doesn't have enough balance to deposit" ); @@ -1075,13 +1027,9 @@ async fn test_deposit( .get_balance(rich_wallet_address, BlockIdentifier::Tag(BlockTag::Latest)) .await?; - let bridge_initial_eth_balance = if native_token_is_eth { - l1_client - .get_balance(bridge_address()?, BlockIdentifier::Tag(BlockTag::Latest)) - .await? - } else { - test_balance_of(l1_client, native_token_l1_address, bridge_address()?).await - }; + let bridge_initial_balance = l1_client + .get_balance(bridge_address()?, BlockIdentifier::Tag(BlockTag::Latest)) + .await?; let coinbase_balance_before_deposit = l2_client .get_balance(coinbase(), BlockIdentifier::Tag(BlockTag::Latest)) @@ -1089,43 +1037,11 @@ async fn test_deposit( println!("test_deposit: Depositing funds from L1 to L2"); - let calldata_values = vec![ - if native_token_is_eth { - Value::Uint(U256::zero()) - } else { - Value::Uint(deposit_value) - }, - Value::Address(rich_wallet_address), - ]; - - let native_token_deposit_calldata = - encode_calldata("deposit(uint256,address)", &calldata_values)?; - - let overrides = Overrides { - value: if native_token_is_eth { - Some(deposit_value) - } else { - None - }, - from: Some(rich_wallet_address), - gas_limit: Some(1_000_000u64), - ..Overrides::default() - }; - - let generic_tx = build_generic_tx( - l1_client, - TxType::EIP1559, - bridge_address()?, + let deposit_tx_hash = ethrex_l2_sdk::deposit_through_transfer( + deposit_value, rich_wallet_address, - native_token_deposit_calldata.into(), - overrides, - ) - .await?; - - let deposit_tx_hash = ethrex_l2_sdk::send_generic_transaction( + rich_wallet_private_key, l1_client, - generic_tx, - &(LocalSigner::new(*rich_wallet_private_key).into()), ) .await?; @@ -1141,50 +1057,25 @@ async fn test_deposit( "Deposit transaction failed. Gas used: {gas_used}", ); - let l1_final_native_balance = if native_token_is_eth { - l1_client - .get_balance(rich_wallet_address, BlockIdentifier::Tag(BlockTag::Latest)) - .await? - } else { - test_balance_of(l1_client, native_token_l1_address, rich_wallet_address).await - }; + let depositor_l1_balance_after_deposit = l1_client + .get_balance(rich_wallet_address, BlockIdentifier::Tag(BlockTag::Latest)) + .await?; - if native_token_is_eth { - assert_eq!( - l1_final_native_balance, - l1_initial_native_balance - - deposit_value - - deposit_tx_receipt.tx_info.gas_used - * deposit_tx_receipt.tx_info.effective_gas_price, - "Depositor L1 balance didn't decrease as expected after deposit" - ); - } else { - let l1_final_eth_balance = l1_client - .get_balance(rich_wallet_address, BlockIdentifier::Tag(BlockTag::Latest)) - .await?; - assert_eq!( - l1_final_native_balance, - l1_initial_native_balance - deposit_value, - "Depositor L1 balance didn't decrease as expected after deposit" - ); - assert_eq!( - l1_final_eth_balance, - initial_eth_balance - gas_used * deposit_tx_receipt.tx_info.effective_gas_price, - "Depositor ETH balance didn't decrease as expected after deposit" - ); - } + assert_eq!( + depositor_l1_balance_after_deposit, + depositor_l1_initial_balance + - deposit_value + - deposit_tx_receipt.tx_info.gas_used * deposit_tx_receipt.tx_info.effective_gas_price, + "Depositor L1 balance didn't decrease as expected after deposit" + ); - let bridge_native_balance_after_deposit = if native_token_is_eth { - l1_client - .get_balance(bridge_address()?, BlockIdentifier::Tag(BlockTag::Latest)) - .await? - } else { - test_balance_of(l1_client, native_token_l1_address, bridge_address()?).await - }; + let bridge_balance_after_deposit = l1_client + .get_balance(bridge_address()?, BlockIdentifier::Tag(BlockTag::Latest)) + .await?; assert_eq!( - bridge_native_balance_after_deposit, - bridge_initial_eth_balance + deposit_value, + bridge_balance_after_deposit, + bridge_initial_balance + deposit_value, "Bridge balance didn't increase as expected after deposit" ); @@ -1519,9 +1410,7 @@ async fn test_n_withdraws( l2_client: &EthClient, withdrawer_private_key: &SecretKey, n: u64, - native_token_l1_address: Address, ) -> Result<(), Box> { - let native_token_is_eth = native_token_l1_address == Address::zero(); println!("test_n_withdraws: Withdrawing funds from L2 to L1"); let withdrawer_address = get_address_from_secret_key(withdrawer_private_key)?; let withdraw_value = std::env::var("INTEGRATION_TEST_WITHDRAW_VALUE") @@ -1539,26 +1428,18 @@ async fn test_n_withdraws( "L2 withdrawer doesn't have enough balance to withdraw" ); - let bridge_initial_native_balance = if native_token_is_eth { - l1_client - .get_balance(bridge_address()?, BlockIdentifier::Tag(BlockTag::Latest)) - .await? - } else { - test_balance_of(l1_client, native_token_l1_address, bridge_address()?).await - }; + let bridge_balance_before_withdrawal = l1_client + .get_balance(bridge_address()?, BlockIdentifier::Tag(BlockTag::Latest)) + .await?; assert!( - bridge_initial_native_balance >= withdraw_value, + bridge_balance_before_withdrawal >= withdraw_value, "L1 bridge doesn't have enough balance to withdraw" ); - let withdrawer_native_balance_before_withdrawal = if native_token_is_eth { - l1_client - .get_balance(withdrawer_address, BlockIdentifier::Tag(BlockTag::Latest)) - .await? - } else { - test_balance_of(l1_client, native_token_l1_address, withdrawer_address).await - }; + let withdrawer_l1_balance_before_withdrawal = l1_client + .get_balance(withdrawer_address, BlockIdentifier::Tag(BlockTag::Latest)) + .await?; let coinbase_balance_before_withdrawal = l2_client .get_balance(coinbase(), BlockIdentifier::Tag(BlockTag::Latest)) @@ -1616,20 +1497,12 @@ async fn test_n_withdraws( "Withdrawer L2 balance didn't decrease by value + gas as expected" ); - let withdrawer_native_balance_after_withdrawal = if native_token_is_eth { - l1_client - .get_balance(withdrawer_address, BlockIdentifier::Tag(BlockTag::Latest)) - .await? - } else { - test_balance_of(l1_client, native_token_l1_address, withdrawer_address).await - }; - // This balance will match to `withdrawer_native_balance_after_withdrawal` if the native token is ETH - let withdrawer_eth_balance_after_withdrawal = l1_client + let withdrawer_l1_balance_after_withdrawal = l1_client .get_balance(withdrawer_address, BlockIdentifier::Tag(BlockTag::Latest)) .await?; assert_eq!( - withdrawer_native_balance_after_withdrawal, withdrawer_native_balance_before_withdrawal, + withdrawer_l1_balance_after_withdrawal, withdrawer_l1_balance_before_withdrawal, "Withdrawer L1 balance should not change after withdrawal" ); @@ -1682,41 +1555,20 @@ async fn test_n_withdraws( println!("test_n_withdraws: Checking balances on L1 and L2 after claim"); - let withdrawer_native_balance_after_claim = if native_token_is_eth { - l1_client - .get_balance(withdrawer_address, BlockIdentifier::Tag(BlockTag::Latest)) - .await? - } else { - test_balance_of(l1_client, native_token_l1_address, withdrawer_address).await - }; + let withdrawer_l1_balance_after_claim = l1_client + .get_balance(withdrawer_address, BlockIdentifier::Tag(BlockTag::Latest)) + .await?; let gas_used_value: u64 = withdraw_claim_txs_receipts .iter() .map(|x| x.tx_info.gas_used * x.tx_info.effective_gas_price) .sum(); - if native_token_is_eth { - assert_eq!( - withdrawer_native_balance_after_claim, - withdrawer_eth_balance_after_withdrawal + withdraw_value * n - gas_used_value, - "Withdrawer L1 balance wasn't updated as expected after claim" - ); - } else { - assert_eq!( - withdrawer_native_balance_after_claim, - withdrawer_native_balance_after_withdrawal + withdraw_value * n, - "Withdrawer L1 balance wasn't updated as expected after claim" - ); - let withdrawer_eth_balance_after_claim = l1_client - .get_balance(withdrawer_address, BlockIdentifier::Tag(BlockTag::Latest)) - .await?; - // This exists since the fees are paid in ETH in the L1 and not in the native token for the L2 - assert_eq!( - withdrawer_eth_balance_after_claim, - withdrawer_eth_balance_after_withdrawal - gas_used_value, - "Withdrawer ETH balance wasn't updated as expected after claim" - ); - } + assert_eq!( + withdrawer_l1_balance_after_claim, + withdrawer_l1_balance_after_withdrawal + withdraw_value * n - gas_used_value, + "Withdrawer L1 balance wasn't updated as expected after claim" + ); let withdrawer_l2_balance_after_claim = l2_client .get_balance(withdrawer_address, BlockIdentifier::Tag(BlockTag::Latest)) @@ -1727,30 +1579,24 @@ async fn test_n_withdraws( "Withdrawer L2 balance should not change after claim" ); - let bridge_native_balance_after_withdrawal = if native_token_is_eth { - l1_client - .get_balance(bridge_address()?, BlockIdentifier::Tag(BlockTag::Latest)) - .await? - } else { - test_balance_of(l1_client, native_token_l1_address, bridge_address()?).await - }; + let bridge_balance_after_withdrawal = l1_client + .get_balance(bridge_address()?, BlockIdentifier::Tag(BlockTag::Latest)) + .await?; assert_eq!( - bridge_native_balance_after_withdrawal, - bridge_initial_native_balance - withdraw_value * n, + bridge_balance_after_withdrawal, + bridge_balance_before_withdrawal - withdraw_value * n, "Bridge balance didn't decrease as expected after withdrawal" ); Ok(()) } -async fn test_total_balance_l2( +async fn test_total_eth_l2( l1_client: &EthClient, l2_client: &EthClient, - native_token_l1_address: Address, ) -> Result<(), Box> { - let native_token_is_eth = native_token_l1_address == Address::zero(); - println!("Checking total balance on L2"); + println!("Checking total ETH on L2"); println!("Fetching rich accounts balance on L2"); let rich_accounts_balance = get_rich_accounts_balance(l2_client) @@ -1777,25 +1623,21 @@ async fn test_total_balance_l2( println!("Checking native tokens locked on CommonBridge"); let bridge_address = bridge_address()?; - let bridge_native_locked = if native_token_is_eth { - l1_client - .get_balance(bridge_address, BlockIdentifier::Tag(BlockTag::Latest)) - .await? - } else { - test_balance_of(l1_client, native_token_l1_address, bridge_address).await - }; + let bridge_locked_eth = l1_client + .get_balance(bridge_address, BlockIdentifier::Tag(BlockTag::Latest)) + .await?; - println!("Bridge has locked: {bridge_native_locked}"); + println!("Bridge locked ETH: {bridge_locked_eth}"); if std::env::var("INTEGRATION_TEST_SKIP_FEE_VAULT_CHECK").is_err() { assert!( - total_balance_on_l2 == bridge_native_locked, - "Total balance on L2 ({total_balance_on_l2}) differs from bridge native locked ({bridge_native_locked})" + total_balance_on_l2 == bridge_locked_eth, + "Total balance on L2 ({total_balance_on_l2}) differs from bridge native locked ({bridge_locked_eth})" ); } else { assert!( - total_balance_on_l2 < bridge_native_locked, - "Total balance on L2 ({total_balance_on_l2}) is greater than the assets locked by the bridge ({bridge_native_locked})" + total_balance_on_l2 < bridge_locked_eth, + "Total balance on L2 ({total_balance_on_l2}) is greater than the assets locked by the bridge ({bridge_locked_eth})" ); } diff --git a/docs/l2/fundamentals/contracts.md b/docs/l2/fundamentals/contracts.md index ee20eab97f9..d9540fe0bc3 100644 --- a/docs/l2/fundamentals/contracts.md +++ b/docs/l2/fundamentals/contracts.md @@ -77,7 +77,7 @@ The `CommonBridgeL2` is an L2 smart contract that facilitates cross-chain transf - **`L1_MESSENGER`**: Constant address (`0x000000000000000000000000000000000000FFFE`) representing the L2-to-L1 messenger contract - **`BURN_ADDRESS`**: Constant address (`0x0000000000000000000000000000000000000000`) used to burn ETH during withdrawals -- **`NATIVE_TOKEN_L2`**: Constant address (`0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`) representing the native token on the L2 +- **`ETH_TOKEN`**: Constant address (`0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`) representing ETH as a token #### **Core Functionality** diff --git a/docs/l2/fundamentals/native_tokens.md b/docs/l2/fundamentals/native_tokens.md deleted file mode 100644 index 09b09f26c9a..00000000000 --- a/docs/l2/fundamentals/native_tokens.md +++ /dev/null @@ -1,21 +0,0 @@ -# Why Use a Different Native Token for L2 Instead of ETH? - -## Motivation and Rationale - -Layer 2 (L2) solutions scale Ethereum by processing transactions off the main chain (L1) while relying on L1 for security and settlement. A key design choice for L2s is their native token—the asset for transaction fees, incentives, and protocol operations. While using ETH seems intuitive, many L2s opt for their own token. - -The primary motivation is protocol independence. A distinct token allows an L2 to define its own monetary policy and fee structure, tailoring its economic model to its ecosystem’s needs. For instance, L2s can experiment with fixed or dynamic pricing, or subsidized transactions, which may not align with Ethereum’s fee dynamics. - -Another factor is ecosystem growth. A native token can be distributed as rewards or grants to early users, developers, and validators, attracting activity and aligning incentives. Staking the token for consensus or security further ties participants to the L2’s success. - -Governance is also key. Native tokens enable on-chain voting for protocol upgrades or treasury decisions, giving the L2 community direct control, which is harder to achieve with ETH alone. - -## Description - -In practice, using a different native token means that all core activities on the L2—such as paying transaction fees, staking, or participating in governance—are done with this token instead of ETH. To interact with the L2, users may need to bridge the native token from L1 or obtain it through other means, although ETH and other assets can still be used for regular transactions and applications on the L2. - -To support this, the L1 bridge contract (`CommonBridge`) is set up with a `NATIVE_TOKEN_L1_ADDRESS` during initialization. This address determines which token can be deposited as the native asset on the L2. If you want to use ETH as the native token, you simply set this address to zero when initializing the bridge. - -The bridge’s deposit function (`deposit(uint256 amount, address token, address L2Recipient)`) only accepts deposits for the token specified as the native token. Withdrawals are also restricted to this token. This setup does not prevent bridging or depositing other ERC20 tokens; it just means you cannot deposit the designated native token unless it matches the one set during initialization. - -On the L2 side, the native token is treated like any other token in terms of functionality, so its use does not change the behavior of the protocol—it simply serves as the main asset for protocol-level operations. diff --git a/fixtures/contracts/ERC20/NativeTokenTest.bin b/fixtures/contracts/ERC20/NativeTokenTest.bin deleted file mode 100644 index 742117d5936..00000000000 --- a/fixtures/contracts/ERC20/NativeTokenTest.bin +++ /dev/null @@ -1 +0,0 @@ -608060405234801561000f575f5ffd5b506040518060400160405280600981526020017f54657374546f6b656e00000000000000000000000000000000000000000000008152506040518060400160405280600481526020017f5445535400000000000000000000000000000000000000000000000000000000815250816003908161008b919061059a565b50806004908161009b919061059a565b5050506100ba336b033b2e3c9fd0803ce80000006100bf60201b60201c565b61077e565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361012f575f6040517fec442f0500000000000000000000000000000000000000000000000000000000815260040161012691906106a8565b60405180910390fd5b6101405f838361014460201b60201c565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610194578060025f82825461018891906106ee565b92505081905550610262565b5f5f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490508181101561021d578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161021493929190610730565b60405180910390fd5b8181035f5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036102a9578060025f82825403925050819055506102f3565b805f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516103509190610765565b60405180910390a3505050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806103d857607f821691505b6020821081036103eb576103ea610394565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261044d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610412565b6104578683610412565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f61049b6104966104918461046f565b610478565b61046f565b9050919050565b5f819050919050565b6104b483610481565b6104c86104c0826104a2565b84845461041e565b825550505050565b5f5f905090565b6104df6104d0565b6104ea8184846104ab565b505050565b5b8181101561050d576105025f826104d7565b6001810190506104f0565b5050565b601f82111561055257610523816103f1565b61052c84610403565b8101602085101561053b578190505b61054f61054785610403565b8301826104ef565b50505b505050565b5f82821c905092915050565b5f6105725f1984600802610557565b1980831691505092915050565b5f61058a8383610563565b9150826002028217905092915050565b6105a38261035d565b67ffffffffffffffff8111156105bc576105bb610367565b5b6105c682546103c1565b6105d1828285610511565b5f60209050601f831160018114610602575f84156105f0578287015190505b6105fa858261057f565b865550610661565b601f198416610610866103f1565b5f5b8281101561063757848901518255600182019150602085019450602081019050610612565b868310156106545784890151610650601f891682610563565b8355505b6001600288020188555050505b505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61069282610669565b9050919050565b6106a281610688565b82525050565b5f6020820190506106bb5f830184610699565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6106f88261046f565b91506107038361046f565b925082820190508082111561071b5761071a6106c1565b5b92915050565b61072a8161046f565b82525050565b5f6060820190506107435f830186610699565b6107506020830185610721565b61075d6040830184610721565b949350505050565b5f6020820190506107785f830184610721565b92915050565b610e8e8061078b5f395ff3fe608060405234801561000f575f5ffd5b506004361061009c575f3560e01c80635b70ea9f116100645780635b70ea9f1461015a57806370a082311461016457806395d89b4114610194578063a9059cbb146101b2578063dd62ed3e146101e25761009c565b806306fdde03146100a0578063095ea7b3146100be57806318160ddd146100ee57806323b872dd1461010c578063313ce5671461013c575b5f5ffd5b6100a8610212565b6040516100b59190610b07565b60405180910390f35b6100d860048036038101906100d39190610bb8565b6102a2565b6040516100e59190610c10565b60405180910390f35b6100f66102c4565b6040516101039190610c38565b60405180910390f35b61012660048036038101906101219190610c51565b6102cd565b6040516101339190610c10565b60405180910390f35b6101446102fb565b6040516101519190610cbc565b60405180910390f35b610162610303565b005b61017e60048036038101906101799190610cd5565b61031b565b60405161018b9190610c38565b60405180910390f35b61019c610360565b6040516101a99190610b07565b60405180910390f35b6101cc60048036038101906101c79190610bb8565b6103f0565b6040516101d99190610c10565b60405180910390f35b6101fc60048036038101906101f79190610d00565b610412565b6040516102099190610c38565b60405180910390f35b60606003805461022190610d6b565b80601f016020809104026020016040519081016040528092919081815260200182805461024d90610d6b565b80156102985780601f1061026f57610100808354040283529160200191610298565b820191905f5260205f20905b81548152906001019060200180831161027b57829003601f168201915b5050505050905090565b5f5f6102ac610494565b90506102b981858561049b565b600191505092915050565b5f600254905090565b5f5f6102d7610494565b90506102e48582856104ad565b6102ef858585610540565b60019150509392505050565b5f6012905090565b610319336b033b2e3c9fd0803ce8000000610630565b565b5f5f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b60606004805461036f90610d6b565b80601f016020809104026020016040519081016040528092919081815260200182805461039b90610d6b565b80156103e65780601f106103bd576101008083540402835291602001916103e6565b820191905f5260205f20905b8154815290600101906020018083116103c957829003601f168201915b5050505050905090565b5f5f6103fa610494565b9050610407818585610540565b600191505092915050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f33905090565b6104a883838360016106af565b505050565b5f6104b88484610412565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81101561053a578181101561052b578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161052293929190610daa565b60405180910390fd5b61053984848484035f6106af565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036105b0575f6040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016105a79190610ddf565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610620575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016106179190610ddf565b60405180910390fd5b61062b83838361087e565b505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036106a0575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016106979190610ddf565b60405180910390fd5b6106ab5f838361087e565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361071f575f6040517fe602df050000000000000000000000000000000000000000000000000000000081526004016107169190610ddf565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361078f575f6040517f94280d620000000000000000000000000000000000000000000000000000000081526004016107869190610ddf565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015610878578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161086f9190610c38565b60405180910390a35b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036108ce578060025f8282546108c29190610e25565b9250508190555061099c565b5f5f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015610957578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161094e93929190610daa565b60405180910390fd5b8181035f5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036109e3578060025f8282540392505081905550610a2d565b805f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610a8a9190610c38565b60405180910390a3505050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f610ad982610a97565b610ae38185610aa1565b9350610af3818560208601610ab1565b610afc81610abf565b840191505092915050565b5f6020820190508181035f830152610b1f8184610acf565b905092915050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610b5482610b2b565b9050919050565b610b6481610b4a565b8114610b6e575f5ffd5b50565b5f81359050610b7f81610b5b565b92915050565b5f819050919050565b610b9781610b85565b8114610ba1575f5ffd5b50565b5f81359050610bb281610b8e565b92915050565b5f5f60408385031215610bce57610bcd610b27565b5b5f610bdb85828601610b71565b9250506020610bec85828601610ba4565b9150509250929050565b5f8115159050919050565b610c0a81610bf6565b82525050565b5f602082019050610c235f830184610c01565b92915050565b610c3281610b85565b82525050565b5f602082019050610c4b5f830184610c29565b92915050565b5f5f5f60608486031215610c6857610c67610b27565b5b5f610c7586828701610b71565b9350506020610c8686828701610b71565b9250506040610c9786828701610ba4565b9150509250925092565b5f60ff82169050919050565b610cb681610ca1565b82525050565b5f602082019050610ccf5f830184610cad565b92915050565b5f60208284031215610cea57610ce9610b27565b5b5f610cf784828501610b71565b91505092915050565b5f5f60408385031215610d1657610d15610b27565b5b5f610d2385828601610b71565b9250506020610d3485828601610b71565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680610d8257607f821691505b602082108103610d9557610d94610d3e565b5b50919050565b610da481610b4a565b82525050565b5f606082019050610dbd5f830186610d9b565b610dca6020830185610c29565b610dd76040830184610c29565b949350505050565b5f602082019050610df25f830184610d9b565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610e2f82610b85565b9150610e3a83610b85565b9250828201905080821115610e5257610e51610df8565b5b9291505056fea26469706673582212201041bb03875b99880d1250ac55ae106ee67155ece5f64d06095289b563f403ff64736f6c634300081d0033 From 3c230d713654d7a554cb746a9655abfb927268db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Paradelo?= Date: Thu, 23 Oct 2025 14:46:48 -0300 Subject: [PATCH 02/14] correct based and native tokens changes --- .github/workflows/pr-main_l2.yaml | 36 ++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-main_l2.yaml b/.github/workflows/pr-main_l2.yaml index c1875f00548..66bab6e6e28 100644 --- a/.github/workflows/pr-main_l2.yaml +++ b/.github/workflows/pr-main_l2.yaml @@ -123,16 +123,24 @@ jobs: - name: "Validium" validium: true web3signer: false + based: false compose_targets: [docker-compose.yaml] - name: "Vanilla" validium: false web3signer: false + based: false compose_targets: [docker-compose.yaml] - name: "Vanilla with Web3signer" validium: false web3signer: true + based: false compose_targets: [docker-compose.yaml, docker-compose-l2-web3signer.yaml] + - name: "Based" + validium: false + web3signer: false + based: true + compose_targets: [docker-compose.yaml] steps: - name: Checkout sources uses: actions/checkout@v4 @@ -172,7 +180,33 @@ jobs: run: | docker load --input /tmp/ethrex_image.tar - - name: Start L1 & Deploy contracts + + - name: Download ethrex L2 image artifact + uses: actions/download-artifact@v4 + with: + name: ethrex_image_l2 + path: /tmp + + - name: Load ethrex L2 image + run: | + docker load --input /tmp/ethrex_image_l2.tar + + - name: Start L1 + run: | + cd crates/l2 + docker compose up --detach ethrex_l1 + + - name: Install rex + if: ${{ matrix.based }} + run: | + cd .. + git clone https://github.com/lambdaclass/rex.git + cd rex + git checkout 18466ec1c3dbcbbf22a68fc1f850d660cb2fbf1f + make cli + echo "rex install successfully at $(which rex)" + + - name: Deploy contracts run: | # # If this job fails due to connection refused to ethrex_l1 consider increasing the failure retries From 2a778f9e9a30ab08296006e409571964dfb812c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Paradelo?= Date: Thu, 23 Oct 2025 14:47:43 -0300 Subject: [PATCH 03/14] more changes to workflow --- .github/workflows/pr-main_l2.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-main_l2.yaml b/.github/workflows/pr-main_l2.yaml index 66bab6e6e28..81421dfa8d2 100644 --- a/.github/workflows/pr-main_l2.yaml +++ b/.github/workflows/pr-main_l2.yaml @@ -180,7 +180,6 @@ jobs: run: | docker load --input /tmp/ethrex_image.tar - - name: Download ethrex L2 image artifact uses: actions/download-artifact@v4 with: @@ -214,6 +213,10 @@ jobs: # touch cmd/.env cd crates/l2 + if [ "${{ matrix.based }}" = true ]; then + export ETHREX_DEPLOYER_DEPLOY_BASED_CONTRACTS=true + export COMPILE_CONTRACTS=true + fi DOCKER_ETHREX_WORKDIR=/usr/local/bin \ ETHREX_DEPLOYER_DEPLOY_RICH=true \ ETHREX_DEPLOYER_PICO_CONTRACT_ADDRESS=0x00000000000000000000000000000000000000aa \ From 2d0fb42e4e81cddad7cb81cf12e88286494a59a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Paradelo?= Date: Thu, 23 Oct 2025 14:58:30 -0300 Subject: [PATCH 04/14] restore contracts --- crates/l2/contracts/src/l1/CommonBridge.sol | 39 ++++++++++++------- .../src/l1/interfaces/ICommonBridge.sol | 7 +++- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/crates/l2/contracts/src/l1/CommonBridge.sol b/crates/l2/contracts/src/l1/CommonBridge.sol index b6408b8c40f..a3aaa24d178 100644 --- a/crates/l2/contracts/src/l1/CommonBridge.sol +++ b/crates/l2/contracts/src/l1/CommonBridge.sol @@ -70,7 +70,8 @@ contract CommonBridge is 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; /// @notice Owner of the L2 system contract proxies - address public constant L2_PROXY_ADMIN = 0x000000000000000000000000000000000000f000; + address public constant L2_PROXY_ADMIN = + 0x000000000000000000000000000000000000f000; /// @notice Mapping of unclaimed withdrawals. A withdrawal is claimed if /// there is a non-zero value in the mapping for the message id @@ -99,6 +100,7 @@ contract CommonBridge is /// @dev It sets the OnChainProposer address. /// @param owner the address of the owner who can perform upgrades. /// @param onChainProposer the address of the OnChainProposer contract. + /// @param inclusionMaxWait the maximum time the sequencer is allowed to take without processing a privileged transaction. function initialize( address owner, address onChainProposer, @@ -134,7 +136,6 @@ contract CommonBridge is while (startingGas - gasleft() < amount) {} } - /// EIP-7702 delegated accounts have code beginning with this. bytes3 internal constant EIP7702_PREFIX = 0xef0100; /// Code size in bytes of an EIP-7702 delegated account @@ -142,7 +143,8 @@ contract CommonBridge is uint256 internal constant EIP7702_CODE_LENGTH = 23; /// This is intentionally different from the constant Optimism uses, but arbitrary. - uint256 internal constant ADDRESS_ALIASING = uint256(uint160(0xEe110000000000000000000000000000000011Ff)); + uint256 internal constant ADDRESS_ALIASING = + uint256(uint160(0xEe110000000000000000000000000000000011Ff)); /// @notice This implements address aliasing, inspired by [Optimism](https://docs.optimism.io/stack/differences#address-aliasing) /// @dev The purpose of this is to prevent L2 contracts from being impersonated by malicious L1 contracts at the same address @@ -159,7 +161,8 @@ contract CommonBridge is return msg.sender; } } - return address(uint160(uint256(uint160(msg.sender)) + ADDRESS_ALIASING)); + return + address(uint160(uint256(uint160(msg.sender)) + ADDRESS_ALIASING)); } function _sendToL2(address from, SendValues memory sendValues) private { @@ -194,12 +197,16 @@ contract CommonBridge is } /// @inheritdoc ICommonBridge - function sendToL2(SendValues calldata sendValues) public override whenNotPaused { + function sendToL2( + SendValues calldata sendValues + ) public override whenNotPaused { _sendToL2(_getSenderAlias(), sendValues); } /// @inheritdoc ICommonBridge - function deposit(address l2Recipient) public payable override whenNotPaused { + function deposit( + address l2Recipient + ) public payable override whenNotPaused { _deposit(l2Recipient); } @@ -344,7 +351,7 @@ contract CommonBridge is uint256 withdrawalBatchNumber, uint256 withdrawalMessageId, bytes32[] calldata withdrawalProof - ) public nonReentrant override whenNotPaused { + ) public override nonReentrant whenNotPaused { _claimWithdrawal( tokenL1, tokenL2, @@ -409,11 +416,7 @@ contract CommonBridge is bytes32[] calldata withdrawalProof ) internal view returns (bool) { bytes32 withdrawalLeaf = keccak256( - abi.encodePacked( - L2_BRIDGE_ADDRESS, - msgHash, - withdrawalMessageId - ) + abi.encodePacked(L2_BRIDGE_ADDRESS, msgHash, withdrawalMessageId) ); return MerkleProof.verify( @@ -423,8 +426,16 @@ contract CommonBridge is ); } - function upgradeL2Contract(address l2Contract, address newImplementation, uint256 gasLimit, bytes calldata data) public onlyOwner { - bytes memory callData = abi.encodeCall(ITransparentUpgradeableProxy.upgradeToAndCall, (newImplementation, data)); + function upgradeL2Contract( + address l2Contract, + address newImplementation, + uint256 gasLimit, + bytes calldata data + ) public onlyOwner { + bytes memory callData = abi.encodeCall( + ITransparentUpgradeableProxy.upgradeToAndCall, + (newImplementation, data) + ); SendValues memory sendValues = SendValues({ to: l2Contract, gasLimit: gasLimit, diff --git a/crates/l2/contracts/src/l1/interfaces/ICommonBridge.sol b/crates/l2/contracts/src/l1/interfaces/ICommonBridge.sol index ab44c84d4e9..86bc2df4303 100644 --- a/crates/l2/contracts/src/l1/interfaces/ICommonBridge.sol +++ b/crates/l2/contracts/src/l1/interfaces/ICommonBridge.sol @@ -15,7 +15,7 @@ interface ICommonBridge { /// @param value the value of the transaction. /// @param gasLimit the gas limit for the deposit transaction. /// @param data The calldata of the deposit transaction. - event PrivilegedTxSent ( + event PrivilegedTxSent( address indexed l1From, address from, address to, @@ -49,7 +49,10 @@ interface ICommonBridge { /// @notice Method to retrieve all the pending transaction hashes. /// @dev This method is used by the L2 L1_Watcher to get the pending /// privileged transactions to be processed. - function getPendingTransactionHashes() external view returns (bytes32[] memory); + function getPendingTransactionHashes() + external + view + returns (bytes32[] memory); /// @notice Method that sends a transaction to L2. /// @dev The deposit process starts here by emitting a L1ToL2Message From 42b2f420d779654d0efe59112587184e58b8f72e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Paradelo?= Date: Thu, 23 Oct 2025 15:19:28 -0300 Subject: [PATCH 05/14] update address contract --- crates/l2/sdk/src/sdk.rs | 6 +++--- docs/CLI.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/l2/sdk/src/sdk.rs b/crates/l2/sdk/src/sdk.rs index 5625b922439..867ae0fd698 100644 --- a/crates/l2/sdk/src/sdk.rs +++ b/crates/l2/sdk/src/sdk.rs @@ -36,10 +36,10 @@ pub use ethrex_sdk_contract_utils::*; use calldata::from_hex_string_to_h256_array; -// 0x36664d7c5031bd965bbb405b55495a90dd780740 +// 0xcb968a1441ffcfb88194912923c5353f8da0210b pub const DEFAULT_BRIDGE_ADDRESS: Address = H160([ - 0x36, 0x66, 0x4d, 0x7c, 0x50, 0x31, 0xbd, 0x96, 0x5b, 0xbb, 0x40, 0x5b, 0x55, 0x49, 0x5a, 0x90, - 0xdd, 0x78, 0x07, 0x40, + 0xcb, 0x96, 0x8a, 0x14, 0x41, 0xff, 0xcf, 0xb8, 0x81, 0x94, 0x91, 0x29, 0x23, 0xc5, 0x35, 0x3f, + 0x8d, 0xa0, 0x21, 0x0b, ]); // 0x000000000000000000000000000000000000ffff diff --git a/docs/CLI.md b/docs/CLI.md index d80d91c1449..c105c56f4b3 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -142,7 +142,7 @@ Block producer options: --block-producer.extra-data Block extra data message. - [default: "ethrex 3.0.0"] + [default: "ethrex 5.0.0"] ``` From a217effea31fad20ebef312b72291ec4740aa4c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Paradelo?= Date: Tue, 28 Oct 2025 09:24:53 -0300 Subject: [PATCH 06/14] review suggestions --- cmd/ethrex/l2/deployer.rs | 2 +- crates/l2/contracts/src/l1/CommonBridge.sol | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/cmd/ethrex/l2/deployer.rs b/cmd/ethrex/l2/deployer.rs index 9e8d75f26ae..4b05a7f5a5b 100644 --- a/cmd/ethrex/l2/deployer.rs +++ b/cmd/ethrex/l2/deployer.rs @@ -492,7 +492,7 @@ const TRANSFER_OWNERSHIP_SIGNATURE: &str = "transferOwnership(address)"; const ACCEPT_OWNERSHIP_SIGNATURE: &str = "acceptOwnership()"; const BRIDGE_INITIALIZER_SIGNATURE: &str = "initialize(address,address,uint256)"; -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct ContractAddresses { pub on_chain_proposer_address: Address, pub bridge_address: Address, diff --git a/crates/l2/contracts/src/l1/CommonBridge.sol b/crates/l2/contracts/src/l1/CommonBridge.sol index a3aaa24d178..f8ae1830ed3 100644 --- a/crates/l2/contracts/src/l1/CommonBridge.sol +++ b/crates/l2/contracts/src/l1/CommonBridge.sol @@ -207,10 +207,6 @@ contract CommonBridge is function deposit( address l2Recipient ) public payable override whenNotPaused { - _deposit(l2Recipient); - } - - function _deposit(address l2Recipient) private { deposits[ETH_TOKEN][ETH_TOKEN] += msg.value; bytes memory callData = abi.encodeCall( ICommonBridgeL2.mintETH, @@ -226,7 +222,7 @@ contract CommonBridge is } receive() external payable whenNotPaused { - _deposit(msg.sender); + deposit(msg.sender); } function depositERC20( From f93245a6a6f3be81ffc22c521c4dc72aa4c6856d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Paradelo?= Date: Tue, 28 Oct 2025 09:32:00 -0300 Subject: [PATCH 07/14] fix deployer --- cmd/ethrex/l2/deployer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/ethrex/l2/deployer.rs b/cmd/ethrex/l2/deployer.rs index 4b05a7f5a5b..3ad7581d1b0 100644 --- a/cmd/ethrex/l2/deployer.rs +++ b/cmd/ethrex/l2/deployer.rs @@ -521,7 +521,7 @@ pub async fn deploy_l1_contracts( let contract_addresses = deploy_contracts(ð_client, &opts, &signer).await?; - initialize_contracts(contract_addresses, ð_client, &opts, &signer).await?; + initialize_contracts(contract_addresses.clone(), ð_client, &opts, &signer).await?; if opts.deposit_rich { let _ = make_deposits(contract_addresses.bridge_address, ð_client, &opts) @@ -531,7 +531,7 @@ pub async fn deploy_l1_contracts( }); } - write_contract_addresses_to_env(contract_addresses, opts.env_file_path)?; + write_contract_addresses_to_env(contract_addresses.clone(), opts.env_file_path)?; info!("Deployer binary finished successfully"); Ok(contract_addresses) } From e45b0fe87c1714a03f769e5f06d64c3856b4b27e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Paradelo?= Date: Tue, 28 Oct 2025 09:53:01 -0300 Subject: [PATCH 08/14] fix default bridge address --- crates/l2/sdk/src/sdk.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/l2/sdk/src/sdk.rs b/crates/l2/sdk/src/sdk.rs index 867ae0fd698..158798647c8 100644 --- a/crates/l2/sdk/src/sdk.rs +++ b/crates/l2/sdk/src/sdk.rs @@ -36,10 +36,10 @@ pub use ethrex_sdk_contract_utils::*; use calldata::from_hex_string_to_h256_array; -// 0xcb968a1441ffcfb88194912923c5353f8da0210b +// 0x8921fff8d1a0646a3aef637837fbe6aa3f18d9b9 pub const DEFAULT_BRIDGE_ADDRESS: Address = H160([ - 0xcb, 0x96, 0x8a, 0x14, 0x41, 0xff, 0xcf, 0xb8, 0x81, 0x94, 0x91, 0x29, 0x23, 0xc5, 0x35, 0x3f, - 0x8d, 0xa0, 0x21, 0x0b, + 0x89, 0x21, 0xff, 0xf8, 0xd1, 0xa0, 0x64, 0x6a, 0x3a, 0xef, 0x63, 0x78, 0x37, 0xfb, 0xe6, 0xaa, + 0x3f, 0x18, 0xd9, 0xb9, ]); // 0x000000000000000000000000000000000000ffff @@ -75,7 +75,7 @@ pub enum SdkError { FailedToParseAddressFromHex, } -/// BRIDGE_ADDRESS or 0x36664d7c5031bd965bbb405b55495a90dd780740 +/// BRIDGE_ADDRESS or 0x8921fff8d1a0646a3aef637837fbe6aa3f18d9b9 pub fn bridge_address() -> Result { std::env::var("ETHREX_WATCHER_BRIDGE_ADDRESS") .unwrap_or(format!("{DEFAULT_BRIDGE_ADDRESS:#x}")) From 7f50595d4745b0c356700d800aa44574a0376afb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Paradelo?= Date: Fri, 31 Oct 2025 15:22:35 -0300 Subject: [PATCH 09/14] fix deafult address --- crates/l2/sdk/src/sdk.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/l2/sdk/src/sdk.rs b/crates/l2/sdk/src/sdk.rs index f24799b42bd..fc44057672d 100644 --- a/crates/l2/sdk/src/sdk.rs +++ b/crates/l2/sdk/src/sdk.rs @@ -36,10 +36,10 @@ pub use ethrex_sdk_contract_utils::*; use calldata::from_hex_string_to_h256_array; -// 0x79d6af40f7c9145b0741639ea969c13d5faa3cc6 +// 0x2eccdb10130eb3f3679bfe60aa19375d82ab5c31 pub const DEFAULT_BRIDGE_ADDRESS: Address = H160([ - 0x79, 0xd6, 0xaf, 0x40, 0xf7, 0xc9, 0x14, 0x5b, 0x07, 0x41, 0x63, 0x9e, 0xa9, 0x69, 0xc1, 0x3d, - 0x5f, 0xaa, 0x3c, 0xc6, + 0x2e, 0xcc, 0xdb, 0x10, 0x13, 0x0e, 0xb3, 0xf3, 0x67, 0x9b, 0xfe, 0x60, 0xaa, 0x19, 0x37, 0x5d, + 0x82, 0xab, 0x5c, 0x31, ]); // 0x000000000000000000000000000000000000ffff @@ -75,7 +75,7 @@ pub enum SdkError { FailedToParseAddressFromHex, } -/// BRIDGE_ADDRESS or 0x8921fff8d1a0646a3aef637837fbe6aa3f18d9b9 +/// BRIDGE_ADDRESS or 0x2eccdb10130eb3f3679bfe60aa19375d82ab5c31 pub fn bridge_address() -> Result { std::env::var("ETHREX_WATCHER_BRIDGE_ADDRESS") .unwrap_or(format!("{DEFAULT_BRIDGE_ADDRESS:#x}")) From 4d0fcf2293440aea912813a12a70dc0b77314fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Paradelo?= Date: Mon, 3 Nov 2025 15:08:02 -0300 Subject: [PATCH 10/14] fix: update default address --- crates/l2/sdk/src/sdk.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/l2/sdk/src/sdk.rs b/crates/l2/sdk/src/sdk.rs index cd665c4ed44..ba19381a353 100644 --- a/crates/l2/sdk/src/sdk.rs +++ b/crates/l2/sdk/src/sdk.rs @@ -37,10 +37,10 @@ pub use ethrex_sdk_contract_utils::*; use calldata::from_hex_string_to_h256_array; -// 0xcecd5910a4404ccf2718feb58dac13e975a862a2 +// 0xb107952dd0e2fe75d03be146ef5f45b91194fa99 pub const DEFAULT_BRIDGE_ADDRESS: Address = H160([ - 0xce, 0xcd, 0x59, 0x10, 0xa4, 0x40, 0x4c, 0xcf, 0x27, 0x18, 0xfe, 0xb5, 0x8d, 0xac, 0x13, 0xe9, - 0x75, 0xa8, 0x62, 0xa2, + 0xb1, 0x07, 0x95, 0x2d, 0xd0, 0xe2, 0xfe, 0x75, 0xd0, 0x3b, 0xe1, 0x46, 0xef, 0x5f, 0x45, 0xb9, + 0x11, 0x94, 0xfa, 0x99, ]); // 0x000000000000000000000000000000000000ffff @@ -76,7 +76,7 @@ pub enum SdkError { FailedToParseAddressFromHex, } -/// BRIDGE_ADDRESS or 0x2eccdb10130eb3f3679bfe60aa19375d82ab5c31 +/// BRIDGE_ADDRESS or 0xb107952dd0e2fe75d03be146ef5f45b91194fa99 pub fn bridge_address() -> Result { std::env::var("ETHREX_WATCHER_BRIDGE_ADDRESS") .unwrap_or(format!("{DEFAULT_BRIDGE_ADDRESS:#x}")) From 14f3b7069fa3224695edaa364ace2c2c5db6cbf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Paradelo?= <112426153+tomip01@users.noreply.github.com> Date: Mon, 10 Nov 2025 12:41:50 -0300 Subject: [PATCH 11/14] update ethrex version --- docs/CLI.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/CLI.md b/docs/CLI.md index 1b8ae492669..6974d2a009c 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -147,7 +147,7 @@ Block building options: --builder.extra-data Block extra data message. - [default: "ethrex 5.0.0"] + [default: "ethrex 6.0.0"] --builder.gas-limit Target block gas limit. @@ -310,7 +310,7 @@ Block building options: --builder.extra-data Block extra data message. - [default: "ethrex 5.0.0"] + [default: "ethrex 6.0.0"] --builder.gas-limit Target block gas limit. From 486093de91c537292b0de4a13a26136761351cbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Paradelo?= Date: Mon, 10 Nov 2025 15:11:50 -0300 Subject: [PATCH 12/14] add deprecated variable --- crates/l2/contracts/src/l1/CommonBridge.sol | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/l2/contracts/src/l1/CommonBridge.sol b/crates/l2/contracts/src/l1/CommonBridge.sol index ad8f7388401..b63dfc7d530 100644 --- a/crates/l2/contracts/src/l1/CommonBridge.sol +++ b/crates/l2/contracts/src/l1/CommonBridge.sol @@ -87,6 +87,12 @@ contract CommonBridge is /// @notice Deadline for the sequencer to include the transaction. mapping(bytes32 => uint256) public privilegedTxDeadline; + /// @dev Deprecated variable. + /// @notice The L1 token address that is treated as the one to be bridged to the L2. + /// @dev If set to address(0), ETH is considered the native token. + /// Otherwise, this address is used for native token deposits and withdrawals. + address public NATIVE_TOKEN_L1; + /// @dev Index pointing to the first unprocessed privileged transaction in the queue. uint256 private pendingPrivilegedTxIndex; From 54122dbe11658cd02e994ec454f64a269c738ea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Paradelo?= Date: Mon, 10 Nov 2025 16:36:52 -0300 Subject: [PATCH 13/14] fix default address --- crates/l2/sdk/src/sdk.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/l2/sdk/src/sdk.rs b/crates/l2/sdk/src/sdk.rs index ba19381a353..0e9ab37bfbe 100644 --- a/crates/l2/sdk/src/sdk.rs +++ b/crates/l2/sdk/src/sdk.rs @@ -37,10 +37,10 @@ pub use ethrex_sdk_contract_utils::*; use calldata::from_hex_string_to_h256_array; -// 0xb107952dd0e2fe75d03be146ef5f45b91194fa99 +// 0xebc31eff9d9f5f63f65a68734816b7de1256845b pub const DEFAULT_BRIDGE_ADDRESS: Address = H160([ - 0xb1, 0x07, 0x95, 0x2d, 0xd0, 0xe2, 0xfe, 0x75, 0xd0, 0x3b, 0xe1, 0x46, 0xef, 0x5f, 0x45, 0xb9, - 0x11, 0x94, 0xfa, 0x99, + 0xeb, 0xc3, 0x1e, 0xff, 0x9d, 0x9f, 0x5f, 0x63, 0xf6, 0x5a, 0x68, 0x73, 0x48, 0x16, 0xb7, 0xde, + 0x12, 0x56, 0x84, 0x5b, ]); // 0x000000000000000000000000000000000000ffff @@ -76,7 +76,7 @@ pub enum SdkError { FailedToParseAddressFromHex, } -/// BRIDGE_ADDRESS or 0xb107952dd0e2fe75d03be146ef5f45b91194fa99 +/// BRIDGE_ADDRESS or 0xebc31eff9d9f5f63f65a68734816b7de1256845b pub fn bridge_address() -> Result { std::env::var("ETHREX_WATCHER_BRIDGE_ADDRESS") .unwrap_or(format!("{DEFAULT_BRIDGE_ADDRESS:#x}")) From ea0e4af855c8bd999d1f6d37bd64c65511523c3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Paradelo?= <112426153+tomip01@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:27:07 -0300 Subject: [PATCH 14/14] Update crates/l2/contracts/src/l1/CommonBridge.sol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Manuel Iñaki Bilbao --- crates/l2/contracts/src/l1/CommonBridge.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/l2/contracts/src/l1/CommonBridge.sol b/crates/l2/contracts/src/l1/CommonBridge.sol index b63dfc7d530..2c5e7bf0669 100644 --- a/crates/l2/contracts/src/l1/CommonBridge.sol +++ b/crates/l2/contracts/src/l1/CommonBridge.sol @@ -88,7 +88,7 @@ contract CommonBridge is mapping(bytes32 => uint256) public privilegedTxDeadline; /// @dev Deprecated variable. - /// @notice The L1 token address that is treated as the one to be bridged to the L2. + /// @notice The L1 token address that is treated as the one to be bridged to the L2. /// @dev If set to address(0), ETH is considered the native token. /// Otherwise, this address is used for native token deposits and withdrawals. address public NATIVE_TOKEN_L1;