CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-openzeppelin-solidity

Secure Smart Contract library providing battle-tested implementations of industry-standard Solidity contracts including ERC20, ERC721, ERC1155 tokens, access control mechanisms, proxy patterns, and governance systems for Ethereum and EVM-compatible blockchains.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

crosschain.mddocs/

Cross-Chain Integration

OpenZeppelin Contracts provides cross-chain messaging utilities that enable smart contracts to communicate across different blockchain networks, supporting various Layer 2 solutions and bridges.

Core Imports

Import cross-chain contracts using Solidity import statements:

import "@openzeppelin/contracts/crosschain/CrossChainEnabled.sol";
import "@openzeppelin/contracts/crosschain/optimism/CrossChainEnabledOptimism.sol";
import "@openzeppelin/contracts/crosschain/arbitrum/CrossChainEnabledArbitrumL1.sol";
import "@openzeppelin/contracts/crosschain/arbitrum/CrossChainEnabledArbitrumL2.sol";
import "@openzeppelin/contracts/crosschain/polygon/CrossChainEnabledPolygonChild.sol";
import "@openzeppelin/contracts/crosschain/amb/CrossChainEnabledAMB.sol";

Capabilities

Base Cross-Chain Framework

Core abstraction for cross-chain message handling that provides a unified interface across different bridge implementations.

abstract contract CrossChainEnabled {
    function _isCrossChain() internal view virtual returns (bool);
    function _crossChainSender() internal view virtual returns (address);
}

Errors:

  • NotCrossChainCall() - Called when function is not executed from cross-chain context
  • InvalidCrossChainSender(address actual, address expected) - Invalid cross-chain message sender

Modifiers:

  • onlyCrossChain() - Restricts function to cross-chain calls only
  • onlyCrossChainSender(address expected) - Restricts to specific cross-chain sender

Optimism Integration

Cross-chain messaging integration for Optimism Layer 2 network using the Optimism bridge.

abstract contract CrossChainEnabledOptimism is CrossChainEnabled {
    constructor(address crossChainMessenger);
    
    function crossChainMessenger() public view virtual returns (address);
}

Usage Example:

contract OptimismContract is CrossChainEnabledOptimism {
    constructor() CrossChainEnabledOptimism(0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1) {}
    
    function handleCrossChainMessage(uint256 data) external onlyCrossChain {
        address sender = _crossChainSender();
        // Process cross-chain message
    }
}

Arbitrum L1 Integration

Cross-chain messaging for Arbitrum Layer 1 contracts that need to communicate with Arbitrum Layer 2.

abstract contract CrossChainEnabledArbitrumL1 is CrossChainEnabled {
    constructor(address bridge);
    
    function bridge() public view virtual returns (address);
}

Arbitrum L2 Integration

Cross-chain messaging for Arbitrum Layer 2 contracts communicating with Layer 1.

abstract contract CrossChainEnabledArbitrumL2 is CrossChainEnabled {
    constructor(address arbSys);
    
    function arbSys() public view virtual returns (address);
}

Polygon PoS Bridge Integration

Cross-chain integration for Polygon Proof-of-Stake bridge enabling communication between Ethereum mainnet and Polygon.

abstract contract CrossChainEnabledPolygonChild is CrossChainEnabled {
    constructor(address fxChild);
    
    function fxChild() public view virtual returns (address);
}

Arbitrary Message Bridge (AMB)

Generic cross-chain messaging through Arbitrary Message Bridge protocol, supporting various bridge implementations.

abstract contract CrossChainEnabledAMB is CrossChainEnabled {
    constructor(address bridge);
    
    function bridge() public view virtual returns (address);
}

Cross-Chain Patterns

Synchronized State Management

Maintain synchronized state across multiple chains:

contract MultiChainRegistry is CrossChainEnabledOptimism {
    mapping(bytes32 => address) public registry;
    
    event CrossChainRegistryUpdate(bytes32 indexed key, address indexed value, address indexed sender);
    
    function updateRegistry(bytes32 key, address value) external onlyCrossChain {
        address sender = _crossChainSender();
        registry[key] = value;
        emit CrossChainRegistryUpdate(key, value, sender);
    }
    
    function localUpdate(bytes32 key, address value) external {
        registry[key] = value;
        // Trigger cross-chain update to other networks
    }
}

Cross-Chain Access Control

Implement access control that works across multiple chains:

contract CrossChainAccessControl is AccessControl, CrossChainEnabledOptimism {
    bytes32 public constant CROSS_CHAIN_ADMIN = keccak256("CROSS_CHAIN_ADMIN");
    
    modifier onlyCrossChainAdmin() {
        require(
            hasRole(CROSS_CHAIN_ADMIN, _msgSender()) || 
            (_isCrossChain() && hasRole(CROSS_CHAIN_ADMIN, _crossChainSender())),
            "Not cross-chain admin"
        );
        _;
    }
    
    function crossChainGrantRole(bytes32 role, address account) external onlyCrossChainAdmin {
        _grantRole(role, account);
    }
}

Cross-Chain Token Bridging

Basic pattern for cross-chain token operations:

contract CrossChainToken is ERC20, CrossChainEnabledOptimism {
    mapping(uint256 => bool) public processedMessages;
    
    event CrossChainMint(address indexed to, uint256 amount, uint256 indexed messageId);
    event CrossChainBurn(address indexed from, uint256 amount, uint256 indexed messageId);
    
    function crossChainMint(address to, uint256 amount, uint256 messageId) 
        external 
        onlyCrossChain 
    {
        require(!processedMessages[messageId], "Message already processed");
        processedMessages[messageId] = true;
        
        _mint(to, amount);
        emit CrossChainMint(to, amount, messageId);
    }
    
    function crossChainBurn(uint256 amount, uint256 messageId) external {
        _burn(msg.sender, amount);
        emit CrossChainBurn(msg.sender, amount, messageId);
        // Trigger cross-chain mint on destination
    }
}

Security Considerations

Message Validation

Always validate cross-chain messages and their senders:

contract SecureCrossChain is CrossChainEnabledOptimism {
    address public trustedL1Contract;
    
    function processMessage(bytes calldata data) external onlyCrossChainSender(trustedL1Contract) {
        // Process validated cross-chain message
    }
}

Replay Attack Prevention

Implement nonces or message IDs to prevent replay attacks:

contract ReplayProtected is CrossChainEnabledOptimism {
    mapping(uint256 => bool) public processedMessages;
    uint256 public nextMessageId;
    
    function processMessage(uint256 messageId, bytes calldata data) external onlyCrossChain {
        require(!processedMessages[messageId], "Message replayed");
        processedMessages[messageId] = true;
        // Process message
    }
}

Bridge-Specific Considerations

  1. Optimism: Messages can be replayed on L1, implement proper validation
  2. Arbitrum: Different gas mechanics between L1 and L2
  3. Polygon: FxPortal requires specific message formats
  4. AMB: Bridge-specific validation requirements

Supported Networks

  • Optimism: Ethereum ↔ Optimism
  • Arbitrum: Ethereum ↔ Arbitrum One/Nova
  • Polygon: Ethereum ↔ Polygon PoS
  • xDai: Ethereum ↔ Gnosis Chain (via AMB)
  • Custom Bridges: Extensible through AMB pattern

Best Practices

  1. Validation: Always validate cross-chain message authenticity
  2. Replay Protection: Implement message deduplication
  3. Gas Management: Account for different gas costs across chains
  4. Error Handling: Implement robust error handling for failed messages
  5. Monitoring: Monitor cross-chain message delivery
  6. Testing: Thoroughly test cross-chain interactions on testnets

Install with Tessl CLI

npx tessl i tessl/npm-openzeppelin-solidity

docs

access-control.md

crosschain.md

finance.md

governance.md

index.md

metatx.md

proxy.md

security.md

tokens.md

utilities.md

tile.json