Skip to content

Commit c25bfd8

Browse files
alexander-seiclaude
andcommitted
fix(skills): correct Addr precompile behavior and safe/finalized wording
Independent-review fixes for the Agent Skills registry (PR #36): - sei-security: getSeiAddr REVERTS for an unassociated address (verified against sei-chain precompiles/addr/addr.go:128-132 — returns a non-nil error, no empty-string path). The old `require(bytes(actual).length != 0)` guard was dead code; wrap the call in try/catch and treat the revert as "not associated". Fix the off-chain prose to match. - sei-precompiles: drop the "reverts or returns ''" hedge so all skills agree the call reverts when unassociated. - All skills: remove the false "no safe/finalized block tags" claim — on Sei safe/finalized/latest all resolve to the same instantly-final block (per evm/differences-with-ethereum.mdx), so just query latest. - ai/skills + snippet: clarify every card copies the same full-set install command; add per-skill aria-labels for accessibility. - sei-frontend: @sei-js/precompiles ships only the seiLocal viem chain, not sei/seiTestnet. - sei-contracts/sei-security: use ~22,100 for the revm SSTORE figure to match differences-with-ethereum.mdx. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 309e754 commit c25bfd8

7 files changed

Lines changed: 30 additions & 25 deletions

File tree

‎.mintlify/skills/sei-contracts/SKILL.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ This skill makes an agent fluent in EVM smart-contract development on Sei: scaff
1919

2020
- **Chain IDs:** mainnet `pacific-1` = `1329` (`0x531`); testnet `atlantic-2` = `1328` (`0x530`). Deploy and verify against testnet first.
2121
- **EVM RPC:** mainnet `https://evm-rpc.sei-apis.com`; testnet `https://evm-rpc-testnet.sei-apis.com`. On the EVM side SEI uses 18 decimals (1 SEI = 10^18 wei); the Cosmos-side micro-denom `usei` has 6 decimals (1 SEI = 1,000,000 usei).
22-
- **~400ms blocks with fast finality:** use `tx.wait(1)` — never `tx.wait(12)`. There are **no `safe` or `finalized` block tags** on Sei; use `latest`.
22+
- **~400ms blocks with fast finality:** use `tx.wait(1)` — never `tx.wait(12)`. On Sei the `safe`, `finalized`, and `latest` commitment levels all resolve to the same instantly-final block, so just use `latest`.
2323
- **No EIP-1559 base-fee burn:** all transaction fees go to validators. Prefer **legacy `gasPrice`**. `maxFeePerGas`/`maxPriorityFeePerGas` are accepted but there is no priority-fee market.
2424
- **`block.coinbase` returns the global fee collector**, not the block proposer — do not use it to identify the validator that produced a block.
2525
- **`block.prevrandao` is NOT a safe randomness source** on Sei. Use an external VRF (Pyth Entropy/VRF or Chainlink VRF).
2626
- **Parallel execution (OCC):** Sei executes non-conflicting transactions in parallel. Transactions that write the same storage key conflict and get re-executed serially. Partition state by user/asset/id; avoid hot global counters.
27-
- **Storage write (SSTORE) gas is 72,000** — far above Ethereum's 20,000, and the **same on mainnet and testnet** (set by governance [Proposal #109](https://www.mintscan.io/sei/proposals/109)). It is a **governance-adjustable** on-chain parameter, so don't assume it is fixed forever: read the live value at https://docs.sei.io/evm/differences-with-ethereum#sstore-gas-cost and estimate per-transaction with `eth_estimateGas`. (A `forge --gas-report --fork-url` report uses revm's standard EVM schedule and shows ~22k, not Sei's cost.) The same governance-adjustable caveat applies to the **minimum gas price** and **block gas limit**.
27+
- **Storage write (SSTORE) gas is 72,000** — far above Ethereum's 20,000, and the **same on mainnet and testnet** (set by governance [Proposal #109](https://www.mintscan.io/sei/proposals/109)). It is a **governance-adjustable** on-chain parameter, so don't assume it is fixed forever: read the live value at https://docs.sei.io/evm/differences-with-ethereum#sstore-gas-cost and estimate per-transaction with `eth_estimateGas`. (A `forge --gas-report --fork-url` report uses revm's standard EVM schedule and shows ~22,100, not Sei's cost.) The same governance-adjustable caveat applies to the **minimum gas price** and **block gas limit**.
2828
- **Dual-address accounts:** every key has a `sei1...` (Cosmos) address and a `0x...` (EVM) address. Cross-VM value transfers require address association via the `Addr` precompile. See https://docs.sei.io/learn/accounts.
2929
- **CosmWasm is deprecated for new development** per SIP-3 — target Sei EVM.
3030
- **Verification is via Seiscan, backed by Sourcify** — no Etherscan API key required.
@@ -72,7 +72,7 @@ forge verify-contract \
7272
src/Counter.sol:Counter
7373
```
7474

75-
Profile your contract's gas with Foundry, but get Sei's real storage-write cost from a live estimate — a `--fork-url` report forks state yet runs the standard EVM gas schedule, so it shows SSTORE at ~22k, not Sei's ~72k:
75+
Profile your contract's gas with Foundry, but get Sei's real storage-write cost from a live estimate — a `--fork-url` report forks state yet runs the standard EVM gas schedule, so it shows SSTORE at ~22,100, not Sei's ~72,000:
7676

7777
```bash
7878
forge test --gas-report --fork-url https://evm-rpc-testnet.sei-apis.com # relative profiling of your own logic
@@ -184,7 +184,7 @@ const signer = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
184184
const tx = await contract.increment();
185185
await tx.wait(1); // one confirmation is final on Sei — do NOT use wait(12)
186186

187-
// Always read against 'latest' — Sei has no 'safe'/'finalized' tags
187+
// Read against 'latest' — on Sei 'safe'/'finalized'/'latest' resolve to the same block
188188
const head = await provider.getBlock('latest');
189189
```
190190

@@ -229,7 +229,7 @@ ERC-4337 works on Sei EVM. Sei's instant finality and gas model make it a good f
229229
## Common pitfalls
230230

231231
- **Waiting for 12 confirmations.** Sei is final in ~1 block; `tx.wait(12)` just stalls your dApp. Use `tx.wait(1)`.
232-
- **Querying `safe` or `finalized` block tags.** They don't exist on Sei — use `latest`.
232+
- **Expecting `safe`/`finalized` to differ from `latest`.** On Sei they all resolve to the same instantly-final block — just use `latest`.
233233
- **Using EIP-1559 fee fields and expecting a priority market.** There's no base-fee burn; set a legacy `gasPrice`.
234234
- **Trusting `block.prevrandao` for randomness.** It is block-time-derived on Sei, not RANDAO output — use an external VRF.
235235
- **Reading the proposer from `block.coinbase`.** It returns the global fee collector address.

‎.mintlify/skills/sei-frontend/SKILL.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ This skill makes the agent good at wiring a React dApp frontend to Sei EVM: conf
1919

2020
- **Chain IDs.** Mainnet `pacific-1` is EVM chain `1329` (`0x531`); testnet `atlantic-2` is EVM chain `1328` (`0x530`). Default to testnet in development and promote to mainnet only when the user explicitly asks.
2121
- **RPC endpoints.** EVM mainnet `https://evm-rpc.sei-apis.com`, EVM testnet `https://evm-rpc-testnet.sei-apis.com`. Cosmos RPC is `https://rpc.sei-apis.com` / `https://rpc-testnet.sei-apis.com` (only needed for Cosmos-side queries).
22-
- **Chain config comes from `wagmi/chains` / `viem/chains`.** Import the `sei` and `seiTestnet` chain objects from `wagmi/chains` (or `viem/chains`) — this is what the Sei frontend docs use. `@sei-js/precompiles` separately exports the precompile constants you need for dual-address resolution (`ADDRESS_PRECOMPILE_ADDRESS`, `ADDRESS_PRECOMPILE_ABI`); it also ships viem chain configs as a secondary option, but lead with `wagmi/chains` and stay consistent across the app.
22+
- **Chain config comes from `wagmi/chains` / `viem/chains`.** Import the `sei` and `seiTestnet` chain objects from `wagmi/chains` (or `viem/chains`) — this is what the Sei frontend docs use. `@sei-js/precompiles` separately exports the precompile constants you need for dual-address resolution (`ADDRESS_PRECOMPILE_ADDRESS`, `ADDRESS_PRECOMPILE_ABI`); it also ships a viem chain config, but only the `seiLocal` dev chain (not `sei`/`seiTestnet`), so lead with `wagmi/chains` and stay consistent across the app.
2323
- **Use legacy `gasPrice`, never EIP-1559 fields.** Sei has no EIP-1559 base-fee burn — set `gasPrice`, not `maxFeePerGas` / `maxPriorityFeePerGas`. The minimum gas price is a governance-adjustable parameter; do not hardcode a forever-number. Let the wallet/RPC estimate when possible, and check the live value at https://docs.sei.io/evm/differences-with-ethereum.
24-
- **~400ms blocks with fast finality.** Wait for a single confirmation (`tx.wait(1)` in ethers, default `useWaitForTransactionReceipt` in wagmi). Never spin on 12 confirmations or "safe"/"finalized" tags — Sei has no `safe`/`finalized` block tags; use `latest`.
24+
- **~400ms blocks with fast finality.** Wait for a single confirmation (`tx.wait(1)` in ethers, default `useWaitForTransactionReceipt` in wagmi). Never spin on 12 confirmations or wait on "safe"/"finalized" — on Sei those commitment levels resolve to the same instantly-final block as `latest`, so just use `latest`.
2525
- **Every account is dual-address.** One key yields a Cosmos `sei1…` (bech32) address and an EVM `0x…` (hex) address, both derived from the same public key. Until the two are **associated** on-chain they behave as separate accounts with separate balances. Resolve either side through the Addr precompile at `0x0000000000000000000000000000000000001004` (`getSeiAddr` / `getEvmAddr`). See https://docs.sei.io/learn/accounts.
2626
- **EIP-6963 is the wallet-discovery standard.** Wallets announce themselves via events instead of fighting over `window.ethereum`; wagmi's `injected()` connector discovers all of them automatically (Sei Global Wallet, MetaMask, Compass, …). See the supported list at https://docs.sei.io/learn/wallets.
2727
- **Target the EVM for new dApps.** CosmWasm is deprecated for new development per SIP-3; build frontends against EVM contracts.
@@ -184,7 +184,7 @@ function DualAddress({ evm }: { evm: `0x${string}` }) {
184184

185185
- **Sending EIP-1559 gas fields.** `maxFeePerGas` / `maxPriorityFeePerGas` are wrong on Sei — use legacy `gasPrice`. There is no base-fee burn; fees go to validators.
186186
- **Hardcoding a gas-price constant forever.** The minimum gas price, block gas limit, and storage (SSTORE) gas cost are governance-adjustable; the gas-price floor can differ between mainnet and testnet, while SSTORE is currently 72,000 on both. Don't bake a magic number into the UI — let the wallet/RPC estimate, or read the live value from https://docs.sei.io/evm/differences-with-ethereum#sstore-gas-cost.
187-
- **Waiting for many confirmations.** Code copied from Ethereum often waits 6–12 confirmations or polls a `finalized` tag. Sei finalizes in ~400ms with no `safe`/`finalized` tags — wait for `1` confirmation against `latest` and update the UI immediately.
187+
- **Waiting for many confirmations.** Code copied from Ethereum often waits 6–12 confirmations or polls a `finalized` tag. Sei finalizes in ~400ms and `safe`/`finalized` resolve to the same block as `latest` — wait for `1` confirmation against `latest` and update the UI immediately.
188188
- **Assuming `0x…` and `sei1…` are different users.** They are the same account once associated. Don't show a "balance is zero" error for an unassociated address — prompt the user to associate (broadcast a tx) first.
189189
- **Treating an Addr-precompile revert as a crash.** A revert means "not yet associated." Catch it and render an unlinked state.
190190
- **Fighting over `window.ethereum`.** With several extensions installed, reading `window.ethereum` directly is unreliable. Rely on EIP-6963 discovery via wagmi `injected()` and let the user choose.

‎.mintlify/skills/sei-payments/SKILL.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ This skill makes an agent good at moving and accepting digital dollars on Sei: t
2323
- Mainnet (pacific-1, chain id 1329): `0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392`
2424
- Testnet (atlantic-2, chain id 1328): `0x4fCF1784B31630811181f670Aea7A7bEF803eaED`
2525
- **Get testnet USDC** from the [Circle Faucet](https://faucet.circle.com), or bridge real USDC cross-chain with [Circle CCTP v2](https://github.com/circlefin/circle-cctp-crosschain-transfer). You still need a little native SEI to pay transaction fees.
26-
- **Sei runs ~400ms blocks with fast finality, which makes micropayments practical.** A payment confirms in roughly a block — confirm with one confirmation (`tx.wait(1)` or one block of polling), never `tx.wait(12)`. There are no `safe`/`finalized` block tags on Sei; query `latest`.
26+
- **Sei runs ~400ms blocks with fast finality, which makes micropayments practical.** A payment confirms in roughly a block — confirm with one confirmation (`tx.wait(1)` or one block of polling), never `tx.wait(12)`. On Sei `safe`/`finalized`/`latest` all resolve to the same instantly-final block; query `latest`.
2727
- **Use legacy `gasPrice`** for payment transactions. Sei has no EIP-1559 base-fee burn — set a single `gasPrice` rather than `maxFeePerGas`/`maxPriorityFeePerGas` (all fees go to validators). The minimum gas price is governance-adjustable; check the live value at https://docs.sei.io/evm/differences-with-ethereum.
2828
- **x402 uses HTTP 402 ("Payment Required").** The server answers an unpaid request with `402` plus a JSON payment challenge; the client pays on-chain, then retries with proof in an `X-Payment` header (base64-encoded JSON). The challenge `x402Version` is `1` and the scheme is `exact`.
2929
- **EVM tooling works as-is.** Use viem or ethers with the Sei EVM RPCs — mainnet `https://evm-rpc.sei-apis.com`, testnet `https://evm-rpc-testnet.sei-apis.com`.
@@ -218,7 +218,7 @@ For production, prefer the `@sei-js/x402-*` middleware (Express/Hono/Next) and c
218218

219219
- **Treating USDC as 18 decimals.** USDC is 6 decimals on Sei. `parseUnits('10', 6)` not `parseEther('10')`. A single wrong constant multiplies the amount by 10^12.
220220
- **Waiting for 12 confirmations.** Sei runs ~400ms blocks with fast finality. Use a single confirmation (`waitForTransactionReceipt` / `tx.wait(1)`); waiting 12 blocks adds pointless latency that defeats the point of micropayments.
221-
- **Querying `safe` or `finalized` block tags.** Those tags do not exist on Sei. Read state at `latest`.
221+
- **Expecting `safe`/`finalized` to differ from `latest`.** On Sei they all resolve to the same instantly-final block. Read state at `latest`.
222222
- **Sending EIP-1559 fee fields.** Use legacy `gasPrice`; there is no base-fee burn on Sei (all fees go to validators). The minimum gas price is governance-adjustable — link to https://docs.sei.io/evm/differences-with-ethereum rather than hardcoding a number.
223223
- **Mixing TypeScript syntax into a `.js` file.** Plain `node index.js` cannot parse `as const`, the `!` non-null assertion, or `as` casts. Either keep the script as valid ESM JavaScript (as above) or rename it `index.ts` and run it with a TS runner like `npx tsx index.ts`.
224224
- **Forgetting native SEI for fees.** A USDC transfer still costs transaction fees paid in native SEI. A wallet with USDC but zero SEI cannot pay.

‎.mintlify/skills/sei-precompiles/SKILL.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ This skill makes the agent precise at calling Sei's native precompiles — fixed
2424
- **The native Oracle precompile (`0x...1008`) is deprecated** and will be shut off soon. For new price feeds use a third-party oracle (Chainlink, Pyth, Redstone, API3) — see https://docs.sei.io/evm/oracles. Do not build new code on the Oracle precompile.
2525
- **Governance voting power = staked SEI only.** Liquid (unstaked) SEI gives zero voting power. Mainnet proposal deposit is 3,500 SEI (7,000 expedited); deposits are burned if a proposal gets >33.4% NoWithVeto. Vote options: `1`=Yes, `2`=Abstain, `3`=No, `4`=NoWithVeto. `voteWeighted` weights are decimal strings that must sum to exactly `"1.0"`.
2626
- **Dual-address accounts.** Every key has a `sei1...` (bech32) and a `0x...` (EVM) address. They are linked only after *association*; the Addr precompile (`0x...1004`) queries/creates the mapping, and association happens automatically on the account's first on-chain transaction. Validator addresses use the `seivaloper1...` prefix.
27-
- **Fast finality + legacy fees.** Block time is ~400ms with fast/instant finality — use `tx.wait(1)`, never `tx.wait(12)`. There are no `safe`/`finalized` tags; query `latest`. Send transactions with a legacy `gasPrice` (Sei has no EIP-1559 base-fee burn).
27+
- **Fast finality + legacy fees.** Block time is ~400ms with fast/instant finality — use `tx.wait(1)`, never `tx.wait(12)`. The `safe`/`finalized`/`latest` commitment levels all resolve to the same instantly-final block on Sei, so just query `latest`. Send transactions with a legacy `gasPrice` (Sei has no EIP-1559 base-fee burn).
2828
- **Storage gas differs from Ethereum.** Writing storage (SSTORE) costs 72,000 gas on Sei — far above Ethereum's 20,000, and the same on mainnet and testnet (set by governance [Proposal #109](https://www.mintscan.io/sei/proposals/109)). It is a governance-adjustable on-chain parameter, so don't hardcode it forever. Block gas limit and minimum gas price are likewise governance-adjustable. Check the live values at https://docs.sei.io/evm/differences-with-ethereum#sstore-gas-cost.
2929

3030
## Setup
@@ -217,7 +217,7 @@ import { ethers } from 'ethers';
217217
import { ADDRESS_PRECOMPILE_ADDRESS, ADDRESS_PRECOMPILE_ABI } from '@sei-js/precompiles';
218218

219219
const addr = new ethers.Contract(ADDRESS_PRECOMPILE_ADDRESS, ADDRESS_PRECOMPILE_ABI, provider);
220-
const seiAddr = await addr.getSeiAddr('0xYourAddress'); // "sei1..."; reverts or returns "" if unassociated
220+
const seiAddr = await addr.getSeiAddr('0xYourAddress'); // "sei1..."; REVERTS if unassociated — wrap in try/catch
221221
const evmAddr = await addr.getEvmAddr('sei1...'); // "0x..."
222222
```
223223

@@ -250,7 +250,7 @@ Deploying a *new* pointer (the registration side, Pointer precompile `0x...100B`
250250
- **`extractAsUint256` on non-integers** (decimals, booleans, negatives) reverts. Scale decimals to integers; encode booleans as 0/1.
251251
- **Expecting voting power from liquid SEI.** Only staked/delegated SEI votes; if you don't vote, your validator's vote is inherited.
252252
- **`voteWeighted` weights not summing to exactly `"1.0"`** → the transaction is rejected by the gov module.
253-
- **Using `tx.wait(12)` or `finalized`/`safe` block tags.** Sei finalizes fast — `tx.wait(1)` and `latest` are correct. Use legacy `gasPrice`, not EIP-1559 `maxFeePerGas`/priority fees.
253+
- **Using `tx.wait(12)` or expecting `finalized`/`safe` to lag `latest`.** Sei finalizes fast and those commitment levels resolve to the same block — `tx.wait(1)` and `latest` are correct. Use legacy `gasPrice`, not EIP-1559 `maxFeePerGas`/priority fees.
254254
- **Hardcoding a single SSTORE/storage gas number.** It is currently 72,000 gas (the same on mainnet and testnet) but is governance-adjustable. Estimate gas dynamically (`estimateGas`) and link to the live value rather than baking in a constant.
255255
- **Assuming a `sei1` and `0x` address are already linked.** They share a key but are only mapped after association; sending native tokens to an unassociated counterpart can be unreachable from the other VM.
256256

0 commit comments

Comments
 (0)