or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.mdl1-messaging-bridging.mdl1-rollup-management.mdl2-messaging-bridging.mdl2-system-contracts.mdstandards-interfaces.mdtypescript-utilities.mdutility-libraries.md
tile.json

standards-interfaces.mddocs/

Standards & Interfaces

Standard contracts and interfaces that define common patterns and APIs used throughout the Optimism ecosystem, including ERC20 tokens, cross-domain messaging interfaces, and address aliasing utilities.

L2StandardERC20

Contract Path: standards/L2StandardERC20.sol

Standard ERC20 implementation for L2 tokens with mint/burn capabilities for bridge integration.

Constructor

constructor(
  address _l2Bridge,
  address _l1Token,
  string memory _name,
  string memory _symbol
);

Parameters:

  • _l2Bridge (address): L2 bridge contract address that can mint/burn
  • _l1Token (address): Corresponding L1 token address
  • _name (string): Token name
  • _symbol (string): Token symbol

Key Functions

contract L2StandardERC20 {
  // Standard ERC20 functions
  function name() external view returns (string memory);
  function symbol() external view returns (string memory);
  function decimals() external view returns (uint8);
  function totalSupply() external view returns (uint256);
  function balanceOf(address account) external view returns (uint256);
  function transfer(address to, uint256 amount) external returns (bool);
  function allowance(address owner, address spender) external view returns (uint256);
  function approve(address spender, uint256 amount) external returns (bool);
  function transferFrom(address from, address to, uint256 amount) external returns (bool);
  
  // Bridge integration functions
  function mint(address _to, uint256 _amount) external;
  function burn(address _from, uint256 _amount) external;
  
  // Metadata functions
  function l1Token() external view returns (address);
  function l2Bridge() external view returns (address);
  
  // ERC165 support
  function supportsInterface(bytes4 _interfaceId) external view returns (bool);
}

mint

Mints tokens to an address (bridge only).

Parameters:

  • _to (address): Address to mint tokens to
  • _amount (uint256): Amount of tokens to mint

Restrictions: Only callable by the L2 bridge contract

burn

Burns tokens from an address (bridge only).

Parameters:

  • _from (address): Address to burn tokens from
  • _amount (uint256): Amount of tokens to burn

Restrictions: Only callable by the L2 bridge contract

l1Token

Returns the address of the corresponding L1 token.

Returns: address - L1 token contract address

l2Bridge

Returns the address of the L2 bridge contract.

Returns: address - L2 bridge contract address

Events

// Standard ERC20 events
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);

// Bridge-specific events
event Mint(address indexed _account, uint256 _amount);
event Burn(address indexed _account, uint256 _amount);

Usage Example

// Deploy L2 token for bridging
L2StandardERC20 l2Token = new L2StandardERC20(
  l2BridgeAddress,
  l1TokenAddress,
  "Optimism USD Coin",
  "USDC"
);

// Bridge will mint tokens when deposits arrive from L1
// Bridge will burn tokens when withdrawing to L1

AddressAliasHelper

Contract Path: standards/AddressAliasHelper.sol

Utilities for L1↔L2 address aliasing to prevent cross-domain replay attacks and ensure secure cross-layer communication.

Key Functions

library AddressAliasHelper {
  function applyL1ToL2Alias(address l1Address) 
    internal 
    pure 
    returns (address l2Address);
    
  function undoL1ToL2Alias(address l2Address) 
    internal 
    pure 
    returns (address l1Address);
}

applyL1ToL2Alias

Applies address aliasing for L1→L2 messages to prevent replay attacks.

Parameters:

  • l1Address (address): Original L1 address

Returns: address - Aliased L2 address

Usage:

// When an L1 contract sends a message, its address is aliased on L2
address l1Sender = 0x1234567890123456789012345678901234567890;
address aliasedSender = AddressAliasHelper.applyL1ToL2Alias(l1Sender);

// L2 contracts should check for the aliased address
require(msg.sender == aliasedSender, "Invalid L1 sender");

undoL1ToL2Alias

Removes address aliasing to recover the original L1 address.

Parameters:

  • l2Address (address): Aliased L2 address

Returns: address - Original L1 address

Usage:

// Recover original L1 address from aliased L2 address
address originalL1 = AddressAliasHelper.undoL1ToL2Alias(msg.sender);

Aliasing Rules

The address aliasing uses a constant offset to transform addresses:

  • L1→L2 Aliasing: l2Address = l1Address + 0x1111000000000000000000000000000000001111
  • L2→L1 Recovery: l1Address = l2Address - 0x1111000000000000000000000000000000001111

Core Interfaces

ICrossDomainMessenger

Contract Path: libraries/bridge/ICrossDomainMessenger.sol

Base interface for cross-domain messenger contracts (both L1 and L2).

interface ICrossDomainMessenger {
  function sendMessage(
    address _target,
    bytes calldata _message,
    uint32 _gasLimit
  ) external;
  
  function xDomainMessageSender() external view returns (address);
}

sendMessage

Sends a message to the other domain.

Parameters:

  • _target (address): Target contract address on the other domain
  • _message (bytes): Message data to send
  • _gasLimit (uint32): Gas limit for execution on the other domain

xDomainMessageSender

Returns the sender address from the other domain when processing a cross-domain message.

Returns: address - Cross-domain sender address

IL1CrossDomainMessenger

Contract Path: L1/messaging/IL1CrossDomainMessenger.sol

Interface for L1 cross-domain messenger functionality.

interface IL1CrossDomainMessenger is ICrossDomainMessenger {
  function relayMessage(
    address _target,
    address _sender,
    bytes memory _message,
    uint256 _messageNonce,
    L2MessageInclusionProof memory _proof
  ) external;
  
  function replayMessage(
    address _target,
    address _sender,
    bytes memory _message,
    uint256 _queueIndex,
    uint32 _oldGasLimit,
    uint32 _newGasLimit
  ) external;
}

IL2CrossDomainMessenger

Contract Path: L2/messaging/IL2CrossDomainMessenger.sol

Interface for L2 cross-domain messenger functionality.

interface IL2CrossDomainMessenger is ICrossDomainMessenger {
  function relayMessage(
    address _target,
    address _sender,
    bytes memory _message,
    uint256 _messageNonce
  ) external;
}

IL1StandardBridge

Contract Path: L1/messaging/IL1StandardBridge.sol

Interface for L1 standard bridge functionality.

interface IL1StandardBridge {
  function depositETH(uint32 _l2Gas, bytes calldata _data) external payable;
  
  function depositETHTo(
    address _to,
    uint32 _l2Gas,
    bytes calldata _data
  ) external payable;
  
  function depositERC20(
    address _l1Token,
    address _l2Token,
    uint256 _amount,
    uint32 _l2Gas,
    bytes calldata _data
  ) external;
  
  function finalizeETHWithdrawal(
    address _from,
    address _to,
    uint256 _amount,
    bytes calldata _data
  ) external;
  
  function finalizeERC20Withdrawal(
    address _l1Token,
    address _l2Token,
    address _from,
    address _to,
    uint256 _amount,
    bytes calldata _data
  ) external;
}

IL2ERC20Bridge

Contract Path: L2/messaging/IL2ERC20Bridge.sol

Interface for L2 bridge functionality.

interface IL2ERC20Bridge {
  function withdraw(
    address _l2Token,
    uint256 _amount,
    uint32 _l1Gas,
    bytes calldata _data
  ) external;
  
  function withdrawTo(
    address _l2Token,
    address _to,
    uint256 _amount,
    uint32 _l1Gas,
    bytes calldata _data
  ) external;
  
  function finalizeDeposit(
    address _l1Token,
    address _l2Token,
    address _from,
    address _to,
    uint256 _amount,
    bytes calldata _data
  ) external;
}

IL2StandardERC20

Contract Path: standards/IL2StandardERC20.sol

Interface for L2 standard ERC20 tokens with mint/burn capabilities.

interface IL2StandardERC20 {
  function mint(address _to, uint256 _amount) external;
  function burn(address _from, uint256 _amount) external;
  
  function l1Token() external returns (address);
  
  // Standard ERC20 functions
  function name() external view returns (string memory);
  function symbol() external view returns (string memory);
  function decimals() external view returns (uint8);
  function totalSupply() external view returns (uint256);
  function balanceOf(address account) external view returns (uint256);
  function transfer(address to, uint256 amount) external returns (bool);
  function allowance(address owner, address spender) external view returns (uint256);
  function approve(address spender, uint256 amount) external returns (bool);
  function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

Common Patterns and Usage

Cross-Domain Message Authentication

contract SecureCrossDomainReceiver {
  ICrossDomainMessenger public messenger;
  address public trustedRemoteSender;
  
  modifier onlyFromTrustedRemote() {
    require(
      msg.sender == address(messenger) &&
      messenger.xDomainMessageSender() == trustedRemoteSender,
      "Unauthorized cross-domain call"
    );
    _;
  }
  
  function handleRemoteCall(bytes calldata data) 
    external 
    onlyFromTrustedRemote 
  {
    // Process trusted cross-domain message
  }
}

L1 Contract Aliasing Check

contract L2ContractReceiver {
  using AddressAliasHelper for address;
  
  address public trustedL1Contract;
  
  function handleL1Message(bytes calldata data) external {
    // Check if sender is the aliased L1 contract
    address expectedAlias = trustedL1Contract.applyL1ToL2Alias();
    require(msg.sender == expectedAlias, "Invalid L1 sender");
    
    // Process message from trusted L1 contract
  }
}

Standard L2 Token Implementation

contract MyL2Token is L2StandardERC20 {
  constructor(
    address _l2Bridge,
    address _l1Token,
    string memory _name,
    string memory _symbol
  ) L2StandardERC20(_l2Bridge, _l1Token, _name, _symbol) {
    // Additional initialization if needed
  }
  
  // Tokens are automatically mintable/burnable by the bridge
  // Standard ERC20 functionality is inherited
}

Bridge Integration Example

contract BridgeIntegration {
  IL1StandardBridge public l1Bridge;
  IL2ERC20Bridge public l2Bridge;
  
  function bridgeTokensToL2(
    address l1Token,
    address l2Token,
    uint256 amount
  ) external {
    // Approve bridge to spend tokens
    IERC20(l1Token).approve(address(l1Bridge), amount);
    
    // Deposit tokens to L2
    l1Bridge.depositERC20(
      l1Token,
      l2Token,
      amount,
      200000, // L2 gas limit
      ""
    );
  }
  
  function bridgeTokensToL1(
    address l2Token,
    uint256 amount
  ) external {
    // Withdraw tokens to L1
    l2Bridge.withdraw(
      l2Token,
      amount,
      200000, // L1 gas limit
      ""
    );
  }
}

Complete Cross-Domain Application

// L1 Contract
contract L1Controller {
  IL1CrossDomainMessenger public messenger;
  address public l2Controller;
  
  function sendCommandToL2(uint256 command, bytes calldata data) external {
    bytes memory message = abi.encodeWithSignature(
      "executeCommand(uint256,bytes)",
      command,
      data
    );
    
    messenger.sendMessage(l2Controller, message, 200000);
  }
  
  function handleL2Response(uint256 result) external {
    require(
      msg.sender == address(messenger) &&
      messenger.xDomainMessageSender() == l2Controller,
      "Invalid L2 response"
    );
    
    // Process result from L2
  }
}

// L2 Contract
contract L2Controller {
  using AddressAliasHelper for address;
  
  IL2CrossDomainMessenger public messenger;
  address public l1Controller;
  
  function executeCommand(uint256 command, bytes calldata data) external {
    // Verify sender is aliased L1 controller
    require(
      msg.sender == l1Controller.applyL1ToL2Alias(),
      "Invalid L1 sender"
    );
    
    // Execute command
    uint256 result = processCommand(command, data);
    
    // Send response back to L1
    bytes memory response = abi.encodeWithSignature(
      "handleL2Response(uint256)",
      result
    );
    
    messenger.sendMessage(l1Controller, response, 200000);
  }
  
  function processCommand(uint256 command, bytes calldata data) 
    internal 
    returns (uint256) 
  {
    // Command processing logic
    return 42;
  }
}

This standards and interfaces documentation provides the foundation for building secure, interoperable contracts within the Optimism ecosystem, with proper cross-domain authentication and standard token implementations.