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
| Operation | Gas |
|---|---|
| initiateTransfer | 50,000 |
| sendMessage | 30,000 |
| getTransferProof | 10,000 |