Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions evm/differences-with-ethereum.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
description: "A comparison of Sei EVM and Ethereum, highlighting Sei's advantages in blocktime, throughput, finality, and execution environment, as well as technical differences in opcodes, state storage, and other features."
keywords: ['Sei EVM', 'Ethereum comparison', 'blockchain differences', 'EVM compatibility', 'blockchain performance']
---

import { SstoreGasLive } from '/snippets/sstore-gas-live.jsx';

While Sei features full EVM compatibility, there are some distinctions between
Sei's EVM and Ethereum itself:

Expand Down Expand Up @@ -47,7 +50,7 @@
- User accounts on Sei have [two addresses](/learn/accounts) derived from the same public key (Cosmos Bech32 and EVM-compatible 0x…)
- Interoperability between EVM and Cosmos-SDK modules is governed and navigated via [precompiles](/evm/precompiles/example-usage) and [pointer contracts](/learn/pointers)

## Sei EVM Release

Check warning on line 53 in evm/differences-with-ethereum.mdx

View check run for this annotation

Mintlify / Mintlify Validation (seilabs) - vale-spellcheck

evm/differences-with-ethereum.mdx#L53

Use sentence case for headings: 'Sei EVM Release'.

Sei EVM was originally deployed at the following block heights and versions:

Expand All @@ -63,7 +66,7 @@
- **Height:** `79123881`
- **Changelog:** https://github.com/sei-protocol/sei-chain/blob/main/CHANGELOG.md#v552

## Opcode Differences

Check warning on line 69 in evm/differences-with-ethereum.mdx

View check run for this annotation

Mintlify / Mintlify Validation (seilabs) - vale-spellcheck

evm/differences-with-ethereum.mdx#L69

Use sentence case for headings: 'Opcode Differences'.

| Opcode | Sei EVM | Ethereum | Notes |
| --- | --- | --- | --- |
Expand All @@ -77,7 +80,7 @@
| Blob‑related opcodes | Not supported (Pectra without blobs) | Supported post‑Cancun (EIP‑4844) | Blob transactions are not enabled on Sei. |


### PREVRANDAO

Check warning on line 83 in evm/differences-with-ethereum.mdx

View check run for this annotation

Mintlify / Mintlify Validation (seilabs) - vale-spellcheck

evm/differences-with-ethereum.mdx#L83

Use sentence case for headings: 'PREVRANDAO'.

Since Sei doesn't rely on the same pseudo‑randomness way of determining the next
validator like Proof of Stake (PoS) Ethereum does, it doesn't have the
Expand All @@ -91,19 +94,19 @@
Coinbase address on Sei is always set to (the EVM address of) the global fee
collector.

## State Root

Check warning on line 97 in evm/differences-with-ethereum.mdx

View check run for this annotation

Mintlify / Mintlify Validation (seilabs) - vale-spellcheck

evm/differences-with-ethereum.mdx#L97

Use sentence case for headings: 'State Root'.

Since Sei uses AVL-tree instead of Merkle Patricia Trie (MPT) for data storage,
Sei doesn't have per-account state root. The global state root is the AVL-tree
root which is also not equivalent to Ethereum's overall state root (which is a
MPT root)

## Block Hash

Check warning on line 104 in evm/differences-with-ethereum.mdx

View check run for this annotation

Mintlify / Mintlify Validation (seilabs) - vale-spellcheck

evm/differences-with-ethereum.mdx#L104

Use sentence case for headings: 'Block Hash'.

The block hash on Sei is computed based on the block header in Tendermint data
format, and is different from Ethereum's block Hash as a result.

## Base Fee & Tips

Check warning on line 109 in evm/differences-with-ethereum.mdx

View check run for this annotation

Mintlify / Mintlify Validation (seilabs) - vale-spellcheck

evm/differences-with-ethereum.mdx#L109

Use sentence case for headings: 'Base Fee & Tips'.

Sei supports all non‑blob transaction types, including the Pectra `SetCode` transaction (EIP‑7702). However for a legacy (non EIP‑1559) type
transaction, you must specify a gas price at or above Sei's governance-set minimum gas price (currently `50 gwei` on mainnet). Query the live value with `eth_gasPrice` rather than hard-coding it. In addition to this, excess
Expand All @@ -128,7 +131,7 @@
value: '"0.007500000000000000"'
```

## Non-EVM Transactions

Check warning on line 134 in evm/differences-with-ethereum.mdx

View check run for this annotation

Mintlify / Mintlify Validation (seilabs) - vale-spellcheck

evm/differences-with-ethereum.mdx#L134

Use sentence case for headings: 'Non-EVM Transactions'.

On Sei there exists non-EVM transactions which may update states accessible by
EVM transactions. The simplest example would be bank balances, which may be
Expand All @@ -142,7 +145,7 @@
committed (~400 ms) — meaning that commitment levels of "safe", "latest",
"justified", and "finalized" on Ethereum are all the same thing on Sei.

## Pending State

Check warning on line 148 in evm/differences-with-ethereum.mdx

View check run for this annotation

Mintlify / Mintlify Validation (seilabs) - vale-spellcheck

evm/differences-with-ethereum.mdx#L148

Use sentence case for headings: 'Pending State'.

On Ethereum the block proposer would execute its proposed block first (and
update its local state) before broadcasting the proposal to others (the updated
Expand All @@ -153,7 +156,7 @@
the same time), so Sei does not have a window when "pending state"
exists.

## Gas Model & Fees

Check warning on line 159 in evm/differences-with-ethereum.mdx

View check run for this annotation

Mintlify / Mintlify Validation (seilabs) - vale-spellcheck

evm/differences-with-ethereum.mdx#L159

Use sentence case for headings: 'Gas Model & Fees'.

Sei does not implement base‑fee burning. There is no base‑fee burn; all transaction fees accrue to validators. Fees are calculated as:

Expand All @@ -175,19 +178,21 @@

</Info>

## SSTORE Gas Cost

Check warning on line 181 in evm/differences-with-ethereum.mdx

View check run for this annotation

Mintlify / Mintlify Validation (seilabs) - vale-spellcheck

evm/differences-with-ethereum.mdx#L181

Use sentence case for headings: 'SSTORE Gas Cost'.

On Sei, the `SSTORE` opcode gas cost is configurable as an on-chain parameter, meaning it can be adjusted via governance proposal without requiring a chain upgrade.
On Sei, the `SSTORE` opcode gas cost is configurable as an on-chain parameter, meaning it can be adjusted via governance proposal without requiring a chain upgrade. This provides flexibility to tune storage costs based on EVM state size and network conditions.

Currently, the `SSTORE` gas cost is set to the non-standard value of **72,000 gas**. This value is the same on both mainnet (`pacific-1`) and testnet (`atlantic-2`). It was set by governance [Proposal #109](https://www.mintscan.io/sei/proposals/109) ("Update EVM SSTORE set gas to 72000"), which changed the `evm` module parameter `KeySeiSstoreSetGasEIP2200` to `72000`.

This provides flexibility to tune storage costs based on EVM state size and network conditions.
The values below are read **live** from the Sei EVM:

Currently, the `SSTORE` gas cost is set to the non-standard value of **72,000 gas**, and this is the same on both mainnet (`pacific-1`) and testnet (`atlantic-2`) — it does not vary by network. It was set by governance [Proposal #109](https://www.mintscan.io/sei/proposals/109) ("Update EVM SSTORE set gas to 72000"), which changed the `evm` module parameter `KeySeiSstoreSetGasEIP2200` to `72000`.
<SstoreGasLive network="mainnet" />

To confirm the real cost yourself, use a live `eth_estimateGas` call against a Sei RPC. Note that a Foundry `forge test --gas-report --fork-url <sei rpc>` report forks chain *state* but applies revm's standard EVM gas schedule, so it reports the Ethereum cost (~22,100) rather than Sei's — it is useful for relative profiling of your own logic, not for the absolute storage-write cost.

<Info>Since `SSTORE` is a governance-controlled parameter, this value may change in the future through a governance proposal.</Info>

## ERC Token Standards Compatibility

Check warning on line 195 in evm/differences-with-ethereum.mdx

View check run for this annotation

Mintlify / Mintlify Validation (seilabs) - vale-spellcheck

evm/differences-with-ethereum.mdx#L195

Use sentence case for headings: 'ERC Token Standards Compatibility'.

Sei’s EVM fully supports the common token standards:

Expand All @@ -197,7 +202,7 @@

Existing OpenZeppelin contracts and tools work unchanged.

## Testing & Migration Checklist

Check warning on line 205 in evm/differences-with-ethereum.mdx

View check run for this annotation

Mintlify / Mintlify Validation (seilabs) - vale-spellcheck

evm/differences-with-ethereum.mdx#L205

Use sentence case for headings: 'Testing & Migration Checklist'.

- ✅ Re‑deploy your Solidity code to Sei testnet; most contracts need no changes.
- ✅ If you used SELFDESTRUCT, refactor to a soft‑close pattern.
Expand Down
139 changes: 139 additions & 0 deletions snippets/sstore-gas-live.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
export const SstoreGasLive = ({ network = 'mainnet' }) => {
// Reads the live SSTORE gas cost from SstoreGasProbe — a tiny, Sourcify-verified
// contract whose functions measure a throwaway SSTORE with the GAS opcode. Called via
// eth_call (read-only, state discarded, no gas spent), so the number always reflects the
// current governance parameter (KeySeiSstoreSetGasEIP2200) and can never go stale.
const COLD = '0x50025cb2'; // coldWriteCost() -> SSTORE_SET + EIP-2929 cold access
const PARAM = '0x095f88b9'; // setParamGas() -> SSTORE_SET parameter alone (pre-warmed)

const RPC = {
mainnet: {
url: 'https://evm-rpc.sei-apis.com',
chain: 'pacific-1',
id: 1329,
probe: '0xeeB428bcf499D0A1c401f123F64BFf754a5de57A',
explorer: 'https://seiscan.io/address/0xeeB428bcf499D0A1c401f123F64BFf754a5de57A'
},
testnet: {
url: 'https://evm-rpc-testnet.sei-apis.com',
chain: 'atlantic-2',
id: 1328,
probe: '0xE5A35b2457E1C3cfF2F6527fAA32DE0B2a8e28E0',
explorer: 'https://testnet.seiscan.io/address/0xE5A35b2457E1C3cfF2F6527fAA32DE0B2a8e28E0'
}
};

const [net, setNet] = useState(network === 'testnet' ? 'testnet' : 'mainnet');
const [data, setData] = useState(null);
const [err, setErr] = useState(null);
const [loading, setLoading] = useState(true);

const ethCall = async (url, to, data) => {
const res = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'eth_call', params: [{ to, data }, 'latest'] })
});
const json = await res.json();
if (json.error) throw new Error(json.error.message || 'eth_call failed');
return parseInt(json.result, 16);
};

const load = async (which) => {
setLoading(true);
setErr(null);
try {
const { url, probe } = RPC[which];
const [param, cold] = await Promise.all([ethCall(url, probe, PARAM), ethCall(url, probe, COLD)]);
setData({ param, cold });
} catch (e) {
setErr(e && e.message ? e.message : 'Failed to query RPC');
setData(null);
} finally {
setLoading(false);
}
};

useEffect(() => {
load(net);
}, [net]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale RPC responses race

Medium Severity

Switching Mainnet/Testnet starts a new load without invalidating earlier eth_call requests. If an older fetch finishes after a newer one, setData and setLoading still run, so the widget can show one network’s gas values while the other tab and footer labels are selected.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 175d012. Configure here.


const fmt = (n) => (n == null ? '—' : n.toLocaleString('en-US'));

const TabButton = ({ value, children }) => {
const active = net === value;
return (
<button
type="button"
onClick={() => setNet(value)}
className="px-3 py-1 transition-colors"
style={{
fontFamily: 'var(--sei-font-mono)',
fontSize: '11px',
textTransform: 'uppercase',
letterSpacing: '0.04em',
color: active ? '#ffffff' : 'var(--sei-maroon-100)',
backgroundColor: active ? 'var(--sei-maroon-100)' : 'transparent',
border: '1px solid var(--sei-maroon-100)',
cursor: active ? 'default' : 'pointer'
}}>
{children}
</button>
);
};

const Stat = ({ label, value, sub }) => (
<div className="flex flex-col gap-0.5">
<span className="text-[11px] uppercase tracking-wide text-neutral-500 dark:text-neutral-400" style={{ fontFamily: 'var(--sei-font-mono)' }}>
{label}
</span>
<span className="text-2xl font-semibold text-neutral-900 dark:text-neutral-50 tabular-nums" style={{ fontFamily: 'var(--sei-font-mono)' }}>
{loading ? '…' : value}
<span className="text-sm font-normal text-neutral-500 dark:text-neutral-400"> gas</span>
</span>
{sub && <span className="text-[11px] text-neutral-500 dark:text-neutral-400">{sub}</span>}
</div>
);

return (
<div
className="not-prose w-full rounded-lg border border-neutral-200 dark:border-neutral-700 p-4"
style={{ backgroundColor: 'rgba(127,127,127,0.04)' }}>
<div className="flex items-center justify-between gap-3 mb-3">
<span className="text-[12px] font-semibold text-neutral-700 dark:text-neutral-200" style={{ fontFamily: 'var(--sei-font-mono)' }}>
Live SSTORE gas — measured on-chain
</span>
<div className="inline-flex">
<TabButton value="mainnet">Mainnet</TabButton>
<TabButton value="testnet">Testnet</TabButton>
</div>
</div>

{err ? (
<div className="text-[12px] text-red-600 dark:text-red-400" style={{ fontFamily: 'var(--sei-font-mono)' }}>
Could not reach {RPC[net].chain} RPC: {err}{' '}
<button type="button" onClick={() => load(net)} className="underline">
retry
</button>
</div>
) : (
<div className="flex flex-wrap gap-x-10 gap-y-3">
<Stat label="SSTORE_SET parameter" value={fmt((data && data.param)-8)} sub="governance value (≈ 72,000)" />
<Stat label="Cold first write" value={fmt((data && data.cold)-7)} sub="SSTORE_SET + EIP-2929 cold access (2,100)" />
</div>
)}

<div className="mt-3 text-[11px] text-neutral-500 dark:text-neutral-400">
{RPC[net].chain} ({RPC[net].id}) · read via <code>eth_call</code> from the verified{' '}
<a href={RPC[net].explorer} target="_blank" rel="noopener noreferrer" className="underline">
SstoreGasProbe
</a>{' '}
contract. Governance-adjustable — set by{' '}
<a href="https://www.mintscan.io/sei/proposals/109" target="_blank" rel="noopener noreferrer" className="underline">
Proposal #109
</a>
.
</div>
</div>
);
};
Loading