diff --git a/docs.json b/docs.json index cca526a2f..9c81a5636 100644 --- a/docs.json +++ b/docs.json @@ -38,9 +38,89 @@ ] }, "redirects": [ + { + "source": "/evm/next/documentation/smart-contracts/precompiles", + "destination": "/evm/next/documentation/smart-contracts/precompiles/overview" + }, + { + "source": "/evm/next/documentation/smart-contracts/introduction", + "destination": "/evm/next/documentation/evm-compatibility" + }, { "source": "/sdk/v0.53/build/spec/addresses/addresses", "destination": "/sdk/v0.53/build/spec/addresses/bech32" + }, + { + "source": "/evm/next/documentation/concepts/predeployed-contracts", + "destination": "/evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts" + }, + { + "source": "/evm/next/documentation/smart-contracts/predeployed-contracts/overview", + "destination": "/evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts" + }, + { + "source": "/evm/next/documentation/smart-contracts/predeployed-contracts/create2", + "destination": "/evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts" + }, + { + "source": "/evm/next/documentation/smart-contracts/predeployed-contracts/multicall3", + "destination": "/evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts" + }, + { + "source": "/evm/next/documentation/smart-contracts/predeployed-contracts/permit2", + "destination": "/evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts" + }, + { + "source": "/evm/next/documentation/smart-contracts/predeployed-contracts/safe-factory", + "destination": "/evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts" + }, + { + "source": "/evm/next/documentation/evm-compatibility/overview", + "destination": "/evm/next/documentation/evm-compatibility" + }, + { + "source": "/evm/next/documentation/evm-compatibility/eip-reference", + "destination": "/evm/next/documentation/evm-compatibility" + }, + { + "source": "/evm/next/documentation/evm-compatibility/eip-2935", + "destination": "/evm/next/documentation/evm-compatibility" + }, + { + "source": "/evm/next/documentation/evm-compatibility/eip-7702", + "destination": "/evm/next/documentation/evm-compatibility" + }, + { + "source": "/evm/next/documentation/getting-started/tooling-and-resources/overview", + "destination": "/evm/next/documentation/getting-started/tooling-and-resources" + }, + { + "source": "/evm/next/documentation/getting-started/tooling-and-resources/hardhat", + "destination": "/evm/next/documentation/getting-started/tooling-and-resources" + }, + { + "source": "/evm/next/documentation/getting-started/tooling-and-resources/foundry", + "destination": "/evm/next/documentation/getting-started/tooling-and-resources" + }, + { + "source": "/evm/next/documentation/getting-started/tooling-and-resources/remix", + "destination": "/evm/next/documentation/getting-started/tooling-and-resources" + }, + { + "source": "/evm/next/documentation/getting-started/tooling-and-resources/testing-and-fuzzing", + "destination": "/evm/next/documentation/getting-started/tooling-and-resources" + }, + { + "source": "/evm/next/documentation/getting-started/tooling-and-resources/wallet-integration", + "destination": "/evm/next/documentation/getting-started/tooling-and-resources" + }, + { + "source": "/evm/next/documentation/getting-started/tooling-and-resources/block-explorers", + "destination": "/evm/next/documentation/getting-started/tooling-and-resources" + }, + { + "source": "/evm/next/documentation/getting-started/tooling-and-resources/development-environment", + "destination": "/evm/next/documentation/getting-started/tooling-and-resources" } ], "integrations": { @@ -1473,61 +1553,33 @@ "tab": "Documentation", "groups": [ { - "group": "Cosmos EVM", + "group": "About", "pages": [ "evm/next/documentation/overview", + "evm/next/documentation/evm-compatibility", + "evm/next/documentation/getting-started/faq" + ] + }, + { + "group": "Build", + "pages": [ + "evm/next/documentation/getting-started/build-a-chain/quick-start", { - "group": "Getting Started", - "pages": [ - { - "group": "Build Your Own Chain", - "pages": [ - "evm/next/documentation/getting-started/build-a-chain/overview", - "evm/next/documentation/getting-started/build-a-chain/quick-start", - { - "group": "Additional Configuration", - "pages": [ - "evm/next/documentation/getting-started/build-a-chain/additional-configuration/mempool-integration", - "evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts" - ] - } - ] - }, - "evm/next/documentation/getting-started/faq" - ] - }, - { - "group": "Tooling and Resources", - "pages": [ - "evm/next/documentation/getting-started/tooling-and-resources/overview", - "evm/next/documentation/getting-started/tooling-and-resources/development-environment", - "evm/next/documentation/getting-started/tooling-and-resources/block-explorers", - "evm/next/documentation/getting-started/tooling-and-resources/foundry", - "evm/next/documentation/getting-started/tooling-and-resources/hardhat", - "evm/next/documentation/getting-started/tooling-and-resources/remix", - "evm/next/documentation/getting-started/tooling-and-resources/testing-and-fuzzing", - "evm/next/documentation/getting-started/tooling-and-resources/wallet-integration" - ] - }, - { - "group": "Migrations", - "pages": [ - "evm/next/documentation/migrations/upgrade-handlers", - "evm/next/documentation/migrations/add-evm-to-existing-chain", - "evm/next/documentation/migrations/migration-v0.3-to-v0.4", - "evm/next/documentation/migrations/migration-v0.4-to-v0.5", - "evm/next/documentation/migrations/erc20-precompiles-migration" - ] - }, - { - "group": "EVM Compatibility", + "group": "Additional Configuration", + "expanded": true, "pages": [ - "evm/next/documentation/evm-compatibility/overview", - "evm/next/documentation/evm-compatibility/eip-reference", - "evm/next/documentation/evm-compatibility/eip-2935", - "evm/next/documentation/evm-compatibility/eip-7702" + "evm/next/documentation/getting-started/build-a-chain/additional-configuration/mempool-integration", + "evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts", + "evm/next/documentation/getting-started/build-a-chain/additional-configuration/precompiles", + "evm/next/documentation/getting-started/network-operators/node-configuration" ] }, + "evm/next/documentation/getting-started/tooling-and-resources" + ] + }, + { + "group": "Learn", + "pages": [ { "group": "Concepts", "pages": [ @@ -1545,46 +1597,27 @@ "evm/next/documentation/concepts/single-token-representation", "evm/next/documentation/concepts/tokens", "evm/next/documentation/concepts/transactions", - "evm/next/documentation/concepts/predeployed-contracts", "evm/next/documentation/concepts/eip-1559-feemarket", "evm/next/documentation/concepts/precision-handling" ] }, { - "group": "Smart Contracts", - "pages": [ - "evm/next/documentation/smart-contracts/introduction", - { - "group": "Precompiles", - "pages": [ - "evm/next/documentation/smart-contracts/precompiles/index", - "evm/next/documentation/smart-contracts/precompiles/overview", - "evm/next/documentation/smart-contracts/precompiles/bank", - "evm/next/documentation/smart-contracts/precompiles/bech32", - "evm/next/documentation/smart-contracts/precompiles/callbacks", - "evm/next/documentation/smart-contracts/precompiles/distribution", - "evm/next/documentation/smart-contracts/precompiles/erc20", - "evm/next/documentation/smart-contracts/precompiles/governance", - "evm/next/documentation/smart-contracts/precompiles/ics20", - "evm/next/documentation/smart-contracts/precompiles/p256", - "evm/next/documentation/smart-contracts/precompiles/slashing", - "evm/next/documentation/smart-contracts/precompiles/staking", - "evm/next/documentation/smart-contracts/precompiles/werc20" - ] - }, - { - "group": "Predeployed Contracts", - "pages": [ - "evm/next/documentation/smart-contracts/predeployed-contracts/overview", - "evm/next/documentation/smart-contracts/predeployed-contracts/create2", - "evm/next/documentation/smart-contracts/predeployed-contracts/multicall3", - "evm/next/documentation/smart-contracts/predeployed-contracts/permit2", - "evm/next/documentation/smart-contracts/predeployed-contracts/safe-factory" - ] - } + "group": "Precompiles", + "pages": [ + "evm/next/documentation/smart-contracts/precompiles/overview", + "evm/next/documentation/smart-contracts/precompiles/bank", + "evm/next/documentation/smart-contracts/precompiles/bech32", + "evm/next/documentation/smart-contracts/precompiles/callbacks", + "evm/next/documentation/smart-contracts/precompiles/distribution", + "evm/next/documentation/smart-contracts/precompiles/erc20", + "evm/next/documentation/smart-contracts/precompiles/governance", + "evm/next/documentation/smart-contracts/precompiles/ics20", + "evm/next/documentation/smart-contracts/precompiles/p256", + "evm/next/documentation/smart-contracts/precompiles/slashing", + "evm/next/documentation/smart-contracts/precompiles/staking", + "evm/next/documentation/smart-contracts/precompiles/werc20" ] }, - "evm/next/documentation/custom-improvement-proposals", { "group": "Cosmos SDK", "pages": [ @@ -1604,6 +1637,22 @@ ] } ] + }, + { + "group": "Migrations", + "pages": [ + { + "group": "Upgrade Guides", + "pages": [ + "evm/next/documentation/migrations/upgrade-handlers", + "evm/next/documentation/migrations/add-evm-to-existing-chain", + "evm/next/documentation/migrations/migration-v0.3-to-v0.4", + "evm/next/documentation/migrations/migration-v0.4-to-v0.5", + "evm/next/documentation/migrations/erc20-precompiles-migration" + ] + }, + "evm/next/documentation/custom-improvement-proposals" + ] } ] }, diff --git a/evm/next/api-reference/ethereum-json-rpc/methods.mdx b/evm/next/api-reference/ethereum-json-rpc/methods.mdx index e3849704a..c4d5c9dbc 100644 --- a/evm/next/api-reference/ethereum-json-rpc/methods.mdx +++ b/evm/next/api-reference/ethereum-json-rpc/methods.mdx @@ -309,7 +309,7 @@ Block Number can be entered as a Hex string, `"earliest"`, `"latest"` or `"pendi * `personal_unlockAccount` - Always returns false * `debug_traceTransaction` - Has issues with block height -For more details on how Cosmos EVM differs from standard Ethereum implementations, see [Differences from Standard EVMs](/evm/next/documentation/evm-compatibility/overview). +For more details on how Cosmos EVM differs from standard Ethereum implementations, see [Differences from Standard EVMs](/evm/next/documentation/evm-compatibility). ## Examples diff --git a/evm/next/documentation/concepts/mempool.mdx b/evm/next/documentation/concepts/mempool.mdx index c5af91878..8e9d96c8c 100644 --- a/evm/next/documentation/concepts/mempool.mdx +++ b/evm/next/documentation/concepts/mempool.mdx @@ -29,7 +29,7 @@ Transactions submitted via JSON-RPC or P2P are received by CometBFT and validate **Nonce Gap Detection**: Transactions with future nonces are intercepted and queued locally: ```go -if errors.Is(err, ErrNonceGap) { +if errors.Is(err, ErrNonceGap) || errors.Is(err, ErrNonceLow) { // Queue locally, don't broadcast err := mempool.InsertInvalidNonce(request.Tx) } @@ -68,6 +68,21 @@ Two-tiered approach: **ExperimentalEVMMempool**: Unified structure managing both EVM and Cosmos transaction pools with single interface for insertion, selection, and removal. +### Transaction Type Routing + +**Ethereum transactions (`MsgEthereumTx`)**: Routed to the EVM TxPool, which handles nonce gaps, promotion, and eviction. Executable transactions are then broadcast via CometBFT P2P. + +**Cosmos transactions (bank, staking, gov, etc.)**: Routed directly to a `PriorityNonceMempool` using fee-based prioritization. Priority is calculated as `fee_amount / gas_limit` in the EVM coin denom. + +### Unified Block Selection + +During block building, EVM and Cosmos transactions compete for inclusion based on their effective tip: + +- **EVM**: `min(gas_tip_cap, gas_fee_cap - base_fee)` +- **Cosmos**: `fee_amount / gas_limit` + +Higher effective tip is selected first regardless of transaction type. + ### Transaction States **Queued (Local Storage)**: Transactions with nonce > expected nonce diff --git a/evm/next/documentation/concepts/predeployed-contracts.mdx b/evm/next/documentation/concepts/predeployed-contracts.mdx deleted file mode 100644 index 4e41f6753..000000000 --- a/evm/next/documentation/concepts/predeployed-contracts.mdx +++ /dev/null @@ -1,115 +0,0 @@ ---- -title: "Predeployed Contracts" -description: "Understanding predeployed contracts - what they are, why they're used, and how they differ from precompiles" -icon: "package" -keywords: ['predeployed', 'preinstalls', 'theory', 'concept', 'comparison', 'precompiles'] ---- - -## What Are Predeployed Contracts? - -Predeployed contracts (also called preinstalls) are regular EVM smart contracts with their bytecode deployed at predetermined addresses, either at chain genesis or through governance mechanisms. Unlike precompiles which are native Go implementations built into the chain binary, predeployed contracts: - -- Contain actual EVM bytecode that can be executed by the EVM -- Consume gas like any regular smart contract -- Can be verified on block explorers -- Are immutable once deployed (no upgrades possible) - -## Why Use Predeployed Contracts? - -Predeployed contracts represent a fundamental pattern in EVM-based chains that provides several key advantages: - -### Standardization -By deploying essential contracts at known addresses, chains ensure compatibility with existing Ethereum tooling and libraries that expect these contracts at specific locations. - -### Developer Experience -Developers don't need to deploy their own versions of common utilities, saving deployment costs and reducing complexity. - -### Cross-chain Consistency -Using the same addresses across different chains enables easier multi-chain development and deployment strategies. - -### Ecosystem Alignment -Many tools, wallets, and dApps in the Ethereum ecosystem expect certain contracts (like Multicall3) at specific addresses. - -## Comparison with Precompiles - -Understanding the distinction between predeployed contracts and precompiles is crucial for choosing the right approach for your implementation: - -| Aspect | Predeployed Contracts | Precompiles | -|--------|----------------------|-------------| -| **Implementation** | EVM bytecode stored on-chain | Native Go code in chain binary | -| **Gas Costs** | Standard EVM gas pricing | Custom, typically lower gas costs | -| **Deployment** | Must be explicitly deployed | Always available when enabled | -| **Upgradeability** | Immutable once deployed | Can be modified via chain upgrades | -| **Verification** | Verifiable on block explorers | Source not visible on-chain | -| **Address Range** | Any valid address | Special range (0x1-0x9FF) | -| **Storage** | Uses regular contract storage | Can access native Cosmos state | - -## When to Choose Predeployed Contracts - -Use predeployed contracts when: -- You need standard Ethereum contracts at expected addresses -- Full EVM compatibility is required -- Contract source verification is important -- The functionality doesn't require native chain integration - -Use precompiles when: -- You need optimized gas costs for frequently used operations -- Direct access to Cosmos SDK state is required -- The functionality requires native chain features -- Upgradeability through chain upgrades is needed - -## Configuration - -### Genesis Configuration - -Predeployed contracts are configured during chain genesis through the `preinstalls` parameter in the VM module. This defines which contracts are deployed at specific addresses during network initialization. - -```json "Genesis Preinstalls Configuration" expandable -{ - "app_state": { - "vm": { - "preinstalls": [ - { - "address": "0x4e59b44847b379578588920ca78fbf26c0b4956c", - "code": "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3", - "name": "Create2" - }, - { - "address": "0xcA11bde05977b3631167028862bE2a173976CA11", - "code": "0x6080604052...", // Full Multicall3 bytecode - "name": "Multicall3" - } - ] - } - } -} -``` - - -The default preinstalls are defined in the codebase at [`x/vm/types/preinstall.go:13-39`](https://github.com/cosmos/evm/blob/main/x/vm/types/preinstall.go#L13-L39). For complete guidance on customizing preinstalls, see: -- [Building Your Chain Guide](/evm/next/documentation/getting-started/build-a-chain/overview#configuring-predeployed-contracts) - Quick start configuration -- [Predeployed Contracts Integration](/evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts) - Detailed implementation guide - - -## Common Examples - -The Cosmos EVM includes several default predeployed contracts (defined in [`evmtypes.DefaultPreinstalls`](https://github.com/cosmos/evm/blob/main/x/vm/types/preinstall.go#L13-L39)): - -- **Create2** (`0x4e59b44847b379578588920ca78fbf26c0b4956c`): Deterministic contract deployment - [Documentation](/evm/next/documentation/smart-contracts/predeployed-contracts/create2) -- **Multicall3** (`0xcA11bde05977b3631167028862bE2a173976CA11`): Batch multiple calls in one transaction - [Documentation](/evm/next/documentation/smart-contracts/predeployed-contracts/multicall3) -- **Permit2** (`0x000000000022D473030F116dDEE9F6B43aC78BA3`): Universal token approval system - [Documentation](/evm/next/documentation/smart-contracts/predeployed-contracts/permit2) -- **Safe Factory** (`0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7`): Deploy Safe multisig wallets - [Documentation](/evm/next/documentation/smart-contracts/predeployed-contracts/safe-factory) -- **EIP-2935** (`0x0b`): Historical block hash storage (system contract) - -For comprehensive information on each contract including usage examples and integration patterns, see the [Predeployed Contracts Overview](/evm/next/documentation/smart-contracts/predeployed-contracts/overview). - -## Related Concepts - -- [Precompiles](/evm/next/documentation/smart-contracts/precompiles/overview) - Native chain implementations exposed as smart contracts -- [VM Module](evm/next/documentation/cosmos-sdk/modules/vm) - Core EVM module configuration including preinstalls -- [Building Your Chain](/evm/next/documentation/getting-started/build-a-chain/overview) - Complete guide to chain setup - -## Implementation Guides - -- [Predeployed Contracts Integration](/evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts) - Detailed technical guide for deploying and managing preinstalled contracts -- [Individual Contract Documentation](/evm/next/documentation/smart-contracts/predeployed-contracts/overview) - Usage examples and integration patterns for each contract \ No newline at end of file diff --git a/evm/next/documentation/cosmos-sdk/modules/erc20.mdx b/evm/next/documentation/cosmos-sdk/modules/erc20.mdx index 13afd1acc..a90bfcf81 100644 --- a/evm/next/documentation/cosmos-sdk/modules/erc20.mdx +++ b/evm/next/documentation/cosmos-sdk/modules/erc20.mdx @@ -523,7 +523,7 @@ evmd tx erc20 register-coin --from mykey ## Related Documentation - [Building Your Chain Guide](/evm/next/documentation/getting-started/build-a-chain/overview) - Main configuration walkthrough -- [VM Module](evm/next/documentation/cosmos-sdk/modules/vm) - EVM configuration +- [VM Module](/evm/next/documentation/cosmos-sdk/modules/vm) - EVM configuration - [IBC Module](/evm/next/documentation/cosmos-sdk/modules/ibc) - IBC token handling --- diff --git a/evm/next/documentation/evm-compatibility.mdx b/evm/next/documentation/evm-compatibility.mdx new file mode 100644 index 000000000..65bda08d0 --- /dev/null +++ b/evm/next/documentation/evm-compatibility.mdx @@ -0,0 +1,177 @@ +--- +title: "EVM Compatibility" +keywords: ['differences', 'ethereum', 'evm', 'cosmos', 'CometBFT', 'consensus', 'finality', 'json-rpc', 'compatibility', 'precompiles', 'ibc', 'mev', 'gas', 'basefee', 'reorganization', 'bft', 'validator', 'staking'] +--- + +Cosmos EVM provides full Ethereum compatibility for Cosmos SDK chains. Existing contracts, tools, and workflows run without modification: deploy Solidity contracts, connect MetaMask, and use the same libraries and frameworks you already know. + +## Solidity Smart Contracts + +The Cosmos EVM smart contract development flow is identical to the flow on Ethereum. Contracts that work on Ethereum work on Cosmos EVM without code changes. The same tools, the same Solidity, the same patterns. + +### Development + +Write Solidity using [Hardhat](https://hardhat.org), [Foundry](https://book.getfoundry.sh), or [Remix](https://remix.ethereum.org) with no custom configuration needed. Point your tooling at your chain's JSON-RPC endpoint and chain ID and you're set. See the [tooling overview](/evm/next/documentation/getting-started/tooling-and-resources) for a full list of supported tools, and the [quick-start guide](/evm/next/documentation/getting-started/build-a-chain/quick-start#deploy-a-solidity-contract-with-forge) for a step-by-step contract deployment walkthrough. + +### Deployment + +[Deploy using standard Ethereum tools](/evm/next/documentation/getting-started/build-a-chain/quick-start#deploy-a-solidity-contract-with-forge) by pointing them at your chain's RPC endpoint. Deployment transactions go through the JSON-RPC or Cosmos gRPC interface and are processed by the EVM module. Once deployed, contract bytecode is stored in chain state and callable at its Ethereum address like any other chain. + +### Upgrading + +Cosmos EVM supports all standard EVM upgrade patterns: + +- **Proxy patterns (EIP-1967, Transparent Proxy, UUPS)**: Delegate calls to an implementation contract. Upgrading means swapping the implementation address in the proxy without touching the proxy's storage or address. +- **Diamond pattern (EIP-2535)**: Modular contracts split into "facets" that can be added, replaced, or removed independently. The diamond routes calls to the appropriate facet, enabling granular upgrades without redeploying the whole contract. + +Any upgrade architecture that works on Ethereum works on Cosmos EVM. + +## Supported Standards + +**Cosmos EVM supports all standard EVM opcodes, EIPs, and ERC token interfaces** up to the Prague hard fork. + +### EIPs + +The following are notable supported EIPs; the full list is [much longer](https://eips.ethereum.org/all). + +| EIP | Name | Purpose | +|-----|------|---------| +| [EIP-155](https://eips.ethereum.org/EIPS/eip-155) | Replay Protection | Chain ID in signatures prevents cross-chain replay attacks | +| [EIP-712](https://eips.ethereum.org/EIPS/eip-712) | Typed Structured Data Signing | Sign structured data, human-readable messages, and custom Cosmos transactions | +| [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) | Dynamic Fees | Base fee + priority fee model; base fee is distributed to validators rather than burned | +| [EIP-2535](https://eips.ethereum.org/EIPS/eip-2535) | Diamond Standard | Proxy pattern for upgradeable contracts with multiple implementation facets | +| [EIP-2935](https://eips.ethereum.org/EIPS/eip-2935) | Historical Block Hashes | `BLOCKHASH` opcode provides access to up to 8192 previous block hashes (configurable) | +| [EIP-4337](https://eips.ethereum.org/EIPS/eip-4337) | Account Abstraction | Smart contract wallets can pay fees, batch transactions, and use custom auth schemes | +| [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) | Set Code for EOA | Temporarily assigns contract code to an EOA for sponsored transactions and complex auth | + +### ERCs + +Any ERC standard that runs on the EVM is compatible with Cosmos EVM. The most commonly used are: + +- **[ERC-20](https://eips.ethereum.org/EIPS/eip-20) — Fungible Tokens:** Standard interface for currency representations with transfer, approval, and allowance mechanisms. +- **[ERC-721](https://eips.ethereum.org/EIPS/eip-721) — Non-Fungible Tokens:** Standard for unique asset identifiers, digital certificates, or proof of ownership records. +- **[ERC-1155](https://eips.ethereum.org/EIPS/eip-1155) — Multi-Token Standard:** Supports both fungible and non-fungible assets in a single contract, enabling batch operations and reduced deployment costs for complex asset systems. + +### Opcodes + +Cosmos EVM supports **all EVM opcodes up to the Prague hard fork**. For the full reference, see [evm.codes](https://www.evm.codes/). + +The following are **not supported**: + +- **[EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) — Blob-Carrying Transactions:** Blob data and L2-specific functionality. +- **[EIP-4399](https://eips.ethereum.org/EIPS/eip-4399) — PREVRANDAO:** The replacement of the `DIFFICULTY` opcode with `PREVRANDAO`. + +## Tooling + +Any tool that connects to a standard Ethereum JSON-RPC endpoint works with Cosmos EVM without custom configuration. + +| Tool | Category | +|------|----------| +| [Hardhat](https://hardhat.org), [Foundry](https://book.getfoundry.sh), [Remix](https://remix.ethereum.org) | Contract development | +| [OpenZeppelin Contracts](https://docs.openzeppelin.com/contracts) | Smart contract libraries | +| [Forge](https://book.getfoundry.sh/forge/), [Hardhat](https://hardhat.org) | Testing & fuzzing | +| [MetaMask](https://metamask.io), [WalletConnect](https://walletconnect.com), [Rabby](https://rabby.io) | Wallets | +| [ethers.js](https://docs.ethers.org/v6/), [viem](https://viem.sh), [web3.js](https://web3js.org), [wagmi](https://wagmi.sh) | JavaScript libraries | +| [Blockscout](https://github.com/blockscout/blockscout) | Block explorer | + +### JSON-RPC + +The JSON-RPC interface implements the full Ethereum spec. Point any standard tool at your chain's RPC endpoint and it works. + + + Most standard Ethereum JSON-RPC methods are supported, with some returning stub values for compatibility. View the complete reference. + + +All standard transaction, query, and subscription methods work as expected — `eth_sendRawTransaction`, `eth_call`, `eth_estimateGas`, event logs and filters, WebSocket subscriptions, and the debug namespace for tracing. + +A few things to know: +- `eth_gasPrice` returns 0 — use EIP-1559 fee fields instead +- Mining-related methods don't apply (consensus is handled by CometBFT) +- `txpool` methods require the experimental mempool to be enabled + +## Beyond Ethereum + +Cosmos EVM adds capabilities on top of full Ethereum compatibility. None of these change how existing contracts or tooling behave. + +| Area | Ethereum | Cosmos EVM | +|------|----------|------------| +| **Block time** | ~12 seconds | 1–2 seconds | +| **Finality** | 12+ blocks (~3 min) | 1 block (~2 seconds) | +| **Reorganizations** | Possible | Not possible | +| **Cross-chain** | Bridge protocols | Native IBC | +| **Fee distribution** | Base fee burned | Distributed to validators | + +### Finality + +Cosmos EVM transactions are final after one block (~2 seconds) via CometBFT consensus—no waiting for confirmations, no reorganizations possible. The validator set requires 2/3+ stake agreement for any block to be committed. + +### Gas & fees + +Cosmos EVM uses EIP-1559 dynamic fees. Unlike Ethereum, the base fee is distributed to validators and delegators rather than burned. The base fee can also be disabled entirely via the `NoBaseFee` parameter, and a chain-wide minimum gas price floor is configurable. + +### Address system + +Every account has two representations that reference the same underlying key: + +``` +Ethereum: 0x742d35cc6644c068532fddb11B4C36A58D6D3eAb +Cosmos: cosmos1wskntvnryr5qxpe4tv5k64rhc6kx6ma4dxjmav +``` + +### Chain IDs + +Cosmos EVM uses two independent chain IDs: a Cosmos Chain ID (string, e.g. `cosmosevm-1`) and an EVM Chain ID (integer, e.g. `9000`). These are configured separately, unlike legacy Ethermint where the format was coupled. + +### Precompiled Contracts + + + + Full list of built-in Cosmos precompiles and their addresses. + + + Enable built-in precompiles or add your own to your chain. + + + +All standard Ethereum cryptographic precompiles (ecrecover, sha256, etc.) are also supported; visit [evm.codes/precompiled](https://www.evm.codes/precompiled) for the full reference. + +### Predeployed Contracts + +Cosmos EVM ships with standard EVM infrastructure contracts already in chain state at their canonical addresses — Create2, Multicall3, Permit2, Safe Singleton Factory, and EIP-2935 block hash storage. Any tooling that depends on these contracts at their well-known addresses works without extra setup. + + + Learn which contracts are preinstalled and how to preinstall contracts at genesis. + + +#### Key Precompile Addresses + +| Function | Address | +|----------|---------| +| **Staking** | `0x0000000000000000000000000000000000000800` | +| **Distribution** | `0x0000000000000000000000000000000000000801` | +| **IBC Transfer** | `0x0000000000000000000000000000000000000802` | +| **Bank** | `0x0000000000000000000000000000000000000804` | +| **Governance** | `0x0000000000000000000000000000000000000805` | + +### Performance + +Cosmos EVM gas estimation is optimized: plain ETH transfers return 21000 immediately without simulation, and complex transactions use initial execution results to tighten the binary search bounds, making `eth_estimateGas` significantly faster across the board. + +The Cosmos EVM mempool follows standard Ethereum behavior (gas price + nonce ordering, multiple transactions per account per block). Pool limits, timeouts, and priority functions are [configurable per chain](/evm/next/documentation/getting-started/build-a-chain/additional-configuration/mempool-integration). An optional experimental mempool adds nonce gap handling and automatic transaction promotion. + +## Resources + + + + Deploy a chain and your first contract end-to-end. + + + Full list of supported tools, libraries, and frameworks. + + + Built-in Cosmos precompiles and their addresses. + + + Standard EVM contracts available at genesis. + + diff --git a/evm/next/documentation/evm-compatibility/eip-2935.mdx b/evm/next/documentation/evm-compatibility/eip-2935.mdx deleted file mode 100644 index 8a43e4f2e..000000000 --- a/evm/next/documentation/evm-compatibility/eip-2935.mdx +++ /dev/null @@ -1,289 +0,0 @@ ---- -title: "EIP-2935: Historical Block Hash Storage" -description: "Implementation of EIP-2935 for reliable historical block hash access in smart contracts" ---- - -EIP-2935 provides standardized access to historical block hashes through contract storage, enabling smart contracts to reliably access block hashes beyond the traditional 256-block limit. - -## Overview - -### What is EIP-2935? - -EIP-2935 introduces a system contract that stores block hashes in contract storage, making them accessible to smart contracts for extended periods. This enables protocols requiring verifiable randomness, block-based logic, or historical verification. - -### Key Benefits - -- **Extended History:** Access up to 8192 block hashes (configurable) -- **Reliable Access:** No longer limited to recent 256 blocks -- **Smart Contract Compatibility:** Works with existing `BLOCKHASH` opcode -- **Verifiable Randomness:** Enable protocols requiring historical entropy - -## Implementation Details - -### Block Hash Storage Mechanism - -Cosmos EVM implements EIP-2935 by storing block hashes in a special system contract storage: - -``` -Contract Address: 0x0aae40965e6800cd9b1f4b05ff21581047e3f91e (EIP-2935 system contract) -Storage Layout: block_number % HISTORY_SERVE_WINDOW → block_hash -``` - -### Configuration Parameter - -The `history_serve_window` parameter controls how many historical block hashes are stored: - -```json -{ - "vm": { - "params": { - "history_serve_window": 8192 // Default: 8192 blocks - } - } -} -``` - -**Parameter Details:** -- **Type:** `uint64` -- **Default:** `8192` ([source](https://github.com/cosmos/evm/blob/main/x/vm/types/params.go#L46)) -- **Range:** Must be > 0, recommended ≤ 8192 -- **Storage Impact:** Higher values increase storage requirements linearly - -## Comparison with Ethereum - -### Similarities - -- **Same storage contract address:** `0x0aae40965e6800cd9b1f4b05ff21581047e3f91e` -- **Same storage layout:** Ring buffer using modulo arithmetic -- **Same opcode behavior:** `BLOCKHASH` queries contract storage -- **Same gas costs:** Standard SLOAD costs apply (2100 gas for cold access) - -### Differences - -- **Configurable window:** Cosmos EVM allows custom `history_serve_window` (vs fixed 8192 in Ethereum) -- **Instant activation:** Available immediately on upgrade (not block-based activation) -- **No fork logic:** Uses consensus parameter instead of fork activation -- **Performance tuning:** Can be optimized per chain requirements -- **Traditional 256-block limit:** Ethereum's original `BLOCKHASH` opcode only provided access to the most recent 256 blocks; EIP-2935 extends this significantly - -## Usage in Smart Contracts - -### Basic Block Hash Access - -```solidity Basic Block Hash Access expandable -pragma solidity ^0.8.0; - -contract BlockHashExample { - function getRecentBlockHash(uint256 blockNumber) - external - view - returns (bytes32) - { - // Works for blocks within history_serve_window range - return blockhash(blockNumber); - } - - function getCurrentBlockNumber() external view returns (uint256) { - return block.number; - } - - function getHistoricalRange() external view returns (uint256) { - // Can access block hashes for last 8192 blocks (default) - return 8192; - } -} -``` - -### Verifiable Randomness Protocol - -```solidity Verifiable Randomness Protocol expandable -contract VerifiableRandomness { - struct RandomnessCommit { - bytes32 blockHash; - uint256 blockNumber; - uint256 timestamp; - bool revealed; - } - - mapping(bytes32 => RandomnessCommit) public commits; - - function commitRandomness(bytes32 commitment) external { - // Commit to using future block hash as randomness source - uint256 revealBlock = block.number + 10; // Reveal 10 blocks later - - commits[commitment] = RandomnessCommit({ - blockHash: bytes32(0), // Will be filled during reveal - blockNumber: revealBlock, - timestamp: block.timestamp, - revealed: false - }); - } - - function revealRandomness( - bytes32 commitment, - uint256 nonce - ) external returns (bytes32 randomness) { - RandomnessCommit storage commit = commits[commitment]; - require(!commit.revealed, "Already revealed"); - require(block.number >= commit.blockNumber, "Too early to reveal"); - - // Get block hash from historical storage (EIP-2935) - bytes32 blockHash = blockhash(commit.blockNumber); - require(blockHash != bytes32(0), "Block hash not available"); - - commit.blockHash = blockHash; - commit.revealed = true; - - // Generate verifiable randomness - randomness = keccak256(abi.encodePacked( - blockHash, - commitment, - nonce - )); - - return randomness; - } -} -``` - -### Block-Based State Transitions - -```solidity Block-Based State Transitions expandable -contract BlockBasedLogic { - uint256 public constant EPOCH_LENGTH = 1000; // blocks - mapping(uint256 => bytes32) public epochSeeds; - - function updateEpochSeed() external { - uint256 currentEpoch = block.number / EPOCH_LENGTH; - - if (epochSeeds[currentEpoch] == bytes32(0)) { - // Use block hash from start of epoch as seed - uint256 epochStartBlock = currentEpoch * EPOCH_LENGTH; - bytes32 seedHash = blockhash(epochStartBlock); - - require(seedHash != bytes32(0), "Epoch seed block not available"); - epochSeeds[currentEpoch] = seedHash; - } - } - - function getEpochSeed(uint256 epoch) external view returns (bytes32) { - return epochSeeds[epoch]; - } -} -``` - -## Configuration Examples - -### High Compatibility (Default) - -```json -{ - "vm": { - "params": { - "history_serve_window": 8192 - } - } -} -``` - -**Use Case:** Full EIP-2935 compatibility for protocols requiring extended block history -**Storage:** ~256KB additional storage (32 bytes × 8192 blocks) -**Performance:** Standard performance, suitable for most chains - -### Performance Optimized - -```json -{ - "vm": { - "params": { - "history_serve_window": 1024 - } - } -} -``` - -**Use Case:** Resource-constrained nodes or chains prioritizing performance -**Storage:** ~32KB additional storage (32 bytes × 1024 blocks) -**Trade-off:** Shorter historical access but better performance - -### Extended History - -```json -{ - "vm": { - "params": { - "history_serve_window": 16384 - } - } -} -``` - -**Use Case:** Protocols requiring very long historical access -**Storage:** ~512KB additional storage (32 bytes × 16384 blocks) -**Performance:** Higher storage overhead but maximum compatibility - -## Technical Implementation - -### BLOCKHASH Opcode Behavior - -**Before EIP-2935:** -``` -blockhash(n) → Returns hash only if (block.number - 257) < n < block.number - Returns 0x0 for older blocks -``` - -**After EIP-2935:** -``` -blockhash(n) → Returns hash if (block.number - history_serve_window) < n < block.number - Uses contract storage for historical hashes - Returns 0x0 only if outside window or invalid -``` - -### Storage Layout - -The EIP-2935 system contract uses a simple storage mapping: - -``` -Key: block_number % history_serve_window -Value: block_hash -``` - -**Example with history_serve_window = 8192:** -``` -Storage[0] = hash(block 0, 8192, 16384, ...) -Storage[1] = hash(block 1, 8193, 16385, ...) -... -Storage[8191] = hash(block 8191, 16383, 24575, ...) -``` - -### Integration with EVM - -The implementation integrates seamlessly with the EVM: - -1. **Block Processing:** Each new block stores its hash in the system contract -2. **BLOCKHASH Opcode:** Modified to query contract storage for historical hashes -3. **Gas Costs:** Uses standard SLOAD gas costs for historical access -4. **Compatibility:** Maintains full backward compatibility - -## Comparison with Ethereum - -### Similarities - -- **Same storage contract address:** `0x0aae40965e6800cd9b1f4b05ff21581047e3f91e` -- **Same storage layout:** Ring buffer using modulo arithmetic -- **Same opcode behavior:** `BLOCKHASH` queries contract storage -- **Same gas costs:** Standard SLOAD costs apply - -### Differences - -- **Configurable window:** Cosmos EVM allows custom `history_serve_window` -- **Instant activation:** Available immediately on upgrade (not block-based) -- **No fork logic:** Uses consensus parameter instead of fork activation -- **Performance tuning:** Can be optimized per chain requirements - -## References - -- **EIP-2935 Specification:** https://eips.ethereum.org/EIPS/eip-2935 -- **Implementation PR:** [cosmos/evm#407](https://github.com/cosmos/evm/pull/407) -- **System Contract Address:** `0x0aae40965e6800cd9b1f4b05ff21581047e3f91e` -- **Related Documentation:** [VM Module Parameters](../cosmos-sdk/modules/vm#parameters) \ No newline at end of file diff --git a/evm/next/documentation/evm-compatibility/eip-7702.mdx b/evm/next/documentation/evm-compatibility/eip-7702.mdx deleted file mode 100644 index 5c027ac19..000000000 --- a/evm/next/documentation/evm-compatibility/eip-7702.mdx +++ /dev/null @@ -1,367 +0,0 @@ ---- -title: "EIP-7702: Set EOA Code" -description: "Implementation of EIP-7702 for enabling externally owned accounts to execute smart contract code temporarily" ---- - -EIP-7702 allows externally owned accounts (EOAs) to delegate their code execution to smart contracts for the duration of a transaction. EOAs temporarily "borrow" code from smart contracts through signed authorizations, enabling account abstraction, batched operations, and enhanced wallet functionality. Code delegation only lasts for the transaction duration, maintaining EOA security while adding programmable capabilities. - -## Comparison with Ethereum - -### Similarities - -- **Same transaction structure:** SetCodeTx format with authorization lists -- **Same authorization signature format:** EIP-712 compatible signatures -- **Same nonce validation rules:** Authorization nonce must match account nonce -- **Same delegation bytecode format:** Standard delegation proxy pattern -- **Same gas cost parameters:** Standard EVM gas costs apply - -### Cosmos SDK Enhancements - -- **Instant Finality:** Delegations are final after one block (~2s) vs 12+ confirmations on Ethereum -- **Lower Gas Costs:** Typically much lower transaction costs than Ethereum mainnet -- **Enhanced Debugging:** Better error messages and transaction tracing -- **IBC Integration:** Delegated code can interact with IBC precompiles for cross-chain operations - -## Comparison with Account Abstraction - -### EIP-7702 vs EIP-4337 - -| Feature | EIP-7702 (Code Delegation) | EIP-4337 (Account Abstraction) | -|---------|---------------------------|--------------------------------| -| **Account Type** | Enhances existing EOAs | Requires new contract accounts | -| **Compatibility** | Works with all existing wallets | Requires AA-compatible wallets | -| **Gas Costs** | Standard transaction costs | Additional overhead for UserOps | -| **Complexity** | Simple authorization signatures | Complex bundler infrastructure | -| **Adoption Path** | Gradual EOA enhancement | New account creation required | - -### Use Case Comparison - -**EIP-7702 Strengths:** -- Enhances existing accounts without migration -- Lower complexity and gas costs -- Works with current wallet infrastructure -- Simpler developer experience - -**EIP-4337 Strengths:** -- More flexible validation logic -- Advanced features like social recovery -- Dedicated account abstraction infrastructure -- Better separation of concerns - -## Implementation Details - -### Transaction Structure - -### SetCodeTx Format - - -```go -// SetCodeTx transaction structure (EIP-7702 Type 4 transaction) -// This transaction type enables EOAs to temporarily delegate code execution -type SetCodeTx struct { - // Standard transaction fields - ChainID *uint256.Int // Chain ID for EIP-155 replay protection - Nonce uint64 // Account nonce (must be sequential) - GasTipCap *uint256.Int // Priority fee per gas (EIP-1559) - GasFeeCap *uint256.Int // Maximum fee per gas (EIP-1559) - Gas uint64 // Gas limit for transaction execution - To *common.Address // Recipient address (can be self for delegation) - Value *uint256.Int // ETH value to transfer - Data []byte // Contract call data to execute with delegated code - AccessList ethtypes.AccessList // EIP-2930 access list for gas optimization - - // EIP-7702 specific fields - AuthList []SetCodeAuthorization // List of code delegation authorizations - - // Transaction signature (signs entire transaction) - V *uint256.Int - R *uint256.Int - S *uint256.Int -} -``` - - -### Authorization Structure - - -```go -// SetCodeAuthorization enables an EOA to authorize code delegation -// Each authorization is separately signed and validated -type SetCodeAuthorization struct { - // Delegation parameters - ChainID uint256.Int // Target chain ID (0 = valid on any chain) - Address common.Address // Contract address to delegate code from - Nonce uint64 // Authority's current nonce (prevents replay) - - // Authorization signature (separate from transaction signature) - // Signs: keccak256(0x05 || rlp(chainId, contractAddress, nonce)) - V uint8 // Recovery ID - R *uint256.Int // Signature R value - S *uint256.Int // Signature S value -} - -// Delegation Bytecode Format (automatically generated) -// When delegation is active, the EOA's code becomes: -// 0xEF0100 + contractAddress (23 bytes total) -// - 0xEF01: Delegation marker (EIP-3541 compliance) -// - 0x00: Delegation version -// - contractAddress: 20 bytes of target contract -``` - - -**Source:** [`tests/integration/x/vm/state_transition_benchmark.go:47-55`](https://github.com/cosmos/evm/blob/main/tests/integration/x/vm/state_transition_benchmark.go#L47-55) - -## Usage Examples - - - - - -```javascript -// Example: Delegate EOA to execute multicall contract -// Source: Based on EIP-7702 specification examples -import { ethers } from "ethers"; - -async function createDelegatedMulticall() { - const wallet = new ethers.Wallet(privateKey, provider); - const multicallAddress = "0x..."; // Deployed multicall contract - - // Step 1: Create authorization for code delegation - const authorization = { - chainId: 9000, // Your Cosmos EVM chain ID - address: multicallAddress, // Contract to delegate code from - nonce: await wallet.getNonce(), // Current account nonce - }; - - // Step 2: Sign authorization (EIP-712 format) - const authSignature = await signAuthorization(authorization, wallet); - - // Step 3: Create SetCode transaction (Type 4) - const tx = { - type: 4, // SetCodeTxType - chainId: 9000, - nonce: authorization.nonce + 1, // Must increment after authorization - gasLimit: 500000, - gasFeeCap: ethers.parseUnits("20", "gwei"), - gasTipCap: ethers.parseUnits("1", "gwei"), - to: wallet.address, // Self-delegation - value: 0, - data: "0x", // No direct call data - accessList: [], - authorizationList: [{ - chainId: authorization.chainId, - address: authorization.address, - nonce: authorization.nonce, - v: authSignature.v, - r: authSignature.r, - s: authSignature.s, - }] - }; - - // Step 4: Send transaction - EOA executes as multicall contract - return await wallet.sendTransaction(tx); -} -``` - - - - - - -```solidity -// Custom account logic for enhanced EOA functionality -// Source: Account abstraction pattern for EIP-7702 -pragma solidity ^0.8.0; - -contract CustomAccountLogic { - // Custom state for account logic - mapping(address => uint256) public customNonces; - mapping(address => mapping(address => bool)) public authorizedSpenders; - - // Custom validation logic - function validateTransaction( - address sender, - bytes calldata signature, - bytes calldata txData - ) external view returns (bool) { - // Example: Multi-signature validation - // Example: Spending limit validation - // Example: Time-lock validation - - // Simplified validation - implement your custom logic - return true; - } - - // Custom execution logic - function executeTransaction( - address target, - uint256 value, - bytes calldata data - ) external returns (bool success, bytes memory result) { - // Pre-execution hooks - require(authorizedSpenders[tx.origin][target] || target == tx.origin, "Unauthorized target"); - - // Execute with custom logic - (success, result) = target.call{value: value}(data); - - // Post-execution hooks - customNonces[tx.origin]++; - - // Emit custom events - emit CustomTransaction(tx.origin, target, value, success); - - return (success, result); - } - - // Authorization management - function authorizeSpender(address spender) external { - authorizedSpenders[tx.origin][spender] = true; - } - - event CustomTransaction(address indexed account, address indexed target, uint256 value, bool success); -} -``` - - - - - - -```javascript -// Example: Batch multiple DeFi operations in one transaction -// Source: DeFi batching pattern using EIP-7702 -async function batchDeFiOperations() { - const batchExecutorAddress = "0x..."; // Deployed batch executor contract - - // Step 1: Authorization to use batch executor - const authorization = await signAuthorization({ - chainId: 9000, - address: batchExecutorAddress, - nonce: await wallet.getNonce(), - }, wallet); - - // Step 2: Encode batch operations - const operations = [ - // Operation 1: Approve token spending - { - target: tokenAddress, - callData: erc20Interface.encodeFunctionData("approve", [spenderAddress, amount]) - }, - // Operation 2: Stake tokens - { - target: stakingAddress, - callData: stakingInterface.encodeFunctionData("stake", [amount]) - }, - // Operation 3: Claim rewards - { - target: rewardsAddress, - callData: rewardsInterface.encodeFunctionData("claimRewards", []) - } - ]; - - // Step 3: Encode batch call data - const batchCallData = batchInterface.encodeFunctionData("executeBatch", [operations]); - - // Step 4: Create SetCode transaction - const tx = { - type: 4, - authorizationList: [authorization], - to: wallet.address, // Self-delegation - data: batchCallData, // Execute batch operations - gasLimit: 800000, // Higher gas for multiple operations - // ... other tx fields - }; - - return await wallet.sendTransaction(tx); -} -``` - - - - - - -```solidity -// Enhanced wallet functionality using EIP-7702 -// Source: Smart wallet pattern implementation -pragma solidity ^0.8.0; - -contract SmartWalletLogic { - struct SpendingLimit { - uint256 dailyLimit; - uint256 spentToday; - uint256 lastResetDay; - } - - mapping(address => SpendingLimit) public spendingLimits; - mapping(address => mapping(bytes32 => bool)) public executedTxHashes; - - // Enhanced wallet functions - function setDailySpendingLimit(uint256 limit) external { - spendingLimits[tx.origin] = SpendingLimit({ - dailyLimit: limit, - spentToday: 0, - lastResetDay: block.timestamp / 1 days - }); - } - - function executeWithLimits( - address target, - uint256 value, - bytes calldata data - ) external returns (bytes memory) { - // Check spending limits - SpendingLimit storage limit = spendingLimits[tx.origin]; - - // Reset daily counter if new day - uint256 currentDay = block.timestamp / 1 days; - if (currentDay > limit.lastResetDay) { - limit.spentToday = 0; - limit.lastResetDay = currentDay; - } - - // Enforce spending limit - require(limit.spentToday + value <= limit.dailyLimit, "Daily spending limit exceeded"); - - // Execute transaction - (bool success, bytes memory result) = target.call{value: value}(data); - require(success, "Transaction execution failed"); - - // Update spent amount - limit.spentToday += value; - - return result; - } - - // Prevent replay attacks - function executeOnce( - bytes32 txHash, - address target, - uint256 value, - bytes calldata data - ) external returns (bytes memory) { - require(!executedTxHashes[tx.origin][txHash], "Transaction already executed"); - executedTxHashes[tx.origin][txHash] = true; - - (bool success, bytes memory result) = target.call{value: value}(data); - require(success, "Transaction execution failed"); - - return result; - } -} -``` - - - - -## References - -- **EIP-7702 Specification:** https://eips.ethereum.org/EIPS/eip-7702 -- **Implementation PRs:** - - [Core Implementation](https://github.com/cosmos/evm/commit/4b0dcd3e) (July 2025) - - [Ante Handler Support](https://github.com/cosmos/evm/commit/2cc93849) (July 2025) - - [RPC Integration](https://github.com/cosmos/evm/commit/9164b471) (July 2025) -- **Source Code:** - - [`x/vm/keeper/state_transition.go:426+`](https://github.com/cosmos/evm/blob/main/x/vm/keeper/state_transition.go#L426) - Core delegation logic - - [`ante/evm/06_account_verification.go:33+`](https://github.com/cosmos/evm/blob/main/ante/evm/06_account_verification.go#L33) - Authorization validation - - [`rpc/types/utils.go:322+`](https://github.com/cosmos/evm/blob/main/rpc/types/utils.go#L322) - RPC transaction formatting \ No newline at end of file diff --git a/evm/next/documentation/evm-compatibility/eip-reference.mdx b/evm/next/documentation/evm-compatibility/eip-reference.mdx deleted file mode 100644 index 116052ab8..000000000 --- a/evm/next/documentation/evm-compatibility/eip-reference.mdx +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "EIP Reference" -description: "A complete list of Ethereum Mainnet \"Final\" EIPs and details on their implementation with Cosmos-EVM" -mode: "custom" ---- - -import EIPCompatibilityTable from '/snippets/eip-compatibility-table.jsx'; - - diff --git a/evm/next/documentation/evm-compatibility/overview.mdx b/evm/next/documentation/evm-compatibility/overview.mdx deleted file mode 100644 index 1a69ec1bc..000000000 --- a/evm/next/documentation/evm-compatibility/overview.mdx +++ /dev/null @@ -1,238 +0,0 @@ ---- -title: "Overview" -mode: "wide" -keywords: ['differences', 'ethereum', 'evm', 'cosmos', 'CometBFT', 'consensus', 'finality', 'json-rpc', 'compatibility', 'precompiles', 'ibc', 'mev', 'gas', 'basefee', 'reorganization', 'bft', 'validator', 'staking'] ---- - -The EVM module provides **developer and end-user Ethereum compatibility** for Cosmos-SDK based chains. All standard / common Ethereum dApps, tools, and workflows work seamlessly while gaining the benefits of Cosmos consensus and interoperability. -All the tools and workflows you rely on work exactly as they should. Deploy contracts seamlessly, connect with MetaMask, and build with Web3.js/Ethers, Hardhat, Remix, Foundry—the full Ethereum toolkit. - - -For a detailed breakdown on **Ethereum Improvement Proposal (EIP)** support and functional comparisons, see the [EIP reference](/evm/next/documentation/evm-compatibility/eip-reference) table. - - -## Key Compatibility Focus Areas - -Cosmos EVM maintains all critical EVM behaviors that developers expect. The table below shows how we've addressed each compatibility requirement. - -| Feature | Ethereum Behavior | Cosmos EVM Implementation | Compatible? | -|---------|------------------|---------------------------|---------------| -| **Transaction Ordering** | Gas price + nonce ordering | Fee priority + nonce ordering with configurable MinTip | Yes | -| **Multiple Txs per Block** | Multiple per account | Multiple per account | Yes | -| **Mempool Behavior** | Pending pool for transactions | ExperimentalEVMMempool with unified EVM/Cosmos pools | Yes | -| **Nonce Management** | Sequential nonce enforcement | Sequential nonce enforcement with gap queuing | Yes | -| **EIP-1559 (Dynamic Fees)** | Base fee + priority fee | Base fee + priority fee (distributed, not burned) | Yes | -| **EIP-7702 (Set Code)** | Account code delegation | Full support with authorization lists | Yes | -| **Address Format** | 0x addresses | 0x addresses (+ cosmos1 alias) | Yes | -| **Smart Contracts** | EVM bytecode execution | Full EVM bytecode execution | Yes | -| **Gas Metering** | Standard gas costs | Standard gas costs | Yes | -| **Event Logs** | Ethereum event system | Full event compatibility | Yes | -| **JSON-RPC API** | Standard Ethereum RPC | Full RPC implementation | Yes | -| **Block Time** | 12 seconds | 1-2 seconds | Faster | -| **Finality** | 12+ blocks (~3min) | 1 block (~2s) | Instant | -| **Reorganizations** | Possible | Not possible | More secure | -| **Cross-chain** | Bridge protocols | Native IBC | Enhanced | - -### What This Means for Developers - -**You can build on Cosmos EVM exactly like you would on Ethereum.** Every essential feature works identically - from deploying contracts to managing transactions. The enhancements (faster blocks, instant finality, IBC) are pure additions that don't break any existing patterns or workflows. - -## Architectural Improvements Over Ethereum - -### Faster & Final Transactions - -**Instant Finality:** Transactions are final after one block (~2 seconds) thanks to 'CometBFT' BFT consensus. No waiting for confirmations, no reorganizations possible. - -**Validator Set:** Fixed validator set with stake-based voting power. Requires 2/3+ stake agreement for consensus. - -### Gas & Fees - - -**Base Fee Distribution:** Unlike Ethereum where base fees are burned, Cosmos EVM distributes them to validators, preserving token economics. - - -- **EIP-1559 Support:** Dynamic base fee adjustments based on block utilization -- **Configurable:** Base fee can be disabled (`NoBaseFee` parameter) -- **Priority Calculation:** `min(gas_tip_cap, gas_fee_cap - base_fee)` -- **Minimum Gas Price:** Chain-wide floor price configuration - -### Address System - -Every account has two representations: -``` -Ethereum: 0x742d35cc6644c068532fddb11B4C36A58D6D3eAb -Cosmos: cosmos1wskntvnryr5qxpe4tv5k64rhc6kx6ma4dxjmav -``` - -Both formats reference the same account - use either based on your needs. - -### Chain ID Architecture - - -**Two Independent Chain IDs:** Cosmos EVM uses separate chain IDs: -- **Cosmos Chain ID:** [String] (e.g., "cosmosevm-1") for native features -- **EVM Chain ID:** [integer] (e.g., 9000) for EVM compatibility - -Unlike with legacy Ethermint, these values are independent. - - -## Precompiled Contracts - - - - Access Cosmos SDK modules (staking, governance, IBC) via precompiled contracts. - - - All Ethereum cryptographic precompiles supported (ecrecover, sha256, etc.) - - - -### Key Precompile Addresses - -| Function | Address | -|----------|---------| -| **Staking** | `0x0000000000000000000000000000000000000800` | -| **Distribution** | `0x0000000000000000000000000000000000000801` | -| **IBC Transfer** | `0x0000000000000000000000000000000000000802` | -| **Bank** | `0x0000000000000000000000000000000000000804` | -| **Governance** | `0x0000000000000000000000000000000000000805` | - -## JSON-RPC API - - - Most standard Ethereum JSON-RPC methods are supported, with some returning stub values for compatibility. View the complete reference. - - -**Core functionality for developers:** -- All standard transaction methods (`eth_sendRawTransaction`, `eth_call`, `eth_estimateGas`) -- Block and receipt queries -- Account balances and nonces -- Event logs and filters -- Web3 utilities and net info -- Debug namespace (partial - tracing and profiling methods available) -- Websocket subscription support - -**Implementation notes:** -- Some methods return stub values for compatibility (e.g., `eth_gasPrice` returns 0) -- Mining-related methods are not applicable (Cosmos uses 'CometBFT' consensus) -- `txpool` methods require experimental mempool configuration -- Debug namespace includes functional tracing and profiling tools - -## EIP Support - - - Interactive table showing support status for Ethereum Improvement Proposals. - - -### Notable Implementation Details - -- **EIP-1559:** Fully supported - with base fee distributed to validators instead of burned -- **EIP-155:** Fully supported - per-node configuration for unprotected transactions (v0.5.0+) -- **EIP-2935:** Full support - historical block hash storage with configurable depth (v0.5.0+) -- **EIP-3651:** Partial - COINBASE always returns empty address currently -- **EIP-7702:** Full support - EOA code delegation for account abstraction (v0.5.0+) -- **Access Lists:** Full support via `eth_createAccessList` RPC method (v0.5.0+) -- **Custom Improvement Proposals (CIPs):** Chain-specific optimizations available - -## Developer Experience - -### Familiarity Out Of The Box - -**Your Ethereum skills and tools work unchanged:** -- Deploy contracts with Hardhat, Foundry, or Remix -- Connect MetaMask and other Web3 wallets -- Use Web3.js, Ethers.js, Viem, or any Web3 library -- All ERC standards work (ERC20, ERC721, ERC1155, etc.) -- Solidity and Vyper compile and run identically -- Standard tooling like OpenZeppelin contracts work perfectly - -### Additional Benefits - -**Enhanced capabilities without breaking compatibility:** -- **Native IBC:** Built-in cross-chain communication to any Cosmos chain -- **Lower Costs:** Typically much lower gas fees than Ethereum mainnet -- **Faster Blocks:** 1-2 second block times vs 12 seconds on Ethereum -- **Enhanced Security:** Byzantine Fault Tolerant consensus prevents attacks - -## v0.5.0 Compatibility Enhancements - -### EVM Equivalency Improvements - -**EOA Code Delegation (EIP-7702):** -- **What:** Externally owned accounts can temporarily execute smart contract code -- **Benefit:** Account abstraction, batched operations, enhanced wallet functionality -- **Use Case:** Multi-sig wallets, automated strategies, custom transaction validation - -**Historical Block Hash Access (EIP-2935):** -- **What:** BLOCKHASH opcode now provides reliable access to historical block hashes -- **Benefit:** Smart contracts can access up to 8192 previous block hashes (configurable) -- **Use Case:** Protocols requiring verifiable randomness or block-based logic - -**Access List Optimization:** -- **What:** New `eth_createAccessList` RPC method for transaction optimization -- **Benefit:** Generate access lists to reduce transaction costs -- **Compatibility:** Matches Ethereum's access list functionality exactly - -**Enhanced Transaction Responses:** -- **What:** Added `max_used_gas` field to transaction responses -- **Benefit:** Better gas estimation and transaction analytics -- **Use Case:** Tools can optimize gas usage more effectively - -### Performance Optimizations - -**Smart Gas Estimation:** -- **Plain Transfer Detection:** Simple ETH transfers return 21000 gas immediately (~90% faster) -- **Optimistic Bounds:** Complex transactions use initial execution results for better estimation bounds -- **Result:** Significantly faster `eth_estimateGas` for all transaction types - -**Mempool Configurability:** -- **What:** Transaction pool limits, timeouts, and priority functions now fully configurable -- **Benefit:** Chains can optimize for their specific throughput and economic requirements -- **Example:** High-frequency DeFi chains can increase pool sizes, games can use custom priority - -### Transaction Pool - -**Standard Ethereum mempool behavior is fully supported.** Transactions are ordered by gas price and nonce, multiple transactions per account per block work perfectly. - - -**Optional Enhancement:** An experimental two-tiered mempool is available that adds intelligent nonce gap handling and automatic transaction promotion. This is purely optional - the standard mempool works exactly like Ethereum. - - -## Migration from Ethermint/Evmos - -Key breaking changes when migrating: - -1. **Chain ID Format:** Cannot use Ethermint format (`evmos_9001-2`). Must configure two separate IDs. -2. **Module Names:** `x/evm` → `x/vm` -3. **Parameter Types:** Several parameter type changes (e.g., MinGasPrice: string → sdk.Dec) -4. **Precompile Addresses:** Different addresses than Ethermint - - - Detailed steps for migrating from Ethermint-based chains. - - -## Security & Reliability - -**Battle-tested and audited:** -- **Security Audited:** Full audit by Sherlock (July 2025) -- **Production Ready:** Core EVM implementation is stable and deployed on multiple mainnets -- **Enhanced Security:** No reorganization attacks possible due to instant finality -- **Byzantine Fault Tolerant:** Requires 2/3+ validator stake for any state changes -- **Proven Stack:** Built on Cosmos SDK and 'CometBFT', powering hundreds of chains - -## Resources - - - - Add EVM support to your Cosmos chain - - - Deep dive into architecture and design - - - Source code and issue tracker - - - Using Cosmos functionality through Solidity - - diff --git a/evm/next/documentation/getting-started/build-a-chain/additional-configuration/mempool-integration.mdx b/evm/next/documentation/getting-started/build-a-chain/additional-configuration/mempool-integration.mdx index 1d048f3e2..d9968764c 100644 --- a/evm/next/documentation/getting-started/build-a-chain/additional-configuration/mempool-integration.mdx +++ b/evm/next/documentation/getting-started/build-a-chain/additional-configuration/mempool-integration.mdx @@ -1,181 +1,48 @@ --- -title: "EVM Mempool Integration" -description: "Integrate the EVM mempool with your Cosmos EVM chain" +title: "Mempool Configuration" +description: "Customize the EVM mempool behavior on your Cosmos EVM chain." --- -## Overview +The mempool holds submitted transactions before they are included in a block, handling ordering, nonce gap queuing, and fee-based prioritization across both EVM and Cosmos transactions. The EVM mempool is enabled by default in `evmd`. For conceptual information about mempool design and architecture, see the [Mempool Concepts](/evm/next/documentation/concepts/mempool) page. -This guide provides step-by-step instructions for integrating the EVM mempool into your Cosmos EVM chain. For conceptual information about mempool design and architecture, see the [Mempool Concepts](/evm/next/documentation/concepts/mempool) page. +The mempool setup is split across two locations: -### Step 1: Add EVM Mempool to App Struct +- [`evmd/mempool.go`](https://github.com/cosmos/evm/blob/main/evmd/mempool.go) — `configureEVMMempool` and `createMempoolConfig`, called automatically from `NewExampleApp` +- [`mempool/`](https://github.com/cosmos/evm/tree/main/mempool) — the mempool implementation (`ExperimentalEVMMempool`, `CheckTxHandler`, `TxPool`) -```go expandable -// Update your app/app.go to include the EVM mempool -type App struct { - *baseapp.BaseApp - // ... other keepers - - // Cosmos EVM keepers - FeeMarketKeeper feemarketkeeper.Keeper - EVMKeeper *evmkeeper.Keeper - EVMMempool *evmmempool.ExperimentalEVMMempool -} -``` - -### Step 2: Configure Mempool in NewApp Constructor - - -The mempool must be initialized **after** the antehandler has been set in the app. - - -Add the following configuration in your `NewApp` constructor: - -```go expandable -// Set the EVM priority nonce mempool -if evmtypes.GetChainConfig() != nil { - mempoolConfig := &evmmempool.EVMMempoolConfig{ - AnteHandler: app.GetAnteHandler(), - BlockGasLimit: 100_000_000, // or 0 to use default - } - - evmMempool := evmmempool.NewExperimentalEVMMempool( - app.CreateQueryContext, - logger, - app.EVMKeeper, - app.FeeMarketKeeper, - app.txConfig, - app.clientCtx, - mempoolConfig, - ) - app.EVMMempool = evmMempool - - // Replace BaseApp mempool - app.SetMempool(evmMempool) - - // Set custom CheckTx handler for nonce gap support - checkTxHandler := evmmempool.NewCheckTxHandler(evmMempool) - app.SetCheckTxHandler(checkTxHandler) - - // Set custom PrepareProposal handler - abciProposalHandler := baseapp.NewDefaultProposalHandler(evmMempool, app) - abciProposalHandler.SetSignerExtractionAdapter( - evmmempool.NewEthSignerExtractionAdapter( - sdkmempool.NewDefaultSignerExtractionAdapter(), - ), - ) - app.SetPrepareProposal(abciProposalHandler.PrepareProposalHandler()) -} -``` - - -**Breaking Change from v0.4.x:** The global mempool registry (`SetGlobalEVMMempool`) has been removed. Mempool is now passed directly to the JSON-RPC server during initialization. - +Legacy pool parameters and `MinTip` can be set via `app.toml` without code changes. `CosmosPoolConfig` and `BroadCastTxFn` require modifying `createMempoolConfig` in `evmd/mempool.go`. `BlockGasLimit` is read from `consensus_params.block.max_gas` in `genesis.json`. ## Configuration Options -The `EVMMempoolConfig` struct provides several configuration options for customizing the mempool behavior: - - - -For most use cases, the minimal configuration is sufficient: - -```go expandable -mempoolConfig := &evmmempool.EVMMempoolConfig{ - AnteHandler: app.GetAnteHandler(), - BlockGasLimit: 100_000_000, // or 0 to use default -} -``` - +The `EVMMempoolConfig` struct controls mempool behavior: - -```go expandable +```go type EVMMempoolConfig struct { - // Required: AnteHandler for transaction validation - AnteHandler sdk.AnteHandler - - // Required: Block gas limit for transaction selection - BlockGasLimit uint64 - - // Optional: Custom legacy pool configuration (replaces TxPool) - LegacyPoolConfig *legacypool.Config - - // Optional: Custom Cosmos pool configuration (replaces CosmosPool) - CosmosPoolConfig *sdkmempool.PriorityNonceMempoolConfig[math.Int] - - // Optional: Custom broadcast function for promoted transactions - BroadcastTxFn func(txs []*ethtypes.Transaction) error - - // Optional: Minimum tip required for EVM transactions - MinTip *uint256.Int + AnteHandler sdk.AnteHandler // Required: transaction validation + BlockGasLimit uint64 // Required: gas limit for block selection + LegacyPoolConfig *legacypool.Config // Optional: EVM pool tuning — see Custom Legacy Pool below + CosmosPoolConfig *sdkmempool.PriorityNonceMempoolConfig[math.Int] // Optional: Cosmos pool tuning — see Custom Cosmos Mempool below + BroadCastTxFn func(txs []*ethtypes.Transaction) error // Optional: custom promotion broadcast — see Custom Broadcast below + MinTip *uint256.Int // Optional: minimum tip for EVM txs } ``` - - -#### Defaults and Fallbacks +### Defaults and Fallbacks - If `BlockGasLimit` is `0`, the mempool uses a fallback of `100_000_000` gas. - If `LegacyPoolConfig` is not provided, defaults from `legacypool.DefaultConfig` are used. - If `CosmosPoolConfig` is not provided, a default `PriorityNonceMempool` is created with: - - Priority = `(fee_amount / gas_limit)` in the chain bond denom + - Priority = `(fee_amount / gas_limit)` in the EVM coin denom - Comparator = big-int comparison (higher is selected first) - `MinValue = 0` -- If `BroadcastTxFn` is not provided, a default is created that uses the app `clientCtx`/`txConfig` to broadcast EVM transactions when they are promoted from queued → pending. +- If `BroadCastTxFn` is not provided, a default is created that uses the app `clientCtx`/`txConfig` to broadcast EVM transactions when they are promoted from queued → pending. - `MinTip` is optional. If unset, selection uses the effective tip from each tx (`min(gas_tip_cap, gas_fee_cap - base_fee)`). -### v0.4.x to v0.5.0 Migration - -**Breaking Change:** Pre-built pools replaced with configuration objects - -PR [#496](https://github.com/cosmos/evm/pull/496) replaced pre-built pools with configs in `EVMMempoolConfig`: - -- **Removed:** `TxPool *txpool.TxPool`, `CosmosPool sdkmempool.ExtMempool` -- **Added:** `LegacyPoolConfig *legacypool.Config`, `CosmosPoolConfig *sdkmempool.PriorityNonceMempoolConfig[math.Int]` - -#### Minimal Setups: Nothing to Change - -If you use the default mempool wiring (no custom pools), your existing code continues to work: - -```go expandable -mempoolConfig := &evmmempool.EVMMempoolConfig{ - AnteHandler: app.GetAnteHandler(), - BlockGasLimit: 100_000_000, // or 0 to use default -} -evmMempool := evmmempool.NewExperimentalEVMMempool( - app.CreateQueryContext, logger, app.EVMKeeper, app.FeeMarketKeeper, - app.txConfig, app.clientCtx, mempoolConfig -) -``` - -#### Advanced Setups: Migrate Your Customizations - -If you built custom pools yourself, replace them with configuration objects: - -**Before (v0.4.x):** -```go expandable -mempoolConfig := &evmmempool.EVMMempoolConfig{ - TxPool: customTxPool, // ← REMOVED - CosmosPool: customCosmosPool, // ← REMOVED - AnteHandler: app.GetAnteHandler(), - BlockGasLimit: 100_000_000, -} -``` - -**After (v0.5.0):** -```go expandable -mempoolConfig := &evmmempool.EVMMempoolConfig{ - LegacyPoolConfig: &legacyCfg, // ← NEW (or nil for defaults) - CosmosPoolConfig: &cosmosCfg, // ← NEW (or nil for defaults) - AnteHandler: app.GetAnteHandler(), - BlockGasLimit: 100_000_000, -} -``` - ### Custom Legacy Pool Configuration Customize EVM transaction pool parameters: -```go expandable +```go title="evmd/mempool.go" // EVM legacy txpool tuning legacyCfg := legacypool.DefaultConfig legacyCfg.PriceLimit = 2 // Minimum gas price (wei) @@ -193,7 +60,7 @@ mempoolConfig.LegacyPoolConfig = &legacyCfg The mempool uses a `PriorityNonceMempool` for Cosmos transactions by default. You can customize the priority calculation: -```go expandable +```go title="evmd/mempool.go" // Define custom priority calculation for Cosmos transactions cosmosCfg := sdkmempool.PriorityNonceMempoolConfig[math.Int]{} cosmosCfg.TxPriority = sdkmempool.TxPriority[math.Int]{ @@ -228,9 +95,9 @@ mempoolConfig.CosmosPoolConfig = &cosmosCfg Override the default broadcast behavior for promoted EVM transactions: -```go expandable +```go title="evmd/mempool.go" // Custom EVM broadcast (optional) -mempoolConfig.BroadcastTxFn = func(txs []*ethtypes.Transaction) error { +mempoolConfig.BroadCastTxFn = func(txs []*ethtypes.Transaction) error { // Custom logic for broadcasting promoted transactions return nil } @@ -238,9 +105,9 @@ mempoolConfig.BroadcastTxFn = func(txs []*ethtypes.Transaction) error { ### Custom Block Gas Limit -Different chains may require different gas limits based on their capacity: +`BlockGasLimit` is read automatically from `consensus_params.block.max_gas` in `genesis.json` — it is not an `app.toml` setting. To change it, update the genesis file before chain start. The value can also be overridden in code: -```go expandable +```go title="evmd/mempool.go" // Example: 50M gas limit for lower capacity chains mempoolConfig := &evmmempool.EVMMempoolConfig{ AnteHandler: app.GetAnteHandler(), @@ -252,7 +119,7 @@ mempoolConfig := &evmmempool.EVMMempoolConfig{ For best results, connect the mempool to CometBFT's EventBus so it can react to finalized blocks: -```go expandable +```go title="evmd/app.go" // After starting the CometBFT node if m, ok := app.GetMempool().(*evmmempool.ExperimentalEVMMempool); ok { m.SetEventBus(bftNode.EventBus()) @@ -260,130 +127,22 @@ if m, ok := app.GetMempool().(*evmmempool.ExperimentalEVMMempool); ok { ``` This enables chain-head notifications so the mempool can promptly promote/evict transactions when blocks are committed. -## Architecture Components +## app.toml Configuration -The EVM mempool consists of several key components: +The following settings can be configured in `app.toml` and take effect at node startup without code changes: -### ExperimentalEVMMempool +| Key | Default | Description | +|-----|---------|-------------| +| `evm.min-tip` | `0` | Minimum tip (priority fee) in wei; transactions below this are excluded from block selection | +| `evm.mempool.price-limit` | `1` | Minimum gas price in wei to accept a transaction into the pool | +| `evm.mempool.price-bump` | `10` | Minimum % increase required to replace a pending transaction with the same nonce | +| `evm.mempool.account-slots` | `16` | Max executable transactions per account | +| `evm.mempool.global-slots` | `5120` | Max total executable transactions across all accounts | +| `evm.mempool.account-queue` | `64` | Max queued (non-executable) transactions per account | +| `evm.mempool.global-queue` | `1024` | Max total queued transactions across all accounts | +| `evm.mempool.lifetime` | `3h` | Max time a transaction can remain queued before eviction | -The main coordinator implementing Cosmos SDK's `ExtMempool` interface (`mempool/mempool.go`). - -**Key Methods**: -- `Insert(ctx, tx)`: Routes transactions to appropriate pools -- `Select(ctx, filter)`: Returns unified iterator over all transactions -- `Remove(tx)`: Handles transaction removal with EVM-specific logic -- `InsertInvalidNonce(txBytes)`: Queues nonce-gapped EVM transactions locally - -### CheckTx Handler - -Custom transaction validation that handles nonce gaps specially (`mempool/check_tx.go`). - -**Special Handling**: On `ErrNonceGap` for EVM transactions: -```go expandable -if errors.Is(err, ErrNonceGap) { - // Route to local queue instead of rejecting - err := mempool.InsertInvalidNonce(request.Tx) - // Must intercept error and return success to EVM client - return interceptedSuccess -} -``` - -### TxPool - -Direct port of Ethereum's transaction pool managing both pending and queued transactions (`mempool/txpool/`). - -**Key Features**: -- Uses `vm.StateDB` interface for Cosmos state compatibility -- Implements `BroadcastTxFn` callback for transaction promotion -- Cosmos-specific reset logic for instant finality - -### PriorityNonceMempool - -Standard Cosmos SDK mempool for non-EVM transactions with fee-based prioritization. - -**Default Priority Calculation**: -```go expandable -// Calculate effective gas price -priority = (fee_amount / gas_limit) - base_fee -``` - -## Transaction Type Routing - -The mempool handles different transaction types appropriately: - -### Ethereum Transactions (MsgEthereumTx) - -- **Tier 1 (Local)**: EVM TxPool handles nonce gaps and promotion -- **Tier 2 (Network)**: CometBFT broadcasts executable transactions - -### Cosmos Transactions (Bank, Staking, Gov, etc.) - -- **Direct to Tier 2**: Always go directly to CometBFT mempool -- **Standard Flow**: Follow normal Cosmos SDK validation and broadcasting -- **Priority-Based**: Use PriorityNonceMempool for fee-based ordering - -## Unified Transaction Selection - -During block building, both transaction types compete fairly based on their effective tips: - -```go expandable -// Simplified selection logic -func SelectTransactions() Iterator { - evmTxs := GetPendingEVMTransactions() // From local TxPool - cosmosTxs := GetPendingCosmosTransactions() // From Cosmos mempool - - return NewUnifiedIterator(evmTxs, cosmosTxs) // Fee-based priority -} -``` - -**Fee Comparison**: -- **EVM**: `gas_tip_cap` or `min(gas_tip_cap, gas_fee_cap - base_fee)` -- **Cosmos**: `(fee_amount / gas_limit) - base_fee` -- **Selection**: Higher effective tip gets selected first - -## Testing Your Integration - -### Verify Nonce Gap Handling - -Test that transactions with nonce gaps are properly queued: - -```javascript expandable -// Send transactions out of order -await wallet.sendTransaction({nonce: 100, ...}); // OK: Immediate execution -await wallet.sendTransaction({nonce: 102, ...}); // OK: Queued locally (gap) -await wallet.sendTransaction({nonce: 101, ...}); // OK: Fills gap, both execute -``` - -### Test Transaction Replacement - -Verify that higher-fee transactions replace lower-fee ones: - -```javascript expandable -// Send initial transaction -const tx1 = await wallet.sendTransaction({ - nonce: 100, - gasPrice: parseUnits("20", "gwei") -}); - -// Replace with higher fee -const tx2 = await wallet.sendTransaction({ - nonce: 100, // Same nonce - gasPrice: parseUnits("30", "gwei") // Higher fee -}); -// tx1 is replaced by tx2 -``` - -### Verify Batch Deployments - -Test typical deployment scripts (like Uniswap) that send many transactions at once: - -```javascript expandable -// Deploy multiple contracts in quick succession -const factory = await Factory.deploy(); -const router = await Router.deploy(factory.address); -const multicall = await Multicall.deploy(); -// All transactions should queue and execute properly -``` +`CosmosPoolConfig` and `BroadCastTxFn` have no `app.toml` equivalent and require code changes in `createMempoolConfig`. ## Monitoring and Debugging @@ -397,5 +156,5 @@ Use the [txpool RPC methods](/evm/next/api-reference/ethereum-json-rpc/methods#t ## Related Documentation - [Mempool Concepts](/evm/next/documentation/concepts/mempool) - Understanding mempool behavior and design -- [EVM Module Integration](/evm/next/documentation/getting-started/build-a-chain/overview.mdx) - Prerequisites for mempool integration +- [EVM Module Integration](/evm/next/documentation/getting-started/build-a-chain/overview) - Prerequisites for mempool integration - [JSON-RPC Methods](/evm/next/api-reference/ethereum-json-rpc/methods#txpool-methods) - Mempool query methods diff --git a/evm/next/documentation/getting-started/build-a-chain/additional-configuration/precompiles.mdx b/evm/next/documentation/getting-started/build-a-chain/additional-configuration/precompiles.mdx new file mode 100644 index 000000000..8d49e8995 --- /dev/null +++ b/evm/next/documentation/getting-started/build-a-chain/additional-configuration/precompiles.mdx @@ -0,0 +1,212 @@ +--- +title: "Precompile Configuration" +description: "Choose which precompiles are active on your chain and add custom ones." +--- + +[Precompiles](/evm/next/documentation/smart-contracts/precompiles/overview) are smart contract interfaces at fixed addresses where the implementation runs as native Go code. Cosmos EVM ships with precompiles for staking, governance, IBC, and more. As a chain builder you control which ones are active and can add your own. for more information and to see the full list of available precompiles, see the [precompiles overview](/evm/next/documentation/smart-contracts/precompiles/overview). + +## Enabling Precompiles + +Precompiles are enabled via the `active_static_precompiles` parameter in the `vm` module. Only addresses listed here are callable at runtime. For the full list of built-in precompiles and their addresses, see the [precompiles overview](/evm/next/documentation/smart-contracts/precompiles/overview). + +Set this in your genesis configuration ([`evmd/genesis.go`](https://github.com/cosmos/evm/blob/main/evmd/genesis.go)): + +```go +func NewEVMGenesisState() *evmtypes.GenesisState { + evmGenState := evmtypes.DefaultGenesisState() + + // Enable all available precompiles + evmGenState.Params.ActiveStaticPrecompiles = evmtypes.AvailableStaticPrecompiles + + return evmGenState +} +``` + +To enable only a specific subset, pass the addresses explicitly. Addresses must be in sorted order: + +```go +evmGenState.Params.ActiveStaticPrecompiles = []string{ + evmtypes.StakingPrecompileAddress, // 0x0000000000000000000000000000000000000800 + evmtypes.DistributionPrecompileAddress, // 0x0000000000000000000000000000000000000801 + evmtypes.BankPrecompileAddress, // 0x0000000000000000000000000000000000000804 +} +``` + +The full list of available addresses is defined in [`x/vm/types/precompiles.go`](https://github.com/cosmos/evm/blob/main/x/vm/types/precompiles.go). + +Already-registered precompiles can also be enabled or disabled after launch via a governance parameter change proposal targeting the `vm` module's `active_static_precompiles` param. Adding a genuinely new custom precompile requires a chain upgrade, since the implementation lives in the Go binary. + +## Adding a Custom Precompile + +The following example adds a stateful `DenomSupply` precompile with a single `supplyOf` method that reads total token supply directly from the Cosmos bank module. This demonstrates the core pattern for basic precompiles: injecting a Cosmos SDK keeper and using `RunNativeAction` to access live chain state from an EVM call. + +### 1. Create the precompile package + +Create a directory `precompiles/denomsupply/` with two files. + +`precompiles/denomsupply/abi.json` — the Solidity ABI: + +```json +[ + { + "inputs": [{"internalType": "string", "name": "denom", "type": "string"}], + "name": "supplyOf", + "outputs": [{"internalType": "uint256", "name": "amount", "type": "uint256"}], + "stateMutability": "view", + "type": "function" + } +] +``` + +`precompiles/denomsupply/denomsupply.go` — the implementation: + +```go +package denomsupply + +import ( + "bytes" + _ "embed" + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + + cmn "github.com/cosmos/evm/precompiles/common" + evmtypes "github.com/cosmos/evm/x/vm/types" + + storetypes "cosmossdk.io/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var _ vm.PrecompiledContract = &Precompile{} + +var ( + //go:embed abi.json + f []byte + ABI abi.ABI +) + +func init() { + var err error + ABI, err = abi.JSON(bytes.NewReader(f)) + if err != nil { + panic(err) + } +} + +// Precompile queries the total supply of a Cosmos denomination from the bank module. +type Precompile struct { + cmn.Precompile + bankKeeper cmn.BankKeeper +} + +func NewPrecompile(bankKeeper cmn.BankKeeper) *Precompile { + return &Precompile{ + Precompile: cmn.Precompile{ + KvGasConfig: storetypes.GasConfig{}, + TransientKVGasConfig: storetypes.GasConfig{}, + ContractAddress: common.HexToAddress(evmtypes.DenomSupplyPrecompileAddress), + }, + bankKeeper: bankKeeper, + } +} + +func (p Precompile) RequiredGas(_ []byte) uint64 { + return 3_000 +} + +// Run executes the precompile inside the Cosmos EVM context. +// RunNativeAction bridges the EVM execution environment to the Cosmos SDK, +// providing an sdk.Context with access to all module state. +func (p Precompile) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) { + return p.RunNativeAction(evm, contract, func(ctx sdk.Context) ([]byte, error) { + method, args, err := cmn.SetupABI(ABI, contract, readonly, p.IsTransaction) + if err != nil { + return nil, err + } + + switch method.Name { + case "supplyOf": + denom, ok := args[0].(string) + if !ok { + return nil, fmt.Errorf("invalid argument: expected string") + } + coin := p.bankKeeper.GetSupply(ctx, denom) + return method.Outputs.Pack(coin.Amount.BigInt()) + } + + return nil, fmt.Errorf("unknown method: %s", method.Name) + }) +} + +// IsTransaction returns false because supplyOf is a read-only query. +func (Precompile) IsTransaction(_ *abi.Method) bool { + return false +} +``` + +The struct embeds `cmn.Precompile` rather than handling context directly. `RunNativeAction` sets up the SDK context, manages gas metering, and handles snapshot/revert so that precompile calls participate correctly in EVM transaction atomicity. Inside the closure, `p.bankKeeper` provides access to the bank module's state. + +### 2. Register the address + +In [`x/vm/types/precompiles.go`](https://github.com/cosmos/evm/blob/main/x/vm/types/precompiles.go), add a constant and include it in `AvailableStaticPrecompiles`. Addresses must be appended in sorted order: + +```go +const DenomSupplyPrecompileAddress = "0x0000000000000000000000000000000000000809" + +var AvailableStaticPrecompiles = []string{ + // ... existing addresses ... + MathPrecompileAddress, + DenomSupplyPrecompileAddress, // appended in sorted order +} +``` + +### 3. Add a builder method + +In [`precompiles/types/static_precompiles.go`](https://github.com/cosmos/evm/blob/main/precompiles/types/static_precompiles.go), add a `With` method. Pass any keepers your precompile needs as parameters: + +```go +func (s StaticPrecompiles) WithDenomSupplyPrecompile(bankKeeper cmn.BankKeeper) StaticPrecompiles { + denomSupplyPrecompile := denomsupplyprecompile.NewPrecompile(bankKeeper) + s[denomSupplyPrecompile.Address()] = denomSupplyPrecompile + return s +} +``` + +### 4. Wire it into the app + +In [`precompiles/types/defaults.go`](https://github.com/cosmos/evm/blob/main/precompiles/types/defaults.go), add your method to the builder chain. The `bankKeeper` is already a parameter of `DefaultStaticPrecompiles`: + +```go +precompiles := NewStaticPrecompiles(). + // ... existing precompiles ... + WithSlashingPrecompile(slashingKeeper, bankKeeper, opts...). + WithMathPrecompile(). + WithDenomSupplyPrecompile(bankKeeper) +``` + +### 5. Activate at genesis + +Add the address to `active_static_precompiles` in your genesis setup and in `local_node.sh` if you're using that script for local development: + +```go +// evmd/genesis.go +evmGenState.Params.ActiveStaticPrecompiles = evmtypes.AvailableStaticPrecompiles +``` + +### 6. Build and verify + +```bash +make install +./local_node.sh -y +``` + +Once the chain is running, call the precompile and get a decoded result in one step: + +```bash +cast call 0x0000000000000000000000000000000000000809 \ + "supplyOf(string)(uint256)" "atest" \ + --rpc-url http://localhost:8545 +# 100025807224055573593873019 [1e26] +``` diff --git a/evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts.mdx b/evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts.mdx index b3d3b7655..928ebc27e 100644 --- a/evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts.mdx +++ b/evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts.mdx @@ -1,48 +1,51 @@ --- title: "Predeployed Contracts" -description: "Deploying and managing predeployed contracts" +description: "Deploy standard EVM contracts at fixed addresses on your Cosmos EVM chain." --- - -**New to predeployed contracts?** Start here: -- [Predeployed Contracts Concept](/evm/next/documentation/concepts/predeployed-contracts) - Understanding predeployed contracts and how they differ from precompiles -- [Predeployed Contracts Overview](/evm/next/documentation/smart-contracts/predeployed-contracts/overview) - Quick reference of available contracts -- [Building Your Chain Guide](/evm/next/documentation/getting-started/build-a-chain/overview#configuring-predeployed-contracts) - Quick start configuration examples +Predeployed contracts (also called preinstalls) are EVM contracts that exist in chain state at a specific address from genesis. Because the address is fixed and known in advance, the same contract can exist at the same address across every chain that includes it, making them useful for infrastructure that needs to be reliably reachable everywhere. -**Individual Contract Documentation**: -- [Create2 Factory](/evm/next/documentation/smart-contracts/predeployed-contracts/create2) - Deterministic deployment patterns -- [Multicall3](/evm/next/documentation/smart-contracts/predeployed-contracts/multicall3) - Batch operations examples -- [Permit2](/evm/next/documentation/smart-contracts/predeployed-contracts/permit2) - Signature-based approvals -- [Safe Factory](/evm/next/documentation/smart-contracts/predeployed-contracts/safe-factory) - Multisig wallet deployment - +## Default Contracts -## Getting Started +Cosmos EVM includes five default preinstalls ([`x/vm/types/preinstall.go`](https://github.com/cosmos/evm/blob/main/x/vm/types/preinstall.go)): -There are several methods to deploy preinstalled contracts on a Cosmos EVM chain: +| Contract | Address | Purpose | Docs | +|----------|---------|---------|------| +| **Create2** | `0x4e59b44847b379578588920ca78fbf26c0b4956c` | Deterministic contract deployment using CREATE2 | [EIP-1014](https://eips.ethereum.org/EIPS/eip-1014) | +| **Multicall3** | `0xcA11bde05977b3631167028862bE2a173976CA11` | Batch multiple contract calls in one transaction | [Repo](https://github.com/mds1/multicall) · [Site](https://www.multicall3.com/) | +| **Permit2** | `0x000000000022D473030F116dDEE9F6B43aC78BA3` | Signature-based token approvals for any ERC20 | [Repo](https://github.com/Uniswap/permit2) · [Docs](https://docs.uniswap.org/contracts/permit2/overview) | +| **Safe Singleton Factory** | `0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7` | Deploy Safe multisig wallets at deterministic addresses | [Repo](https://github.com/safe-global/safe-singleton-factory) · [Docs](https://docs.safe.global/) | +| **EIP-2935** | `0x0000F90827F1C53a10cb7A02335B175320002935` | Historical block hash storage | [EIP-2935](https://eips.ethereum.org/EIPS/eip-2935) | -### 1. Genesis Configuration -The most straightforward method for new chains or testnets. Contracts are deployed when the chain is first initialized. +## Enabling at Genesis - - -If using the reference `evmd` application, your chain automatically includes default preinstalls, however they will not be active by default. +Preinstalls are deployed when the chain first starts, based on the `preinstalls` array in `genesis.json`. If the array is empty, no contracts are deployed. -```go expandable -// Source: evmd/genesis.go:28-34 +### App-level configuration + +In your chain's application code, define which preinstalls to include in `NewEVMGenesisState`. The `evmd` reference chain includes all five defaults: + +```go title="evmd/genesis.go" func NewEVMGenesisState() *evmtypes.GenesisState { evmGenState := evmtypes.DefaultGenesisState() evmGenState.Params.ActiveStaticPrecompiles = evmtypes.AvailableStaticPrecompiles - evmGenState.Preinstalls = evmtypes.DefaultPreinstalls // Defined in x/vm/types/preinstall.go + evmGenState.Preinstalls = evmtypes.DefaultPreinstalls return evmGenState } ``` - - -To customize which contracts are deployed: +This function is called by your app's `DefaultGenesis()`, which is used when generating genesis state programmatically (e.g. `evmd testnet`). + +### Populating genesis.json + + +`evmd init` generates a genesis.json with an empty `preinstalls` array. The app-level preinstall configuration is **not** automatically written to the genesis file by the init command. + -```json expandable +To enable preinstalls on a chain started from a genesis file (including `local_node.sh`), populate the `preinstalls` array in `genesis.json` before starting the node. Each entry requires the contract name, address, and compiled bytecode: + +```json title="genesis.json" { "app_state": { "evm": { @@ -55,314 +58,104 @@ To customize which contracts are deployed: { "name": "Multicall3", "address": "0xcA11bde05977b3631167028862bE2a173976CA11", - "code": "0x6080604052..." // Full bytecode + "code": "0x..." } ] } } } ``` - - - -#### Local Development - -The `local_node.sh` script automatically configures default preinstalls: - -```bash expandable -./local_node.sh -# Automatically deploys all default preinstalls -``` -### 2. Governance Proposal +The full bytecode for each default preinstall is defined in [`x/vm/types/preinstall.go`](https://github.com/cosmos/evm/blob/main/x/vm/types/preinstall.go). -For chains already in production, use the `MsgRegisterPreinstalls` governance proposal: +## Adding Contracts After Launch -#### Proposal Structure +### Governance Proposal - -The `authority` field must be set to the governance module account address, which is typically derived from the gov module name. This is usually something like `cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn` for the standard gov module. - +Use `MsgRegisterPreinstalls` to deploy contracts on a running chain via governance: -```json expandable +```json title="proposal.json" { "messages": [ { "@type": "/cosmos.evm.vm.v1.MsgRegisterPreinstalls", - "authority": "[gov module account address]", + "authority": "", "preinstalls": [ { "name": "Multicall3", "address": "0xcA11bde05977b3631167028862bE2a173976CA11", - "code": "0x6080604052..." + "code": "0x..." } ] } ], - "metadata": "ipfs://CID", "deposit": "10000000stake", - "title": "Deploy Multicall3 Contract", - "summary": "Deploy the Multicall3 contract to enable batched calls" + "title": "Deploy Multicall3", + "summary": "Deploy Multicall3 to enable batched contract calls" } ``` -#### Submission Process - -```bash expandable -# Submit proposal -evmd tx gov submit-proposal proposal.json \ - --from mykey \ - --chain-id cosmosevm_9001-1 \ - --gas auto - -# Vote on proposal +```bash +evmd tx gov submit-proposal proposal.json --from mykey --chain-id --gas auto evmd tx gov vote 1 yes --from mykey ``` -### 3. Chain Upgrade Handler +### Chain Upgrade Handler -Include predeployed contracts as part of a coordinated chain upgrade: +Include preinstalls in a coordinated chain upgrade: -```go expandable +```go title="app/upgrades/v2/upgrades.go" func CreateUpgradeHandler( mm *module.Manager, configurator module.Configurator, evmKeeper *evmkeeper.Keeper, ) upgradetypes.UpgradeHandler { return func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { - // Add preinstalls during upgrade if err := evmKeeper.AddPreinstalls(ctx, evmtypes.DefaultPreinstalls); err != nil { return nil, err } - return mm.RunMigrations(ctx, configurator, fromVM) } } ``` -## Implementation Details - -### Validation Process - -All preinstall deployments undergo strict validation: - -1. **Address Validation** - - Must be valid Ethereum address format (40 hex characters) - - Cannot conflict with existing contracts - - Should not overlap with precompile reserved addresses (typically 0x1-0x9FF) - -2. **Code Validation** - - Must be valid EVM bytecode (hex encoded) - - Cannot have empty code hash - - Must pass bytecode verification - -3. **Conflict Prevention** - - Checks for existing contracts at target address - - Validates against account keeper for existing accounts - - Ensures no code hash conflicts with different bytecode - -### Storage and State - -Predeployed contracts are stored in the chain state like regular contracts: +## Adding Custom Contracts -```go expandable -// Actual deployment process from x/vm/keeper/preinstalls.go -func (k *Keeper) AddPreinstalls(ctx sdk.Context, preinstalls []types.Preinstall) error { - for _, preinstall := range preinstalls { - address := common.HexToAddress(preinstall.Address) - accAddress := sdk.AccAddress(address.Bytes()) +To deploy a contract beyond the defaults, add it to your preinstalls list: - if len(preinstall.Code) == 0 { - return errorsmod.Wrapf(types.ErrInvalidPreinstall, - "preinstall %s has no code", preinstall.Address) - } - - codeHash := crypto.Keccak256Hash(common.FromHex(preinstall.Code)).Bytes() - if types.IsEmptyCodeHash(codeHash) { - return errorsmod.Wrapf(types.ErrInvalidPreinstall, - "preinstall %s has empty code hash", preinstall.Address) - } - - // Check for existing code hash conflicts - existingCodeHash := k.GetCodeHash(ctx, address) - if !types.IsEmptyCodeHash(existingCodeHash.Bytes()) && - !bytes.Equal(existingCodeHash.Bytes(), codeHash) { - return errorsmod.Wrapf(types.ErrInvalidPreinstall, - "preinstall %s already has a different code hash", preinstall.Address) - } - - // Check that the account is not already set - if acc := k.accountKeeper.GetAccount(ctx, accAddress); acc != nil { - return errorsmod.Wrapf(types.ErrInvalidPreinstall, - "preinstall %s already has an account in account keeper", preinstall.Address) - } - - // Create account and store code - account := k.accountKeeper.NewAccountWithAddress(ctx, accAddress) - k.accountKeeper.SetAccount(ctx, account) - k.SetCodeHash(ctx, address.Bytes(), codeHash) - k.SetCode(ctx, codeHash, common.FromHex(preinstall.Code)) - } - return nil +```go title="evmd/genesis.go" +customPreinstall := evmtypes.Preinstall{ + Name: "MyContract", + Address: "0xYourChosenAddress", + Code: "0xCompiledBytecode", } +evmGenState.Preinstalls = append(evmtypes.DefaultPreinstalls, customPreinstall) ``` -## Verification and Testing +Requirements for a valid preinstall: +- Valid Ethereum address (0x prefix, 40 hex characters) +- Must not conflict with existing contracts or precompile addresses (0x1–0x9FF) +- Non-empty, valid EVM bytecode (hex encoded) -### Verify Deployment +## Verification -After deployment, verify contracts are properly installed: +After the chain starts with preinstalls in genesis.json, confirm the contracts are installed: -```bash expandable -# Query contract code via CLI +```bash +# Check contract code is present evmd query evm code 0x4e59b44847b379578588920ca78fbf26c0b4956c # Check account exists evmd query evm account 0x4e59b44847b379578588920ca78fbf26c0b4956c ``` -```javascript expandable -// Verify via Web3 -const code = await provider.getCode("0x4e59b44847b379578588920ca78fbf26c0b4956c"); -console.log("Deployed:", code !== "0x"); -``` - -### Testing Strategy - -1. **Local Testing**: Deploy on local node first -2. **Testnet Validation**: Test governance proposal process -3. **Integration Testing**: Verify interactions with other contracts -4. **Gas Analysis**: Monitor gas consumption patterns -5. **Security Audit**: Review bytecode before mainnet deployment - -## Best Practices - -### Security Considerations - -- **Bytecode Verification**: Always verify that bytecode matches official releases -- **Address Selection**: Ensure addresses don't conflict with future plans -- **Audit Requirements**: Even well-known contracts should be reviewed -- **Immutability**: Remember that predeployed contracts cannot be upgraded - -### Deployment Recommendations - -1. **Start with Defaults**: Use `evmtypes.DefaultPreinstalls` unless you have specific requirements -2. **Test Thoroughly**: Validate on testnet before mainnet deployment -3. **Document Changes**: Clearly communicate any non-standard deployments to developers -4. **Monitor Usage**: Track contract interactions to understand adoption - -### Common Pitfalls to Avoid - -- Don't deploy to addresses that could conflict with precompiles (typically 0x1-0x9FF) -- Don't assume contracts are deployed - always check first -- Don't modify standard contract addresses without strong justification -- Don't deploy untested or unaudited bytecode - -## Known Issues - - -**Critical - Safe Factory Bytecode Error** - -The Safe Singleton Factory bytecode in `DefaultPreinstalls` ([`x/vm/types/preinstall.go:30-32`](https://github.com/cosmos/evm/blob/main/x/vm/types/preinstall.go#L30-L32)) is **identical to the Create2 factory bytecode**, which is incorrect and will not function for deploying Safe wallets. - -**Verification**: -```bash expandable -# Create2 bytecode -0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3 - -# Safe Factory bytecode (INCORRECT - same as Create2) -0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3 -``` - -**Before deploying to production**: -1. Get the correct Safe Singleton Factory bytecode from the [official repository](https://github.com/safe-global/safe-singleton-factory) -2. Update your genesis `preinstalls` configuration with the correct bytecode -3. Test thoroughly on a testnet -4. See the [Safe Factory documentation](/evm/next/documentation/smart-contracts/predeployed-contracts/safe-factory) for more details - -**Temporary workaround**: If you need Safe functionality immediately, manually update the bytecode in your genesis.json or use a governance proposal to deploy the correct contract. - - -## Adding Custom Preinstalls - -To add custom contracts beyond the defaults: - -```go expandable -// Define custom preinstall -customPreinstall := types.Preinstall{ - Name: "MyCustomContract", - Address: "0xYourChosenAddress", - Code: "0xCompiledBytecode", -} - -// Validate before deployment -if err := customPreinstall.Validate(); err != nil { - return err -} - -// Add via appropriate method (genesis, governance, or upgrade) -preinstalls := append(evmtypes.DefaultPreinstalls, customPreinstall) -``` +Both commands should return non-empty results. If `code` returns `null`, the preinstall was not included in genesis.json when the chain was initialized. ## Troubleshooting -### Common Issues - -| Issue | Cause | Solution | -|-|-|-| -| "preinstall already has an account in account keeper" | Address collision | Choose different address | -| "preinstall has empty code hash" | Invalid or empty bytecode | Verify bytecode hex string is valid | -| "preinstall address is not a valid hex address" | Malformed address | Ensure 0x prefix and 40 hex chars | -| "invalid authority" | Wrong governance address | Use correct gov module account address | -| Contract not found after deployment | Wrong network | Verify chain ID and RPC endpoint | - -### Debugging Steps - -1. Check chain genesis configuration -2. Verify proposal passed and executed -3. Query contract code directly -4. Test with simple contract interaction -5. Review chain logs for errors - -## Quick Reference - -### Default Preinstalls - -| Contract | Address | Bytecode Field | Status | -|-|||--| -| Create2 | `0x4e59b44847b379578588920ca78fbf26c0b4956c` | `preinstall.Code` | ✓ Verified | -| Multicall3 | `0xcA11bde05977b3631167028862bE2a173976CA11` | `preinstall.Code` | ✓ Verified | -| Permit2 | `0x000000000022D473030F116dDEE9F6B43aC78BA3` | `preinstall.Code` | ✓ Verified | -| Safe Factory | `0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7` | `preinstall.Code` | ⚠️ Bytecode Issue | -| EIP-2935 | `0x0b` | `params.HistoryStorageCode` | ✓ System Contract | - -**Source**: [`x/vm/types/preinstall.go:13-39`](https://github.com/cosmos/evm/blob/main/x/vm/types/preinstall.go#L13-L39) - -### Genesis Configuration Paths - -```json expandable -{ - "app_state": { - "vm": { - "preinstalls": [...], // Configure predeployed contracts - "params": { - "active_static_precompiles": [...] // Configure precompiles (different!) - } - } - } -} -``` - -## Further Resources - -### Official Specifications -- [EIP-1014: CREATE2 Specification](https://eips.ethereum.org/EIPS/eip-1014) - Understanding deterministic deployment -- [EIP-2935: Historical Block Hashes](https://eips.ethereum.org/EIPS/eip-2935) - Block hash storage specification - -### Contract Documentation -- [Multicall3 Documentation](https://github.com/mds1/multicall) - Official Multicall3 repository -- [Permit2 Introduction](https://blog.uniswap.org/permit2-and-universal-router) - Uniswap's Permit2 design -- [Safe Contracts](https://github.com/safe-global/safe-contracts) - Safe multisig implementation - -### Cosmos EVM Resources -- [VM Module Reference](evm/next/documentation/cosmos-sdk/modules/vm) - Complete VM module configuration \ No newline at end of file +| Error | Cause | Fix | +|-------|-------|-----| +| `preinstall already has an account in account keeper` | Address already has a contract | Choose a different address | +| `preinstall has empty code hash` | Invalid or empty bytecode | Verify bytecode hex string is valid and non-empty | +| `preinstall address is not a valid hex address` | Malformed address | Ensure 0x prefix and 40 hex characters | +| `invalid authority` | Wrong governance address | Use the correct gov module account address | diff --git a/evm/next/documentation/getting-started/build-a-chain/overview.mdx b/evm/next/documentation/getting-started/build-a-chain/overview.mdx index 29a875cae..5c80f4967 100644 --- a/evm/next/documentation/getting-started/build-a-chain/overview.mdx +++ b/evm/next/documentation/getting-started/build-a-chain/overview.mdx @@ -31,7 +31,7 @@ Configure the EVM mempool for nonce gap handling and transaction prioritization
- + Deploy standard contracts at genesis for Create2, Multicall3, Permit2, and Safe
diff --git a/evm/next/documentation/getting-started/build-a-chain/quick-start.mdx b/evm/next/documentation/getting-started/build-a-chain/quick-start.mdx index de64e40a5..fc9860284 100644 --- a/evm/next/documentation/getting-started/build-a-chain/quick-start.mdx +++ b/evm/next/documentation/getting-started/build-a-chain/quick-start.mdx @@ -1,172 +1,66 @@ --- -title: "Build A Custom EVM Chain" +title: "Run an EVM Chain" description: "Create your own blockchain by forking and customizing the Cosmos EVM reference chain (evmd). This guide covers the example chain configuration, running the chain locally, and understanding the foundation for building your custom network." --- -# Example Cosmos EVM Chain - -The `evmd` directory in the Cosmos EVM repository contains an example chain that demonstrates the integration of Cosmos EVM modules. This reference implementation is based on the simapp implementation from the Cosmos SDK repository, which provides a simplified yet complete blockchain foundation. - - -This chain implementation serves two primary purposes: -1. **Demonstration**: Shows how to integrate Cosmos EVM modules into a blockchain -2. **Testing Foundation**: Provides a working chain for development and testing - -You can use evmd as the starting point for building your own custom chain. - +The `evmd` [directory in the Cosmos EVM repository](https://github.com/cosmos/evm/tree/main/evmd) contains an example chain that demonstrates the integration of Cosmos EVM modules. This reference implementation is based on the simapp implementation from the Cosmos SDK repository, which provides a simplified yet complete blockchain foundation. ## Prerequisites -You'll need a standard Go development environment: +Make sure you have the following prerequisites: - **Go 1.23.8+** - [Installation guide](https://go.dev/doc/install) -- **Git** - For repository management -- **Make** - For build commands -- **GCC/Build Tools** - Required for CGo compilation +- **Git** - [Installation guide](https://git-scm.com/downloads) +- **Make** - [Installation guide](https://www.gnu.org/software/make/) +- **GCC/Build Tools** - [Installation guide](https://gcc.gnu.org/install/) -If you're new to Go development, ensure your `$GOPATH/bin` is in your system PATH. Most package managers (Homebrew, apt, pacman) handle this automatically. +If you're new to Go development, ensure your `$GOPATH/bin` is in your system PATH. Most package managers (Homebrew, apt, pacman) handle this automatically. See the [Go environment setup guide](https://go.dev/doc/gopath_code) for details. -## Building Your Custom Chain +## Building `evmd` The `evmd` implementation serves as the foundation for building your own custom blockchain. To create your chain: - - -Start by forking the Cosmos EVM repository: +1. **Fork the repository** — Clone the Cosmos EVM repository: ```bash git clone https://github.com/cosmos/evm.git cd evm ``` - - - -Rename the `evmd` directory and update all references: - -```bash -# Rename directory -mv evmd yourchain - -# Update imports and binary name -find . -type f -name "*.go" -exec sed -i 's/evmd/yourchain/g' {} \; -``` - -Update `go.mod` to reflect your repository path. - - - -Modify the default configuration in your chain: - -- **Chain IDs**: Update Cosmos chain ID and EVM chain ID -- **Bech32 Prefix**: Set your address prefix in `evmd/config/config.go` -- **Token Denomination**: Configure in genesis -- **Precompiles**: Enable only the precompiles you need -- **Modules**: Add or remove modules based on requirements - - - -Use the local node script to test your changes: +2. **Run the chain** — Run the local node script to start the chain: ```bash ./local_node.sh -y ``` - -Verify that: -- The chain starts successfully -- JSON-RPC is accessible -- Wallets can connect -- Transactions work as expected - - - -Once testing is complete, prepare for testnet deployment: - -- Set up validator infrastructure -- Configure persistent peers -- Coordinate genesis with validators -- Launch the network - - - - -## Default Configuration - -The example chain (`evmd`) comes with the following default configuration: - -| Option | Value | Description | -|---------------------|------------------------|-------------| -| **Binary** | `evmd` | The compiled chain binary name | -| **Chain ID** | `cosmos_262144-1` | Default Cosmos chain ID (format: `name_evmChainID-version`) | -| **EVM Chain ID** | `262144` | EVM chain ID for transaction replay protection | -| **Custom Opcodes** | - | No custom opcodes by default | -| **Token Pairs** | 1 (native token) | Default ERC20 token pair for the native denomination | -| **Denomination** | `atest` | Native token denomination (18 decimals, atto-prefix) | -| **EVM Permissioning** | Permissionless | Anyone can deploy and call contracts | -| **Enabled Precompiles** | All | All nine static precompiles are enabled by default | - - -The default configuration uses an 18-decimal token (`atest`) which provides direct EVM compatibility without requiring the precisebank module. This is the recommended setup for new chains. - - -## Running The Chain - -To run the example chain locally, use the provided local node script from the repository root: +The script runs `make install` before starting, so the `evmd` binary will be available in your `$GOPATH/bin` once it completes. The JSON-RPC server will be available at `http://localhost:8545`. ```bash -./local_node.sh [FLAGS] -``` - -### Available Flags - -- `-y`: Overwrite previous database (fresh start) -- `-n`: Do **not** overwrite previous database (resume from previous state) -- `--no-install`: Skip installation of the binary (use existing binary) -- `--remote-debugging`: Build a binary suitable for remote debugging - - -The `local_node.sh` script handles all the setup including: -- Building the `evmd` binary -- Initializing the chain configuration -- Setting up genesis parameters -- Starting the chain with JSON-RPC enabled - - -### Example Usage - - -```bash Fresh Start -# Start with a clean slate -./local_node.sh -y +evmd status +evmd keys list +evmd query bank balances
+evmd --help # full list of commands ``` -```bash Resume Previous State -# Continue from where you left off -./local_node.sh -n -``` +## `local_node.sh` Flags -```bash Development Mode -# Skip rebuild if binary already exists -./local_node.sh --no-install -``` +The following are the available flags for the local node script: -```bash Debug Mode -# Build with debugging symbols -./local_node.sh --remote-debugging +```bash +./local_node.sh -y # fresh start (overwrite previous database) +./local_node.sh -n # resume from previous state +./local_node.sh --no-install # skip rebuild, use the existing binary +./local_node.sh --remote-debugging # build with debugging symbols (for remote debugging) ``` - -## Connect to Wallet +## Connect a Wallet Once the chain is running, you can connect using any Ethereum-compatible wallet. The example below uses MetaMask: ### MetaMask Setup - - -Use the following seed phrase when adding a new wallet in MetaMask: +**1. Import the test account** — Add a new wallet in MetaMask using this seed phrase: ``` gesture inject test cycle original hollow east ridge hen combine @@ -175,14 +69,10 @@ unhappy lunar seat ``` -**Notice**: This is a well-known test seed phrase. **Never** use it for mainnet or with real funds. It's provided solely for local development and testing purposes. +This is a well-known test seed phrase. **Never** use it for mainnet or with real funds. - - -1. Click the **Network** button on the top left of MetaMask -2. Click **Add custom network** at the bottom of the modal -3. Configure the network with these settings: +**2. Add the network** — Go to **Networks → Add custom network** and enter: | Setting | Value | |---------|-------| @@ -190,72 +80,86 @@ unhappy lunar seat | **RPC URL** | `http://localhost:8545` | | **Chain ID** | `262144` | | **Currency Symbol** | `TEST` | -| **Block Explorer URL** | (leave empty for local) | +| **Block Explorer URL** | (leave empty) | - -Make sure your local chain is running before adding the network. The RPC URL must be accessible from your browser. - - +**3. Verify** — Switch to "Cosmos EVM Local" in MetaMask. You should see your account balance and can now send transactions. - -After adding the network: -- Switch to the "Cosmos EVM Local" network in MetaMask -- You should see your account balance (if the test account was funded in genesis) -- You can now interact with the chain through MetaMask - - +**4. Send a test transaction** — Send 1 TEST to `0x742d35cc6644c068532fddb11B4C36A58D6D3eAb` to confirm end-to-end transaction flow is working. -## Key Concepts +## Deploy a Solidity Contract with Forge -Before diving into configuration, familiarize yourself with: +With the chain running, you can deploy Solidity contracts using [Forge](https://book.getfoundry.sh/forge/). Install it with `curl -L https://foundry.paradigm.xyz | bash && foundryup` if you haven't already. -**Precompiled Contracts** - [Precompiles](/evm/next/documentation/smart-contracts/precompiles) bridge EVM smart contracts with Cosmos SDK modules, enabling Solidity contracts to access staking, governance, IBC, and other native functionality. +1. **Create a contract** — Save the following as `Counter.sol`: -**Cosmos SDK Modules** - Explore the [core modules](/evm/next/documentation/cosmos-sdk) that provide blockchain functionality: -- [Bank](/sdk/v0.53/build/modules/bank) - Token transfers and balances -- [Staking](/sdk/v0.53/build/modules/staking) - Validator delegation and rewards -- [Governance](/sdk/v0.53/build/modules/gov) - On-chain voting and proposals -- [Slashing](/sdk/v0.53/build/modules/slashing) - Validator penalty enforcement -- [Distribution](/sdk/v0.53/build/modules/distribution) - Fee and reward distribution +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; -## Understanding the Stack +contract Counter { + uint256 public count; + function increment() public { count++; } +} +``` -Before diving into configuration, it's helpful to understand what you're building with: +2. **Deploy it** — Use the dev0 test account private key to deploy: -- **[Cosmos SDK Modules](/evm/next/documentation/cosmos-sdk)** - Core blockchain functionality including staking, governance, and token management -- **[Precompiles](/evm/next/documentation/smart-contracts/precompiles)** - Smart contract interfaces that bridge EVM and Cosmos SDK capabilities -- **[Security & Audits](/evm/next/documentation/overview#audits)** - Third-party security assessments of the codebase +```bash +forge create Counter.sol:Counter \ + --rpc-url http://localhost:8545 \ + --private-key 0x88cbead91aee890d27bf06e003ade3d4e952427e88f88d31d61d3ef5e5d54305 \ + --broadcast +``` + + +This private key is for local development only. Never use it with real funds. + + +3. **Interact with the contract** — Read the current count, send a transaction to increment it, then read again to confirm the state change: + +```bash +# Read current count (returns 0) +cast call "count()(uint256)" --rpc-url http://localhost:8545 + +# Increment the counter +cast send "increment()" \ + --rpc-url http://localhost:8545 \ + --private-key 0x88cbead91aee890d27bf06e003ade3d4e952427e88f88d31d61d3ef5e5d54305 + +# Read again (returns 1) +cast call "count()(uint256)" --rpc-url http://localhost:8545 +``` -## Advanced Configuration +## Configuration -For specialized customization beyond the core configuration: +### Basic Chain Configuration -## Advanced Configuration +The following are some examples of basic configuration options for the `evmd` chain. -For specialized customization beyond the core configuration: +| Setting | Default | How to change | Reference | +|---------|---------|---------------|-----------| +| **Cosmos Chain ID** | `cosmos_262144-1` | Pass `--chain-id` at node start | — | +| **EVM Chain ID** | `262144` | Pass `--evm-chain-id` at node start | [`x/vm/types/params.go`](https://github.com/cosmos/evm/blob/main/x/vm/types/params.go) | +| **Bech32 Prefix** | `cosmos` | Change `Bech32Prefix` constant | [`evmd/config/bech32.go`](https://github.com/cosmos/evm/blob/main/evmd/config/bech32.go) | +| **Token Denomination** | `aatom` | Update `ExampleAttoDenom`, used by `NewMintGenesisState()` | [`testutil/constants/constants.go`](https://github.com/cosmos/evm/blob/main/testutil/constants/constants.go) | +| **EVM Permissioning** | Permissionless | Set `AccessType` in `DefaultAccessControl` | [`x/vm/types/params.go`](https://github.com/cosmos/evm/blob/main/x/vm/types/params.go) | +| **Precompiles** | All (9 enabled) | Replace `AvailableStaticPrecompiles` in `NewEVMGenesisState()` | [`evmd/genesis.go`](https://github.com/cosmos/evm/blob/main/evmd/genesis.go) | +| **Modules** | Standard SDK set | Register, set the pre-begin-, begin-, and endblockers, genesis module order, and keeper initialization | [`evmd/app.go`](https://github.com/cosmos/evm/blob/main/evmd/app.go) | +| **Binary name** | `evmd` | Rename directory and run `find . -type f -name "*.go" -exec sed -i 's/evmd/yourchain/g' {} \;`, then update `go.mod` | — | -
- -Configure the EVM mempool for nonce gap handling and transaction prioritization - -
-
- -Deploy standard contracts at genesis for Create2, Multicall3, Permit2, and Safe - -
+### Advanced Configuration -### Recommended Reading +`evmd` works out of the box with sensible defaults. The following are optional configurations for chains that need to go further. - - -EVM execution and parameter configuration - +| Configuration | Description | Reference | +|---------------|-------------|-----------| +| **Mempool** | Custom transaction prioritization, nonce gap handling, pool size limits | [Mempool Configuration](/evm/next/documentation/getting-started/build-a-chain/additional-configuration/mempool-integration) | +| **Fee Market** | Disable base fee, set min gas price, tune base fee adjustment rate | [Fee Market Module](/evm/next/documentation/cosmos-sdk/modules/feemarket) | +| **EVM Access Control** | Restrict contract deployment/calls to whitelisted addresses | [VM Module](/evm/next/documentation/cosmos-sdk/modules/vm) | +| **JSON-RPC** | Enable/disable namespaces, set resource caps, configure WebSocket origins | [Node Configuration](/evm/next/documentation/getting-started/network-operators/node-configuration) | +| **Predeployed Contracts** | Deploy Create2, Multicall3, Permit2, Safe at genesis | [Predeployed Contracts](/evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts) | +| **Precompiles** | Enable built-in precompiles or add custom ones | [Precompile Configuration](/evm/next/documentation/getting-started/build-a-chain/additional-configuration/precompiles) | - -Precompiled contracts and integration - - For additional support and community resources, visit the [Cosmos EVM GitHub repository](https://github.com/cosmos/evm) or join the Cosmos developer community. \ No newline at end of file diff --git a/evm/next/documentation/getting-started/faq.mdx b/evm/next/documentation/getting-started/faq.mdx index f7fdd66fa..b32a2daf3 100644 --- a/evm/next/documentation/getting-started/faq.mdx +++ b/evm/next/documentation/getting-started/faq.mdx @@ -3,23 +3,105 @@ title: "Frequently Asked Questions" --- + + Cosmos EVM is an open-source [Cosmos SDK](https://docs.cosmos.network) module that embeds a full Ethereum Virtual Machine into a CometBFT-based blockchain. You can launch a sovereign L1 that runs standard Solidity contracts and supports the full Ethereum toolchain, while also getting things Ethereum doesn't have: single-block finality, no reorganizations, native IBC cross-chain transfers, and direct Cosmos SDK module access from smart contracts. + + Unlike rollups, you control your own validator set, governance, and fee economics. See the [overview](/evm/next/documentation/overview) for more. + + + + Yes, fully. Cosmos EVM chains implement the complete Ethereum JSON-RPC API and execute the same EVM bytecode. Contracts that work on Ethereum work on Cosmos EVM without code changes, and tools like MetaMask, Hardhat, Foundry, ethers.js, and viem all work as-is. + + The differences are additions, not substitutions: faster finality (~1–2 seconds vs. ~3 minutes on Ethereum), no reorgs, native IBC, and [precompiles](/evm/next/documentation/smart-contracts/precompiles/overview) that expose Cosmos SDK functionality from Solidity. See the [EVM Compatibility page](/evm/next/documentation/evm-compatibility) for a full breakdown. + + + + Yes. All opcodes, ABI encoding, and libraries work the same as on Ethereum. Any contract that compiles and runs on Ethereum runs on a Cosmos EVM chain without modification. Point your tooling at your chain's RPC endpoint and chain ID and you're set. + + + + No. Use Hardhat, Foundry, or Remix pointed at your chain's JSON-RPC endpoint. Deployment goes through `eth_sendRawTransaction` and is processed by the EVM module the same way as on Ethereum. The contract gets an Ethereum address and behaves as expected. + + See the [quick start guide](/evm/next/documentation/getting-started/build-a-chain/quick-start#deploy-a-solidity-contract-with-forge) for a step-by-step deployment walkthrough with Forge. + + + + Any tool that speaks standard Ethereum JSON-RPC works without modification: + + - **Contract development:** [Hardhat](https://hardhat.org), [Foundry](https://book.getfoundry.sh), [Remix](https://remix.ethereum.org) + - **Libraries:** [ethers.js](https://docs.ethers.org/v6/), [viem](https://viem.sh), [wagmi](https://wagmi.sh), [web3.js](https://web3js.org) + - **Wallets:** [MetaMask](https://metamask.io), [Rabby](https://rabby.io), [WalletConnect](https://walletconnect.com), [Keplr](https://www.keplr.app) + - **Block explorers:** [Blockscout](https://github.com/blockscout/blockscout) + + See the [Tooling & Resources page](/evm/next/documentation/getting-started/tooling-and-resources) for the full list. + + + + Cosmos EVM supports all standard EVM opcodes and EIPs up to the Prague hard fork. Some notable ones: + + | EIP | Purpose | + |-----|---------| + | EIP-155 | Replay protection via chain ID in signatures | + | EIP-712 | Typed structured data signing | + | EIP-1559 | Dynamic fees (base fee + priority fee) | + | EIP-2535 | Diamond proxy pattern for upgradeable contracts | + | EIP-4337 | Account abstraction | + | EIP-7702 | Set code for EOAs | + + Two things are not supported: [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) (blob transactions) and [EIP-4399](https://eips.ethereum.org/EIPS/eip-4399) (PREVRANDAO). See the [EVM Compatibility page](/evm/next/documentation/evm-compatibility#eips) for the complete list. + + + + Precompiles are smart contract interfaces at fixed addresses where the implementation runs as native Go code rather than EVM bytecode. On standard Ethereum, precompiles handle things like signature verification and hashing. Cosmos EVM adds stateful precompiles that let Solidity contracts interact directly with Cosmos SDK modules. + + From Solidity, you can call the staking precompile to delegate tokens, the governance precompile to submit a proposal, or the ICS20 precompile to send an IBC transfer, all within a single transaction. Built-in precompiles include: + + | Precompile | Address | Purpose | + |------------|---------|---------| + | Staking | `0x...0800` | Delegate, undelegate, claim rewards | + | Distribution | `0x...0801` | Staking rewards and community pool | + | ICS20 | `0x...0802` | IBC cross-chain token transfers | + | Bank | `0x...0804` | ERC-20 access to native Cosmos tokens | + | Governance | `0x...0805` | Submit proposals and vote | + + See the [Precompiles Overview](/evm/next/documentation/smart-contracts/precompiles/overview) for the full list of addresses and interfaces. + + + + Predeployed contracts (also called preinstalls) are standard EVM contracts deployed at their canonical Ethereum addresses from genesis. Any tooling that expects them at those addresses works without extra setup. + + Cosmos EVM ships five by default: + + | Contract | Purpose | + |----------|---------| + | Create2 | Deterministic contract deployment | + | Multicall3 | Batch multiple calls in one transaction | + | Permit2 | Signature-based ERC-20 approvals | + | Safe Singleton Factory | Deploy Safe multisig wallets | + | EIP-2935 | Historical block hash storage | + + See the [Predeployed Contracts page](/evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts) for addresses, configuration, and how to add your own. + + + + The quickest path is running the example chain locally. It takes a few minutes and only requires Go and Make. The [Quick Start guide](/evm/next/documentation/getting-started/build-a-chain/quick-start) covers cloning the repo, starting the chain, connecting a wallet, and deploying your first contract. + + We're working on a migration guide for this and will have it posted up here as soon as possible! - - secp256k1 and ed25519 are both popular cryptographic algorithms used for digital signatures and key generation, but they have some differences in terms of security, performance, and compatibility with different systems. - secp256k1 is an elliptic curve algorithm that is widely used in Bitcoin and many other cryptocurrencies. It provides 128-bit security, which is considered sufficient for most practical purposes. secp256k1 is relatively fast and efficient, making it a good choice for applications that require high performance. It is widely supported by most cryptographic libraries and software, which makes it a good choice for cross-platform applications. + + Both are elliptic curve algorithms that produce 128-bit security. The practical difference is compatibility vs. attack surface. - ed25519 is a newer elliptic curve algorithm that provides 128-bit security, similar to secp256k1. However, ed25519 is generally considered to be more secure than secp256k1, due to its resistance to certain types of attacks such as [side-channel attacks](https://en.wikipedia.org/wiki/Side-channel_attack). It is also faster than many other elliptic curve algorithms, including secp256k1, making it a good choice for applications that require high performance. + secp256k1 is the curve used by Bitcoin and most EVM chains. It's well-tested, broadly supported, and the natural choice when you need to interoperate with existing crypto infrastructure, including Ethereum tooling and wallets. - In terms of compatibility, secp256k1 is more widely supported by existing systems, while ed25519 is less widely supported. However, ed25519 is gaining popularity, and is supported by many cryptographic libraries and software. + ed25519 is faster for signature verification and resistant to certain [side-channel attacks](https://en.wikipedia.org/wiki/Side-channel_attack) that can affect secp256k1. Cosmos SDK validators default to ed25519 for this reason. The tradeoff is narrower tool support, though that gap has closed over time. - When choosing between secp256k1 and ed25519, you should consider your specific needs in terms of security, performance, and compatibility. If you are building an application that requires high performance and compatibility with existing systems, secp256k1 may be a better choice. However, if you are building an application that requires a higher level of security and performance, and you can afford to sacrifice some compatibility, ed25519 may be a better choice. + In practice, the context usually decides for you: EVM contracts and Ethereum-style accounts use secp256k1; Cosmos validator keys use ed25519. - Please go to the Cosmos [Buf](https://buf.build/cosmos) project page. + See the Cosmos [Buf](https://buf.build/cosmos) project page. - diff --git a/evm/next/documentation/getting-started/tooling-and-resources.mdx b/evm/next/documentation/getting-started/tooling-and-resources.mdx new file mode 100644 index 000000000..3a14721a4 --- /dev/null +++ b/evm/next/documentation/getting-started/tooling-and-resources.mdx @@ -0,0 +1,58 @@ +--- +title: Tooling & Resources +description: Tools, libraries, wallets, and explorers for building on Cosmos EVM. +--- + +Cosmos EVM implements a complete Ethereum execution environment, so the standard development toolchain carries over without modification. You can use any of the EVM tools you already know; just point them at your chain's RPC endpoint and chain ID. + +## Development Tools + +The following tools are a few examples of the many tools that are available for development on Cosmos EVM: + +| Tool | Description | +|------|-------------| +| [Hardhat](https://hardhat.org) | JavaScript/TypeScript-based framework with a flexible plugin system and Ethers.js integration. | +| [Foundry](https://book.getfoundry.sh) | Rust-based toolkit with Solidity-native tests and fast execution. Includes `forge`, `cast`, `anvil`, and `chisel`. | +| [OpenZeppelin Contracts](https://docs.openzeppelin.com/contracts) | Audited implementations of common standards — ERC-20, ERC-721, access control, and more. | + +## Client Libraries + +| Library | Description | +|---------|-------------| +| [Ethers.js](https://docs.ethers.org/v6/) | JS/TS library for contract interaction, transaction signing, and provider management. | +| [Viem](https://viem.sh) | TypeScript-first, tree-shakeable library for RPC calls, ABI encoding, and contract access. Used by Wagmi. | +| [Wagmi](https://wagmi.sh) | React hooks for wallet connection, chain state, and contract reads/writes. Built on Viem. | +| [RainbowKit](https://www.rainbowkit.com) | React component library for wallet connection UI. Integrates with Wagmi. | +## Wallets + +See the [quick-start guide](/evm/next/documentation/getting-started/build-a-chain/quick-start#connect-a-wallet) for a walkthrough of connecting MetaMask to a local chain. The following are a few examples of the many wallets that are available for development on Cosmos EVM: + +| Wallet | Notes | +|--------|-------| +| [MetaMask](https://metamask.io) | Add network via Settings → Networks | +| [Rabby](https://rabby.io) | Add network via Settings → Networks | +| [WalletConnect](https://walletconnect.com) | Standard WalletConnect integration | +| [Keplr](https://www.keplr.app) | Supports both Cosmos and Ethereum transaction formats | +| [Leap](https://www.leapwallet.io) | Supports both Cosmos and Ethereum transaction formats | +| Ledger | Compatible via MetaMask or other wallet interfaces | + +To add a chain manually, you'll need: the network name, RPC URL (port 8545), chain ID, and currency symbol. + +## Block Explorers + +Cosmos EVM chains support two types of explorer: EVM explorers for Ethereum-formatted data and Cosmos explorers for Cosmos and IBC data. [Mintscan](https://mintscan.io) supports both but requires a custom integration. + +| Explorer | Type | Link | +|----------|------|------| +| Blockscout | EVM | [GitHub](https://github.com/blockscout/blockscout) | +| Ping.pub | Cosmos | [GitHub](https://github.com/ping-pub/explorer) | +| BigDipper | Cosmos | [GitHub](https://github.com/forbole/big-dipper-2.0-cosmos) | + +## Testing & Analysis + +| Tool | Purpose | +|------|---------| +| [Slither](https://github.com/crytic/slither) | Static analysis — detects common vulnerability patterns in Solidity. | +| [solidity-coverage](https://github.com/sc-forks/solidity-coverage) | Reports untested code branches. Works with Hardhat and Foundry. | +| [Echidna](https://github.com/crytic/echidna) | Property-based fuzzer for Solidity contracts. | +| [OpenZeppelin Test Helpers](https://github.com/OpenZeppelin/openzeppelin-test-helpers) | Time manipulation, event assertions, and revert testing for Hardhat/Mocha. | diff --git a/evm/next/documentation/getting-started/tooling-and-resources/block-explorers.mdx b/evm/next/documentation/getting-started/tooling-and-resources/block-explorers.mdx deleted file mode 100644 index 21d5d86ed..000000000 --- a/evm/next/documentation/getting-started/tooling-and-resources/block-explorers.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: "Block Explorers" -description: "Blockchain explorers allow users to query the blockchain for data. Explorers are often compared to search engines for the blockchain. By using an explorer, users can search and track balances, transactions, contracts, and other broadcast data to the blockchain." ---- - -Cosmos EVM chains can use two types block explorers: an EVM explorer and a Cosmos explorer. Each explorer queries data respective to their environment with the EVM explorers querying Ethereum-formatted data (blocks, transactions, accounts, smart contracts, etc) and the Cosmos explorers querying Cosmos-formatted data (Cosmos and IBC transactions, blocks, accounts, module data, etc). - -## List of Block Explorers[​](#list-of-block-explorers "Direct link to List of Block Explorers") - -Below is a list of open source explorers that you can use: - -| Service | Support | URL | -| ---------- | ---------- | --------------------------------------------------------------- | -| Ping.Pub | `cosmos` | [Github Repo](https://github.com/ping-pub/explorer) | -| BigDipper | `cosmos` | [Github Repo](https://github.com/forbole/big-dipper-2.0-cosmos) | -| Blockscout | `ethereum` | [Github Repo](https://github.com/blockscout/blockscout) | - -## Cosmos & EVM Compatible explorers[​](#cosmos--evm-compatible-explorers "Direct link to Cosmos & EVM Compatible explorers") - -As of yet, there is no open source explorer that supports both EVM and Cosmos transactions. [Mintscan](https://mintscan.io/) does support this but requires an integration. - diff --git a/evm/next/documentation/getting-started/tooling-and-resources/development-environment.mdx b/evm/next/documentation/getting-started/tooling-and-resources/development-environment.mdx deleted file mode 100644 index 0183dfd6d..000000000 --- a/evm/next/documentation/getting-started/tooling-and-resources/development-environment.mdx +++ /dev/null @@ -1,121 +0,0 @@ ---- -title: "Development Environment Setup" -description: "A guide to setting up a local environment for Cosmos EVM development." ---- - -Taking the time to set up the overall development environment is often overlooked, yet is one of the most important tasks. -Each person has their own preference and different tasks or scopes of work may call for vastly different setups, so this section will cover just enough to get you started, and pointed in the right direction. - -## IDE Setup - - -[Remix](https://remix.ethereum.org) is a full-feature IDE in a web-app supporting all EVM compatible networks out of the box. A convenient option For quick testing, or as a self-contained smart contract depoyment interface. -[Read more..](/evm/next/documentation/getting-started/tooling-and-resources/remix.mdx) - - - -### Visual Studio / Visual Studio Code - -"VSCode" is widely used and has unparalelled extension support. - -#### Essential Extensions - -- **Solidity by Nomic Foundation**: Syntax highlighting, code completion, and linting. -- **Go by Google**: Required for Cosmos SDK development. -- **Prettier - Code formatter**: For automated code formatting. -- **ESLint**: For JavaScript/TypeScript error detection. - -#### VS Code Configuration - -Create a `.vscode/settings.json` file in your project root: - -```json -{ - "go.testFlags": ["-v"], - "go.testTimeout": "60s", - "go.lintTool": "golangci-lint", - "solidity.defaultCompiler": "remote", - "solidity.compileUsingRemoteVersion": "v0.8.20+commit.a1b79de6" -} -``` - -## Core Tooling - -### Node.js - -Most smart contract frameworks require Node.js. Install using Node Version Manager (nvm): - -```bash -# Install nvm -curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash - -# Install latest LTS Node.js -nvm install --lts - -# Install yarn (recommended over npm) -npm install -g yarn -``` - -### Go - -Required for Cosmos SDK development: - -```bash -# Install Go from https://go.dev/doc/install -# Verify installation -go version -``` - -## Environment Configuration - -Configure your shell environment variables in `~/.bashrc` or `~/.zshrc`: - -```bash -# Set Go paths -export GOPATH=$HOME/go -export PATH=$PATH:$GOPATH/bin - -# Useful aliases -alias evm-build='make build' -alias evm-test='make test' -``` - -## Development Workflow - - -Always use the provided `make` targets for consistency with core developers and CI/CD pipelines. - - -### Common Commands - -```bash -make build # Build binaries -make test # Run tests -make lint # Check code style -make format # Format code -``` - -### Project Structure - -``` -cosmos-evm/ -├── app/ # Application configuration -├── x/ # Custom modules -│ ├── evm/ # EVM module -│ └── feemarket/ # Fee market module -├── tests/ # Integration tests -└── Makefile # Build automation -``` - -## Next Steps - -With your environment configured, explore the development tools: - - - - Fast, efficient smart contract development and testing - - - Flexible environment for compiling, deploying, and debugging - - diff --git a/evm/next/documentation/getting-started/tooling-and-resources/foundry.mdx b/evm/next/documentation/getting-started/tooling-and-resources/foundry.mdx deleted file mode 100644 index a54d46273..000000000 --- a/evm/next/documentation/getting-started/tooling-and-resources/foundry.mdx +++ /dev/null @@ -1,180 +0,0 @@ ---- -title: "Foundry Guide - Setup & Walkthrough" -description: "An introduction to Foundry and using the `cast` function, replacing complex scripts that may otherwise require multiple rpc calls and other functions in between with a single command." ---- - -Foundry is a fast and modular toolkit for Ethereum application development written in Rust. It provides four main command-line tools—`forge`, `cast`, `anvil`, and `chisel`—to streamline everything from project setup to live-chain interactions. - -Among these, `cast` serves as your "Swiss-army knife" for JSON-RPC calls, letting you execute tedious day-to-day tasks (like sending raw transactions, querying balances, fetching blocks, and looking up chain metadata) with simple, consistent commands instead of verbose `curl` scripts. - -This guide walks you through installing Foundry, configuring your environment, and using the most common `cast` commands to accelerate your development workflow. - -## Installation & Setup - -### Install Foundry - -Run the following command to install `foundryup`, the Foundry toolchain installer. This will give you the four main binaries. - -```bash lines -curl -L https://foundry.paradigm.xyz | bash -foundryup -``` - -After installation, you can switch to the nightly builds for the latest features, though this is optional. - -```bash lines -foundryup -i nightly -``` - -### Verify Installation - -Check that each binary was installed correctly by running: - -```bash lines expandable -foundryup --version -cast --version -forge --version -anvil --version -``` - -You should see version outputs for each tool (e.g., `cast 0.2.0`). - -## Configuration - -To avoid passing the `--rpc-url` flag with every command, you can set defaults in a `foundry.toml` file. This file can be placed in your project's root directory for project-specific settings, or you can create a global configuration at `~/.foundry/foundry.toml` for settings you use across all projects. - -Here is an example of a global configuration for connecting to a local Cosmos EVM node: - -```toml title="~/.foundry/foundry.toml" lines expandable -# ~/.foundry/foundry.toml - -# Declare your named endpoints (optional; for forge test / forking) -[rpc_endpoints] -cosmos = "" - -# Configure the default profile for cast/forge/anvil -[profile.default] -# Tell Foundry which chain you're targeting: -chain_id = 4321 -# Directly tell cast to use your endpoint: -eth_rpc_url = "" -# Set EVM version for Solidity compilation -evm_version = "istanbul" -``` - -With this global configuration, Foundry tools will automatically connect to your local node without needing additional flags. - -## Basic Usage of `cast` - -`cast` replaces the need for custom shell scripts and verbose `curl` commands by offering first-class RPC commands. - -### Chain Metadata - -- **Get Chain ID** - ```bash lines - cast chain-id --rpc-url local - ``` - Returns the chain ID in decimal format. - -- **Get Client Version** - ```bash lines - cast client --rpc-url local - ``` - Displays the client implementation and version (e.g., `reth/v1.0.0`). - -## `cast` Command Reference - -### Chain Commands - -| Command | Purpose | -| :--- | :--- | -| `cast chain` | Show the symbolic name of the current chain. | -| `cast chain-id` | Fetch the numeric chain ID. | -| `cast client` | Get the JSON-RPC client version. | - -**Example**: -```bash lines -# Assuming FOUNDRY_RPC_URL is set or using a configured alias -cast chain -cast chain-id -cast client -``` - -### Transaction Commands - -| Command | Purpose | -| :--- | :--- | -| `cast send` | Sign and publish a transaction. | -| `cast publish` | Publish a raw, signed transaction. | -| `cast receipt` | Fetch the receipt for a transaction hash. | -| `cast tx` | Query transaction details (status, logs, etc.). | -| `cast rpc` | Invoke any raw JSON-RPC method. | - -- **Sign and Send** (using a private key or local keystore): - ```bash lines - cast send 0xRecipientAddress "transfer(address,uint256)" "0xSomeOtherAddress,100" --private-key $YOUR_PK - ``` - -- **Publish Raw Transaction** (hex-encoded): - ```bash lines - cast publish 0xf86b808504a817c80082520894... - ``` - -- **Generic RPC Call**: - ```bash lines - cast rpc eth_sendRawTransaction 0xf86b8085... - ``` - -### Account & Block Commands - -| Command | Purpose | -| :--- | :--- | -| `cast balance` | Get an account's balance (supports ENS and units). | -| `cast block` | Fetch block information by number or hash. | -| `cast block-number`| Get the latest block number. | -| `cast logs` | Query event logs. | - -- **Get Balance** (with unit flag): - ```bash lines - # Using an ENS name on Ethereum mainnet - cast balance vitalik.eth --ether --rpc-url https://eth.merkle.io - ``` - -- **Get Block Details**: - ```bash lines - cast block latest - ``` - -### Utility & Conversion Commands - -| Command | Purpose | -| :--- | :--- | -| `cast estimate` | Estimate gas for a call or deployment. | -| `cast find-block` | Find a block by its timestamp. | -| `cast compute-address`| Calculate a CREATE2 address. | -| `cast from-bin` | Decode binary data to hex. | -| `cast from-wei` | Convert wei to a more readable unit (e.g., ether). | -| `cast to-wei` | Convert a unit (e.g., ether) to wei. | -| `cast abi-encode` | Encode function arguments. | -| `cast keccak` | Hash data with Keccak-256. | - -These commands allow you to drop one-off scripts for common conversions and estimations. - -## Streamlining Repetative / Tedious tasks - -When performing testing or development roles you may find yourself doing one or more small but very -tedious tasks frequently. -In your shell's configuration file (`~/.bashrc`, `~/.zshrc`), you can alias `cast` with your default RPC URL -(or multiple on various chains) to save time. - -```bash lines expandable -# Set your default RPC endpoint -export CDEV_RPC="" -# Create an alias -alias ccast='cast --rpc-url $CDEV_RPC' - -# Now you can run commands like: -ccast balance 0x... -``` - -This is an extremely basic example of how you can improve your workflows by building upon the heavy lifting Foundry already does out of the box. \ No newline at end of file diff --git a/evm/next/documentation/getting-started/tooling-and-resources/hardhat.mdx b/evm/next/documentation/getting-started/tooling-and-resources/hardhat.mdx deleted file mode 100644 index 73961ba9d..000000000 --- a/evm/next/documentation/getting-started/tooling-and-resources/hardhat.mdx +++ /dev/null @@ -1,237 +0,0 @@ ---- -title: "Hardhat Guide: Setup & Workflows" -description: "A guide to setting up and using the Hardhat development environment for building, testing, and deploying on Cosmos EVM." ---- - -Hardhat is a flexible and extensible Ethereum development environment that is fully compatible with Cosmos EVM. It's an excellent choice for teams with JavaScript/TypeScript expertise or those who need complex deployment and testing workflows. - -## Project Setup and Configuration - -Initialize and configure a new Hardhat project for Cosmos EVM development. - -### 1. Installation - -```bash lines expandable -mkdir cosmos-evm-hardhat -cd cosmos-evm-hardhat -npm init -y -npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox @openzeppelin/contracts -npx hardhat init # Select "Create a TypeScript project" -``` - -### 2. Configuration - -Modify `hardhat.config.ts` to include networks and settings for Cosmos EVM. - -```typescript title="hardhat.config.ts" lines expandable -import { HardhatUserConfig } from "hardhat/config"; -import "@nomicfoundation/hardhat-toolbox"; -import "dotenv/config"; - -const config: HardhatUserConfig = { - solidity: { - version: "0.8.24", - settings: { - optimizer: { - enabled: true, - runs: 200, - }, - evmVersion: "istanbul" - }, - }, - networks: { - local: { - url: "http://127.0.0.1:8545", - chainId: 4321, // Your EVM chain ID - accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [], - gasPrice: 20000000000, - }, - testnet: { - url: "", - chainId: 4321, // Your EVM chain ID - accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [], - } - }, - gasReporter: { - enabled: process.env.REPORT_GAS !== undefined, - currency: "USD", - }, - etherscan: { - apiKey: { - cosmosEvmTestnet: process.env.ETHERSCAN_API_KEY || "dummy_key" - }, - customChains: [ - { - network: "cosmosEvmTestnet", - chainId: 4321, // Your EVM chain ID - urls: { - apiURL: "", - browserURL: "" - } - } - ] - } -}; - -export default config; -``` - -## TypeScript Integration - -Hardhat's first-class TypeScript support enables type-safe contract interactions and tests. - -### 1. Writing a Contract - -Create a contract in the `contracts/` directory. For this example, we'll use a simple `LiquidStakingVault`. - -```solidity title="contracts/LiquidStakingVault.sol" lines expandable -// contracts/LiquidStakingVault.sol -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import "@openzeppelin/contracts/access/Ownable.sol"; - -// Interface for the staking precompile -interface IStaking { - function delegate(address validator, uint256 amount) external returns (bool); - function undelegate(address validator, uint256 amount) external returns (bool, uint64); -} - -contract LiquidStakingVault is Ownable { - IStaking constant STAKING = IStaking(0x0000000000000000000000000000000000000800); - - mapping(address => uint256) public stakedBalance; - address public primaryValidator; - uint256 public totalStaked; - - event Staked(address indexed user, uint256 amount); - - constructor(address _primaryValidator) Ownable(msg.sender) { - primaryValidator = _primaryValidator; - } - - function stake() external payable { - require(msg.value > 0, "Must stake positive amount"); - bool success = STAKING.delegate(primaryValidator, msg.value); - require(success, "Delegation failed"); - stakedBalance[msg.sender] += msg.value; - totalStaked += msg.value; - emit Staked(msg.sender, msg.value); - } -} -``` - -### 2. Writing Tests - -Create type-safe tests in the `test/` directory. - -```typescript title="test/LiquidStakingVault.test.ts" lines expandable -// test/LiquidStakingVault.test.ts -import { expect } from "chai"; -import { ethers } from "hardhat"; -import { LiquidStakingVault } from "../typechain-types"; -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; - -describe("LiquidStakingVault", function () { - let vault: LiquidStakingVault; - let owner: SignerWithAddress; - let user1: SignerWithAddress; - - const STAKING_PRECOMPILE = "0x0000000000000000000000000000000000000800"; - const VALIDATOR_ADDRESS = "0x1234567890123456789012345678901234567890"; - - beforeEach(async function () { - [owner, user1] = await ethers.getSigners(); - - const VaultFactory = await ethers.getContractFactory("LiquidStakingVault"); - vault = await VaultFactory.deploy(VALIDATOR_ADDRESS); - await vault.waitForDeployment(); - - // Mock the staking precompile's delegate function to always return true - // This bytecode is a minimal contract that returns true for any call - const successBytecode = "0x6080604052348015600f57600080fd5b50600160005560016000f3"; - await ethers.provider.send("hardhat_setCode", [ - STAKING_PRECOMPILE, - successBytecode, - ]); - }); - - it("Should allow a user to stake tokens", async function () { - const stakeAmount = ethers.parseEther("1.0"); - - await expect(vault.connect(user1).stake({ value: stakeAmount })) - .to.emit(vault, "Staked") - .withArgs(user1.address, stakeAmount); - - expect(await vault.stakedBalance(user1.address)).to.equal(stakeAmount); - expect(await vault.totalStaked()).to.equal(stakeAmount); - }); -}); -``` - -Run your tests: -```bash lines -npx hardhat test -``` - -## Deployment Scripts - -Create a deployment script in the `scripts/` directory to deploy your contract to a live network. - -```typescript title="scripts/deploy.ts" lines expandable -// scripts/deploy.ts -import { ethers, network } from "hardhat"; -import { writeFileSync } from "fs"; - -async function main() { - const [deployer] = await ethers.getSigners(); - - console.log("Deploying contracts with the account:", deployer.address); - - const validatorAddress = process.env.VALIDATOR_ADDRESS || "0x0000000000000000000000000000000000000000"; - - const VaultFactory = await ethers.getContractFactory("LiquidStakingVault"); - const vault = await VaultFactory.deploy(validatorAddress); - await vault.waitForDeployment(); - - const vaultAddress = await vault.getAddress(); - console.log("LiquidStakingVault deployed to:", vaultAddress); - - // Save deployment information - const deploymentInfo = { - contractAddress: vaultAddress, - deployer: deployer.address, - network: network.name, - chainId: network.config.chainId, - }; - - writeFileSync( - `deployments/${network.name}-deployment.json`, - JSON.stringify(deploymentInfo, null, 2) - ); - - // Optional: Verify contract on Etherscan-compatible explorer - if (network.name !== "local" && process.env.ETHERSCAN_API_KEY) { - console.log("Waiting for block confirmations before verification..."); - // await vault.deploymentTransaction()?.wait(5); // Wait for 5 blocks - await new Promise(resolve => setTimeout(resolve, 30000)); // Or wait 30 seconds - - await hre.run("verify:verify", { - address: vaultAddress, - constructorArguments: [validatorAddress], - }); - } -} - -main() - .then(() => process.exit(0)) - .catch((error) => { - console.error(error); - process.exit(1); - }); -``` - -Run the deployment script: -```bash lines -npx hardhat run scripts/deploy.ts --network testnet -``` \ No newline at end of file diff --git a/evm/next/documentation/getting-started/tooling-and-resources/overview.mdx b/evm/next/documentation/getting-started/tooling-and-resources/overview.mdx deleted file mode 100644 index 2bac0f3ce..000000000 --- a/evm/next/documentation/getting-started/tooling-and-resources/overview.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: Overview -description: "Tooling and resources to 10x your development workflows." ---- - -## Client Integrations - -Client libraries play a crucial role indevelopment by making it easier for developers interact with the underlying protocols. -Well-made libraries abstract away complexities and provide optimized methods to allow developers to focus on their project rather than the network itself." - -EthersJS and Web3JS are two most commonly used libraries in dApp development. Developer uses these libraries to interact with blockchain and query JSON-RPC data, for example. Additionally, both of these libraries contain utilities to aid in task like converting large numbers (BigNumber). - -* [Ethers.js](https://docs.ethers.org/v6/) is the latest JS library that aims to be a complete and compact library for interacting with the Ethereum Blockchain and its ecosystem. - - -## Development & Testing Toolkits - - - - Fast, modular toolkit for Solidity and Forge-based development, testing, and - deployment workflows. - - - - Flexible, plug-in-rich environment for building, testing, and deploying - smart contracts with TypeScript support. - - - - Libraries, fuzzers, and best practices to ensure contract correctness, - safety, and edge-case coverage. - - - - Browser-based integrated development environment for rapid prototyping, - debugging, and interactive contract deployment. - - diff --git a/evm/next/documentation/getting-started/tooling-and-resources/remix.mdx b/evm/next/documentation/getting-started/tooling-and-resources/remix.mdx deleted file mode 100644 index 427616f32..000000000 --- a/evm/next/documentation/getting-started/tooling-and-resources/remix.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: "Remix IDE" -description: "Deploy and test smart contracts on Cosmos EVM chains using the Remix browser-based IDE" ---- - -# Remix IDE - -[Remix](https://remix.ethereum.org) is a powerful browser-based IDE that allows you to write, compile, deploy, and test smart contracts directly from your web browser. It's an excellent tool for rapid prototyping and testing smart contracts on Cosmos EVM chains without needing to set up a local development environment. - -## Connecting to Cosmos EVM Chains - -To deploy contracts to a Cosmos EVM chain through Remix, you'll need to use the **Injected Provider** option with MetaMask. - - - Remix cannot connect directly to custom RPC endpoints. You must use MetaMask as an intermediary to connect to Cosmos EVM chains. - - -### Step-by-Step Guide - -1. **Configure MetaMask**: First, add your Cosmos EVM chain to MetaMask with the correct RPC endpoint, Chain ID, and currency symbol. - -2. **Select Network in MetaMask**: Make sure the Cosmos EVM network you want to use is currently selected in MetaMask. - -3. **Open Remix**: Navigate to [https://remix.ethereum.org](https://remix.ethereum.org) - -4. **Deploy Your Contract**: - - Go to the "Deploy & Run Transactions" tab (the Ethereum icon in the sidebar) - - In the "Environment" dropdown, select **"Injected Provider - MetaMask"** - - Remix will automatically connect to the network currently selected in MetaMask - -![Remix Injected Provider Selection](/assets/public/remix-provider.png) - -5. **Confirm Connection**: MetaMask will prompt you to connect to Remix. Approve the connection to proceed. - -6. **Deploy and Interact**: You can now compile, deploy, and interact with your contracts on the Cosmos EVM chain through Remix. - -## Important Considerations - -- **Network Selection**: Always verify that MetaMask is connected to the correct network before deploying contracts -- **Gas Fees**: Ensure you have sufficient native tokens in your MetaMask wallet to pay for transaction fees -- **Chain Compatibility**: Your smart contracts should be compatible with the EVM version supported by the Cosmos chain - -## Additional Resources - -For more detailed information about using Remix IDE, including advanced features and troubleshooting, refer to the [official Remix documentation](https://remix-ide.readthedocs.io/en/latest/run.html). - - - **Quick Tip**: You can save your Remix workspace to GitHub or IPFS to preserve your contracts and deployment configurations across sessions. - \ No newline at end of file diff --git a/evm/next/documentation/getting-started/tooling-and-resources/testing-and-fuzzing.mdx b/evm/next/documentation/getting-started/tooling-and-resources/testing-and-fuzzing.mdx deleted file mode 100644 index 5749a95cf..000000000 --- a/evm/next/documentation/getting-started/tooling-and-resources/testing-and-fuzzing.mdx +++ /dev/null @@ -1,181 +0,0 @@ ---- -title: "Popular Libraries for Development, Testing & Fuzzing" -description: "Key frameworks, libraries, and practices for frontend development, wallet integration, smart contracts, testing and more." -mode: "wide" ---- - - -## Common Libraries & Tooling - -These libraries are used across the stack to write tests, simulate transactions, connect wallets, and interface with the blockchain in both scripting and frontend contexts. - -| Library | Purpose | Key Features | -|---------------|------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------| -| **Ethers.js** | Contract interaction, transaction signing, provider management in JS/TS environments | Provides `Contract`, `Provider`, `Wallet`, and `Interface` abstractions. Deep Hardhat integration. ABI coder, calldata utilities, and ENS support. | -| **Viem** | Modular TypeScript-first library for RPC, contract access, encoding, and data formatting | Tree-shakeable. Supports batching, client-side caching, EIP-1559 fees, multicalls, typed reads/writes. Used by Wagmi. | -| **Wagmi** | React hooks for wallet connection, chain state, and contract calls in frontend apps | Built on Viem. Includes `useAccount`, `useConnect`, `useContractRead`, and event subscriptions. Enables seamless integration with wallet modals. | -| **Web3.js** | Legacy Ethereum contract and RPC library | One of the earliest libraries. Now largely unmaintained. Lacks EIP-1559 support and modern modularity. | -| **RainbowKit** | React component library for wallet connection UI and chain management | Pre-built wallet connect buttons, chain switch UI, and custom themes. Integrates with Wagmi for wallet state management and tx handling. | - -> Ethers and Viem serve similar purposes, but Viem is optimized for frontend apps. Wagmi builds on Viem. Web3.js is no longer recommended for new projects. - ---- - - -## Testing Frameworks - -> **Note** -> Smart contract quality and security depend on a comprehensive testing strategy including but not limited to: -> -> - **Unit Tests**: Verify individual functions and components -> - **Property-Based Fuzzing**: Test invariants with random inputs -> - **Code Coverage**: Ensure all code paths are tested -> - **Static Analysis**: Detect common vulnerabilities and anti-patterns -> -> The tools and frameworks below provide a foundation for each of these testing layers. - - -### Foundry — Solidity-Native - -- Tests written directly in Solidity. -- Very fast runner (`forge test`) and rich cheatcodes for state manipulation. -- Built-in, configurable fuzzing (`forge test --fuzz-runs=N`). -- Includes tools like `forge script`, `forge coverage`, and `forge snapshot`. - -### Hardhat — JavaScript / TypeScript - -- Mocha + Chai test runner for JS/TS-based tests. -- Flexible task system (`hardhat.config.js`), plugin support, and network forking. -- Integrates with Ethers.js and Solidity tooling for deployments, gas tracking, and test orchestration. - -## v0.5.0 Compatibility Testing Framework - -Cosmos EVM v0.5.0 introduces comprehensive compatibility testing to ensure seamless integration with major Ethereum development tools. - -### EVM Tools Compatibility Testing - -**Automated Testing Suites:** Five comprehensive test suites validate compatibility with popular Ethereum tools: - -| Tool | Test Coverage | GitHub Workflow | -|------|---------------|-----------------| -| **Foundry** | Contract deployment, testing, gas estimation | `.github/workflows/tests-compatibility-foundry.yml` | -| **Hardhat** | Contract deployment, ethers.js integration | `.github/workflows/tests-compatibility-hardhat.yml` | -| **Viem** | TypeScript client compatibility, RPC methods | `.github/workflows/tests-compatibility-viem.yml` | -| **Web3.js** | Legacy client compatibility, transaction handling | `.github/workflows/tests-compatibility-web3js.yml` | -| **Foundry + UniswapV3** | Complex DeFi protocol deployment | `.github/workflows/tests-compatibility-foundry-uniswap-v3.yml` | - -### Running Compatibility Tests - -**Local Testing:** -```bash -# Run JSON-RPC compatibility tests -cd /path/to/cosmos-evm -make test-rpc-compat # Makefile:373 - -# Test specific tool -./scripts/tests_compatibility_foundry.sh -./scripts/tests_compatibility_hardhat.sh -./scripts/tests_compatibility_viem.sh -./scripts/tests_compatibility_web3js.sh -./scripts/tests_compatibility_foundry_uniswap_v3.sh -``` - -**Test Structure:** -``` -tests/evm-tools-compatibility/ -├── foundry/ # Foundry compatibility tests -├── hardhat/ # Hardhat + Ethers.js tests -├── viem/ # Viem TypeScript tests -├── web3.js/ # Web3.js legacy tests -└── foundry-uniswap-v3/ # Complex DeFi protocol tests -``` - -### JSON-RPC Compatibility Testing - -**Comprehensive RPC Validation:** New framework compares Cosmos EVM responses against geth for accuracy. - -**Setup:** -```bash -# Start comparison testing environment -cd tests/jsonrpc - -# Build required Docker images -make localnet-build-env - -# Start both evmd and geth for comparison -./scripts/start-networks.sh - -# Run compatibility test suite -cd simulator && go build . && ./simulator - -# Stop testing environment -./scripts/stop-networks.sh -``` - -**Test Coverage:** -- **Transaction Processing:** Compare transaction execution results -- **Block Queries:** Validate block structure and data -- **Account Queries:** Verify balance and nonce handling -- **Event Logs:** Ensure log filtering and retrieval accuracy -- **Gas Estimation:** Compare gas estimation algorithms - -**Configuration:** -```go -// tests/jsonrpc/simulator/config/config.go:27-36 -type Config struct { - EvmdHttpEndpoint string // Default: "http://localhost:8545" - EvmdWsEndpoint string // Default: "ws://localhost:8546" - GethHttpEndpoint string // Default: "http://localhost:8547" - GethWsEndpoint string // Default: "ws://localhost:8548" - RichPrivKey string - Timeout string -} -``` - -## Fuzz (Property-Based) Testing - -Fuzz testing generates random inputs to find edge cases that violate expected properties. - -```solidity title="test/MyContract.t.sol (Foundry)" lines expandable -// test/MyContract.t.sol (Foundry) -function test_myFunction_fuzz(uint256 amount) public { - vm.assume(amount > 0 && amount < 1e18); // constrain input - myContract.myFunction(amount); - assertEq(myContract.someState(), expectedValue); -} -``` - -| Tool | Notes | -| ----------- | ------------------------------------------------------------------- | -| **Foundry** | Built-in fuzzing; enabled by default when running `forge test`. | -| **Echidna** | External, property-based fuzzer. Supports invariants and campaigns. | - -Use fuzzing to test against invariants such as: - -* balance never exceeds total supply -* no overflow or underflow under bounded inputs -* access control is consistently enforced - -## Supplementary Tools - -Tools that enhance test coverage, assert correctness, or catch common vulnerabilities. - -| Tool | Purpose | Typical Command | -| ----------------------------- | --------------------------------------- | ----------------------------------------- | -| **OpenZeppelin Test Helpers** | Time travel, event assertions, reverts | JS/TS only. Works with Hardhat + Mocha. | -| **solidity-coverage** | Reports untested branches in Solidity | `npx hardhat coverage` · `forge coverage` | -| **Slither** | Static analysis for known vuln patterns | `slither .` | - -### Example — OpenZeppelin Test Helpers - -```js lines expandable -const { time, expectRevert } = require('@openzeppelin/test-helpers'); - -// advance clock by one day -await time.increase(time.duration.days(1)); - -// expect revert with specific reason -await expectRevert(contract.someFunction(), "Ownable: caller is not the owner"); -``` - ---- diff --git a/evm/next/documentation/getting-started/tooling-and-resources/wallet-integration.mdx b/evm/next/documentation/getting-started/tooling-and-resources/wallet-integration.mdx deleted file mode 100644 index 002825ae3..000000000 --- a/evm/next/documentation/getting-started/tooling-and-resources/wallet-integration.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "Wallet Integration" -description: "Wallet integration is an essential aspect of dApp development that allows users to securely interact with blockchain-based applications." ---- - -## EVM Wallet Compatibility[​](#evm-wallet-compatibility "Direct link to EVM Wallet Compatibility") - -**Any standard EVM wallet works out of the box with Cosmos EVM chains.** This includes popular wallets like MetaMask, Rabby, WalletConnect, and any other wallet that supports Ethereum and EVM-compatible chains. No special configuration or custom integration is required - simply add your chain's RPC endpoint and chain ID to any EVM wallet. - -### Key Integration Points[​](#key-integration-points "Direct link to Key Integration Points") - -* **Standard EVM RPC**: Cosmos EVM exposes the standard Ethereum JSON-RPC API, ensuring compatibility with all EVM wallets -* **EIP-1559 Support**: Full support for EIP-1559 dynamic fee transactions, enabling automatic gas estimation -* **Address Format**: Uses standard Ethereum addresses (0x format) for EVM transactions -* **Transaction Types**: Supports all standard Ethereum transaction types including legacy and EIP-1559 transactions - -## Wallet Support[​](#wallet-support "Direct link to Wallet Support") - -| Wallet | Type | Notes | -| ------------- | ------------ | ----------------------------------------------------- | -| MetaMask | EVM | Works out of the box - just add network RPC | -| Rabby | EVM | Works out of the box - just add network RPC | -| WalletConnect | EVM | Standard WalletConnect integration works | -| Keplr | Cosmos + EVM | Supports both Cosmos and Ethereum transaction formats | -| Leap | Cosmos + EVM | Supports both Cosmos and Ethereum transaction formats | -| Ledger | Hardware | Compatible via MetaMask or other wallet interfaces | - -## Client Libraries[​](#client-libraries "Direct link to Client Libraries") - -For programmatic wallet integration, use standard Ethereum client libraries like ethers.js, web3.js, or viem which are fully compatible with Cosmos EVM chains. - -## Quick Start[​](#quick-start "Direct link to Quick Start") - -To add a Cosmos EVM chain to MetaMask or any EVM wallet: - -1. Open your wallet and navigate to "Add Network" - -2. Enter the following details: - - * **Network Name**: Your chain name - * **RPC URL**: Your chain's JSON-RPC endpoint (port 8545) - * **Chain ID**: Your EVM chain ID (integer) - * **Currency Symbol**: Your native token symbol - * **Block Explorer URL**: (optional) Your chain's block explorer - -That's it! Your wallet is now ready to interact with the Cosmos EVM chain. - diff --git a/evm/next/documentation/overview.mdx b/evm/next/documentation/overview.mdx index 2d05d2b71..602ffa0c4 100644 --- a/evm/next/documentation/overview.mdx +++ b/evm/next/documentation/overview.mdx @@ -1,37 +1,52 @@ --- title: "Overview" -description: "Cosmos EVM is an open-source platform for teams building their own chain, rollup, or EVM-compatible application. It offers the industry's leading Layer 1 stack with custom modules, instant finality, and a native interoperability layer. With Cosmos EVM, you maintain full ownership of your entire stack—from the application layer down to consensus." -mode: "wide" --- +Cosmos EVM is an open-source Cosmos SDK module that embeds a full Ethereum Virtual Machine into a CometBFT-based chain. Deploy existing Solidity contracts, use standard EVM tooling, and launch a sovereign L1 with instant finality and native cross-chain support. + +Unlike rollups, Cosmos EVM chains control their own validator set, governance, and fee economics, all while preserving full Ethereum bytecode and JSON-RPC compatibility. + import { EthereumOutlineIcon, CosmosOutlineIcon } from '/snippets/icons.mdx' - } href="/evm/v0.5.0/documentation/evm-compatibility/overview"> - Deploy existing Solidity contracts, use familiar tools like MetaMask, Hardhat, and Foundry + + Build and run your own EVM-compatible chain using the evmd reference implementation - } href="/evm/v0.5.0/documentation/smart-contracts/precompiles/overview"> - Access staking, governance, IBC, and other Cosmos SDK modules directly from smart contracts + + Explore the source code, open issues, and contribute to Cosmos EVM - - 1-2 second block times with instant finality via 'CometBFT' consensus + } href="/evm/next/documentation/evm-compatibility"> + Deploy existing Solidity contracts and use MetaMask, Hardhat, Foundry, Remix, ethers.js, viem, and more - - Built-in IBC support for interoperability across a growing list of ecosystems + } href="/evm/next/documentation/smart-contracts/precompiles/overview"> + Access staking, governance, IBC, and other Cosmos SDK modules directly from smart contracts -## Why Cosmos EVM +## What you can build + +Cosmos EVM is for teams that want [full EVM compatibility](/evm/next/documentation/evm-compatibility) without giving up the benefits of launching a sovereign L1. You control the entire stack: the EVM execution environment, gas model, validator set, governance rules, and which Cosmos SDK modules to include. If you already deploy to Ethereum or EVM rollups, you can deploy to a Cosmos EVM chain with no contract changes. + +Chains can also run a permissioned EVM—restricting contract deployment or calls to whitelisted addresses—for use cases that require access controls at the protocol level. + +## EVM compatibility + +"EVM compatible" means your chain runs standard Ethereum bytecode. From a developer standpoint, it behaves like any Ethereum network: deploy Solidity contracts with Hardhat, Foundry, or Remix; connect MetaMask or any EVM wallet; use ethers.js, viem, or web3.js without changes. See the [full tooling list](/evm/next/documentation/getting-started/tooling-and-resources). + +Cosmos EVM implements the full [Ethereum JSON-RPC API](/evm/next/api-reference/ethereum-json-rpc/methods) and supports all common transaction formats: [EIP-155](https://eips.ethereum.org/EIPS/eip-155) (chain ID protection), [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) (dynamic fees), [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930) (access lists), and [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) (EOA code delegation). + +## Ethereum with more + +If you know Solidity, you already know how to build on Cosmos EVM. Contracts [compile and deploy the same way](/evm/next/documentation/getting-started/build-a-chain/quick-start), the [same opcodes are available](/evm/next/documentation/evm-compatibility#opcodes), and the same libraries work. The differences are additions, not substitutions. -Cosmos EVM provides a production-ready foundation for building EVM-compatible blockchains with the full power of the Cosmos SDK. The repository includes `evmd`, a fully functional reference implementation that serves as a boilerplate application for teams launching their own chains. +- **Instant finality:** On Ethereum, transactions reach probabilistic finality over multiple blocks. On Cosmos EVM, transactions are final after one block (~1–2 seconds) with no possibility of reorganization. Your contracts don't need to account for reorgs. +- **Fee distribution:** Both use EIP-1559 dynamic fees. The base fee on Cosmos EVM is distributed to validators and delegators rather than burned—same fee mechanics for the developer, different economics for the chain. +- **Native cross-chain:** Rather than relying on external bridge contracts, Cosmos EVM has [IBC (Inter-Blockchain Communication)](/evm/next/documentation/concepts/ibc) built into the protocol. Cross-chain token transfers are a first-class feature, accessible from Solidity via the [IBC precompile](/evm/next/documentation/smart-contracts/precompiles/ics20). +- **Precompiles:** Cosmos EVM exposes protocol-level functionality as precompiled contracts at fixed addresses. From Solidity, you can call into staking, distribution, governance, bank, IBC transfers (ICS-20), slashing, vesting, and address conversion utilities the same way you'd call any other contract. See the [precompiles reference](/evm/next/documentation/smart-contracts/precompiles/overview) for the full list of addresses and interfaces. +- **EIP-712 signing:** MetaMask and other EVM wallets can sign Cosmos SDK transactions—including governance votes, staking operations, and more—using the standard `eth_signTypedData` method. No separate Cosmos wallet required. -### Complete EVM Compatibility +## Getting started -From a developer's perspective, chains built with Cosmos EVM are **indistinguishable from canonical EVM chains** like Ethereum mainnet. Your existing tooling, workflows, and even AI coding assistants work without modification: +The quickest way to get started is [running the example chain locally](/evm/next/documentation/getting-started)— it takes less than 3 minutes and requires only Go and Make. -- **Deploy contracts** using Hardhat, Foundry, or Remix exactly as you would on Ethereum -- **Connect wallets** like MetaMask, WalletConnect, or Rabby without custom configuration -- **Use standard libraries** such as ethers.js, viem, and web3.js with zero changes -- **AI tools work seamlessly** - Claude, ChatGPT, and other AI assistants treat your local testnet as if it's Ethereum mainnet, deploying contracts and interacting with them using standard Ethereum patterns -All user-facing components are identical. The difference lies in what happens under the hood: instant finality, native IBC interoperability, and direct access to Cosmos SDK modules from your smart contracts. \ No newline at end of file diff --git a/evm/next/documentation/smart-contracts/introduction.mdx b/evm/next/documentation/smart-contracts/introduction.mdx deleted file mode 100644 index 96c17c3e1..000000000 --- a/evm/next/documentation/smart-contracts/introduction.mdx +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: "Introduction" -description: "Build and deploy EVM smart contracts on Cosmos chains with full Ethereum compatibility" ---- - -# Smart Contract Development on Cosmos EVM - -Since the introduction of Ethereum in 2015, the ability to control digital assets through smart contracts has attracted a large community of developers to build decentralized applications on the Ethereum Virtual Machine (EVM). Cosmos EVM brings this powerful ecosystem to Cosmos chains with full compatibility. - -> **Cosmos EVM is fully compatible with the EVM**, allowing you to use the same tools (Solidity, Remix, Oracles) and APIs (Ethereum JSON-RPC) that are available on Ethereum. - -## Why Build on Cosmos EVM? - -Whether you're building new use cases on a Cosmos EVM-enabled chain or porting an existing dApp from Ethereum, you can: - -* **Use familiar tools** - Deploy with the same Solidity contracts and development environment -* **Access Cosmos features** - Leverage cross-chain interoperability through IBC -* **Scale your applications** - Build on performant, application-specific blockchains -* **Extend functionality** - Use custom precompiles for staking, governance, and more - -## Getting Started - -### Build with Solidity - -Develop EVM smart contracts using [Solidity](https://github.com/ethereum/solidity), the most widely used smart contract language. If you've deployed on Ethereum or any EVM-compatible chain, you can use the same contracts on Cosmos EVM. - -* **Write Your First Contract:** Follow the [Solidity Beginner Tutorial](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html) -* **Set Up Your Tools:** Use [Hardhat](https://hardhat.org/getting-started/) or [Foundry](https://book.getfoundry.sh/) for your development environment -* **Test and Deploy:** Learn testing patterns with [OpenZeppelin's Guides](https://docs.openzeppelin.com/learn) -* **Ensure Security:** Follow [OpenZeppelin's Security Patterns](https://docs.openzeppelin.com/learn/security-patterns) - -### Deploy with Ethereum JSON-RPC - -Cosmos EVM supports the full [Ethereum JSON-RPC](/evm/next/api-reference/ethereum-json-rpc) API, enabling you to: - -* Deploy and interact with smart contracts using familiar web3 tools -* Connect existing Ethereum tooling without modifications -* Use [block explorers](/evm/next/documentation/getting-started/tooling-and-resources/block-explorers) to debug and monitor your contracts - -### Leverage Cosmos EVM Precompiles - -Unlike standard EVM, Cosmos EVM introduces **stateful precompiled contracts** that can perform state transitions. These custom precompiles enable: - -* **Native staking operations** - Stake tokens directly from smart contracts -* **On-chain governance** - Participate in governance through contract calls -* **Cross-chain communication** - Access IBC functionality programmatically -* **Advanced cryptography** - Use elliptic curve operations efficiently - -These precompiles open up functionality that would be impossible or prohibitively expensive with regular smart contracts. [View all available precompiles →](/evm/next/documentation/smart-contracts/precompiles) - -## Development Workflow - -1. **Choose your tooling** - Select from Hardhat, Foundry, or other familiar EVM development frameworks -2. **Write smart contracts** - Develop in Solidity with access to Cosmos-specific precompiles -3. **Test thoroughly** - Use existing testing frameworks with Cosmos EVM's full compatibility -4. **Deploy seamlessly** - Use Ethereum JSON-RPC to deploy just like on any EVM chain -5. **Monitor and iterate** - Use block explorers and debugging tools to refine your dApp - -## Resources - -* **Documentation:** [Cosmos EVM Precompiles](/evm/next/documentation/smart-contracts/precompiles) | [Tooling Guide](/evm/next/documentation/getting-started/tooling-and-resources/overview) -* **Community:** [Discord](https://discord.gg/interchain) | [Cosmos Forum](https://forum.cosmos.network) -* **Examples:** Browse sample contracts and integration patterns in our guides - -Start building cross-chain applications today with the power of EVM and the interoperability of Cosmos. \ No newline at end of file diff --git a/evm/next/documentation/smart-contracts/precompiles/index.mdx b/evm/next/documentation/smart-contracts/precompiles/index.mdx deleted file mode 100644 index 7c9bd776b..000000000 --- a/evm/next/documentation/smart-contracts/precompiles/index.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: "Precompiled Contracts" -description: "A hub for precompiled contracts that bridge EVM and Cosmos SDK modules." -keywords: ['precompiles', 'precompiled contracts', 'cosmos sdk', 'evm', 'smart contracts', 'hybrid applications', 'token decimals', 'native functionality', 'solidity interface', 'cosmos integration', 'chain precision', 'gas efficient'] ---- - -## Available Precompiles - -Access native Cosmos SDK features directly from Solidity: - - - - Interface with native Cosmos SDK tokens for balance and supply queries. - - - Convert addresses between Ethereum hex and Cosmos bech32 formats. - - - Handle IBC packet lifecycle callbacks in smart contracts. - - - Withdraw staking rewards and interact with the community pool. - - - Utilize standard ERC20 token functionality for native Cosmos tokens. - - - Participate in on-chain governance through proposals and voting. - - - Perform cross-chain token transfers via the IBC protocol. - - - Execute P-256 elliptic curve cryptographic operations. - - - Manage validator slashing and jailing for network security. - - - Perform validator operations, manage delegations, and handle staking. - - - Wrap native tokens to provide ERC20-compatible functionality. - - \ No newline at end of file diff --git a/evm/next/documentation/smart-contracts/precompiles/overview.mdx b/evm/next/documentation/smart-contracts/precompiles/overview.mdx index 3d812bfcb..967c134ee 100644 --- a/evm/next/documentation/smart-contracts/precompiles/overview.mdx +++ b/evm/next/documentation/smart-contracts/precompiles/overview.mdx @@ -5,226 +5,34 @@ icon: "code" keywords: ['precompiles', 'precompiled contracts', 'cosmos sdk', 'evm', 'smart contracts', 'staking', 'governance', 'ibc', 'bank', 'distribution', 'slashing', 'evidence', 'bech32', 'p256', 'erc20', 'werc20', 'callbacks'] --- -## Available Precompiles +Precompiles are smart contract interfaces deployed at fixed addresses where the implementation runs as native Go code rather than EVM bytecode. In standard Ethereum, precompiles are stateless and handle things like signature verification and hashing. In Cosmos EVM, they can also be stateful — reading from and writing to Cosmos SDK module state outside the EVM. -| Precompile | Address | Purpose | Reference | -| ---------------- | -------------------------------------------- | ---------------------------------------------------------------- | ------------------------- | -| **P256** | `0x0000000000000000000000000000000000000100` | P-256 elliptic curve cryptographic operations | [Details](./p256) | -| **Bech32** | `0x0000000000000000000000000000000000000400` | Address format conversion between Ethereum hex and Cosmos bech32 | [Details](./bech32) | -| **Staking** | `0x0000000000000000000000000000000000000800` | Validator operations, delegation, and staking rewards | [Details](./staking) | -| **Distribution** | `0x0000000000000000000000000000000000000801` | Staking rewards and community pool management | [Details](./distribution) | -| **ICS20** | `0x0000000000000000000000000000000000000802` | Cross-chain token transfers via IBC | [Details](./ics20) | -| **Vesting** | `0x0000000000000000000000000000000000000803` | Vesting account creation and management | Coming Soon | -| **Bank** | `0x0000000000000000000000000000000000000804` | ERC20-style access to native Cosmos SDK tokens | [Details](./bank) | -| **Governance** | `0x0000000000000000000000000000000000000805` | On-chain governance proposals and voting | [Details](./governance) | -| **Slashing** | `0x0000000000000000000000000000000000000806` | Validator slashing and jail management | [Details](./slashing) | -| **ERC20** | Dynamic per token | Standard ERC20 functionality for native Cosmos tokens | [Details](./erc20) | -| **WERC20** | Dynamic per token | Wrapped native token functionality | [Details](./werc20) | - -## Configuration +This is what makes them powerful: a smart contract can call the staking precompile to delegate tokens, the governance precompile to submit a proposal, or the IBC precompile to send tokens cross-chain — all using a standard Solidity interface, all within a single transaction. -Precompiled contracts provide direct, gas-efficient access to native Cosmos SDK functionality from within the EVM. Build powerful hybrid applications that leverage the best of both worlds. This page provides an overview of the available precompiled contracts, each with detailed documentation on its usage, Solidity interface, and ABI. +Calls are bidirectional. EVM contracts can call precompiles, and precompiles can call back into EVM contracts. When a precompile is invoked, execution routes from the EVM through the corresponding Cosmos SDK module and returns the result to the EVM for continued execution. Gas is metered across both environments. - **Critical: Understanding Token Decimals in Precompiles** - - All Cosmos EVM precompile contracts use the **native chain's decimal precision**, not Ethereum's standard 18 decimals (wei). - - **Why this matters:** - - Cosmos chains typically use 6 decimals, while Ethereum uses 18 - - Passing values while assuming conventional Ethereum exponents could cause significant miscalculations - - Example: On a 6-decimal chain, passing `1000000000000000000` (1 token in wei) will be interpreted as **1 trillion tokens** - - **Before using any precompile:** - 1. Check your chain's native token decimal precision - 2. Convert amounts to match the native token's format - 3. Never assume 18-decimal precision + All precompile contracts use the native chain's decimal precision, not Ethereum's standard 18 decimals. - ```solidity - // WRONG: Assuming Ethereum's 18 decimals - uint256 amount = 1 ether; // 1000000000000000000 - staking.delegate(validator, amount); // Delegates 1 trillion tokens! + Cosmos chains typically use 6 decimals. Passing a value like `1000000000000000000` (1 ETH in wei) to a precompile on a 6-decimal chain will be interpreted as 1 trillion tokens. - // CORRECT: Using chain's native 6 decimals - uint256 amount = 1000000; // 1 token with 6 decimals - staking.delegate(validator, amount); // Delegates 1 token - ``` + Always check your chain's decimal precision before interacting with a precompile, and convert amounts accordingly. -### Genesis Configuration - -Precompiles must be enabled in the genesis file to be available on the network. The `active_static_precompiles` parameter controls which precompiles are activated at network launch. - -```json -{ - "app_state": { - "vm": { - "params": { - "active_static_precompiles": [ - "0x0000000000000000000000000000000000000100", // P256 - "0x0000000000000000000000000000000000000400", // Bech32 - "0x0000000000000000000000000000000000000800", // Staking - "0x0000000000000000000000000000000000000801", // Distribution - "0x0000000000000000000000000000000000000802", // ICS20 - "0x0000000000000000000000000000000000000803", // Vesting - "0x0000000000000000000000000000000000000804", // Bank - "0x0000000000000000000000000000000000000805", // Governance - "0x0000000000000000000000000000000000000806" // Slashing - ] - } - } - } -} -``` - - -For complete genesis configuration including EVM and fee market parameters, see the [Node Configuration](/evm/next/documentation/getting-started/network-operators/node-configuration) reference. - - -## v0.5.0 Breaking Changes - - -**Precompile Constructor Interface Changes** - -All precompile constructors in v0.5.0 now require keeper interfaces instead of concrete keeper implementations. This improves decoupling and testability but requires updates to custom precompile implementations. - - -### Interface Requirements - -**Before (v0.4.x):** -```go -// Concrete keeper types required -bankPrecompile, err := bankprecompile.NewPrecompile( - bankKeeper, // bankkeeper.Keeper concrete type - stakingKeeper, // stakingkeeper.Keeper concrete type - // ... other keepers -) -``` - -**After (v0.5.0):** -```go -// Keeper interfaces required (parameters accept interfaces directly) -bankPrecompile, err := bankprecompile.NewPrecompile( - bankKeeper, // common.BankKeeper interface - erc20Keeper, // erc20keeper.Keeper interface -) -``` - -**Source:** [`evmd/precompiles.go:122`](https://github.com/cosmos/evm/blob/main/evmd/precompiles.go#L122) - -### Required Interfaces - -The following keeper interfaces are defined in [`precompiles/common/interfaces.go`](https://github.com/cosmos/evm/blob/main/precompiles/common/interfaces.go): - -- `BankKeeper`: Account balances, token transfers, metadata -- `StakingKeeper`: Validator operations, delegations, bond denom -- `DistributionKeeper`: Reward withdrawals and distribution -- `SlashingKeeper`: Validator slashing information -- `TransferKeeper`: IBC transfer operations -- `ChannelKeeper`: IBC channel and connection queries -- `ERC20Keeper`: Token pair mappings and conversions +## Built-in Precompiles -### Migration Example - -**Custom Precompile Migration:** -```go -// Before (v0.4.x) -func NewCustomPrecompile( - bankKeeper bankkeeper.Keeper, - stakingKeeper stakingkeeper.Keeper, -) (*CustomPrecompile, error) { - return &CustomPrecompile{ - bankKeeper: bankKeeper, - stakingKeeper: stakingKeeper, - }, nil -} - -// After (v0.5.0) -func NewCustomPrecompile( - bankKeeper common.BankKeeper, // Interface instead of concrete type - stakingKeeper common.StakingKeeper, // Interface instead of concrete type -) (*CustomPrecompile, error) { - return &CustomPrecompile{ - bankKeeper: bankKeeper, - stakingKeeper: stakingKeeper, - }, nil -} -``` - -**Assembly Updates:** -```go -// In your precompile assembly function (based on evmd/precompiles.go) -func NewAvailableStaticPrecompiles( - stakingKeeper stakingkeeper.Keeper, - distributionKeeper distributionkeeper.Keeper, - bankKeeper cmn.BankKeeper, // Already interface type - erc20Keeper erc20keeper.Keeper, - // ... other keeper interfaces - opts ...Option, -) map[common.Address]vm.PrecompiledContract { - precompiles := make(map[common.Address]vm.PrecompiledContract) - - // No casting needed - parameters are already interface types - bankPrecompile, err := bankprecompile.NewPrecompile(bankKeeper, erc20Keeper) - if err != nil { - panic(fmt.Errorf("failed to instantiate bank precompile: %w", err)) - } - precompiles[bankPrecompile.Address()] = bankPrecompile -) -if err != nil { - return nil, err -} -precompiles[bankAddress] = bankPrecompile -``` - -## Integration Guide - -### Activation - -Precompiles must be explicitly activated via the `active_static_precompiles` parameter: - -```bash -# Via genesis configuration -{ - "active_static_precompiles": [ - "0x0000000000000000000000000000000000000804", // Bank - "0x0000000000000000000000000000000000000800" // Staking - ] -} - -# Via governance proposal -evmd tx gov submit-proposal param-change-proposal.json --from validator -``` - -### Usage in Smart Contracts - -```solidity -// Import precompile interfaces -import "./IBank.sol"; -import "./IStaking.sol"; - -contract MyDApp { - IBank constant bank = IBank(0x0000000000000000000000000000000000000804); - IStaking constant staking = IStaking(0x0000000000000000000000000000000000000800); - - function getBalance(string memory denom) external view returns (uint256) { - return bank.balances(msg.sender, denom); - } - - function delegateTokens(string memory validatorAddr, uint256 amount) external { - staking.delegate(msg.sender, validatorAddr, amount); - } -} -``` - -### Testing - -All precompiles include comprehensive Solidity test suites for validation: - -```bash -# Run precompile tests -cd tests && npm test - -# Test specific precompile -npx hardhat test test/Bank.test.js -``` +| Precompile | Address | Purpose | Reference | +| ---------------- | -------------------------------------------- | ---------------------------------------------------------------- | ------------------------- | +| P256 | `0x0000000000000000000000000000000000000100` | P-256 elliptic curve signature verification | [Details](/evm/next/documentation/smart-contracts/precompiles/p256) | +| Bech32 | `0x0000000000000000000000000000000000000400` | Address format conversion between Ethereum hex and Cosmos bech32 | [Details](/evm/next/documentation/smart-contracts/precompiles/bech32) | +| Staking | `0x0000000000000000000000000000000000000800` | Validator operations, delegation, and staking rewards | [Details](/evm/next/documentation/smart-contracts/precompiles/staking) | +| Distribution | `0x0000000000000000000000000000000000000801` | Staking rewards and community pool management | [Details](/evm/next/documentation/smart-contracts/precompiles/distribution) | +| ICS20 | `0x0000000000000000000000000000000000000802` | Cross-chain token transfers via IBC | [Details](/evm/next/documentation/smart-contracts/precompiles/ics20) | +| Bank | `0x0000000000000000000000000000000000000804` | ERC20-style access to native Cosmos SDK tokens | [Details](/evm/next/documentation/smart-contracts/precompiles/bank) | +| Governance | `0x0000000000000000000000000000000000000805` | On-chain governance proposals and voting | [Details](/evm/next/documentation/smart-contracts/precompiles/governance) | +| Slashing | `0x0000000000000000000000000000000000000806` | Validator slashing and jail management | [Details](/evm/next/documentation/smart-contracts/precompiles/slashing) | +| ICS02 | `0x0000000000000000000000000000000000000807` | IBC light client queries | [Source](https://github.com/cosmos/evm/tree/main/precompiles/ics02) | +| ERC20 | Dynamic per token | Standard ERC20 interface for native Cosmos tokens | [Details](/evm/next/documentation/smart-contracts/precompiles/erc20) | +| WERC20 | Dynamic per token | Wrapped native token functionality | [Details](/evm/next/documentation/smart-contracts/precompiles/werc20) | + +Chain builders can control which precompiles are active and add their own. See the [Precompile Configuration guide](/evm/next/documentation/getting-started/build-a-chain/additional-configuration/precompiles) for details. diff --git a/evm/next/documentation/smart-contracts/predeployed-contracts/create2.mdx b/evm/next/documentation/smart-contracts/predeployed-contracts/create2.mdx deleted file mode 100644 index eb98b1467..000000000 --- a/evm/next/documentation/smart-contracts/predeployed-contracts/create2.mdx +++ /dev/null @@ -1,303 +0,0 @@ ---- -title: "Create2 Factory" -description: "Deterministic contract deployment factory using the CREATE2 opcode" -icon: "factory" -keywords: ['create2', 'deterministic', 'deployment', 'factory', 'salt', 'address', 'prediction', 'bytecode'] ---- - -The Create2 Factory is a minimal proxy contract that enables deterministic contract deployment using the CREATE2 opcode. This allows developers to deploy contracts to addresses that can be computed in advance, regardless of the deployer's nonce or transaction order. - -**Contract Address**: `0x4e59b44847b379578588920ca78fbf26c0b4956c` -**Deployment Status**: Default preinstall -**Gas Cost**: Deployment cost + ~32,000 gas overhead - -## Key Features - -- **Deterministic Addresses**: Compute contract addresses before deployment -- **Cross-chain Consistency**: Same address on all chains with the same bytecode and salt -- **Minimal Implementation**: Only 45 bytes of optimized assembly code -- **No Storage or State**: Pure function contract with no storage variables - -## How It Works - -The CREATE2 opcode computes addresses using: -``` -address = keccak256(0xff ++ deployerAddress ++ salt ++ keccak256(bytecode))[12:] -``` - -This formula ensures that the same inputs always produce the same address, enabling: -- Pre-funding of contract addresses before deployment -- Cross-chain address consistency -- Gasless contract deployment patterns - -## Usage - -### Deploy a Contract - - -```javascript "Ethers.js Create2 Contract Deployment" expandable -import { ethers } from "ethers"; - -const provider = new ethers.JsonRpcProvider("YOUR_RPC_URL"); -const signer = new ethers.Wallet("YOUR_PRIVATE_KEY", provider); - -// Create2 Factory address -const CREATE2_FACTORY = "0x4e59b44847b379578588920ca78fbf26c0b4956c"; - -// Your contract bytecode (including constructor args) -const bytecode = "0x608060405234801561001057600080fd5b50..."; // Your compiled bytecode - -// Choose a salt (32 bytes) -const salt = ethers.id("my-unique-salt-v1"); // Or use ethers.randomBytes(32) - -// Deploy using Create2 -async function deployWithCreate2() { - // Compute the deployment address - const deployAddress = ethers.getCreate2Address( - CREATE2_FACTORY, - salt, - ethers.keccak256(bytecode) - ); - - console.log("Contract will be deployed to:", deployAddress); - - // Send deployment transaction - const tx = await signer.sendTransaction({ - to: CREATE2_FACTORY, - data: salt + bytecode.slice(2), // Concatenate salt and bytecode - gasLimit: 3000000, // Adjust based on your contract - }); - - console.log("Deployment tx:", tx.hash); - await tx.wait(); - - console.log("Contract deployed to:", deployAddress); - return deployAddress; -} - -deployWithCreate2(); -``` - -```solidity "Solidity Create2 Deployer Contract" expandable -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -contract Create2Deployer { - address constant CREATE2_FACTORY = 0x4e59b44847b379578588920ca78fbf26c0b4956c; - - function deployContract( - bytes32 salt, - bytes memory bytecode - ) external returns (address) { - // Prepare deployment data - bytes memory deploymentData = abi.encodePacked(salt, bytecode); - - // Deploy via Create2 factory - (bool success, bytes memory result) = CREATE2_FACTORY.call(deploymentData); - require(success, "Create2 deployment failed"); - - // Extract deployed address from return data - address deployed = abi.decode(result, (address)); - return deployed; - } - - function computeAddress( - bytes32 salt, - bytes memory bytecode - ) external pure returns (address) { - bytes32 hash = keccak256( - abi.encodePacked( - bytes1(0xff), - CREATE2_FACTORY, - salt, - keccak256(bytecode) - ) - ); - return address(uint160(uint256(hash))); - } -} -``` - - -### Compute Deployment Address - -You can calculate the deployment address without actually deploying: - -```javascript -import { ethers } from "ethers"; - -function computeCreate2Address(salt, bytecode) { - const factoryAddress = "0x4e59b44847b379578588920ca78fbf26c0b4956c"; - - const address = ethers.getCreate2Address( - factoryAddress, - salt, - ethers.keccak256(bytecode) - ); - - return address; -} - -// Example usage -const salt = ethers.id("my-deployment-v1"); -const bytecode = "0x608060405234801561001057600080fd5b50..."; -const futureAddress = computeCreate2Address(salt, bytecode); -console.log("Contract will deploy to:", futureAddress); -``` - -## Common Use Cases - - - - Deploy contracts to the same address across multiple chains: - ```javascript - const salt = ethers.id("myapp-v1.0.0"); - // Same salt + bytecode = same address on all chains - ``` - - - - Interact with contracts before they're deployed: - 1. Compute the future address - 2. Send funds or tokens to that address - 3. Deploy the contract later when needed - - - - Predictable upgrade addresses using versioned salts: - ```javascript - const v1Salt = ethers.id("mycontract-v1"); - const v2Salt = ethers.id("mycontract-v2"); - ``` - - - - Build factory contracts with deterministic child addresses: - ```solidity - function deployChild(uint256 nonce) external { - bytes32 salt = keccak256(abi.encode(msg.sender, nonce)); - // Deploy with predictable address - } - ``` - - - -## Implementation Details - -The Create2 factory contract is extremely minimal: - -```assembly -// Entire contract bytecode (45 bytes) -0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3 -``` - -This assembly code: -1. Reads the salt (32 bytes) and bytecode from calldata -2. Uses the CREATE2 opcode to deploy the contract -3. Returns the deployed contract address - -## Best Practices - - - **Security Considerations**: - - Always verify bytecode integrity before deployment - - Be aware that anyone can deploy to a CREATE2 address if they have the bytecode and salt - - Consider using access controls in your factory contracts - - -### Salt Selection - -Choose salts carefully for your use case: - -```javascript "Salt Selection Strategies" expandable -// Sequential salts for multiple instances -const salt1 = ethers.solidityPacked(["uint256"], [1]); -const salt2 = ethers.solidityPacked(["uint256"], [2]); - -// User-specific salts -const userSalt = ethers.solidityPacked(["address", "uint256"], [userAddress, nonce]); - -// Version-based salts -const versionSalt = ethers.id("v1.2.3"); - -// Random salts for uniqueness -const randomSalt = ethers.randomBytes(32); -``` - -### Gas Optimization - -- The Create2 factory adds ~32,000 gas overhead -- Batch deployments in a single transaction when possible -- Pre-compute addresses to avoid on-chain calculations - -## Comparison with CREATE - -| Aspect | CREATE | CREATE2 | -|--------|--------|---------| -| Address Calculation | Based on deployer + nonce | Based on deployer + salt + bytecode | -| Predictability | Requires knowing nonce | Fully deterministic | -| Cross-chain | Different addresses | Same address possible | -| Gas Cost | Baseline | ~32,000 gas overhead | -| Use Case | Standard deployments | Deterministic deployments | - -## Troubleshooting - -Common issues and solutions: - -| Issue | Solution | -|-------|----------| -| "Create2 deployment failed" | Ensure sufficient gas and correct bytecode format | -| Address mismatch | Verify salt and bytecode are identical to computation | -| Contract already deployed | CREATE2 can't deploy to the same address twice | -| Invalid bytecode | Ensure bytecode includes constructor arguments if needed | - -## Example: Multi-chain Token Deployment - -Deploy an ERC20 token to the same address across multiple chains: - -```javascript "Multi-chain Token Deployment" expandable -import { ethers } from "ethers"; - -async function deployTokenMultichain(chains) { - const bytecode = "0x..."; // ERC20 bytecode with constructor args - const salt = ethers.id("MyToken-v1.0.0"); - - // Compute address (same on all chains) - const tokenAddress = ethers.getCreate2Address( - "0x4e59b44847b379578588920ca78fbf26c0b4956c", - salt, - ethers.keccak256(bytecode) - ); - - console.log("Token will deploy to:", tokenAddress); - - // Deploy on each chain - for (const chain of chains) { - const provider = new ethers.JsonRpcProvider(chain.rpc); - const signer = new ethers.Wallet(privateKey, provider); - - // Check if already deployed - const code = await provider.getCode(tokenAddress); - if (code !== "0x") { - console.log(`Already deployed on ${chain.name}`); - continue; - } - - // Deploy - const tx = await signer.sendTransaction({ - to: "0x4e59b44847b379578588920ca78fbf26c0b4956c", - data: salt + bytecode.slice(2), - gasLimit: 3000000, - }); - - await tx.wait(); - console.log(`Deployed on ${chain.name}`); - } -} -``` - -## Further Reading - -- [EIP-1014: CREATE2 Specification](https://eips.ethereum.org/EIPS/eip-1014) -- [Ethereum Yellowpaper: CREATE2 Definition](https://ethereum.github.io/yellowpaper/paper.pdf) -- [OpenZeppelin Create2 Library](https://docs.openzeppelin.com/contracts/4.x/api/utils#Create2) \ No newline at end of file diff --git a/evm/next/documentation/smart-contracts/predeployed-contracts/multicall3.mdx b/evm/next/documentation/smart-contracts/predeployed-contracts/multicall3.mdx deleted file mode 100644 index c0f712a2e..000000000 --- a/evm/next/documentation/smart-contracts/predeployed-contracts/multicall3.mdx +++ /dev/null @@ -1,330 +0,0 @@ ---- -title: "Multicall3" -description: "Batch multiple contract calls in a single transaction for gas efficiency and atomicity" -icon: "layers" -keywords: ['multicall', 'batch', 'aggregate', 'optimization', 'gas', 'efficiency', 'atomic'] ---- - -Multicall3 is a utility contract that enables batching multiple contract calls into a single transaction. This provides gas savings, atomic execution, and simplified interaction patterns for complex multi-step operations. - -**Contract Address**: `0xcA11bde05977b3631167028862bE2a173976CA11` -**Deployment Status**: Default preinstall -**Repository**: [github.com/mds1/multicall](https://github.com/mds1/multicall) - -## Key Features - -- **Gas Efficiency**: Save on base transaction costs by batching calls -- **Atomic Execution**: All calls succeed or all revert together (optional) -- **State Consistency**: Read multiple values from the same block -- **Flexible Error Handling**: Choose between strict or permissive execution -- **Value Forwarding**: Send ETH/native tokens with calls - -## Core Methods - -### `aggregate` -Execute multiple calls and revert if any fail. - -```solidity -function aggregate(Call[] calldata calls) - returns (uint256 blockNumber, bytes[] memory returnData) -``` - -### `tryAggregate` -Execute multiple calls, returning success status for each. - -```solidity -function tryAggregate(bool requireSuccess, Call[] calldata calls) - returns (Result[] memory returnData) -``` - -### `aggregate3` -Most flexible method with per-call configuration. - -```solidity -function aggregate3(Call3[] calldata calls) - returns (Result[] memory returnData) -``` - -### `aggregate3Value` -Like aggregate3 but allows sending value with each call. - -```solidity -function aggregate3Value(Call3Value[] calldata calls) - payable returns (Result[] memory returnData) -``` - -## Usage Examples - -### Basic Batch Calls - - -```javascript "Ethers.js Multiple Token Balance Query" expandable -import { ethers } from "ethers"; - -const provider = new ethers.JsonRpcProvider("YOUR_RPC_URL"); -const MULTICALL3 = "0xcA11bde05977b3631167028862bE2a173976CA11"; - -// Multicall3 ABI -const multicallAbi = [ - "function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) returns (tuple(bool success, bytes returnData)[] returnData)" -]; - -const multicall = new ethers.Contract(MULTICALL3, multicallAbi, provider); - -// Example: Read multiple token balances -async function getMultipleBalances(tokenAddress, accounts) { - const erc20Abi = ["function balanceOf(address) view returns (uint256)"]; - const iface = new ethers.Interface(erc20Abi); - - // Prepare calls - const calls = accounts.map(account => ({ - target: tokenAddress, - allowFailure: false, - callData: iface.encodeFunctionData("balanceOf", [account]) - })); - - // Execute multicall - const results = await multicall.aggregate3(calls); - - // Decode results - const balances = results.map((result, i) => { - if (result.success) { - return { - account: accounts[i], - balance: iface.decodeFunctionResult("balanceOf", result.returnData)[0] - }; - } - return { account: accounts[i], balance: null }; - }); - - return balances; -} -``` - -```solidity "Solidity Multi-Token Balance Reader" expandable -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface IMulticall3 { - struct Call3 { - address target; - bool allowFailure; - bytes callData; - } - - struct Result { - bool success; - bytes returnData; - } - - function aggregate3(Call3[] calldata calls) - external returns (Result[] memory returnData); -} - -contract MultiTokenReader { - IMulticall3 constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11); - - function getTokenBalances( - address[] calldata tokens, - address account - ) external returns (uint256[] memory balances) { - IMulticall3.Call3[] memory calls = new IMulticall3.Call3[](tokens.length); - - for (uint i = 0; i < tokens.length; i++) { - calls[i] = IMulticall3.Call3({ - target: tokens[i], - allowFailure: true, - callData: abi.encodeWithSignature("balanceOf(address)", account) - }); - } - - IMulticall3.Result[] memory results = multicall.aggregate3(calls); - balances = new uint256[](results.length); - - for (uint i = 0; i < results.length; i++) { - if (results[i].success) { - balances[i] = abi.decode(results[i].returnData, (uint256)); - } - } - } -} -``` - - -### Complex DeFi Operations - -Combine multiple DeFi operations atomically: - -```javascript "Complex DeFi Swap and Stake Operation" expandable -// Swap and stake in one transaction -async function swapAndStake(tokenIn, tokenOut, amountIn, poolAddress) { - const calls = [ - // 1. Approve router - { - target: tokenIn, - allowFailure: false, - callData: iface.encodeFunctionData("approve", [router, amountIn]) - }, - // 2. Perform swap - { - target: router, - allowFailure: false, - callData: iface.encodeFunctionData("swap", [tokenIn, tokenOut, amountIn]) - }, - // 3. Approve staking - { - target: tokenOut, - allowFailure: false, - callData: iface.encodeFunctionData("approve", [poolAddress, amountOut]) - }, - // 4. Stake tokens - { - target: poolAddress, - allowFailure: false, - callData: iface.encodeFunctionData("stake", [amountOut]) - } - ]; - - return await multicall.aggregate3(calls); -} -``` - -### Reading Protocol State - -Get consistent protocol state in one call: - -```javascript -async function getProtocolState(protocol) { - const calls = [ - { target: protocol, callData: "0x18160ddd", allowFailure: false }, // totalSupply() - { target: protocol, callData: "0x313ce567", allowFailure: false }, // decimals() - { target: protocol, callData: "0x06fdde03", allowFailure: false }, // name() - { target: protocol, callData: "0x95d89b41", allowFailure: false }, // symbol() - ]; - - const results = await multicall.aggregate3(calls); - // All values from the same block - return decodeResults(results); -} -``` - -## Advanced Features - -### Value Forwarding - -Send native tokens with calls using `aggregate3Value`: - -```javascript "Native Token Forwarding with Multicall3" expandable -const calls = [ - { - target: weth, - allowFailure: false, - value: ethers.parseEther("1.0"), - callData: iface.encodeFunctionData("deposit") - }, - { - target: contract2, - allowFailure: false, - value: ethers.parseEther("0.5"), - callData: iface.encodeFunctionData("buyTokens") - } -]; - -await multicall.aggregate3Value(calls, { - value: ethers.parseEther("1.5") // Total ETH to send -}); -``` - -### Error Handling Strategies - -```javascript "Error Handling Strategies" expandable -// Strict mode - revert if any call fails -const strictCalls = calls.map(call => ({ - ...call, - allowFailure: false -})); - -// Permissive mode - continue even if some fail -const permissiveCalls = calls.map(call => ({ - ...call, - allowFailure: true -})); - -// Mixed mode - critical calls must succeed -const mixedCalls = [ - { ...criticalCall, allowFailure: false }, - { ...optionalCall, allowFailure: true } -]; -``` - -## Common Use Cases - - - - Query multiple token balances for multiple users efficiently. - - - Fetch prices from multiple DEXs in a single call for best execution. - - - Cast votes on multiple proposals in one transaction. - - - Claim rewards, compound, and rebalance positions atomically. - - - Mint, transfer, or approve multiple NFTs efficiently. - - - -## Gas Optimization - -Multicall3 saves gas through: - -1. **Base Fee Savings**: Pay the 21,000 gas base fee only once -2. **Storage Optimization**: Warm storage slots across calls -3. **Reduced State Changes**: Fewer transaction state transitions - -Typical savings: 20-40% for batching 5+ calls - -## Best Practices - -- **Batch Size**: Optimal batch size is 10-50 calls depending on complexity -- **Gas Limits**: Set appropriate gas limits for complex batches -- **Error Handling**: Use `allowFailure` wisely based on criticality -- **Return Data**: Decode return data carefully, checking success flags -- **Reentrancy**: Be aware of potential reentrancy in batched calls - -## Comparison with Alternatives - -| Feature | Multicall3 | Multicall2 | Manual Batching | -|---------|-----------|-----------|-----------------| -| Gas Efficiency | Excellent | Good | Poor | -| Error Handling | Flexible | Basic | N/A | -| Value Support | Yes | No | Yes | -| Deployment | Standard address | Varies | N/A | -| Block Consistency | Yes | Yes | No | - -## Integration Libraries - -Popular libraries with Multicall3 support: - -- **ethers-rs**: Rust implementation -- **web3.py**: Python Web3 library -- **viem**: TypeScript alternative to ethers -- **wagmi**: React hooks for Ethereum - -## Troubleshooting - -| Issue | Solution | -|-------|----------| -| "Multicall3: call failed" | Check individual call success flags | -| Gas estimation failure | Increase gas limit or reduce batch size | -| Unexpected revert | One of the calls with `allowFailure: false` failed | -| Value mismatch | Ensure total value sent matches sum of individual values | - -## Further Reading - -- [Multicall3 GitHub Repository](https://github.com/mds1/multicall) -- [Multicall3 Deployments](https://www.multicall3.com/) -- [Original Multicall by MakerDAO](https://github.com/makerdao/multicall) \ No newline at end of file diff --git a/evm/next/documentation/smart-contracts/predeployed-contracts/overview.mdx b/evm/next/documentation/smart-contracts/predeployed-contracts/overview.mdx deleted file mode 100644 index b4106ed7b..000000000 --- a/evm/next/documentation/smart-contracts/predeployed-contracts/overview.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: "Overview" -description: "Ready-to-use smart contracts deployed at predefined addresses" -icon: "package" -keywords: ['predeployed', 'preinstalls', 'create2', 'multicall', 'permit2', 'safe', 'factory'] ---- - -## "Pre-deployed" Contracts - -### Default Preinstalls - -These contracts are included in `evmtypes.DefaultPreinstalls` (defined in [`x/vm/types/preinstall.go:13-39`](https://github.com/cosmos/evm/blob/main/x/vm/types/preinstall.go#L13-L39)) and can be deployed at genesis or via governance: - -| Contract | Address | Purpose | Documentation | -|----------|---------|---------|---------------| -| **Create2** | `0x4e59b44847b379578588920ca78fbf26c0b4956c` | Deterministic contract deployment using CREATE2 opcode | [Details](./create2) | -| **Multicall3** | `0xcA11bde05977b3631167028862bE2a173976CA11` | Batch multiple contract calls in a single transaction | [Details](./multicall3) | -| **Permit2** | `0x000000000022D473030F116dDEE9F6B43aC78BA3` | Token approval and transfer management with signatures | [Details](./permit2) | -| **Safe Singleton Factory** | `0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7` | Deploy Safe multisig wallets at deterministic addresses | [Details](./safe-factory) | -| **EIP-2935** | `0x0b` | Historical block hash storage (system contract) | N/A | - - -Additional pre-deployable contracts can be incorporated into your project in a similar way, given that any dependencies are met. See the [Predeployed Contracts Integration](/evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts) guide for instructions. - - - -## Learn More - -- [Implementation](/evm/next/documentation/getting-started/build-a-chain/additional-configuration/predeployed-contracts) - Activate these contracts for your project -- [Create2](./create2) - Deterministic deployment factory documentation -- [Multicall3](./multicall3) - Batch operations contract documentation -- [Permit2](./permit2) - Advanced token approvals documentation -- [Safe Factory](./safe-factory) - Multisig wallet factory documentation \ No newline at end of file diff --git a/evm/next/documentation/smart-contracts/predeployed-contracts/permit2.mdx b/evm/next/documentation/smart-contracts/predeployed-contracts/permit2.mdx deleted file mode 100644 index dd3c28b9e..000000000 --- a/evm/next/documentation/smart-contracts/predeployed-contracts/permit2.mdx +++ /dev/null @@ -1,415 +0,0 @@ ---- -title: "Permit2" -description: "Universal token approval and transfer management system with signature-based permissions" -icon: "key-round" -keywords: ['permit2', 'approval', 'signature', 'eip-2612', 'token', 'transfer', 'allowance', 'gasless'] ---- - -Permit2 is a universal token approval contract that enables signature-based approvals and transfers. Developed by Uniswap Labs, it improves upon EIP-2612 by providing a single contract for managing token permissions across all ERC20 tokens, even those that don't natively support permits. - -**Contract Address**: `0x000000000022D473030F116dDEE9F6B43aC78BA3` -**Deployment Status**: Default preinstall -**Audit Reports**: [Multiple audits available](https://github.com/Uniswap/permit2/tree/main/audits) - -## Key Benefits - -- **Universal Compatibility**: Works with any ERC20 token -- **Gas Savings**: One-time approval to Permit2, then signature-based transfers -- **Enhanced Security**: Granular permissions with expiration times -- **Better UX**: Gasless approvals via signatures -- **Batching Support**: Multiple token operations in one transaction - -## Core Concepts - -### Two-Step Process - -1. **One-time Approval**: User approves Permit2 to spend their tokens -2. **Signature Permits**: User signs messages for specific transfers - -### Permission Types - -- **AllowanceTransfer**: Traditional allowance model with signatures -- **SignatureTransfer**: Direct transfers using only signatures - -## Core Methods - -### Allowance Transfer - -```solidity -// Grant permission via signature -function permit( - address owner, - PermitSingle memory permitSingle, - bytes calldata signature -) external - -// Transfer with existing permission -function transferFrom( - address from, - address to, - uint160 amount, - address token -) external -``` - -### Signature Transfer - -```solidity -// One-time transfer via signature -function permitTransferFrom( - PermitTransferFrom memory permit, - SignatureTransferDetails calldata transferDetails, - address owner, - bytes calldata signature -) external -``` - -## Usage Examples - -### Basic Permit2 Integration - - -```javascript "Ethers.js Complete Permit2 Integration" expandable -import { ethers } from "ethers"; -import { AllowanceProvider, AllowanceTransfer } from "@uniswap/permit2-sdk"; - -const PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3"; - -// Step 1: User approves Permit2 for token (one-time) -async function approvePermit2(tokenContract, signer) { - const tx = await tokenContract.approve( - PERMIT2_ADDRESS, - ethers.MaxUint256 - ); - await tx.wait(); - console.log("Permit2 approved for token"); -} - -// Step 2: Create and sign permit -async function createPermit(token, spender, amount, deadline, signer) { - const permit = { - details: { - token: token, - amount: amount, - expiration: deadline, - nonce: 0, // Get current nonce from contract - }, - spender: spender, - sigDeadline: deadline, - }; - - // Create permit data - const { domain, types, values } = AllowanceTransfer.getPermitData( - permit, - PERMIT2_ADDRESS, - await signer.provider.getNetwork().then(n => n.chainId) - ); - - // Sign permit - const signature = await signer._signTypedData(domain, types, values); - - return { permit, signature }; -} - -// Step 3: Execute transfer with permit -async function transferWithPermit(permit, signature, transferDetails) { - const permit2 = new ethers.Contract( - PERMIT2_ADDRESS, - ["function transferFrom(address,address,uint160,address)"], - signer - ); - - // First, submit the permit - await permit2.permit( - signer.address, - permit, - signature - ); - - // Then transfer - await permit2.transferFrom( - transferDetails.from, - transferDetails.to, - transferDetails.amount, - transferDetails.token - ); -} -``` - -```solidity "Solidity Permit2 Integration Contract" expandable -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface IPermit2 { - struct PermitDetails { - address token; - uint160 amount; - uint48 expiration; - uint48 nonce; - } - - struct PermitSingle { - PermitDetails details; - address spender; - uint256 sigDeadline; - } - - struct SignatureTransferDetails { - address to; - uint256 requestedAmount; - } - - function permit( - address owner, - PermitSingle memory permitSingle, - bytes calldata signature - ) external; - - function transferFrom( - address from, - address to, - uint160 amount, - address token - ) external; -} - -contract Permit2Integration { - IPermit2 constant permit2 = IPermit2(0x000000000022D473030F116dDEE9F6B43aC78BA3); - - function executeTransferWithPermit( - address token, - address from, - address to, - uint160 amount, - IPermit2.PermitSingle calldata permit, - bytes calldata signature - ) external { - // Submit permit - permit2.permit(from, permit, signature); - - // Execute transfer - permit2.transferFrom(from, to, amount, token); - } -} -``` - - -### Batch Operations - -Handle multiple tokens in one transaction: - -```javascript "Batch Token Transfers with Permit2" expandable -async function batchTransferWithPermit2(transfers, owner, signer) { - const permits = []; - const signatures = []; - - // Prepare batch permits - for (const transfer of transfers) { - const permit = { - details: { - token: transfer.token, - amount: transfer.amount, - expiration: transfer.expiration, - nonce: await getNonce(transfer.token, owner), - }, - spender: transfer.spender, - sigDeadline: transfer.deadline, - }; - - const signature = await signPermit(permit, signer); - permits.push(permit); - signatures.push(signature); - } - - // Execute batch - const permit2 = new ethers.Contract(PERMIT2_ADDRESS, abi, signer); - await permit2.permitBatch(owner, permits, signatures); -} -``` - -### Gasless Approvals - -Enable gasless token approvals using meta-transactions: - -```javascript "Gasless Approval via Meta-transactions" expandable -// User signs permit off-chain -async function createGaslessPermit(token, spender, amount, signer) { - const deadline = Math.floor(Date.now() / 1000) + 3600; // 1 hour - - const permit = { - details: { - token: token, - amount: amount, - expiration: deadline, - nonce: 0, - }, - spender: spender, - sigDeadline: deadline, - }; - - const signature = await signPermit(permit, signer); - - // Return data for relayer - return { - permit, - signature, - owner: signer.address, - }; -} - -// Relayer submits transaction -async function relayPermit(permitData, relayerSigner) { - const permit2 = new ethers.Contract(PERMIT2_ADDRESS, abi, relayerSigner); - - const tx = await permit2.permit( - permitData.owner, - permitData.permit, - permitData.signature - ); - - return tx.wait(); -} -``` - -## Advanced Features - -### Witness Data - -Include additional data in permits for complex protocols: - -```solidity -struct PermitWitnessTransferFrom { - TokenPermissions permitted; - address spender; - uint256 nonce; - uint256 deadline; - bytes32 witness; // Custom data hash -} -``` - -### Nonce Management - -Permit2 uses unordered nonces for flexibility: - -```javascript -// Invalidate specific nonces -await permit2.invalidateNonces(token, spender, newNonce); - -// Invalidate nonce range -await permit2.invalidateUnorderedNonces(wordPos, mask); -``` - -### Expiration Handling - -Set appropriate expiration times: - -```javascript -const expirations = { - shortTerm: Math.floor(Date.now() / 1000) + 300, // 5 minutes - standard: Math.floor(Date.now() / 1000) + 3600, // 1 hour - longTerm: Math.floor(Date.now() / 1000) + 86400, // 1 day - maximum: 2n ** 48n - 1n, // Max allowed -}; -``` - -## Security Considerations - -### Best Practices - -1. **Validate Signatures**: Always verify signature validity -2. **Check Expiration**: Ensure permits haven't expired -3. **Nonce Tracking**: Prevent replay attacks -4. **Amount Limits**: Set reasonable amount limits -5. **Deadline Checks**: Validate signature deadlines - -### Common Attack Vectors - -- **Signature Replay**: Mitigated by nonces -- **Front-running**: Use commit-reveal or deadlines -- **Phishing**: Educate users about signing -- **Unlimited Approvals**: Set specific amounts - -## Integration Patterns - -### DEX Integration - -```solidity "DEX Integration with Permit2" expandable -contract DEXWithPermit2 { - function swapWithPermit( - SwapParams calldata params, - PermitSingle calldata permit, - bytes calldata signature - ) external { - // Get tokens via permit - permit2.permit(msg.sender, permit, signature); - permit2.transferFrom( - msg.sender, - address(this), - permit.details.amount, - permit.details.token - ); - - // Execute swap - _performSwap(params); - } -} -``` - -### Payment Processor - -```javascript "Payment Processor with Permit2" expandable -class PaymentProcessor { - async processPayment(order, permit, signature) { - // Verify order details - if (!this.verifyOrder(order)) { - throw new Error("Invalid order"); - } - - // Process payment via Permit2 - await this.permit2.permitTransferFrom( - permit, - { - to: this.treasury, - requestedAmount: order.amount, - }, - order.buyer, - signature - ); - - // Fulfill order - await this.fulfillOrder(order); - } -} -``` - -## Comparison with Alternatives - -| Feature | Permit2 | EIP-2612 | Traditional Approve | -|---------|---------|----------|-------------------| -| Universal Support | Yes | No (per-token) | Yes | -| Gas for Approval | Once per token | None (signature) | Every time | -| Granular Control | Excellent | Limited | Basic | -| Batch Operations | Yes | No | No | -| Signature Required | Yes | Yes | No | - -## Common Issues - -| Issue | Solution | -|-------|----------| -| "PERMIT_EXPIRED" | Increase deadline or request new signature | -| "INVALID_SIGNATURE" | Verify signer address and signature data | -| "INSUFFICIENT_ALLOWANCE" | Ensure Permit2 is approved for token | -| "NONCE_ALREADY_USED" | Use a new nonce for the permit | - -## Libraries and SDKs - -- [Permit2 SDK](https://github.com/Uniswap/permit2-sdk) - Official TypeScript SDK -- [Permit2 Universal Router](https://github.com/Uniswap/universal-router) - Integration example -- [Uniswap v2 Periphery](https://github.com/Uniswap/v2-periphery) - Helper contracts - -## Further Reading - -- [Permit2 Introduction Blog](https://blog.uniswap.org/permit2-and-universal-router) -- [Permit2 GitHub Repository](https://github.com/Uniswap/permit2) -- [EIP-2612: Permit Extension](https://eips.ethereum.org/EIPS/eip-2612) -- [Permit2 Documentation](https://github.com/Uniswap/permit2/blob/main/README.md) \ No newline at end of file diff --git a/evm/next/documentation/smart-contracts/predeployed-contracts/safe-factory.mdx b/evm/next/documentation/smart-contracts/predeployed-contracts/safe-factory.mdx deleted file mode 100644 index 3478d69bc..000000000 --- a/evm/next/documentation/smart-contracts/predeployed-contracts/safe-factory.mdx +++ /dev/null @@ -1,419 +0,0 @@ ---- -title: "Safe Singleton Factory" -description: "Factory contract for deploying Safe multisig wallets at deterministic addresses" -icon: "shield-check" -keywords: ['safe', 'multisig', 'factory', 'gnosis', 'deterministic', 'wallet', 'singleton'] ---- - -The Safe Singleton Factory is a minimal proxy factory that enables deterministic deployment of Safe (formerly Gnosis Safe) multisig wallets and related contracts. It uses CREATE2 to ensure the same wallet addresses across all EVM chains. - -**Contract Address**: `0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7` -**Deployment Status**: Default preinstall -**Repository**: [github.com/safe-global/safe-singleton-factory](https://github.com/safe-global/safe-singleton-factory) - - -**Known Issue - Bytecode Verification Required** - -The Safe Singleton Factory bytecode in the current `DefaultPreinstalls` ([x/vm/types/preinstall.go:30-32](https://github.com/cosmos/evm/blob/main/x/vm/types/preinstall.go#L30-L32)) is currently **identical to the Create2 factory bytecode**, which is incorrect. - -Before deploying this contract in production: -1. Verify the correct Safe Singleton Factory bytecode from the [official repository](https://github.com/safe-global/safe-singleton-factory) -2. Update your genesis configuration with the correct bytecode -3. Test the deployment on a testnet first - -This issue is tracked and will be addressed in a future release. For now, you should manually verify and update the bytecode if you need Safe Factory functionality. - - -## Key Features - -- **Deterministic Deployment**: Same Safe addresses across all chains -- **Minimal Implementation**: Simple factory pattern using CREATE2 -- **Version Agnostic**: Deploy any version of Safe contracts -- **Gas Efficient**: Optimized proxy deployment pattern -- **Ecosystem Standard**: Used by Safe infrastructure globally - -## How It Works - -The factory uses a two-step deployment process: - -1. **Deploy Singleton**: Deploy the Safe master copy (implementation) -2. **Deploy Proxy**: Deploy minimal proxies pointing to the singleton - -This pattern enables gas-efficient deployment of multiple Safe wallets sharing the same implementation. - -## Core Method - -```solidity -function deploy(bytes memory data, bytes32 salt) - returns (address deploymentAddress) -``` - -The factory has a single method that deploys contracts using CREATE2. - -## Usage Examples - -### Deploy a Safe Wallet - - -```javascript "Ethers.js Safe SDK Implementation" expandable -import { ethers } from "ethers"; -import { SafeFactory } from "@safe-global/safe-core-sdk"; - -const FACTORY_ADDRESS = "0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7"; - -// Using Safe SDK -async function deploySafeWallet(owners, threshold, signer) { - const safeFactory = await SafeFactory.create({ - ethAdapter: new EthersAdapter({ ethers, signer }), - safeVersion: '1.4.1' - }); - - const safeAccountConfig = { - owners: owners, - threshold: threshold, - // Optional parameters - fallbackHandler: "0x...", // Fallback handler address - paymentToken: ethers.ZeroAddress, - payment: 0, - paymentReceiver: ethers.ZeroAddress - }; - - // Predict address before deployment - const predictedAddress = await safeFactory.predictSafeAddress(safeAccountConfig); - console.log("Safe will be deployed to:", predictedAddress); - - // Deploy the Safe - const safeSdk = await safeFactory.deploySafe({ safeAccountConfig }); - const safeAddress = await safeSdk.getAddress(); - - console.log("Safe deployed to:", safeAddress); - return safeSdk; -} - -// Manual deployment without SDK -async function deployManually(signer) { - const factory = new ethers.Contract( - FACTORY_ADDRESS, - ["function deploy(bytes,bytes32) returns (address)"], - signer - ); - - // Prepare Safe proxy bytecode with initialization - const proxyBytecode = "0x..."; // Safe proxy bytecode - const salt = ethers.id("my-safe-v1"); - - // Deploy - const tx = await factory.deploy(proxyBytecode, salt); - const receipt = await tx.wait(); - - // Get deployed address from events - const deployedAddress = receipt.logs[0].address; - return deployedAddress; -} -``` - -```solidity "Solidity Safe Deployer Contract" expandable -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface ISafeFactory { - function deploy(bytes memory code, bytes32 salt) - external returns (address); -} - -contract SafeDeployer { - ISafeFactory constant factory = ISafeFactory( - 0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7 - ); - - function deploySafe( - address safeSingleton, - bytes memory initializer, - uint256 saltNonce - ) external returns (address safe) { - // Prepare proxy creation code - bytes memory deploymentData = abi.encodePacked( - getProxyCreationCode(), - uint256(uint160(safeSingleton)) - ); - - // Calculate salt - bytes32 salt = keccak256(abi.encodePacked( - keccak256(initializer), - saltNonce - )); - - // Deploy via factory - safe = factory.deploy(deploymentData, salt); - - // Initialize the Safe - (bool success,) = safe.call(initializer); - require(success, "Safe initialization failed"); - } - - function getProxyCreationCode() pure returns (bytes memory) { - // Safe proxy bytecode - return hex"608060405234801561001057600080fd5b50..."; - } -} -``` - - -### Predict Safe Address - -Calculate the deployment address before deploying: - -```javascript -function predictSafeAddress(owners, threshold, saltNonce) { - const initializer = encodeSafeSetup(owners, threshold); - const salt = ethers.solidityPackedKeccak256( - ["bytes32", "uint256"], - [ethers.keccak256(initializer), saltNonce] - ); - - const initCode = ethers.concat([ - PROXY_CREATION_CODE, - ethers.AbiCoder.defaultAbiCoder().encode(["address"], [SAFE_SINGLETON]) - ]); - - const deploymentAddress = ethers.getCreate2Address( - FACTORY_ADDRESS, - salt, - ethers.keccak256(initCode) - ); - - return deploymentAddress; -} -``` - -### Deploy with Custom Configuration - -```javascript "Deploy Safe with Custom Configuration" expandable -async function deployCustomSafe(config, signer) { - const { - owners, - threshold, - modules = [], - guards = [], - fallbackHandler - } = config; - - // Encode initialization data - const setupData = safeSingleton.interface.encodeFunctionData("setup", [ - owners, - threshold, - ethers.ZeroAddress, // to - "0x", // data - fallbackHandler, - ethers.ZeroAddress, // paymentToken - 0, // payment - ethers.ZeroAddress // paymentReceiver - ]); - - // Deploy proxy pointing to singleton - const proxyFactory = new ethers.Contract( - PROXY_FACTORY_ADDRESS, - proxyFactoryAbi, - signer - ); - - const tx = await proxyFactory.createProxyWithNonce( - SAFE_SINGLETON_ADDRESS, - setupData, - Date.now() // saltNonce - ); - - const receipt = await tx.wait(); - const safeAddress = getSafeAddressFromReceipt(receipt); - - // Enable modules if specified - for (const module of modules) { - await enableModule(safeAddress, module, signer); - } - - return safeAddress; -} -``` - -## Deployment Patterns - -### Organization Wallets - -Deploy consistent treasury addresses across chains: - -```javascript "Deploy Organization Treasury Across Chains" expandable -async function deployOrgTreasury(orgId, chains) { - const salt = ethers.id(`org-treasury-${orgId}`); - const results = {}; - - for (const chain of chains) { - const provider = new ethers.JsonRpcProvider(chain.rpc); - const signer = new ethers.Wallet(deployerKey, provider); - - // Same salt = same address on all chains - const address = await deploySafeWithSalt(salt, signer); - results[chain.name] = address; - } - - return results; -} -``` - -### Counterfactual Wallets - -Create wallets that can receive funds before deployment: - -```javascript "Counterfactual Safe Class Implementation" expandable -class CounterfactualSafe { - constructor(owners, threshold) { - this.owners = owners; - this.threshold = threshold; - this.address = this.predictAddress(); - } - - predictAddress() { - // Calculate address without deploying - return predictSafeAddress( - this.owners, - this.threshold, - 0 // saltNonce - ); - } - - async deploy(signer) { - // Only deploy when needed - const code = await signer.provider.getCode(this.address); - if (code !== "0x") { - console.log("Already deployed"); - return this.address; - } - - return deploySafeWallet( - this.owners, - this.threshold, - signer - ); - } -} -``` - -## Integration with Safe Ecosystem - -### Safe Modules - -Deploy and enable Safe modules: - -```javascript "Safe Module Deployment and Configuration" expandable -// Deploy module via factory -async function deployModule(moduleCode, salt) { - const tx = await factory.deploy(moduleCode, salt); - const receipt = await tx.wait(); - return receipt.contractAddress; -} - -// Enable module on Safe -async function enableModule(safeAddress, moduleAddress, signer) { - const safe = new ethers.Contract(safeAddress, safeAbi, signer); - const tx = await safe.enableModule(moduleAddress); - await tx.wait(); -} -``` - -### Safe Guards - -Deploy transaction guards for additional security: - -```javascript "Deploy and Set Safe Transaction Guard" expandable -async function deployAndSetGuard(safeAddress, guardCode, signer) { - // Deploy guard - const salt = ethers.id(`guard-${safeAddress}`); - const guardAddress = await factory.deploy(guardCode, salt); - - // Set as Safe guard - const safe = new ethers.Contract(safeAddress, safeAbi, signer); - const tx = await safe.setGuard(guardAddress); - await tx.wait(); - - return guardAddress; -} -``` - -## Best Practices - -### Salt Management - -```javascript "Structured Salt Generation Patterns" expandable -// Structured salt generation -function generateSalt(context, nonce) { - return ethers.solidityPackedKeccak256( - ["string", "uint256"], - [context, nonce] - ); -} - -// Examples -const userSalt = generateSalt(`user-${userId}`, 0); -const orgSalt = generateSalt(`org-${orgId}`, iteration); -const appSalt = generateSalt(`app-${appId}-${version}`, 0); -``` - -### Version Control - -```javascript "Safe Version Management" expandable -const SAFE_VERSIONS = { - "1.3.0": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", - "1.4.0": "0x41675C099F32341bf84BFc5382aF534df5C7461a", - "1.4.1": "0x29fcB43b46531BcA003ddC8FCB67FFE91900C762" -}; - -async function deploySafeVersion(version, owners, threshold) { - const singleton = SAFE_VERSIONS[version]; - if (!singleton) throw new Error(`Unknown version: ${version}`); - - return deployWithSingleton(singleton, owners, threshold); -} -``` - -### Gas Optimization - -- Deploy singleton once per chain -- Reuse proxy bytecode -- Batch deployments when possible -- Use minimal initializers - -## Security Considerations - -- **Initialization**: Ensure Safes are properly initialized after deployment -- **Salt Uniqueness**: Use unique salts to prevent address collisions -- **Singleton Verification**: Verify singleton contract before deployment -- **Access Control**: The factory itself has no access control - anyone can deploy - -## Troubleshooting - -| Issue | Solution | -|-------|----------| -| Address mismatch | Verify salt and bytecode are identical | -| Deployment fails | Check sufficient gas and valid bytecode | -| Safe not working | Ensure proper initialization after deployment | -| Cross-chain inconsistency | Verify same singleton and salt used | - -## Related Contracts - -### Safe Infrastructure - -```javascript -const SAFE_CONTRACTS = { - factory: "0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7", - singleton_1_4_1: "0x29fcB43b46531BcA003ddC8FCB67FFE91900C762", - proxyFactory: "0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67", - multiSend: "0x38869bf66a61cF6bDB996A6aE40D5853Fd43B526", - fallbackHandler: "0xfd0732Dc9E303f09fCEf3a7388Ad10A83459Ec99" -}; -``` - -## Further Reading - -- [Safe Documentation](https://docs.safe.global/) -- [Safe Singleton Factory](https://github.com/safe-global/safe-singleton-factory) -- [Safe Contracts](https://github.com/safe-global/safe-contracts) -- [Safe SDK](https://github.com/safe-global/safe-core-sdk) \ No newline at end of file