MonmouthMonmouth Docs

Message Passer

Overview

The Message Passer precompile (0x4200) handles cross-chain communication and asset transfers:

  • Asset Transfers: Move assets between Monmouth and connected chains
  • Messaging: Arbitrary data between chains
  • Proof Generation: Merkle proofs for cross-chain verification

Address

0x0000000000000000000000000000000000004200

Interface

interface IMessagePasser {
    /// @notice Initiate an outbound asset transfer
    /// @param target The destination address
    /// @param value The ETH value to send
    /// @param data The calldata to execute on the destination chain
    /// @param gasLimit The destination gas limit
    function initiateTransfer(
        address target,
        uint256 value,
        bytes calldata data,
        uint256 gasLimit
    ) external payable;
 
    /// @notice Send a cross-chain message
    /// @param target The destination contract to call
    /// @param data The message data
    /// @param gasLimit The destination gas limit
    function sendMessage(
        address target,
        bytes calldata data,
        uint256 gasLimit
    ) external;
 
    /// @notice Get transfer proof for finalization
    /// @param transferHash The transfer hash
    /// @return proof The Merkle proof
    function getTransferProof(
        bytes32 transferHash
    ) external view returns (bytes memory proof);
 
    /// @notice Check if a message has been relayed
    /// @param messageHash The message hash
    /// @return relayed Whether the message was relayed
    function isMessageRelayed(
        bytes32 messageHash
    ) external view returns (bool relayed);
}

Inbound Transfers (→ Monmouth)

Inbound transfers are initiated on the source chain via the bridge contract:

// On source chain
const bridge = new ethers.Contract(
  BRIDGE_ADDRESS,
  BridgeABI,
  signer
)
 
// Transfer ETH
await bridge.depositETH(200000, { value: parseEther('1') })
 
// Transfer ERC-20
await bridge.depositERC20(
  sourceTokenAddress,
  monmouthTokenAddress,
  parseUnits('1000', 6), // USDC
  200000
)

Outbound Transfers (Monmouth →)

Outbound transfers are initiated on Monmouth:

import { MessagePasser } from '@monmouth/wallet-sdk'
 
const passer = new MessagePasser(wallet)
 
// Initiate transfer
const transfer = await passer.initiateTransfer({
  target: recipientAddress,
  value: parseEther('1'),
  gasLimit: 200000,
})
 
console.log(transfer.hash) // Transfer hash

After the challenge period, finalize on the destination chain:

// Get proof from Monmouth
const proof = await passer.getTransferProof(transfer.hash)
 
// Finalize on destination chain
await bridge.finalizeTransfer(
  transfer.target,
  transfer.token,
  transfer.value,
  proof
)

Cross-Chain Messaging

Send arbitrary messages between chains:

// Send message to contract on another chain
await passer.sendMessage({
  target: targetContractAddress,
  data: targetContract.interface.encodeFunctionData('someFunction', [arg1, arg2]),
  gasLimit: 200000,
})

Receive messages on Monmouth:

contract MyContract {
    modifier onlyMessagePasser() {
        require(msg.sender == address(0x4200), "Not from Message Passer");
        _;
    }
 
    function receiveMessage(bytes calldata data) external onlyMessagePasser {
        // Process cross-chain message
    }
}

SDK Helpers

The Wallet SDK provides high-level helpers:

// Transfer assets to Monmouth
await wallet.bridge({
  direction: 'inbound',
  token: 'ETH',
  amount: '1 ETH',
})
 
// Transfer assets from Monmouth
await wallet.bridge({
  direction: 'outbound',
  token: 'ETH',
  amount: '1 ETH',
  recipient: '0x...', // Optional, defaults to agent
})

Gas Costs

OperationGas
initiateTransfer50,000
sendMessage30,000
getTransferProof10,000

On this page