Deployment Summary for Developers
This page summarizes what you need to know when developing or deploying smart contracts for Monad.
Network Information
See Network Information for chain id, public RPC, block explorer, and canonical contract deployments.
Accounts
Address space | Same address space as Ethereum (last 20 bytes of ECDSA public key) |
Smart Contracts
Opcodes | All opcodes as of the Pectra fork are supported. |
Precompiles | All Ethereum precompiles as of the Pectra fork (0x01 to 0x11 ) are supported.info: 0x01 to 0x0a info: 0x0b to 0x11 |
Opcode pricing | Opcode pricing matches Ethereum as of the Pectra fork. |
Max contract size | 128 kb (up from 24.5 kb in Ethereum) |
Transaction types
Transaction types | Supported:
|
Gas limits
Per-transaction gas limit | 30 million gas |
Block gas limit | 150 million gas |
Gas throughput | 375 million gas/sec (150 million gas/block divided by 0.4 sec/block) |
Gas pricing
Gas charged | The gas limit is what is charged. That is: total tokens deducted from the sender's balance is value + gas_price * gas_limit . See discussion. |
Opcode pricing | All opcodes cost the same amount of gas as on Ethereum; see reference. For example, ADD costs 3 gas. |
EIP-1559 dynamics | Monad is EIP-1559-compatible; base fee and priority fee work as on Ethereum. EIP-1559 explainer |
Base fee | Hard-coded to 50 monad gwei (i.e. 50 * 10^-9 MON ) per unit of gas on testnet.This will become dynamic in the future. |
Timing considerations
Block frequency | 400 ms |
TIMESTAMP opcode | As in Ethereum, TIMESTAMP is a second-granularity unix timestamp. Since blocks
are every 400 ms, this means that 2-3 blocks will likely have the same timestamp. |
Finality | Blocks are finalized after two blocks (800 ms). Once a block is finalized, it cannot be reorged. See MonadBFT for a fuller discussion. |
Speculative finality | Blocks can be
speculatively finalized
after one block (400 ms), when it is marked as being in the Voted stage.Speculative finality can revert under very rare circumstances (see fuller discussion here), but most frontends should be able to reflect state based on speculative finality. |
Mempool
Monad does not have a global mempool, as this approach is not suitable for high-performance blockchains.
Each validator maintains a local mempool with transactions that it is aware of. When an RPC receives a transaction, it forwards it strategically to upcoming leaders, repeating this process if it doesn't observe the transaction getting included.
An in-depth description of the behavior can be found here.
Although this is an important part of Monad's design, it is not one that should generally affect smart contract developers in their system designs.
Parallel Execution
Monad utilizes parallel execution for efficiency, but smart contract developers don't need to change anything to account for this.
In Monad, transactions are still linearly ordered, and the only correct outcome of execution is the result as if the transactions were serially executed. All aspects of parallel execution can be treated by smart contract developers as implementation details. See further discussion.
Asynchronous Execution
Monad utilizes asynchronous execution for
efficiency, but most developers shouldn't need to change anything. Developers with significant
off-chain financial logic (e.g. exchanges, bridges, and stablecoin/RWA issuers) should wait until
blocks reach the Verified
phase (aka state root finality), three blocks later than Finalized
,
to be sure that the entire network agrees with their own node's local execution of a finalized
block.
More detail: asynchronous execution is a technique that allows Monad to substantially increase execution throughput by decoupling consensus from execution. In asynchronous execution, validators vote first, execute later - because once the transaction order is determined, the state is determined. Afterward, each node executes locally. There is a delayed merkle root three blocks later which confirms that the network got the same state trie as local execution.
From the developer perspective:
- Someone submits a transaction through your frontend which interacts with your smart contract. You make note of the hash.
- The transaction gets included in a block.
- The block gets
Voted
(speculatively finalized) one block later. (T+1
) - The block gets
Finalized
one block later (T+2
) - The block gets
Verified
(state root finalized) three blocks later (T+5
)
You listen for transaction receipts by calling
eth_getTransactionReceipt
.
Receipts will first be available after a block becomes Voted
(speculatively finalized).
Your choice of when to update your UI to give feedback to the user depends on risk preference, but
for most applications it is reasonable to do so when the block becomes Voted
because speculative
finality reversion is extremely rare. A more conservative approach would be to wait until the
block is Finalized
, since then you will never have to handle a reorg. Waiting until Verified
is not generally necessary (except for the aforementioned developers with off-chain financial
logic).
Reading blockchain data
The following methods are supported for reading blockchain data:
JSON-RPC | See RPC API. Monad supports all standard RPC methods from Ethereum. Differences are noted here. |
WebSocket | See the WebSocket Guide. Monad implements the eth_subscribe method with the following subscription types:
syncing and newPendingTransactions subscription types are not supported.
For more details see Real-time Data Sources. |
Real-time data SDK | Docs coming soon. For developers running software on the same machine as a full node, Monad supports a real-time data SDK in C and rust for reading event logs from shared memory queue in realtime as they are being executed. |
You can also use the supported Indexers.
Historic data
Monad full nodes provide access to all historic ledger data (blocks, transactions, receipts, events, and traces).
Monad full nodes do not provide access to arbitrary historic state.
See further discussion of historic data here.
Canonical contract addresses
See Canonical Contracts.