diff --git a/AGENTS.md b/AGENTS.md index cab6418..318fdd0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,41 +1,55 @@ # AGENTS.md — building on Rome with an AI coding agent -**Rome is EVM chains that run on Solana.** Your Solidity/EVM app executes inside a Solana program and can call Solana programs atomically (CPI). Two lanes reach the same chain and the same state: MetaMask/EVM tooling, and Phantom/Solana. This file is the set of Rome-specific rules to follow — vanilla-EVM habits produce plausible-but-wrong code here. Reads (`eth_call`, balances, logs) are standard; the differences are in **writes, gas, tooling, and CPI**. +**Rome is EVM chains that run natively inside the Solana runtime.** Your Solidity/EVM app executes inside a Solana program and can call Solana programs atomically (CPI). Two lanes reach the same chain and the same state: MetaMask/EVM tooling, and Phantom/Solana. -## The rules that differ from vanilla EVM +This file gives you the facts, organized by **what you're starting from**. Find your starting point, apply the rules that bite on every path, and read the example repo closest to what you're building. Vanilla-EVM habits produce plausible-but-wrong code here — reads (`eth_call`, balances, logs) are standard; the differences are in writes, gas, tooling, CPI, and architecture. -### 1. Every Rome write goes through `submitRomeTx` -Do **not** send state-changing txs with raw `wagmi`/`ethers`/`viem` `writeContract`/`sendTransaction`. Rome writes have specific fee and submission semantics — use the SDK's `submitRomeTx` wrapper. Reads stay vanilla. +## First, the mental model — three facts everything rests on +- **EVM inside Solana.** Your Solidity runs inside a Solana program; from Solidity you can invoke *any* Solana program (SPL Token, Meteora, a program you wrote) atomically, in one transaction, via the CPI precompile. +- **One state, two lanes.** MetaMask (an EVM key) and Phantom (a Solana key) drive the **same** contracts and the **same** state. A Phantom user signs with their **Solana** key — no EVM keypair, no separate address. An EVM user's on-chain identity is a Rome-derived PDA (`external_auth`). +- **SPL *is* ERC-20, automatically.** Any SPL token is already an ERC-20 on Rome — the **same account**, no bridge and no wrapped-asset hop. An LP or position token minted as an SPL mint is immediately spendable as an ERC-20, and vice-versa. -### 2. Gas: the estimate over-predicts; the charge is exact -`eth_estimateGas` can over-predict by a large factor — Rome charges the **exact** gas used, so do not hard-fail or size budgets off a high estimate. A plain **native-token transfer costs ~1.48M gas** on Rome (not 21k); budget for it in scripts and sweeps. +## Find your starting point -### 3. Foundry / Hardhat -`forge script` needs **`--skip-simulation`** (Rome's execution model breaks forge's local simulation). `forge create`, `cast`, and Hardhat work normally. +### You have Solidity — a contract, or an EVM app to fork +Deploy it as it is, with standard Hardhat or Foundry (one caveat: `forge script` needs `--skip-simulation`; `forge create`, `cast`, and Hardhat work normally). The moment it's on Rome it's open to EVM users, Solana users, and users arriving from other chains **at once** — you don't write per-audience code. Nothing about your Solidity changes. When you want Solana liquidity or data, call a Solana program via CPI (see the rules below). +**Read:** [compound-on-rome-comet](https://github.com/rome-protocol/compound-on-rome-comet) and [rome-aave-v3](https://github.com/rome-protocol/rome-aave-v3) — Compound v3 and Aave v3 running unchanged. -### 4. Calling Solana programs from Solidity (CPI — the differentiator) -Precompiles: **CPI `0xFF…08`**, **Helper `0xFF…09`**, **Withdraw `0x42…16`**. The account rules agents get wrong: -- the accounts array must be **non-empty**; -- the **operator and the program_id must NOT** appear in the accounts; -- to sign **as your contract**, use `HELPER.pda(address(this))` as the signer — the precompile signs as `msg.sender`, not `tx.origin`, so a router contract cannot sign a user's PDA. +### You have a Solana program +It keeps doing what it already does for your Solana users — no changes. To open it to EVM (and other-chain) users, write a **thin Solidity wrapper that CPIs your program**: the accounts array and instruction data are the same layout your program already expects. Make your instructions **authority-agnostic** — act on whichever authority signs — so the caller can be a Solana wallet pubkey *or* an EVM user's `external_auth` PDA. The precompile signs as `msg.sender` (the wrapper's own PDA), not `tx.origin`. +**Read:** [cardo](https://github.com/rome-protocol/cardo) — drives Jupiter, Meteora, Marinade, and Mango from an EVM account. -Full ABI + per-selector billing: the precompile reference (docs). +### You have one lane and want to open the other — the Parity Pattern +Keep **one** source of truth: a native Solana program written authority-agnostic, plus a thin EVM router. A Phantom user drives the program directly; a MetaMask user drives it through the router and Rome auto-signs their PDA — **both act on the same reserves/state at near-CU parity**. Because the LP/position token is an SPL mint, it's automatically an ERC-20, so a position opened on one lane is spendable on the other. Keep the account set lean and ALT-friendly to keep the EVM lane cheap, and test both lanes. +**Read:** [rome-dex](https://github.com/rome-protocol/rome-dex) (AMM), [aerarium](https://github.com/rome-protocol/aerarium) (lending). -### 5. Never hardcode addresses — read the registry -Chain ids, RPC URLs, contract addresses, token mints, and Solana program ids all come from **`@rome-protocol/registry`**. Hardcoded values drift and break across deploys. +### You're building greenfield — bring your idea +Use both sides from day one: one pool both audiences trade, one market both borrow from, an oracle that brings Solana prices into the EVM. Decide the architecture up front — **Solidity-first** (a Solidity app that calls Solana via CPI) is the default; reach for a **native program + router** only when a Solana wallet must act natively on shared state, or a hot path needs native-CU efficiency. Resolve everything from the registry; use the SDK for writes. +**Read:** [rome-dex](https://github.com/rome-protocol/rome-dex), [appia](https://github.com/rome-protocol/appia), [rome-oracle-gateway](https://github.com/rome-protocol/rome-oracle-gateway). **Scaffold:** `create-rome-app` (ships with the docs release). -### 6. Test both lanes with a fresh wallet -A Rome feature must work on the **EVM lane** (MetaMask) *and* the **Solana lane** (Phantom). Verify each with a brand-new wallet and a tiny amount before claiming done. +### Your users are on their home turf — reach Rome from another chain +Your users don't move — from their home chain (an L2, Solana, …) they reach your Rome app without leaving. The bridge is **on-chain**: `RomeBridgeWithdraw` (egress from Rome) + the rome-evm `settle_inbound_bridge` program (inbound credit, authorized by the user's own signed **EIP-712** intent — trustless, no privileged settler key). Transport is Circle CCTP (USDC) or Wormhole. The off-chain **`rome-bridge-api`** orchestrates it: quote a route → verify the source tx → fee-sponsor the settle. It holds no keys and can only *trigger* what the user already signed. +**Read:** [appia](https://github.com/rome-protocol/appia) (a from-home app), [rome-bridge-api](https://github.com/rome-protocol/rome-bridge-api) (the orchestrator; see its `docs/BRIDGE_API_ARCHITECTURE.md`). -### 7. When a tx fails, use the taxonomy + the cross-VM map -Rome surfaces specific failures (starved pool-payer rent, StateHolder rent, emulation-vs-simulation mismatches, nonce races). Match them against the **error taxonomy** (docs). To see the Solana settlement of a Rome tx, map it with `solanaTxForEvmTx`. +## The rules that bite on every path (different from vanilla EVM) + +1. **Every write goes through `submitRomeTx`.** Do not send state-changing txs with raw `wagmi`/`ethers`/`viem` `writeContract`/`sendTransaction` — Rome writes have specific fee + submission semantics; use the SDK's `submitRomeTx`. Reads stay vanilla. +2. **Gas: the estimate over-predicts; the charge is exact.** `eth_estimateGas` can over-predict by a large factor — Rome charges the exact gas used, so don't hard-fail or size budgets off a high estimate. A plain native-token transfer costs **~1.48M gas** (not 21k); budget for it in scripts and sweeps. +3. **Calling Solana from Solidity (CPI — the differentiator).** Precompiles: **CPI `0xFF…08`**, **Helper `0xFF…09`**, **Withdraw `0x42…16`**. The account rules agents get wrong: the accounts array must be **non-empty**; the **operator and the program_id must NOT** appear in it; to sign as your contract use `HELPER.pda(address(this))` as the signer (the precompile signs as `msg.sender`, so a router contract cannot sign a *user's* PDA). Full ABI + per-selector billing: the precompile reference (docs). +4. **Never hardcode addresses — read the registry.** Chain ids, RPC URLs, contract addresses, token mints, and Solana program ids all come from **`@rome-protocol/registry`** (or the `rome-mcp` `getChain`/`getTokens`/`getContracts` tools). Hardcoded values drift and break across deploys. +5. **Test both lanes with a fresh wallet.** A feature must work on the EVM lane (MetaMask) *and* the Solana lane (Phantom). Verify each with a brand-new wallet and a tiny amount before claiming done. +6. **When a tx fails, use the taxonomy + the cross-VM map.** Rome surfaces specific failures (starved pool-payer rent, StateHolder rent, emulation-vs-simulation mismatches, nonce races). Match them against the error taxonomy (docs). To see the Solana settlement of a Rome tx, map it with `solanaTxForEvmTx`. + +## The SDK — `@rome-protocol/sdk` +The TypeScript SDK ([`rome-sdk-ts`](https://github.com/rome-protocol/rome-sdk-ts)) is your write path and your CPI toolkit: `submitRomeTx` + fee sizing, PDA/ATA derivation, CPI `invoke`/`invoke_signed` encoders, precompile bindings, and a `/bridge` module. Use it for every write and every Solana-from-Solidity call rather than hand-rolling calldata. ## Live tools for your agent > **Shipping with the Rome docs release** — the `rome-mcp` server and the `doctor` self-check below are being published alongside the docs site and are not on npm yet. Until then, read the registry directly via `@rome-protocol/registry` and verify manually (see below). diff --git a/README.md b/README.md index eab39bb..8291dae 100644 --- a/README.md +++ b/README.md @@ -132,3 +132,6 @@ The AMM programs, EVM routers, and frontend deploy via the standard Rome flow. T ## Provenance The AMM core forks **[`spl-token-swap`](https://github.com/solana-labs/solana-program-library/tree/master/token-swap)** (Solana Labs, Apache-2.0). We keep the curve/fee math and add the parity layer — authority-agnostic instructions, an account-lean + ALT-friendly layout for a cheap EVM lane, `CreatePool` (no ephemeral signers, so the EVM lane can create pools), exact-out, and the dual-lane SDK/UI. The x·y=k curve is not the novel part — the two-lane parity layer is. See `LICENSE` + `NOTICE`. + +## Building on Rome with an agent +See [`AGENTS.md`](./AGENTS.md) — the Rome-specific rules a coding agent needs.