◆ 8 EVM Chains · Immutable · No Admin

Send permanent
messages on-chain

Message any address on the blockchain. Reach whitehats, anons, deployers, or broadcast to the world. No code, no complexity — your words live forever.

Global Feed
Last 25 public broadcasts on Ethereum

No public broadcasts yet. Be the first.

Inbox
Last 25 messages sent to you on Ethereum

Connect your wallet to see messages sent to you.

Sent
Last 25 messages you sent on Ethereum

Connect your wallet to see messages you've sent.

Address Lookup
View messages to/from any address on Ethereum
🔍

Paste an address above to view their on-chain messages.

Short 0 / 280
Cost: 0.005 ETH
Message sent on-chain ✓
Short
≤ 280 chars
0.005
ETH per message
Medium
≤ 1,000 chars
0.01
ETH per message
Long
≤ 100,000 chars
0.05
ETH per message
The Problem

Sending messages on-chain is needlessly hard

Want to reach a whitehat hacker sitting on exploited funds? Message an anonymous deployer? Today you'd need to encode hex calldata by hand or deploy a custom contract. That's insane.

Without OnChain Message
✗ Need Solidity knowledge to deploy contracts
✗ Must encode calldata manually via Etherscan
✗ Different process on every chain
✗ No way to check if someone messaged you
✗ Risk of mistakes burning gas with no result
With OnChain Message
✓ Paste an address, type a message, click send
✓ Works on 8 chains with one interface
✓ Flat tiered pricing — no surprises
✓ Inbox shows messages sent to your address
✓ Lookup any address to see their messages
How It Works

Three steps to forever

No accounts. No apps to install. If you have a wallet, you can message any address on-chain in under 30 seconds.

1
Connect Wallet
MetaMask, Rabby, Coinbase Wallet — any EVM wallet. Pick your chain from the ribbon.
2
Write Your Message
Public broadcast or direct message to any address. From a quick thought (280 chars) to a full essay (100K chars).
3
Send On-Chain
Confirm the transaction. Your message is emitted as an immutable event — permanent, censorship-resistant, forever.
Multi-Chain

One contract, eight chains

Same deterministic address on every chain. Pick the one that fits your budget and audience.

Ethereum
ETH
Base
ETH
BSC
BNB
Arbitrum
ETH
Polygon
POL
Monad
MON
Sonic
S
HyperEVM
HYPE
Why On-Chain

Words that can't be erased

Tweets get deleted. Servers go down. DMs get ignored. On-chain messages are different — they exist as long as the blockchain exists.

Permanent
Stored in transaction logs forever. As long as the chain runs, your message exists.
Immutable
No admin keys. No owner. No upgrade proxy. No pause. The contract cannot be changed by anyone.
Censorship-Resistant
No one can delete, edit, or hide your message. Once confirmed, it's final.
FAQ

Questions & answers

Three tiers: Short (≤280 chars) costs 0.005 ETH. Medium (≤1,000 chars) costs 0.01 ETH. Long (≤100,000 chars) costs 0.05 ETH. Plus the chain's gas fee for the transaction.

As an event log in the smart contract transaction. Event logs are part of the blockchain's permanent record — readable by any node, block explorer, or application forever.

Yes. Paste any valid Ethereum address as the recipient. They don't need to have used this site — the message is on-chain and can be found via the Inbox tab, Lookup tab, or any block explorer. This is how you can reach whitehats, anonymous deployers, or anyone on-chain.

Yes. All on-chain messages are public. Do not send private or sensitive information. Both public broadcasts and direct messages are visible to everyone on the blockchain.

No. Once confirmed on-chain, a message cannot be changed or removed by anyone — not by you, not by us, not by any admin. The contract is fully immutable with no owner, no upgrade mechanism, and no pause function.

Any EVM-compatible browser wallet: MetaMask, Rabby, Coinbase Wallet, Rainbow, Phantom (EVM mode), Trust Wallet, and more. The connect modal auto-discovers all installed wallets via EIP-6963.

Your messages still exist on-chain forever. This site is just a convenience layer. Anyone can build another frontend, or read messages directly from any block explorer's event logs.

A public broadcast sends the message to address(0) — the zero address. It means the message isn't directed at anyone specific and shows up in the Global Feed for everyone to see. Direct messages go to a specific recipient address and show up in their Inbox.

Whitepaper

Read the full protocol specification

The OnChain Message whitepaper covers the protocol design, smart contract architecture, tiered pricing model, security model, multi-chain deployment strategy, and roadmap. Written by Textoshi.

Read Whitepaper Download PDF
Smart Contract

Fully verified, fully immutable

The entire contract is under 80 lines of Solidity. One function. One event. No owner, no admin, no proxy, no pause. Read it yourself.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

contract OnChainMessage {

    // Fee Recipient (immutable, hardcoded in bytecode)
    address public constant FEE_RECIPIENT = 0x...;

    // Tier Pricing
    uint256 public constant SHORT_MAX_BYTES  = 560;
    uint256 public constant MEDIUM_MAX_BYTES = 2000;
    uint256 public constant LONG_MAX_BYTES   = 200000;

    uint256 public constant SHORT_PRICE  = 0.005 ether;
    uint256 public constant MEDIUM_PRICE = 0.01 ether;
    uint256 public constant LONG_PRICE   = 0.05 ether;

    event MessageSent(
        address indexed sender,
        address indexed to,
        string message,
        uint256 timestamp
    );

    error MessageEmpty();
    error MessageTooLong();
    error WrongPayment(uint256 required, uint256 sent);
    error TransferFailed();

    function sendMessage(address to, string calldata message) external payable {
        uint256 len = bytes(message).length;

        if (len == 0) revert MessageEmpty();
        if (len > LONG_MAX_BYTES) revert MessageTooLong();

        uint256 required;
        if (len <= SHORT_MAX_BYTES) required = SHORT_PRICE;
        else if (len <= MEDIUM_MAX_BYTES) required = MEDIUM_PRICE;
        else required = LONG_PRICE;

        if (msg.value != required) revert WrongPayment(required, msg.value);

        emit MessageSent(msg.sender, to, message, block.timestamp);

        (bool success, ) = FEE_RECIPIENT.call{value: msg.value}("");
        if (!success) revert TransferFailed();
    }

    receive() external payable { revert("Use sendMessage()"); }
}

Full source verified on all chain explorers. Contract address linked in footer.