# Attribution Tags
Source: https://docs.celo.org/build-on-celo/attribution-tags
Attribution tags let you mark transactions as coming from your app — so on-chain activity can be credited back to you for programs like [Proof of Ship](/build-on-celo/fund-your-project), MiniPay leaderboards, and hackathon tracking. Celo's implementation follows [ERC-8021](https://oxlib.sh/ercs/erc8021/Attribution).
## How It Works
ERC-8021 appends a small suffix to a transaction's calldata. The suffix is invisible to the contract being called — the EVM discards trailing bytes — so adding it never changes execution semantics. It just makes the transaction identifiable as having come through your app to anyone reading calldata off-chain.
Tagging a transaction is open to everyone. Whether a code gets *credited* on a leaderboard or rewards program is resolved at the registry/indexer layer, not at the tagging step.
## Install
```bash theme={null}
npm install @celo/attribution-tags viem
```
`viem` is an optional peer dependency — only required if you call `verifyTx` to decode a tag from a transaction hash.
The SDK exports four functions:
```ts theme={null}
toDataSuffix(code | [codes]) // → encoded suffix (Hex)
codeFromHostname(hostname) // → "celo_" + 12 hex chars, derived from a hostname
fromDataSuffix(data) // → { codes, schemaId } | null
verifyTx({ client, hash }) // → { codes, schemaId } | null
```
## Quickstart
If you've been issued a code (`celo_xxxxxxxx`) — for example through Proof of Ship onboarding or a hackathon registration — pass it directly:
```ts theme={null}
import { toDataSuffix } from "@celo/attribution-tags";
const tag = toDataSuffix("celo_b7k3p9da"); // issued code, or any custom string
await wallet.sendTransaction({ to, value, data: tag });
```
Any string matching `[a-z0-9_]` (1–32 characters) is a valid code. If a program assigned you a code, it must be present in the suffix — leaderboards and reward programs only credit the assigned code, not one you derive yourself with `codeFromHostname`. You can include both:
```ts theme={null}
const tag = toDataSuffix(["your_own_code", "celo_assigned1234"]);
```
## Tagging a Contract Call
Concatenate your encoded calldata with the suffix:
```ts theme={null}
import { encodeFunctionData, concat } from "viem";
const callData = encodeFunctionData({ abi, functionName: "transfer", args });
const taggedData = concat([callData, tag]);
await wallet.sendTransaction({ to: tokenAddress, data: taggedData });
```
With [wagmi](/tooling/dev-environments/thirdweb/overview), pass `dataSuffix` directly and wagmi handles the concatenation:
```ts theme={null}
const { writeContract } = useWriteContract();
writeContract({
address,
abi,
functionName: "transfer",
args,
dataSuffix: tag,
});
```
## The Layering Rule
ERC-8021 suffixes can carry multiple codes, but **each code should only be added by the entity it represents**:
* **Your app code** — added by your app, as shown above.
* **A platform code** like `minipay` — added by the platform itself (the wallet or cohort layer), never by your app.
Adding a platform code from your own app would falsely claim every transaction ran inside that platform, polluting attribution data.
## Verifying It Worked
```ts theme={null}
import { verifyTx } from "@celo/attribution-tags";
import { createPublicClient, http } from "viem";
import { celo } from "viem/chains";
const client = createPublicClient({ chain: celo, transport: http() });
const result = await verifyTx({ client, hash: "0x..." });
console.log(result); // { codes: ["celo_b7k3p9da"], schemaId: 0 }
```
`verifyTx` returns `null` (never throws) if no tag is found. For offline decoding without an RPC call, use `fromDataSuffix(rawCalldata)` instead.
Some smart-account / bundler flows (ERC-4337 bundlers, meta-tx relayers) rewrite calldata and can strip trailing bytes. Verify on-chain with `verifyTx` before relying on tags in production.
## Resources
| Resource | Link |
| ------------------ | ------------------------------------------------------------------------------------ |
| Source & full docs | [github.com/celo-org/attribution-tags](https://github.com/celo-org/attribution-tags) |
| npm package | [@celo/attribution-tags](https://www.npmjs.com/package/@celo/attribution-tags) |
| ERC-8021 standard | [oxlib.sh/ercs/erc8021](https://oxlib.sh/ercs/erc8021/Attribution) |
## Related
* [x402: Agent Payments](/build-on-celo/build-with-ai/x402)
* [Fund your Project](/build-on-celo/fund-your-project) — Proof of Ship progress tracking uses attribution tags
* [Launch Checklist](/build-on-celo/launch-checklist)
# MiniPay Code Library
Source: https://docs.celo.org/build-on-celo/build-on-minipay/code-library
Snippets of code that can be used to implement flows inside MiniPay
Make sure you are using Typescript v5 or above and Viem v2 or above.
## Get the connected user's address without any Library
```js theme={null}
// The code must run in a browser environment and not in node environment
if (window && window.ethereum) {
// User has a injected wallet
if (window.ethereum.isMiniPay) {
// User is using Minipay
// Requesting account addresses
let accounts = await window.ethereum.request({
method: "eth_requestAccounts",
params: [],
});
// Injected wallets inject all available addresses,
// to comply with API Minipay injects one address but in the form of array
console.log(accounts[0]);
}
// User is not using MiniPay
}
// User does not have a injected wallet
```
To use the code snippets below, install the following packages:
```bash yarn theme={null}
yarn add @celo/abis @celo/identity viem@2
```
```bash npm theme={null}
npm install @celo/abis @celo/identity viem@2
```
## Check USDm Balance of an address
```js theme={null}
import { getContract, formatEther, createPublicClient, http } from "viem";
import { celo } from "viem/chains";
import { stableTokenABI } from "@celo/abis";
// USDm address on Celo mainnet
const STABLE_TOKEN_ADDRESS = "0x765DE816845861e75A25fCA122bb6898B8B1282a";
async function checkUSDmBalance(publicClient, address) {
const StableTokenContract = getContract({
abi: stableTokenABI,
address: STABLE_TOKEN_ADDRESS,
client: publicClient,
});
const balanceInBigNumber = await StableTokenContract.read.balanceOf([
address,
]);
const balanceInWei = balanceInBigNumber.toString();
const balanceInEthers = formatEther(balanceInWei);
return balanceInEthers;
}
const publicClient = createPublicClient({
chain: celo,
transport: http(),
}); // Mainnet
const balance = await checkUSDmBalance(publicClient, address); // In Ether unit
```
## Check If a transaction succeeded
```js theme={null}
import { createPublicClient, http } from "viem";
import { celo } from "viem/chains";
async function checkIfTransactionSucceeded(publicClient, transactionHash) {
const receipt = await publicClient.getTransactionReceipt({
hash: transactionHash,
});
return receipt.status === "success";
}
const publicClient = createPublicClient({
chain: celo,
transport: http(),
}); // Mainnet
const transactionStatus = await checkIfTransactionSucceeded(
publicClient,
transactionHash
);
```
## Estimate Gas for a transaction (in Celo)
```js theme={null}
import { createPublicClient, http } from "viem";
import { celo } from "viem/chains";
async function estimateGas(publicClient, transaction, feeCurrency = "") {
return await publicClient.estimateGas({
...transaction,
feeCurrency: feeCurrency ? feeCurrency : "",
});
}
const publicClient = createPublicClient({
chain: celo,
transport: http(),
});
const gasLimit = await estimateGas(publicClient, {
account: "0x8eb02597d85abc268bc4769e06a0d4cc603ab05f",
to: "0x4f93fa058b03953c851efaa2e4fc5c34afdfab84",
value: "0x1",
data: "0x",
});
```
## Estimate Gas for a transaction (in USDm)
```js theme={null}
import { createPublicClient, http } from "viem";
import { celo } from "viem/chains";
async function estimateGas(publicClient, transaction, feeCurrency = "") {
return await publicClient.estimateGas({
...transaction,
feeCurrency: feeCurrency ? feeCurrency : "",
});
}
const publicClient = createPublicClient({
chain: celo,
transport: http(),
});
const STABLE_TOKEN_ADDRESS = "0x765DE816845861e75A25fCA122bb6898B8B1282a";
const gasLimit = await estimateGas(
publicClient,
{
account: "0x8eb02597d85abc268bc4769e06a0d4cc603ab05f",
to: "0x4f93fa058b03953c851efaa2e4fc5c34afdfab84",
value: "0x1",
data: "0x",
},
STABLE_TOKEN_ADDRESS
);
```
## Estimate Gas Price for a transaction (in Celo)
```js theme={null}
import { createPublicClient, http } from "viem";
import { celo } from "viem/chains";
async function estimateGasPrice(publicClient, feeCurrency = "") {
return await publicClient.request({
method: "eth_gasPrice",
params: feeCurrency ? [feeCurrency] : [],
});
}
const publicClient = createPublicClient({
chain: celo,
transport: http(),
});
const gasPrice = await estimateGasPrice(publicClient);
```
## Estimate Gas Price for a transaction (in USDm)
```js theme={null}
import { createPublicClient, http } from "viem";
import { celo } from "viem/chains";
async function estimateGasPrice(publicClient, feeCurrency = "") {
return await publicClient.request({
method: "eth_gasPrice",
params: feeCurrency ? [feeCurrency] : [],
});
}
const publicClient = createPublicClient({
chain: celo,
transport: http(),
});
const STABLE_TOKEN_ADDRESS = "0x765DE816845861e75A25fCA122bb6898B8B1282a";
const gasPrice = await estimateGasPrice(publicClient, STABLE_TOKEN_ADDRESS);
```
## Calculate USDm to be spent for transaction fees
```js theme={null}
import { createPublicClient, http, formatEther, fromHex } from "viem";
import { celo } from "viem/chains";
const publicClient = createPublicClient({
chain: celo,
transport: http(),
});
const STABLE_TOKEN_ADDRESS = "0x765DE816845861e75A25fCA122bb6898B8B1282a";
// `estimateGas` implemented above
const gasLimit = await estimateGas(
publicClient,
{
account: "0x8eb02597d85abc268bc4769e06a0d4cc603ab05f",
to: "0x4f93fa058b03953c851efaa2e4fc5c34afdfab84",
value: "0x1",
data: "0x",
},
STABLE_TOKEN_ADDRESS
);
// `estimateGasPrice` implemented above
const gasPrice = await estimateGasPrice(publicClient, STABLE_TOKEN_ADDRESS);
// Convert hex gas price to BigInt and calculate fees
const gasPriceBigInt = fromHex(gasPrice, "bigint");
const transactionFeesInUSDm = formatEther(gasLimit * gasPriceBigInt);
```
## Resolve Minipay phone numbers to Addresses
Install the `@celo/identity` package:
```bash theme={null}
npm install @celo/identity
```
### Step 1: Set up your issuer
The issuer is the account registering attestations. When a user requests attestation registration, verify they own the identifier (e.g., SMS verification for phone numbers).
```js theme={null}
import { createWalletClient, http } from "viem";
import { celoSepolia } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
// The issuer is the account that is registering the attestation
const ISSUER_PRIVATE_KEY = "YOUR_ISSUER_PRIVATE_KEY";
// Create Celo Sepolia viem client with the issuer private key
const viemClient = createWalletClient({
account: privateKeyToAccount(ISSUER_PRIVATE_KEY),
transport: http(),
chain: celoSepolia,
});
// Information provided by user, issuer should confirm they own the identifier
const userPlaintextIdentifier = "+12345678910";
const userAccountAddress = "0x000000000000000000000000000000000000user";
// Time at which issuer verified the user owns their identifier
const attestationVerifiedTime = Date.now();
```
### Step 2: Check and top up ODIS quota
```js theme={null}
import { OdisUtils } from "@celo/identity";
import { AuthSigner } from "@celo/identity/lib/odis/query";
import { OdisContextName } from "@celo/identity/lib/odis/query";
// authSigner provides information needed to authenticate with ODIS
const authSigner: AuthSigner = {
authenticationMethod: OdisUtils.Query.AuthenticationMethod.WALLET_KEY,
sign191: ({ message, account }) => viemClient.signMessage({ message, account }),
};
// serviceContext provides the ODIS endpoint and public key
const serviceContext = OdisUtils.Query.getServiceContext(
OdisContextName.CELO_SEPOLIA
);
// Check existing quota on issuer account
const issuerAddress = viemClient.account.address;
const { remainingQuota } = await OdisUtils.Quota.getPnpQuotaStatus(
issuerAddress,
authSigner,
serviceContext
);
// If needed, approve and send payment to OdisPayments to get quota for ODIS
// Note: This example uses viem. For contract interactions, use getContract from viem
if (remainingQuota < 1) {
// Use viem's getContract to interact with stable token and ODIS payments contracts
// Implementation depends on your specific contract setup
}
```
### Step 3: Derive the obfuscated identifier
Get the obfuscated identifier from the plaintext identifier by querying ODIS:
```js theme={null}
const { obfuscatedIdentifier } = await OdisUtils.Identifier.getObfuscatedIdentifier(
userPlaintextIdentifier,
OdisUtils.Identifier.IdentifierPrefix.PHONE_NUMBER,
issuerAddress,
authSigner,
serviceContext
);
```
### Step 4: Look up account addresses
Query the FederatedAttestations contract to look up account addresses owned by an identifier:
```js theme={null}
const attestations = await federatedAttestationsContract.lookupAttestations(
obfuscatedIdentifier,
[issuerAddress] // Trusted issuers
);
console.log(attestations.accounts);
```
## Request an ERC20 token transfer
USDT and USDC on Celo use **6 decimals**, not 18. Pass `tokenDecimals` as `6` when
transferring either token. Using `18` will send 1,000,000,000,000× more than intended.
USDm uses 18 decimals.
```js theme={null}
import { createWalletClient, createPublicClient, custom, http, encodeFunctionData, parseUnits } from "viem";
import { celo, celoSepolia } from "viem/chains";
import { stableTokenABI } from "@celo/abis";
const walletClient = createWalletClient({
chain: celoSepolia, // For testnet
// chain: celo, // For mainnet
transport: custom(window.ethereum!),
});
const publicClient = createPublicClient({
chain: celoSepolia, // For testnet
// chain: celo, // For mainnet
transport: http(),
});
async function requestTransfer(tokenAddress, transferValue, tokenDecimals, receiverAddress) {
const hash = await walletClient.sendTransaction({
to: tokenAddress,
// Mainnet token addresses and their decimals:
// USDm: '0x765DE816845861e75A25fCA122bb6898B8B1282a' (18 decimals)
// USDC: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C' (6 decimals)
// USDT: '0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e' (6 decimals)
data: encodeFunctionData({
abi: stableTokenABI, // Token ABI from @celo/abis
functionName: "transfer",
args: [
receiverAddress,
// USDm uses 18 decimals; USDC and USDT use 6 decimals
parseUnits(`${Number(transferValue)}`, tokenDecimals),
],
}),
});
const transaction = await publicClient.waitForTransactionReceipt({
hash, // Transaction hash that can be used to search transaction on the explorer.
});
if (transaction.status === "success") {
// Do something after transaction is successful.
} else {
// Do something after transaction has failed.
}
}
```
# MiniPay Deeplinks
Source: https://docs.celo.org/build-on-celo/build-on-minipay/deeplinks
Deeplinks let your Mini App interact with MiniPay's native features without manual navigation. They use the host `link.minipay.xyz` and can be triggered from external apps or from within MiniPay itself.
The user must have MiniPay installed and be logged in. Users without the app
are shown an install prompt.
## Available deeplinks
| Action | Deeplink | Description |
| ------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| Add cash | `https://link.minipay.xyz/add_cash` | Launches the add cash flow. Optionally scope the tokens with `?tokens=USDM,USDT` (supported: `USDM`, `USDT`, `USDC`). |
| Open Mini App | `https://link.minipay.xyz/browse?url=xxx` | Opens an approved Mini App at the given URL. |
| Discover tab | `https://link.minipay.xyz/discover` | Opens the Mini Apps discovery page. |
| Transaction receipt | `https://link.minipay.xyz/receipt?tx=xxx` | Shows the receipt for a transaction hash. Append `&celebrate` for a celebration animation. |
| QR code | `https://link.minipay.xyz/qr` | Shows the user's QR code. |
| Invite friends | `https://link.minipay.xyz/invite_friends` | Opens the invite friends screen. |
| Pockets | `https://link.minipay.xyz/balance` | Opens the balance (pockets) view. |
## Trigger the add cash screen
To trigger or redirect a MiniPay user to the add cash screen inside MiniPay, use the following link:
[https://link.minipay.xyz/add\_cash](https://link.minipay.xyz/add_cash)
To pre-select which tokens the user can add, pass the `tokens` query parameter, for example [https://link.minipay.xyz/add\_cash?tokens=USDM,USDT](https://link.minipay.xyz/add_cash?tokens=USDM,USDT).
# Build on MiniPay
Source: https://docs.celo.org/build-on-celo/build-on-minipay/overview
## Create a Mini App for the MiniPay Stablecoin Wallet
***
[MiniPay](https://www.opera.com/products/minipay) is a stablecoin wallet with a built-in Mini App discovery page, integrated directly within the popular Opera Mini Android browser and also available as a standalone application on Android and iOS.
Since launching, MiniPay is the fastest growing non-custodial wallet in the Global South with more than 10M+ activations.
Install the new MiniPay standalone app for [Android](https://play.google.com/store/apps/details?id=com.opera.minipay) or [iOS](https://apps.apple.com/de/app/minipay-easy-global-wallet/id6504087257?l=en-GB) now! 🎉 📥
## Why Build on MiniPay?
* **Useful Applications:** MiniPay focuses on practical uses in everyday life, especially in emerging markets, where most of their users are located.
* **Integrated App Discovery:** MiniPay includes a built-in app discovery page, allowing users to interact with selected Mini Apps directly within their wallet, without needing to switch to other platforms.
* **Access to Opera’s Large User Base** Developers can tap into MiniPay’s growing user base (10 Million activated addresses) and Opera browser distribution.
## Key Features of MiniPay
* **Phone Number mapping:** Uses mobile phone numbers as wallet addresses.
* **Fast, Low-Cost Transactions:** Offers fast P2P stablecoin transactions with sub-cent fees.
* **Lightweight Design:** At just 2MB, users can use the wallet with limited data.
## Opportunities for MiniPay Builders
* **Raising Funding?** Reach out to [team@verda.ventures](mailto:team@verda.ventures) with a deck and/or product demo.
* **Still Building?** Register your project for [Build With Celo: Proof-of-Ship](https://www.celopg.eco/programs/proof-of-ship-s1) for monthly rewards.
# Ngrok Setup
Source: https://docs.celo.org/build-on-celo/build-on-minipay/prerequisites/ngrok-setup
When builidng dApps for MiniPay locally, you want to test the dApp inside MiniPay wallet on your phone.
But since the dApp is running locally, you cannot simply visit localhost on your phone to open the dApp on your phone.
To solve this, we use `ngrok`.
`ngrok` allows us to share our localhost by providing us with a temporary web url that can be used on any device!
## Installing Ngrok
1. Visit [ngrok.com](https://ngrok.com)
2. Sign up
3. The dashboard will have instructions based on your OS on how to install and use ngrok!
4. Once installed you can use the following command to share your localhost port.
```bash theme={null}
> ngrok http [PORT]
```
The output looks something like this.
You can use the highlighted url to launch the localhost dApp on the [MiniPay's Site Tester](/build-on-celo/build-on-minipay/quickstart#test-your-mini-app-inside-minipay).
# Get Started Building on MiniPay
Source: https://docs.celo.org/build-on-celo/build-on-minipay/quickstart
A step-by-step guide to setting up, building, and testing your MiniPay Mini App.
***
## 1. Installing MiniPay
MiniPay is designed for mainstream adoption, making digital payments simple and easy to use.
#### Key Features:
* **Currency Display**: Balances appear in your local currency.
* **Stablecoin Support**: Only stablecoins (USDm, USDC, and USDT) are supported.
* **Simple Swaps**: The pocket swap feature allows for easy swaps between stablecoins by dragging one pocket into another.
MiniPay is only available on Celo and Celo Sepolia Testnet. Other blockchain
networks are not supported.
#### How to Access MiniPay:
* [**Opera Mini Browser**](https://www.opera.com/pl/products/minipay) (Android)
* [**Standalone App Android**](https://play.google.com/store/apps/details?id=com.opera.minipay)
* [**Standalone App iOS**](https://apps.apple.com/de/app/minipay-easy-global-wallet/id6504087257?l=en-GB)
#### Set Up MiniPay:
* **Install the MiniPay Standalone App:** Download for [Android](https://play.google.com/store/apps/details?id=com.opera.minipay) and [iOS](https://apps.apple.com/de/app/minipay-easy-global-wallet/id6504087257?l=en-GB)
* **Create an Account:** Sign up using your Google account and phone number.
## 2. Build Your MiniPay Mini App
#### For creating a new app:
* Use the [Celo Composer MiniPay Template](https://github.com/celo-org/minipay-template) to start building.
```bash theme={null}
npx @celo/celo-composer@latest create -t minipay
```
* Follow the [Quickstart Guide](/build-on-celo/quickstart) for a step-by-step tutorial.
#### For integrating an existing app:
* Follow the [Helpful Tips Guide](#helpful-tips-to-make-your-mini-app-minipay-compatible) to ensure your app is MiniPay compatible.
## 3. Get Testnet Tokens
Request CELO testnet tokens from the Celo [faucet](https://faucet.celo.org/celo-sepolia/) to test your Mini App. After you got the CELO tokens, you can exchange them for stablecoins like USDm, USDT and USDC in the [mento app](https://app.mento.org/).
## 4. Test your Mini App inside MiniPay
You cannot test MiniPay using the Android Studio Emulator. Use an Android or
iOS mobile device.
### Enable Developer Mode:
1. Open the MiniPay app on your phone and navigate to settings.
2. In the **About** section, tap the **Version** number repeatedly until the confirmation message appears.
3. Return to **Settings**, then select **Developer Settings**.
4. Enable **Developer Mode** and toggle **Use Testnet** to connect to Sepolia L2 testnet.
### Load Your Mini App:
1. In **Developer Settings,** tap **Load Test Page.**
2. Enter your **Mini App URL.**
* If testing a local deployment, use [ngrok](#testing-local-development-with-minipay) to expose your localhost.
6. Click **Go** to launch and test your Mini App.
***
## Helpful Tips to Make Your Mini App MiniPay Compatible
MiniPay uses Custom [Fee Abstraction](/build-on-celo/fee-abstraction/overview) based
transactions. We recommend using viem or wagmi as they provide native support
for fee currency.
#### 1. Using Viem
```js theme={null}
import { createWalletClient, custom } from "viem";
import { celo, celoSepolia } from "viem/chains";
const client = createWalletClient({
chain: celo,
// chain: celoSepolia, // For Celo Sepolia Testnet
transport: custom(window.ethereum),
});
const [address] = await client.getAddresses();
```
#### 2. Using Wagmi
These snippets use **wagmi v2** (the current major version). In v2, connectors
are functions (e.g. `injected()`) rather than the classes used in v1
(`new InjectedConnector()`), `WagmiConfig` is now `WagmiProvider`, and the
config is built with `createConfig`.
First, create your wagmi config and wrap your app in `WagmiProvider` (wagmi v2 also requires a TanStack Query provider):
```tsx theme={null}
// providers.tsx
"use client";
import { WagmiProvider, createConfig, http } from "wagmi";
import { celo } from "wagmi/chains";
import { injected } from "wagmi/connectors";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
export const config = createConfig({
chains: [celo],
connectors: [injected({ target: "metaMask" })],
transports: {
[celo.id]: http(),
},
});
const queryClient = new QueryClient();
export function Providers({ children }: { children: React.ReactNode }) {
return (
{children}
);
}
```
Then auto-connect on load using the connector from your config:
```tsx theme={null}
import { useEffect } from "react";
import { useConnect } from "wagmi";
const { connect, connectors } = useConnect();
useEffect(() => {
// `connectors[0]` is the `injected()` connector registered in `createConfig`
connect({ connector: connectors[0] });
}, [connect, connectors]);
```
This sets up the `injected` connector in `createConfig` and then uses the `connect` method from the `useConnect` hook. The `useEffect` ensures that the connection is established when the page loads.
In the Viem example, we're creating a wallet client that specifies the chain and a custom transport using `window.ethereum`. The `getAddresses` method then retrieves the connected addresses.
### Important Notes
Ensure the "Connect Wallet" button is hidden when your DApp is loaded inside the MiniPay app, as the wallet connection is implicit.
*Code Example to hide Connect Wallet button if the user is using MiniPay wallet*
```tsx theme={null}
import { useEffect, useState } from "react";
import { useConnect } from "wagmi";
import { injected } from "wagmi/connectors";
export default function Header() {
// State variable that determines whether to hide the button or not.
const [hideConnectBtn, setHideConnectBtn] = useState(false);
const { connect } = useConnect();
useEffect(() => {
if (window.ethereum && window.ethereum.isMiniPay) {
// User is using MiniPay so hide connect wallet button.
setHideConnectBtn(true);
connect({ connector: injected({ target: "metaMask" }) });
}
}, [connect]);
return (
);
}
```
* Always verify the existence of `window.provider` before initializing your web3 library to ensure seamless compatibility with the MiniPay wallet.
* When using `ngrok`, remember that the tunneling URL is temporary. You'll get a new URL every time you restart ngrok.
* Be cautious about exposing sensitive information or functionality when using public tunneling services like ngrok. Always use them in a controlled environment.
* MiniPay manages gas fees for you. You can set the `feeCurrency` property when running `eth_sendTransaction`, but MiniPay may ignore it and pay gas in the stablecoin the user holds the most of. Supported gas tokens include `USDT`, `USDC`, and `USDm` (as well as other Mento stablecoins).
* Use viem or wagmi to build and send transactions, as they provide native support for Celo's fee-currency transactions.
## Testing Local Development with MiniPay
If you're developing your MiniApp locally (e.g., on `localhost:3000`), use `ngrok` to tunnel traffic over HTTP, for real-time testing.
#### Set Up ngrok
* **Install ngrok:** If you haven't already, install ngrok. You can find instructions on their [official website](https://ngrok.com/download).
* **Start Your Local Server:** Ensure your local development server is running. For instance, if you're using Next.js, you might run `npm run dev` to start your server at `localhost:3000`.
* **Tunnel Traffic with ngrok:** In your terminal, run the following command to start an ngrok tunnel:
```bash theme={null}
ngrok http 3000
```
This will provide you with a public URL that tunnels to your localhost.
For a more in depth guide, check out the official [ngrok setup](/build-on-celo/build-on-minipay/prerequisites/ngrok-setup).
* **Test in MiniPay:** Copy the provided ngrok URL and use it inside the MiniPay app to test your DApp.
# ERC-8004: Agent Trust Protocol
Source: https://docs.celo.org/build-on-celo/build-with-ai/8004
[ERC-8004](https://github.com/erc-8004/erc-8004-contracts/tree/master) is an Ethereum standard that establishes trust infrastructure for autonomous AI agents. It enables agents to discover, identify, and evaluate other agents across organizational boundaries without pre-existing trust relationships.
## Key Features
* **Identity Registry**: Portable agent identifiers based on ERC-721 NFTs
* **Reputation Registry**: Standardized feedback and rating system for agents
* **Validation Registry**: Independent verification hooks where third-party validators can attest to agent outputs—supporting stake-secured re-execution, zkML proofs, or TEE attestations for high-stakes operations
* **Cross-Chain Support**: Works on any EVM-compatible chain including Celo
## Why ERC-8004?
When AI agents interact across organizational boundaries, three critical questions arise:
* **Discovery**: How do agents find each other? The Identity Registry provides searchable metadata—agents query the registry to discover other agents by capabilities, endpoints, or domain.
* **Identity**: How do agents verify who they're dealing with? Each agent is an ERC-721 NFT with a cryptographically linked wallet, enabling verification that you're communicating with the authentic agent owner.
* **Trust**: How do agents evaluate reliability? The Reputation Registry stores feedback from every interaction, creating a portable track record that travels with the agent across platforms.
### Protocol stack
ERC-8004 fits into the broader agent infrastructure stack:
```mermaid theme={null}
flowchart TB
subgraph APP["APPLICATION LAYER"]
A1["Agent Apps, Platforms, Marketplaces"]
end
subgraph TRUST["TRUST LAYER"]
T1["ERC-8004"]
T2["Identity, Reputation, Validation"]
end
subgraph PAY["PAYMENT LAYER"]
P1["x402"]
P2["HTTP 402 + Stablecoin Payments"]
end
subgraph COMM["COMMUNICATION LAYER"]
C1["A2A (Google) + MCP (Anthropic)"]
end
APP --> TRUST
TRUST --> PAY
PAY --> COMM
```
## The Three Registries
### 1. Identity Registry
Makes agents discoverable via portable NFT identifiers.
**Key capabilities:**
* Every agent **identity** is represented as an ERC-721 NFT—the agent itself runs off-chain, but its on-chain identity is an NFT that's browsable in wallets, transferable between owners, and queryable by smart contracts
* `agentURI` points to registration file with endpoints
* Supports multiple endpoint types (A2A, MCP, wallet, ENS, DIDs)
* Domain verification for endpoint ownership
**Agent registration file structure:**
```json theme={null}
{
"type": "Agent",
"name": "My AI Agent",
"description": "Description of capabilities",
"image": "ipfs://...",
"endpoints": [
{
"type": "a2a",
"url": "https://example.com/.well-known/agent.json"
},
{
"type": "mcp",
"url": "https://example.com/mcp"
},
{
"type": "wallet",
"address": "0x...",
"chainId": 42220
}
],
"supportedTrust": ["reputation", "validation", "tee"]
}
```
### 2. Reputation Registry
Stores feedback and attestations about agent performance. Feedback is submitted on-chain by any address that has interacted with the agent—this includes users who hired the agent, other agents that collaborated with it, or monitoring services that track uptime and responsiveness. The contract prevents agents from rating themselves (owner and operator addresses are blocked from submitting feedback on their own agent).
**Common feedback tags:**
| Tag | Measures | Example |
| -------------- | ---------------------- | ---------- |
| `starred` | Quality rating (0-100) | 87/100 |
| `uptime` | Endpoint uptime % | 99.77% |
| `successRate` | Task success rate % | 89% |
| `responseTime` | Response time (ms) | 560ms |
| `reachable` | Endpoint reachable | true/false |
**Key functions:**
* `giveFeedback()` - Submit feedback with score and tags
* `revokeFeedback()` - Remove previous feedback
* `readAllFeedback()` - Get all feedback for an agent
* `getSummary()` - Get aggregated reputation summary
### 3. Validation Registry
Independent verification hooks for high-stakes operations.
**Supported validation approaches:**
| Model | Mechanism | Best For |
| -------------------- | ------------------------------------------ | --------------------------------- |
| **Reputation-based** | Client feedback with scores | Low-stake, frequent interactions |
| **Crypto-economic** | Stake-secured validation with slashing | Medium-stake financial operations |
| **zkML** | Zero-knowledge proofs of correct execution | Privacy-preserving verification |
| **TEE Attestation** | Hardware-isolated execution proofs | High-assurance requirements |
Check out the [repository](https://github.com/erc-8004/erc-8004-contracts/tree/master) of the ERC-8004 protocol for agent discovery and trust through reputation and validation.
## Contract Deployments
### Celo Mainnet
| Contract | Address |
| ------------------- | ------------------------------------------ |
| Identity Registry | 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 |
| Reputation Registry | 0x8004BAa17C55a88189AE136b182e5fdA19dE9b63 |
### Celo Sepolia (Testnet)
| Contract | Address |
| ------------------- | ------------------------------------------ |
| Identity Registry | 0x8004A818BFB912233c491871b3d84c89A494BD9e |
| Reputation Registry | 0x8004B663056A597Dffe9eCcC1965A193B7388713 |
## Quick Start
### Install SDK
The ERC-8004 SDK provides TypeScript/JavaScript and Python interfaces to interact with the on-chain registries. Install the SDK for your preferred language:
```bash theme={null}
# JavaScript/TypeScript
npm install @chaoschain/sdk
# Python
pip install chaoschain-sdk
```
### Register an Agent
Registration mints a new ERC-721 NFT that represents your agent's on-chain identity. You'll need to:
1. Create a registration file (JSON) describing your agent's name, capabilities, and endpoints
2. Upload it to IPFS or host it at a public URL
3. Call the registry to mint your agent NFT with the URI pointing to that file
```javascript theme={null}
import { IdentityRegistry } from '@chaoschain/sdk';
const registry = new IdentityRegistry(provider);
// Upload registration file to IPFS first
const agentURI = 'ipfs://QmYourRegistrationFile';
// Register and get agent ID
const tx = await registry.register(agentURI);
const agentId = tx.events.Transfer.returnValues.tokenId;
console.log('Agent registered with ID:', agentId);
```
### Give Feedback
After interacting with an agent, submit feedback to the Reputation Registry. Each feedback entry includes a score, category tag (like "starred" for quality or "uptime" for availability), and an optional link to detailed off-chain feedback data:
```javascript theme={null}
import { ReputationRegistry } from '@chaoschain/sdk';
const reputation = new ReputationRegistry(provider);
await reputation.giveFeedback(
agentId,
85, // score (0-100)
0, // decimals
'starred', // tag1: category
'', // tag2: optional
'https://agent.example.com', // endpoint used
'ipfs://QmDetailedFeedback', // detailed feedback URI
feedbackHash // keccak256 of feedback content
);
```
### Query Agent Reputation
Before delegating tasks to an agent, check its reputation. You can retrieve all individual feedback entries or get aggregated statistics:
```javascript theme={null}
// Get all feedback
const feedback = await reputation.readAllFeedback(agentId);
// Get summary statistics
const summary = await reputation.getSummary(agentId);
console.log('Average rating:', summary.averageScore);
console.log('Total reviews:', summary.totalFeedback);
```
## Use Cases
### DeFi Trading Agents
This diagram shows a typical agent-to-agent interaction flow. A portfolio management agent needs to execute a trade, so it:
1. Queries the Identity Registry to discover available strategy agents
2. Filters candidates using the Reputation Registry (checking track records, success rates)
3. Selects an agent and requests a trade
4. Pays for the service via x402 (HTTP-native payments)
5. After the trade completes, submits feedback to build the strategy agent's reputation
```mermaid theme={null}
sequenceDiagram
participant PA as Portfolio Agent
participant IR as Identity Registry
participant RR as Reputation Registry
participant SA as Strategy Agent
participant x402 as x402 Payment
PA->>IR: Discover Strategy Agents
IR-->>PA: List of registered agents
PA->>RR: Check reputation scores
RR-->>PA: Filtered by track record
PA->>SA: Execute trade request
SA->>x402: Payment required
PA->>x402: Pay for service
x402-->>SA: Payment confirmed
SA-->>PA: Trade executed
PA->>RR: Submit feedback
```
### Multi-Agent Workflows
AI agents collaborating across organizations can:
* Discover each other via Identity Registry
* Verify credentials before delegation
* Track performance with Reputation Registry
* Use Validation Registry for high-stakes decisions
## Integration with Celo
ERC-8004 works seamlessly with Celo's ecosystem:
* **Fee abstraction**: Register agents and give feedback paying gas in stablecoins
* **x402 payments**: Combine trust verification with instant payments
* **MCP servers**: Agents can expose capabilities via Celo MCP Server
## Resources
| Resource | Link |
| ----------------- | ---------------------------------------------------------------------------------------- |
| EIP Specification | [eips.ethereum.org/EIPS/eip-8004](https://eips.ethereum.org/EIPS/eip-8004) |
| Official Website | [8004.org](https://www.8004.org) |
| Learning Portal | [8004.org/learn](https://www.8004.org/learn) |
| Contracts Repo | [github.com/erc-8004/erc-8004-contracts](https://github.com/erc-8004/erc-8004-contracts) |
| Telegram | [t.me/ERC8004](https://t.me/ERC8004) |
| Builder Program | [bit.ly/8004builderprogram](http://bit.ly/8004builderprogram) |
## Related Protocols
* [x402](/build-on-celo/build-with-ai/x402) - Payment layer for AI agents
* [MPP](/build-on-celo/build-with-ai/mpp) - Machine Payments Protocol: charge USDC per request over HTTP
* [Celopedia](/build-on-celo/build-with-ai/celopedia) - Celo ecosystem knowledge for coding assistants
* [MCP Servers](/build-on-celo/build-with-ai/mcp/index) - Connect agents to data and tools
# Celopedia
Source: https://docs.celo.org/build-on-celo/build-with-ai/celopedia
**Your AI coding assistant, now fluent in Celo.** Celopedia is a knowledge skill that plugs verified Celo intelligence — contract addresses, protocols, MiniPay, grants, and agent infrastructure — straight into the tools you already build with.
Go from "what should I build?" to a live dApp without tab-hopping through docs.
Search live ecosystem data to spot the gaps and opportunities worth building.
Compare verticals, pick the right protocols, and scope an architecture that fits Celo.
Pressure-test as you go — how saturated is this market, how does my approach compare?
Grab contract addresses, MiniPay and fee-abstraction patterns, and deploy — all in your editor.
## Install Celopedia
Add it to your coding assistant with one command:
```bash theme={null}
npx skills add celo-org/celopedia-skills
```
Restart your coding assistant afterward if it doesn't discover new skills mid-session. Celopedia works with file-based skill environments including Codex, Claude Code, and OpenClaw — see the [GitHub repository](https://github.com/celo-org/celopedia-skills) for tool-specific install notes.
## Try it
Once installed, ask your assistant things like:
```text theme={null}
What lending protocols exist on Celo, and which vertical is least saturated?
Give me the Uniswap V4 contract addresses on Celo mainnet.
Scaffold a payments Mini App with the recommended architecture.
Set up a Foundry project for Celo with fee abstraction.
```
## What's inside
| Area | What you get |
| ---------------------- | ---------------------------------------------------------------------------------- |
| Network & contracts | Chain IDs, RPCs, explorers, fee currencies, and verified contract addresses |
| Ecosystem intelligence | Product discovery, competitor scans, and vertical analysis |
| Builder setup | Foundry, Hardhat, Viem, Wagmi, fee abstraction, and deploy & verify patterns |
| DeFi | References for Uniswap, Aave, Morpho, Mento, Velodrome, Curve, Ubeswap, and stCELO |
| MiniPay | Wallet detection, stablecoin payments, ODIS, templates, and listing guidance |
| AI agents | ERC-8004, x402, the Celo MCP Server, and agent skill references |
| Grants | Funding programs and grant matchmaking |
Celopedia is curated from official Celo documentation, protocol references, and live public data sources including Celo Docs, The Grid, DefiLlama, and Celoscan.
## Resources
* [Celopedia](https://celopedia.celo.org/)
* [Celopedia GitHub repository](https://github.com/celo-org/celopedia-skills)
# Celo MCP Server
Source: https://docs.celo.org/build-on-celo/build-with-ai/mcp/celo-mcp
The **Celo MCP Server** is a Model Context Protocol (MCP) server that provides comprehensive access to the Celo blockchain. This powerful tool enables AI assistants and development environments to interact directly with Celo blockchain data, execute token operations, manage NFTs, handle smart contract interactions, process transactions, and participate in governance operations.
## Key Features
* 🔗 **Blockchain Data Access**: Real-time access to blocks, transactions, and account information
* 💰 **Token Operations**: Complete ERC20 and Mento stable token support (USDm, EURm, BRLm)
* 🖼️ **NFT Management**: Support for ERC721 and ERC1155 standards with metadata fetching
* 📄 **Smart Contract Interactions**: Call functions, estimate gas, and manage ABIs
* 📊 **Transaction Handling**: Gas estimation, EIP-1559 support, and transaction simulation
* 🏛️ **Governance Operations**: Access to Celo governance proposals and voting data
## Prerequisites
* Python 3.11 or higher
* Git (v2.38 or higher)
* An IDE that supports MCP (Cursor or Claude Desktop)
## Installation
### Method 1: Direct Installation
Clone the repository and install dependencies:
```bash theme={null}
git clone https://github.com/celo-org/celo-mcp
cd celo-mcp
pip install -e .
```
### Method 2: Using pipx (Recommended)
```bash theme={null}
pip install pipx
pipx install celo-mcp
```
## Configuration
Set up optional environment variables for custom RPC endpoints:
```bash theme={null}
export CELO_RPC_URL="https://forno.celo.org" # Default: Celo mainnet
export CELO_TESTNET_RPC_URL="https://forno.celo-sepolia.celo-testnet.org/" # Celo Sepolia testnet
```
## MCP Client Integration
MCP is supported by a wide range of IDEs and development tools. Below are setup instructions for popular options:
### VS Code Setup
VS Code has native MCP support. Add the following configuration to your MCP settings:
**macOS/Linux**: `~/.vscode/mcp.json` or via VS Code settings
**Windows**: `%APPDATA%\Code\User\mcp.json`
```json theme={null}
{
"mcpServers": {
"celo-mcp": {
"command": "uvx",
"args": ["--refresh", "celo-mcp"]
}
}
}
```
### Cursor IDE Setup
Add the following configuration to your MCP settings file (`~/.cursor/mcp.json`):
```json theme={null}
{
"mcpServers": {
"celo-mcp": {
"command": "uvx",
"args": ["--refresh", "celo-mcp"]
}
}
}
```
The `--refresh` flag ensures the latest code is always loaded when the MCP server starts.
### JetBrains IDEs Setup
For IntelliJ IDEA, WebStorm, PyCharm, and other JetBrains IDEs, configure MCP through the IDE settings or via the JetBrains MCP Server plugin.
### Windsurf Setup
Windsurf has built-in MCP support. Configure MCP servers through the Windsurf settings interface.
### Claude Desktop Setup
For Claude Desktop, add this configuration to your MCP settings file:
* **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
* **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
```json theme={null}
{
"mcpServers": {
"celo-mcp": {
"command": "uvx",
"args": ["--refresh", "celo-mcp"]
}
}
}
```
## Available Tools
### Blockchain Data Operations
#### Network and Block Information
* **`get_network_status`**: Get current network status and connection information
* **`get_block`**: Fetch block information by number, hash, or "latest"
* **`get_latest_blocks`**: Get information about recent blocks (up to 100)
#### Account and Transaction Data
* **`get_account`**: Get account information including balance and nonce
* **`get_transaction`**: Get detailed transaction information by hash
### Token Operations
#### Token Information and Balances
* **`get_token_info`**: Get detailed token information (name, symbol, decimals, supply)
* **`get_token_balance`**: Get token balance for a specific address
* **`get_celo_balances`**: Get CELO and stable token balances for an address
### NFT Operations
#### NFT Management
* **`get_nft_info`**: Get NFT information including metadata and collection details
* **`get_nft_balance`**: Get NFT balance for an address (supports ERC721 and ERC1155)
### Smart Contract Operations
#### Contract Interactions
* **`call_contract_function`**: Call read-only contract functions
* **`estimate_contract_gas`**: Estimate gas for contract function calls
### Transaction Operations
#### Transaction Management
* **`estimate_transaction`**: Estimate gas and cost for transactions
* **`get_gas_fee_data`**: Get current gas fee data including EIP-1559 fees
### Governance Operations
#### Celo Governance
* **`get_governance_proposals`**: Get Celo governance proposals with pagination
* **`get_proposal_details`**: Get detailed information about specific governance proposals
## Development
### Running Tests
```bash theme={null}
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run with coverage
pytest --cov=celo_mcp
```
### Code Quality
```bash theme={null}
# Format code
black src/
isort src/
# Lint code
flake8 src/
mypy src/
```
## Running the Server
Start the MCP server directly:
```bash theme={null}
# Run the MCP server
python -m celo_mcp.server
```
# Model Context Protocol (MCP)
Source: https://docs.celo.org/build-on-celo/build-with-ai/mcp/index
[The Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) is an open protocol that standardizes how applications provide context to Large Language Models (LLMs). It was developed by Anthropic, the AI company behind Claude, to solve the challenge of consistently and efficiently connecting AI models with various data sources and tools. MCP has become the industry standard for integrating AI tools and IDEs, with widespread adoption across major development environments including VS Code, Cursor, JetBrains IDEs, Windsurf, Zed, and many others. OpenAI has also adopted MCP across their Agents SDK and ChatGPT desktop app, ensuring broad compatibility across major AI platforms.
## Celo specific MCPs:
* [Celo MPC Server](/build/build-with-ai/mcp/celo-mcp)
* Chain Info
* Governance Proposals
## Why MCP?
MCP helps you build agents and complex workflows on top of LLMs by providing:
* A growing list of pre-built integrations that your LLM can directly plug into
* The flexibility to switch between LLM providers and vendors
* Best practices for securing your data within your infrastructure
## Core Architecture
MCP follows a client-server architecture where a host application can connect to multiple servers:
### Components
* **MCP Hosts**: Programs like Claude Desktop, IDEs (VS Code, Cursor, JetBrains, Windsurf, Zed, and more), or AI tools that want to access data through MCP
* **MCP Clients**: Protocol clients that maintain 1:1 connections with servers
* **MCP Servers**: Lightweight programs that each expose specific capabilities through the standardized Model Context Protocol
* **Local Data Sources**: Your computer's files, databases, and services that MCP servers can securely access
* **Remote Services**: External systems available over the internet (e.g., through APIs) that MCP servers can connect to
## Discover MCP Servers
Explore existing MCP server implementations:
* [Awesome MCP Servers](https://mcpservers.org/) - Technical implementations
* [Awesome MCP Servers](https://github.com/punkpeye/awesome-mcp-servers) - Technical, art, marketing, and more
## Additional Resources
* [Official MCP Documentation](https://modelcontextprotocol.io/introduction)
* [MCP Community Discussions](https://github.com/modelcontextprotocol/modelcontextprotocol/discussions)
# MPP: Machine Payments Protocol
Source: https://docs.celo.org/build-on-celo/build-with-ai/mpp
The **Machine Payments Protocol (MPP)** is an open standard for HTTP-native payments — it gives meaning to the HTTP `402 Payment Required` status code so that agents, apps, and services can pay each other for API access in a single request, with no accounts, invoices, or checkout flows.
On Celo, MPP lets any service charge **USDC** per request. The buyer pays **no gas** — settlement is handled on-chain by a hosted facilitator.
## How it works
A request with no payment gets a `402` carrying an MPP **Challenge**. The buyer signs a **Credential** and retries; the server settles the payment on Celo and returns a **Receipt** with the on-chain transaction.
```mermaid theme={null}
sequenceDiagram
participant Buyer as Buyer (agent/app)
participant Seller as Your API
participant Facilitator as Facilitator
participant Chain as Celo
Buyer->>Seller: 1. GET /premium (no payment)
Seller-->>Buyer: 2. 402 + WWW-Authenticate: Payment (challenge)
Buyer->>Buyer: 3. Sign credential (EIP-3009, no gas)
Buyer->>Seller: 4. Retry with Authorization (credential)
Seller->>Facilitator: 5. Settle
Facilitator->>Chain: 6. Submit USDC transfer, pay gas
Chain-->>Facilitator: 7. Confirmed
Facilitator-->>Seller: 8. Settlement reference
Seller-->>Buyer: 9. 200 + Payment-Receipt (tx hash)
```
USDC moves buyer → seller directly inside the token contract. The facilitator
submits the transaction and pays the gas; it never custodies funds.
## Prerequisites
Settlement runs through a hosted facilitator that charges a small credit per
transaction. Get an API key (a human does this once):
1. Open [x402.celo.org](https://x402.celo.org) and connect an EVM wallet.
2. Click **Create API key** and sign the message (no gas, no transaction).
3. Copy the key (shown once) — it looks like `x402_...`.
4. Set it as `X402_API_KEY` in your project.
New accounts start with free testnet and mainnet credits. Develop on **Celo
Sepolia** first.
## Build with MPP
Install the [`mppx`](https://www.npmjs.com/package/mppx) SDK.
```bash theme={null}
npm i mppx @hono/node-server hono viem
```
### Seller — charge for your API
Configure MPP with one payment method — a one-time EVM charge on Celo — and
settle through the Celo facilitator. Passing the known asset
(`assets.celoSepolia.USDC`) lets `mppx` infer the chain id, decimals, and EIP-712
domain for you.
```ts theme={null}
import { serve } from "@hono/node-server";
import { Hono } from "hono";
import { Mppx } from "mppx/server";
import { evm, assets } from "mppx/evm/server";
// Attach the facilitator API key to every settlement request.
const apiKeyFetch: typeof fetch = (input, init = {}) => {
const headers = new Headers(init.headers);
headers.set("X-API-Key", process.env.X402_API_KEY!);
return fetch(input, { ...init, headers });
};
const mppx = Mppx.create({
methods: [
evm.charge({
currency: assets.celoSepolia.USDC, // Celo Sepolia (mainnet: assets.celo.USDC)
recipient: process.env.SELLER_PAY_TO as `0x${string}`, // your receiving wallet
x402: {
facilitator: "https://api.x402.sepolia.celo.org", // mainnet: https://api.x402.celo.org
fetch: apiKeyFetch,
},
}),
],
secretKey: process.env.MPP_SECRET_KEY!, // openssl rand -base64 32
});
const app = new Hono();
app.get("/premium", async (c) => {
const result = await mppx.charge({ amount: "0.01" })(c.req.raw); // $0.01
if (result.status === 402) return result.challenge;
return result.withReceipt(Response.json({ data: "this response cost $0.01" }));
});
serve({ fetch: app.fetch, port: 3402 });
```
### Buyer — pay automatically
The `mppx` client patches `fetch` to answer MPP challenges automatically. The
buyer needs a wallet funded with USDC and **no** native gas.
```ts theme={null}
import { privateKeyToAccount } from "viem/accounts";
import { Mppx } from "mppx/client";
import { evm } from "mppx/evm/client";
const account = privateKeyToAccount(process.env.BUYER_PRIVATE_KEY as `0x${string}`);
Mppx.create({
methods: [
evm.charge({
account,
networks: [11142220], // Celo Sepolia (mainnet: 42220)
currencies: ["0x01C5C0122039549AD1493B8220cABEdD739BC44E"], // Celo Sepolia USDC
decimals: 6,
authorization: { name: "USDC", version: "2" }, // Celo USDC EIP-712 domain
maxAmount: "1", // never pay more than 1 USDC per request
}),
],
});
// Global fetch now pays MPP-gated endpoints automatically.
const res = await fetch("http://localhost:3402/premium");
console.log(res.status, await res.json()); // 200, your paid content
```
On the **buyer** side you must supply the token `decimals` and its EIP-712
`authorization` (`{ name, version }`) — the client builds the payment
credential locally and does not read these from the server's challenge. For
Celo USDC the domain is `name: "USDC"`, `version: "2"`.
## Example project
A complete, runnable seller + buyer you can clone and run in minutes — verified
end-to-end on Celo testnet and mainnet:
Minimal MPP example on Celo — a paid API and a client that pays it.
```bash theme={null}
git clone https://github.com/celo-org/mpp-celo-example
cd mpp-celo-example
npm install
cp .env.example .env # add MPP_SECRET_KEY, X402_API_KEY, SELLER_PAY_TO, BUYER_PRIVATE_KEY
npm run seller # terminal 1
npm run buyer # terminal 2 — pays and prints the settlement tx
```
## Supported assets on Celo
| Token | Network | Address |
| ----- | ------------ | -------------------------------------------- |
| USDC | Celo mainnet | `0xcebA9300f2b948710d2653dD7B07f33A8B32118C` |
| USDC | Celo Sepolia | `0x01C5C0122039549AD1493B8220cABEdD739BC44E` |
Both are 6-decimal and support gasless EIP-3009 transfers.
## Resources
* MPP protocol: [mpp.dev](https://mpp.dev)
* `mppx` SDK: [npmjs.com/package/mppx](https://www.npmjs.com/package/mppx)
* Facilitator dashboard (API key + credits): [x402.celo.org](https://x402.celo.org)
* Example repo: [celo-org/mpp-celo-example](https://github.com/celo-org/mpp-celo-example)
# Build with AI on Celo
Source: https://docs.celo.org/build-on-celo/build-with-ai/overview
## Agentic Activity with Real World Utility
Celo is a leading Ethereum Layer 2 optimized for agentic activity with real-world utility, enabling AI agents to autonomously perform onchain actions tied directly to payments, commerce, and financial coordination.
Agents on Celo can tap into the network's expansive payments ecosystem, leveraging fast finality, sub-cent transaction costs, and a stablecoin-optimized financial stack spanning peer-to-peer transfers, merchant payments, remittances, and onchain FX. Combined with native support for agent standards like [ERC-8004](/build-on-celo/build-with-ai/8004) for trust, [x402](/build-on-celo/build-with-ai/x402) and [MPP](/build-on-celo/build-with-ai/mpp) for HTTP-native payments, and Celo's [Celopedia](/build-on-celo/build-with-ai/celopedia), Celo provides a production-ready environment for deploying AI agents that do more than trade tokens—they move money, coordinate economic activity, and interact with real users at global scale.
## Why Build AI Agents on Celo
On Celo, AI Agents can experiment and execute at scale. Celo's infrastructure is optimized for high-frequency, real-world transactions that AI agents rely on to operate autonomously and cost-effectively.
Key advantages include:
* **Fast finality and sub-cent transaction costs**, enabling agents to act continuously without prohibitive fees
* **Stablecoin-optimized design**, supporting payments, savings, subscriptions, and settlements across 25 stable assets tracking a wide range of local currencies
* **Mobile-first reach**, allowing agents to interact with users through wallets and apps used daily across global markets
* **Ethereum alignment**, giving agents access to the broader Ethereum ecosystem while operating in a purpose-built execution environment
This makes Celo uniquely suited for agentic workflows tied to commerce, coordination, and financial automation.
## What Is an AI Agent on Celo
An AI agent on Celo is a software system that can:
* Observe onchain and offchain data
* Make decisions using AI models or rule-based logic
* Execute transactions and contract calls autonomously
* Interact with users, wallets, and protocols without constant manual input
On Celo, agents are first-class participants in the economy. They can send and receive stablecoins, pay for services, manage balances, interact with DeFi protocols, and coordinate activity across multiple users and applications.
## Types of AI Agents
**1. Basic AI Agents**
* Simple tasks like chatbots with decision trees.
* Examples: Command processors, basic I/O automation.
**2. Functional Agents**
* Specialized agents with defined purposes.
* Examples: Code review agents, research assistants, or domain-specific solvers.
**3. Autonomous Agents**
* Operate with minimal human intervention.
* Capabilities: Multi-step reasoning, task automation, self-improvement.
**4. Multi-Agent Systems**
* Collaborative systems where agents work together.
* Examples: Collective problem-solving, distributed decision-making, or agent-to-agent communication.
## Agent Payments with x402 and MPP
Agents on Celo can charge and pay for services over plain HTTP, settling in stablecoins in a single request — no accounts, invoices, or checkout flows.
* **[x402](/build-on-celo/build-with-ai/x402)** gives meaning to the HTTP `402 Payment Required` status code, letting an agent settle a stablecoin micropayment inline with the request.
* **[MPP (Machine Payments Protocol)](/build-on-celo/build-with-ai/mpp)** builds on the same flow so any service can charge USDC per request through a hosted facilitator — the buyer pays no gas.
Both settle on-chain in seconds, making them well-suited to paid APIs, pay-per-use tools, and agent-to-agent commerce.
## Fee Abstraction for Agents
AI agents on Celo can pay gas fees in stablecoins like USDC or USDT instead of needing a separate CELO balance. This simplifies agent treasury management to a single token — the same stablecoin the agent already holds for payments and settlements.
Celo supports a `feeCurrency` field on transactions that lets you specify which token to use for gas. [viem](https://viem.sh/) has native support for this field, making it the recommended library for agent backends.
### Quick Start
This example shows an agent sending a USDC transfer while paying gas in USDC:
```typescript theme={null}
import { createWalletClient, createPublicClient, http, parseUnits } from "viem";
import { celo } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
import { erc20Abi } from "viem";
// Agent's wallet
const account = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY as `0x${string}`);
const walletClient = createWalletClient({
account,
chain: celo,
transport: http(),
});
const publicClient = createPublicClient({
chain: celo,
transport: http(),
});
// Addresses
const USDC = "0xcebA9300f2b948710d2653dD7B07f33A8B32118C";
const USDC_ADAPTER = "0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B";
async function sendUSDCWithFeeAbstraction(to: `0x${string}`, amount: bigint) {
const hash = await walletClient.writeContract({
address: USDC,
abi: erc20Abi,
functionName: "transfer",
args: [to, amount],
feeCurrency: USDC_ADAPTER, // Pay gas in USDC
});
const receipt = await publicClient.waitForTransactionReceipt({ hash });
return receipt;
}
// Agent sends 1 USDC, gas paid in USDC — no CELO needed
await sendUSDCWithFeeAbstraction("0xRecipient...", parseUnits("1", 6));
```
When using USDC or USDT as fee currency, always use the **adapter address** (not the token address). Adapters normalize the 6-decimal tokens to the 18-decimal format that Celo's gas pricing requires. For 18-decimal tokens like USDm, use the token address directly.
### Adapter Addresses
| Token | Network | Token Address | Adapter Address (use for `feeCurrency`) |
| ----- | ------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
| USDC | Mainnet | [`0xcebA9300f2b948710d2653dD7B07f33A8B32118C`](https://celoscan.io/address/0xcebA9300f2b948710d2653dD7B07f33A8B32118C) | [`0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B`](https://celoscan.io/address/0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B) |
| USDT | Mainnet | [`0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e`](https://celoscan.io/address/0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e) | [`0x0e2a3e05bc9a16f5292a6170456a710cb89c6f72`](https://celoscan.io/address/0x0e2a3e05bc9a16f5292a6170456a710cb89c6f72) |
| USDC | Sepolia | [`0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B`](https://sepolia.celoscan.io/address/0x2f25deb3848c207fc8e0c34035b3ba7fc157602b) | [`0x4822e58de6f5e485eF90df51C41CE01721331dC0`](https://sepolia.celoscan.io/address/0x4822e58de6f5e485eF90df51C41CE01721331dC0) |
For the full guide — including gas estimation, CIP-64 transaction types, and CLI usage — see [Fee Abstraction](/build-on-celo/fee-abstraction/using-fee-abstraction).
## Crediting Agent Transactions to Your App
Agents transacting on behalf of your app can also carry an [attribution tag](/build-on-celo/attribution-tags), so the on-chain activity they generate is credited back to you — useful for tracking usage across Proof of Ship, MiniPay, or your own analytics.
# AI Agents Examples
Source: https://docs.celo.org/build-on-celo/build-with-ai/usecases
## Use Cases
AI Agents transform how people interact with onchain applications. Here's a list of 25+ use cases.
Do you have an AI Agent project, tool, or hackathon you want to share? Add it to the GitHub resources list [here](https://github.com/celo-org/ai-agent-ideas).
## Ideas to Build
#### Onchain Foreign Exchange (FX) Trading with Autonomous Agents
* Celo, known as the "Home of Stablecoins," supports several dollar-pegged stablecoins like USDT, USDC, and 13 native stablecoins tracking currencies such as the US Dollar, Euro, Brazilian Real, and Kenyan Shilling.
* Build AI agents that facilitate seamless onchain FX trading, leveraging Celo's native stable assets and incentivized liquidity pairs on [Uniswap](https://app.uniswap.org/explore/pools/celo) (powered by [Merkl campaigns](https://merkl.angle.money/?chain=42220) and managed through Steer Protocol).
* **Arbitrage Bots**
* Develop AI-driven arbitrage bots that identify and execute profitable trades across decentralized exchanges (DEXs) on Celo, optimizing for low fees and fast transaction times.
* **Liquidity Pool (LP) Management**
* Create AI tools to automate LP management, ensuring optimal allocation of assets, rebalancing, and yield maximization.
* **Merkle Rewards Optimization with Steer Protocol**
* Find the Merkl campaigns with the highest rewards and provide liquidity through Steer Protocol.
#### Prediction Markets
* Design AI-powered prediction markets that leverage Celo's stablecoins for low-cost, high-efficiency betting and forecasting.
#### Automated Savings and Dollar-Cost Averaging (DCA)
* Develop AI agents that help users automate savings strategies or execute DCA plans using Celo's stablecoins, making financial planning effortless.
#### Automated Data Collection Payments
* Today, 82.7% of collected biodiversity data comes from North America and Europe, leaving massive data gaps in emerging markets.
* AI agents can automate payments for individuals and communities in Celo’s ecosystem, ensuring fair, real-time compensation for valuable data collection.
* See a [case study](https://www.daviddao.org/posts/regenerative-intelligence/) on how GainForest is using AI to drive regenerative finance and intelligent data economies.
#### Optimized Retroactive Funding
* The Celo ecosystem has hosted multiple retroactive funding rounds to reward top contributors for their impact.
* AI agents can automate and optimize this process by analyzing onchain activity, GitHub contributions, and deployed contracts to fairly distribute funding.
* Check out [Proof-of-Ship on Karma](https://www.karmahq.xyz/community/celo) for a list of projects deployed on Celo this month.
# Vibe Coding
Source: https://docs.celo.org/build-on-celo/build-with-ai/vibe-coding
# Vibe Coding Tools
Vibe Coding refers to an approach to software development where you use chat agents inside your IDE and build an application mainly by using prompts. This guide introduces you to a curated collection of tools that can significantly improve your development process, from full-stack application development to code editing and research.
Watch a quick intro to Vibe Coding with the Celo MCP Servers. You can find out more about them in the [MCP section](/build/build-with-ai/mcp/index).
Make sure you watch some tutorials and check out some X threads to understand
other people's setup. Being successful with Vibe Coding relies on your
preparation and setup.
## Full Stack Development Tools
These tools help you build complete applications with minimal setup and maximum efficiency. We list here our favorite tools but this list will be updated continuously. Feel free to create a PR with your favorite tool and let us know why you think it's useful.
### Create a frontend with AI tools, no code
#### [Bolt](https://bolt.new/)
* **Design Integration**: Native Figma support
* **IDE Compatibility**: Runs directly in your development environment
* **Backend Solutions**: Supabase integration for auth and database operations
* **Version Control**: GitHub integration
#### [Lovable](https://lovable.dev/)
* **Beginner-Friendly**: Simplified development process
* **Backend Integration**: Supabase for authentication and database
* **Version Control**: GitHub integration
* **Learning Resources**: Comprehensive documentation
### Development Environments
#### [Replit](https://replit.com/)
* **Production-Ready**: Built-in production server
* **Collaboration**: Real-time coding with team members
* **Deployment**: One-click deployment options
* **Package Management**: Integrated package handling
#### [Base44](https://base44.app/)
For advanced developers seeking:
* **Customization**: Advanced configuration options
* **Performance**: Optimized development environment
* **Integration**: Extensive tool compatibility
* **Scalability**: Enterprise-grade features
## AI-Enhanced IDEs
Modern code editors with AI capabilities to enhance your development workflow.
### [Cursor](https://www.cursor.com/)
An AI-powered code editor featuring:
* **Code Assistance**: Direct code modification suggestions
* **MCP Integration**: Native MCP server support
* **Customization**: Rules and context files for personalized guidance
* **AI Features**: Smart code completion and refactoring
### [Windsurf](https://windsurf.com/)
A development environment with:
* **Code Editing**: AI-assisted code modifications
* **MCP Support**: Integrated MCP server capabilities
* **Live Preview**: In-editor application preview
* **Real-time Collaboration**: Team coding features
## Research & Context Enhancement Tools - MCP Servers
Tools that help you gather and process information effectively, mainly MCPs. Add these to your Cursor!s
### AI-Powered Research - HIGHLY Recommended
* [Perplexity MCP](https://www.perplexity.ai/)
* Web search capabilities
* AI-powered reasoning
* Context-aware responses
* Research synthesis
### Data Collection
* [Firecrawl MCP](https://www.firecrawl.dev/mcp)
* Web scraping capabilities
* Data extraction
* Automated data collection
* Structured output
## Additional Resources
* [MCP Server Guide](/build/build-with-ai/mcp/index) - Learn more about MCP integration
# x402: Agent Payments
Source: https://docs.celo.org/build-on-celo/build-with-ai/x402
x402 is an open protocol for internet-native payments that activates the HTTP 402 "Payment Required" status code. It enables AI agents and applications to make instant, permissionless micropayments using stablecoins.
## Key Features
* **HTTP-Native**: Built into existing HTTP requests with no additional communication required
* **Instant Settlement**: Sub-second on Celo, compared to days with traditional payments
* **Zero Protocol Fees**: Only pay nominal blockchain gas fees
* **Agent-First**: Designed for autonomous AI agent transactions
* **Chain Agnostic**: Supports 170+ EVM chains including Celo
## Why x402?
Traditional payment systems don't work for AI agents and micropayments:
| Challenge | Traditional Payments | x402 |
| ---------------- | -------------------- | ------------------ |
| Setup Time | Days to weeks | Minutes |
| Settlement | 2-7 days | Sub-second on Celo |
| Fees | 2-3% + \$0.30 fixed | \~\$0.001 gas |
| Minimum Payment | \$0.50+ | \$0.001 |
| Account Required | Yes | No |
| API Keys | Required | Not needed |
| Chargebacks | Yes (120 days) | No |
| AI Agent Support | Not possible | Native |
## How It Works
```mermaid theme={null}
sequenceDiagram
participant Client as Client (Agent)
participant Server as Resource Server
participant Facilitator as Facilitator
participant Chain as Blockchain
Client->>Server: 1. Request Resource
Server-->>Client: 2. 402 Payment Required
Note over Server,Client: Payment requirements in headers
Client->>Client: 3. Sign Payment Authorization
Client->>Server: 4. Request + Payment Header
Server->>Facilitator: 5. Verify Payment
Facilitator-->>Server: 6. Valid
Server->>Facilitator: 7. Settle Payment
Facilitator->>Chain: 8. Submit Transaction
Chain-->>Facilitator: 9. Confirmed
Facilitator-->>Server: 10. Settlement Receipt
Server-->>Client: 11. Response + Receipt
```
**Step-by-step:**
1. **Client requests resource** - AI agent or app sends HTTP request to API
2. **Server returns 402** - If no payment attached, server responds with `HTTP 402 Payment Required` and payment details in headers
3. **Client signs payment** - Client signs payment authorization using their wallet
4. **Client retries with payment** - Request sent again with a `PAYMENT-SIGNATURE` header
5. **Server verifies and settles** - Payment is verified and settled on-chain
6. **Server delivers resource** - Requested content returned with payment receipt
## Get Started with the Celo Facilitator
Celo runs its own hosted x402 facilitator, built on the open-source [`x402-rs`](https://github.com/x402-rs/x402-rs) implementation. It is the recommended default for accepting x402 payments on Celo. It accepts **USDC** and **USDT** on Celo via the gasless EIP-3009 `transferWithAuthorization` scheme — the buyer signs an authorization off-chain, and the facilitator submits it on-chain and pays the gas itself. The facilitator never custodies funds: `transferWithAuthorization` moves tokens directly payer → payee inside the token contract.
Two hosts are involved, and they are not interchangeable:
* **Dashboard** — [x402.celo.org](https://x402.celo.org/) serves the web dashboard (a single-page app). Do not point a resource server at it.
* **Payment API** — `https://api.x402.celo.org` (mainnet) is the facilitator endpoint your resource server talks to for `/verify`, `/settle`, and `/supported`. Celo Sepolia is at `https://api.x402.sepolia.celo.org`.
Source: `celo-org/x402-facilitator` (private repo). The endpoints below are live at `https://api.x402.celo.org` (mainnet) and `https://api.x402.sepolia.celo.org` (Celo Sepolia).
### Endpoints
Base URLs:
* **Mainnet** — `https://api.x402.celo.org`
* **Celo Sepolia** — `https://api.x402.sepolia.celo.org`
| Method | Path | Auth | Purpose |
| ------ | ------------ | ----------- | ----------------------------------------------------------------- |
| `POST` | `/verify` | Open | Off-chain signature and simulation check of a payment payload. |
| `POST` | `/settle` | **API key** | Submit the buyer's authorization on-chain (facilitator pays gas). |
| `GET` | `/supported` | Open | List supported `(network, scheme)` pairs. |
| `GET` | `/health` | Open | Liveness probe. |
Only `/settle` requires an API key — so `/verify` and `/supported` succeed and an integration looks healthy right up until its first settlement, which fails with `401` if no key is attached. See [Getting an API Key](#getting-an-api-key).
### Pointing a Resource Server at It
The x402 v2 middleware wires a resource server to the Celo facilitator. Install the scoped packages:
```bash theme={null}
npm i @x402/express @x402/core @x402/evm
```
```ts theme={null}
import express from "express";
import { paymentMiddleware, x402ResourceServer } from "@x402/express";
import { HTTPFacilitatorClient, type RoutesConfig } from "@x402/core/server";
import { ExactEvmScheme } from "@x402/evm/exact/server";
// Celo's hosted facilitator — note the api. subdomain
const facilitator = new HTTPFacilitatorClient({
url: "https://api.x402.celo.org",
// Attaches your metering key to every facilitator request. /settle is
// key-gated; without a valid key it returns 401 Missing X-API-Key.
createAuthHeaders: async () => {
const h = { "X-API-Key": process.env.X402_API_KEY! };
return { verify: h, settle: h, supported: h };
},
});
const server = new x402ResourceServer(facilitator);
server.register("eip155:*", new ExactEvmScheme());
// The RoutesConfig annotation is load-bearing: without it `network` widens to
// `string` and no longer satisfies the CAIP-2 `${string}:${string}` type.
const routes: RoutesConfig = {
"GET /premium": {
accepts: [
{
scheme: "exact",
network: "eip155:42220", // Celo mainnet
payTo: "0xYourSellerPayoutAddress", // your wallet — receives the USDC
price: {
amount: "10000", // $0.01 — USDC has 6 decimals; always a string
asset: "0xcEBA9300f2b948710d2653dD7B07f33A8B32118C",
extra: { name: "USDC", version: "2" }, // EIP-712 domain, must match the token
},
},
],
description: "Premium content",
},
};
const app = express();
app.use(paymentMiddleware(routes, server)); // routes first, then server
app.get("/premium", (_req, res) => res.json({ data: "paid content" }));
app.listen(3000);
```
Using Hono instead of Express? Swap `@x402/express` → `@x402/hono`; the body is identical.
On Celo, use the explicit `price` object shown above. The `price: "$0.01"` dollar shorthand type-checks but currently throws `No default asset configured for network eip155:42220` at request time — it will work once the release carrying Celo's default-asset registry entry ships.
USDT has no `version()` method on-chain — its EIP-712 domain resolves to `name: "Tether USD"`, `version: "1"`. Set those exactly in the `extra` field or signature verification fails.
### Getting an API Key
`/settle` is metered, so accepting real payments requires an API key. To create one:
1. Open the [dashboard](https://x402.celo.org) and connect your wallet.
2. Click **Create API key** and sign the message. This is an off-chain signature — no gas, no transaction.
3. The key is shown once. Copy it and set it as `X402_API_KEY` in your server environment.
The API key is a server-side secret. Never ship it to the browser or expose it to buyers — anyone with the key can spend your settlement credits.
New accounts get free credits on both networks. Beyond that, credits are bought by depositing USDC on the dashboard, priced at \$0.001 per settlement.
If a call to `/settle` fails, the status code tells you why:
| Status | Meaning |
| ------ | ----------------------------------------- |
| `401` | Missing or invalid API key. |
| `402` | Out of credits — top up on the dashboard. |
| `429` | Free-tier rate limit reached. |
## x402 on Celo
Celo is an ideal network for x402 due to:
* **Low fees**: Gas costs under \$0.001 per transaction
* **Fast finality**: \~1 second block times
* **Stablecoin support**: Native USDC and USDT for predictable pricing
* **Fee abstraction**: Agents can pay gas in the same stablecoins used for x402 payments — no separate CELO balance needed. See [Fee Abstraction for Agents](/build-on-celo/build-with-ai/overview#fee-abstraction-for-agents)
### Supported Payment Tokens on Celo
The Celo facilitator settles **USDC** and **USDT** via EIP-3009 `transferWithAuthorization`:
| Token | Address | Decimals |
| ----- | -------------------------------------------- | -------- |
| USDC | `0xcEBA9300f2b948710d2653dD7B07f33A8B32118C` | 6 |
| USDT | `0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e` | 6 |
### Celo Configuration
Each route lists what it accepts by CAIP-2 network identifier. Use the flat `price` object with an explicit asset address on both networks:
```typescript theme={null}
// Mainnet
const mainnetAccepts = {
scheme: "exact",
network: "eip155:42220",
payTo: "0xYourSellerPayoutAddress",
price: {
amount: "10000", // $0.01 — USDC has 6 decimals
asset: "0xcEBA9300f2b948710d2653dD7B07f33A8B32118C", // Celo mainnet USDC
extra: { name: "USDC", version: "2" },
},
};
// Testnet (Celo Sepolia)
const testnetAccepts = {
scheme: "exact",
network: "eip155:11142220",
payTo: "0xYourSellerPayoutAddress",
price: {
amount: "10000", // $0.01 — USDC has 6 decimals
asset: "0x01C5C0122039549AD1493B8220cABEdD739BC44E", // Celo Sepolia USDC
extra: { name: "USDC", version: "2" },
},
};
```
## Use Cases
### AI Agent API Access
An AI agent uses its own wallet to pay for API calls autonomously. The agent doesn't need API keys or pre-registered accounts—it simply pays per request using the x402 protocol. Each call attaches a `PAYMENT-SIGNATURE` header signed by the agent's wallet, enabling truly permissionless agent commerce without accounts or onboarding.
### Pay-Per-Use AI Inference
Instead of charging a fixed price upfront, a server can price each request by actual usage: verify that the buyer's authorization covers up to a maximum amount, run the inference, measure real token consumption, and settle only for what was used. This is ideal for AI inference, where cost varies with prompt length and output tokens. Support for usage-based or "up-to" pricing depends on the x402 middleware and facilitator you use.
### Micropayments for Content
Publishers can monetize individual articles instead of requiring subscriptions. Each request is checked for a valid x402 payment—if missing, the server returns `402 Payment Required` with pricing details; if present, the payment is settled and the content is delivered. This unlocks true pay-per-article pricing at amounts too small for card-based payments.
## Alternative: thirdweb facilitator
[thirdweb](https://thirdweb.com) offers a hosted x402 facilitator and SDK supporting Celo and 170+ EVM chains. It provides React hooks (`useFetchWithPayment`), a `wrapFetchWithPayment` helper for non-React clients, and a `settlePayment` helper for servers, handling wallet connection, payment signing, and retries. See the [thirdweb x402 docs](https://portal.thirdweb.com/x402) and [playground](https://playground.thirdweb.com/x402) to get started.
## Resources
| Resource | Link |
| ------------------------- | ------------------------------------------------------------------------ |
| x402 Official Website | [x402.org](https://www.x402.org) |
| Celo x402 Dashboard | [x402.celo.org](https://x402.celo.org/) |
| Celo x402 Facilitator API | `https://api.x402.celo.org` |
| thirdweb x402 Docs | [portal.thirdweb.com/x402](https://portal.thirdweb.com/x402) |
| thirdweb Playground | [playground.thirdweb.com/x402](https://playground.thirdweb.com/x402) |
| GitHub | [github.com/coinbase/x402](https://github.com/coinbase/x402) |
| Whitepaper | [x402.org/x402-whitepaper.pdf](https://www.x402.org/x402-whitepaper.pdf) |
## Related
* [ERC-8004](/build-on-celo/build-with-ai/8004) - Trust layer for AI agents
* [MPP](/build-on-celo/build-with-ai/mpp) - Machine Payments Protocol: charge USDC per request over HTTP
* [Celopedia](/build-on-celo/build-with-ai/celopedia) - Celo ecosystem knowledge for coding assistants
* [Fee Abstraction](/build-on-celo/fee-abstraction/overview) - Pay gas with stablecoins on Celo
* [Attribution Tags](/build-on-celo/attribution-tags) - Credit on-chain activity back to your app
# Build with DeFi
Source: https://docs.celo.org/build-on-celo/build-with-defi
In this guide you can explore tooling and infrastructure for building DeFi on Celo.
## Overview
DeFi on Celo is designed for builders who want to create accessible, stable, and inclusive financial systems. This guide walks you through the key tools and infrastructure available for developing decentralized finance applications on Celo.
Stablecoins are at the heart of DeFi, they provide price stability, reduce volatility, and power seamless transactions. Celo’s ecosystem is uniquely optimized for stablecoins, supporting real-world use cases that go beyond speculation. By building on Celo, you’re contributing to a global movement that makes financial access open and affordable for everyone.
Explore below how to integrate stablecoins, exchanges, and oracles into your next DeFi project.
## Why Stablecoins Matter
[Stablecoins](/build-on-celo/build-with-local-stablecoin) are digital assets pegged to a stable reserve, such as fiat currency or a basket of assets. They provide key benefits in DeFi and financial transactions and financial inclusion:
Check out [Build with Local
Stablecoins](/build-on-celo/build-with-local-stablecoin) for an overview of
Celo's stablecoin ecosystem, or [Stablecoin
Contracts](/tooling/contracts/stablecoin-contracts) for their addresses.
* **Price Stability** – Unlike volatile cryptocurrencies, stablecoins maintain a predictable value.
* **Low-Cost Transactions** – Sending stablecoins on Celo costs significantly less than on traditional blockchains.
* **Borderless Access** – Users can send and receive stablecoins globally, without needing a bank account.
* **Programmability** – Stablecoins can be used in smart contracts to enable lending, savings, and remittances.
* **Financial Inclusion** – Stablecoins empower unbanked and underbanked populations with access to digital financial services.
Celo is uniquely positioned to advance the adoption of stable digital assets through the [Mento](https://www.mento.org/) Protocol—a decentralized stablecoin platform built on Celo. [Mento](https://www.mento.org/) enables the creation of local stablecoins that are algorithmically stabilized and backed by crypto collateral. This approach helps users access a price-stable digital currency that is aligned with their local economy.
The goal of Mento is simple: to provide a stable asset for every country in the world. These stable assets can be used for everyday payments, savings, remittances, and commerce—empowering individuals in regions with high inflation or limited access to traditional banking infrastructure.
## Examples of DeFi Applications on Celo
Celo supports a vibrant ecosystem of DeFi protocols that utilize stablecoins:
### Lending & Borrowing
* **[Aave](https://aave.com/)** – Decentralized lending and borrowing platform officially launched on Celo in 2025, expanding lending options with institutional and retail liquidity support.
* **[Credit Collective](https://www.credit-collective.com)** – On-chain private credit protocol supporting real-world assets (RWAs) and emerging market stablecoins. Manages liquidity strategies and provides sustainable market-making for new stablecoins.
* **[PWN](https://pwn.xyz/)** – Fixed rate lending platform.
### Exchanges
Find all Exchanges [here](/home/exchanges). For cross-chain exchanges check out the [bridges](/tooling/bridges) and [cross-chain messaging](/tooling/bridges/cross-chain-messaging) pages.
* **[Uniswap v4](https://app.uniswap.org/)** – Launched on Celo in early 2025, bringing advanced "Hooks" features for developer customizations, low-cost swaps, and sub-cent transaction fees. Enables seamless integration with Ethereum liquidity.
* **[Velodrome](https://velodrome.finance/)** – Decentralized exchange where you can execute low-fee swaps, deposit tokens to earn rewards, and actively participate in the onchain economy. Offers high liquidity mining yields.
* **[Carbon DeFi by Bancor](https://www.carbondefi.xyz/)** – Empowering users with onchain automation and superior orderbook-like features. One of the largest DEXs on Celo, processing over \$33.5M in trading volume within its first year.
* **[Ubeswap](https://ubeswap.org/)** – A Celo-native DEX optimized for mobile users, supporting hundreds of trading pairs.
### DEX Aggregators
* **[LI.FI](https://li.fi/)** – Cross-chain DEX aggregator and bridge, facilitating optimal trading routes with a focus on speed and user-friendly access.
* **[Matcha](https://matcha.xyz/)** – Cross-chain DEX aggregator allowing users to find optimal trading routes and limit orders for a wide variety of tokens.
### Liquidity Incentives
* **[Steer Protocol](https://steer.finance/)** – Automated liquidity strategies.
* **[Merkl](https://app.merkl.xyz/)** – Rewarding liquidity providers with stablecoin incentives.
* **[Ichi](https://www.ichi.org/)** – Automated Liquidity Strategies for DeFi Yield.
### Derivatives
* **[Lynx](https://lynx.finance/)** – Decentralized perpetual contract trading platform, adding leveraged trading and robust liquidity to Celo's DeFi toolkit.
### Oracles
Oracles are a crucial part to get real time price information on tokens. Speed is crucial when it comes to building DeFi applications, and you should not rely on web2 APIs for price feeds. Find all Oracles in the [tooling section](/tooling/oracles).
* [RedStone Oracles](/tooling/oracles/redstone)
* [Chainlink Price Feed Oracles](https://docs.chain.link/data-feeds/price-feeds/addresses?network=celo)
* [Supra Oracles](/tooling/oracles/supra)
* [Band Protocol](/tooling/oracles/band-protocol)
### Human-Centered Security Tools
* **[Noves](https://docs.noves.fi/reference/api-overview)** - Deciphering onchain activity and standardizing the results
* Human‑readable DeFi, ReFi & bridge txs
* Pre‑sign safety simulations in any Celo wallet
* Real‑time CELO / USDm / stCELO pricing
## Get Started
Developers and entrepreneurs can leverage Celo's infrastructure to build next-generation stablecoin applications.
By building on Celo, you're not just creating DeFi applications, you're enabling real-world financial inclusion and empowering users globally.
# Build with Farcaster
Source: https://docs.celo.org/build-on-celo/build-with-farcaster
## Build a Farcaster MiniApp
Building a MiniApp comes with many benefits. You don't need to manage on- and off‑ramp integrations, and the user experience is more seamless because your app runs inside a wallet client. For testing and scaling, we recommend keeping a standard wallet connection in your app; it should be hidden automatically when the app runs in a MiniApp environment. Our templates already include this setup, so we suggest creating your MiniApp using our starterkit, [Celo Composer](https://github.com/celo-org/celo-composer). Setting up a Farcaster MiniApp involves several specific settings, and our template provides a step‑by‑step guide to walk you through them.
Before you start building a Farcaster MiniApp, we recommend watching this video on how to build a successful MiniApp on Farcaster.
Make sure to also read the [Farcaster MiniApp documentation](https://miniapps.farcaster.xyz/). You'll save a lot of time by reviewing it in detail before building. We also recommend testing a few popular Farcaster MiniApps to get a feel for UX patterns.
## Quick Start
Use this command to scaffold a Farcaster MiniApp quickly using the [Celo Composer](https://github.com/celo-org/celo-composer):
```bash theme={null}
npx @celo/celo-composer@latest create --template farcaster-miniapp
```
When using this command, follow this workshop to configure everything correctly and avoid missing important implementations or settings.
## SDK Installation and Setup
### Install the MiniApp SDK
Install the Farcaster MiniApp SDK using your preferred package manager:
```bash npm theme={null}
npm install @farcaster/miniapp-sdk
```
```bash yarn theme={null}
yarn add @farcaster/miniapp-sdk
```
```bash pnpm theme={null}
pnpm add @farcaster/miniapp-sdk
```
### Initialize the SDK
After your app loads, you **must** call `sdk.actions.ready()` to hide the splash screen and display your content:
```js theme={null}
import { sdk } from "@farcaster/miniapp-sdk";
// After your app is fully loaded and ready to display
await sdk.actions.ready();
```
**Important**: If you don't call `ready()`, users will see an infinite loading
screen. This is one of the most common issues when building Mini Apps.
## Wallet Integration
### Using Wagmi (Recommended)
The Mini App SDK exposes an [EIP-1193 Ethereum Provider API](https://eips.ethereum.org/EIPS/eip-1193) at `sdk.wallet.getEthereumProvider()`. We recommend using [Wagmi](https://wagmi.sh) to connect to and interact with the user's wallet.
#### Install the Wagmi Connector
```bash theme={null}
npm install @farcaster/miniapp-wagmi-connector wagmi viem
```
#### Configure Wagmi
Add the Mini App connector to your Wagmi config:
```js theme={null}
import { http, createConfig } from "wagmi";
import { celo, celoSepolia } from "wagmi/chains";
import { farcasterMiniApp as miniAppConnector } from "@farcaster/miniapp-wagmi-connector";
export const config = createConfig({
chains: [celo, celoSepolia],
transports: {
[celo.id]: http(),
[celoSepolia.id]: http(),
},
connectors: [miniAppConnector()],
});
```
#### Connect to Wallet
If a user already has a connected wallet, the connector will automatically connect (e.g., `isConnected` will be `true`). Always check for a connection and prompt users to connect if needed:
```js theme={null}
import { useAccount, useConnect } from "wagmi";
function ConnectMenu() {
const { isConnected, address } = useAccount();
const { connect, connectors } = useConnect();
if (isConnected) {
return (
<>
You're connected!
Address: {address}
>
);
}
return (
);
}
```
Your Mini App won't need to show a wallet selection dialog that is common in a
web-based dapp. The Farcaster client hosting your app will take care of
getting the user connected to their preferred crypto wallet.
### Send Transactions
You're now ready to prompt the user to transact. They will be shown a preview of the transaction in their wallet and asked to confirm it:
```js theme={null}
import { useSendTransaction } from "wagmi";
import { parseEther } from "viem";
function SendTransaction() {
const { sendTransaction } = useSendTransaction();
const handleSend = () => {
sendTransaction({
to: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
value: parseEther("0.01"),
});
};
return ;
}
```
### Batch Transactions (EIP-5792)
The Farcaster Wallet supports EIP-5792 `wallet_sendCalls`, allowing you to batch multiple transactions into a single user confirmation. This improves UX by enabling operations like "approve and swap" in one step.
Common use cases include:
* Approving a token allowance and executing a swap
* Multiple NFT mints in one operation
* Complex DeFi interactions requiring multiple contract calls
#### Using Batch Transactions with Wagmi
```js theme={null}
import { useSendCalls } from "wagmi";
import { parseEther } from "viem";
function BatchTransfer() {
const { sendCalls } = useSendCalls();
return (
);
}
```
#### Example: Token Approval and Swap
```js theme={null}
import { useSendCalls } from "wagmi";
import { encodeFunctionData, parseUnits } from "viem";
import { erc20Abi } from "viem";
function ApproveAndSwap() {
const { sendCalls } = useSendCalls();
const handleApproveAndSwap = () => {
sendCalls({
calls: [
// Approve USDC
{
to: "0xcebA9300f2b948710d2653dD7B07f33A8B32118C", // USDC on Celo
data: encodeFunctionData({
abi: erc20Abi,
functionName: "approve",
args: [
"0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", // Router address
parseUnits("100", 6), // Amount
],
}),
},
// Swap USDC for CELO
{
to: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", // Uniswap Router
data: encodeFunctionData({
abi: uniswapAbi,
functionName: "swapExactTokensForETH",
args: [
/* swap parameters */
],
}),
},
],
});
};
return ;
}
```
**Limitations:**
* Transactions execute sequentially, not atomically
* No paymaster support yet
* Available on all EVM chains Farcaster supports
Use individual transactions when you need to check outputs between calls.
## Authentication
### Quick Auth (Recommended)
Quick Auth is the easiest way to get an authenticated session for a user. It uses [Sign in with Farcaster](https://docs.farcaster.xyz/developers/siwf/) under the hood and returns a standard JWT that can be easily verified by your server.
```js theme={null}
import { sdk } from "@farcaster/miniapp-sdk";
// Get authentication token
const token = await sdk.quickAuth.getToken();
// Use token in API calls
const response = await fetch("https://api.example.com/user", {
headers: {
Authorization: `Bearer ${token}`,
},
});
```
The `getToken()` method stores the token in memory and returns it if not expired, otherwise fetches a new one.
### Sign In with Farcaster
Alternatively, you can use the `signIn` action to get a Sign in with Farcaster authentication credential:
```js theme={null}
import { sdk } from "@farcaster/miniapp-sdk";
const credential = await sdk.actions.signIn();
```
After requesting the credential, applications must verify it on their server using [`verifySignInMessage`](https://docs.farcaster.xyz/auth-kit/client/app/verify-sign-in-message). Apps can then issue a session token like a JWT for the remainder of the session.
## Manifest Configuration
Mini Apps require a manifest file that describes your app. The manifest tells Farcaster clients how to display and interact with your app.
### Basic Manifest
Create a `manifest.json` file in your app's root directory:
```json theme={null}
{
"name": "My Celo MiniApp",
"description": "A MiniApp built on Celo",
"iconUrl": "https://example.com/icon.png",
"splashImageUrl": "https://example.com/splash.png",
"splashBackgroundColor": "#000000",
"url": "https://example.com"
}
```
### Required Fields
* **name**: Display name of your MiniApp
* **description**: Brief description of what your app does
* **iconUrl**: URL to your app's icon (recommended: 512x512px)
* **splashImageUrl**: URL to splash screen image (recommended: 1920x1080px)
* **splashBackgroundColor**: Background color for splash screen (hex format)
* **url**: URL where your MiniApp is hosted
### Optional Fields
* **requiredChains**: Array of chain IDs your app requires (e.g., `[42220]` for Celo)
* **requiredCapabilities**: Array of required wallet capabilities
* **homeUrl**: URL to navigate when user taps home button
### Deprecated Fields
The following fields are deprecated and should not be used:
* `imageUrl` (use `iconUrl` instead)
* `buttonTitle` (no longer needed)
When `url` is not provided in `actionLaunchFrameSchema`, it defaults to the
current webpage URL (including query parameters).
## Additional Features
### Environment Detection
Detect if your app is running inside a MiniApp environment:
```js theme={null}
import { isInMiniApp } from "@farcaster/miniapp-sdk";
if (isInMiniApp()) {
// Running in MiniApp
} else {
// Running in regular browser
}
```
### Back Navigation
Integrate back control for better navigation:
```js theme={null}
import { sdk } from "@farcaster/miniapp-sdk";
// Navigate back
sdk.back();
```
### Haptic Feedback
Provide haptic feedback for better user interaction:
```js theme={null}
import { sdk } from "@farcaster/miniapp-sdk";
// Trigger haptic feedback
sdk.haptics.impact(); // Light impact
sdk.haptics.notification(); // Notification feedback
sdk.haptics.selection(); // Selection feedback
```
### Share Extensions
Enable your app to receive shared casts from the system share sheet:
```js theme={null}
import { sdk } from "@farcaster/miniapp-sdk";
// Listen for shared casts
sdk.context.cast_share?.then((cast) => {
console.log("Received cast:", cast);
});
```
## Publishing Your MiniApp
After building your MiniApp, you'll need to publish it so users can discover and use it. Follow the [Farcaster MiniApp publishing guide](https://miniapps.farcaster.xyz/docs/guides/publishing) for detailed instructions.
## Resources
* [Farcaster MiniApp Documentation](https://miniapps.farcaster.xyz/)
* [Farcaster MiniApp SDK Reference](https://miniapps.farcaster.xyz/docs/sdk)
* [Celo Composer](https://github.com/celo-org/celo-composer)
* [Wagmi Documentation](https://wagmi.sh)
# Build with Local Stablecoins
Source: https://docs.celo.org/build-on-celo/build-with-local-stablecoin
Celo supports more than 30 fiat-referenced stablecoins: 7 USD-pegged assets, 26 pegged to regional currencies, and GoodDollar's UBI token. Most chains give builders a dollar and little else. On Celo, a payments app in Nairobi can settle in KESm, a remittance corridor into Brazil can settle in BRLm, and neither has to route through a dollar first.
Contract addresses for every stablecoin on Celo Mainnet and the Celo Sepolia Testnet.
## Why Local Stablecoins Matter
* **Price stability** — unlike volatile cryptocurrencies, stablecoins hold a predictable value.
* **Local denomination** — users hold and spend in their own currency instead of converting to and from dollars.
* **Low-cost transactions** — sub-cent fees make small transfers and micropayments practical.
* **Borderless access** — send and receive globally without a bank account.
* **Programmability** — use them in smart contracts for lending, savings, payroll, and remittances.
* **Onchain FX** — swap directly between currency pairs through [Mento](https://www.mento.org/).
## Mento Stablecoins
[Mento](https://www.mento.org/) is a decentralized stablecoin platform built on Celo. It issues 15 stablecoins that are algorithmically stabilized and backed by crypto collateral, spanning both major reserve currencies and local ones:
| Region | Stablecoins |
| ------------ | ---------------------------- |
| Americas | USDm, BRLm, CADm, COPm |
| Europe | EURm, GBPm, CHFm |
| Africa | KESm, NGNm, GHSm, ZARm, XOFm |
| Asia-Pacific | JPYm, PHPm, AUDm |
Because Mento holds a diversified reserve, these assets can be swapped directly against one another — a Kenyan Shilling to West African CFA franc trade settles onchain without a dollar leg.
## Other Issuers
Alongside Mento, independent issuers have deployed stablecoins on Celo:
| Issuer | Assets |
| -------------------------------------------------- | -------------------------------------- |
| [Circle](https://www.circle.com/usdc) | USDC |
| [Tether](https://tether.to/en/) | USD₮ |
| [Anchorage Digital Bank](https://usat.io/) | [USA₮](/build-on-celo/build-with-usat) |
| [Ripio](https://ripio.com/) | wARS, wBRL, wMXN, wCOP, wPEN, wCLP |
| [VNX](https://vnx.li/) | vGBP, vCHF |
| [Africa Stablecoin Consortium](https://cngn.co/) | cNGN |
| [Angle](https://www.angle.money/) | USDA, EURA |
| [Mountain Protocol](https://mountainprotocol.com/) | USDM |
| [Glo Foundation](https://www.glodollar.org/) | USDGLO |
| [BRLA](https://brla.digital/) | BRLA |
| [Minteo](https://minteo.com/) | COPM |
| [GoodDollar](https://www.gooddollar.org/) | G\$ |
## Paying Gas in Stablecoins
Users don't need to hold CELO to transact. Celo's [fee abstraction](/build-on-celo/fee-abstraction/overview) lets them pay gas in ERC20 tokens, and every Mento stablecoin plus USDC, USD₮ and USA₮ is on the allowlist — so a wallet holding only KESm can still send a transaction. See [Fee Currencies](/tooling/contracts/fee-currencies) for the current list.
## Next Steps
Contract addresses on Celo Mainnet and the Celo Sepolia Testnet.
Let users pay gas fees in the stablecoin they already hold.
Reach mobile users of a stablecoin wallet built into Opera Mini.
Integrate swaps, lending, and oracles on top of these assets.
# Build with Self
Source: https://docs.celo.org/build-on-celo/build-with-self
Self is a leading digital identity infrastructure for Web2 and Web3. Self leverages zero-knowledge cryptography to disclose verifiable credentials without revealing any sensitive information. No third parties. No data leaks.
Self is the only leader in the space that is production-ready, live across iOS and Google Play Store, and fully audited by third-party zkSecurity that doesn’t rely on additional dependencies such as biometric hardware.
By the conclusion of this guide, you will have a comprehensive understanding of Self and how to integrate it into your Celo applications.
This document will cover:
* What is Self?
* Getting Started
* New Features (2025)
* Technical Resources
* Use Cases
## What is Self?
[Self](https://self.xyz/) is a privacy-first, open-source identity protocol that uses zero-knowledge proofs for secure identity verification.
It enables Sybil resistance and selective disclosure using real-world attestations like passports, EU ID cards, and Indian Aadhaar. With a few lines of code, developers can easily check if their users are humans, while preserving their privacy.
### How It Works
Self Protocol simplifies digital identity verification with zero-knowledge proofs in three steps:
1. **Scan Your Identity Document**: Users scan their passport, EU ID card, or Aadhaar using the NFC reader of their phone.
2. **Generate a Proof**: Generate a zk proof over the identity document, selecting only what you want to disclose.
3. **Share Your Proof**: Share the zk proof with the selected application.
## Use cases
Seamlessly and securely verify your digital identity with Self. It allows you to:
* **Prove Your Humanity:** Confirm you are human without revealing personal information.
* Airdrop Protection
* Social Media & Marketplaces (add trust to user profiles)
* Quadratic Funding
* Sybil-Resistant Polling
* **Prove Identity, Age, Nationality:** Demonstrate where you're from while maintaining privacy. Securely capture the first page data and RFID from your passport to verify your identity.
* Sanction List Checking
* Age Verification
* Wallet Recovery
* **Privacy-preserving Technology:** Protect your users' private information. They will only disclose credentials and information that they allow.
* **Streamline Verification:** Enjoy a smooth and efficient identity verification process.
* **Optimized for Web3 and Universal Apps:** Harness zero-knowledge proofs and one-tap verifications in Web3 apps.
## New Features (2025)
### Expanded Identity Document Support
Self now supports:
* **EU Biometric ID Cards**: Scan NFC-enabled EU IDs covering 27 countries
* **Indian Aadhaar**: Support for Aadhaar verification
* **Passports**: Continued support for passport verification
All verification leverages zero-knowledge proofs (ZKPs) and no data leaves the user's device.
### Points/Rewards System
Self has introduced a points program that incentivizes consistent, secure use:
* Users earn points for setting up Self Pass
* Points earned for continued use across partner platforms
* Points can be redeemed for rewards
* Designed to drive engagement and validate active, verified users
### Major Integrations
* **Google Cloud**: Integrated Self's SDK and ZKP-based proof-of-humanity in its Web3 Portal
* **Aave**: DeFi protocol integration enabling compliance checks, sybil-resistant airdrops, and age/country-gated services
* **Celo Blockchain**: On-chain attestations leverage the Celo blockchain for transparency and auditability
## Technical Resources
* [Self Website](https://self.xyz/)
* [Self Documentation](https://docs.self.xyz/)
* [Self Playground](https://playground.self.xyz/)
* [Self Staging Playground](https://playground.staging.self.xyz/)
* [Self Quickstart Guide](https://docs.self.xyz/docs/self-pass/quickstart)
* [Contract Integration Guide](https://docs.self.xyz/docs/self-pass/contracts/basic-integration)
* [Backend Integration Guide](https://docs.self.xyz/docs/self-pass/backend/basic-integration)
* [QRCode SDK Documentation](https://docs.self.xyz/docs/self-pass/frontend/qrcode-sdk)
* [Deployed Contracts](https://docs.self.xyz/docs/self-pass/contracts/deployed-contracts)
## Support
Join the [Self Builder Group](https://t.me/selfprotocolbuilder) on Telegram for community support and updates.
For Celo-specific integrations, visit the [Celo Discord](https://discord.com/invite/celo) and ask in the #build-with-celo channel.
# L2 Architecture
Source: https://docs.celo.org/build-on-celo/cel2-architecture
Celo’s architecture is a multi-layered system that includes a Layer 2 blockchain, core smart contracts, user applications, and a dynamic network topology, all optimized for scalability, security, and ease of use.
***
## Introduction to the Celo Stack
The Celo stack consists of three main components that work together to deliver a seamless blockchain experience:
### Celo Blockchain
The Celo blockchain operates as a Layer 2 (L2) solution using the OP Stack, with distinct layers for optimal performance and security:
* **Execution Layer**: EVM-compatible, allowing easy deployment of Ethereum smart contracts.
* **Data Availability Layer**: Utilizes EigenDA to ensure transaction data is accessible and cost-efficient.
* **Settlement Layer**: Leverages Ethereum to finalize transactions, benefiting from its security.
### Celo Core Contracts
Celo Core Contracts are essential smart contracts on the Celo blockchain, managed through decentralized governance. Key contracts include:
* **Attestations**: Links users' phone numbers to their blockchain addresses for secure identity verification and Social Connect features.
* **Governance**: Allows community voting on protocol upgrades and changes.
* **StableToken** (e.g., USDm, EURm): Manages native stablecoin issuance and stability for seamless transactions.
* **Exchange**: Facilitates asset trading and liquidity within the Celo ecosystem.
* **SortedOracles**: Provides external data, like price feeds, critical for stability and DeFi applications.
* **Validators**: Manages validator operations and network security.
### Applications
The Application Layer connects users directly to the blockchain. Developers can build user-friendly applications that are secure, transparent, and decentralized by utilizing Celo’s blockchain.
## Our Network Topology
The Celo network topology consists of various nodes running the Celo blockchain software in different configurations to support the decentralized infrastructure of the network.
### Sequencer
The sequencer replaces the traditional validator role in the L2 architecture. It is responsible for:
* Gathering transactions from other nodes
* Executing associated smart contracts to form new blocks
* Submitting these blocks to the Ethereum L1 for final settlement
The sequencer operates on a 1-second block time, improving transaction speed and throughput.
### Full Nodes
Full nodes in the Celo L2 network serve multiple important functions:
* Maintaining a copy of the L2 blockchain state
* Interacting with Ethereum L1 to read and verify L2 block data
* Optionally running an Ethereum node or using a third-party Ethereum node service
Full nodes can join or leave the network at any time, providing a decentralized infrastructure for the network.
### Data Availability Layer
Celo L2 incorporates EigenDA as its Data Availability (DA) layer:
* Ensures transaction data remains accessible and cost-efficient
* Operates separately from the execution and settlement layers
* Contributes to lower transaction costs and improved scalability
# Adding Fee Currencies
Source: https://docs.celo.org/build-on-celo/fee-abstraction/add-fee-currency
Any ERC20 token can become a fee currency on Celo. Two steps are required:
1. **Implement the `IFeeCurrency` interface** — the token must extend ERC20 with the functions the Celo blockchain uses to debit and credit gas fees. This step is the responsibility of the token issuer.
2. **Register the token through governance** — the token must be added to the on-chain allowlist via a governance proposal. The Celo team can support you through this step.
This guide walks through both steps.
For background on how fee abstraction works, see the [Overview](/build-on-celo/fee-abstraction/overview).
***
## Step 1: Implement the IFeeCurrency Interface
This step must be completed by the token issuer — every project implements and maintains its own fee currency token.
### The IFeeCurrency Interface
Fee currencies must implement the [IFeeCurrency](https://github.com/celo-org/fee-currency-example/blob/92e2fcb/src/IFeeCurrency.sol) interface, which extends ERC20 with two additional functions used by the Celo blockchain to debit and credit gas fees.
When a [CIP-64](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0064.md) transaction is executed:
1. **Before execution** — the blockchain calls `debitGasFees` to reserve the maximum gas the transaction can spend
2. **After execution** — the blockchain calls `creditGasFees` to refund unused gas and distribute fees to the appropriate recipients
#### debitGasFees
```solidity theme={null}
function debitGasFees(address from, uint256 value) external;
```
Called before transaction execution to reserve the maximum gas amount.
* Must deduct `value` from `from`'s balance
* Must revert if `msg.sender` is not `address(0)` (only the VM may call this)
#### creditGasFees
There are two versions of `creditGasFees`. Both should be implemented for compatibility.
**New signature** (used once all fee currencies have migrated):
```solidity theme={null}
function creditGasFees(address[] calldata recipients, uint256[] calldata amounts) external;
```
* Must credit each `recipient` the corresponding `amount`
* Must revert if `msg.sender` is not `address(0)`
* Must revert if `recipients` and `amounts` have different lengths
**Legacy signature** (for backwards compatibility):
```solidity theme={null}
function creditGasFees(
address refundRecipient,
address tipRecipient,
address _gatewayFeeRecipient,
address baseFeeRecipient,
uint256 refundAmount,
uint256 tipAmount,
uint256 _gatewayFeeAmount,
uint256 baseFeeAmount
) external;
```
* `_gatewayFeeRecipient` and `_gatewayFeeAmount` are deprecated and will always be zero
* Must revert if `msg.sender` is not `address(0)`
***
### Example Implementation
The following example from [celo-org/fee-currency-example](https://github.com/celo-org/fee-currency-example) shows a minimal fee currency token using OpenZeppelin's ERC20 with burn/mint mechanics for gas fee handling:
```solidity theme={null}
pragma solidity ^0.8.13;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {IFeeCurrency} from "./IFeeCurrency.sol";
contract FeeCurrency is ERC20, IFeeCurrency {
constructor(uint256 initialSupply) ERC20("ExampleFeeCurrency", "EFC") {
_mint(msg.sender, initialSupply);
}
modifier onlyVm() {
require(msg.sender == address(0), "Only VM can call");
_;
}
function debitGasFees(address from, uint256 value) external onlyVm {
_burn(from, value);
}
// New function signature
function creditGasFees(
address[] calldata recipients,
uint256[] calldata amounts
) public onlyVm {
require(
recipients.length == amounts.length,
"Recipients and amounts must be the same length."
);
for (uint256 i = 0; i < recipients.length; i++) {
_mint(recipients[i], amounts[i]);
}
}
// Legacy function signature for backwards compatibility
function creditGasFees(
address from,
address feeRecipient,
address, // gatewayFeeRecipient, unused
address communityFund,
uint256 refund,
uint256 tipTxFee,
uint256, // gatewayFee, unused
uint256 baseTxFee
) public onlyVm {
_mint(from, refund);
_mint(feeRecipient, tipTxFee);
_mint(communityFund, baseTxFee);
}
}
```
This implementation uses `_burn` in `debitGasFees` and `_mint` in `creditGasFees` to handle the gas fee lifecycle. The `onlyVm` modifier ensures only the blockchain itself (via `address(0)`) can call these functions.
***
### Testing
Use [Foundry](https://book.getfoundry.sh/) to test your fee currency implementation. The [fee-currency-example](https://github.com/celo-org/fee-currency-example) repository includes a test suite you can use as a starting point:
```bash theme={null}
git clone https://github.com/celo-org/fee-currency-example.git
cd fee-currency-example
forge build
forge test
```
Key things to test:
* `debitGasFees` correctly reduces the sender's balance
* `debitGasFees` reverts when called by any address other than `address(0)`
* Both `creditGasFees` signatures correctly credit all recipients
* `creditGasFees` reverts when called by any address other than `address(0)`
* The total debited amount equals the total credited amount across a transaction lifecycle
***
## Step 2: Register Through Governance
Once your token implements `IFeeCurrency`, it must be added to the on-chain allowlist in [**FeeCurrencyDirectory.sol**](/tooling/contracts/core-contracts) through a governance proposal. The governance process ensures that fee currencies meet the necessary requirements for network stability.
Unlike step 1, you don't have to navigate this step alone — the Celo team can support you through the governance process. Reach out on the [Celo Discord server](https://discord.com/invite/celo) to get started.
If your token uses decimals other than 18, you will also need to deploy an adapter contract. See [Adapters for Non-18-Decimal Tokens](/build-on-celo/fee-abstraction/overview#adapters-for-non-18-decimal-tokens) for details.
# Fee Abstraction
Source: https://docs.celo.org/build-on-celo/fee-abstraction/overview
Fee abstraction is one of Celo's core protocol features. It allows users to pay gas fees in ERC20 tokens — like USDC, USDT, or Mento stablecoins — instead of needing to hold the native CELO token.
## Why Fee Abstraction Matters
On most EVM chains, users must hold the native token to pay for gas. This creates friction: a user who receives USDC on Celo can't send it anywhere without first acquiring CELO. Fee abstraction removes this barrier entirely.
With fee abstraction, a user holding only USDC can send transactions, interact with contracts, and pay gas — all in USDC. No bridging, no swaps, no extra steps. This is especially valuable for:
* **Onboarding new users** who receive stablecoins but don't know about gas tokens
* **Payment applications** where users transact in a single currency end-to-end
* **AI agents** that operate autonomously with a single token balance
## How It Works
Fee abstraction is built into the Celo protocol at the node level — it is not a paymaster or relayer. When a transaction includes a `feeCurrency` field, the Celo blockchain:
1. Calls `debitGasFees` on the fee currency contract to reserve the maximum gas cost
2. Executes the transaction normally
3. Calls `creditGasFees` to refund unused gas and distribute fees to block producers
This means fee abstraction works with any externally owned account (EOA). No smart contract wallets, no relayers, no extra infrastructure needed.
To use an alternate fee currency, set its token or adapter address as the `feeCurrency` property on the transaction object.
For implementation details, see [Using Fee Abstraction](/build-on-celo/fee-abstraction/using-fee-abstraction). To add a new fee currency to the protocol, see [Adding Fee Currencies](/build-on-celo/fee-abstraction/add-fee-currency).
## Whitelisted Fee Currencies (Mainnet)
The full up-to-date list of whitelisted fee currencies — including token and adapter addresses — is automatically maintained at [Fee Currencies](/tooling/contracts/fee-currencies).
Tokens with non-18 decimals (e.g. USDC, USD₮, USA₮ with 6 decimals) require an adapter contract. Use the adapter address — not the token address — in the `feeCurrency` field. See the adapter table in [Using Fee Abstraction](/build-on-celo/fee-abstraction/using-fee-abstraction#adapters-for-non-18-decimal-tokens).
***
## Related
* [Fee Abstraction for AI Agents](/build-on-celo/build-with-ai/overview#fee-abstraction-for-agents) — Using fee abstraction in autonomous agent backends
* [x402: Agent Payments](/build-on-celo/build-with-ai/x402) — HTTP-native stablecoin payments for agents
* [Using Fee Abstraction](/build-on-celo/fee-abstraction/using-fee-abstraction) — How to pay gas with alternate fee currencies in your transactions
* [Adding Fee Currencies](/build-on-celo/fee-abstraction/add-fee-currency) — How to implement and register a new fee currency
# Using Fee Abstraction in Transactions
Source: https://docs.celo.org/build-on-celo/fee-abstraction/using-fee-abstraction
This guide shows how to send transactions that pay gas fees in ERC20 tokens instead of CELO. For background on how fee abstraction works, see the [Overview](/build-on-celo/fee-abstraction/overview).
***
## Allowlisted Fee Currencies
The protocol maintains a governable allowlist of smart contract addresses that can be used as fee currencies. These contracts implement an extension of the ERC20 interface with additional functions for debiting and crediting transaction fees (see [Adding Fee Currencies](/build-on-celo/fee-abstraction/add-fee-currency)).
To fetch the current allowlist, call `getCurrencies()` on the `FeeCurrencyDirectory` contract, or use `celocli`:
```bash theme={null}
# Celo Sepolia testnet
celocli network:whitelist --node celo-sepolia
# Celo mainnet
celocli network:whitelist --node celo
```
***
## Adapters for Non-18-Decimal Tokens
Allowlisted addresses may be **adapters** rather than full ERC20 tokens. Adapters are used when a token has decimals other than 18 (e.g., USDC and USDT use 6 decimals). The Celo blockchain calculates gas pricing in 18 decimals, so adapters normalize the value.
* **For transfers**: use the token address as usual.
* **For `feeCurrency`**: use the adapter address.
* **For `balanceOf`**: querying via the adapter returns the balance as if the token had 18 decimals — useful for checking whether an account can cover gas without converting units.
To get the underlying token address for an adapter, call `adaptedToken()` on the adapter contract. Newer adapters — including the USD₮ and USA₮ ones — expose this as `getAdaptedToken()` instead, so try both if the first call reverts.
For more on gas pricing, see [Gas Pricing](/legacy/protocol/transaction/gas-pricing).
### Adapter Addresses
#### Mainnet
| Name | Token Address | Adapter Address |
| ------ | --------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `USDC` | [`0xcebA9300f2b948710d2653dD7B07f33A8B32118C`](https://celoscan.io/address/0xcebA9300f2b948710d2653dD7B07f33A8B32118C#code) | [`0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B`](https://celoscan.io/address/0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B#code) |
| `USD₮` | [`0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e`](https://celoscan.io/address/0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e#code) | [`0x0e2a3e05bc9a16f5292a6170456a710cb89c6f72`](https://celoscan.io/address/0x0e2a3e05bc9a16f5292a6170456a710cb89c6f72#code) |
| `USA₮` | [`0xD2ab3C9A02DBBAB236BfEC45D1d755DF4267F771`](https://celoscan.io/address/0xD2ab3C9A02DBBAB236BfEC45D1d755DF4267F771#code) | [`0x0357EE22278c922e1D36cFe6b899269b161880C4`](https://celoscan.io/address/0x0357EE22278c922e1D36cFe6b899269b161880C4#code) |
#### Celo Sepolia (Testnet)
| Name | Token Address | Adapter Address |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `USDC` | [`0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B`](https://sepolia.celoscan.io/address/0x2f25deb3848c207fc8e0c34035b3ba7fc157602b#code) | [`0x4822e58de6f5e485eF90df51C41CE01721331dC0`](https://sepolia.celoscan.io/address/0x4822e58de6f5e485eF90df51C41CE01721331dC0#code) |
***
## Using Fee Abstraction with Celo CLI
Transfer 1 USDC using USDC as the fee currency via [`celocli`](/cli):
```bash theme={null}
celocli transfer:erc20 \
--erc20Address 0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B \
--from 0x22ae7Cf4cD59773f058B685a7e6B7E0984C54966 \
--to 0xDF7d8B197EB130cF68809730b0D41999A830c4d7 \
--value 1000000 \
--gasCurrency 0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B \
--privateKey [PRIVATE_KEY]
```
When using USDC, USD₮, or USA₮, use the **adapter address** (not the token address) as `--gasCurrency`. All three tokens use 6 decimals — pass `--value` in units of `10^6` (e.g. `1000000` = 1 USD₮/USDC/USA₮).
Transfer 1 USD₮ using USD₮ as the fee currency:
```bash theme={null}
celocli transfer:erc20 \
--erc20Address 0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e \
--from 0x22ae7Cf4cD59773f058B685a7e6B7E0984C54966 \
--to 0xDF7d8B197EB130cF68809730b0D41999A830c4d7 \
--value 1000000 \
--gasCurrency 0x0e2a3e05bc9a16f5292a6170456a710cb89c6f72 \
--privateKey [PRIVATE_KEY]
```
***
## Using Fee Abstraction with viem
We recommend [viem](https://viem.sh/), which has native support for the `feeCurrency` field. Ethers.js and web3.js do not currently support this field.
### 1. Estimate the Gas Fee
Before sending, estimate the transaction fee so the UI can reserve that amount and prevent users from trying to transfer more than their available balance.
The gas price returned from the RPC is always expressed in 18 decimals, regardless of the fee currency.
Use the adapter address (for USDC/USD₮/USA₮) or token address (for USDm, EURm, BRLm) as the `feeCurrency` value when estimating.
```js theme={null}
import { createPublicClient, hexToBigInt, http } from "viem";
import { celo } from "viem/chains";
const USDC_ADAPTER_MAINNET = "0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B";
const publicClient = createPublicClient({
chain: celo,
transport: http(),
});
const transaction = {
from: "0xccc9576F841de93Cd32bEe7B98fE8B9BD3070e3D",
to: "0xcebA9300f2b948710d2653dD7B07f33A8B32118C",
data: "0xa9059cbb000000000000000000000000ccc9576f841de93cd32bee7b98fe8b9bd3070e3d00000000000000000000000000000000000000000000000000000000000f4240",
feeCurrency: USDC_ADAPTER_MAINNET,
};
async function getGasPriceInUSDC() {
const priceHex = await publicClient.request({
method: "eth_gasPrice",
params: [USDC_ADAPTER_MAINNET],
});
return hexToBigInt(priceHex);
}
async function estimateGasInUSDC(transaction) {
const estimatedGasInHex = await publicClient.estimateGas({
...transaction,
feeCurrency: USDC_ADAPTER_MAINNET,
});
return hexToBigInt(estimatedGasInHex);
}
async function main() {
const gasPriceInUSDC = await getGasPriceInUSDC();
const estimatedGas = await estimateGasInUSDC(transaction);
// Total fee the user must reserve before transferring
const transactionFeeInUSDC = formatEther(gasPriceInUSDC * estimatedGas).toString();
return transactionFeeInUSDC;
}
```
### 2. Prepare the Transaction
Set `feeCurrency` to the adapter address (USDC/USD₮/USA₮) or token address (USDm, EURm, BRLm). Use transaction type `123` (`0x7b`), which is [CIP-64](/legacy/protocol/transaction/transaction-types) compliant.
```js theme={null}
let tx = {
// ... other transaction fields
feeCurrency: "0x2f25deb3848c207fc8e0c34035b3ba7fc157602b", // USDC Adapter address
type: "0x7b",
};
```
### 3. Send the Transaction
The example below transfers 1 USDC, subtracting the estimated fee from the transfer amount so the sender's full balance is not over-spent.
```js theme={null}
import { createWalletClient, http } from "viem";
import { celo } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
import { stableTokenAbi } from "@celo/abis";
const account = privateKeyToAccount("0x432c...");
const client = createWalletClient({
account,
chain: celo,
transport: http(),
});
const USDC_ADAPTER_MAINNET = "0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B";
const USDC_MAINNET = "0xcebA9300f2b948710d2653dD7B07f33A8B32118C";
async function calculateTransactionFeesInUSDC(transaction) {
const gasPriceInUSDC = await getGasPriceInUSDC();
const estimatedGas = await estimateGasInUSDC(transaction);
return gasPriceInUSDC * estimatedGas;
}
async function send(amountInWei) {
const to = USDC_MAINNET;
const data = encodeFunctionData({
abi: stableTokenAbi,
functionName: "transfer",
args: ["0xccc9576F841de93Cd32bEe7B98fE8B9BD3070e3D", amountInWei],
});
const transactionFee = await calculateTransactionFeesInUSDC({ to, data });
// Subtract the fee from the amount so the sender isn't over-spending
const tokenReceivedByReceiver = parseEther("1") - transactionFee;
const dataAfterFeeCalculation = encodeFunctionData({
abi: stableTokenAbi,
functionName: "transfer",
args: ["0xccc9576F841de93Cd32bEe7B98fE8B9BD3070e3D", tokenReceivedByReceiver],
});
const hash = await client.sendTransaction({
...{ to, data: dataAfterFeeCalculation },
feeCurrency: USDC_ADAPTER_MAINNET,
});
return hash;
}
```
***
If you have any questions, please [reach out](https://github.com/celo-org/developer-tooling/discussions/categories/q-a).
# Fund your Project
Source: https://docs.celo.org/build-on-celo/fund-your-project
Discover funding opportunities in the Celo ecosystem.
***
The Celo ecosystem offers a variety of funding mechanisms, with a strong focus on retroactive funding, rewarding impactful contributions after they’ve been made. Grants and sustainable revenue models are also available to support projects at different stages.
Explore these opportunities to maximize your funding potential.
Learn more about the programs below.
## From Idea to MVP to your first users
Here’s how you can get started:
1. **Apply for monthly rewards with [Proof of Ship](https://celo-devs.beehiiv.com/subscribe)** Demonstrate consistent progress for automated retroactive rewards. Add [attribution tags](/build-on-celo/attribution-tags) to your transactions so your on-chain activity is credited to your project.
## Apply for Grant Opportunities
There are various grant opportunities for builders in the Celo ecosystem, with funding available at different stages of your project. To maximize your chances of receiving rewards, include your Karma GAP project profile when applying.
1. **[Prezenti Grants](https://www.prezenti.xyz/)**
## Funds
1. **[Verda Ventures](https://verda.ventures/)**: Building for MiniPay & raising funding? Reach out to [team@verda.ventures](mailto:team@verda.ventures) with a deck and product demo.
If you want to add another ecosystem-led funding program, [edit this page](https://github.com/celo-org/docs/edit/main/build-on-celo/fund-your-project.mdx) to include it.
## Get Funding Updates
Stay up to date with the latest funding opportunities by [joining our newsletter](https://embeds.beehiiv.com/eeadfef4-2f0c-45ce-801c-b920827d5cd2).
# Building dApps on Celo
Source: https://docs.celo.org/build-on-celo/index
Celo was created to enable real-world uses cases on Ethereum.
Whether you're building your first dApp or looking to integrate an existing protocol onto Celo, we have all the resources and tools you need to get started.
***
## Why Build on Celo?
* **EVM Compatibile:** Celo is fully EVM-compatible, offering the same development experience as Ethereum with improved scalability and lower costs.
* **Fast Transactions:** After the migrations to an L2 Celo now has a **1-second block finality** compared to formerly 5 seconds.
* **Easy, Low-Cost Payments:** Celo's seamless payment infrastructure, including [Fee Abstraction](/build-on-celo/fee-abstraction/overview), **sub-cent fees**, and **native stablecoins**, enables simple and affordable transactions.
* **Global Reach:** Celo provides access to more than **8 million real-world users** with some dApps having more than **200,000 DAUs**.
## Getting Started
Get started fast with Celopedia
Deploy a smart contract on Celo
Receive testnet funds
Explore developer tooling
## Celo L2 Mainnet
Celo has transitioned from a standalone EVM-compatible Layer 1 blockchain to an Ethereum Layer 2.
This shift, [proposed by cLabs in July 2023](https://forum.celo.org/t/clabs-proposal-for-celo-to-transition-to-an-ethereum-l2/6109), aims to maintain the seamless user experience that Celo is known for—characterized by speed, low costs, and ease of use—while leveraging Ethereum’s security and ecosystem.
## What does this mean for our ecosystem?
Celo's evolution from an L1 EVM-compatible chain to an L2 solution marks a significant milestone in our ongoing relationship with the Ethereum ecosystem. As an L1 chain, Celo has always maintained close ties with Ethereum, sharing its commitment to decentralization, security, and innovation. By transitioning to an L2, Celo strengthens this bond, allowing our developers and protocols to immerse themselves even deeper into the vibrant, collaborative Ethereum community. This integration enhances opportunities for open-source contributions, joint initiatives, and the development of public goods, ensuring that Celo's impact resonates widely across the blockchain space.
## Important Dates
### Early July, 2024: Dango L2 Testnet Launch
The Dango Testnet announced on the 7th of July 2024, Celo’s first L2 public test network, went live. Dango allowed developers and infrastructure providers to familiarize themselves with the L2 environment. It was shut down on the 9th of October 2024.
### 26th September, 2024: Alfajores L2 Testnet Launch
The Celo L2 testnet, Alfajores, went live! This provides a testing environment for node operators and developers to ensure compatibility before the Mainnet launch.
### October 2024: Code Freeze and Audits
The core dev team froze all feature development by mid-October and underwent a thorough external audit. The result is available at [https://celo.org/audits](https://celo.org/audits).
### 20th February, 2025: Baklava L2 Testnet Launch
Using the final audited release, the Celo validator community performed a dry run of the L2 upgrade on the Baklava network.
### 26th March, 2025: Celo L2 Mainnet Launch
Following a successful Baklava upgrade, the Celo L2 Mainnet officially went live.
## Useful Links
* [Layer 2 Specification](/specs)
* [Node Operator Guide](/infra-partners/operators/overview)
* [What's Changed?](/legacy/overview)
* [Cel2 Code](https://github.com/celo-org/optimism)
* [FAQ](/legacy/faq)
# Launch Checklist
Source: https://docs.celo.org/build-on-celo/launch-checklist
A comprehensive guide to assist you in launching dapps on Celo.
## Pre-Launch
### Security & Audits
* [ ] **Security Audit**: Complete a professional security audit for your smart contracts
* [ ] **Audit Publication**: Publish audit results and auditor details on your website
* [ ] **Code Review**: Conduct internal code review and testing
* [ ] **Best Practices**: Use audited libraries (e.g., OpenZeppelin) instead of writing everything from scratch
* [ ] **Test Coverage**: Ensure comprehensive test coverage for all critical functions
### Smart Contract Preparation
* [ ] **Contract Verification**: Verify contracts on [CeloScan](https://celoscan.io/verifyContract) and [Celo Explorer](https://celo.blockscout.com/contract-verification)
* [ ] **Documentation**: Add clear tutorials and documentation on how to use your contracts/tokens
* [ ] **Upgradeability**: Document upgrade paths if using upgradeable contracts
* [ ] **Gas Optimization**: Optimize gas usage for better user experience
### Integration & Testing
* [ ] **Wallet Integration**: Integrate wallet connection (WalletConnect, RainbowKit, etc.)
* [ ] **Multi-Wallet Support**: Test with multiple wallets (Valora, MetaMask, etc.)
* [ ] **Network Configuration**: Ensure proper Celo mainnet and testnet configuration
* [ ] **Error Handling**: Implement comprehensive error handling and user feedback
* [ ] **Mobile Testing**: Test on mobile devices, especially for MiniPay integration
### Analytics & Monitoring
* [ ] **Attribution Tags**: Add [attribution tags](/build-on-celo/attribution-tags) to your transactions so on-chain activity is credited to your app (used by Proof of Ship and MiniPay tracking)
* [ ] **Analytics Setup**: Configure analytics tracking (e.g., Google Analytics, Mixpanel)
* [ ] **Monitoring Tools**: Set up monitoring and alerting (e.g., Sentry, DataDog)
* [ ] **On-Chain Analytics**: Integrate on-chain analytics tools (e.g., Dune, The Graph)
* [ ] **Performance Monitoring**: Monitor application performance and transaction success rates
* [ ] **User Behavior Tracking**: Track key user actions and conversion funnels
### Documentation & User Resources
* [ ] **Getting Started Guide**: Create a clear guide for new users
* [ ] **On/Off-Ramp Instructions**: Provide instructions for buying/selling crypto
* [ ] **FAQ Section**: Address common questions and concerns
* [ ] **Video Tutorials**: Create video walkthroughs if applicable
* [ ] **Developer Documentation**: Document APIs and integration guides
## Launch
### Platform Reporting
Make your dapp discoverable by reporting it on these platforms:
* [ ] [Dapp Radar](https://dappradar.com) - General dApp directory
* [ ] [DeFi Llama](https://docs.llama.fi/list-your-project/submit-a-project) - For DeFi & NFT projects
* [ ] [Electric Capital](https://github.com/electric-capital/crypto-ecosystems) - Ecosystem reporting
* [ ] [Dune Analytics](https://dune.com/contracts/new) - Add your contracts for analytics
### Marketing
* [ ] **Marketing Intake**: Complete the [Marketing Intake Form](https://docs.google.com/forms/d/e/1FAIpQLSe0LMpEy2nicTcdoI5_LFhg3VZbpyhTymmSTzZ7HavdRiE4AQ/viewform)
* [ ] **Community Engagement**: Join the Celo Founders Telegram group
* [ ] **Social Media**: Tag [@Celo](https://x.com/Celo) in launch announcements
* [ ] **Press Release**: Prepare and distribute launch announcement
* [ ] **Content Marketing**: Create blog posts, tutorials, or case studies
### Legal & Compliance
* [ ] **Terms & Conditions**: Ensure public-facing Terms & Conditions are published
* [ ] **Privacy Policy**: Publish GDPR-compliant privacy policy or meet other privacy requirements
* [ ] **Regulatory Compliance**: Verify compliance with relevant regulations in your jurisdiction
* [ ] **Disclaimers**: Add appropriate disclaimers for financial/DeFi applications
## Post-Launch
### Monitoring & Maintenance
* [ ] **Monitor Metrics**: Track key metrics (users, transactions, TVL, etc.)
* [ ] **Error Tracking**: Monitor and address errors promptly
* [ ] **User Feedback**: Collect and respond to user feedback
* [ ] **Performance Optimization**: Continuously optimize based on usage patterns
### Growth & Iteration
* [ ] **Feature Updates**: Plan and execute feature updates based on user needs
* [ ] **Community Building**: Engage with users and build a community
* [ ] **Partnerships**: Explore partnerships with other Celo projects
* [ ] **Grant Applications**: Consider applying for ecosystem grants and funding
### Documentation Updates
* [ ] **Keep Docs Updated**: Update documentation as features evolve
* [ ] **Changelog**: Maintain a changelog for transparency
* [ ] **Migration Guides**: Provide guides for breaking changes if applicable
# Network Information
Source: https://docs.celo.org/build-on-celo/network-overview
Overview of Celo Mainnet and the Celo Sepolia Testnet.
***
## Celo Mainnet
| Name | Value |
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Network Name | Celo Mainnet |
| Description | The production Celo network |
| Chain ID | 42220 |
| Currency Symbol | CELO |
| RPC Nodes | [List of RPC providers](/tooling/nodes/overview#as-a-service) |
| RPC Endpoint (best effort) | [https://forno.celo.org](https://forno.celo.org) Note: [Forno](/tooling/nodes/forno#celo-mainnet) is rate limited, as your usage increases consider options that can provide the desired level of support (SLA). |
| Block Explorers |
|
The Celo Sepolia Testnet is Celo's new developer testnet built on Ethereum Sepolia, designed to replace Alfajores following the planned Holesky deprecation in September 2025.
**Key Features:**
* **Fresh State**: Starts with a clean slate, no state inheritance from Alfajores
* **L1 Foundation**: Built on Ethereum Sepolia for enhanced stability
* **Developer-Focused**: Provides the same developer experience as Alfajores
**New Celo Sepolia Testnet Now Live!**
Try Celo's new developer testnet on Ethereum Sepolia.
[Learn more →](/infra-partners/notices/archive/celo-sepolia-launch)
The Celo Sepolia Testnet is designed for testing and experimentation by developers. Its tokens hold no real world economic value. The testnet software will be upgraded on a regular basis. This will erase your accounts, their balance and your transaction history. You may encounter bugs and limitations with the software and documentation.
# Nightfall Privacy Layer
Source: https://docs.celo.org/build-on-celo/nightfall
## Overview
**Nightfall** is an open-source, zero-knowledge proof (ZKP) privacy layer developed by EY Blockchain that enables private transactions on Celo. As a Layer 3 solution on top of Celo, Nightfall brings enterprise-grade privacy to payments, supply chain finance, and B2B transactions while maintaining Celo's speed and low-cost advantages.
Celo is the **first payments-focused blockchain** to deploy Nightfall, combining private transactions with Celo's mobile-first infrastructure and 1-second block times.
Visit the [Nightfall website](https://nightfall.celo.org/) to learn more about
Nightfall on Celo, explore use cases, and see what enterprises are saying.
**Testnet Status**: Live and ready for testing
**Nightfall** testnet is currently active on Celo Sepolia for developers and enterprises to build and test private payment applications.
**Full API documentation** is available in the [Nightfall GitHub docs](https://github.com/EYBlockchain/nightfall_4_CE/blob/master/doc/nf_4.md#apis).
## What is Nightfall?
Nightfall uses **zero-knowledge rollup (ZK-ZK rollup)** technology to batch private transactions into succinct blocks that are verified on-chain through cryptographic proofs. This means:
* **Transaction details are hidden**: Sender, receiver, and amounts remain private
* **Fast finality**: Achieves finality at the same speed as the underlying Celo blockchain
* **Low cost**: Private transfers typically cost around 6000 Gas (\~90% cheaper than standard transfers)
* **Auditable privacy**: Transactions are cryptographically verifiable for compliance
## Key Features
### Privacy Technology
* **Zero-Knowledge Proofs**: Cryptographic privacy without trusted intermediaries
* **Layer 3 Architecture**: Runs on top of Celo L2 for maximum efficiency
* **Enterprise Access Control**: X509 certificate-based authentication
### Token Support
* **ERC-20**: Stablecoins (USDT, USDC) and other fungible tokens
* **ERC-721**: Non-fungible tokens (NFTs)
* **ERC-1155**: Multi-token standard
* **ERC-3525**: Semi-fungible tokens
### Performance
* **Low Gas Costs**: \~6000 Gas per private transfer
* **Fast Finality**: Cryptographic finality matching Celo's block time
* **Scalability**: Transaction batching for efficient throughput
## Architecture
Nightfall operates with three main components:
### Client
The user-facing application that enables users to make private transactions. Clients interact with proposers and manage:
* Deposits (converting public tokens to private commitments)
* Transfers (private peer-to-peer transactions)
* Withdrawals (converting private commitments back to public tokens)
### Proposer
Network nodes that create Layer 2 blocks by batching transactions and generating zero-knowledge proofs. Proposers:
* Collect transactions from clients
* Generate ZK proofs for transaction validity
* Submit blocks to on-chain smart contracts
### Smart Contracts
On-chain contracts that handle:
* Token escrow for deposits and withdrawals
* ZK proof verification
* X509 certificate validation for access control
## Use Cases
### Private B2B Payments
Enable confidential business-to-business transactions while maintaining an auditable record for compliance. Ideal for:
* Invoice settlements
* Vendor payments
* Intercompany transfers
### Supply Chain Finance
Process payments across supply chain partners with privacy, reducing transaction costs and eliminating intermediaries.
### Enterprise Treasury Management
Manage corporate funds with confidentiality for strategic transactions, mergers, acquisitions, and sensitive operations.
### Cross-Border Payments
Leverage Celo's global reach and low fees with added privacy for international B2B flows, particularly valuable in emerging markets.
## Getting Started
### Prerequisites
To integrate Nightfall, you'll need:
1. **Development Tools**:
* **git**: For cloning the repository
* **docker-compose**: For running the client services
* **curl**: For making API requests to the client
* **cast** (from Foundry): For generating mnemonics (optional)
2. **Ethereum Keys**: For signing transactions on Celo Sepolia
3. **ZKP Keys**: For generating zero-knowledge proofs (derived from mnemonic)
4. **Testnet Tokens**: CELO tokens on Celo Sepolia for paying gas fees and deposits
### Transaction Flow
#### Deposits
Convert public tokens on Celo into private commitments on Nightfall:
```
Public Celo Token → Nightfall Smart Contract (escrow) → Private Commitment
```
#### Transfers
Send private transactions between Nightfall users:
```
Private Commitment (sender) → ZK Proof → Private Commitment (receiver)
```
#### Withdrawals
Convert private commitments back to public tokens:
```
Private Commitment → ZK Proof → Nightfall Smart Contract → Public Celo Token
```
### Running the Client on Celo Sepolia
This guide explains how to set up and use the Nightfall client to interact with the Celo Sepolia testnet.
#### Setup
**1. Clone the Repository**
```bash theme={null}
git clone https://github.com/celo-org/nightfall_4_CE
cd nightfall_4_CE
git checkout celo
```
**2. Configure Environment Variables**
Before running the client, update the `celo-sepolia.env` file with your own addresses and private keys. These addresses must have CELO tokens for paying gas fees during deposits and withdrawals, as well as the tokens you want to deposit.
Update the following variables in `celo-sepolia.env`:
* `CLIENT_SIGNING_KEY`: Your private key (without the `0x` prefix or with it, depending on your setup)
* `CLIENT_ADDRESS`: The Ethereum address corresponding to your private key
* `NF4_SIGNING_KEY`: Should be the same as `CLIENT_SIGNING_KEY`
**Funding Your Address**
`CLIENT_ADDRESS` must be funded on Celo Sepolia with:
* **CELO for gas** on deposit and de-escrow transactions. Get it from the [Celo Sepolia faucet](https://faucet.celo.org/celo-sepolia).
* **A balance of whichever token you intend to deposit.** For example, to move USDT into Nightfall, `CLIENT_ADDRESS` must hold USDT on Celo Sepolia.
The client calls `approve()` and `transferFrom()` on your behalf when you submit a deposit — no manual approval step is needed.
**3. Run Docker Compose as Client**
Start the client connected to the Celo Sepolia testnet. This will build the necessary Docker images and start the webhook service:
```bash theme={null}
NF4_RUN_MODE=celo_sepolia docker-compose --env-file celo-sepolia.env --profile indie-client up --build
```
The client will be available at `http://localhost:3000` and the webhook at `http://localhost:8081/webhook` once they're healthy. The webhook automatically receives notifications from the client about transaction status updates.
**4. Configure Your Mnemonic**
Before performing any operations, you need to derive your ZKP keys from a mnemonic. Generate a new 24-word mnemonic using `cast` (from Foundry):
```bash theme={null}
cast w new-mnemonic -w 24
```
Keep your mnemonic safe. Then derive your keys using the client API:
```bash theme={null}
curl -X POST http://localhost:3000/v1/deriveKey \
-H "Content-Type: application/json" \
-d '{
"mnemonic": "your mnemonic phrase here",
"child_path": "m/44'\''/60'\''/0'\''/0/0"
}'
```
This will return your `root_key`, `nullifier_key`, `zkp_private_key`, and `zkp_public_key`. Save these values for future operations — in particular, the recipient's `zkp_public_key` is what a sender needs to route a private transfer.
**Run one `nightfall_client` instance per user identity**
A `nightfall_client` process tracks exactly one ZKP key pair at a time. The client only decrypts L2 blocks with whichever keys are currently loaded, so swapping mnemonics via `/v1/deriveKey` on a running client **will not reveal funds addressed to the new keys** — past blocks are never re-decrypted.
For a sender → recipient flow, run **two independent stacks** (two `nightfall_client` + MongoDB pairs, e.g. on different host ports). Each stack derives its own mnemonic once and keeps it for its lifetime.
**Do not drop the client's MongoDB while you hold unspent commitments.** The commitment salts and preimages live only there; they cannot be reconstructed from L1, and the underlying L1 escrow for those funds will be permanently stranded.
#### Amount Encoding
Every `value`, `fee`, and `deposit_fee` in Nightfall's API is a **64-character hex string of the raw token amount, without `0x` prefix**. The number of decimals depends on the token:
| Token (Celo Sepolia) | Address | Decimals | 1 whole unit |
| ------------------------- | -------------------------------------------- | -------- | ------------------------------------------------------------------ |
| CELO | `0x471EcE3750Da237f93B8E339c536989b8978a438` | 18 | `0000000000000000000000000000000000000000000000000de0b6b3a7640000` |
| USD₮ (Tether USD testnet) | `0xd077A400968890Eacc75cdc901F0356c943e4fDb` | 6 | `00000000000000000000000000000000000000000000000000000000000f4240` |
Common amounts:
* `0.1 CELO` → `000000000000000000000000000000000000000000000000016345785d8a0000`
* `1 CELO` → `0000000000000000000000000000000000000000000000000de0b6b3a7640000`
* `1 USDT` → `00000000000000000000000000000000000000000000000000000000000f4240`
* `10 USDT` → `0000000000000000000000000000000000000000000000000000000000989680`
#### Diagnostic Endpoints
Useful read-only endpoints for checking state and debugging:
| Endpoint | Returns |
| -------------------------------------- | ----------------------------------------------------------------------------------- |
| `GET /v1/health` | `"Healthy"` when the client is ready |
| `GET /v1/balance/$ercAddress/$tokenId` | Total balance of the token under the currently-loaded ZKP keys (64-char hex) |
| `GET /v1/commitments` | All commitments (preimages, status, nullifiers) known to this client |
| `GET /v1/proposers` | Registered proposers on-chain and their URLs |
| `GET /v1/request/$uuid` | Status of a submitted request (`Queued` → `Processing` → `Submitted` → `Confirmed`) |
#### Operations
**Deposit to Nightfall**
A deposit moves tokens from Layer 1 (Celo Sepolia) into Nightfall's privacy layer.
**Step 1:** Generate a unique deposit ID:
```bash theme={null}
DEPOSIT_ID=$(uuidgen)
```
**Step 2:** Make the deposit request:
```bash theme={null}
curl -X POST http://localhost:3000/v1/deposit \
-H "Content-Type: application/json" \
-H "X-Request-ID: $DEPOSIT_ID" \
-d '{
"ercAddress": "0x471EcE3750Da237f93B8E339c536989b8978a438",
"tokenId": "0000000000000000000000000000000000000000000000000000000000000000",
"tokenType": "0",
"value": "000000000000000000000000000000000000000000000000016345785d8a0000",
"fee": "0000000000000000000000000000000000000000000000000000000000000000",
"deposit_fee": "0000000000000000000000000000000000000000000000000000000000000000"
}'
```
**Parameters:**
* `ercAddress`: The ERC20/ERC721/ERC1155/ERC3525 token contract address. Use `0x471EcE3750Da237f93B8E339c536989b8978a438` for CELO token (ERC20 via Celo Token Duality).
* `tokenId`: Token ID (use all zeros for ERC20 — full 64-char form without `0x`).
* `tokenType`: `0` for ERC20, `1` for ERC721, `2` for ERC1155, `3` for ERC3525.
* `value`: Amount in hex format, without `0x` prefix (see [Amount Encoding](#amount-encoding)).
* `fee`: Transaction fee in hex format.
* `deposit_fee`: Deposit fee in hex format.
**Step 3:** Check deposit status:
```bash theme={null}
curl -i "http://localhost:3000/v1/request/$DEPOSIT_ID"
```
**Transfer in Nightfall**
Transfers tokens privately within Nightfall to another account.
**Step 1:** The recipient must first derive their keys and share their `zkp_public_key`:
```bash theme={null}
curl -X POST http://localhost:3000/v1/deriveKey \
-H "Content-Type: application/json" \
-d '{
"mnemonic": "recipient mnemonic phrase",
"child_path": "m/44'\''/60'\''/0'\''/0/0"
}'
```
Extract the `zkp_public_key` from the response (e.g., `"02dd2cd1ab715037f4b77903844b08c731e6a0a3f5036490af4eaf49f841f9cb"`).
**Step 2:** Generate a transfer ID and make the transfer:
```bash theme={null}
TRANSFER_ID=$(uuidgen)
curl -i -H "Content-Type: application/json" \
-H "X-Request-ID: $TRANSFER_ID" \
--request POST 'http://localhost:3000/v1/transfer' \
--json '{
"ercAddress": "0x471EcE3750Da237f93B8E339c536989b8978a438",
"tokenId": "0x00",
"recipientData": {
"values": ["000000000000000000000000000000000000000000000000016345785d8a0000"],
"recipientCompressedZkpPublicKeys": ["02dd2cd1ab715037f4b77903844b08c731e6a0a3f5036490af4eaf49f841f9cb"]
},
"fee": "0000000000000000000000000000000000000000000000000000000000000000"
}'
```
**Parameters:**
* `ercAddress`: Token contract address
* `tokenId`: Token ID. For **transfers only**, use the short form `"0x00"` — the deposit, withdraw, and de-escrow endpoints expect the full 64-zero form (`"0000…0000"`) without `0x`.
* `recipientData.values`: Array of amounts to send (in hex without `0x` prefix; see [Amount Encoding](#amount-encoding))
* `recipientData.recipientCompressedZkpPublicKeys`: Array of recipient public keys (from each recipient's `deriveKey` response — the recipient must be running their own `nightfall_client`)
* `fee`: Transaction fee
**Step 3:** Check transfer status:
```bash theme={null}
curl -i "http://localhost:3000/v1/request/$TRANSFER_ID"
```
**Withdraw from Nightfall**
Withdraws tokens from Nightfall back to Layer 1. The withdrawal process involves two on-chain phases: initiating the withdrawal (an L2 transaction that nullifies your private commitment), and then de-escrowing (an L1 transaction that releases the tokens from the Nightfall contract to your recipient).
**Step 1: Build the padded recipient address**
`recipientAddress` must be the **32-byte** (64-char) hex representation of the L1 recipient — the 20-byte EOA left-padded with 12 zero bytes, **no `0x` prefix**. The short `0x…` form used elsewhere is not accepted here:
```bash theme={null}
L1_ADDR="0xf39fd6e51aad88f6f4ce6ab8827279cfffb92267"
L1_PADDED="000000000000000000000000${L1_ADDR#0x}"
echo "$L1_PADDED"
# 000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92267
```
**Step 2: Initiate the withdrawal**
```bash theme={null}
WITHDRAW_ID=$(uuidgen)
curl -X POST http://localhost:3000/v1/withdraw \
-H "Content-Type: application/json" \
-H "X-Request-ID: $WITHDRAW_ID" \
-d "{
\"ercAddress\": \"0x471EcE3750Da237f93B8E339c536989b8978a438\",
\"tokenId\": \"0000000000000000000000000000000000000000000000000000000000000000\",
\"tokenType\": \"0\",
\"value\": \"000000000000000000000000000000000000000000000000016345785d8a0000\",
\"recipientAddress\": \"$L1_PADDED\",
\"fee\": \"0000000000000000000000000000000000000000000000000000000000000000\"
}"
```
**Parameters:**
* `ercAddress`: Token contract address
* `tokenId`: Token ID (all zeros for ERC20 — same 64-char form as deposit)
* `tokenType`: `0` for ERC20, `1` for ERC721, `2` for ERC1155, `3` for ERC3525
* `value`: Amount to withdraw in hex format (see [Amount Encoding](#amount-encoding))
* `recipientAddress`: **32-byte** (64-char) hex L1 recipient, no `0x` prefix (see Step 1)
* `fee`: Transaction fee
**Step 3: Capture the `withdrawFundSalt`**
The salt is needed for de-escrow in Step 5. It is returned in the **client stdout logs** (and in the webhook payload if you configured `WEBHOOK_URL`), **not** in `/v1/request/$WITHDRAW_ID`:
```bash theme={null}
SALT=$(docker logs nf4_indie_client 2>&1 \
| grep -o '"withdraw_fund_salt":"[^"]*"' \
| tail -1 \
| sed 's/.*"withdraw_fund_salt":"\([^"]*\)".*/\1/')
echo "$SALT"
```
**Step 4: Wait until the withdrawal is included in an L2 block**
The commitment state is the authoritative signal. When the commitment you just spent flips to `Spent` with `nullifier == withdraw_fund_salt`, the withdrawal has landed on L2 and is ready to be de-escrowed:
```bash theme={null}
curl -s http://localhost:3000/v1/commitments \
| jq '.[] | select(.nullifier == "'"$SALT"'") | .status'
# Expect "PendingSpend" initially, then "Spent" once the block lands
```
In some client builds `/v1/request/$WITHDRAW_ID` can remain stuck at `Submitted` even after the withdrawal has landed. Treat the commitment status (above) as the source of truth. The status-tracking fix is on the `celo` branch of [celo-org/nightfall\_4\_CE](https://github.com/celo-org/nightfall_4_CE) from commit `12a85a8` onward.
**Step 5: De-escrow (release tokens on L1)**
After the commitment is `Spent`, call `/v1/de-escrow` to release the tokens from the Nightfall contract to the L1 recipient:
```bash theme={null}
curl -X POST http://localhost:3000/v1/de-escrow \
-H "Content-Type: application/json" \
-d "{
\"ercAddress\": \"0x471EcE3750Da237f93B8E339c536989b8978a438\",
\"tokenId\": \"0000000000000000000000000000000000000000000000000000000000000000\",
\"tokenType\": \"0\",
\"value\": \"000000000000000000000000000000000000000000000000016345785d8a0000\",
\"recipientAddress\": \"$L1_PADDED\",
\"fee\": \"0000000000000000000000000000000000000000000000000000000000000000\",
\"withdrawFundSalt\": \"$SALT\"
}"
```
Expect `HTTP 200 OK`. The L1 balance of `$L1_ADDR` is now higher by `value` (minus the de-escrow L1 gas).
**Parameters:**
* All parameters from the withdrawal request — in particular, the same padded `recipientAddress` form
* `withdrawFundSalt`: The salt captured in Step 3
**Important Notes:**
* All `value` / `fee` / `tokenId` fields are hex **without** the `0x` prefix — **except** `tokenId` in `/v1/transfer`, which uses the short form `"0x00"`.
* `recipientAddress` on `/v1/withdraw` and `/v1/de-escrow` must be 32-byte (64-char) left-padded hex, **no** `0x` prefix.
* The client must be healthy before making requests. Check with `curl http://localhost:3000/v1/health`.
* The webhook is automatically started with docker-compose and receives notifications about transaction status changes, including the `withdraw_fund_salt`.
* For Celo Sepolia, the default ERC20 token address is `0x471EcE3750Da237f93B8E339c536989b8978a438` (CELO).
* **Timing expectations** (with a healthy proposer):
* Client-side work (proof generation, L1 escrow transaction) typically completes in a few seconds.
* L2 block confirmation of a deposit, transfer, or withdrawal is usually **\~30 minutes** (the proposer batches for 120 s, then generates the rollup proof before posting the `BlockProposed` transaction).
* This can extend up to **\~1 hour** under adverse conditions. If an operation stays at `Submitted` substantially longer, call `GET /v1/proposers` to confirm a registered proposer is available.
* **De-escrow must come after** the withdrawal has been included on L2 (commitment `Spent`). Calling `/v1/de-escrow` earlier will fail.
A worked end-to-end example of this entire flow (deposit → transfer → withdraw → de-escrow), with sample mnemonics, state variables, and diagnostic checkpoints, is available at [`doc/celo_sepolia_client_playbook.md`](https://github.com/celo-org/nightfall_4_CE/blob/celo/doc/celo_sepolia_client_playbook.md) on the `celo` branch.
### Integration Steps
1. **Review Technical Documentation**: Start with the [Nightfall GitHub documentation](https://github.com/EYBlockchain/nightfall_4_CE/blob/master/doc/nf_4.md)
2. **Set Up Development Environment**: Follow the [Running the Client on Celo Sepolia](#running-the-client-on-celo-sepolia) guide above
3. **Test Operations**: Practice deposits, transfers, and withdrawals on testnet
4. **Deploy Test Application**: Build and test your integration on testnet
5. **Implement APIs**: Integrate Nightfall Client and Proposer APIs into your application
## Resources
### Documentation
* **[Nightfall GitHub Repository](https://github.com/EYBlockchain/nightfall_4_CE)**: Full source code and implementation
* **[Technical Documentation](https://github.com/EYBlockchain/nightfall_4_CE/blob/master/doc/nf_4.md)**: Comprehensive guide including architecture, APIs, deployment, and testing
* **[EY Blockchain](https://blockchain.ey.com/)**: Learn more about EY's blockchain solutions
### APIs
* **Client APIs**: Deposit, transfer, withdraw, and balance query endpoints
* **Proposer APIs**: Block submission and transaction validation
* **Webhook Support**: Real-time transaction notifications
Full API documentation is available in the [Nightfall GitHub docs](https://github.com/EYBlockchain/nightfall_4_CE/blob/master/doc/nf_4.md#apis).
### Testing & Deployment
* **Local Testing**: See [Running the Client on Celo Sepolia](#running-the-client-on-celo-sepolia) for instructions on running Nightfall locally with Docker
* **Testnet Deployment**: Guide for deploying on Celo Sepolia testnet
* **Production Deployment**: Best practices for mainnet deployment
### Community & Support
Get help and connect with the community:
* **[Celo Discord](https://chat.celo.org)**: Join the #nightfall channel for questions
* **[Celo Forum](https://forum.celo.org)**: Discuss integration strategies and use cases
* **[GitHub Issues](https://github.com/EYBlockchain/nightfall_4_CE/issues)**: Report bugs or request features
## About EY Nightfall
Nightfall was developed by **Ernst & Young (EY)** as an open-source privacy solution for public blockchains. The project has evolved through multiple iterations:
* **Nightfall\_3**: Optimistic rollup approach
* **Nightfall\_4**: Current version using cryptographic (ZK-ZK) rollups for instant finality
By deploying on Celo, Nightfall brings enterprise-grade privacy to a mobile-first, payments-focused blockchain infrastructure that already serves millions of users globally.
**Testnet Environment**
Nightfall testnet on Celo Sepolia is for development and testing purposes only. Do not use real assets, production data, or sensitive information during testing. Testnet tokens hold no real-world economic value.
***
## Next Steps
1. Explore the [Nightfall technical documentation](https://github.com/EYBlockchain/nightfall_4_CE/blob/master/doc/nf_4.md)
2. Review [integration requirements](#prerequisites)
3. Follow the [Running the Client on Celo Sepolia](#running-the-client-on-celo-sepolia) guide to set up your development environment
4. Join the [Celo community](https://chat.celo.org) to ask questions
5. Start building your private payment application on testnet
# Quickstart
Source: https://docs.celo.org/build-on-celo/quickstart
A powerful CLI tool for generating customizable Celo blockchain starter kits with modern monorepo architecture.
## Prerequisites
* Node.js >= 18.0.0
* PNPM (recommended) or npm/yarn
## Quick Start
Create a new Celo project in seconds:
```bash theme={null}
npx @celo/celo-composer@latest create
```
This will start an interactive setup process where you can choose your template, wallet provider, and smart contract framework.
## Installation
No installation required! Use `npx` to run Celo Composer directly without installing anything globally.
## Usage
### Interactive Mode
Run the command without any flags to enter interactive mode:
```bash theme={null}
npx @celo/celo-composer@latest create my-celo-app
```
The CLI will guide you through:
* Project name and description
* Template selection
* Wallet provider choice
* Smart contract framework selection
* Dependency installation
### Non-Interactive Mode
Create a project with specific configurations using flags:
```bash theme={null}
npx @celo/celo-composer@latest create my-celo-app \
--template basic \
--wallet-provider rainbowkit \
--contracts hardhat \
--description "My awesome Celo app"
```
### Quick Start with Defaults
Skip all prompts and use default settings. This will create a basic app with no additional setup:
```bash theme={null}
npx @celo/celo-composer@latest create my-celo-app --yes
```
## Available Templates
### Basic Web App (default)
A standard Next.js 14+ web application with modern UI, perfect for most dApp projects.
```bash theme={null}
npx @celo/celo-composer@latest create --template basic
```
### Farcaster Miniapp
A specialized template for building Farcaster Miniapps with Farcaster SDK and Frame development support.
```bash theme={null}
npx @celo/celo-composer@latest create --template farcaster-miniapp
```
### MiniPay App
Optimized for building dApps that integrate with the MiniPay mobile wallet, with mobile-first design.
```bash theme={null}
npx @celo/celo-composer@latest create --template minipay
```
Checkout [minipay docs](/build/build-on-minipay/overview) to learn more about it.
### AI Chat App
A standalone Next.js AI chat application template.
```bash theme={null}
npx @celo/celo-composer@latest create --template ai-chat
```
## Wallet Providers
Choose a wallet provider to handle user authentication and transaction signing:
* **RainbowKit** (default): Popular, easy-to-use wallet connector for React apps
* **Thirdweb**: Complete Web3 development framework with powerful wallet tools
* **None**: Skip wallet integration if you want to integrate your own solution
```bash theme={null}
npx @celo/celo-composer@latest create --wallet-provider rainbowkit
```
## Smart Contract Frameworks
Set up a smart contract development environment:
* **Hardhat** (default): Popular Ethereum development environment
* **Foundry**: Fast, portable and modular toolkit for Ethereum application development
* **None**: Skip smart contract development setup
```bash theme={null}
npx @celo/celo-composer@latest create --contracts hardhat
```
## Command Options
```bash theme={null}
npx @celo/celo-composer@latest create [project-name] [options]
```
| Flag | Description | Default |
| --------------------------------- | ------------------------------------------------------------------ | ------------------ |
| `-d, --description ` | Project description | Interactive prompt |
| `-t, --template ` | Template type (`basic`, `farcaster-miniapp`, `minipay`, `ai-chat`) | `basic` |
| `--wallet-provider ` | Wallet provider (`rainbowkit`, `thirdweb`, `none`) | `rainbowkit` |
| `-c, --contracts ` | Smart contract framework (`hardhat`, `foundry`, `none`) | `hardhat` |
| `--skip-install` | Skip automatic dependency installation | `false` |
| `-y, --yes` | Skip all prompts and use defaults | `false` |
## Generated Project Structure
```
my-celo-app/
├── apps/
│ ├── web/ # Next.js application
│ └── contracts/ # Smart contracts (if selected)
├── packages/
│ ├── ui/ # Shared UI components
│ └── utils/ # Shared utilities
├── package.json # Root package.json
├── pnpm-workspace.yaml # PNPM workspace config
├── turbo.json # Turborepo configuration
└── tsconfig.json # TypeScript configuration
```
## Next Steps
After creating your project, navigate to it and install dependencies (if you didn't use `--skip-install`):
```bash theme={null}
cd my-celo-app
pnpm install # If you used --skip-install
pnpm dev # Start development server
```
Your project is automatically initialized with Git and includes an initial commit.
## Tech Stack
**Generated Projects Include:**
* Next.js 14+ with App Router
* TypeScript
* Tailwind CSS
* shadcn/ui components
* Turborepo for monorepo management
* PNPM workspaces
## Support
Join the [Celo Discord server](https://discord.com/invite/celo). Reach out in the #build-with-celo channel with your questions and feedback.
## Resources
* [GitHub Repository](https://github.com/celo-org/celo-composer)
# Scaling Your App
Source: https://docs.celo.org/build-on-celo/scaling-your-app
Scaling a dApp requires careful planning across infrastructure, blockchain interactions, and cost optimization. This guide shares practical strategies from real-world experience building and scaling applications on Celo.
## Overview
As your dApp grows, costs can scale exponentially if not managed properly. This guide covers:
* Infrastructure and hosting strategies
* RPC and blockchain interaction optimization
* Caching and data management
* AI/LLM cost optimization
* Testing and monitoring best practices
## Infrastructure & Hosting
### Server Architecture
Start simple, but plan for growth:
* **Early Stage**: Begin with a single server to minimize costs
* **Monitor Usage**: Track CPU, memory, and network usage closely
* **Plan Migration**: Be ready to migrate to scalable solutions like:
* **Kubernetes (K8s)**: For container orchestration and auto-scaling
* **Docker Swarm**: Lighter alternative for container management
* **Managed Services**: Consider AWS ECS, Google Cloud Run, or similar
Monitor your server metrics from day one. Set up alerts for CPU, memory, and
disk usage to catch scaling issues before they impact users.
### Image Hosting & CDN
Avoid expensive default CDNs:
* **Don't Use**: Vercel's default CDN (can be expensive at scale)
* **Use Instead**: Cost-effective CDN solutions like:
* Cloudflare (free tier available)
* AWS CloudFront
* BunnyCDN
* ImageKit or Cloudinary for image optimization
CDN costs can add up quickly with high traffic. Choose a CDN with predictable
pricing and monitor bandwidth usage.
### Backend Architecture
Separate your backend from your frontend for better scaling:
* **Avoid**: Next.js API routes for production workloads
* **Use Instead**: Separate backend service (Node.js, Python, Go, etc.)
* **Benefits**:
* Scale backend independently without increasing Vercel pricing
* Better control over resources and deployment
* Easier to implement queues, caching, and background jobs
Use Next.js API routes only for lightweight, user-specific operations. Move
heavy processing, RPC calls, and background jobs to a separate backend
service.
### Message Queues
Implement queues wherever they make sense:
* **Use Cases**:
* Processing blockchain transactions
* Sending notifications
* Background data processing
* Image processing
* Email/SMS sending
* **Queue Solutions**:
* **Redis + BullMQ**: Lightweight and fast
* **RabbitMQ**: Robust message broker
* **AWS SQS**: Managed queue service
* **Google Cloud Tasks**: Managed task queue
Queues prevent request timeouts, improve user experience, and allow you to
process jobs at your own pace without overwhelming your server.
## RPC & Blockchain Interactions
### RPC Strategy
RPC calls are a precious resource—treat them carefully:
* **Choose Scalable RPC Providers**:
* Use providers with high rate limits and good uptime
* Consider multiple RPC endpoints for redundancy
* Monitor RPC response times and error rates
* **Early Stage Strategy**:
* Use free RPC endpoints in the frontend
* Each user gets their own rate limits
* Reduces backend RPC load
* **Scale Considerations**:
* RPC usage scales exponentially with user growth
* Audit all RPC calls regularly
* Remove unnecessary RPC calls
* Batch requests when possible
RPC costs can become your largest expense. Audit your RPC calls regularly and
optimize aggressively. A single unnecessary RPC call per user can cost
thousands at scale.
### Caching Strategy
Cache API responses wherever it makes sense:
* **Don't Always Fetch Latest Data**:
* Cache blockchain data that doesn't change frequently
* Use appropriate TTLs (Time To Live) based on data freshness requirements
* Balance between data freshness and RPC costs
* **Cache Layers**:
* **In-Memory Cache**: Redis or Memcached for frequently accessed data
* **CDN Cache**: For static or semi-static content
* **Application Cache**: Cache responses in your application layer
* **What to Cache**:
* Token balances (with short TTL)
* Token metadata
* Historical transaction data
* Price data (with appropriate TTL)
* Contract ABIs
Most blockchain data doesn't need to be real-time. Cache aggressively and only
fetch fresh data when absolutely necessary.
### Indexer Selection
If you need an indexer, choose cost-effective options:
* **Recommended**: Use affordable indexers like [thirdweb Insight](https://portal.thirdweb.com/insights)
* **Consider**:
* The Graph (decentralized indexing)
* Alchemy (if already using their RPC)
* Custom indexer (if you have specific needs)
Indexers can significantly reduce RPC calls by providing pre-indexed
blockchain data. Choose one that fits your budget and requirements.
## AI & LLM Optimization
### Model Selection
Optimize LLM costs by choosing the right model for each task:
* **Small Tasks**: Use cheaper models (e.g., GPT-3.5-turbo, Claude Haiku)
* **Complex Tasks**: Reserve expensive models (e.g., GPT-4, Claude Opus) only when necessary
* **Consider Alternatives**:
* Open-source models (Llama, Mistral)
* Specialized models for specific tasks
Most tasks don't require the most powerful models. Use cheaper models for
simple tasks and save expensive models for complex reasoning.
### AI SDK
Use AI SDKs for better developer experience:
* **Benefits**:
* Better error handling
* Built-in retry logic
* Streaming support
* Cost tracking
* Easier model switching
* **Recommended SDKs**:
* [Vercel AI SDK](https://sdk.vercel.ai/) for JavaScript/TypeScript
* [LangChain](https://www.langchain.com/) for Python
* [LlamaIndex](https://www.llamaindex.ai/) for data indexing
## Testing & Monitoring
### Testing Strategy
Comprehensive testing prevents costly production issues:
* **Unit Tests**: Test individual functions and components
* **Integration Tests**: Test how different parts work together
* **E2E Tests**: Test complete user flows
* **Load Tests**: Test your application under expected load
* **Reburst Tests**: Test how your system handles sudden traffic spikes
Don't skip testing. Production bugs are expensive to fix and can damage user
trust. Invest in a solid testing strategy from the start.
### Error Monitoring
Use Sentry to audit error rates:
* **Benefits**:
* Track error rates over time
* Get alerts for error spikes
* Debug production issues quickly
* Monitor performance issues
* **Setup**:
* Install Sentry SDK in your application
* Configure error tracking
* Set up alerts for critical errors
* Monitor error trends
Sentry helps you catch and fix errors before they impact too many users. Set
up error monitoring from day one.
### Analytics & Logging
Use Grafana for analytics and logs:
* **Metrics to Track**:
* Request rates and response times
* Error rates
* RPC call counts and costs
* Server resource usage
* User activity metrics
* **Logging**:
* Centralized logging with Grafana Loki or similar
* Structured logging (JSON format)
* Log retention policies
* Search and query capabilities
* **Dashboards**:
* Create dashboards for key metrics
* Set up alerts for anomalies
* Monitor trends over time
Good observability helps you catch issues early and make data-driven decisions
about scaling. Invest in monitoring from the start.
## Best Practices Summary
### Cost Optimization Checklist
* [ ] Use cost-effective CDNs instead of default options
* [ ] Separate backend from frontend for independent scaling
* [ ] Implement message queues for background processing
* [ ] Cache API responses aggressively
* [ ] Audit and optimize RPC calls regularly
* [ ] Use free RPC endpoints in frontend during early stages
* [ ] Choose affordable indexers when needed
* [ ] Use cheaper LLM models for simple tasks
* [ ] Monitor all costs and set up alerts
### Scaling Readiness Checklist
* [ ] Monitor server metrics (CPU, memory, disk)
* [ ] Have a plan to migrate to scalable infrastructure (K8s, Docker Swarm)
* [ ] Implement comprehensive testing (unit, integration, E2E, load)
* [ ] Set up error monitoring (Sentry)
* [ ] Configure analytics and logging (Grafana)
* [ ] Document your architecture and scaling plan
* [ ] Set up alerts for critical metrics
## Additional Resources
* [Celo Documentation](/build-on-celo) - Explore Celo development resources
* [Launch Checklist](/build-on-celo/launch-checklist) - Pre-launch preparation guide
* [thirdweb Insight](https://portal.thirdweb.com/insights) - Affordable blockchain indexer
* [Vercel AI SDK](https://sdk.vercel.ai/) - AI SDK for JavaScript/TypeScript
* [Sentry Documentation](https://docs.sentry.io/) - Error monitoring and performance tracking
* [Grafana Documentation](https://grafana.com/docs/) - Analytics and observability platform
# Builders
Source: https://docs.celo.org/contribute-to-celo/builders
Whether you're just starting or are an experienced developer, Celo offers a variety of ways for you to engage and grow your projects.
## Builders in the Celo Ecosystem
The Celo Builder Community is a global network of developers, entrepreneurs, and enthusiasts dedicated to building a regenerative digital economy that promotes prosperity for all. By joining, you'll have the opportunity to create onchain apps and tools that drive financial inclusion and support sustainable development on a global scale. Make sure to check out the local nodes to connect with builders in your region and attend networking events.
## How to Get Involved
There are several ways to get started as a builder on Celo:
* [**Sign up to Proof of Ship**](https://celo-devs.beehiiv.com/subscribe): Prove their impact, showcase progress, and earn rewards. Your onchain reputation unlocks access to grants, retro funding, airdrops, and other funding opportunities. Make sure your app includes an [attribution tag](/build-on-celo/attribution-tags) — self-derived or assigned at registration — so your transactions get credited.
* **Join the Builder Community**: Connect with like-minded individuals on platforms like [Discord](https://discord.com/invite/celo) and the [Celo Forum](https://forum.celo.org/). You'll find channels dedicated to everything from smart contract development to mobile-first dApp creation.
* **Join the office hour**: Office Hours are an excellent way to learn about opportunities in the ecosystem, get feedback on your project and connect with the community. Find governance events on our community [event platform](https://lemonade.social/s/celogovernance).
* **Apply for Grants**: Celo has grants programs, like [Prezenti](https://www.prezenti.xyz/) and [Celo Public Goods](https://www.celopg.eco/) which supports projects that align with its mission to provide financial services to the next billion people.
* **Apply for an Accelerator**: Check out [Celo Camp](https://www.celocamp.com/), the accelerator focused on the Celo ecosystem. If you are not yet at that stage, they also offer [Startup Pathway](https://startup-pathway.mykajabi.com/) a program, that leads you through your first steps to becoming a founder.
# Code of Conduct
Source: https://docs.celo.org/contribute-to-celo/code-of-conduct
# Operating a Community RPC Node
Source: https://docs.celo.org/contribute-to-celo/community-rpc-nodes/community-rpc-node
This guide covers how to operate a community RPC node on Celo.
***
****Terminology****
The term "validator" appears in code and documentation due to historical reasons, but refers to community RPC providers.
To be eligible for rewards, registered and elected nodes must operate independent RPC endpoints. This guide assumes your node has been properly [registered](/contribute-to-celo/community-rpc-nodes/registering-as-rpc-node).
## Running the RPC Service
To operate the required RPC endpoint, follow the [Running a node guide](/infra-partners/operators/run-node).
## Rewards
### Claiming Rewards
Validator rewards for RPC nodes must be claimed, which is possible anytime after allocation. Use this CLI command:
```bash theme={null}
celocli epochs:send-validator-payment --from $YOUR_ADDRESS --for $VALIDATOR_ADDRESS
```
Where:
* `$YOUR_ADDRESS` is your Celo account address sending the transaction
* `$VALIDATOR_ADDRESS` is your validator's Celo account address
Note: anyone can run this command, but rewards distribute according to your validator group's commission rate.
### Verifying Rewards
Confirm successful reward distribution by checking for `ValidatorEpochPaymentDistributed` events on a block explorer like [CeloScan](https://celoscan.io/address/0xf424b5e85b290b66ac20f8a9eab75e25a526725e).
### Tracking Rewards
For accounting purposes, you can:
* Query Celo nodes for `ValidatorEpochPaymentDistributed` events.
* Query the [EpochManager contract](/contracts/core-contracts) for `validatorPendingPayments` to view total allocated payments.
### Group Commission Settings
Validator rewards distribution is affected by the validator group's commission rate. A commission rate of `1` means the entire reward goes to the validator group. Ensure you understand your group's commission settings to correctly anticipate reward allocations.
Check commission settings with:
```bash theme={null}
celocli validatorgroup:show $CELO_GROUP_ADDRESS
```
Update commission settings with the [celocli validatorgroup:commission](/cli/validatorgroup) command.
# How it works
Source: https://docs.celo.org/contribute-to-celo/community-rpc-nodes/how-it-works
## Context
Following Celo's migration to L2, validators have evolved to serve as RPC node providers for the community. The initial active RPC providers were established in Celo L2's genesis block. Subsequently, elections occur at each epoch's conclusion (approximately every 24 hours) to potentially add or remove nodes from the active set.
This system is based on the [proposal for validator engagement during the transition to L2](https://forum.celo.org/t/proposal-validator-engagement-during-the-transition-to-celo-l2/9700) and [Set The Great Celo Halvening Parameters](https://forum.celo.org/t/set-the-great-celo-halvening-parameters/10455/3). For additional details, see [Epoch Rewards](/home/protocol/epoch-rewards/index) and the related [forum discussion: The Great Celo Halvening – Proposed Tokenomics in the Era of Celo L2](https://forum.celo.org/t/the-great-celo-halvening-proposed-tokenomics-in-the-era-of-celo-l2/9701). For updates make sure to refer to the [Celo Forum](https://forum.celo.org).
****Terminology****
The term "validator" is used in the code and corresponding explanation due to historical reasons, but refers to the community RPC providers.
## RPC Elections
In Celo's RPC elections (formerly [validator elections](/legacy/protocol/pos/validator-elections)), holders of the native asset CELO participate in the process to support network operations and earn rewards for voting.
The election process follows these steps:
1. **Lock CELO tokens**: Holders must first move their CELO balances into the [Locked Celo](/legacy/protocol/pos/locked-gold) (formerly "Celo Gold") smart contract before participating in elections.
2. **Vote for Groups**: Rather than voting directly for individual node providers, accounts cast their votes for validator groups that manage collections of nodes.
3. **Earn rewards**: Participants receive rewards for their involvement, and validators and groups can also vote and earn rewards using their own stake.
The same Locked CELO can simultaneously be used for multiple purposes: voting in RPC node elections, maintaining Community RPC stakes, and participating in on-chain [Governance](/home/protocol/governance/overview) proposals.
**No voter slashing**
Unlike in other proof-of-stake systems, holding Locked Gold or voting for a group does not put that amount 'at risk' from slashing due to the behavior of node providers. Only the stake put up by a node provider or group may be slashed.
## Implementation
Elections are handled my smart contracts, and as such can be changed through Celo's on-chain [Governance](/home/protocol/governance/overview) process.
* [`Accounts.sol`](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/common/Accounts.sol) manages key delegation and metadata for all accounts including Validators, Groups and Locked Gold holders.
* [`LockedGold.sol`](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/governance/LockedGold.sol) manages the lifecycle of Locked Gold.
* [`Validators.sol`](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts-0.8/governance/Validators.sol) handles registration, deregistration, staking, key management and epoch rewards for validators and validator groups, as well as routines to manage the members of groups.
* [`Election.sol`](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/governance/Election.sol) manages Locked Gold voting and epoch rewards and runs Validator Elections.
* [`EpochManager.sol`](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts-0.8/common/EpochManager.sol) handles the epoch processing logic, including starting and finishing epoch transitions, reward calculations, and validator elections through permissionless functions.
# Community RPC Provider Penalties
Source: https://docs.celo.org/contribute-to-celo/community-rpc-nodes/penalties
Introduction to Community RPC provider penalties, enforcement mechanisms, and conditions.
***
This page is a work in progress based on the [proposal for validator engagement during the transition to L2](https://forum.celo.org/t/proposal-validator-engagement-during-the-transition-to-celo-l2/9700) and [Set The Great Celo Halvening Parameters](https://forum.celo.org/t/set-the-great-celo-halvening-parameters/10455/3). For updates make sure to refer to the [Celo Forum](https://forum.celo.org).
## Overview
The Celo community has established penalties for Community RPC providers who fail to maintain their RPC nodes. These penalties ensure providers maintain reliable and consistent service to the network.
## How It Works
Community RPC providers receive 82.19178082 USDm per day at a perfect score of 1. Scores are monitored off-chain by the Score Management Committee, an independent working group running custom software based on [Vido by Atalma](https://dev.vido.atalma.io/celo/rpc). This committee operates a Safe Multisig with permissions to manage the on-chain `ScoreManager.sol` smart contract.
Weekly, the committee collates measurements and averages scores for each provider. Scores below 1 are updated and apply to the following week's payments.
**Running a Community RPC is mandatory for elected providers.** Insufficient uptime results in slashing - a portion of locked CELO is forfeited.
### The Score Management Committee
The Committee controls a multisig with governance-granted powers to call functions on the `ScoreManager` and `GovernanceSlasher` contracts. Each member receives \$2k USDm monthly for operational expenses.
**Responsibilities:**
* Running open-source and verifiable monitoring infrastructure for uptime tracking
* Performance evaluation, collaboration, and multisig operations
* Transparent communication
### Metrics
Rewards are allocated automatically after each epoch based on `ScoreManager` contract scores and claimed manually by providers.
Weekly score breakdown:
| RPC Uptime | Score |
| ---------- | ----------- |
| 80% - 100% | 1.00 |
| 60% - 79% | 0.80 |
| 40% - 59% | 0.60 |
| 20% - 39% | 0.40 |
| 0% - 19% | 0 and Slash |
Providers with uptime below 20% for 7 days are slashed.
### References in the Specification
* [Overview of rewards and epochs in L2](/specs/smart-contract-updates-from-l1#overview-of-rewards-and-epochs-in-l2)
* [Scoring](/specs/smart-contract-updates-from-l1#scoring)
* [Slashing](/specs/smart-contract-updates-from-l1#slashing)
# Registering a Community RPC provider
Source: https://docs.celo.org/contribute-to-celo/community-rpc-nodes/registering-as-rpc-node
Step-by-step instructions on how to register a RPC node on chain to be eligible for rewards.
****Terminology****
The term "validator" is used in the code and corresponding explanation due to historical reasons, but refers to the community RPC providers.
## Prerequisites
### Software Requirements
Install the Celo CLI following the [Command Line Interface (CLI)](/cli/) setup instructions. Ensure you're using Node.js version 18 or higher.
### Staking Requirements
To register as a community RPC provider, you need:
* **10,000 CELO** to register an RPC node
* **10,000 CELO per member RPC** to register an RPC Group
If you don't have enough CELO, you can practice the registration process on the [Celo Sepolia Testnet](/build-on-celo/network-overview). Use the [testnet faucet](https://faucet.celo.org/celo-sepolia) to get test CELO - select "Advanced Needs" when requesting funds for RPC provider testing.
### Key Management
Private keys are the central primitive of any cryptographic system and need to be handled with extreme care. Loss of your private key can lead to irreversible loss of assets.
This guide contains a large number of keys, so it is important to understand the purpose of each key. [Read more about key management.](/legacy/validator/key-management/summary)
### Account and Signer Keys
Running an RPC node involves managing multiple keys with different security levels and permissions. Keys used frequently (like those for updating URLs) are more vulnerable to compromise and therefore have limited permissions. Keys used less often (such as for locking CELO) can be stored more securely and have broader permissions.
Below is a summary of the different keys used in the Celo network and their specific permissions:
| Name of the key | Purpose |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Account key | This is the key with the highest level of permissions, and is thus the most sensitive. It can be used to lock and unlock CELO, and authorize vote, validator, and attestation keys. Note that the account key also has all of the permissions of the other keys. |
| Validator signer key | This is the key that has permission to register and manage a node or a Group. |
| Vote signer key | This key can be used to vote in Validator elections and on-chain governance. |
## Addresses Used
In this guide, the following addresses will be used:
| Address name | Purpose | Owner entity | Recommended storage |
| ----------------------- | ------------------------------------------------------------------------------------------------------ | ------------- | ------------------- |
| CELO\_GROUP\_ADDRESS | Address representing a group, with up to five nodes. It's the account that will receive votes. | Group | Cold |
| CELO\_NODE\_ADDRESS | Address that represent a node. | Node | Cold |
| CELO\_VALIDATOR\_SIGNER | Address authorized to generate signers or deregister members or join/leave a group. It can be rotated. | Node operator | Hot |
Groups and validators may be run by different entities. This guide assumes they are running by the same entity, but you can skip those if not relevant to your specific setup.
## Setting Up Accounts
This amount (10,000 CELO) represents the minimum amount needed to be locked in order to register a Validator and Validator group.
Note that you will want to be sure to leave enough CELO unlocked to be able to continue to pay transaction fees for future transactions (such as those issued by running some CLI commands).
Check that your CELO was successfully locked with the following commands:
```bash theme={null}
celocli lockedcelo:show $CELO_GROUP_ADDRESS
celocli lockedcelo:show $CELO_NODE_ADDRESS
```
### Setting Up the Group Account
#### Lock CELO
Lock up CELO for both accounts to secure the right to register a Validator and Validator Group. You need 10,000 CELO to register a node. This CELO stays locked for approximately 60 days after deregistration.
```bash theme={null}
celocli lockedcelo:lock --from $CELO_GROUP_ADDRESS --value 10000e18
```
The Celo CLI needs an RPC address. You can use the Celo Community RPC gateway with `-n https://rpc.celo-community.org`.
You can use the Celo CLI with a Ledger hardware wallet (see [CLI docs](/wallet/ledger/to-celo-cli)) or pass a private key directly with the `--privateKey` flag. Both options work with any transaction-signing command.
### Setting Up the Node Account
#### Lock CELO
Lock up CELO for the node account to secure the right to register a Validator. You need 10,000 CELO to register a node. This CELO stays locked for approximately 180 days after removal of the Nth validator from the group.
```bash theme={null}
celocli lockedcelo:lock --from $CELO_NODE_ADDRESS --value 10000e18
```
#### Create a Validator Signer
To register as a node, you need to generate a validator signer key. You can create this account by:
* Exporting a private key from a wallet (like MetaMask)
* Using a hardware wallet
* Running the command below:
```bash theme={null}
# On the validator machine
celocli account:new
```
Make sure to safely store the signer key.
#### Create a Validator Signer Proof-of-Possession
Next, create a proof-of-possession to verify you control the validator signer private key. This involves signing a message containing the validator account address.
```bash theme={null}
celocli account:proof-of-possession --signer $CELO_VALIDATOR_SIGNER_ADDRESS --account $CELO_NODE_ADDRESS
```
#### Register Node Metadata On-Chain
Before proceeding with the election process, you need to register your node's metadata on-chain. This step is critical - nodes without proper metadata are at risk of being slashed.
For detailed instructions on registering your node URL and metadata, see [Registering the Node URL](#registering-the-node-url).
## Register the Nodes and Group
To participate in elections as an RPC provider, you must register both your group and individual node. When registering a Group, you'll need to specify a [commission](/legacy/protocol/pos/validator-groups#group-share) - this is the percentage of epoch rewards that group members pay to the group.
Since we want to keep our account key secure, we'll first authorize the validator signing key instead of using the account key for validation:
#### Authorize Signer
```bash theme={null}
celocli account:authorize --from $CELO_NODE_ADDRESS --role validator --signature 0x$CELO_VALIDATOR_SIGNER_SIGNATURE --signer 0x$CELO_VALIDATOR_SIGNER_ADDRESS
```
Confirm by checking the authorized Validator signer for your Validator:
```bash theme={null}
celocli account:show $CELO_NODE_ADDRESS
```
#### Registering the Group
Register your Group using the following command. Since we haven't authorized a validator signer for the Group account, use the account key for registration.
```bash theme={null}
celocli validatorgroup:register --from $CELO_GROUP_ADDRESS --commission 0.1
```
View your Validator Group information:
```bash theme={null}
celocli validatorgroup:show $CELO_GROUP_ADDRESS
```
#### Registering the Node
Register your node with the following command. Since we authorized a validator signer, this step can be performed on the validator machine. Running it locally avoids installing the [Celo CLI](/cli/) on the validator machine.
```bash theme={null}
celocli validator:register --from $CELO_NODE_ADDRESS --ecdsaKey $CELO_VALIDATOR_SIGNER_PUBLIC_KEY
```
#### Affiliate the Node to the Group
Link your node to your Group. Note that you won't be a group member until the Group accepts the affiliation. This command can also be run from the validator signer on the validator machine.
```bash theme={null}
celocli validator:affiliate $CELO_GROUP_ADDRESS --from $CELO_NODE_ADDRESS
```
Accept the affiliation request:
```bash theme={null}
celocli validatorgroup:member --accept $CELO_NODE_ADDRESS --from $CELO_GROUP_ADDRESS
```
Verify that your node is now a member of your Group:
```bash theme={null}
celocli validator:show $CELO_NODE_ADDRESS
celocli validatorgroup:show $CELO_GROUP_ADDRESS
```
## Registering the Node URL
To register your node as an RPC provider, you must register a public HTTPS URL on-chain through a signed metadata file in your Celo Account.
The `--from` flag in the CLI commands can use either the validator account itself or the validator signer.
#### Create Metadata File
Create a new metadata file for your node. If you need to update an existing metadata file, download it instead of creating a new one.
```bash theme={null}
celocli account:create-metadata ./metadata.json --from $CELO_VALIDATOR_SIGNER_ADDRESS
```
#### Claim RPC URL
Register your public RPC URL in the metadata file:
```bash theme={null}
celocli account:claim-rpc-url ./metadata.json --from $CELO_VALIDATOR_SIGNER_ADDRESS --rpcUrl $RPC_URL
```
#### Upload Metadata
Upload the metadata file to a publicly available URL with high availability.
#### Register Metadata URL
Link the metadata URL to your validator Celo account:
```bash theme={null}
celocli account:register-metadata --url $METADATA_URL --from $CELO_NODE_ADDRESS
```
If your account is a [ReleaseGold contract](/home/manage/release-gold), use the command `celocli releasecelo:set-account` instead. Documentation can be found [here](/cli/releasecelo#celocli-releaseceloset-account).
#### Verify Registration
Confirm that the metadata registration was successful:
```bash theme={null}
celocli account:get-metadata $CELO_NODE_ADDRESS
```
You can also list all registered RPC URLs on the network:
```bash theme={null}
celocli network:rpc-urls
```
## Voting
As an optional step, you can use both accounts to vote for your Group.
#### Vote With All Accounts
Since we haven't authorized a vote signer for either account, these transactions must be sent using the account keys.
You can only run these commands with accounts you control. All commands are listed here for the sake of completeness.
```bash theme={null}
celocli election:vote --from $CELO_NODE_ADDRESS --for $CELO_GROUP_ADDRESS --value 10000e18
celocli election:vote --from $CELO_GROUP_ADDRESS --for $CELO_GROUP_ADDRESS --value 10000e18
```
Verify that your votes were cast successfully:
```bash theme={null}
celocli election:show $CELO_NODE_ADDRESS --voter
celocli election:show $CELO_GROUP_ADDRESS --group
celocli election:show $CELO_GROUP_ADDRESS --voter
```
#### Activate Your Votes
Users voting in the Celo protocol receive epoch rewards only after submitting a special transaction to activate their votes. This must be done every time new votes are cast, and can only be executed after the most recent epoch has ended. Use the following command, which waits until the epoch ends before sending the transaction:
```bash theme={null}
# Note: This may take time as the epoch needs to end before votes can be activated
celocli election:activate --from $CELO_NODE_ADDRESS --wait &&
celocli election:activate --from $CELO_GROUP_ADDRESS --wait
```
Confirm that your votes were activated by running:
```bash theme={null}
celocli election:show $CELO_NODE_ADDRESS --voter
celocli election:show $CELO_GROUP_ADDRESS --voter
```
## Watching the Election Process
You're all set! Elections are finalized at the end of each epoch, roughly once a day on Mainnet. If elected, your node will start participating. After the first epoch of participation, you'll receive your first epoch rewards.
You can view current election status and the minimum votes needed on [Mondo](https://mondo.celo.org/).
Inspect the current validator elections:
```bash theme={null}
celocli election:list
```
Check your node's status, including election status:
```bash theme={null}
celocli validator:status --validator $CELO_NODE_ADDRESS
```
View additional node information, including uptime score:
```bash theme={null}
celocli validator:show $CELO_NODE_ADDRESS
```
## Rewards
### CELO Rewards
If your Validator Group elects validators, you'll receive epoch rewards as additional Locked CELO voting for your Validator Group. You can monitor these rewards using the previous commands and:
```bash theme={null}
celocli lockedcelo:show $CELO_GROUP_ADDRESS
celocli lockedcelo:show $CELO_NODE_ADDRESS
```
### USDm Rewards
Active validators receive USDm rewards based on their validator score, calculated as part of the L2 epoch rewards process (see `EpochRewards.calculateTargetEpochRewards()`). For more details, refer to the [L2 Epoch Rewards documentation](/home/protocol/epoch-rewards/index).
For reward claiming instructions, see [Claiming Rewards](./community-rpc-node#claiming-rewards).
# Community RPC Provider FAQ
Source: https://docs.celo.org/contribute-to-celo/community-rpc-nodes/validator-rpc-faq
* Install [Celo CLI](/cli/index) at version 6.1.0 or later. Then run: `celocli network:community-rpc-nodes`.
* [Vido Node Explorer](https://dev.vido.atalma.io/celo/rpc)
* [Celo Community RPC Gateway](https://celo-community.org/)
Correct. Validators will move to become Community RPC providers.
The status onchain does not change after the migration, only the kind of node you’re supposed to run will change. This is not related to token duality.
Operators will need to register their RPC or deregister completely before the migration block, however, the actual RPC node can only be started after the L2 starts.
[See Running a Community RPC Node](/contribute-to-celo/community-rpc-nodes/community-rpc-node)
If a validator chooses to not run the RPC nodes after the transition, and does not deregister, they will get slashed and rewards will eventually drop to zero for the voters and the validators.
Only full node or archive node.
No, there will no longer be any validator nodes on the L2.
Rewards are limited to validators who register as a community RPC provider. There is a proposal in draft that will outline all the details on the monitoring.
Migrations need to happen by the time the L2 is activated. If RPC is consistently offline / unregistered, it will eventually get slashed.
You can make the group ineligible for election by removing all its members, after that you can move forward with deregistering and waiting for the unlock period.
If validators choose to not run the RPC nodes after the transition, rewards will eventually drop to zero for the voters and the validators.
# Community Improvement Proposals
Source: https://docs.celo.org/contribute-to-celo/contributors/cip-contributors
Celo's Improvement Proposals (CIPs) describe standards for the Celo platform, including the core protocol specifications, SDK, and contract standards. A CIP is a design document that should provide background information, a rationale for the proposal, detailed solution including technical specifications, and, if any, a list of potential risks. The proposer is responsible for soliciting community feedback and for driving consensus.
Participation in the Celo project is subject to the [Code of Conduct](https://celo.org/code-of-conduct).
## Submitting CIPs
Draft all proposals following the template below and submit to the [CIPs repository](https://github.com/celo-org/celo-proposals) via a PR (pull request).
CIP template:
* **Summary:** Describe your proposal in 280 characters or less.
* **Abstract**: Provide a short description of the technical issue being addressed.
* **Motivation:** Clearly explain why the proposed change should be made. It should layout the current Celo protocol shortcomings it addresses and why doing so is important.
* **Specification:** Define and explain in detail the technical requirements for new features and/or changes proposed.
* **Rationale**: Explain the reasoning behind your approach. It should cover alternative approaches considered, related work, and trade-offs made.
* **Implementation:** For all proposals going through the governance process, this section should reference the code implementing the proposed change. It’s recommended to get community feedback before writing any code.
* **Risks:** Highlight any risks and concerns that may affect consensus, proof-of-stake, governance, protocol economics, the stability protocol, security, and privacy.
For questions, comments, and discussions please use the [Celo Forum](https://forum.celo.org/) or [Discord](https://chat.celo.org/).
# Code Contributors
Source: https://docs.celo.org/contribute-to-celo/contributors/code-contributors
How to contribute to open source projects and further the growth of the Celo ecosystem.
## How to Contribute
Contributing to the Celo ecosystem through open-source projects is a valuable way to support public goods and connect with the community. Whether you're new to open-source or an experienced contributor, the guidelines below will help you get started.
For quick questions, chat with the assistant in the docs or reach out in the [Celo Discord](https://discord.com/invite/celo). Please avoid filing an issue on GitHub just to ask a question; using the resources above will provide faster responses.
### Prerequisites
To contribute to Celo, the following accounts are necessary:
* [GitHub:](https://github.com/celo-org) Required for raising issues, contributing code, or editing documentation.
* [Discord:](https://discord.com/invite/celo) Required for engaging with the Celo community.
### Getting Started
Browse the [code](https://github.com/celo-org), raise an issue, or contribute a pull request.
Look for issues that are tagged as "[good first issue](https://github.com/search?q=org%3Acelo-org+is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22\&type=issues)", "[help wanted](https://github.com/search?q=org%3Acelo-org+is%3Aissue+is%3Aopen+label%3A%22help+wanted%22\&type=issues)", or "[1 hour tasks](https://github.com/search?q=org%3Acelo-org+is%3Aissue+is%3Aopen+label%3A%221+hour+tasks%22\&type=issues)". These labels will help you find appropriate starting points. If you want to dive deeper, explore other labels and TODOs in the code.
### Working On An Issue
1. Reach out to the repository maintainer to assign you to the issue.
2. Add a comment outlining your plan and timeline.
3. If someone is already assigned, check with the repo maintainer if they are still working on it.
4. Ensure no duplicate issues exist for the work you're planning.
### Submitting Issues
If you're interested in creating a new issue, first explore existing projects and ensure that the issue doesn't already exist. When submitting a new issue, follow these guidelines:
1. Ensure the issue is placed in the correct repository.
2. Provide a clear and specific title.
3. Include a comprehensive description outlining the current and expected behavior.
4. Add relevant labels to categorize the issue.
Tasks range from minor to major improvements. Based on your interests, skillset, and level of comfort with the code-base feel free to contribute where you see appropriate. Our only ask is that you follow the guidelines below to ensure a smooth and effective collaboration.
## Contribution Workflow
Celo uses a standard "contributor workflow" where changes are made through pull requests (PRs). This workflow enables peer review, easy testing, and social collaboration.
Following these guidelines will help ensure that your pull request (PR) gets approved. Each protocol may have its own specific guidelines, so review them before contributing. Celo-specific contribution guidelines can be found [here](./overview.md).
1. Fork the repository. Make sure you also [add an upstream](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork) to be able to update your fork.
2. Clone your fork to your computer.
3. Create a topic branch and name it appropriately. Starting the branch name with the issue number is a good practice and a reminder to fix only one issue in a Pull-Request (PR).
4. **Make your changes** adhering to the coding conventions described below. In general, a commit serves a single purpose and diffs should be easily comprehensible. For this reason do not mix any formatting fixes or code moves with actual code changes.
5. Commit your changes. See [How to Write a Git Commit Message](https://cbea.ms/git-commit/) article by Chris Beams.
6. Test your changes locally before pushing to ensure that what you are proposing is not breaking another part of the software. Check the repository for the needed tests. Your PR should contain unit and end-to-end tests and a description of how these were run.
7. Include changes to relevant documentation.. You should update the documentation based on your changes.
8. Push your changes to your remote fork (usually labeled as origin).
9. Create a pull-request (PR) on the repository. If it's not ready to review, make it a `Draft` PR. If the PR addresses an existing issue, include the issue number in the PR title in square brackets (for example, \[#2374]).
10. Provide a **comprehensive description** of the problem addressed and changes made. Explain dependencies and backwards incompatible changes.
11. Add labels to identify the type of your PR. For example, if your PR fixes a bug, add the "bug" label.
12. If the PR address an existing issue, comment in the issue with the PR number.
13. Ensure your changes are reviewed. Request the appropriate reviewers. When in doubt, consult the CODEOWNERS file for suggestions.Let the project you are contributing to know in the issue comments on GitHub or using the Discord sever chat channels that your PR is ready for review. If you are a maintainer, you can choose reviewers, otherwise this will be done by one of the maintainers.
14. **Make any required changes** on your contribution from the reviewers' feedback. Make the changes, commit to your branch, and push to your remote fork.
15. When your PR is approved, validated, all tests pass and your branch has no conflicts, it can be merged. Again, this action needs to be done by a maintainer - usually the same person who approves will also merge it.
You contributed to Celo! Congratulations and thanks!
If you've commented on an existing issue and have been waiting for a reply, or want to message us for any other reason, please use the [Celo Forum](https://forum.celo.org/) or [Discord](https://chat.celo.org/).
# Documentation Contributors
Source: https://docs.celo.org/contribute-to-celo/contributors/documentation-contributors
Help improve the Celo ecosystem by contributing to documentation and educational resources.
## Why Documentation Matters
Documentation contributors play a vital role in the Celo ecosystem by creating clear, accessible resources that help users, developers, and community members understand and use Celo technology. High-quality documentation is essential for adoption, education, and the overall growth of the ecosystem.
Good documentation:
* **Lowers barriers to entry** for newcomers
* **Improves developer experience** and productivity
* **Empowers users** to solve problems independently
* **Supports the community** by reducing the support burden
* **Helps explain** Celo's vision and technical implementation
## How You Can Contribute
There are many ways to improve Celo documentation, regardless of your technical expertise:
### 1. Technical Documentation
* Protocol specifications and architecture guides
* Integration guides and code samples
### 2. Documentation Maintenance
* Update outdated information
* Fix broken links and references
* Improve organization and navigation
* Enhance readability and clarity
## Getting Started
### Edit an existing page
To edit an existing page in the documentation:
1. Fork the [Celo Docs repository](https://github.com/celo-org/docs)
2. Create a branch naming it after the changes you want to make
3. Write a clear commit message describing your changes
4. Create a Pull Request (PR)
5. Describe your changes in the PR
6. Tag appropriate reviewers
7. Wait for approval and for the site build checks to pass before merging
### Add/remove pages
To add a new page to the documentation:
1. Fork the [Celo Docs repository](https://github.com/celo-org/docs)
2. Add or delete pages in the appropriate location
3. Create a PR with your changes for the live version of the site
4. Update the "docs.json" file in the main folder:
* This file controls the navigation menu on the left side of the docs site
* Add or remove the appropriate files from the list
### Content Guidelines
When creating or editing documentation:
* **Be accurate**: Verify all information, examples, and code snippets
* **Be clear**: Use simple language and avoid unnecessary jargon
* **Be comprehensive**: Cover topics thoroughly but concisely
* **Be structured**: Use proper headings, lists, and formatting
* **Be inclusive**: Write for a global audience with diverse backgrounds
* **Be helpful**: Anticipate questions and provide helpful resources
For questions, comments, and discussions please use the [Celo Forum](https://forum.celo.org/) or [Discord](https://chat.celo.org/).
# Celo Contributor Overview
Source: https://docs.celo.org/contribute-to-celo/contributors/overview
Celo is open source and welcomes participation from everyone. We strive to be inclusive and empowering. All contributors must abide by Celo's [Code of Conduct](https://celo.org/code-of-conduct).
## Ways to Contribute
Our community welcomes contributors with diverse skills:
* [**Code Contributors**](/contribute-to-celo/contributors/code-contributors) - Developers who improve Celo's protocol and infrastructure
* [**CIP Contributors**](/contribute-to-celo/contributors/cip-contributors) - Authors of Celo Improvement Proposals
* [**Documentation Contributors**](/contribute-to-celo/contributors/documentation-contributors) - Writers who create and maintain technical documentation
## General Contribution Guidelines
Whether you're contributing code, documentation, or other content, these principles apply:
* **Fork the repository** - Always work in your own fork before submitting changes
* **Use PRs for changes** - Pull requests are preferred, especially for small changes like typos
* **Work in branches** - Use feature branches, not master/main, for ongoing work
* **Submit regularly** - For non-trivial work, submit PRs regularly to get feedback
* **Quality matters** - Double-check your work before submission
* **Be objective** - Remain fact-based and neutral in tone
## PR Best Practices
For effective contributions:
* Create meaningful PRs with clear descriptions
* For works in progress, use "WIP" in the title
* Request appropriate reviewers (check CODEOWNERS when unsure)
* Explain dependencies and breaking changes
* Include relevant tests and documentation updates
For questions or discussions, use the [Celo Forum](https://forum.celo.org/) or [Discord](https://chat.celo.org/).
# Celo Regional DAOs
Source: https://docs.celo.org/contribute-to-celo/daos
As of March 2025, the **Regional DAOs** have established a **Regional Council** to coordinate shared funding and enhance collaboration with the Celo Foundation.
You can read more in the latest proposal: [Celo Regional Council H1 2025](https://forum.celo.org/t/celo-regional-council-h1-2025/10063).
The **landscape of Regional DAOs is constantly evolving**, so stay updated by following discussions in the **[Celo Forum](https://forum.celo.org/)**.
Regional DAOs are community-driven organizations that operate autonomously, focusing on local development and empowering communities to use and build on Celo. Explore the many ways to get involved.
***
## How Regional DAOs Are Furthering Celo's Mission
Regional DAOs have been an essential part of Celo's growth. They onboard builders, developers and users into the ecosystem by hosting IRL events, providing mentorship and governance.
Each regional DAO has a different focus which might change over time, but the general idea is to further Celo's mission for Prosperity for All on the ground.
### Celo Africa DAO
Celo Africa DAO, [launched in April 2023](https://forum.celo.org/t/celo-africa-dao-report-may-june-july/6385) , has been building a huge network of builders and founders on the ground in Africa and was able to maintain and grow it through showing up consistently. If you live in one of the listed countries below, make sure to connect and to try joining one of the IRL events. Read up on the reports and proposals in the [Celo Forum](https://forum.celo.org/u/celoafricadao/summary).
Reach out to the main DAO or the chapters on [Twitter](https://x.com/CeloAfricaDao) or [Telegram](https://t.me/CeloAfrica).
#### Local Chapters
* [Celo Ghana](https://x.com/Celo_Ghana)
* [Celo Kenya](https://x.com/CeloKenya)
* [Celo Nigeria](https://x.com/CeloNigeria)
* [Celo South Africa](https://x.com/CeloSouthAfrica)
* [Celo Uganda](https://x.com/CeloUganda)
### Celo Europe DAO
Celo Europe DAO launched in [June 2023](https://forum.celo.org/t/celo-europe-dao-s0-report/7050) , has been hosting events and fostering the community around ReFi and RWA protocols as well as Celo Gather and supporting other Ecosystem DAOs with similar events. Read up on the reports and proposals in the [Celo Forum](https://forum.celo.org/search?q=celo%20europe%20dao).
* [Twitter](https://x.com/CeloEurope)
### Koh Celo (Celo Thailand DAO) DAO
Koh Celo has been launched in the [beginning of 2024](https://forum.celo.org/t/kohcelo-celo-thailand-dao-project-for-road-to-devcon-h1-2024-regional-dao-final/7402) , starting off by proposing a program for the Road to DevCon 2024. Read up on the reports and proposals in the [Celo Forum](https://forum.celo.org/search?q=KohCelo).
* [Twitter](https://x.com/KohCelo)
### CeLatam
CeLatam has been launched in the [April 2023](https://forum.celo.org/t/celatam-season-0-report/7870) , starting off by proposing a program for the Road to DevCon 2024. Read up on the reports and proposals in the [Celo Forum](https://forum.celo.org/u/celatam/summary).
Reach out to them on [Twitter](https://x.com/CeLatamOrg).
### Celo Columbia
Reach out to them on [Twitter](https://x.com/Celo_Col).
### Celo Mexico
Reach out to them on [Twitter](https://x.com/celomexico).
### Celo PH DAO
Reach out to them on [Twitter](https://x.com/celophdao).
### Celo Korea
Reach out to them on [Twitter](https://x.com/CeloKorea).
### Celo Türkiye
Reach out to them on [Twitter](https://x.com/TrCelo).
### Celo Arabia
Reach out to them on [Twitter](https://x.com/CeloArabia).
### Celo India
Reach out to them on [Twitter](https://x.com/Celo_India).
## Get Involved with Regional DAOs
By participating in a Regional DAO, you can contribute to the growth of the Celo ecosystem in your local area. Each DAO offers opportunities for developers, entrepreneurs, and community members to collaborate, share ideas, and drive impactful projects. Explore your region’s DAO to see how you can get involved and help further Celo’s mission of financial inclusion and sustainability.
For more information on how to join or collaborate with a Regional DAO, visit the [Celo Forum](https://forum.celo.org/) or [Discord](https://discord.com/invite/celo) to connect with the community.
# Joining Celo
Source: https://docs.celo.org/contribute-to-celo/index
Explore the many ways to engage with the Celo ecosystem and contribute to its growth.
Welcome to the Celo Ecosystem! Whether you're a user, developer, founder, or contributor, there are numerous ways to engage and make a meaningful impact. This guide will help you explore the various opportunities available within the Celo community, from using innovative applications to contributing to open-source projects, and participating in governance. Dive in to discover how you can be a part of Celo's mission to create a more inclusive financial system.
### As a User
* [**Explore Projects on Celo:**](https://celo.org/ecosystem) Start using and engaging with Celo apps.
* [**Follow updates from the Celo Foundation on Twitter**](https://x.com/Celo)
### As a Builder
* **Register your project** in our [ecosystem database](https://www.karmahq.xyz/community/celo) and get ready to apply for [ecosystem builder and grant programs.](https://www.celopg.eco/programs)
* [**Join our builder community:**](/contribute-to-celo/builders) Connect with other builders in the ecosystem.
* [**Contribute to open source projects:**](/contribute-to-celo/contributors/code-contributors) Help grow Celo by contributing to key projects.
* [**Get involved in a local chapter:**](/contribute-to-celo/daos) Attend in-person workshops for mentoring and support.
* [**Participate in Celo Public Goods:**](https://www.celopg.eco/) Explore ongoing funding rounds.
* **Introduce your project** in the [**Celo Forum**](https://forum.celo.org/) in the founders' category.
* [**Apply to Celo Camp:**](https://www.celocamp.com/) Join the accelerator focused on scaling apps on Opera MiniPay.
* **Explore grant opportunities:** Apply for [Prezenti Grants](https://www.prezenti.xyz/) .
### As a Contributor
* [**Participate in governance:**](/home/protocol/governance/overview) Engage in current discussions and connect with the ecosystem.
* [**Participate in the community:**](https://calendar.google.com/calendar/u/0/r?cid=c_asn0b4c1emdgsq3urlh2ei2dig@group.calendar.google.com) Add the Community Calendar
* [**Contribute to local chapters:**](/contribute-to-celo/daos) Connect with the community, offer support, and mentor others.
* [**Sign up for Celo Signal:**](https://share.hsforms.com/1Qrhush1vSA2WIamd_yL4ow53n4j) If you are a Node Operator, Dapp Running Its Own Node, Exchange or Custodian, Owner who is Staking and Participating in Governance, or a Core Developer or Contributor
***
## Social Media
Follow to stay updated with the latest news about Celo.
* [Celo on X](https://x.com/Celo)
* [Celo Devs on X](https://x.com/CeloDevs)
* [cLabs on X](https://x.com/cLabs)
* [Farcaster](https://farcaster.xyz/celo)
* [Reddit](https://www.reddit.com/r/celo/)
* [GitHub](https://github.com/celo-org)
* [Medium Blogs](https://medium.com/@celoorg)
* [LinkedIn](https://www.linkedin.com/company/celo-foundation)
* [Instagram](https://www.instagram.com/celoorg/)
* [YouTube](https://www.youtube.com/@CeloOrg)
## Discussions
Ask questions, find answers, and connect with the community.
* [Celo Developer Chat on Discord](https://chat.celo.org/)
* [Celo Official Telegram](https://t.me/celoplatform)
* [Celo Builder Telegram](https://t.me/buildwithcelo)
* [Celo Forum](https://forum.celo.org/)
* [Celo Subreddit](https://www.reddit.com/r/celo/)
# Attestation Service Release Process
Source: https://docs.celo.org/contribute-to-celo/release-process/attestation-service
Details of the release process for updating the attestation service on the Celo platform.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
This release process is currently in use.
## Versioning
Releases of Attestation Service are made as needed. Releases are numbered according to semantic versioning, as described at [semver.org](https://semver.org).
Development builds should be identified with `-dev`, and only one commit should exist with a released version `x.y.z` for any `(x, y, z)`.
## Documentation
Documentation is maintained in the [celo-org/docs](https://github.com/celo-org/docs) repo and is hosted on [docs.celo.org](/).
## Identifying releases
### Git branches
Development is done on the `master` branch, which corresponds to the next major or minor version. Changes to be included in a patch release of an existing minor version are cherry-picked to that existing release branch.
### Git tags
Each release should be [created on Github](https://github.com/celo-org/celo-monorepo/releases) and tagged with the version number, e.g. `attestation-service-vX.Y.Z`. Each release should include a summary of the release contents, including links to pull requests and issues with detailed description of any notable changes.
Tags should be signed and can be verified with the following command.
```bash theme={null}
git verify-tag attestation-service-vX.Y.Z
```
On Github, each release tag should have attached signatures that can be used to verify the Docker images.
### Docker tags
Each Docker image is tagged with `attestation-service-`. Just as a Git tag immutably points to a commit hash, the Docker tag should immutably point to an image hash.
In addition, each Docker image corresponding to a released version should be tagged with `attestation-service-vX.Y.Z`.
The latest image qualified for deployment to various networks are also tagged as follows:
* Alfajores: `attestation-service-alfajores`
* Baklava: `attestation-service-baklava`
* Mainnet: `attestation-service-mainnet`
### Signatures
Artifacts produced by this build process (e.g. tags, Docker images) will be signed by a [core developer key](https://github.com/celo-org/celo-monorepo/blob/master/developer_key_publishing.md).
Public keys for core developers are hosted on celo.org and can be imported to `gpg` with the following command:
```bash theme={null}
gpg --auto-key-locate wkd --locate-keys $EMAIL
```
Currently hosted core developer keys used for Attestation Service releases include:
* [tim@clabs.co](mailto:tim@clabs.co)
## Build process
### Docker images
Docker images are built automatically with [Google Cloud Build](https://cloud.google.com/build) upon pushes to `master` and all release branches. Automated builds will be tagged in [Google Artifact Registry](https://cloud.google.com/artifact-registry) with the corresponding commit hash.
A signature should be produced over the image automatically built at the corresponding commit hash and included with the Github release.
Release image signatures can be verified with the following command:
```bash theme={null}
docker save $(docker image inspect us.gcr.io/celo-testnet/celo-monorepo:attestation-service-vX.Y.Z -f '{{ .Id }}') | gpg --verify attestation-service-vX.Y.Z.docker.asc -
```
## Testing
As well as monorepo CI tests, all releases are expected to go through manual testing as needed to verify security properties, accuracy of documentation, and compatibility with deployed and anticipated versions of `celocli` and wallets including Valora. Releases currently involve coordinating with Valora to run the verification e2e tests in CI.
## Promotion process
### Source control
Patch releases should be constructed by cherry-picking all included commits from `master` to the `release/attestation-service/x.y` branch, if necessary created from the `attestation-service-vX.Y.Z` tag of the most recent major or minor release. The first commit of this process should change the version number encoded in the source from `x.y.z` to `x.y.z+1-dev` and the final commit should change the version number to `x.y.z+1`.
Major and minor releases should be constructed by pushing a commit to the `master` branch to change the encoded version number from `x.y.z-dev` to `x.y.z`. A `attestation-service-vX.Y.Z` tag should be created at this commit which uniquely references one commit; release notes should be published alongside this. The next commit should change the version number from `x.y.z` to `x.y+1.0-dev`, or `x+1.0.0-dev` if the next planned release is a major release.
### Distribution
Distribution of an image follows this schedule:
Date
Action
T-1w
Deploy release candidate build to Alfajores testnet
Test manually and via e2e verification tests
T
Confirm Valora production and testing builds against Alfajores experience no issues and that e2e verification tests complete successfully
Publish the release notes and tag the relevant commit on GitHub
Tag released Docker image with attestation-service-alfajores, attestation-service-baklava, attestation-service-mainnet, and attestation-service-vX.Y.Z tags (removing tags from other releases)
Inform the community of the new release via Discord and the Celo Forum
T+1w onwards
Confirm Mainnet services have upgraded without issues
Continue monitoring dashboards for user issues
### Emergency Patches
Bugs which affect the security, stability, or core functionality of the Celo identity protocol or prevent new users onboarding to wallets including Valora may need to be released outside the standard release cycle. In this case, an emergency patch release should be created on top of all supported minor releases which contains the minimal change and corresponding test for the fix.
If the issue is not exploitable, release notes should describe the issue in detail and the image should be distributed publicly.
If the issue is exploitable and mitigations are not readily available, a patch should be prepared privately and signed binaries should be distributed from private commits. Establishing trust is key to pushing out the fix. An audit from a reputable third party may be contracted to verify the release to help earn that trust.
## Vulnerability Disclosure
Vulnerabilities in Attestation Service releases should be disclosed according to the [security policy](https://github.com/celo-org/celo-blockchain/blob/master/SECURITY.md).
# Release Process for CeloCLI and ContractKit
Source: https://docs.celo.org/contribute-to-celo/release-process/base-cli-contractkit-dappkit-utils
Details of the release process for updating CeloCLI and ContractKit on the Celo platform.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
## Versioning
Use the standard MAJOR.MINOR.PATCH semantic versioning scheme described at [semver.org](https://semver.org).
New releases can be expected as follows:
* Major releases: approximately yearly
* Minor releases: approximately 8 times a year
* Patch releases: as needed
Development builds will be identified as such: `x.y.z-dev`, and will be published as `x.y.z` when stable.
## Identifying releases
### NPM
You can find the npm packages in the following places:
* [@celo/celocli](https://www.npmjs.com/package/@celo/celocli)
* [@celo/contractkit](https://www.npmjs.com/package/@celo/contractkit)
### Github tags
To identify the commits included in a specific release and see which new features were added or bugs fixed, please refer to the [release notes](https://github.com/celo-org/celo-monorepo/releases) in the monorepo. Also to keep track of continual updates to the stable and dev versions of the packages, each package has a `CHANGELOG.md` file: [Celocli](https://github.com/celo-org/developer-tooling/blob/master/packages/cli/CHANGELOG.md) and [Contractkit](https://github.com/celo-org/developer-tooling/blob/master/packages/sdk/contractkit/CHANGELOG.md).
All releases should be tagged with the version number, e.g. `contractkit-vX.Y.Z`. Each release should include a summary of the release contents, including links to pull requests and issues with detailed description of any notable changes.
### Communication
The community will be notified of package updates through the following channels:
For all releases:
* Each package’s `CHANGELOG.md` file, as mentioned above
* Github releases page, as mentioned above
* [Discord](https://chat.celo.org): #developer-news
For major releases:
* Twitter: [@cLabs](https://x.com/cLabs)
* Mailing list: cLabs’ Tech Sync
* [Celo Forum](https://forum.celo.org/)
## Testing
All builds of these packages are automatically tested for performance and backwards compatibility in CI. Any regressions in these tests should be considered a blocker for a release.
Minor and major releases are expected to go through additional rounds of manual testing as needed to verify behavior under stress conditions.
Work in progress
## Promotion process
* For a patch release: The first step of this process should be a commit that changes the version number encoded in the source from `x.y.z-dev` to `x.y.z+1-dev` and the final step should change the published version number from `x.y.z-1` to `x.y.z`.
* For minor releases, the same process should be followed, except the `y` value would increment, and the `z` value would become 0.
* For major releases, the same process should be followed, except the `x` value would increment, and `y` and `z` values would become 0.
Only one commit should ever have a non-dev tag at any given version number. When that commit is created, a tag should be added along with release notes. Once the tag is published it should not be reused for any further release or changes.
### Emergency patches
Bugs which affect the security, stability, or core functionality of the network may need to be released outside the standard release cycle. In this case, an emergency patch release should be created on top of all supported minor releases which contains the minimal change and corresponding test for the fix. An emergency patch retro will also be published, and will include information such as why the patch was necessary and what code changes it includes.
## Vulnerability Disclosure
Vulnerabilities in any of these releases should be disclosed according to the [security policy](https://github.com/celo-org/celo-blockchain/blob/master/SECURITY.md).
## Dependencies
* @celo/mobile - Dappkit relies on this
* Celocli
* All the packages under the ["SDK" folder](https://github.com/celo-org/developer-tooling/tree/master/packages/sdk) -- These all rely on each other quite a bit, so triple-check that these packages weren’t affected by a change in another.
# Blockchain Client Release Process
Source: https://docs.celo.org/contribute-to-celo/release-process/blockchain-client
Details of the release process for updating the blockchain client on the Celo platform.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
## Versioning
Releases of celo-blockchain are numbered according to semantic versioning, as described at [semver.org](https://semver.org).
All builds are identified as `unstable` (a development build) or `stable` (a commit released as a particular version number). There should only ever exist one commit with a version `x.y.z-stable` for any `(x, y, z)`.
### Signatures
Artifacts produced by this build process (e.g. Docker images) will be signed by [cosign](https://github.com/sigstore/cosign).
## Documentation
The documentation for client features, such as APIs and commands, is maintained in the `docs` directory within the `celo-blockchain` repository. Documentation on protocol features, such as the proof-of-stake protocol, is hosted on [docs.celo.org]().
## Identifying releases:
### Git branches
Each minor version of celo-blockchain has its own “release branch”, e.g. `release/1.0`.
Development is done on the `master` branch, which corresponds to the next major or minor version. Changes to be included in a patch release of an existing minor version are cherry-picked to that existing release branch.
### Git tags
All releases should be tagged with the version number, e.g. `vX.Y.Z`. Each release should include a
summary of the release contents, including links to pull requests and issues with detailed
description of any notable changes.
Tags should be signed and can be verified with the following command.
```bash theme={null}
git verify-tag vX.Y.Z
```
On Github, each release tag should link to the respective Docker image, along with signatures that
can be used to verify those images.
### Docker tags
Each released Docker image should be tagged with its version number such that for release `x.y.z`, the image should have tags `x`, `x.y`, and `x.y.z`, with the first two tags potentially being moved from a previous image. Just as a Git tag `x.y.z` immutably points to a commit hash, the Docker tag, `x.y.z` should immutably point to an image hash.
## Build process
### Docker images
Docker images are built automatically with [Google Cloud Build](https://cloud.google.com/build) upon pushes to `master` and all release branches. Automated builds will be tagged in [Google Artifact Registry](https://cloud.google.com/artifact-registry) with the corresponding commit hash.
A signature should be produced over the image automatically built at the corresponding commit hash and included with the GitHub release.
Release image signatures can be verified with the following command:
```bash theme={null}
docker save $(docker image inspect us.gcr.io/celo-org/geth:X.Y.Z -f '{{ .Id }}') | gpg --verify celo-blockchain-vX.Y.Z.docker.asc -
```
## Testing
All builds of `celo-blockchain` are automatically tested for performance and backwards compatibility in CI. Any regressions in these tests should be considered a blocker for a release.
Minor and major releases are expected to go through additional rounds of manual testing as needed to verify behavior under stress conditions, such as a network with faulty nodes, and poor network connectivity.
## Promotion process
### Source control
Patch releases should be constructed by cherry-picking all included commits from `master` to the `release/x.y` branch. The first commit of this process should change the version number encoded in the source from `x.y.z-stable` to `x.y.z+1-unstable` and the final commit should change the version number to `x.y.z+1-stable`.
Major and minor releases should be constructed by pushing a commit to the `master` branch to change the encoded version number from `x.y.z-unstable` to `x.y.z-stable`. A `release/x.y` branch should be created from this commit. The next commit must change the version number from `x.y.z-stable` to `x.y+1.0-unstable`, or `x+1.0.0-unstable` if the next planned release is a major release.
Only one commit should ever have a “stable” tag at any given version number. When that commit is created, a tag should be added along with release notes. Once the tag is published it should not be reused for any further release or changes.
### Emergency Patches
Bugs which affect the security, stability, or core functionality of the network may need to be released outside the standard release cycle. In this case, an emergency patch release should be created on top of all supported minor releases which contains the minimal change and corresponding test for the fix.
If the issue is not exploitable, release notes should describe the issue in detail and the image should be distributed publicly.
If the issue is exploitable and mitigations are not readily available, a patch should be prepared privately, and signed binaries should be distributed from private commits. Establishing trust is key to pushing out the fix. An audit from a reputable third party may be contracted to verify the release to help earn that trust. Once a majority of validators are updated, patch details can be made public.
> Pushing an upgrade with this process will be disruptive to any nodes that do not upgrade quickly. It should *only* be used when the circumstances require it.
## Vulnerability Disclosure
Vulnerabilities in `celo-blockchain` releases should be disclosed according to the [security policy](https://github.com/celo-org/celo-blockchain/blob/master/SECURITY.md).
# Release Process
Source: https://docs.celo.org/contribute-to-celo/release-process/index
Overview of the release process for updates to the Celo platform.
It is critical that updates to the Celo platform can be released on a regular basis, and in a way that ensures the security and reliability of the Celo network. In order to facilitate this, the following release processes are published here.
* [Smart Contracts](/contribute-to-celo/release-process/smart-contracts)
* [Blockchain Client](/contribute-to-celo/release-process/blockchain-client)
* [CeloCLI and ContractKit](/contribute-to-celo/release-process/base-cli-contractkit-dappkit-utils)
* [Attestation Service](/contribute-to-celo/release-process/attestation-service)
# Smart Contracts Release Process
Source: https://docs.celo.org/contribute-to-celo/release-process/smart-contracts
Details of the release process for updating smart contracts on the Celo platform.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
This release process is a work in progress. Many infrastructure components required to execute it are not in place, and the process itself is subject to change.
## Versioning
Each deployed Celo core smart contract is versioned independently, according to semantic versioning, as described at [semver.org](https://semver.org), with the following modifications:
* STORAGE version when you make incompatible storage layout changes
* MAJOR version when you make incompatible ABI changes
* MINOR version when you add functionality in a backwards compatible manner, and
* PATCH version when you make backwards compatible bug fixes.
Changes to core smart contracts are made via on-chain Governance, approximately four times a year. When a release is made, **all** smart contracts from the release branch that differ from the deployed smart contracts are released, and included in the **same** governance proposal. Each release is identified by a unique monotonically increasing version number `N`, with `1` being the first release.
### Core Contracts
Every deployed Celo core contract has its current version number as a constant which is publicly accessible via the `getVersionNumber()` function, which returns the storage, major, minor, and patch versions. The version number is encoded in the Solidity source and updated as part of code changes.
Celo Core Contracts deployed to a live network without the `getVersionNumber()` function, such as the original set of core contracts, are to be considered version `1.1.0.0`.
### Mixins and libraries
Mixin contracts and libraries are considered part of the contracts that consume them. When a mixin or library has changed, all contracts that consume them should be considered to have changed as well, and thus the contracts should have their version numbers incremented and should be re-deployed as part of the next smart contract release.
### Initialize Data
Whenever Celo Core Contracts need to be re-initialized, their initialization arguments should be checked into version control under `packages/what-is-celo/about-celo-l1/protocol/releaseData/initializationData/release${N}.json`.
### Release management in Git/Github
Github branches/tags and Github releases are used to coordinate past and ongoing releases. Ongoing smart contract development is done on the `master` branch (even after release branches are cut). Every smart contract release has a designated release branch, e.g. `release/core-contracts/${N}` in the celo-monorepo.
#### When a new release branch is cut:
1. A new release branch is created `release/core-contracts/${N}` with the contracts to be audited.
2. The latest commit on the release branch is tagged with `core-contracts.v${N}.pre-audit`.
3. On Github, a pre-release Github release should be created pointing at the latest tag on the release branch.
4. On master branch, `.circleci/config.yml` should be edited so that the variable `RELEASE_TAG` points to the tag `celo-core-contracts-v${N}.pre-audit` so that all future changes to master are versioned against the new release.
5. Ongoing audit responses/fixes should continue to go into `release/celo-core-contracts/${N}`.
#### After a completed release process:
1. The release branch should be merged into `master` with a merge commit (instead of the usual squash merge strategy).
2. On master branch, `.circleci/config.yml` should be edited so that the variable `RELEASE_TAG` points to the tag `core-contracts.v${N}`
## Release Process
There are several scripts provided (under `packages/protocol` in [celo-org/celo-monorepo](https://github.com/celo-org/celo-monorepo) and via [celocli](/cli/)) for use in the release process and with contract upgrade governance proposals to give participating stakeholders increased confidence.
For these to run, you may need to set up the celo-monorepo: follow the [Getting Started](https://github.com/celo-org/celo-monorepo/blob/045aa0061/README.md#-getting-started) steps and install the Node version pinned in [`.nvmrc`](https://github.com/celo-org/celo-monorepo/blob/045aa0061/.nvmrc) (managed with `nvm`). A successful `yarn install` and `yarn build` in the protocol package signal a completed setup.
Using these tools, a contract release candidate can be built, deployed, and proposed for upgrade automatically on a specified network. Subsequently, stakeholders can verify the release candidate against a governance upgrade proposal's contents on the network.
Typical script options:
* By default, the scripts expect a celo-blockchain RPC at port 8545 locally. With `-f` you can specify the scripts to use a hosted forno node
* By default, scripts will output verbose logs under `/tmp/celo-${script-name}.log`. You can change the location of the log output with `-l file.log`
### View the tagged releases for each network
```bash theme={null}
yarn tags:view
```
### Verify the previous Release on the Network
`release:verify-deployed` is a script that allows you to assess whether the bytecode on the given network matches the source code of a particular commit. It will run through the Celo Core Contracts and verify that the contracts' bytecodes as specified in the `Registry` match. Here, we will want to sanity-check that our network is running the previous release's audited commit.
```bash theme={null}
# Run from `packages/protocol` in the celo-monorepo
PREVIOUS_RELEASE="core-contracts.v${N-1}"
NETWORK=${"anvil"|"celo-sepolia"|"mainnet"}
# A -f boolean flag can be provided to use a forno full node to connect to the provided network
yarn release:verify-deployed -n $NETWORK -b $PREVIOUS_RELEASE -f
```
A `libraries.json` file is written to disk only necessary for `release:make` that describes linked library addresses.
### Check Backward Compatibility
This script performs some automatic checks to ensure that the smart contract versions in the source code have been set correctly with respect to the latest release. It is run as part of CI and helps ensure that backwards incompatibilities are not accidentally introduced by requiring that devs manually update version numbers whenever smart contract changes are made.
Specifically, it compiles the latest and candidate releases and compares smart contracts:
1. Storage layout, to detect storage version changes
2. ABI, to detect major and minor version changes
3. Bytecode, to detect patch version changes
Finally, it checks release candidate smart contract version numbers and requires that they have been updated appropriately since the latest release by following semantic versioning as defined in the [Versioning section](#versioning) above.
The following exceptions apply:
* If the STORAGE version has changed, it does not perform backward compatibility checks
* If the MAJOR version has changed, it checks storage layout compatibility but not ABI compatibility
Critically, this ensures that proxied contracts do not experience storage
collisions between implementation versions. See [this
article](https://docs.openzeppelin.com/upgrades-plugins/proxies#storage-collisions-between-implementation-versions)
by OpenZeppelin for a good overview of this problem and why it's important to
check for it.
The script generates a detailed report on version changes in JSON format.
```bash theme={null}
PREVIOUS_RELEASE="core-contracts.v${N-1}"
RELEASE_CANDIDATE="core-contracts.v${N}"
yarn release:check-versions -a $PREVIOUS_RELEASE -b $RELEASE_CANDIDATE -r "report.json"
```
This should be used in tandem with `release:verify-deployed -b $PREVIOUS_RELEASE -n $NETWORK` to ensure the compatibility checks compare the release candidate to what is actually active on the network.
### Deploy the release candidate
Use the following script to build and deploy a candidate release. This takes as input the corresponding backward compatibility report and canonical library address mapping to deploy **changed** contracts to the specified network. (Use `-d` to dry-run the deploy).
STORAGE updates are adopted by deploying a new proxy/implementation pair. This script outputs a JSON contract upgrade governance proposal.
```bash theme={null}
NETWORK=${"anvil"|"celo-sepolia"|"mainnet"}
RELEASE_CANDIDATE="core-contracts.v${N}"
yarn release:make -b $RELEASE_CANDIDATE -n $NETWORK -r "report.json" -i "releaseData/initializationData/release${N}.json" -p "proposal.json" -l "libraries.json"
```
The proposal encodes STORAGE updates by repointing the Registry to the new proxy. Storage compatible upgrades are encoded by repointing the existing proxy's implementation.
### Submit Upgrade Proposal
Submit the autogenerated upgrade proposal to the Governance contract for review by voters, outputting a unique identifier.
```bash theme={null}
# resultant proposal ID should be communicated publicly
celocli governance:propose --deposit 100e18 --from $YOUR_ADDRESS --jsonTransactions "proposal.json" --descriptionURL https://github.com/celo-org/governance/blob/main/CGPs/cgp-0055.md
```
### Fetch Upgrade Proposal
Fetch the upgrade proposal and output the JSON encoded proposal contents.
```bash theme={null}
# Make sure you run at least celocli 0.0.60
celocli governance:show --proposalID --jsonTransactions "upgrade_proposal.json"
```
### Verify Proposed Release Candidate
This script serves the same purpose as `release:verify-deployed` but for a not-yet
accepted contract upgrade (in the form of the proposal.json you fetched in the step prior). It gives you the confidence that the branch specified in the `-b` flag in (same as `release:check-versions`) will be the resulting network state of the proposal if executed. It does so by going over all Celo Core Contracts and determining updates to the Registry pointers, proxy or implementation contracts and verifying their implied bytecode against the compiled source code.
Additionally, include `initialization_data.json` from the CGP if any of the contracts have to be initialized.
```bash theme={null}
RELEASE_CANDIDATE="core-contracts.v${N}"
NETWORK=${"anvil"|"celo-sepolia"|"mainnet"}
# A -f boolean flag can be provided to use a forno full node to connect to the provided network
yarn release:verify-release -p "upgrade_proposal.json" -b $RELEASE_CANDIDATE -n $NETWORK -f -i initialization_data.json
```
### Verify Executed Release
After a release executes via Governance, you can use `release:verify-deployed` again to check that the resulting network state does indeed reflect the tagged release candidate:
```bash theme={null}
RELEASE="core-contracts.v${N}"
NETWORK=${"anvil"|"celo-sepolia"|"mainnet"}
yarn release:verify-deployed -n $NETWORK -b $RELEASE -f
```
## Testing
All releases should be evaluated according to the following tests.
### Unit tests
All changes since the last release should be covered by unit tests. Unit test coverage should be enforced by automated checks run on every commit.
### Manual Checklist
After a successful release execution on a testnet, the resulting network state should be spot-checked to ensure that no regressions have been caused by the release. Flows to test include:
* Do a USDm and CELO transfer
```bash theme={null}
celocli transfer:dollars --from --value --to
celocli transfer:celo --from --value --to
```
* Register a Celo account
```bash theme={null}
celocli account:register --from --name
```
* Report an Oracle rate
```bash theme={null}
celocli oracle:report --from --value
```
* Do a CP-DOTO exchange
```bash theme={null}
celocli exchange:celo --value --from
celocli exchange:dollars --value --from
```
* Complete a round of attestation
* Redeem from Escrow
* Register a Vaildator
```bash theme={null}
celocli validator:register --blsKey --blsSignature --ecdsaKey --from
```
* Vote for a Validator
* Run a mock election
```bash theme={null}
celocli election:run
```
* Get a valildator slashed for downtime and ejected from the validator set
* Propose a governance proposal and get it executed
```bash theme={null}
celocli governance:propose --jsonTransactions --deposit --from --descriptionURL https://gist.github.com/yorhodes/46430eacb8ed2f73f7bf79bef9d58a33
```
### Automated environment tests
Stakeholders can use the `env-tests` package in `celo-monorepo` to run an automated test suite against the network
### Verify smart contracts
Verification of smart contracts should be done both on [https://celoscan.io/](https://celoscan.io/) and [https://celo.blockscout.com/](https://celo.blockscout.com/).
1. [Update your Smart Contract on celoscan](/developer/verify/celoscan)
2. [Update your Smart Contract on Blockscout](/developer/verify/blockscout)
### Performance
A ceiling on the gas consumption for all common operations should be defined and enforced by automated checks run on every commit.
For troubleshooting please see Readme.md of protocol package.
### Backwards compatibility
Automated checks should ensure that any new commit to `master` does not introduce a breaking change to storage layout, ABI, or other common backward compatibility issues unless the STORAGE or MAJOR version numbers are incremented.
Backwards compatibility tests will also be run before every release to confirm that no breaking changes exist between the pending release and deployed smart contracts.
### Audits
All changes since the last release should be audited by a reputable third party auditor.
### Emergency patches
If patches need to be applied before the next scheduled smart contract release, they should be cherry-picked to a new release branch, branched from the latest deployed release branch.
## Promotion process
Deploying a new contract release should occur with the following process. On-chain governance proposals should be submitted on Tuesdays for consistency and predictability.
Date
Action
T
Create a Github issue tracking all these checklist items as an audit
log
Let the community know about the upcoming release proposal by posting
details to the Governance category on [https://forum.celo.org](https://forum.celo.org) and cross
post in the
Discord #governance channel.
See the 'Communication guidelines' section below for information on what
your post should contain.
T+2w
Confirm all contracts working as intended on an Anvil testnet.
Run the
smart contract release script
in order to to deploy the contracts to Celo Sepolia as well as submit a
governance proposal.
Update your forum post with the Celo Sepolia PROPOSAL\_ID,
updated timings (if any changes), and notify the community in the
Discord #governance channel.
T+3w
Confirm all contracts working as intended on Celo Sepolia.
Confirm audit is complete and make the release notes and forum post
contain a link to it.
On Tuesday: Run the
smart contract release script
in order to to deploy the contracts to Mainnet as well as submit a
governance proposal.
Update the corresponding governance proposal with the updated on-chain
PROPOSAL\_ID and mark CGP status as "PROPOSED".
Update your forum post with the Mainnet PROPOSAL\_ID,
updated timings (if any changes), and notify the community in the
Discord #governance channel.
At this point all stakeholders are encouraged to
verify the proposed contracts
deployed match the contracts from the release branch.
Currently the governance process should take approximately 1 week:
24 hours for the dequeue process, 24 hours for the approval
process, and 5 days for the referendum process. After which, the
proposal is either declined or is ready to be executed within 3
days.
For updated timeframes, use the celocli:
celocli network:parameters
T+5w
If the proposal passed:
Confirm all contracts working as intended on Mainnet.
Update your forum post with the Mainnet governance outcome (
Passed or Rejected) and notify the
community in the Discord #governance channel.
Change corresponding CGP status to EXCECUTED.
Merge the release branch into master with a merge
commit
If the proposal failed:
Change corresponding CGP status to EXPIRED.
If the contents of the release (i.e. source Git commit) change at any point after the release has been tagged in Git, the process should increment the release identifier, and process should start again from the beginning. If the changes are small or do not introduce new code (e.g. reverting a contract to a previous version) the audit step may be accelerated.
### Communication guidelines
Communicating the upcoming governance proposal to the community is critical and may help getting it approved.
Each smart contract release governance proposal should be accompanied by a [Governance category](https://forum.celo.org/c/governance/) forum post that contains the following information:
* Name of proposer (individual contributor or organization).
* Background information.
* Link to the release on Github.
* Link to the audit report(s).
* Anticipated timings for the Celo Sepolia testnet and Mainnet.
Make sure to keep the post up to date. All updates (excluding fixing typos) should be communicated to the community in the [Discord](http://chat.celo.org/) `#governance` channel.
### Emergency patches
Work in progress
## Vulnerability Disclosure
Vulnerabilities in smart contract releases should be disclosed according to the [security policy](https://github.com/celo-org/celo-blockchain/blob/master/SECURITY.md).
## Dependencies
None
## Dependents
Work in progress
# Bridging
Source: https://docs.celo.org/home/bridged-tokens/bridges
Bridging allows users to transfer assets between the Celo network and other blockchain networks. This section provides an overview of available bridging and swapping options.
***
Be sure you understand and review the risks when bridging assets between chains.
## Bridging To and From Celo
### Popular Bridges
* [Squid Router V2](https://v2.app.squidrouter.com/?chains=10%2C42220\&tokens=0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee%2C0x471ece3750da237f93b8e339c536989b8978a438)
* [LayerZero](https://layerzero.network/)
* [Jumper Exchange](https://jumper.exchange/?fromChain=10\&fromToken=0x0000000000000000000000000000000000000000\&toChain=42220\&toToken=0x471EcE3750Da237f93B8E339c536989b8978a438)
* [Portal Bridge (Wormhole)](https://portalbridge.com/)
* [AllBridge](https://app.allbridge.io/bridge?from=ETH\&to=CELO\&asset=ABR)
* [Satellite (Axelar)](https://satellite.money/)
* [Transporter (Chainlink CCIP)](https://www.transporter.io/)
* [Mach Exchange](https://www.mach.exchange/)
### Gasless Bridges
* [SmolRefuel](https://smolrefuel.com/?outboundChain=42220)
### Native Bridges
Native bridging refers to the process of transferring assets directly between the L2 (Celo) and the underlying L1 (Ethereum) without the need for intermediary networks or tokens.
This method is designed to be more secure, efficient and cost-effective, leveraging the security and scalability of L2 solutions.
* [Superbridge Celo Mainnet](https://superbridge.app/celo)
* [Superbridge Celo Sepolia Testnet](https://testnets.superbridge.app/?fromChainId=11155111\&toChainId=11142220)
* [USDT0](https://usdt0.to/): 1:1 transfers of native USDT powered by the Layer Zero OFT. Best for moving USDT
Follow [this guide](/home/bridged-tokens/native-ETH-bridging) to learn how to bridge native ETH and have it auto-wrapped to WETH on Celo.
#### Natively Bridged Tokens on Mainnet
| Symbol | Token Name | Contract Addresses |
| ------ | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1INCH | 1INCH Token | L1: [0x111111111117dC0aa78b770fA6A738034120C302](https://etherscan.io/token/0x111111111117dC0aa78b770fA6A738034120C302) L2: [0x28ba8d26f5f6710f42170ee545a0c953ca4997b9](https://celoscan.io/token/0x28ba8d26f5f6710f42170ee545a0c953ca4997b9) |
| AAVE | Aave Token | L1: [0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9](https://etherscan.io/token/0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9) L2: [0xF6A54aff8c97f7AF3CC86dbaeE88aF6a7AaB6288](https://celoscan.io/token/0xF6A54aff8c97f7AF3CC86dbaeE88aF6a7AaB6288) |
| ACX | Across Protocol Token | L1: [0x44108f0223A3C3028F5Fe7AEC7f9bb2E66beF82F](https://etherscan.io/token/0x44108f0223A3C3028F5Fe7AEC7f9bb2E66beF82F) L2: [0x3a05ef6467309f388f90bcc3d79a522e6c39fabb](https://celoscan.io/token/0x3a05ef6467309f388f90bcc3d79a522e6c39fabb) |
| LINK | Chainlink | L1: [0x514910771af9ca656af840dff83e8264ecf986ca](https://etherscan.io/token/0x514910771af9ca656af840dff83e8264ecf986ca) L2: [0xf630876008a4ed9249fb4cac978ba16827f52e91](https://celoscan.io/token/0xf630876008a4ed9249fb4cac978ba16827f52e91) |
| CRV | Curve DAO Token | L1: [0xD533a949740bb3306d119CC777fa900bA034cd52](https://etherscan.io/token/0xD533a949740bb3306d119CC777fa900bA034cd52) L2: [0x75184c282e55a7393053f0b8F4F3E7BeAE067fdC](https://celoscan.io/token/0x75184c282e55a7393053f0b8F4F3E7BeAE067fdC) |
| crvUSD | Curve.Fi USD Stablecoin | L1: [0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E](https://etherscan.io/token/0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E) L2: [0x9efd56a126a0e3a8782db5fd5adb23a8dd9023c6](https://celoscan.io/token/0x9efd56a126a0e3a8782db5fd5adb23a8dd9023c6) |
| DAI | Dai Stablecoin | L1: [0x6B175474E89094C44Da98b954EedeAC495271d0F](https://etherscan.io/token/0x6B175474E89094C44Da98b954EedeAC495271d0F) L2: [0xac177de2439bd0c7659c61f373dbf247d1f41abe](https://celoscan.io/token/0xac177de2439bd0c7659c61f373dbf247d1f41abe) |
| DOLA | Dola USD Stablecoin | L1: [0x865377367054516e17014CcdED1e7d814EDC9ce4](https://etherscan.io/token/0x865377367054516e17014CcdED1e7d814EDC9ce4) L2: [0x31f01af056b7e829bd41e59e8ba3d2313d2b0ff3](https://celoscan.io/token/0x31f01af056b7e829bd41e59e8ba3d2313d2b0ff3) |
| GTC | Gitcoin | L1: [0xde30da39c46104798bb5aa3fe8b9e0e1f348163f](https://etherscan.io/token/0xde30da39c46104798bb5aa3fe8b9e0e1f348163f) L2: [0xa80e318dc786c58b8bcb692579764f56f89ab27e](https://celoscan.io/token/0xa80e318dc786c58b8bcb692579764f56f89ab27e) |
| LUSD | LUSD Stablecoin | L1: [0x5f98805a4e8be255a32880fdec7f6728c6568ba0](https://etherscan.io/token/0x5f98805a4e8be255a32880fdec7f6728c6568ba0) L2: [0xef6379fa3090310862a42f6c732dba2f20880f0a](https://celoscan.io/token/0xef6379fa3090310862a42f6c732dba2f20880f0a) |
| LDO | Lido DAO Token | L1: [0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32](https://etherscan.io/token/0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32) L2: [0x6981f932c2ec5f9e15d44d7ef46859a133f544dd](https://celoscan.io/token/0x6981f932c2ec5f9e15d44d7ef46859a133f544dd) |
| MKR | Maker | L1: [0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2](https://etherscan.io/token/0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2) L2: [0x918b13745de61380d5d3efddf51244c369f101d5](https://celoscan.io/token/0x918b13745de61380d5d3efddf51244c369f101d5) |
| POOL | PoolTogether | L1: [0x0cec1a9154ff802e7934fc916ed7ca50bde6844e](https://etherscan.io/token/0x0cec1a9154ff802e7934fc916ed7ca50bde6844e) L2: [0xe00892b8636f0c7450177f89717539d656d870fb](https://celoscan.io/token/0xe00892b8636f0c7450177f89717539d656d870fb) |
| rETH | Rocket Pool ETH | L1: [0xae78736cd615f374d3085123a210448e74fc6393](https://etherscan.io/token/0xae78736cd615f374d3085123a210448e74fc6393) L2: [0x55f3d16e6bd2b8b8e6599df6ef4593ce9dcae9ed](https://celoscan.io/token/0x55f3d16e6bd2b8b8e6599df6ef4593ce9dcae9ed) |
| RPL | Rocket Pool Protocol | L1: [0xD33526068D116cE69F19A9ee46F0bd304F21A51f](https://etherscan.io/token/0xD33526068D116cE69F19A9ee46F0bd304F21A51f) L2: [0x73a363ed1526f5e02be99f51c59400a2c508312c](https://celoscan.io/token/0x73a363ed1526f5e02be99f51c59400a2c508312c) |
| sDAI | Savings Dai | L1: [0x83F20F44975D03b1b09e64809B757c47f942BEeA](https://etherscan.io/token/0x83F20F44975D03b1b09e64809B757c47f942BEeA) L2: [0x4c430944d20410a16d5cec69b0cb66541b00a817](https://celoscan.io/token/0x4c430944d20410a16d5cec69b0cb66541b00a817) |
| XAUt | Tether Gold | L1: [0x68749665FF8D2d112Fa859AA293F07A622782F38](https://etherscan.io/token/0x68749665FF8D2d112Fa859AA293F07A622782F38) L2: [0x3776228836bfcfc87cac36c28830b67759c02707](https://celoscan.io/token/0x3776228836bfcfc87cac36c28830b67759c02707) |
| UMA | UMA Voting Token v1 | L1: [0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828](https://etherscan.io/token/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828) L2: [0x4672ecbd03a1f93dd67310caecd3a8ef6397e72a](https://celoscan.io/token/0x4672ecbd03a1f93dd67310caecd3a8ef6397e72a) |
| UNI | Uniswap | L1: [0x1f9840a85d5af5bf1d1762f925bdaddc4201f984](https://etherscan.io/token/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984) L2: [0xeE571697998ec64e32B57D754D700c4dda2f2a0e](https://celoscan.io/token/0xeE571697998ec64e32B57D754D700c4dda2f2a0e) |
| WLD | Worldcoin | L1: [0x163f8C2467924be0ae7B5347228CABF260318753](https://etherscan.io/token/0x163f8C2467924be0ae7B5347228CABF260318753) L2: [0x88c400d871829e381b53b55eee79145b4287461a](https://celoscan.io/token/0x88c400d871829e381b53b55eee79145b4287461a) |
| WBTC | Wrapped BTC | L1: [0x2260fac5e5542a773aa44fbcfedf7c193bc2c599](https://etherscan.io/token/0x2260fac5e5542a773aa44fbcfedf7c193bc2c599) L2: [0x8aC2901Dd8A1F17a1A4768A6bA4C3751e3995B2D](https://celoscan.io/token/0x8aC2901Dd8A1F17a1A4768A6bA4C3751e3995B2D) |
| WETH | Wrapped Ether | L1: [0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2](https://etherscan.io/token/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2) L2: [0xD221812de1BD094f35587EE8E174B07B6167D9Af](https://celoscan.io/token/0xD221812de1BD094f35587EE8E174B07B6167D9Af) |
## Cross-Chain Messaging
In addition to token bridges, there are also protocols that enable cross-chain messaging and interoperability:
* [Chainlink CCIP](https://chain.link/cross-chain)
* [Hyperlane](https://www.hyperlane.xyz/)
* [Wormhole](https://wormhole.com/)
* [Layer Zero](https://layerzero.network/)
* [Axelar Network](https://axelar.network/)
# Bridging Native ETH to Celo
Source: https://docs.celo.org/home/bridged-tokens/native-ETH-bridging
This document provides a minimal overview of the `SuperBridgeETHWrapper.sol` contract and its deployed addresses.
Alfajores has been replaced by Celo Sepolia as testnet on Celo.
This tutorial has not yet been updated to Celo Sepolia.
***
## Purpose
The `SuperBridgeETHWrapper.sol` contract allows users to bridge native ETH from an L1 network (like Ethereum or Sepolia) to the Celo L2 network, where it arrives as WETH.
When using Superbridge, this entire process is abstracted away from the user.
### How it Works (Simplified):
1. User sends ETH to this contract on L1 (calls `wrapAndBridge` function).
2. Contract wraps ETH into WETH on L1.
3. Contract uses the L1 Standard Bridge to send this WETH to Celo L2.
4. WETH arrives on Celo L2.
## Deployed Contract Addresses
### Mainnet (L1: Ethereum)
| Description | Address |
| :----------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------- |
| L1 WETH Address (WETH\_ADDRESS\_LOCAL) | [`0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2`](https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2) |
| L2 WETH Address (WETH\_ADDRESS\_REMOTE on Celo Mainnet) | [`0xD221812de1BD094f35587EE8E174B07B6167D9Af`](https://celoscan.io/address/0xD221812de1BD094f35587EE8E174B07B6167D9Af) |
| L1 Standard Bridge Proxy (STANDARD\_BRIDGE\_ADDRESS) | [`0x9C4955b92F34148dbcfDCD82e9c9eCe5CF2badfe`](https://etherscan.io/address/0x9C4955b92F34148dbcfDCD82e9c9eCe5CF2badfe) |
| Deployed SuperBridgeETHWrapper Address (on Ethereum Mainnet) | [`0x3bC7C4f8Afe7C8d514c9d4a3A42fb8176BE33c1e`](https://etherscan.io/address/0x3bC7C4f8Afe7C8d514c9d4a3A42fb8176BE33c1e) |
### Celo Sepolia (L1: Sepolia)
| Description | Address |
| :----------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ |
| L1 WETH Address (WETH\_ADDRESS\_LOCAL) | [`0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9`](https://sepolia.etherscan.io/address/0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9) |
| L2 WETH Address (WETH\_ADDRESS\_REMOTE on Celo Sepolia) | [`0x2cE73DC897A3E10b3FF3F86470847c36ddB735cf`](https://sepolia.celoscan.io/address/0x2cE73DC897A3E10b3FF3F86470847c36ddB735cf) |
| L1 Standard Bridge Proxy (STANDARD\_BRIDGE\_ADDRESS) | [`0xec18a3c30131a0db4246e785355fbc16e2eaf408`](https://sepolia.etherscan.io/address/0xec18a3c30131a0db4246e785355fbc16e2eaf408) |
| Deployed SuperBridgeETHWrapper Address (on Ethereum Sepolia) | [`0x523e358dFd0c4e98F3401DAc7b1879445d377e37`](https://sepolia.etherscan.io/address/0x523e358dFd0c4e98F3401DAc7b1879445d377e37) |
# Celo
Source: https://docs.celo.org/home/celo
Celo is a leading Ethereum L2. As the frontier chain for global impact, we're scaling real-world solutions for all.
Build your first app on Celo. No coding experience required.
***
## AI Agent Infrastructure
Establish trust infrastructure for autonomous AI agents with identity, reputation, and validation registries.
Enable instant, permissionless micropayments for AI agents using stablecoins via HTTP 402.
Charge USDC per API request over HTTP — gasless for the buyer, settled on-chain via a hosted facilitator.
Give your coding assistant Celo ecosystem knowledge — contract addresses, MiniPay, DeFi, grants, and agent infrastructure.
## Real World Use Cases
Build apps that scale to millions of global mobile wallet users via MiniPay.
Create low-cost FX and payment apps via Mento’s 25+ local digital currencies.
Launch AI agents, use MCP servers, and build intelligent applications for the onchain economy with Celo's AI-focused tools and frameworks.
Prove users’ humanity and unique identity without compromising privacy via Self Protocol.
## Builder Support
Explore comprehensive guides, tutorials, and tools to build dApps, DeFi protocols, mobile apps, and more on Celo's fast, low-cost blockchain.
Discover grant opportunities and funding sources available in the Celo ecosystem.
## Add Celo to your wallet
Connect your browser wallet to Celo in one click. See all network details on the [Network Information](/build-on-celo/network-overview) page.
## Explore Developer Tools & Resources
Discover how Celo L2 is scaling real world use cases on Ethereum
Overview of our stack and core contracts
Dive in to understand our protocol and social impact
Learn about our protocol and its relationship to Ethereum
Build & Deploy your dApps in under 5 minutes
Explore Celo Tutorials
Connect Celo to your application
Get testnet tokens for development
Explore transactions on Celo
Bridge Assets across chains
Deploy your contract on Celo
Discover grant opportunities in the Celo ecosystem
Get more awareness about your project
***
## Join the Celo Builder Ecosystem
💡 Discover the many ways to connect with our growing community of developers
Stay updated on the latest news, grants, and opportunities
Join our Discord
Sign up for upcoming governance calls and workshops
Build your onchain reputation to unlock exclusive rewards
Vote on Governance Proposals
Follow our CeloDev on X
***
New to Celo? Start with the [Celo Overview](/home) for a complete introduction to the platform.
# Exchanges on Celo
Source: https://docs.celo.org/home/exchanges
CELO is the native token that powers the Celo network.
***
Be sure you understand and review the risks when swapping assets.
#### Centralized Exchanges
* [Binance](https://www.binance.com/en/trade/CELO_USDT?ref=40896146)
* [Coinbase](https://exchange.coinbase.com/trade/CGLD-USD)
#### Decentralized Exchanges
* [Uniswap](https://app.uniswap.org/)
* [Velodrome](https://velodrome.finance/)
* [Other Exchanges](https://coinmarketcap.com/currencies/celo/)
#### Celo Specific Exchanges
* [Ubeswap](https://app.ubeswap.org/#/swap)
* [Mento](https://app.mento.org/) - Good for stablecoin swaps
# Getting CELO for Gas Fees
Source: https://docs.celo.org/home/gas-fees
When using a Celo-optimized wallet, gas fees can be paid with various ERC-20 tokens including USDC, USD₮, USA₮, USDm and CELO. For non Celo-optimized wallets, you'll need CELO tokens for gas fees.
***
### Using an Exchange
CELO is listed on 20+ exchanges worldwide.
* [Get CELO](https://coinmarketcap.com/currencies/celo/)
* [Get USDm](https://coinmarketcap.com/currencies/celo-dollar/)
* [Get EURm](https://coinmarketcap.com/currencies/celo-euro/)
Be sure to research which exchanges operate within your legal jurisdiction and support the tokens you need.
### Bridging from Other Chains
Bridge assets from other blockchains to CELO using:
* [Squid Router V2](https://v2.app.squidrouter.com/?chains=10%2C42220\&tokens=0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee%2C0x471ece3750da237f93b8e339c536989b8978a438)
* [SmolRefeul](https://smolrefuel.com/?outboundChain=42220) (Gas-free)
* [Other Bridges](/home/bridged-tokens/bridges)
# Our History
Source: https://docs.celo.org/home/history
Celo launched on Earth Day 2020 as an energy-efficient and low-cost Layer 1 blockchain. Since its inception, Celo has continually evolved to adapt to the changing landscape of blockchain technology and needs of its users in the broader crypto ecosystem.
***
## The Evolution of Celo: From Layer 1 to Layer 2
This timeline highlights the key milestones in Celo's development, from its launch as a Layer 1 blockchain to its transition to an Ethereum Layer 2 solution.
### Celo's Journey from L1 to L2
Watch this video to learn about Celo's transition from Layer 1 to Layer 2, exploring the reasons behind this strategic move and what it means for the future of the ecosystem:
## Timeline of Celo's Journey
Celo officially completes its transition to Layer 2 on Ethereum, marking a new era of enhanced security, scalability, and interoperability.\
[Read More](https://forum.celo.org/t/returning-home-to-ethereum-the-launch-of-celo-l2-mainnet/10466)
The Baklava testnet transitions to Layer 2 as a final preparation before mainnet deployment.\
[Read More](https://forum.celo.org/t/baklava-testnet-is-upgrading-to-l2/10238/8)
cLabs officially announces plans for the Celo Layer 2 mainnet launch, outlining final steps and timelines.\
[Read More](https://forum.celo.org/t/celo-l2-mainnet-announcement/9442)
cLabs provides an update on testnet progress and announces an upcoming code audit to ensure security and stability before mainnet deployment.\
[Read More](https://forum.celo.org/t/l2-testnet-update-and-upcoming-code-audit/9322)
The Alfajores testnet successfully transitions to a Layer 2, allowing developers to start testing under the new architecture.\
[Read More](https://forum.celo.org/t/alfajores-goes-l2/9052)
The Celo ecosystem begins preparations to upgrade the Alfajores testnet to a Layer 2 environment, marking another step towards mainnet migration.\
[Read More](https://forum.celo.org/t/preparing-for-alfajores-l2/8645)
Dango, the first Celo Layer 2 testnet, is launched, allowing developers and infrastructure providers to familiarize themselves with the new environment.\
[Read More](https://forum.celo.org/t/introducing-dango-l2-celo-testnet/8313)
cLabs proposes integrating an off-chain data availability layer, powered by EigenLayer and EigenDA, to enhance scalability and reduce costs.\
[Read More](https://forum.celo.org/t/clabs-proposes-off-chain-data-availability-layer-powered-by-eigenlayer-and-eigenda/8236)
cLabs proposes adopting the OP Stack for Celo's Layer 2 migration to align more closely with Ethereum, reduce production time, enhance security, and maintain its unique features with minimal migration risk.\
[Read More](https://forum.celo.org/t/clabs-proposes-migrating-celo-to-an-ethereum-l2-leveraging-the-op-stack/7902)
An update is provided on refinements in the Layer 2 stack selection process, addressing key technical considerations.\
[Read More](https://forum.celo.org/t/quick-update-on-l2-stack-selection/7838)
cLabs announces the latest developments in selecting the technology stack for Celo's Layer 2 transition.\
[Read More](https://forum.celo.org/t/l2-stack-selection-update/7314)
cLabs provides a framework for evaluating different Layer 2 technology stacks, guiding the decision-making process for Celo's migration.\
[Read More](https://forum.celo.org/t/framework-for-selecting-an-l2-stack/6992)
cLabs releases an update on the roadmap for Celo's transition to Layer 2, outlining expected phases and milestones.\
[Read More](https://forum.celo.org/t/cel2-roadmap-update/6815)
The Gingerbread hardfork is implemented to prepare for Celo L2 with a focus on improving Celo's compatibility with Ethereum by streamlining code and introducing [Ultragreen Money](https://blog.celo.org/ultragreen-money-c677e7508abb), on-chain carbon offsetting through transaction fees, enhancing both performance and sustainability.\
[Read More](https://forum.celo.org/t/introducing-celo-s-gingerbread-hard-fork-join-for-q-a-on-june-21/5918)
In a strategic move, cLabs proposes transitioning Celo from an independent Layer 1 blockchain to an Ethereum Layer 2 to leverage Ethereum's security and expand its reach within the Ethereum ecosystem.\
[Read More](https://forum.celo.org/t/clabs-proposal-for-celo-to-transition-to-an-ethereum-l2/6109)
cLabs announces Celo 2.0 with improved Ethereum compatibility, better performance, and enhanced tokenomics.\
[Read More](https://forum.celo.org/t/the-next-chapter-introducing-celo-2-0/5124)
Ethereum completes its transition from Proof of Work to Proof of Stake, significantly reducing its energy consumption and addressing some of the sustainability concerns that Celo originally set out to solve.\
[Read More](https://ethereum.org/en/roadmap/merge/)
The Donut hard fork is implemented on Celo, enhancing its EVM (Ethereum Virtual Machine) compatibility and introducing cross-chain interoperability with other blockchain networks.\
[Read More](https://blog.celo.org/donut-hardfork-is-live-on-celo-585e2e294dcb)
Celo officially launches its Mainnet on Earth Day, marking its debut as a Layer 1 blockchain network. Designed with a focus on energy efficiency and low transaction costs, Celo sets out to provide a more sustainable and accessible blockchain solution.\
[Read More](https://blog.celo.org/its-official-celo-mainnet-is-here-6a3a71763f68)
Ethereum debuts as a Proof-of-Work blockchain, introducing smart contracts but facing high fees and energy consumption.
## White Papers
For a deeper understanding of Celo's evolution and the technical foundations behind it, check out our [white papers](https://celo.org/papers). These documents cover the innovations and decisions that have shaped Celo.
[Read our White Papers](https://celo.org/papers)
# Discover Celo
Source: https://docs.celo.org/home/index
## What is Celo?
Celo is an Ethereum Layer-2 designed to make blockchain technology accessible to all. With its focus on scalability, low fees, and ease of use, Celo is ideal for building blockchain products that reach millions of users around the globe.
Check out Rene Reinsberg speaking about Celo as the chain for real-world adoption in the video below.
## Why Build on Celo?
Celo is fully EVM-compatible, offering the same development experience as Ethereum with improved scalability and lower costs.
#### Built for Everyday Users:
Celo is designed with features that lower the entry barrier for those new to cryptocurrency.
* [**Fee Abstraction**](/home/gas-fees): Users can pay transaction fees with several different tokens, making payments simple and flexible.
* **Sub-Cent Fees**: Celo maintains low gas fees, often below a cent, keeping transactions affordable.
* **Fast Transactions**: Celo achieves 1 second block finality, enabling near-instant transaction confirmations.
* **Native Stablecoins**: Celo provides native stablecoins like USDm, EURm, BRLm, XOFm, KESm, PHPm, and COPm, offering a stable way to send and receive money. Check out [Mento](https://www.mento.org/) to learn more.
* [**Token Duality**](/home/protocol/celo-token#celo-token-duality): CELO token is both the native currency of the Celo blockchain as well as an ERC20 compatible token. This means CELO tokens can be moved both by doing a native transfer as well as ERC20 transfers and will show up in both in the native account balance and the ERC20 balance, no matter how they were transferred. In contrast to ETH/WETH, no token wrapping or unwrapping is necessary.
* **Mobile-Focused Approach**: Celo is optimized for mobile devices, making blockchain accessible to billions of smartphone users worldwide.
#### Optimized for Global Reach:
* **Global Distribution**: Build apps that scale to millions of mobile wallet users via [MiniPay](https://www.minipay.to/).
* [**Global Community**](/contribute-to-celo/daos): Connect with our extensive network of Celo Regional Hubs to bring your app to users around the globe.
## Participating in the Network
Holders of CELO tokens can also participate in network governance, helping shape the platform's future.
* [Voting on Governance](/home/protocol/governance/voting-in-governance-using-mondo) - Participate in Celo governance decisions
* [Governance Parameters](/home/protocol/governance/governable-parameters) - Reference all governable parameters
## Getting Support
For questions, comments, and discussions, connect with the Celo community:
* [Celo Forum](https://forum.celo.org/)
* [Discord](https://chat.celo.org/)
# Asset Management
Source: https://docs.celo.org/home/manage/asset
Access and account management for holding, exchanging, or sending Mento stablecoins like USDm (Mento Dollar).
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
## Prerequisites
This guide assumes:
* You have read [Key Management](/legacy/validator/key-management/summary) on Celo
* You have installed the [Celo Command Line Interface](/cli/) (Celo CLI)
## Choose a Node
In order to execute the tasks listed below, you will need to point the Celo CLI to a node that is synchronized with the [Mainnet](/build-on-celo/network-overview).
## Create an Account
There are two ways to create an account:
* (Recommended) use [accounts generated by Ledger](/wallet/ledger/setup), if you possess a [Ledger hardware wallet](https://shop.ledger.com/products/ledger-nano-s)
* Use CLI to [generate an account](/cli/account#celocli-accountnew) -- this approach is less secure and hence not recommended
After creating an account, record its address in environment variables:
```shell theme={null}
export CELO_ACCOUNT_ADDRESS=
```
## Exchange CELO for Mento Stablecoins
Once you have deposited CELO to your account, you can check your balance:
```shell theme={null}
celocli account:balance $CELO_ACCOUNT_ADDRESS
```
As an example of a common stablecoin swap, you can exchange CELO for USDm using the following command. This exchanges CELO for stable tokens (USDm by default) via the stability mechanism. Note that the unit of value is CELO Wei (1 CELO = 10^18 CELO Wei).
```shell theme={null}
celocli exchange:celo --value --from $CELO_ACCOUNT_ADDRESS
```
## Transfer Mento Stablecoins
When you have sufficient balance, you can send Mento stablecoins such as USDm to other accounts. Note that the unit of value is USDm Wei (1 USDm = 10^18 USDm Wei).
```shell theme={null}
celocli transfer:dollars --from $CELO_ACCOUNT_ADDRESS --to --value
```
# Understanding ReleaseGold
Source: https://docs.celo.org/home/manage/release-gold
Introduction to ReleaseGold including examples, use cases, and FAQ.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
## What is ReleaseGold?
[`ReleaseGold`](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/governance/ReleaseGold.sol) is a smart contract that enables CELO to be released programmatically to a beneficiary over a period of time. In a deployed `ReleaseGold` smart contract, only the CELO balance that has been released according to the release schedule can be withdrawn by the contract’s beneficiary. The unreleased CELO cannot be withdrawn, but can be used for specific functions in Celo’s Proof of Stake protocol, namely voting and validating.
The intent of the `ReleaseGold` contract is to allow beneficiaries to participate in Celo’s Proof of Stake protocol with CELO that has not yet been fully released to them. Beneficiaries are able to lock CELO for voting and validating with the full `ReleaseGold` balance, including both released and unreleased CELO.
Increasing the volume of CELO that can be used in Celo’s Proof of Stake consensus promotes network security and even greater decentralization. See below for details on specific features of the `ReleaseGold` contract, as well as how they are implemented. The [source code](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/governance/ReleaseGold.sol) includes documentation, and technical readers are encouraged to find further details there.
### Example
To illustrate with an example, let’s consider a `ReleaseGold` contract deployed with a total balance of 100 CELO. For example purposes, we’ll assume this contract enables both voting and validating.
Let's also assume the beneficiary is an individual who is receiving CELO based on a vesting schedule (or a ‘release schedule’). According to this release schedule, the beneficiary will receive 10% of the total CELO balance each month.
In three months time after deployment, there will be 30 released CELO in the contract, because 10 CELO (10% of 100 CELO) was released each month, for 3 months. Now, the beneficiary can transfer this 30 CELO freely.
The beneficiary does not yet have full rights to the remaining 70 unreleased CELO. However, this 70 CELO while unavailable for withdrawal, can still be used by the beneficiary for voting and validating. This unreleased balance will also continue to release at the rate of 10 CELO per month, until the total balance is empty.
## Addresses Involved
*Beneficiary*
The `beneficiary` address is the recipient of the CELO in the `ReleaseGold` contract. As the CELO is released over time, it is incrementally made withdrawable solely to the beneficiary. The beneficiary is also able to use both unreleased and released CELO to participate in Celo’s Proof of Stake consensus protocol, via locking gold and voting or validating.
*Release Owner*
The `releaseOwner` is the address involved in administering the `ReleaseGold` contract. The release owner may be able to perform actions including [setting the liquidity provision](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/governance/ReleaseGold.sol#L268) for the contract, setting the maximum withdrawal amount, or [revoking](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/governance/ReleaseGold.sol#L362) the contract, depending on the ReleaseGold configuration.
*Refund Address*
The `refundAddress` is the address where funds that have not been released will be sent if a `ReleaseGold` contract is revoked. Contracts that are not revocable do not have a `refundAddress`.
## Use Cases for `ReleaseGold`
Two anticipated use cases for `ReleaseGold` contracts are for “holders” and “earners”. Note that these are not specified in `ReleaseGold` explicitly, rather they represent sample configurations that the `ReleaseGold` contract supports.
In the “holder” case, a recipient may have purchased or been awarded an amount of CELO, but is subject to a distribution schedule limiting the amount of CELO that can be liquidated at any given time. These recipients may be able to validate and vote with the full `ReleaseGold` balance, and also are not subject to the contract’s revocation by another party (eg. an employer).
In the “earner” case, a grant recipient may have entered a legal contract wherein an exchange of services earns them an amount of CELO over a releasing, or vesting, schedule. These grants are characterized by extra restrictions because the total grant amount is still being *earned*. The `ReleaseGold` balance cannot be used for running a validator, but it can be used to vote for validators and governance proposals on the Celo network. Additionally, these contracts may be revocable and may be subject to the `liquidityProvision` flag, which prevents CELO distribution when markets are incapable of absorbing additional CELO without significant slippage.
## Release Schedule
In `ReleaseGold` smart contracts, a fixed amount of CELO becomes accessible to the `beneficiary` over time.
The following arguments specify a ReleaseGold smart contract schedule:
```mdx-code-block theme={null}
- `releasePeriod` - the frequency, in seconds, at which CELO is released
- Some common values: monthly (2628000), every 3 months (7884000)
- `amountReleasedPerPeriod` - the amount of CELO to be released each `releasePeriod`
- `numReleasePeriods` - the number of `releasePeriods` in which CELO will be released
- `releaseCliff` - the time at which the release cliff expires.
```
The total balance for the ReleaseGold account can be determined by multiplying the `numReleasePeriods` by `amountReleasedPerPeriod`.
Similar to vesting-type schedules with cliffs used for other assets, ReleaseGold allows for a `releaseCliff` (expressed in seconds) before which the released CELO cannot be withdrawn by its beneficiary. A common value for this is `31536000`, which is 1 year.
## Released and Unreleased CELO
In deployed `ReleaseGold` accounts, you can conceptually think of CELO in two states -- released, and unreleased. There are other states including locked, but for the purposes of the contract, these are the two primary states to consider.
Released CELO can be withdrawn to the `beneficiary` where it can be used freely. Unreleased CELO comes with some restrictions. Foremost, it cannot be withdrawn by the beneficiary. If `canVote` and `canValidate` are set to false, the beneficiary cannot vote or validate, respectively.
If the contract permits voting and validating using the unreleased balance, the specific keys to perform these actions must first be authorized. For example, if the `beneficiary` desires to vote using their `ReleaseGold` contract, they must authorize a voting key to vote on the contract’s behalf.
## FAQ
* Keep in mind that in a `ReleaseGold` contract, there is both released CELO, and unreleased CELO. You can always vote or validate with the released balance if you are the beneficiary. However, for unreleased CELO, you can only vote or validate if `canVote` or `canValidate` properties are respectively set to true on the contract .
* No, the `releaseOwner` cannot make transactions with the CELO balance in a `ReleaseGold` contract. However, they can perform some administrative functions if the permissions are given at time of deployment. For example, a `releaseOwner` cannot revoke a contract unless the property `revocable` is set to true when the contract is deployed.
* It is highly recommended to review the contract at its deployed address, to learn specific details of a `ReleaseGold` contract.
* Of course! Once CELO is released and the cliff has passed, the beneficiary is free to do what they want with it.
* You may use any keys for your voting and validating signers, so long as those keys are not for a registered account or for another signing purpose. This means you *could* use your `beneficiary` address as one of your signing roles, but you would need another account for an additional role.
* Yes, but changing the beneficiary requires signatures from both the `releaseOwner` and the current `beneficiary` of the `ReleaseGold` contract. This is implemented as a two out of two multisig contract.
* Unfortunately, if you lose the private key for the beneficiary address, then you won't be able to access your funds. Please be careful in ownership of this key, as it’s loss is irreversible.
* The `ReleaseGold` contract has been reviewed by security firms, and has passed smart contract audits. That said, if any unforeseen bugs are found, it is possible to modify the contract and redeploy it. This process requires a 2/2 multisig agreement from both `releaseOwner` and `beneficiary`.
* Some grants are subject to “distribution schedules,” which control the release of funds outside of a traditional vesting schedule for legal reasons. This schedule is controlled by the `distributionRatio` and is adjustable by the `releaseOwner`.
# Self-Custody CELO
Source: https://docs.celo.org/home/manage/self-custody
Account access and reward details for self-custodying holder of CELO on the Celo Mainnet.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
## Prerequisites
This guide assumes:
* You are self-custodying (you hold the private key to your address), and that you have provided that address directly to cLabs. If you are using a custody provider ([Anchorage](https://anchorage.com), [CoinList](https://coinlist.co), or others), please contact them for directions.
* Your address is the beneficiary of a [ReleaseGold](/home/manage/release-gold) contract, which releases CELO programmatically to a beneficiary over a period of time.
* You have been informed by cLabs that the `ReleaseGold` instance corresponding to your address has been deployed.
* You have your private key held on a [Ledger Nano S or Ledger Nano X](/wallet/ledger/setup) device, and you have a second such device available for managing a voting key. If you only have a single Ledger available, see [below](#using-a-single-ledger).
**Warning**: Self-custodying keys have associated security and financial risks. Loss or theft of keys can result in irrecoverable loss of funds. This guide also requires technical knowledge. You should be comfortable with using a Command Line Interface (CLI) and understand the basics of how cryptographic network accounts work.
## Support
If you have any questions or need assistance with these instructions, please contact cLabs or ask in the `#celo-holders` channel on [Celo's Discord server](https://chat.celo.org). Remember that Discord is a public channel: never disclose recovery phrases (also known as backup keys, or mnemonics), private keys, unsanitized log output, or personal information.
Please refer to the [Ledger Troubleshooting](/wallet/ledger/to-celo-cli#troubleshooting) for issues using Ledgers with the Celo CLI.
## Outline
In this guide, you will:
* Install the Celo CLI (and optionally, a local node to connect to the network)
* Access the `ReleaseGold` account associated with your address using your existing Ledger
* Authorize a voting key, which you will hold on a new, second Ledger
* Lock some of the Gold in your `ReleaseGold` account
* Use that Locked CELO to vote for Validator Groups to operate Celo's [Proof of Stake](/legacy/protocol/pos/index/) network (and in doing so be ready to receive epoch rewards of 6% when the community enables them in a forthcoming governance proposal)
## Preparing Ledgers
You will need:
* Your **Beneficiary Ledger**: One Ledger Nano S or X configured with your beneficiary key (used to produce the address you supplied cLabs). Once you have completed this guide, this will become a "cold wallet" that you can keep offline most of the time.
* Your **Vote Signer Ledger:** One Ledger Nano S or X configured with a new, unused key. This will become a "warm wallet" you can use whenever you want to participate in validator elections or governance proposals.
As a first step, follow [these instructions](/wallet/ledger/setup) for both Ledgers to install the Ledger Celo app, obtain and verify the associated addresses, and (recommended) run a test transaction on the Celo Sepolia test network.
The latest version of the Celo Ledger app is 1.1.8. If you are already using a Ledger with an earlier version installed, please [upgrade](/wallet/ledger/setup).
The remainder of this guide assumes you are using the first address available on each Ledger. You can add the flags described in [these instructions](/wallet/ledger/setup) to commands below to use different addresses.
### Using a single Ledger
If you only have a single Ledger, and are comfortable losing the security advantage of keeping the beneficiary key offline when voting, you can configure a second address on the same Ledger as your voting key.
First, read [these instructions](/wallet/ledger/setup) carefully. Then, wherever you see instructions to connect your Vote Signer Ledger, for each command line containing `--useLedger` also add `--ledgerCustomAddresses "[1]"`. If in doubt, [ask for help](#support).
## Deployment
If you haven't already, open a terminal window and install the [Celo CLI](/cli/):
```bash theme={null}
npm install -g @celo/celocli
```
If you have previously installed the CLI, ensure that you are using version 0.0.47 or later:
```bash theme={null}
celocli --version
```
And if not, upgrade by running the same command as above.
You will now need to point the Celo CLI to a node that is synchronized with the [Mainnet](/build-on-celo/network-overview) network. There are two options:
* **Local Celo Blockchain node**: You can run a full node on your local machine which will communicate
with other nodes and cryptographically verify all data it receives. Since this approach does not require you to trust the network, it is most secure.
To do this, follow the tutorial for [running a full node](/infra-partners/operators/run-node) (and make sure to pass `--usb`).
Then run:
```bash theme={null}
celocli config:set --node http://localhost:8545
```
* **cLabs-operated node**: As an alternative to using your own node, you can use an existing transaction
node service. Forno, operated by cLabs, is one example. While this approach does not require you to deploy a node locally, it requires you to trust cLabs and the remote Forno nodes (in the same way you would trust a centralized web service). An attacker may be able to manipulate data returned to you from the service, which the CLI may rely on to complete operations.
To use Forno, run this command:
```bash theme={null}
celocli config:set --node https://forno.celo.org
```
## Locate and verify your `ReleaseGold` contract address
First, copy the beneficiary address into the clipboard, and set it in an environment variable:
```bash theme={null}
export CELO_BENEFICIARY_ADDRESS=
```
Next, you will find the address of the `ReleaseGold` contract deployed for your beneficiary address. The `ReleaseGold` contract has its own address and is separate from the beneficiary address, but there are certain aspects of it that can be controlled only by the beneficiary. For more details, please refer to the [Understanding ReleaseGold page](/home/manage/release-gold).
Open the list of [all ReleaseGold deployments](https://storage.googleapis.com/celo-website/releasegold/CeloMainnetReleaseGoldAll.json) and locate your address (use Edit>Find in your browser, then paste the beneficiary address). Copy the matching value next to `ContractAddress` into your clipboard.
If you cannot locate your address in these mappings, please contact cLabs.
If you have more than one beneficiary address, you'll want to step through this guide and complete the steps for each one separately.
Record the value of the `ContractAddress` in an environment variable:
```bash theme={null}
export CELO_RG_ADDRESS=
```
You should find your beneficiary account already has a very small CELO balance to pay for transaction fees (values are shown in wei, so For example, 1 CELO = 1000000000000000000):
```bash theme={null}
celocli account:balance $CELO_BENEFICIARY_ADDRESS
```
Next, check the details of your `ReleaseGold` contract:
```bash theme={null}
celocli releasecelo:show --contract $CELO_RG_ADDRESS
```
Verify the configuration, balance, and beneficiary details. You can find an explanation of these parameters on the [ReleaseGold](/home/manage/release-gold) page.
If any of these details appear to be incorrect, please contact cLabs, and do not proceed with the remainder of this guide.
If the configuration shows `canVote: true`, your contract allows you to participate in electing Validator Groups for Celo's Proof of Stake protocol, and potentially earn epoch rewards for doing so. Please continue to follow the remainder of this guide (or you can come back and continue at any time).
Otherwise, you're all set. You don't need to take any further action right now.
## Authorize Vote Signer Keys
To allow you to keep your Beneficiary Ledger offline on a day-to-day basis, it’s recommended to use a separate [Authorized Vote Signer Account](/legacy/validator/key-management/detailed#authorized-vote-signers) that will vote on behalf of the beneficiary.
A vote signer can either be another Ledger device or a cloud Hardware Security Module (HSM).
This is a two step process. First, you create a "proof of possession" that shows that the holder of the beneficiary key also holds the vote signer key. Then, you will use that when the beneficiary signs a transaction authorizing the vote signer key. This proves to the Celo network that a single entity holds both keys.
Connect your **Vote Signer Ledger** now, unlock it, and open the Celo application.
First, obtain your vote signer address:
```bash theme={null}
# Using the Vote Signer Ledger
celocli account:list --useLedger
```
Your address is listed under `Ledger Addresses`. Create an environment variable for your vote signer address.
```bash theme={null}
export CELO_VOTE_SIGNER_ADDRESS=
```
Then create the proof of possession:
```bash theme={null}
# Using the Vote Signer Ledger
celocli account:proof-of-possession --signer $CELO_VOTE_SIGNER_ADDRESS --account $CELO_RG_ADDRESS --useLedger
```
The Ledger `Celo app` will ask you to confirm the transaction. Toggle right on the device until you see `Sign Message` on screen. Press both buttons at the same time to confirm.
Take note of the signature produced by the `proof-of-possession` command and create an environment variable for it.
```bash theme={null}
export CELO_VOTE_SIGNER_SIGNATURE=
```
Now switch ledgers.
Connect your **Beneficiary Ledger** now, unlock it, and open the Celo application.
Next, register the `ReleaseGold` contract as a “Locked CELO” account:
```bash theme={null}
# Using the Beneficiary Ledger
celocli releasecelo:create-account --contract $CELO_RG_ADDRESS --useLedger
```
You'll need to press right on the Ledger several times to review details of the transactions, then when the device says "Accept and send" press both buttons together.
Check that the `ReleaseGold` contract address is associated with a registered Locked CELO Account:
```bash theme={null}
celocli account:show $CELO_RG_ADDRESS
```
Now, using the proof-of-possession you generated above, as the Locked CELO Account account, you will authorize the vote signing key to vote on the Locked CELO Account's behalf:
```bash theme={null}
# Using the Beneficiary Ledger
celocli releasecelo:authorize --contract $CELO_RG_ADDRESS --role=vote --signer $CELO_VOTE_SIGNER_ADDRESS --signature $CELO_VOTE_SIGNER_SIGNATURE --useLedger
```
Finally, verify that your signer was correctly authorized:
```bash theme={null}
celocli account:show $CELO_RG_ADDRESS
```
The `vote` address under `authorizedSigners` should match `$CELO_VOTE_SIGNER_ADDRESS`.
The `ReleaseGold` contract was funded with an additional 1 CELO that it sends to the first vote signer account to be authorized. This allows the vote signer account to cover transaction fees. You can confirm this:
```bash theme={null}
celocli account:balance $CELO_VOTE_SIGNER_ADDRESS
```
**Warning**: If you authorize a second vote signer, it will not be automatically funded by the `ReleaseGold` contract. You will need to transfer a fraction of 1 CELO from your beneficiary address to it in order to cover transaction fees when using it.
## Lock CELO
To vote for Validator Groups and on governance proposals you will need to lock CELO. This is to keep the network secure by making sure each unit of CELO can only be used to vote once.
Specify the amount of CELO you wish to lock (don’t include the `< >` braces). All amounts are given as wei, i.e., units of 10^-18 CELO. For example, 1 CELO = 1000000000000000000.
Make sure to leave at least 1 CELO unlocked to pay for transaction fees.
```bash theme={null}
# Using the Beneficiary Ledger
celocli releasecelo:locked-gold --contract $CELO_RG_ADDRESS --action lock --useLedger --value
```
Check that your CELO was successfully locked.
```bash theme={null}
celocli lockedgold:show $CELO_RG_ADDRESS
```
## Vote for a Validator Group
Similar to staking or delegating in other Proof of Stake cryptocurrency protocols, CELO holders can lock CELO and vote for Validator Groups on the Celo network. By doing this, not only do you contribute to the health and security of the network, but you can also earn [epoch rewards](/home/protocol/epoch-rewards).
For more details, check out the [Voting for Validators page](/legacy/validator/voting), which contains useful background on how voting Validator Elections work, as well as more guidance on how to select a Validator Group to vote for. For now, all you need to know is that:
* in Celo, CELO holders vote for Validator Groups, not Validators directly
* you only earn epoch rewards if the Validator Group you voted for gets at least 1 Validator elected
Keeping this in mind, you will need to find a Validator Group to vote for and copy its address. You can find this information on community validator explorers such as the [cLabs Validator explorer](/legacy/validator/validator-explorer) and [Bi23 Labs' `thecelo` dashboard](https://thecelo.com).
You can also see registered Validator Groups through the Celo CLI. This will display a list of Validator Groups, the number of votes they have received, the number of additional votes they are able to receive, and whether or not they are eligible to elect Validators:
```bash theme={null}
celocli election:list
```
Once you have found one or more Validator Groups you’d like to vote for, create an environment variable for its Group address (don’t include the `< >` braces):
```bash theme={null}
export CELO_VALIDATOR_GROUP_ADDRESS=
```
For each vote you will need to select the amount of locked CELO you wish to vote with. You can look up your balance again if you need to:
```bash theme={null}
celocli account:balance $CELO_RG_ADDRESS
```
All CELO amounts should be expressed in wei: that means 1 CELO = 1000000000000000000. Don’t include the `< >` braces in the line below.
To vote, you will use your vote signer key, which is voting *on behalf of* your Locked CELO account.
Connect your **Vote Signer Ledger** now, unlock it, and open the Celo application.
```bash theme={null}
# Using the Vote Signer Ledger
celocli election:vote --from $CELO_VOTE_SIGNER_ADDRESS --for $CELO_VALIDATOR_GROUP_ADDRESS --useLedger --value
```
Verify that your votes were cast successfully. Since your Vote Signer account votes on behalf of the Celo Locked CELO account, you want to check the election status for that account:
```bash theme={null}
celocli election:show $CELO_RG_ADDRESS --voter
```
Your locked CELO votes should be displayed next to `pending` under `votes`.
## The next day: Activate your Vote
Your vote will apply starting at the next Validator Election, held once per day, and will continue to apply at each subsequent election until you change it.
After that election has occurred, you will need to activate your vote. This will allow you to receive epoch rewards if in that election (or at any subsequent one, until you change your vote) the Validator Group for which you voted elected at least one Validator. Rewards will get added to your votes for that Group and will compound automatically.
Epoch lengths in Mainnet are set to be the number of blocks produced in a day. As a result, votes may need to be activated up to 24 hours after they are cast.
Check that your votes were cast in a previous epoch:
```bash theme={null}
celocli election:show $CELO_RG_ADDRESS --voter
```
Your vote should be displayed next to `pending` under `votes`.
Connect your **Vote Signer Ledger** now, unlock it, and open the Celo application.
Now activate your votes:
```bash theme={null}
# Using the Vote Signer Ledger
# You must do this in an epoch after the one you voted in: this may take up to 24h
celocli election:activate --from $CELO_VOTE_SIGNER_ADDRESS --useLedger
```
If you run `election:show` again, your vote should be displayed next to `active` under `votes`.
Congratulations! You're all set.
At the end of the epoch following your vote activation, you may receive voter rewards (if at least one Validator from the Validator Group for which you voted was elected).
You can see rewards using:
```bash theme={null}
celocli rewards:show --voter $CELO_RG_ADDRESS
```
Or by searching for your `ReleaseGold` address on the [Block Explorer](https://explorer.celo.org) and clicking the "Celo Info" tab.
## Next Steps
You are now set up to participate in the Celo network!
You might want to read more about [choosing a Validator Group](/legacy/validator/voting) to vote for, and how [voter rewards](/home/protocol/epoch-rewards/index) are calculated. You can vote for up to ten different Groups from a single account.
Now you've locked CELO, you can use it to participate in voting for or against [Governance proposals](/home/protocol/governance/voting-in-governance). You can do this without affecting any vote you have made for Validator Groups.
You can also read more about how Celo's [Proof of Stake](/legacy/protocol/pos/index/) and on-chain [Governance](/home/protocol/governance/overview) mechanisms work.
## Revoking Votes
At any point you can revoke votes cast for a Validator Group. For example, a Group may be performing poorly and affecting your rewards, and you may prefer to vote for another Group.
When you revoke your votes you will stop receiving voter rewards.
Specify the amount of CELO you wish to revoke (don’t include the `< >` braces). All CELO amounts should be expressed in 18 decimal places. For example, 1 CELO = 1000000000000000000.
Connect your **Vote Signer Ledger** now, unlock it, and open the Celo application.
Revoke votes for the Group:
```bash theme={null}
# Using the Vote Signer Ledger
celocli election:revoke --from $CELO_VOTE_SIGNER_ADDRESS --for $CELO_VALIDATOR_GROUP_ADDRESS --value --useLedger
```
You can immediately re-use this locked CELO to vote for another Group.
## Unlocking and Withdrawing
At some point, the terms of your `ReleaseGold` contract will allow you to withdraw funds and transfer them to your beneficiary address.
There are actually several steps to this process:
1. First, revoke all outstanding votes as above (including for governance proposals)
2. Unlock the non-voting Locked CELO, starting a 72 hour unlocking period
3. After the three day unlocking period is complete, withdraw the CELO back to the `ReleaseGold` contract
4. Assuming vesting and distribution requirements are met, withdraw the CELO to the beneficiary address
Check the current status of outstanding votes:
```bash theme={null}
celocli election:show $CELO_RG_ADDRESS --voter
```
You can view the balance of locked CELO:
```bash theme={null}
celocli account:balance $CELO_RG_ADDRESS
```
Connect your **Beneficiary Ledger** now, unlock it and open the Celo application.
Assuming you have non-voting Locked Celo, you can initiate the process to unlock:
```bash theme={null}
# Using the Beneficiary Ledger
celocli releasecelo:locked-gold --contract $CELO_RG_ADDRESS --action unlock --useLedger --value
```
After the 72 hour unlocking period has passed, withdraw the CELO back to the `ReleaseGold` contract:
```bash theme={null}
# Using the Beneficiary Ledger
celocli releasecelo:locked-gold --contract $CELO_RG_ADDRESS --action withdraw --useLedger --value
```
Finally, request that the `ReleaseGold` contract transfer an amount to your beneficiary address:
```bash theme={null}
# Using the Beneficiary Ledger
celocli releasecelo:withdraw --contract $CELO_RG_ADDRESS --useLedger --value
```
To vote with any CELO in your beneficiary account, you'll want to register it as a Locked CELO Account, authorize a new vote signing key for it, then lock CELO.
# CELO Token Duality
Source: https://docs.celo.org/home/protocol/celo-token
Introduction to CELO and its compliance to the ERC20 standard.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
The CELO token is unique in its ability to function as both a native token and an ERC-20 compatible token.
## What is Token Duality?
Token duality means that **CELO functions both as the native currency of the Celo blockchain and as an ERC-20 compatible token**. This enables CELO tokens to be transferred in two ways:
1. **Native transfers**, similar to how ETH is transferred on Ethereum.
2. **ERC-20 transfers**, using the standard ERC-20 interface.
Regardless of the transfer method, CELO tokens **reflect in both the native account balance and the ERC-20 balance**. Unlike ETH/WETH, there is **no need for wrapping or unwrapping**.
***
## Implementation Details
### **Native Transfers and Balances**
* Native transfers and balance storage work exactly as they do on Ethereum.
* The CELO ERC-20 contract **reads native balances** and triggers native transfers via its ERC-20 interface.
### **Reading Balances via ERC-20**
* The ERC-20 implementation does **not** store balances in contract storage.
* Instead, `balanceOf(address)` directly returns the **native balance**, ensuring consistency across both transfer types.
### **Transfers via ERC-20**
* The `transfer` and `transferFrom` functions do **not** modify contract storage.
* Instead, these functions **initiate a native transfer**.
* Since Ethereum does not support native transfers from smart contracts, **Celo introduces a transfer precompile** to handle this. This precompile can only be called by the CELO token.
***
By enabling seamless interoperability between native and ERC-20 transactions, **CELO remains highly flexible within the Ethereum and Celo ecosystems** without requiring additional conversion steps.
# Challengers
Source: https://docs.celo.org/home/protocol/challengers
Listing of the Celo Challengers
With the [Jello Hardfork](/infra-partners/notices/archive/jello-upgrade), Celo switched to use OP Succinct Lite and introduced a set of independent challengers. Those challengers are responsible for checking the validity of the state roots sent to the L1.
## List of Challengers
Currently, there are six registered challengers. Five challengers are independent entities, one challenger is run by cLabs.
| Name | Challenger address |
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| [atalma.io](https://atalma.io) | [`0x77E831A0A6a680335BB54937E085fF625dfE3f6F`](https://eth.blockscout.com/address/0x77E831A0A6a680335BB54937E085fF625dfE3f6F) |
| [atweb3 GmbH](https://atweb3.co) | [`0xe4ce4999b1C4C60C384AC96f370F00796ae9eC78`](https://eth.blockscout.com/address/0xe4ce4999b1C4C60C384AC96f370F00796ae9eC78) |
| cLabs | [`0x7247204E46B381149d99acF88b318713fE12c32f`](https://eth.blockscout.com/address/0x7247204E46B381149d99acF88b318713fE12c32f) |
| [Grassroots Economics](https://sarafu.network/) | [`0xc6E6836CaCB6fF0a843050DB7F64bb2ab864C463`](https://eth.blockscout.com/address/0xc6E6836CaCB6fF0a843050DB7F64bb2ab864C463) |
| [Swiftstaking](https://www.swiftstaking.com/) | [`0x53e8eeaae0731ccc888513695ec1bd792ec975ca`](https://eth.blockscout.com/address/0x53e8eeaae0731ccc888513695ec1bd792ec975ca) |
| Usopp's | [`0x56966549e0953e8d6e17fcd3278b003d81f58ca8`](https://eth.blockscout.com/address/0x56966549e0953e8d6e17fcd3278b003d81f58ca8) |
# Carbon Offsetting Fund
Source: https://docs.celo.org/home/protocol/epoch-rewards/carbon-offsetting-fund
Introduction to the Carbon Offsetting fund, its purpose, and governance process.
***
Check out the ["The Great Celo Halvening – Proposed Tokenomics in the Era of Celo L2"](https://forum.celo.org/t/the-great-celo-halvening-proposed-tokenomics-in-the-era-of-celo-l2/9701).
## What is the Carbon Offsetting Fund?
The Carbon Offsetting Fund represents Celo's commitment to environmental sustainability by making the platform's infrastructure **carbon-negative**. The fund automatically transfers resources every epoch to partner organizations that use these assets for verified carbon offsetting projects.
## How the Carbon Offsetting Fund Receives Assets
* **Epoch rewards**: the Carbon Offsetting Fund receives 0.1% of epoch rewards, adjustable via governance and distributed automatically at each epoch.
* **Transaction fees**: the Carbon Offsetting Fund receives 10% of transaction fees, adjustable via governance.
# Community Fund
Source: https://docs.celo.org/home/protocol/epoch-rewards/community-fund
Introduction to the community fund, its assets, and its relationship to the on-chain reserve.
***
Check out the [State of Celo Community Treasury | Q1 2025](https://forum.celo.org/t/state-of-celo-community-treasury-q1-2025/10573)
## What is the Community Fund?
The Community Fund supports the ongoing development and maintenance of the Celo platform. CELO holders collectively decide how to allocate these funds through governance proposals submitted to the [governance forum](https://forum.celo.org/c/governance/12).
## How the Community Fund Receives Assets
The Community Fund is funded through two primary mechanisms:
* **Epoch rewards**: the Community Fund receives 1% of epoch rewards, adjustable via governance and distributed automatically at each epoch.
* **Slashed assets**: the Community Fund is the default destination for slashed assets.
In April 2023, [CGP-79](https://mondo.celo.org/governance/cgp-79) was passed, enabling the Mento Reserve to return 120M CELO (originally allocated at genesis) to the Celo Community Fund.
## On-chain and Analytics
All Community Fund activities are transparent and verifiable on-chain: [0xD533Ca259b330c7A88f74E000a3FaEa2d63B7972](https://celoscan.io/address/0xD533Ca259b330c7A88f74E000a3FaEa2d63B7972).
For deeper analysis of Community Fund activities, use the [Dune Analytics dashboard](https://dune.com/superchain_eco/celo-community-treasury).
For a detailed view of the fund's assets, including both historical and current spending breakdowns, explore the [Celo Community Fund website](https://www.celocommunityfund.xyz/).
# L2 Epoch Rewards
Source: https://docs.celo.org/home/protocol/epoch-rewards/index
Learn how Celo distributes rewards to network participants.
***
## What are Epoch Rewards?
**Epoch Rewards** function similarly to block rewards in other blockchains. They distribute new CELO tokens as epochs progress, creating incentives for various network participants.
## How Epoch Rewards Work
Rewards are distributed at the end of each epoch (roughly every 24 hours) to:
* **Community RPC providers** - Node operators serving the network
* **Locked CELO holders** - Users who vote for groups that elected community RPC providers
* **Community Fund** - Supporting protocol infrastructure grants
* **Carbon Offsetting Fund** - Environmental sustainability initiatives
## Token Economics
A total of **400 million CELO** will be released through epoch rewards over time. CELO serves multiple roles:
* Utility and governance token for the Celo network
* Reserve collateral backing Celo stablecoins
* Fixed supply asset with long-term deflationary characteristics (similar to Ethereum)
****Migration from L1 to L2****
For details on how epoch rewards worked when Celo was a Layer 1 blockchain, see [the historical epoch rewards section](/legacy/protocol/pos/epoch-rewards).
For technical changes since the L1 to L2 migration, refer to the [official specs](/specs/smart-contract-updates-from-l1#epochs-and-rewards).
## Epoch Duration and Processing
An epoch is a time period lasting at least one day, with no guaranteed maximum duration.
The epoch logic is implemented in Solidity via the [EpochManager contract](/contracts/core-contracts), introduced in [Contract Release 12](https://github.com/celo-org/celo-monorepo/tree/core-contracts.v12).
Since epoch processing requires significant gas consumption, it's handled through multiple function calls rather than a single transaction.
## Reward Distribution Process
CELO tokens are transferred from the `CeloUnreleasedTreasury` contract, which was allocated the full amount of unminted CELO during the L2 transition.
****TERMINOLOGY****
The term "validator" is used in the code and corresponding explanation due to historical reasons, but refers to the community RPC providers.
### Phase 1: Starting Epoch Processing
When the epoch duration has elapsed, anyone can call `startNextEpochProcess()` to begin reward distribution.
**Requirements:**
* Sufficient time has passed since the current epoch began.
* No epoch is currently being processed.
**Actions performed:**
1. **Updates target voting yield** - Adjusts reward rates
2. **Calculates epoch rewards** - Determines total rewards via `EpochRewards.calculateTargetEpochRewards()`
3. **Allocates validator rewards:**
* Mints CELO and exchanges it for USDm
* Creates internal mapping for validator allocations
* Validators later claim rewards by calling `sendValidatorPayment`
4. **Activates protection mode** - Temporarily blocks certain actions (locking/unlocking CELO, changing validator locks)
5. **Emits events:**
* EpochRewards: `TargetVotingYieldUpdated(uint256 fraction)`
* CeloUnreleasedTreasury: `Released(address indexed to, uint256 amount)`
* USDm: `Transfer(address indexed from, address indexed to, uint256 value)`
* EpochManager: `EpochProcessingStarted(uint256 indexed epochNumber)`
### Phase 2: Completing Epoch Processing
After the initial phase, anyone can call `finishNextEpochProcess()` to complete the epoch.
**Requirements:**
* `startNextEpochProcess` must have been called previously.
**Actions performed:**
1. **Allocates voter rewards** - Makes CELO available to eligible voters
2. **Conducts validator elections** - Stores elected validator accounts and signers
3. **Removes protection mode** - Re-enables previously blocked actions
4. **Updates epoch state** - Advances to the next epoch
5. **Emits events:**
* Election: `EpochRewardsDistributedToVoters(address indexed group, uint256 value)`
* CeloUnreleasedTreasury: `Released(address indexed to, uint256 amount)`
* EpochManager: `EpochProcessingEnded(uint256 indexed epochNumber)`
# Escrow
Source: https://docs.celo.org/home/protocol/escrow
Introduction to the Celo Escrow contract and how to use it to withdraw, revoke, and reclaim funds.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
## What is the Escrow Contract?
The `Escrow` contract utilizes Celo's Lightweight identity feature to allow users to *send payments to other users who don't yet have a public/private key pair or an address*. These payments are stored in this contract itself and can be either withdrawn by the intended recipient or reclaimed by the sender. This functionality supports *both* versions of Celo's lightweight identity: identifier-based (such as a phone number to address mapping) and privacy-based. This gives applications that intend to use this contract some flexibility in deciding which version of identity they prefer to use.
## How it works
If Alice wants to send a payment to Bob, who doesn't yet have an associated address, she will send that payment to this `Escrow` contract and will also create a temporary public/private key pair. The associated temporary address will be referred to as the `paymentId`. Alice will then externally share the newly created temporary private key, also known as an *invitation*, to Bob, who will later use it to claim the payment. This paymentId will now be stored in this contract and will be mapped to relevant details related to this specific payment such as: the value of the payment, an optional identifier of the intended recipient, an optional amount of `attestations` the recipient must have before being able to withdraw the payment, an amount of time after which the sender can revoke the payment (via the `expirySeconds` field - more on that in the "withdrawing" section below), which asset is being transferred in this payment, etc.
## Withdrawing
The recipient of an escrowed payment can choose to withdraw their payment assuming they have successfully created their own public/private key pair and now have an address. To prove their identity, the recipient must be able to prove ownership of the paymentId's private key, which should have been given to them by the original sender. If the sender set a minimum number of attestations required to withdraw the payment, that will also be checked in order to successfully withdraw. Following the same example as above, if Bob wants to withdraw the payment Alice sent him, he must sign a message with the private key given to him by Alice. The message will be the address of Bob's newly created account. Bob will then be able to withdraw his payment by providing the paymentId and the v, r, and s outputs of the generated ECDSA signature. An escrowed payment may have `expirySeconds` set, which references the amount of time that must pass before the sender can revoke the payment. Note that after `expirySeconds` have passed, the payment recipient may *still withdraw the payment as long as it has not already been revoked*.
## Revoking & Reclaiming
Alice sends Bob an escrowed payment. Let's say Bob never withdraws it, or worse, the temporary private key he needs to withdraw the payment gets lost or sent to the wrong person. For this purpose, Celo's protocol also allows for senders to reclaim any unclaimed escrowed payment that they sent. After an escrowed payment's `expirySeconds` (set by the sender on creation of the payment) has passed, the sender of the payment can revoke the payment and reclaim their funds with just the paymentId.
# Create a Governance Proposal
Source: https://docs.celo.org/home/protocol/governance/create-governance-proposal
How to create a governance proposal and get it through the governance process.
***
For a detailed explanation of the entire governance process, and to view the latest proposals and discussions, make sure to check out the [Celo Governance GitHub repository](https://github.com/celo-org/governance).
## Prerequisites
Before creating a Celo governance proposal, ensure you have:
1. **[Celo CLI](/cli) Knowledge:** Familiarity with the Celo Command Line Interface for network interaction and proposal submission.
2. **10,000 CELO:** Required minimum for proposal submission. This deposit is refunded if the proposal reaches Approval stage, but forfeited if the proposal expires after 4 weeks in queue.
3. **Multi-Signature Wallet:** Required for treasury fund requests. Multisig signers should self-identify on the Forum post to demonstrate oversight and build community trust.
## Life Cycle of a Proposal on Celo
### Step 1: Drafting the Proposal
The initial phase in the lifecycle of a governance proposal is the drafting stage. Here, you must comprehensively outline the proposal's purpose, scope, and impact. This should include:
* **Objective**: Clearly state what the proposal aims to achieve.
* **Rationale**: Explain why this proposal is necessary and the problems it addresses.
* **Technical Specifications**: If applicable, provide technical details or code changes.
* **Budget and Funding**: Outline any financial requirements, including a detailed breakdown of costs.
Setting up a secure multisig wallet is recommended for proposals requesting funds, as it ensures enhanced security and trust within the community.
### Step 2: Posting the Proposal on Celo Forum
Once your proposal is drafted, post it on the [Celo Forum](https://forum.celo.org/c/governance/12) to initiate community discussion. This post should:
* **Detail the Proposal**: Share every aspect of the proposal, leaving no ambiguity.
* **Include Multisig Information**: If requesting funds, provide the multisig wallet details.
* **Solicit Feedback**: Encourage community input to refine and improve the proposal.
**Respond and Iterate**: After posting, actively engage with the community, addressing queries and incorporating feedback to strengthen the proposal.
### Step 3: Governance Community Call
To further socialize your proposal, apply to present it during the Celo Governance Community Call by:
* **Booking a Slot**: Comment on the [celo-org/governance](https://github.com/celo-org/governance) repository issue for the next upcoming Governance call to reserve your presentation slot.
* **Join a Governance Call Discussion**: Discuss your proposal in depth and answer questions from the community and approvers.
### Step 4: Publishing the Proposal on GitHub
After refining your proposal through community feedback, the next step is to formalize it by publishing on GitHub. This involves:
* **Create a Pull Request (PR)**: Submit your proposal as a PR to the [celo-org/governance](https://github.com/celo-org/governance) repository. This should include the proposal in markdown format and any associated code in a JSON file. Review previous proposal that are similar to your proposal for hints on how the code should be structured.
* **Celo Governance Proposal (CGP) Editors' Review**: CGP editors will review your submission to ensure it meets the required standards and provide feedback or request changes if necessary. The CGP Editors will assign an id.
* **Acceptance of PR**: Once the CGP editors approve the PR, it signals that your proposal is ready to be submitted on-chain.
* **On-chain Submission**: Accepted proposals can then be submitted on-chain through the Celo CLI for formal voting by the community.
Wait for PRs to be merged on proposals prior to submitting on chain!
### Step 5: Formal Proposal Submission On-Chain
The formal submission of your proposal to the blockchain is detailed [below](#creating-on-chain-proposal). It involves using **`celocli`** to submit your proposal on-chain for approval and voting.
It is best to ensure all details are correct before submission.
### Step 6: Voting
After submission, your proposal enters the voting phase, which consists of:
* **Upvoting**: If multiple proposals are submitted at the same time in a 24 hour period, then they must receive upvotes. Anyone, including yourself, can upvote proposals. The highest upvoted proposal moves automatically to the Referendum stage.
* **Approval Voting**: Approvers review the proposal for any security risks or potential harm to the network. They may follow up with questions so ensure you are easy to contact via your profile on forum or via a connection with a CGP Editor.
* **Referendum Voting**: Once a proposal is in Referendum stage, all CELO holders may vote on the proposal. They can vote YES to support the proposal, NO to reject the proposal, and ABSTAIN to acknowledge but defer the vote to the remaining community.
* **Quorum**: For a proposal to pass successfully, the total number of CELO voted must meet or exceed Quorum. YES, NO, and ABSTAIN votes all count towards quorum. A successfully proposal must receive a 60% majority of votes above quorum. Quorum needed for proposals is dynamic and depends on previous number of votes on recent proposals.
* **Conclusion**: Approvers have until the proposal’s deadline to approve any passing proposals. Once approved, YES votes exceed 60% of necessary quorum, then they may be Executed.
The **approval voting** and **referendum voting** phases run in parallel. This means that the community can vote before the proposal is approved—approval is still necessary.
### Step 7: Execution
If the proposal passes the voting phase, it moves to execution. This involves enacting the changes or transferring the funds as outlined in the proposal. Detailed steps for execution will be provided in a subsequent section.
By following these steps, your proposal will go through the necessary stages from conception to execution in the Celo governance process. Proposals must be executed within 3 days from the referendum stage or they will be rejected automatically by the system.
Warning: Anyone on the network can execute a successful proposal at any time.
## Creating On-Chain Proposal
### Step 1: Create the Proposal File (mainnet.json)
Create a folder named after your proposal number (e.g., `cgp-0123`) inside the CGPs folder of the [Governance repository](https://github.com/celo-org/governance/). Within this folder, create a file called `mainnet.json`.
**Note:** Your proposal PR should be merged or pending merge before proceeding. You can reference [this example](https://github.com/celo-org/governance/blob/main/CGPs/cgp-0075/mainet.json) for the proper file structure.
Inside this file, paste the following content:
```json theme={null}
[
{
"contract": "GoldToken",
"function": "approve",
"args": [
"0xE1061b397cC3C381E95a411967e3F053A7c50E70",
"5980314000000000000000000"
],
"value": "0"
}
]
```
💡 If requesting funds from Treasury
```json theme={null}
{
"contract": "StableToken",
"address": "0x765DE816845861e75A25fCA122bb6898B8B1282a",
"function": "increaseAllowance",
"args": [
"0x71f433514957d00287A9d33Da759f1e0C1732381",
"1700000000000000000000000"
],
"value": "0"
}
```
💡 If making contract call from Governance Contract
Make sure to replace your address and the amount of CELO you want to approve. Save this file and add it to CGPs folder in the Governance repository.
### Step 2: Submit the Proposal On-Chain
After your PR is merged, we can submit the proposal on-chain.
#### Step 2.1: Install celocli
In your terminal, run the following command to install the [Celo CLI](/cli):
```bash theme={null}
npm install -g @celo/celocli
```
#### Step 2.2: Target the json file
We will submit the proposal using the `mainnet.json` file you created earlier. To do this, in your terminal:
```bash theme={null}
cd governance // repository folder
cd CGPs
cd cgp-(your proposal number)
cat mainnet.json
```
Once you see the content of your `mainnet.json` file in the terminal output, you can submit the proposal using:
```bash theme={null}
celocli governance:propose --jsonTransactions=mainnet.json --deposit=10000e18 --descriptionURL=https://github.com/celo-org/governance/blob/main/CGPs/cgp-.md --from= --privateKey=
```
Replace the --descriptionURL, --from fields with your proposal Github file URL.
💡 Note that 10,000 CELO tokens are required inthe account to submit a proposal. This amount will be refunded to the proposer if the proposal reaches the Approval stage. If a proposal has been on the queue for for more than 4 weeks, it expires and the deposit is forfeited.
💡 You can see your proposal ID in the terminal output. Save this ID for future use. To see you proposal in detail, run the following command in your terminal: `celocli governance:show --proposalID `
### Step 3: Execute the Proposal
Once the proposal passes the series of votes, you need to execute it. Connect your ledger to your computer and run the following command in your terminal:
```bash theme={null}
celocli governance:execute --proposalID --from= --privateKey=
```
Replace `number` with the proposal ID.
## Best Practices for Creating a Proposal
* **Clarity and Justification**: Ensure your proposal is clearly written, with straightforward language and a strong justification for why it's needed. Provide as much detail as possible about what you are proposing and why it is beneficial for the Celo ecosystem.
* **Community Engagement**: Engage with the community early on. Seek feedback and address concerns before formal submission. This not only improves your proposal but also builds community support.
* **Security Assessment**: If your proposal involves smart contract code, conduct a thorough security audit. Include the audit report in your proposal to increase credibility and trust.
* **Transparency**: Be transparent about your affiliations and intentions. If your proposal involves funding, detail how the funds will be used.
* **Follow Governance Structure**: Adhere strictly to the governance process as laid out by Celo, including any templates or formats required for proposals.
## What to Expect in Governance Calls
* **Presentation Slot**: Be prepared to present your proposal succinctly. Typically, you may be allocated a specific time slot, such as 5 minutes for presentation and 5 minutes for Q\&A.
* **Technical Questions**: Expect technical questions from the community, especially if your proposal involves code changes. Be ready to explain complex concepts in accessible language.
* **Community Feedback**: Governance calls are an opportunity for the community to provide direct feedback. Take notes and be open to incorporating this feedback into your proposal.
* **Approval Indicators**: Use these calls as a temperature check on your proposal's likelihood of passing. Positive engagement and constructive feedback are good indicators.
* **Networking**: These calls are an excellent opportunity to network with other members of the Celo ecosystem, which can be valuable for building future support.
Each of these elements is important for navigating the governance calls effectively and maximizing the chance of your proposal's success.
### FAQ Section for Celo Governance
1. **What is a multisig wallet, and why is it recommended for proposals?**
* A multisig wallet requires multiple signatures to authorize transactions, providing increased security and trust for proposals involving treasury funds.
2. **Who are the Governance approvers?**
* Governance approvers are individuals or entities with the authority to review and approve proposals before they go to a community vote, ensuring they meet certain criteria and standards.
3. **Who are the CGP editors?**
* CGP (Celo Governance Proposal) editors are responsible for reviewing and managing the content of governance proposals submitted on GitHub to ensure clarity, completeness, and adherence to the format.
4. **How to reach CGP editors?**
* To reach CGP editors, you can use the [Discord](https://discord.com/invite/celo) channel. They are available to assist with questions and provide guidance on the proposal process.
5. **Can I submit the proposal again?**
* If a proposal is rejected or needs significant revisions, it may be resubmitted after addressing the community's feedback and making necessary adjustments.
6. **What if I made a mistake in the proposal?**
* If you discover a mistake in your proposal, it's important to communicate this to the community and CGP editors as soon as possible. Depending on the stage of the proposal, you may need to withdraw and resubmit it with corrections.
## How to create Multisig with Safe and withdraw fund from Treasury?
### Step: 1 Log in to your Safe
Log in and click `New Transaction` on the left hand side of the page. This wil bring up a modal, click `Contract Interation`.
> Note: Don't use [https://safe.celo.org/](https://safe.celo.org/) as it is not officilly supported. Use official Safe at - [https://safe.global/](https://safe.global/)
### Step 2: Enter ABI
Enter the Celo Proxy Address.
### Step 3. Change the ABI to the CELO Contract
Step 2 will auto populate the ABI with the proxy ABI. We will want to change that to the actual CELO ERC20 ABI to access the transferFrom function
> For the image below
>
> 1. This is the Celo Token Proxy Address(0x471ece3750da237f93b8e339c536989b8978a438)
> 2. The ABI of the CELO Token Contract
> 3. This is where our contract interaction is being sent to and this will be the CELO Token proxy.
> 4. The method we want to interact with(We specify the transferFrom)
### Step 4 Fill in the appropriate addresses
You will now need to add the addresses you are wishing to interact with
> For the image below:
>
> 5. from(address): This is the Celo Governance Contract(0xD533Ca259b330c7A88f74E000a3FaEa2d63B7972)
> 6. to(address): This is the address you are wishing to transfer funds from the Governance contract to. It could be the multisig you are using to do this interaction from or any other address.
> 7. value(uint256)\*: The wei amount of funds you are wishing to transfer. eg 1 CELO = 10 \*\* 18.
> You can use [this](https://eth-converter.com/) webpage to easily convert CELO to the wei value.
### Step 5: Create Transaction
Click `Add Transaction`, and after that other multisig signers will need to confirm the transaction. Once the required number of signers have confirmed the transaction, it will be executed. You can also add a description to the transaction to help other signers understand the purpose of the transaction.
# Governance Cheat Sheet
Source: https://docs.celo.org/home/protocol/governance/governable-parameters
List of governable parameters and governance restrictions on Celo.
***
## Governable Parameters
* The stability protocol, including the exchange
* What the protocol does with data feeds from Oracles
* Adding or removing Mento stablecoins
* Adding Mento stablecoins (or other ERC20s) for use in paying gas fees
* The identity protocol, including how phone number attestations works
* Linking of signers and off-chain metadata (e.g claims) to accounts
* On-chain governance itself
* MinimumClientVersion
* BlockGasLimit
* IntrinsicGasForAlternativeFeeCurrency
## Things That Can't Be Modified By Governance
* The protocol by which nodes communicate
* The format of block headers, block bodies, the fields in transactions, etc
* How nodes sync
* How nodes store their data locally
* Most parameters that affect the blockchain
# Governance Toolkit
Source: https://docs.celo.org/home/protocol/governance/governance-toolkit
An overview of the tools, platforms, and resources available for participating in Celo Governance.
***
## Mechanisms for Main Onchain Celo Governance Proposals
* [**Celo Governance Contract**](https://celoscan.io/address/0xd533ca259b330c7a88f74e000a3faea2d63b7972#code): The onchain voting contract for Celo Governance. This is also the address of the Celo Community Treasury.
* [**Celo Mondo**](https://mondo.celo.org/): The UI friendly interface to Lock, Stake, Delegate and Vote.
* [**CeloCLI**](/cli): The command line interface for interacting with the Celo network, including governance proposals and voting.
* [**Celo Terminal**](https://celoterminal.com/): A desktop application allowing Celo chain interactions and governance participation.
* [**StakedCelo dApp**](https://app.stcelo.xyz/connect): An application that allows for liquid staking of Celo and voting on Governance proposals.
### Mechanisms for Celo Public Goods Proposals
* [**Celo Public Goods Snapshot**](https://snapshot.org/#/celopg.eth): A Locked CELO snapshot to allow votes to occur on Snapshot to decide about Celo Public Goods Proposals.
### Mechanisms for Discussions
* [**The Celo Forum**](https://forum.celo.org/): The platform for governance and community discussion.
* [**Discord**](https://discord.com/invite/celo): For informal governance discussion and feedback.
* [**Github**](https://github.com/celo-org/governance): Governance guidelines and CGP proposals are tracked via Github.
* [**Governance Events**](https://lemonade.social/s/celogovernance): Sign Up to the next Governance Call.
## Celo Governance Guardians Overview
Celo Governance is represented by Celo Governance Guardians who can help answer any questions about the governance process.
The curent Celo Governance Guardians (formerly known as CGP Editors), actively participating in the Governance Process, are:
* **Guardian:** 0xj4an [Celo Forum](https://forum.celo.org/u/0xj4an-work), [Twitter](https://x.com/0xj4an)
* **Guardian:** Wade [Celo Forum](https://forum.celo.org/u/wade), [Twitter](https://x.com/0xZOZ)
* **Advisors Guardians:**
* Eric [Celo Forum](https://forum.celo.org/u/ericnakagawa), [Twitter](https://x.com/ericnakagawa)
* Anna [Celo Forum](https://forum.celo.org/u/annaalexa), [Twitter](https://x.com/AnnaAlexaK)
# Celo Governance
Source: https://docs.celo.org/home/protocol/governance/overview
This overview covers Celo governance and network management through the stakeholder proposal process.
***
## What is Celo Governance?
Celo uses a formal onchain governance mechanism to manage and upgrade the protocol such as for upgrading smart contracts, adding new stable currencies, or modifying the reserve target asset allocation. All changes must be agreed upon by CELO holders. A quorum threshold model is used to determine the number of votes needed for a proposal to pass.
For a detailed explanation of the entire governance process, and to view the latest proposals and discussions, make sure to check out the [Celo Governance GitHub repository](https://github.com/celo-org/governance).
## Stakeholder Proposal Process
Changes are managed via the Celo `Governance` smart contract. This contract acts as an "owner" for making modifications to other protocol smart contracts. Such smart contracts are termed **governable**. The `Governance` contract itself is governable, and owned by itself.
Please follow [this guide to create a proposal](/home/protocol/governance/create-governance-proposal), but make sure to go through this page to fully understand the process before you do so.
## Phases
### Overview
The governance process follows three sequential phases, each with specific timing requirements:
1. **Proposal Phase** - **Up to 4 weeks**: Each proposal starts in the proposal queue where community members can upvote it to improve its position relative to other queued proposals. Proposal authors should actively seek community support for upvotes (proposers may upvote their own proposals). The top 3 proposals are automatically promoted to the referendum stage daily. Proposals remaining in the queue for 4 weeks will expire.
2. **Referendum Phase** - **7 days**: Locked CELO holders vote YES or NO on the proposal during this period. Proposals that meet the required quorum threshold are promoted to the execution phase.
3. **Execution Phase** - **Up to 3 days**: Any community member may trigger the execution of the approved proposal during this window.
**Important Note on Approval**: Approval is not a separate stage, but rather a requirement that can be satisfied during either the Referendum or Execution phases. The designated Approvers can grant approval at any point during these phases. A proposal can only be executed after receiving full approval from the Approvers, regardless of when that approval is granted.
### Proposal
Any user may submit a Proposal to the Governance smart contract, along with a small deposit of CELO. This deposit is required to avoid spam proposals, and is refunded to the proposer when the proposal is dequeued. A Proposal consists of a list of transactions, and a description URL where voters can get more information about the proposal. It is encouraged that this description URL points to a CGP document in the [celo-org/celo-proposals](https://github.com/celo-org/celo-proposals) repository. Transaction data in the proposal includes the destination address, data, and value. If the proposal passes, the included transactions will be executed by the `Governance` contract.
Submitted proposals are added to the queue of proposals. While a proposal is on this queue, voters may use their Locked CELO to upvote the proposal. Once per day the top three proposals, by weight of the Locked CELO upvoting them, are dequeued and moved into the Referendum phase. Note that if there are fewer than three proposals on the queue, all may be dequeued even if they have no upvotes. If a proposal has been on the queue for for more than 4 weeks, it expires and the deposit is forfeited.
#### Types of Proposals
Governance Proposals must fall within one of the following categories to be considered acceptable.
| **Proposal Type** | **Governance Platform** | **Description** | **Submission Requirements** | **Quorum** | **Approval Threshold** |
| ---------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | -------------------------------------------- | -------------------------------------------- |
| Celo Protocol Governance | Celo Governance Contracts | Celo Network decisions and Celo Protocol Improvements | Deposit of 10,000 Locked CELO. | Dynamic based on the current Celo Algorithm. | Dynamic based on the current Celo Algorithm. |
| Smart Contract Governance | Celo Governance Contracts | onchain smart contract changes | Deposit of 10,000 Locked CELO. | Dynamic based on the current Celo Algorithm. | Dynamic based on the current Celo Algorithm. |
| Celo Community Treasury Governance | Celo Governance Contracts | Funding proposals that do not fall within a current Celo Public Good Budget or aim to request over \$500,000 in value in a single proposal. | Deposit of 10,000 Locked CELO. | Dynamic based on the current Celo Algorithm. | Dynamic based on the current Celo Algorithm. |
| Mento Governance | Celo Governance Contracts | Mento reserve and protocol decisions. To separate once, Mento will establish their own Governance system in 2024. | Deposit of 10,000 Locked CELO. | Dynamic based on the current Celo Algorithm. | Dynamic based on the current Celo Algorithm. |
| Celo Public Goods Governance | Celo Public Goods Snapshot | Program selection within approved Celo Public Goods budgets. | Minimum of 10,000 Locked CELO Balance | 2.5M Celo | 50% |
#### Feedback and Review
Proposals must be posted in the Celo Forum for review by the Celo community. It is required to post the proposal as a new discussion thread in the [Governance category](https://forum.celo.org/c/governance/12) and to mark it with **\[DRAFT]** in the title. Proposal authors are expected to be responsive to feedback.
A proposal needs to be up for discussion for at least **7 full days,** during which responsiveness from the author is mandatory.
After a proposal has received feedback and has been presented on the governance call the proposal author shall update the proposal thread title from \[Draft] to \[Final]. Authors shall also include a summary of incorporated feedback as a comment on their proposal thread so future reviewers can understand the proposal's progress. If feedback was gathered outside of the Forum (e.g., on Discord), proposal authors should include relevant links.
### Referendum
Once dequeued, proposals move to the Referendum phase. Any user may vote YES, NO, or ABSTAIN on these proposals. Their vote's weight is determined by the weight of their Locked CELO. After the Referendum phase is over, which lasts seven days, each proposal is marked as passed or failed as a function of the votes and the corresponding passing function parameters.
During the Referendum phase, the proposal can also receive approval from the designated Approvers (initially a 3 of 9 multi-signature address held by individuals from the Celo community. Approval is not required for a proposal to advance to the Execution phase, but is required before a proposal can be executed.
In order for a proposal to pass, it must meet a minimum threshold for **participation**, and **agreement**:
* Participation is the minimum portion of Locked CELO which must cast a vote for a proposal to pass. It exists to prevent proposals passing with very low participation. The participation requirement is calculated as a governable portion of the participation baseline, which is an exponential moving average of final participation in past governance proposals.
* Agreement is the portion of votes cast that must be YES votes for a proposal to pass. Each contract and function can define a required level of agreement, and the required agreement for a proposal is the maximum requirement among its constituent transactions.
### Execution
Proposals that graduate from the Referendum phase to the Execution phase may be executed by anyone, triggering a call operation code with the arguments defined in the proposal, originating from the Governance smart contract. However, a proposal can only be executed if it has received approval from the designated Approvers. If approval was not granted during the Referendum phase, it can still be granted during the Execution phase. Proposals expire from this phase after three days.
## Cool-off period for failed proposals
If a proposal is not accepted, a cool-off period is required for additional conversation and potential changes before the proposal can be resubmitted. There are two situations in which a cool-off period is required:
1. If a proposal is rejected due to not reaching a quorum but having a majority of YES votes, the proposal is moved back to the discussion stage and may be submitted for a vote after waiting for 14 days.
2. If a proposal is rejected and has a majority of NO votes, the proposal is moved back to the discussion stage and may be submitted for a vote after receiving approval from the Governance Guardians and waiting for 28 days.
**Note**: In the event that a proposal meets or exceeds quorum, but is not approved in time, the proposers should be able to re-submit as soon as they are able. This would happen in rare situations when approvers are unable to approve during the 7-day Referendum phase or the 3-day Execution phase.
# Smart Contract Upgradeability
Source: https://docs.celo.org/home/protocol/governance/smart-contracts-upgrades
Smart contracts deployed to an EVM blockchain like Celo are immutable. To allow for improvements, new features, and bug fixes, the Celo codebase uses the Proxy Upgrade Pattern. All of the core contracts owned by Governance are proxied. Thus, a smart contract implementation can be upgraded using the standard onchain governance process.
## Upgrade risks
The core contracts define critical behavior of the Celo network such as CELO and Celo Dollar asset management or validator elections and rewards. Malicious or inadvertent contract bugs could compromise user balances or potentially cause harm, irreversible without a blockchain hard fork.
Great care must be taken to ensure that any Governance proposal that modifies smart contract code will not break the existing system. To this end, the contracts have a well defined release process, which includes soliciting security audits from reputable third-party auditors.
As Celo is a decentralized network, all Celo network participants are invited to participate in the governance proposals discussions on the forum.
## Governance Hotfix Process
The Governance Hotfix process uses a multisig approach to handle critical security patches that need to be deployed quickly without going through the standard governance timeline.
The cadence and transparency of the standard onchain governance protocol make it poorly suited for proposals that patch issues that may compromise the security of the network, especially when the patch would reveal an exploitable bug in one of the core contracts. Instead, these sorts of changes are better suited for the more responsive hotfix protocol.
The current process requires approval from both an approver multisig and the Security Council multisig. The list of Security Council signers remains fixed, which simplifies the approval process. If a hotfix is not executed within the specified execution time limit, it must be reset and re-approved.
## Celo Blockchain Software Upgrades
Some changes cannot be made through the onchain governance process alone. Examples include changes to the underlying consensus protocol and changes which would result in a hard-fork.
# CeloCLI for Governance Proposals
Source: https://docs.celo.org/home/protocol/governance/voting-in-governance
How to use the [Celo CLI](/cli/) to participate in Goverance and create a Governance proposal.
***
## Governance
Celo uses a formal on-chain governance mechanism to manage and upgrade the protocol. More information about the Governance system can be found in the [Governance overview](/home/protocol/governance/overview).
In the following commands `` is used as a placeholder for something you should specify on the command line.
## Viewing Proposals
A list of active proposals can be viewed with the following command:
```bash theme={null}
celocli governance:list
```
Included will be three lists of proposals by status:
* **Queued** proposals have been submitted, but are not yet being considered. Voters can upvote proposals in this list, and proposals with the most upvotes from this list will be moved from the queue to be considered.
* **Dequeued** proposals are actively being considered and will pass through the Approval, Referendum, and Execution stages, as discussed in the [Governance overview](/home/protocol/governance/overview).
* **Expired** proposals are no longer being considered.
## Understanding Proposal Details
You can view information about a specific proposal with:
```bash theme={null}
celocli governance:show --proposalID=
```
For example, the proposal 14 on Mainnet was as follows:
```
Running Checks:
✔ 14 is an existing proposal
proposal:
0:
contract: Governance
function: setBaselineQuorumFactor
args:
0: 500000000000000000000000
params:
baselineQuorumFactor: 500000000000000000000000 (~5.000e+23)
value: 0
metadata:
proposer: 0xF3EB910DA09B8AF348E0E5B6636da442cFa79239
deposit: 100000000000000000000 (~1.000e+20)
timestamp: 1609961608 (~1.610e+9)
transactionCount: 1
descriptionURL: https://github.com/celo-org/governance/blob/main/CGPs/cgp-0016.md
stage: Referendum
upvotes: 0
votes:
Yes: 30992399904903465125627698 (~3.099e+25)
No: 0
Abstain: 0
passing: true
requirements:
constitutionThreshold: 0.7
support: 0.99883105743491071638
required: 29107673282861669327494319.531832308424 (~2.910e+25)
total: 30992399904903465125627698 (~3.099e+25)
isApproved: true
isProposalPassing: true
timeUntilStages:
referendum: past
execution: 57 minutes, 59 seconds
expiration: 3 days, 57 minutes, 59 seconds
```
To see how many votes a proposal needs to pass (depending on what type of commands are being executed), you can refer to the **requirements** section of the respose.
In the proposal above, there is a **constitutionThreshold** target of "0.7" or 70% of votes must be in support, "0.998" or 99.8% of votes have currently voted "yes", the number of votes required to pass are 29.1M CELO, with 30.9M CELO currently voted in total.
## Voting on Proposals
When a proposal is Queued, you can upvote the proposal to indicate you'd like it to be considered.
If you are using a Ledger wallet, make sure to include `--useLedger` and `--ledgerAddresses` in the
following commands.
```bash theme={null}
celocli governance:upvote --proposalID= --from=
```
At a defined frequency, which can be checked with the `celocli network:parameters` command, proposals can be dequeued, with the highest upvoted proposals being dequeued first.
After a proposal is dequeued, it will first enter the Approval phase.
In this phase, the [Governance Approver](/home/protocol/governance/overview#approval) may choose to approve the proposal, which will allow it to proceed to the Referendum phase after the configured length of time.
Once a proposal has reached the Referendum phase, it is open to community for voting.
```bash theme={null}
celocli governance:vote --proposalID= --value= --from=
```
## Executing a Proposal
If a Governance Proposal receives enough votes and passes in the Referendum phase, it can be executed by anyone.
```bash theme={null}
celocli governance:execute --proposalID= --from=
```
## Vote Delegation
[Contract Release 10](https://github.com/celo-org/celo-monorepo/issues/10375) introduced vote delegation, which allows the governance participant to delgate their voting power.
### Delegating Votes
You can delegate votes using the following command:
```bash theme={null}
celocli lockedgold:delegate --from --to --percent
```
**NOTE**
Currently, participants can only delegate to 10 delegatees.
You can view the max number of delegatees one can have using the following command:
```bash theme={null}
celocli lockedgold:max-delegatees-count
```
### Revoking Delegated Votes
You can use the following command to revoke delegated votes:
```bash theme={null}
celocli lockedgold:revoke-delegate --from --to --percent
```
For example, If you have delegated 15% to the delegatee and pass 5% as `percent` then 5% will be subtracted from the 15% resulting in 10% delegation.
### Total percent of Locked Celo delegated by an account
You can use the following command to get the total percent of locked celo delegated by an account:
```bash theme={null}
celocli lockedgold:delegate-info --account
```
### List of Delegatees of a Delegator
You can use the following command to get the list of delegatees of an account:
```bash theme={null}
celocli lockedgold:delegate-info --account
```
### Total Delegated Votes to an address
You can use the following command to get the total delegated votes to an address:
```bash theme={null}
celocli lockedgold:delegate-info --account
```
## Staying Informed
To stay up-to-date with all governance activities and proposals:
* Sign up for the [Celo Signal mailing list](https://share.hsforms.com/1Qrhush1vSA2WIamd_yL4ow53n4j)
* Add the [Celo Signal public calendar](https://calendar.google.com/calendar/u/0/embed?src=c_9su6ich1uhmetr4ob3sij6kaqs@group.calendar.google.com) to track important dates and events
* Follow discussions on the [Celo Forum](https://forum.celo.org/) in the Governance category
For more comprehensive information about Celo's governance system, see the [Governance Overview](/home/protocol/governance/overview) and [Voting in Governance](/home/protocol/governance/voting-in-governance) guides.
# Voting on Governance with Celo Mondo
Source: https://docs.celo.org/home/protocol/governance/voting-in-governance-using-mondo
Celo uses a formal onchain governance mechanism to manage and upgrade the protocol. This guide explains how to participate in governance using Celo Mondo.
***
## What is Celo Mondo?
Celo Mondo is a decentralized application for staking and governance within the Celo ecosystem. It enables users to lock and stake their CELO tokens to earn rewards and participate in the network's governance by voting on onchain proposals.
## Using Celo Mondo for Governance
With Celo Mondo, you can:
* View active and past governance proposals
* Vote on proposals with your locked CELO
* Delegate your voting power to another address
* Track proposal status and outcomes
## Getting Started
* [Launch Celo Mondo](https://mondo.celo.org/governance)
* [Celo Mondo GitHub](https://github.com/celo-org/celo-mondo)
* [Become a Delegate](https://mondo.celo.org/delegate)
## Staying Informed
To stay up-to-date with all governance activities and proposals:
* Sign up for the [Celo Signal mailing list](https://share.hsforms.com/1Qrhush1vSA2WIamd_yL4ow53n4j)
* Add the [Celo Signal public calendar](https://calendar.google.com/calendar/u/0/embed?src=c_9su6ich1uhmetr4ob3sij6kaqs@group.calendar.google.com) to track important dates and events
* Follow discussions on the [Celo Forum](https://forum.celo.org/) in the Governance category
For more comprehensive information about Celo's governance system, see the [Governance Overview](/home/protocol/governance/overview) and [Voting in Governance](/home/protocol/governance/voting-in-governance) guides.
# Celo Protocol
Source: https://docs.celo.org/home/protocol/index
Introduction to the Celo protocol, its implementation, and its relationship to Ethereum.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
## What is the Celo Protocol?
Celo's blockchain reference implementation is based on go-ethereum, the Go implementation of the Ethereum protocol. The project team is indebted to the Geth community for providing these shoulders to stand on and, while recognizing that Ethereum is an independent project with its own trajectory, hopes to contribute changes where it makes sense to do so.
In addition to the blockchain client, there are some core components of the Celo protocol that are implemented at the smart contract level and even off-chain (e.g. phone number verification via SMS). Some of these core components have become their own protocol, e.g. Mento and Self.
## Protocol Upgrades
There are a number of substantial changes and additions have been made in service of Celo's product goals, including the following:
* [Consensus](/legacy/protocol/consensus/index)
* [Governance](/home/protocol/governance/overview)
* [Stability Mechanism - Mento](https://www.mento.org/)
* [Transactions](/legacy/protocol/transaction/index)
* [Identity - Self](https://self.xyz/)
# Security Council
Source: https://docs.celo.org/home/protocol/security-council
Introduction to the Celo Security Council. This page captures the key points about the proposed Security Council and its role in the Celo L2 Network.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
This page is a work in progress based on the [proposal for the Celo L2's
Security
Council](https://forum.celo.org/t/proposing-celo-l2s-security-council/10578/1).
For updates make sure to refer to the [Celo Forum](https://forum.celo.org).
### Celo L2 Security Council Overview
* **Purpose**:
* To decentralize the Celo L2 Network.
* Manage key upgrades and security fixes.
* **Responsibilities**:
* Upgrade L1 protocol contracts for Celo's L2.
* Modify designations for roles like sequencers, proposers, and challengers.
* Execute urgent security fixes via hotfixes.
* Act independently in urgent situations for the network's best interest.
* **Decentralization Goals**:
* Prevent any single entity from upgrading the system, modifying rollup state, or censoring transactions.
* **Governance**:
* Regular Governance Process for Celo Core Contracts and Community Fund remains unchanged.
* **Proposed Multisig Structure**:
* **2/2 Safe Multisig**:
* Members: cLabs Multisig and Celo Community Security Council.
* **cLabs Multisig**: 6/8 multisig.
* **Celo Community Security Council**: 6/8 multisig with members from L2Beat, Hyperlane, Valora, Mento, Nitya Subramanian, Kris Kaczor, Tim Moreton, and Aaron Boyd.
* Ensures non-cLabs controlled quorum-blocking group.
* **Security Standards**:
* Follow Optimism multisig security policy.
* Allow nested multisigs if all signers adhere to the security policy.
# Transactions on Celo
Source: https://docs.celo.org/home/protocol/transactions/overview
In Celo's transition to a Layer 2 (L2) solution, several key changes have been proposed to the network's tokenomics, particularly concerning gas pricing and transaction fee allocation.
***
This section is a work in progress and based on the ["The Great Celo Halvening - Proposed Tokenomics in the Era of Celo L2"](https://forum.celo.org/t/the-great-celo-halvening-proposed-tokenomics-in-the-era-of-celo-l2/9701/1). Please check the [forum](https://forum.celo.org/) for the latest information.
## Gas Pricing Mechanism
Celo employs a gas pricing model based on **EIP-1559**, which dynamically adjusts the base fee to manage network demand. This mechanism ensures that gas prices respond to network congestion, increasing during high demand periods and decreasing when demand is low. The protocol sets a **base fee floor** to prevent the base fee from falling below a certain threshold, safeguarding the network against spam transactions and uncontrolled state growth.
## Fee Abstraction
A notable feature of Celo's network is **fee abstraction**, allowing users to pay transaction fees
using approved ERC-20 tokens such as USDT, USDC, USDm, and others, in addition to the native CELO
token. This flexibility simplifies the user experience by eliminating the need to hold a separate
CELO balance for gas fees. To utilize this feature, transactions include a `feeCurrency` field
specifying the token for gas payment. It's important to note that transactions specifying non-CELO
gas currencies incur approximately 50,000 additional gas units.
Celo allows paying gas fees in currencies other than the native currency. The tokens that can be
used to pay gas fees are controlled via governance and the list of tokens allowed is maintained in
FeeCurrencyDirectory.sol. Fee abstraction on Celo works with EOAs. No paymaster required! Learn all
about [fee abstraction](/build-on-celo/fee-abstraction/overview).
## Transaction Fee Allocation Post-L2 Transition
With the shift to L2, the allocation of transaction fees has been restructured to support the network's evolving operational needs:
* [**Carbon Offset Fund**](/home/protocol/epoch-rewards/carbon-offsetting-fund): 10% of transaction fees continue to support the carbon offset fund, maintaining Celo's environmental commitment. This adjustment reflects the network's reduced carbon footprint following the L2 upgrade.
* **Network Operations**: The remaining 90% of transaction fees are allocated to essential network operations, including:
* **Data Availability**: Ensuring that transaction data is accessible and secure.
* **Layer 1 Fees**: Covering costs associated with interactions between Celo's L2 and the Ethereum mainnet.
* **Sequencer and Batcher Operations**: Supporting the infrastructure that orders and batches transactions on the network.
* **Revenue Sharing with the OP-Stack**: Complying with the Superchain Ecosystem requirements, which involve sharing revenue with the OP-Stack.
This reallocation ensures that transaction fees are utilized effectively to maintain network sustainability and operational efficiency in the L2 environment.
## Conclusion
Celo's transition to L2 introduces significant changes to gas pricing and transaction fee allocation, aligning with the network's goals of sustainability, user accessibility, and robust operational support. These adjustments are designed to enhance the overall efficiency and resilience of the Celo ecosystem.
# Transaction Types on Celo
Source: https://docs.celo.org/home/protocol/transactions/transaction-types
This page contains an explainer on transaction types supported on Celo and a demo to make specific transactions.
***
## Summary
Celo has support for all Ethereum transaction types (i.e. "100% Ethereum compatibility") and a single Celo transaction type.
### Actively Supported on Celo
| Chain | Transaction type | # | Specification | Recommended | Support | Comment |
| --------------- | -------------------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | --------- | -------------------------------------------------------- |
| | Dynamic fee transaction v2 | `123` | [CIP-64](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0064.md) | ✅ | Active 🟢 | Supports paying gas in custom fee currencies |
| | Set code transaction | `4` | [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) | Available since the Isthmus hardfork | | |
| | Dynamic fee transaction | `2` | [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) ([CIP-42](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0042.md)) | ✅ | Active 🟢 | Typical Ethereum transaction |
| | Access list transaction | `1` | [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930) ([CIP-35](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0035.md)) | ❌ | Active 🟢 | Does not support dynamically changing *base fee* per gas |
| | Legacy transaction | `0` | [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf) ([CIP-35](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0035.md)) | ❌ | Active 🟢 | Does not support dynamically changing *base fee* per gas |
### Deprecated on Celo
| Chain | Transaction type | # | Specification | Support | Comment |
| --------------- | ----------------------- | ----- | -------------------------------------------------------------------------------------------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| | Dynamic fee transaction | `124` | [CIP-42](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0042.md) | Deprecated 🔴 | Deprecation warning published in [Gingerbread hard fork](https://github.com/celo-org/celo-proposals/blob/8260b49b2ec9a87ded6727fec7d9104586eb0752/CIPs/cip-0062.md#deprecation-warning) and no longer supported following the transition to Celo L2 |
| | Legacy transaction | `0` | Celo Mainnet launch ([Blockchain client v1.0.0](https://github.com/celo-org/celo-blockchain/tree/celo-v1.0.0)) | Deprecated 🔴 | Deprecation warning published in [Gingerbread hard fork](https://github.com/celo-org/celo-proposals/blob/8260b49b2ec9a87ded6727fec7d9104586eb0752/CIPs/cip-0062.md#deprecation-warning) and no longer supported following the transition to Celo L2 |
The stages of support are:
* **Active support** 🟢: the transaction type is supported and recommended for use.
* **Security support** 🟠: the transaction type is supported but not recommended for use
because it might be deprecated in the future.
* **Deprecated** 🔴: the transaction type is not supported and not recommended for use.
### Client Library Support
Legend:
* =
support for the recommended Ethereum transaction type (`2`)
* = support
for the recommended Celo transaction type (`123`)
* ✅ = available
* ❌ = not available
| Client library | Language | | | since | Comment |
| --------------------- | :------: | :-------------: | :-------------- | --------------------------------------------------------------------------- | ------------------------------------------------ |
| `viem` | TS/JS | ✅ | ✅ | >[1.19.5][1] | --- |
| `ethers` | TS/JS | ✅ | ❌ | | Support via fork in `celo-ethers-wrapper` |
| `celo-ethers-wrapper` | TS/JS | ✅ | ✅ | >[2.0.0](https://github.com/jmrossy/celo-ethers-wrapper/releases/tag/2.0.0) | --- |
| `web3js` | TS/JS | ✅ | ❌ | | Support via fork in `contractkit` |
| `contractkit` | TS/JS | ✅ | ✅ | >[5.0.0](https://github.com/celo-org/celo-monorepo/releases/tag/v5.0) | --- |
| `Web3j` | Java | ✅ | ❌ | | --- |
| `rust-ethers` | Rust | ✅ | ❌ | | --- |
| `brownie` | Python | ✅ | ❌ | | --- |
[1]: https://github.com/wevm/viem/blob/main/src/CHANGELOG.md#1195
## Background
### Legacy Transactions
Ethereum originally had one format for transactions (now called "legacy transactions").
A legacy transaction contains the following transaction parameters:
`nonce`, `gasPrice`, `gasLimit`, `recipient`, `amount`, `data`, and `chaindId`.
To produce a valid "legacy transaction":
1. the **transaction parameters** are [RLP-encoded](https://eth.wiki/fundamentals/rlp):
```
RLP([nonce, gasprice, gaslimit, recipient, amount, data, chaindId, 0, 0])
```
2. the RLP-encoded transaction is hashed (using Keccak256).
3. the hash is signed with a private key using the ECDSA algorithm, which generates the `v`, `r`,
and `s` **signature parameters**.
4. the transaction *and* signature parameters above are RLP-encoded to produce a valid **signed
transaction**:
```
RLP([nonce, gasprice, gaslimit, recipient, amount, data, v, r, s])
```
A valid signed transaction can then be submitted on-chain, and its raw parameters can be
parsed by RLP-decoding the transaction.
### Typed Transactions
Over time, the Ethereum community has sought to add new types of transactions
such as dynamic fee transactions
([EIP-1559: Fee market change for ETH 1.0 chain](https://eips.ethereum.org/EIPS/eip-1559))
or optional access list transactions
([EIP-2930: Optional access lists](https://eips.ethereum.org/EIPS/eip-2930))
to supported new desired behaviors on the network.
To allow new transactions to be supported without breaking support with the
legacy transaction format, the concept of **typed transactions** was proposed in
[EIP-2718: Typed Transaction Envelope](https://eips.ethereum.org/EIPS/eip-2718), which introduces
a new high-level transaction format that is used to implement all future transaction types.
### Distinguishing Between Legacy and Typed Transactions
Whereas a valid "legacy transaction" is simply an RLP-encoded list of
**transaction parameters**, a valid "typed transactions" is an arbitrary byte array
prepended with a **transaction type**, where:
* a **transaction type**, is a number between 0 (`0x00`) and 127 (`0x7f`) representing
the type of the transaction, and
* a **transaction payload**, is arbitrary byte data that encodes raw transaction parameters
in compliance with the specified transaction type.
To distinguish between legacy transactions and typed transactions at the client level,
the EIP designers observed that the **first byte** of a legacy transaction would never be in the range
`[0, 0x7f]` (or `[0, 127]`), and instead always be in the range `[0xc0, 0xfe]` (or `[192, 254]`).
With that observation, transactions can be decoded with the following heuristic:
* read the first byte of a transaction
* if it's bigger than `0x7f` (`127`), then it's a **legacy transaction**. To decode it, you
must read *all* bytes (including the first byte just read) and interpret them as a
legacy transaction.
* else, if it's smaller or equal to `0x7f` (`127`), then it's a **typed transaction**. To decode
it you must read the *remaining* bytes (excluding the first byte just read) and interpret them
according to the specified transaction type.
Every transaction type is defined in an EIP, which specifies how to *encode* as well as *decode*
transaction payloads. This means that a typed transaction can only be interpreted with knowledge of
its transaction type and a relevant decoder.
## List of Transaction Types on Celo
### Legacy Transaction (`0`)
This transaction type is 100% compatible with Ethereum and has no Celo-specific parameters.
Although legacy transactions are never formally prepended with the `0x00` transaction type,
they are commonly referred to as "type 0" transactions.
* This transaction is defined as follows:
```
RLP([nonce, gasprice, gaslimit, recipient, amount, data, v, r, s])
```
* It was introduced on Ethereum during Mainnet launch on [Jul 30, 2015](https://en.wikipedia.org/wiki/Ethereum)
as specified in the [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf).
* It was introduced on Celo during the
[Celo Donut hard fork](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0027.md)
on [May 19, 2021](https://blog.celo.org/donut-hardfork-is-live-on-celo-585e2e294dcb)
as specified in [CIP-35: Support for Ethereum-compatible transactions](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0035.md).
### Access List Transaction (`1`)
This transaction type is 100% compatible with Ethereum and has no Celo-specific parameters.
* This transaction is defined as follows:
```
0x01 || RLP([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, signatureYParity, signatureR, signatureS])
```
* It was introduced on Ethereum during the Ethereum Berlin hard fork on
[Apr, 15 2021](https://ethereum.org/en/history/#berlin) as specified in
[EIP-2930: Optional access lists](https://eips.ethereum.org/EIPS/eip-2930).
* It was introduced on Celo during the
[Celo Donut hard fork](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0027.md)
on [May 19, 2021](https://blog.celo.org/donut-hardfork-is-live-on-celo-585e2e294dcb)
as specified in [CIP-35: Support for Ethereum-compatible transactions](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0035.md).
### Dynamic Fee Transaction (`2`)
This transaction type is 100% compatible with Ethereum and has no Celo-specific parameters.
* This transaction is defined as follows:
```
0x02 || RLP([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, data, accessList, signatureYParity, signatureR, signatureS])
```
* It was introduced on Ethereum during the Ethereum London hard fork on
[Aug, 5 2021](https://ethereum.org/en/history/#london) as specified in
[EIP-1559: Fee market change for ETH 1.0 chain](https://eips.ethereum.org/EIPS/eip-1559).
* It was introduced on Celo during the
[Celo Espresso hard fork](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0041.md)
on [Mar 8, 2022](https://blog.celo.org/brewing-the-espresso-hardfork-92a696af1a17) as specified
in [CIP-42: Modification to EIP-1559](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0042.md)
### Set Code Transaction (`4`)
This transaction type is 100% compatible with Ethereum and has no Celo-specific parameters.
* This transaction is defined as follows:
```
0x04 || RLP([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, data, accessList, authorizationList, signatureYParity, signatureR, signatureS])
```
* It was introduced on Ethereum during the Ethereum Pectra hard fork on
[May, 7 2025](https://ethereum.org/en/history/#pectra) as specified in
[EIP-7702: Set Code for EOAs](https://eips.ethereum.org/EIPS/eip-7702).
* It is scheduled for support on Celo during the
[Celo Isthmus](/infra-partners/notices/archive/isthmus-upgrade) hardfork.
### Legacy Transaction (`0`)
This transaction type is no longer supported following the migration to Celo L2.
This transaction is not compatible with Ethereum and has three Celo-specific
parameters: `feecurrency`, `gatewayfeerecipient`, and `gatewayfee`.
* This transaction is defined as follows:
```
RLP([nonce, gasprice, gaslimit, feecurrency, gatewayfeerecipient, gatewayfee, recipient, amount, data, v, r, s])
```
* It was introduced on Celo during Mainnet launch on
[Apr 22, 2020](https://dune.com/queries/3106924/5185945) as specified in
[Blockchain client v1.0.0](https://github.com/celo-org/celo-blockchain/tree/celo-v1.0.0).
### Dynamic Fee Transaction (`124`)
This transaction type is no longer supported following the migration to Celo L2.
This transaction is not compatible with Ethereum and has three Celo-specific
parameters: `feecurrency`, `gatewayfeerecipient`, and `gatewayfee`.
> **Warning**
> This transaction type is scheduled for deprecation. A deprecation warning was published in the
> [Gingerbread hard fork](https://github.com/celo-org/celo-proposals/blob/8260b49b2ec9a87ded6727fec7d9104586eb0752/CIPs/cip-0062.md#deprecation-warning)
> on [Sep 26, 2023](https://forum.celo.org/t/mainnet-alfajores-gingerbread-hard-fork-release-sep-26-17-00-utc/6499).
* This transaction is defined as follows:
```
0x7c || RLP([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, feecurrency, gatewayfeerecipient, gatewayfee, destination, amount, data, access_list, v, r, s])
```
* It was introduced on Celo during the
[Celo Espresso hard fork](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0041.md)
on [Mar 8, 2022](https://blog.celo.org/brewing-the-espresso-hardfork-92a696af1a17) as specified
in [CIP-42: Modification to EIP-1559](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0042.md).
### Dynamic Fee Transaction v2 (`123`)
This transaction is not compatible with Ethereum and has one Celo-specific
parameter: `feecurrency`.
* This transaction is defined as follows:
```
0x7b || RLP([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, data, accessList, feeCurrency, v, r, s])
```
* It was introduced on Celo during the
[Celo Gingerbread hard fork](https://github.com/celo-org/celo-proposals/blob/8260b49b2ec9a87ded6727fec7d9104586eb0752/CIPs/cip-0062.md)
on [Sep 26, 2023](https://forum.celo.org/t/mainnet-alfajores-gingerbread-hard-fork-release-sep-26-17-00-utc/6499)
as specified in
[CIP-64: New Transaction Type: Celo Dynamic Fee v2](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0064.md)
## How to Send Transactions
### Import Dependencies
```ts theme={null}
import {
createPublicClient,
createWalletClient,
hexToBigInt,
http,
parseEther,
parseGwei,
} from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { celoAlfajores } from "viem/chains";
import "dotenv/config"; // use to read private key from environment variable
```
### Create Public and Wallet Client
```ts theme={null}
const PRIVATE_KEY = process.env.PRIVATE_KEY;
/**
* Boilerplate to create a viem client
*/
const account = privateKeyToAccount(`0x${PRIVATE_KEY}`);
const publicClient = createPublicClient({
chain: celoAlfajores,
transport: http(),
});
const walletClient = createWalletClient({
chain: celoAlfajores, // Celo testnet
transport: http(),
});
```
### Function to Print Transaction Receipt
```ts theme={null}
function printFormattedTransactionReceipt(transactionReceipt: any) {
const {
blockHash,
blockNumber,
contractAddress,
cumulativeGasUsed,
effectiveGasPrice,
from,
gasUsed,
logs,
logsBloom,
status,
to,
transactionHash,
transactionIndex,
type,
feeCurrency,
gatewayFee,
gatewayFeeRecipient
} = transactionReceipt;
const filteredTransactionReceipt = {
type,
status,
transactionHash,
from,
to
};
console.log(`Transaction details:`, filteredTransactionReceipt, `\n`);
}
```
### Code to Send Transaction Type (0)
```ts theme={null}
/**
- Transation type: 0 (0x00)
- Name: "Legacy"
- Description: Ethereum legacy transaction
*/
async function demoLegacyTransactionType() {
console.log(`Initiating legacy transaction...`);
const transactionHash = await walletClient.sendTransaction({
account, // Sender
to: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", // Recipient (illustrative address)
value: parseEther("0.01"), // 0.01 CELO
gasPrice: parseGwei("20"), // Special field for legacy transaction type
});
const transactionReceipt = await publicClient.waitForTransactionReceipt({
hash: await transactionHash,
});
printFormattedTransactionReceipt(transactionReceipt);
}
```
### Code to Send Transaction Type (2)
```ts theme={null}
/**
* Transaction type: 2 (0x02)
* Name: "Dynamic fee"
* Description: Ethereum EIP-1559 transaction
*/
async function demoDynamicFeeTransactionType() {
console.log(`Initiating dynamic fee (EIP-1559) transaction...`);
const transactionHash = await walletClient.sendTransaction({
account, // Sender
to: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", // Recipient (illustrative address)
value: parseEther("0.01"), // 0.01 CELO
maxFeePerGas: parseGwei("10"), // Special field for dynamic fee transaction type (EIP-1559)
maxPriorityFeePerGas: parseGwei("10"), // Special field for dynamic fee transaction type (EIP-1559)
});
const transactionReceipt = await publicClient.waitForTransactionReceipt({
hash: await transactionHash,
});
printFormattedTransactionReceipt(transactionReceipt);
}
```
### Code to Send Transaction Type (123)
```ts theme={null}
/**
* Transaction type: 123 (0x7b)
* Name: "Dynamic fee"
* Description: Celo dynamic fee transaction (with custom fee currency)
*/
async function demoFeeCurrencyTransactionType() {
console.log(`Initiating custom fee currency transaction...`);
const transactionHash = await walletClient.sendTransaction({
account, // Sender
to: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", // Recipient (illustrative address)
value: parseEther("0.01"), // 0.01 CELO
feeCurrency: "0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1", // USDm fee currency
maxFeePerGas: parseGwei("10"), // Special field for dynamic fee transaction type (EIP-1559)
maxPriorityFeePerGas: parseGwei("10"), // Special field for dynamic fee transaction type (EIP-1559)
});
const transactionReceipt = await publicClient.waitForTransactionReceipt({
hash: await transactionHash,
});
printFormattedTransactionReceipt(transactionReceipt);
}
```
# Encrypted Payment Comments
Source: https://docs.celo.org/home/protocol/transactions/tx-comment-encryption
In this section, you will find detailed information about the various transaction types supported on Celo, including encrypted payment comments and their technical details, as well as insights into gas pricing and fee abstraction.
***
## Introduction to Comment Encryption
As part of Celo's identity protocol, a public encryption key is stored along with a user's address in the `Accounts` contract.
Both the address key pair and the encryption key pair are derived from the backup phrase. When sending a transaction the encryption key of the recipient is retrieved when getting his or her address. The comment is then encrypted using a 128 bit hybrid encryption scheme (ECDH on secp256k1 with AES-128-CTR). This system ensures that comments can only be read by the sending and receiving parties and that messages will be recovered when restoring a wallet from its backup phrase.
## Comment Encryption Technical Details
A 128 bit randomly generated session key, sk, is generated and used to symmetrically encrypt the comment. sk is asymmetrically encrypted to the sender and to the recipient.
`Encrypted = ECIES(sk, to=pubSelf) | ECIES(sk, to=pubOther) | AES(ke=sk, km=sk, comment)`
### Symmetric Encryption (AES-128-CTR)
* Takes encryption key, ke, and MAC key, km, and the data to encrypt, plaintext
* Cipher: AES-128-CTR using a randomly generated iv
* Authenticate iv | ciphertext using HMAC with SHA-256 and km
* Return iv | ciphertext | mac
### Asymmetric Encryption (ECIES)
1. Takes data to encrypt, plaintext, and the public key of the recipient, pubKeyTo
2. Generate an ephemeral keypair, ephemPubKey and ephemPrivKey
3. Derive 32 bytes of key material, k, from ECDH between ephemPrivKey and pubKeyTousing ConcatKDF (specified as NIST 800-56C Rev 1 One Step KDF) with SHA-256 for H(x)
4. The encryption key, ke, is the first 128 bits of k
5. The MAC key, km, is SHA-256 of the second 128 bits of k
6. Encrypt the plaintext symmetrically with AES-128-CTR using ke, km, and a random iv
7. Return ephemPubKey | AES-128-CTR-HMAC(ke, km, plaintext) where the public key needs to be uncompressed (current limitation with decrypt).
# Celo Global Ramps Ecosystem
Source: https://docs.celo.org/home/ramps
Explore Celo's on-ramp and off-ramp providers for converting between fiat and crypto across 127+ countries using mobile money, cards, and bank transfers.
## Overview
On and off-ramps are fundamental infrastructure for bridging traditional finance (TradFi) and decentralized finance (DeFi), enabling users worldwide to convert between fiat currencies and digital assets seamlessly. Since its inception, Celo has prioritized building a comprehensive ramp ecosystem to support real-world use cases and drive mainstream adoption of digital currencies.
### What are Ramps?
**On-ramps** allow users to purchase cryptocurrencies using traditional payment methods like bank transfers, credit cards, or mobile money. **Off-ramps** enable users to convert their digital assets back to fiat currency and withdraw to their bank accounts or mobile wallets.
### Why Ramps Matter for Celo
Celo's mission to build a financial system that creates conditions for prosperity for everyone requires robust infrastructure that connects the traditional financial world with the blockchain ecosystem. Our comprehensive ramp network enables:
* **Financial Inclusion**: Supporting users in emerging markets with mobile-first payment solutions
* **Global Accessibility**: Coverage across 127+ countries with localized payment methods
* **Seamless UX**: Reducing friction for users entering and exiting the Celo ecosystem
* **Real-World Utility**: Enabling practical use cases for digital currencies in everyday transactions
***
## Important Disclaimer
**This directory provides a list of ramp providers and their basic availability information only**. Before using any provider, users should independently verify current fee structures, transaction limits, processing times, and KYC requirements specific to their region. Developers must obtain proper API documentation, technical specifications, and access to testing environments directly from each provider. Always confirm regulatory compliance, licensing status, and security certifications in your jurisdiction before integration or use. **Celo does not endorse or guarantee the services of these providers - conduct your own due diligence.**
*Last updated: 06/24/2025*
***
## Integrated Ramp Providers
Below you'll find our complete network of 21+ integrated ramp providers, covering diverse payment methods from traditional banking to mobile money solutions across six continents.
## [Banxa](https://banxa.com/)
**Countries**
* Andorra
* Angola
* Antigua and Barbuda
* Argentina
* Armenia
* Aruba
* Australia
* Austria
* Azerbaijan
* Bahrain
* Bangladesh
* Barbados
* Belgium
* Belize
* Benin
* Bhutan
* Bolivia
* Botswana
* Brazil
* Brunei Darussalam
* Bulgaria
* Cabo Verde
* Cambodia
* Cameroon
* Canada
* Cayman Islands
* Chad
* Chile
* Colombia
* Comoros
* Costa Rica
* Croatia
* Cyprus
* Czechia
* Denmark
* Djibouti
* Dominica
* Dominican Republic
* Ecuador
* Egypt
* El Salvador
* Equatorial Guinea
* Estonia
* Falkland Island
* Faroe Islands
* Fiji
* France
* French Polynesia
* Gambia
* Georgia
* Germany
* Ghana
* Greece
* Grenada
* Guatemala
* Guyana
* Honduras
* Hong Kong
* Hungary
* Iceland
* India
* Indonesia
* Ireland
* Israel
* Italy
* Jamaica
* Japan
* Jersey
* Jordan
* Kazakhstan
* Kenya
* Kiribati
* Kuwait
* Kyrgyzstan
* Laos
* Latvia
* Lesotho
* Liechtenstein
* Lithuania
* Luxembourg
* Madagascar
* Malawi
* Malaysia
* Maldives
* Marshall Islands
* Mauritania
* Mauritius
* Mexico
* Monaco
* Montenegro
* Morocco
* Mozambique
* Namibia
* Nauru
* Nepal
* Netherlands
* New Zealand
* Niue
* Norfolk Island
* North Macedonia
* Northern Mariana Islands
* Norway
* Oman
* Pakistan
* Palau
* Panama
* Papua New Guinea
* Paraguay
* Peru
* Philippines
* Poland
* Portugal
* Puerto Rico
* Qatar
* Réunion
* Romania
* Rwanda
* Samoa
* San Marino
* Saudi Arabia
* Senegal
* Serbia
* Seychelles
* Sierra Leone
* Singapore
* Slovenia
* Solomon Islands
* South Africa
* South Korea
* Spain
* St. Martin
* Suriname
* Swaziland
* Sweden
* Switzerland
* Tajikistan
* Tanzania
* Thailand
* Timor-Leste
* Togo
* Tonga
* Trinidad and Tobago
* Turkey
* Turkmenistan
* Turks and Caicos Islands
* Tuvalu
* Uganda
* United Arab Emirates
* United Kingdom
* United States
* Uruguay
* Uzbekistan
* Vatican
* Vietnam
* Wallis and Futuna
* Zambia
**Payment Method**
* Card Payment
* Manual Bank Transfer (SEPA)
**Currency**
* USDT
* CELO
* USDm
***
## Bitfy
**Countries**
* Brazil
**Payment Method**
* Bank Transfer (PIX)
**Currency**
* CELO
* USDm
***
## [Bitmama](https://bitmama.io/)
**Countries**
* Ghana
* Nigeria
**Payment Method**
* Bank Transfer
* Mobile Money
**Currency**
* CELO
* USDm
***
## [Bridge](https://www.bridge.xyz/) (Developer API)
**Developer infrastructure, not a consumer ramp.** Bridge powers other apps to add fiat on/off ramps via API rather than letting end users buy crypto directly. See the [Bridge API docs](https://apidocs.bridge.xyz) for the developer guide.
**Countries**
Global coverage via supported fiat rails. See the [Bridge supported countries list](https://apidocs.bridge.xyz/platform/customers/compliance/supported-countries-list).
**Payment Method**
* ACH and Wire (USD)
* SEPA (EUR)
* SPEI (MXN)
* Pix (BRL)
* Faster Payments (GBP)
* Bre-B and Bank Transfer PSE/ACH (COP, beta)
**Currency**
* USDC
***
## [Cashramp](https://cashramp.co/)
**Countries**
* Nigeria
* Ghana
* Kenya
* Uganda
**Payment Method**
* Bank Transfer
**Currency**
* USDT
* USDC
* CELO
* USDm
***
## [Cobru](https://cobru.co/)
**Countries**
* Colombia
**Payment Method**
* Bank Transfer (SPEI)
**Currency**
* USDT
* USDC
***
## [El Dorado](https://eldorado.io/en/)
**Countries**
* Argentina
* Colombia
* Panama
* Venezuela
**Payment Method**
* Bank Transfer
**Currency**
* USDT
* USDC
***
## [FlowBTC](https://www.flowbtc.com.br/)
**Countries**
* Brazil
**Payment Method**
* Bank Transfer (PIX)
**Currency**
* CELO
* USDm
***
## [Fonbnk](https://www.fonbnk.com/)
**Countries**
* Ghana
* Kenya
* Nigeria
* South Africa
* Tanzania
**Payment Method**
* Mobile Money
**Currency**
* USDT
* USDC
* CELO
* USDm
***
## [Gcash](https://new.gcash.com/)
**Countries**
* Philippines
**Payment Method**
* Mobile Wallet (Gcash)
***
## [Kotani Pay](https://kotanipay.com/)
**Countries**
* Kenya
* Tanzania
* Uganda
**Payment Method**
* Mobile Money
**Currency**
* USDT
* USDC
***
## [Moonpay](https://www.moonpay.com/en-gb)
**Countries**
* Algeria
* Andorra
* Angola
* Antigua and Barbuda
* Argentina
* Armenia
* Australia
* Austria
* Azerbaijan
* Bahrain
* Belgium
* Brazil
* Bulgaria
* Canada
* Colombia
* Croatia
* Cyprus
* Czechia
* Denmark
* Dominica
* Dominican Republic
* Egypt
* El Salvador
* Estonia
* France
* Germany
* Greece
* Hong Kong
* Indonesia
* Ireland
* Israel
* Italy
* Jordan
* Kenya
* Kiribati
* Kuwait
* Latvia
* Liechtenstein
* Lithuania
* Luxembourg
* Marshall Islands
* Mexico
* Monaco
* Montenegro
* Nauru
* Netherlands
* New Zealand
* Nigeria
* Norway
* Oman
* Palau
* Peru
* Poland
* Portugal
* Romania
* San Marino
* Slovenia
* South Africa
* Spain
* Sri Lanka
* Sweden
* Switzerland
* Thailand
* Timor-Leste
* Turkey
* Tuvalu
* United Kingdom
* Vatican
* Vietnam
**Payment Method**
* Card Payment
* Manual Bank Transfer (SEPA)
**Currency**
* USDT
* USDC
***
## [Partna](https://getpartna.com/)
**Countries**
* Nigeria
**Payment Method**
* Bank Transfer
**Currency**
* USDT
* USDC
***
## [Paychant](https://paychant.com/)
**Countries**
* Nigeria
* Kenya
* Ghana
* Uganda
* Zambia
**Payment Method**
* Bank Transfer
**Currency**
* USDT
* USDC
***
## [Ramp Network](https://ramp.network/)
**Countries**
* Albania
* Andorra
* Angola
* Antigua and Barbuda
* Argentina
* Australia
* Austria
* Belgium
* Belize
* Bhutan
* Bosnia and Herzegovina
* Botswana
* Brazil
* Bulgaria
* Cabo Verde
* Canada
* Chile
* Comoros
* Costa Rica
* Croatia
* Cyprus
* Czechia
* Denmark
* Djibouti
* Dominica
* Dominican Republic
* El Salvador
* Equatorial Guinea
* Estonia
* Eswatini
* Ethiopia
* Falkland Island
* Faroe Islands
* Finland
* France
* French Polynesia
* Gambia
* Georgia
* Germany
* Ghana
* Greece
* Grenada
* Guatemala
* Guinea
* Honduras
* Hong Kong
* Hungary
* Iceland
* India
* Ireland
* Israel
* Italy
* Jersey
* Kazakhstan
* Kenya
* Kiribati
* Kuwait
* Laos
* Latvia
* Liechtenstein
* Lithuania
* Luxembourg
* Madagascar
* Malawi
* Malaysia
* Malta
* Marshall Islands
* Mauritania
* Mexico
* Moldova
* Monaco
* Montenegro
* Mozambique
* Nauru
* Netherlands
* New Zealand
* Niue
* Norfolk Island
* North Macedonia
* Northern Mariana Islands
* Norway
* Papua New Guinea
* Paraguay
* Peru
* Philippines
* Poland
* Portugal
* Réunion
* Romania
* Rwanda
* San Marino
* Sao Tome and Principe
* Senegal
* Serbia
* Sierra Leone
* Singapore
* Sint Maarten
* Slovenia
* Solomon Islands
* South Africa
* Spain
* Sri Lanka
* St. Lucia
* St. Martin
* St. Vincent and the Grenadines
* Suriname
* Sweden
* Switzerland
* Tajikistan
* Thailand
* Timor-Leste
* Togo
* Tonga
* Turkey
* Turkmenistan
* Turks and Caicos Islands
* Tuvalu
* Ukraine
* United Kingdom
* United States
* Uruguay
* Uzbekistan
* Vatican
* Wallis and Futuna
* Zambia
**Payment Method**
* Card Payment
* Manual Bank Transfer (SEPA)
**Currency**
* USDT
* USDC
***
## [Simplex](https://www.simplex.com/)
**Countries**
* Andorra
* Antigua and Barbuda
* Argentina
* Armenia
* Aruba
* Australia
* Austria
* Azerbaijan
* Bahamas, The
* Bahrain
* Belgium
* Belize
* Benin
* Bhutan
* Bosnia and Herzegovina
* Botswana
* Brazil
* Brunei Darussalam
* Cabo Verde
* Canada
* Central African Republic
* Chad
* Chile
* Colombia
* Comoros
* Costa Rica
* Cyprus
* Czechia
* Denmark
* Djibouti
* Dominica
* Dominican Republic
* Ecuador
* Egypt
* El Salvador
* Equatorial Guinea
* Eritrea
* Estonia
* Eswatini
* Ethiopia
* Falkland Island
* Faroe Islands
* Fiji
* Finland
* France
* French Polynesia
* Gabon
* Gambia
* Georgia
* Germany
* Ghana
* Greece
* Grenada
* Guatemala
* Guinea
* Guinea-Bissau
* Guyana
* Honduras
* Hong Kong
* Hungary
* Iceland
* India
* Indonesia
* Ireland
* Israel
* Italy
* Japan
* Jersey
* Kazakhstan
* Kiribati
* Kosovo
* Kuwait
* Laos
* Latvia
* Lesotho
* Liberia
* Liechtenstein
* Lithuania
* Luxembourg
* Madagascar
* Malawi
* Malaysia
* Maldives
* Mali
* Malta
* Marshall Islands
* Mauritania
* Mauritius
* Mexico
* Moldova
* Mongolia
* Montenegro
* Nauru
* Nepal
* Netherlands
* New Zealand
* Niue
* Norfolk Island
* North Macedonia
* Northern Mariana Islands
* Norway
* Oman
* Palau
* Papua New Guinea
* Paraguay
* Peru
* Poland
* Portugal
* Puerto Rico
* Qatar
* Réunion
* Romania
* Rwanda
* Samoa
* San Marino
* Sao Tome and Principe
* Senegal
* Serbia
* Seychelles
* Sierra Leone
* Singapore
* Sint Maarten
* Slovenia
* Solomon Islands
* South Korea
* Spain
* Sri Lanka
* St. Kitts and Nevis
* St. Lucia
* St. Martin
* St. Vincent and the Grenadines
* Suriname
* Swaziland
* Sweden
* Switzerland
* Tajikistan
* Thailand
* Timor-Leste
* Togo
* Tonga
* Tunisia
* Turkey
* Turkmenistan
* Turks and Caicos Islands
* Tuvalu
* Ukraine
* United Arab Emirates
* Uruguay
* Uzbekistan
* Vatican
* Vietnam
* Zambia
**Payment Method**
* Card Payment
**Currency**
* CELO
***
## [Transak](https://transak.com/)
**Countries**
* Angola
* Argentina
* Australia
* Austria
* Belgium
* Belize
* Brazil
* Brunei Darussalam
* Canada
* Chile
* Comoros
* Costa Rica
* Croatia
* Cyprus
* Czechia
* Denmark
* Djibouti
* Dominica
* Dominican Republic
* Estonia
* Falkland Island
* Fiji
* Finland
* France
* Georgia
* Germany
* Greece
* Grenada
* Guatemala
* Honduras
* Hong Kong
* Hungary
* Iceland
* India
* Indonesia
* Ireland
* Israel
* Italy
* Japan
* Kazakhstan
* Kenya
* Kyrgyzstan
* Latvia
* Liechtenstein
* Luxembourg
* Madagascar
* Malawi
* Malaysia
* Malta
* Mauritania
* Mexico
* Moldova
* Monaco
* Netherlands
* New Zealand
* Norway
* Oman
* Papua New Guinea
* Paraguay
* Peru
* Philippines
* Poland
* Portugal
* Romania
* Rwanda
* Sao Tome and Principe
* Seychelles
* Singapore
* Slovakia
* Slovenia
* Solomon Islands
* South Korea
* Spain
* St. Kitts and Nevis
* St. Lucia
* St. Vincent and the Grenadines
* Suriname
* Swaziland
* Sweden
* Switzerland
* Tajikistan
* Tonga
* Turkmenistan
* United Kingdom
* United States
* Uruguay
**Payment Method**
* Card Payment
* Manual Bank Transfer (SEPA)
**Currency**
* USDT
* USDC
* CELO
* USDm
***
## [Transfi](https://www.transfi.com/)
**Countries**
* India
* Philippines
**Payment Method**
* Bank Transfer (UPI)
* Mobile Wallet (Gcash)
***
## [Yellow Card](https://yellowcard.io/)
**Countries**
* Benin
* Bostwana
* Burkina Faso
* Cameroon
* DRC
* Gabon
* Ghana
* Ivory Coast
* Kenya
* Malawi
* Mali
* Nigeria
* Republic of Congo
* Rwanda
* Senegal
* South Africa
* Tanzania
* Togo
* Uganda
* Zambia
**Payment Method**
* Bank Transfer
* Mobile Money
**Currency**
* USDT
* USDC
* CELO
* USDm
***
# Wallets
Source: https://docs.celo.org/home/wallets
Overview of digital wallets available to send, spend, and earn Celo assets.
***
## Choosing a Wallet
Celo is designed to work seamlessly with a range of wallets, each offering features to meet different user needs.
The [Celo Native Wallets](#celo-native-wallets) section provides an overview of wallets that are optimized for the Celo network. These wallets allow users to fully benefit from Celo’s native functionalities, such as [phone number mapping](/legacy/protocol/identity) and [fee abstraction](/build-on-celo/fee-abstraction/overview).
The [Celo Compatible Wallets](#celo-compatible-wallets) section provides an overview of commonly used wallets wallets that support the Celo network.
## Celo Native Wallets
***
### [MiniPay](https://www.opera.com/products/minipay)
MiniPay is a non-custodial lightweight mobile wallet that allows users to send and receive stablecoins with transaction below 1 cent. It was first launched within the Opera Mini browser to assist people in sending and receiving stablecoins using mobile numbers.
* [Homepage](https://www.opera.com/products/minipay)
* Platforms: [Android](https://play.google.com/store/apps/details?id=com.opera.minipay), [iOS](https://apps.apple.com/de/app/minipay-easy-global-wallet/id6504087257?l=en-GB), inside [Opera Mini](https://play.google.com/store/apps/details?id=com.opera.mini.native) in Ghana, Nigeria, Kenya, South Africa, and Uganda
* Maintainers: Opera
* Ledger support: No
* Supported tokens: USDm, USDT, and USDC
***
### [Valora](https://valora.xyz/)
Valora is a non-custodial multichain mobile wallet focused on helping users save, earn, and send their crypto. It supports Celo's ability to pay for transactions with stablecoins, supports Wallet Connect, and has a built in swap experience that works across chains. It also lets users verify their phone number and send payments to their contacts.
* [Homepage](https://valora.xyz/)
* Platforms: [iOS](https://apps.apple.com/us/app/valora-crypto-wallet/id1520414263?mt=8), [Android](https://play.google.com/store/apps/details?id=co.clabs.valora)
* Maintainers: [Valora](https://valora.xyz/)
* Ledger support: No
* [Source Code](https://github.com/valora-inc/wallet)
***
### [Celo Terminal](https://celoterminal.com/)
Celo Terminal is a wallet and dApp platform designed as a hub for managing and running Celo dApps locally.
* Homepage: [celoterminal.com](https://celoterminal.com)
* Platforms: MacOS, Linux, Windows
* Maintainers: [WOTrust](https://x.com/wotrust1)
* Ledger support: Yes (Note: [EIP-712 signing requires workaround](/wallet/ledger/eip712-workaround))
* [Source Code](https://github.com/zviadm/celoterminal)
***
## Celo Compatible Wallets
Here’s an overview of popular wallets compatible with the Celo network. Note that some wallets do not support fee abstraction for gas payments with different tokens.
### [Rabby](https://rabby.io/)
Your go-to wallet for Ethereum and EVM - Track portfolio across all EVM chains in one place - Discover popular Dapps for your needs.
* [Homepage](https://rabby.io/)
* Platforms: Browser, iOS, Android
***
### [MetaMask](https://metamask.io/)
MetaMask is a self-custody wallet with support for Celo.
You can learn more about connecting MetaMask to the Celo network [here](/wallet/metamask/use).
* [Homepage](https://metamask.io/)
* Platforms: [Browser](https://chromewebstore.google.com/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn), [iOS](https://apps.apple.com/us/app/metamask-blockchain-wallet/id1438144202), [Android](https://play.google.com/store/apps/details?id=io.metamask)
***
### [Uniswap Wallet](https://wallet.uniswap.org/)
Uniswap Wallet is a self-custody wallet with support for Celo.
* [Homepage](https://wallet.uniswap.org/)
* Platforms: [iOS](https://apps.apple.com/us/app/uniswap-crypto-nft-wallet/id6443944476?mt=8), [Android](https://play.google.com/store/apps/details?id=com.uniswap.mobile), and [Chrome](https://chromewebstore.google.com/detail/uniswap-extension/nnpmfplkfogfpmcngplhnbdnnilmcdcg).
* Maintainers: [Uniswap](https://app.uniswap.org/)
* [Source Code](https://github.com/Uniswap/wallet)
***
### [Trust Wallet](https://trustwallet.com/)
Trust Wallet is a self-custody wallet with support for Celo available as a mobile app and extension on multiple browsers.
* [Homepage](https://trustwallet.com/)
* Platforms: [iOS](https://apps.apple.com/us/app/trust-crypto-bitcoin-wallet/id1288339409?mt=8), [Android](https://play.google.com/store/apps/details?id=com.wallet.crypto.trustapp), [Chrome, Brave, Opera, & Edge Browser](https://chromewebstore.google.com/detail/trust-wallet/egjidjbpglichdcondbcbdnbeeppgdph),
* Maintainers: [Trust Wallet](https://trustwallet.com/)
* [Source Code](https://github.com/trustwallet)
***
### [Gem Wallet](https://gemwallet.com/)
Gem Wallet is an open-source, self-custody mobile wallet with support for Celo, including sending, receiving, buying, and swapping CELO and Celo stablecoins.
* [Homepage](https://gemwallet.com/)
* Platforms: [iOS](https://apps.apple.com/app/id6448712670), [Android](https://play.google.com/store/apps/details?id=com.gemwallet.android), [APK](https://apk.gemwallet.com/gem_wallet_latest.apk)
* Maintainers: [Gem Wallet](https://gemwallet.com/)
* [Source Code](https://github.com/gemwalletcom/wallet)
***
### [OKX Web3 Wallet](https://web3.okx.com/)
Supports over 130 blockchains, including CELO. Enables users to store, trade, analyze, earn, and connect to Web3 sites. The mobile app features a built-in browser for seamless Web3 access and includes a tab to switch to the OKX exchange (though creating an exchange account is not required to use the wallet). It’s fully compatible with WalletConnect and widely supported across Web3 platforms.
* [Homepage](https://web3.okx.com/)
* Platforms: [iOS](https://apps.apple.com/us/app/okx-wallet-portal-to-web3/id6743309484), [Android](https://play.google.com/store/apps/details?id=com.okx.wallet), [Chrome, Brave, Opera, & Edge Browser](https://chromewebstore.google.com/detail/okx-wallet/mcohilncbfahbmgdjkbpemcciiolgcge), [Telegram](https://web.telegram.org/k/#@OKX_WALLET_BOT)
* Maintainers: [OKX](https://okx.com/)
* Source code is not available, although there are two repositories related and useful for developers: [https://github.com/okx/go-wallet-sdk](https://github.com/okx/go-wallet-sdk) and [https://github.com/okx/js-wallet-sdk](https://github.com/okx/js-wallet-sdk)
***
### [Safe Wallet](https://app.safe.global/welcome)
Decentralized custody protocol and collective asset management platform. Provide multisg wallet support, Account Abstraction and more.
* [Homepage](https://app.safe.global/welcome)
* Platforms: Browser, iOS, Android
* [Docs](https://docs.safe.global/home/what-is-safe)
* [Source Code](https://github.com/safe-global/safe-wallet-monorepo)
***
### [Zerion](https://zerion.io/)
Zerion Wallet is a non-custodial wallet for crypto that gives you access to a broad range of opportunities across DeFi and NFTs.
* [Homepage](https://zerion.io/)
* Platforms: Browser, iOS, Android
* [Source Code](https://developers.zerion.io/reference/getting-started)
***
### [1Inch Wallet](https://1inch.com/wallet)
1inch Wallet gives you rapid updates and swap orders - whether you’re checking balances or trading on the go.
* [Homepage](https://1inch.com/wallet)
* Platforms: iOS, Android
***
### [Bridge Wallet](https://www.mtpelerin.com/bridge-wallet)
* [Homepage](https://www.mtpelerin.com/bridge-wallet)
* Platforms: iOS, Android
# Celo Sepolia Testnet Launch
Source: https://docs.celo.org/infra-partners/notices/archive/celo-sepolia-launch
Celo Sepolia is a new developer testnet that will replace Alfajores when Holesky sunsets in September 2025. The Baklava testnet will also sunset with Holesky, with no replacement planned.
**Key Information**
This page will be kept updated with key information about the transition.
* **Chain ID**: 11142220
* **Status**: testnet live
* **Built on**: Ethereum Sepolia L1
* **Phases**:
* Jul 23, 2025: Celo Sepolia launch ✅
* Jul 24, 2025—Jul 31, 2025: Internal testing ✅
* Aug 1, 2025—Aug 12, 2025: Early access phase ✅
* Aug 13, 2025: Public announcement ✅
* **Aug 14, 2025—Sep 14, 2025: Transition period :round\_pushpin:**
* Sep 30, 2025: Planned Alfajores and Baklava sunset, aligned with Holesky deprecation
**Node Providers**: Please support both Alfajores and Celo Sepolia during the transition period.
**Developers**: Verify that your dependencies support Celo Sepolia, then go ahead and deploy all contracts.
## What is Celo Sepolia?
Celo Sepolia is the new developer testnet for Celo running as an Ethereum Layer 2 on Sepolia. It starts with a clean slate (no inherited state from Alfajores) and is designed for long-term use following Ethereum Sepolia's testnet lifecycle.
## Call to Action
### For Node Providers
Please support both Alfajores and Celo Sepolia in parallel during the early access and transition phases to ensure a smooth migration for developers. See the [node setup guide](/infra-partners/operators/run-node) for technical details and our recommended [Docker Compose Setup](https://github.com/celo-org/celo-l2-node-docker-compose).
Release versions:
* `op-geth` at [v2.1.2](https://github.com/celo-org/op-geth/releases/tag/celo-v2.1.2)
* `op-node` at [v2.1.0](https://github.com/celo-org/optimism/releases/tag/celo-v2.1.0)
* `eigenda-proxy` at [v1.8.2](https://github.com/layr-labs/eigenda/pkgs/container/eigenda-proxy/437919973?tag=v1.8.2)
### For Developers
* Update applications to support chain ID 11142220.
* Redeploy contracts on Celo Sepolia.
* Get testnet CELO tokens from the faucets.
Since Celo Sepolia starts with a clean slate, there is no historical data or contracts carried over from Alfajores, providing a pristine testing environment.
## Key Characteristics and Resources
* Chain ID: 11142220
* L1 Foundation: Ethereum Sepolia
* EigenDA: v2 (Blazar)
* Contracts: [see the L1 and L2 contracts in the specification](/tooling/contracts/core-contracts#celo-sepolia-testnet)
* RPC endpoint: [Celo Sepolia Forno](https://forno.celo-sepolia.celo-testnet.org)
* Block explorer: [Blockscout](https://celo-sepolia.blockscout.com)
* Faucets:
* [Google Cloud Web3 Faucet](https://cloud.google.com/application/web3/faucet/celo/sepolia)
* [Celo Sepolia Token Faucet](https://faucet.celo.org/celo-sepolia)
* Bridge: [Superbridge for Celo Sepolia](https://testnets.superbridge.app/?fromChainId=11155111\&toChainId=11142220)
## Key Differences from Alfajores
| Aspect | Alfajores | Celo Sepolia |
| ------------- | ---------------------------- | ----------------- |
| L1 Foundation | Ethereum Holesky | Ethereum Sepolia |
| Chain ID | 44787 | 11142220 |
| State | Historical from L1 migration | Fresh start |
| Longevity | Sunset planned Sept 2025 | Long-term testnet |
## Early Adopters
Thank you to the first wave of our ecosystem partners supporting Celo Sepolia already:
* **Google Cloud** – [Google Cloud Web3 Faucet](https://cloud.google.com/application/web3/faucet/celo/sepolia)
* **Blockscout** – [Block Explorer](https://celo-sepolia.blockscout.com/)
* **EigenDA v2** – Data Availability
* **Superbridge** – Bridging Infrastructure
* **Ankr** – Node & RPC Provider
* **AllThatNode by DSRV** – Node & RPC Provider
* **Redstone** – Oracle Services
* **Talent Protocol** – Web3 Professional Network
* **Prosperity Pass** – Celo PG Onchain Access Pass
## Getting Help
Please reach out to our team on [Discord](https://chat.celo.org) in the [#celo-L2-support](https://discord.com/channels/600834479145353243/1286649605798367252) channel if you have any questions.
# Ice Cream Hardfork 🍦
Source: https://docs.celo.org/infra-partners/notices/archive/eigenda-v2-upgrade
This page outlines changes related to the EigenDA v2 upgrade for node operators.
This page will be kept updated with key information about the upgrade. As this upgrade is activated on the sequencer, no detailed activation times can be given.
* Baklava testnet activation was executed on Wed, Jul 30, 2025.
* Alfajores testnet activation was executed on Wed, Aug 20, 2025.
* **Mainnet** activation was executed on Wed, Sep 10, 2025.
## What is the Ice Cream Hardfork?
As part of [Celo’s continued growth as an Ethereum L2](https://forum.celo.org/t/celo-as-an-ethereum-l2-a-frontier-chain-for-global-impact/11376), Celo is integrating [EigenDA v2](https://docs.eigencloud.xyz/products/eigenda/releases/blazar), also known as [Blazar](https://docs.eigencloud.xyz/products/eigenda/releases/blazar), to further innovate and strengthen the network’s data availability layer.
Blazar represents a major architectural upgrade to the EigenDA protocol, introducing improved system throughput and stability, alongside new capabilities like permissionless DA payments and enhanced resource throttling.
Most notably for Celo:
* End-to-end confirmation latency is significantly reduced, moving from minutes to near real-time. Blazar’s design enables rollups to reference blocks in their own logic without waiting for L1 confirmations.
* System throughput and network stability are greatly improved through more efficient chunk distribution, optimized request routing, and horizontal scalability of DA nodes.
Support for decentralized dispersal is unlocked by eliminating DDoS attack surfaces inherent in the original push-based mode.
## For Node Operators
Node operators need to upgrade the [EigenDA proxy](https://github.com/Layr-Labs/eigenda/tree/master/api/proxy) to version [v1.8.2](https://github.com/Layr-Labs/eigenda/pkgs/container/eigenda-proxy/437919973?tag=v1.8.2) before the activation date. The version is backwards compatible with EigenDA v1 and can be updated beforehand.
The new proxy version will require to *add* the following new flags for each network (remember to fill the `eigenda.v2.eth-rpc` and `eigenda.v2.signer-payment-key-hex` from your own set up)
### Mainnet
```
--storage.backends-to-enable="V1,V2" \
--eigenda.v2.disperser-rpc=disperser.eigenda.xyz:443 \
--eigenda.v2.eth-rpc= \
--eigenda.v2.signer-payment-key-hex= \
--eigenda.v2.max-blob-length="16MiB" \
--eigenda.v2.cert-verifier-addr="0xE1Ae45810A738F13e70Ac8966354d7D0feCF7BD6" \
--eigenda.v2.service-manager-addr="0x870679e138bcdf293b7ff14dd44b70fc97e12fc0" \
--eigenda.v2.bls-operator-state-retriever-addr="0xEC35aa6521d23479318104E10B4aA216DBBE63Ce" \
```
### Alfajores and Baklava
```
--storage.backends-to-enable="V1,V2" \
--eigenda.v2.disperser-rpc=disperser-holesky.eigenda.xyz:443 \
--eigenda.v2.eth-rpc= \
--eigenda.v2.signer-payment-key-hex= \
--eigenda.v2.max-blob-length="16MiB" \
--eigenda.v2.cert-verifier-addr="0xFe52fE1940858DCb6e12153E2104aD0fDFbE1162" \
--eigenda.v2.service-manager-addr="0xD4A7E1Bd8015057293f0D0A557088c286942e84b" \
--eigenda.v2.bls-operator-state-retriever-addr="0xB4baAfee917fb4449f5ec64804217bccE9f46C67" \
```
### Celo Sepolia
```
--storage.backends-to-enable="V1,V2" \
--eigenda.v2.disperser-rpc=disperser-testnet-sepolia.eigenda.xyz:443 \
--eigenda.v2.eth-rpc= \
--eigenda.v2.signer-payment-key-hex= \
--eigenda.v2.max-blob-length="16MiB" \
--eigenda.v2.cert-verifier-addr="0x73818fed0743085c4557a736a7630447fb57c662" \
--eigenda.v2.service-manager-addr="0x3a5acf46ba6890B8536420F4900AC9BC45Df4764" \
--eigenda.v2.bls-operator-state-retriever-addr="0x22478d082E9edaDc2baE8443E4aC9473F6E047Ff" \
```
**Docker Compose**
The required configuration for each service can be found in our [Docker Compose Setup](https://github.com/celo-org/celo-l2-node-docker-compose), where every network has a corresponding `.env` file.
# L2 Isthmus Hardfork
Source: https://docs.celo.org/infra-partners/notices/archive/isthmus-upgrade
This page outlines breaking changes related to the Isthmus network upgrade for node operators.
This page will be kept updated with key information about the hardfork.
* Baklava testnet activation was executed at timestamp `1749654000` ([block 37881140](https://celo-baklava.blockscout.com/block/0xec4a86ed28d74090b71cb59c34e4b31b8a49ef00b09880d67034dc56237e4b1d)) on Wed, Jun 11, 2025, 15:00:00 UTC.
* Alfajores testnet activation was executed at timestamp `1750863600` ([block 49908280](https://celo-alfajores.blockscout.com/block/0x643b5ce0b59b83ffd8a9b9cfc13a91eeb1228094e0dbb3e1927ec2afc28dfbcb)) on Wed, Jun 25, 2025, 15:00:00 UTC.
* **Mainnet** activation was executed at timestamp **`1752073200`** ([block 40172442](https://celo.blockscout.com/block/0xdef57aaf634a3de07e7763db9b21d5e192e784316b8c233a2a4cd1eea6bf4f41)) on Wed, Jul 9, 2025, 15:00:00 UTC.
If you're encountering a stuck node after Alfajores hardfork block (49908280), see the [FAQ](/legacy/faq#my-alfajores-node-stalled-at-the-isthmus-hardfork-block-49908280).
## What's included in Isthmus
Isthmus contains these main changes:
* **Implement Prague features on the OP Stack**: This includes the EIPs that are relevant to the L2 that are being added to Ethereum with its Pectra activation. Learn more about this [here](https://gov.optimism.io/t/proposal-preview-implement-prague-features-on-the-op-stack/9703).
Notable EIP's included:
* [EIP-7702](https://github.com/ethereum/EIPs/blob/f27ddf2b0af7e862a967ee38ceeaa7d980786ca1/EIPS/eip-7702.md): Set code transaction
* [EIP-2537](https://github.com/ethereum/EIPs/blob/f27ddf2b0af7e862a967ee38ceeaa7d980786ca1/EIPS/eip-2537.md): BLS12-381 precompiles
* [EIP-2935](https://github.com/ethereum/EIPs/blob/f27ddf2b0af7e862a967ee38ceeaa7d980786ca1/EIPS/eip-2935.md): Block hashes contract predeploy
* [EIP-7623](https://github.com/ethereum/EIPs/blob/f27ddf2b0af7e862a967ee38ceeaa7d980786ca1/EIPS/eip-7623.md): Increase calldata cost
* **L2 Withdrawals Root in Block Header**: This lowers the lift for chain operators by allowing them to run a full node to operate op-dispute-mon, making it easier to guarantee the security of the fault proofs for the chains in the Superchain as the number of chains scales. Learn more about this [here](https://gov.optimism.io/t/proposal-preview-l2-withdrawals-root-in-block-header/9730).
For more information on the Isthmus implementation details, please review [OP's Isthmus specification](https://specs.optimism.io/protocol/isthmus/overview.html).
Isthmus additionally enables the [Holocene hardfork](https://docs.optimism.io/notices/holocene-changes) with the following changes:
* **Holocene block derivation**: A set of changes that render the derivation pipeline stricter and simpler, improving worst-case scenarios for the Fault Proof System and Interoperability.
* **EIP-1559 configurability**: The elasticity and denominator EIP-1559 parameters become configurable via the SystemConfig L1 contract, allowing the gas target and gas limit to be configured independently.
For more information on the Holocene details, please review [OP's Holocene specification](https://specs.optimism.io/protocol/holocene/overview.html).
## For node operators
Node operators will need to upgrade to the respective Isthmus releases before the activation dates.
### Update to the latest release
The release contains the activation timestamps for Celo Mainnet, Baklava and Alfajores.
* `op-geth` at [v2.1.0](https://github.com/celo-org/op-geth/releases/tag/celo-v2.1.0)
* `op-node` at [v2.1.0](https://github.com/celo-org/optimism/releases/tag/celo-v2.1.0)
#### Updating the EigenDA proxy
The Isthmus hardfork also prepares the Celo networks for the EigenDA v2 update.
This means that operators need to make sure to upgrade the [EigenDA proxy](https://github.com/Layr-Labs/eigenda/tree/master/api/proxy) to version [v1.8.2](https://github.com/Layr-Labs/eigenda/pkgs/container/eigenda-proxy/437919973?tag=v1.8.2).
### Verify Your Configuration
Make the following checks to verify that your node is properly configured.
* op-node and op-geth will log their configurations at startup
* Check that the Isthmus time is set to `activation-timestamp` in the `op-node` startup logs
* Check that the Isthmus time is set to `activation-timestamp` in the `op-geth` startup logs
# Jello Hardfork: OP Succinct Lite Integration
Source: https://docs.celo.org/infra-partners/notices/archive/jello-upgrade
This page outlines changes related to the Jello Upgrade for node operators.
Jello has been successfully activated.
* Celo Sepolia testnet activation [was executed](https://eth-sepolia.blockscout.com/tx/0x736deb757f4708eeafecc961f36e14f3711c1d9f944e45c933b666329743b31a) on Wed, Oct 5, 2025.
* **Mainnet** activation [was executed](https://eth.blockscout.com/tx/0x5fb3f2225dd2ba91efe941d4c9151df120ab06f6611b7b494bdecc96ff84c44b) on Wed, Dec 10, 2025.
## What is the Jello Hardfork?
The Jello Hardfork enables OP Succinct Lite, a production-ready, zero-knowledge-powered fault proof system built in collaboration with OP Labs and Succinct.
Key benefits include:
* ZK-powered dispute resolution, reducing latency, cost and complexity in the dispute process
* Improved infrastructure security through bond-based incentives and proof verification
* Support for alternative DA layers, aligning with Celo’s modular roadmap
Succinct’s architecture is built on Optimism’s Kona execution engine, Succinct’s high-performance zkVM (SP1), and the Succinct Prover Network.
## For Node Operators
Node operators do **not** need to do any upgrades of the Celo client software for this Upgrade.
We recommend the latest released versions:
* `op-geth` at [v2.1.2](https://github.com/celo-org/op-geth/releases/tag/celo-v2.1.2)
* `op-node` at [v2.1.0](https://github.com/celo-org/optimism/releases/tag/celo-v2.1.0)
* `eigenda-proxy` at [v1.8.2](https://github.com/layr-labs/eigenda/pkgs/container/eigenda-proxy/437919973?tag=v1.8.2)
**Docker Compose**
The required configuration for each service can be found in our [Docker Compose Setup](https://github.com/celo-org/celo-l2-node-docker-compose), where every network has a corresponding `.env` file.
# Jovian Hardfork
Source: https://docs.celo.org/infra-partners/notices/archive/jovian-upgrade
This page outlines changes related to the Jovian Upgrade for node operators.
This page will be kept updated with key information about the upgrade.
* Celo Sepolia testnet activation: Tue, Mar 17, 2026, 12:03:57 UTC
* Activation timestamp: `1773749037`
* **Mainnet** activation: Tue, Mar 31, 2026, 12:06:28 UTC
* Actvation timestamp: `1774958788`
## What is the Jovian Hardfork?
The Jovian Hardfork adopts features from [Optimism's Jovian hardfork](https://specs.optimism.io/protocol/superchain-upgrades.html) along with Celo-specific improvements focused on gas accounting and base fee alignment.
Key changes include:
* **Transfer Precompile Address Warming**: The transfer precompile now warms `from` and `to` addresses during execution, aligning with standard EVM behavior and ensuring correct gas accounting for subsequent operations on the same address.
* **Minimum Base Fee Transition**: Celo moves from its own gas price floor mechanism to Optimism's configurable Minimum Base Fee standard, maintaining a cost floor while aligning with OP Stack conventions.
For the full technical specification, see the [Jovian upgrade spec](/specs/upgrades/jovian).
* **L1 Fusaka Upgrade**: Celo now includes improvements to handle the L1 Fusaka upgrade, leading to better compatibility with the Optimism stack. For more details see [OP Fusaka upgrade notice](https://docs.optimism.io/notices/archive/fusaka-notice).
* **EigenDA upgrade**: The EigenDA proxy is upgraded to a recent version which improves the trustless integration and allows switching to the latest EigenDA protocol version.
## For Bridges and Users
All withdrawals that are not finalized before the contract upgrade right before the Jovian hardfork will need to be reproven after the upgrade is complete. You may want to consider waiting until after the upgrade is complete to begin a withdrawal during this 7-day window.
Celo's Jovian hardfork includes [Optimism Upgrade 16](https://docs.optimism.io/notices/archive/upgrade-16). Users should be aware of the following impacts:
### Withdrawal flow changes
1. There will be a one-time invalidation of all pending withdrawal proofs created on L1.
2. Complete any pending withdrawals before the upgrade is executed.
3. Avoid creating new withdrawal proofs that would not become executable in time.
4. If a withdrawal was invalidated, submit a second withdrawal proof transaction on L1.
This invalidation does not place any ETH or ERC-20 tokens at risk.
## For Node Operators
Node operators will need to upgrade to the respective Jovian releases before the activation dates.
### Update to the latest release
The release contains the activation timestamps for Celo Mainnet and Celo Sepolia testnet.
* `op-geth` at [v2.2.2](https://github.com/celo-org/op-geth/releases/tag/celo-v2.2.2)
* `op-node` at [v2.2.1](https://github.com/celo-org/optimism/releases/tag/celo-v2.2.1)
* `eigenda-proxy` at [v2.6.0](https://github.com/Layr-Labs/eigenda/releases/tag/v2.6.0)
* For an easy way to run a node and an example of valid flags see [celo-l2-node-docker-compose v1.3.3](https://github.com/celo-org/celo-l2-node-docker-compose/tree/v1.3.3)
#### Updating the EigenDA proxy
The Jovian hardfork also increases the minimum EigenDA proxy version to `v2.6.0`.
This update requires some changes to the configuration:
* Set the following flags
* `--eigenda.v2.network` to either `mainnet` or `sepolia_testnet`
* `--eigenda.v2.cert-verifier-router-or-immutable-verifier-addr` to the `CertRouter` contract on the corresponding L1
* Sepolia: [`0xf4f934A0b5c09d302d9C6f60040754fEebdd6073`](https://sepolia.etherscan.io/address/0xf4f934A0b5c09d302d9C6f60040754fEebdd6073)
* Mainnet: [`0x2ea418AE1852bfC79e18B37E55F278F9c598AA08`](https://etherscan.io/address/0x2ea418AE1852bfC79e18B37E55F278F9c598AA08)
* `--apis.enabled` to `"op-generic,op-keccak,standard,metrics"`
* Remove the following flags if they are set
* `--eigenda.signer-private-key-hex`
* `--eigenda.v2.disperser-rpc`
* `--eigenda.v2.cert-verifier-addr`
* `--eigenda.v2.eigenda-directory`
* `--eigenda.v2.signer-payment-key-hex`
* `--eigenda.v2.service-manager-addr`
* `--eigenda.v2.bls-operator-state-retriever-addr`
* `--eigenda.g1-path`
* `--eigenda.g2-path`
* `--eigenda.g2-path-trailing`
**Docker Compose**
The configuration for each service can be found in our [Docker Compose Setup](https://github.com/celo-org/celo-l2-node-docker-compose), where every network has a corresponding `.env` file.
### Re-download genesis and rollup.json files
The `genesis.json` and `rollup.json` files have been updated for the Jovian hardfork. Node operators not using the [Docker Compose setup](https://github.com/celo-org/celo-l2-node-docker-compose) must re-download these files before upgrading.
**Mainnet:**
* [`genesis.json`](https://storage.googleapis.com/cel2-rollup-files/celo/genesis.json)
* [`rollup.json`](https://storage.googleapis.com/cel2-rollup-files/celo/rollup.json)
**Celo Sepolia:**
* [`genesis.json`](https://storage.googleapis.com/cel2-rollup-files/celo-sepolia/genesis.json)
* [`rollup.json`](https://storage.googleapis.com/cel2-rollup-files/celo-sepolia/rollup.json)
### Verify Your Configuration
Make the following checks to verify that your node is properly configured.
* op-node and op-geth will log their configurations at startup
* Check that the Jovian time is set correctly in the `op-node` startup logs
* Check that the Jovian time is set correctly in the `op-geth` startup logs
### Notes
#### Event logs index rebuild on upgrade
Nodes will perform a one-time log index rebuild on first start, visible as `Log
index head rendering in progress` in logs. This can take several hours as the
full chain history is processed. Subsequent restarts will not re-index.
#### Event logs new flag `--history.logs`
Controls how long (in blocks) to maintain the event log indexes. Prior to this
upgrade the event log index was maintained for all event logs since genesis, now
the flag has a default setting of 28200000 blocks which is \~326 days. To index
all event logs since genesis set the flag to zero.
# L1 Fusaka Upgrade
Source: https://docs.celo.org/infra-partners/notices/archive/l1-fusaka-upgrade
## What is the Ethereum L1 Fusaka upgrade
The Fusaka hardfork contains various breaking changes on the L1. See [EIP-7607: Hardfork Meta - Fusaka](https://eips.ethereum.org/EIPS/eip-7607) for more info.
## Important dates
* Ethereum Sepolia Fusaka hard fork: Tuesday, October 14th, 2025 07:36:00 UTC, affects Celo Sepolia testnet.
* Ethereum Mainnet Fusaka hard fork: Expected early December 2025, affects Celo Mainnet. We will update this notice with the exact date, and new software releases, once it is confirmed
As Celo relies on Ethereum L1, node operators must make sure to provide a Fusaka compatible L1 node access for the Celo client.
For Celo users, there are no changes expected from the L1 Fusaka upgrade.
## Call to Action
### For Node Operators
#### L1 Ethereum clients
You need to make sure that your L1 nodes are updated to a compatible version. Check the [Ethereum Client release list](https://blog.ethereum.org/2025/09/26/fusaka-testnet-announcement#client-releases) for compatible versions.
#### L2 Celo client
There are no upgrades required for the Celo L2 client for the L1 Fusaka upgrade. We recommend the latest released versions:
* `op-geth` at [v2.1.2](https://github.com/celo-org/op-geth/releases/tag/celo-v2.1.2)
* `op-node` at [v2.1.0](https://github.com/celo-org/optimism/releases/tag/celo-v2.1.0)
* `eigenda-proxy` at [v1.8.2](https://github.com/layr-labs/eigenda/pkgs/container/eigenda-proxy/437919973?tag=v1.8.2)
## Getting Help
Please reach out to our team on [Discord](https://chat.celo.org) in the [#celo-L2-support](https://discord.com/channels/600834479145353243/1286649605798367252) channel if you have any questions.
# Celo L2 Migration
Source: https://docs.celo.org/infra-partners/notices/archive/l2-migration
* Mainnet has been migrated on block **31056500**, March 26, 2025, 3:00 AM UTC.
* The Baklava testnet has been migrated on block **28308600**, February 20, 2025.
* The Alfajores testnet has been migrated on block **26384000**, September 26, 2024.
The instructions for migrating a Celo node from Layer 1 to Layer 2 are outlined [in this guide](/infra-partners/operators/migrate-node). This process is necessary to transition your Celo L1 node to the new Celo L2 architecture based on the OP-Stack.
If you wish to run a Celo L2 node from scratch, you can follow the instructions in the [Running a Celo Node](/infra-partners/operators/run-node) guide.
# End of Support for op-geth
Source: https://docs.celo.org/infra-partners/notices/op-geth-deprecation
Transition from op-geth to op-reth as Celo's supported execution client
This notice outlines the deprecation of `op-geth` and the transition to `op-reth` as the supported execution client for Celo. It includes key information for node operators, RPC providers, and bridge operators.
Celo is switching its execution client from `op-geth` to `op-reth`. All node operators must migrate to `op-reth` by the switch date for their network to remain in sync with the canonical chain.
## Switch dates
* **Celo Sepolia**: June 24, 2026
* **Mainnet**: July 22, 2026
## Summary Of Changes
Following [Optimism's](https://docs.optimism.io/notices/op-geth-deprecation) deprecation of op-geth, Celo will also discontinue support for `op-geth` and adopt `op-reth` as the primary execution client.
* **`op-geth`**: Supported only until the switch date for each network. After that, it might follow the wrong chain.
* **`op-reth`**: The new supported execution client built on `reth`.
* **`op-node`**: No changes. It remains fully supported.
## Requirements for Node Operators
Node operators must complete migration to `op-reth` by the switch date for their network (see above).
A Celo-compatible `op-reth` release is available, and the node-operator guides now use it:
* Follow [Run a node with Docker](/infra-partners/operators/run-node) to run `op-reth`. A new node starts from an empty datadir — bootstrap it from a published snapshot (`OP_RETH__SNAPSHOT=true`, required on mainnet) or, on Celo Sepolia, sync from genesis; no L1 data migration is required.
* A migrated `op-geth` datadir cannot be reused — `op-reth` uses a different on-disk format. Start `op-reth` with an empty `DATADIR_PATH`.
* For archive nodes and pre-L2 historical state, see [Running an archive node](/infra-partners/operators/archive-node).
* See the [Configuration reference](/infra-partners/operators/configuration) for the `OP_RETH__*` variables, and the [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose) repository for the latest images.
## RPC Providers and Bridge Operators
For most RPC users, this transition should be seamless. `op-reth` supports the same JSON-RPC interface as `op-geth`.
However, some differences may exist in non-standard or debug RPC methods. We recommend validating your integrations against `op-reth` on Celo Sepolia, which switches first (see the dates above).
# Overview
Source: https://docs.celo.org/infra-partners/notices/overview
Active upgrade notices, deprecations, and network change announcements for Celo node operators.
Transition from op-geth to op-reth as Celo's supported execution client.
The op-node Req/Res consensus-layer P2P sync client is deprecated in favor of execution-layer syncing.
# Deprecation of Req/Res CL P2P Sync
Source: https://docs.celo.org/infra-partners/notices/req-resp-cl-sync-deprecation
The `op-node` request-response consensus-layer P2P sync client is being deprecated in favor of execution-layer syncing.
Celo is following [Optimism's deprecation of Req/Res CL P2P sync](https://docs.optimism.io/notices/req-resp-cl-sync-deprecation). This change simplifies `op-node` configuration, removes fragile sync logic, and relies on the execution client's native P2P sync, which is the more battle-tested path.
## What This Means
* The Req/Res CL P2P sync **client** in `op-node` is being deprecated. Execution-layer syncing is now the preferred method.
* `op-node` will rely on a connected execution-layer node for syncing rather than its own consensus-layer P2P mechanism.
* Node operators must ensure their execution-layer node has healthy P2P connectivity.
* If you have explicitly set `--syncmode.req-resp=true`, you must remove this override.
* The Req/Res sync **server** will remain temporarily to support legacy nodes before being fully removed.
## Action Required
### For Node Operators
1. Ensure your EL node has healthy P2P connectivity. The execution client's native P2P sync will be the primary sync path going forward.
2. Remove any explicit `--syncmode.req-resp=true` settings from your node configuration.
3. If you are running an older release where req-resp sync is still enabled by default, set `--syncmode.req-resp=false` explicitly.
Nodes with unhealthy execution-layer peer connectivity may fail to catch up to the unsafe tip once the deprecated sync path is fully removed.
# Node Architecture
Source: https://docs.celo.org/infra-partners/operators/architecture
This page reviews node architecture for all nodes running on the Celo network. All L2 Celo nodes are composed of two core software services, the Rollup Node and the Execution Client. Celo also optionally supports a third component, Legacy L1 Celo, that can serve stateful queries for blocks and transactions created before the [L2 migration](/infra-partners/notices/archive/l2-migration).
## Rollup node
The Rollup Node is responsible for deriving L2 block payloads from L1 data and passing those payloads to the Execution Client. The Rollup Node can also optionally participate in a peer-to-peer network to receive blocks directly from the Sequencer before those blocks are submitted to L1. The Rollup Node is largely analogous to a [consensus client](https://ethereum.org/en/developers/docs/nodes-and-clients/#what-are-nodes-and-clients) in Ethereum.
## Execution client
The Execution Client is responsible for executing the block payloads it receives from the Rollup Node over JSON-RPC via the standard [Ethereum Engine API](https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md#engine-api----common-definitions). The Execution Client exposes the standard JSON-RPC API that Ethereum developers are familiar with, and can be used to query blockchain data and submit transactions to the network. The Execution Client is largely analogous to an [execution client](https://ethereum.org/en/developers/docs/nodes-and-clients/#what-are-nodes-and-clients) in Ethereum. On Celo this is `op-reth`; `op-geth` is supported until your network's [switch date](/infra-partners/notices/op-geth-deprecation).
## Next steps
* To get your node up and running, [run a node with Docker](/infra-partners/operators/run-node).
* If you are moving existing Celo L1 data to L2, see [how to migrate an L1 node](/infra-partners/operators/migrate-node).
# Running an Archive Node
Source: https://docs.celo.org/infra-partners/operators/archive-node
**Archive node vs. historical proofs**
This guide covers running a **full archive node**, which serves every historical-state RPC call (such as `eth_getBalance` or `eth_call`) at any block and requires terabytes of storage. Celo also supports a narrower **historical proofs** feature for serving deep `eth_getProof` within a bounded window without keeping full archive state; see [Serving historical proofs](/infra-partners/operators/historical-proofs).
**Execution client: op-reth**
These instructions use `op-reth`, Celo's primary execution client. `op-geth` is supported until your network's switch date — see the **Still running op-geth?** notes at the end of this guide and [End of Support for op-geth](/infra-partners/notices/op-geth-deprecation).
## Overview
To run an L2 archive node, you need to start the L2 execution client in archive mode. This allows the node to accept RPC requests that require archive data for blocks created after the L2 transition. For historical data from before the L2 transition, you can configure your node to forward those requests to a legacy Celo L1 archive node that contains the historical blockchain state.
## Instructions
**Prerequisites**
An L2 archive node starts from an empty datadir, like a full node — no migrated L1 data is required. To serve pre-L2 historical state, you additionally need one of:
1. A non-migrated Celo L1 archive node datadir (the compose setup runs a legacy archive node from it). Do not attempt to migrate an archive datadir.
2. The RPC endpoint of a running legacy Celo L1 archive node.
Ensure any datadir you supply is not in use by a running node before proceeding.
1. Pull the latest version of [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose) and `cd` into the root of the project.
```bash theme={null}
git clone https://github.com/celo-org/celo-l2-node-docker-compose.git
cd celo-l2-node-docker-compose
```
2. Configure your `.env` file.
#### Copy default configurations
The [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose) repo contains a `.env` file for each Celo network (`celo-sepolia`, `mainnet`). Start by copying the default configuration for the appropriate network.
```bash theme={null}
export NETWORK=
cp $NETWORK.env .env
```
#### Configure node type
To enable `archive` mode, configure `.env` as follows:
```text theme={null}
NODE_TYPE=archive
```
#### Bootstrap your datadir
An archive node starts from an **empty** datadir and keeps the full historical state. Bootstrap it from a published snapshot:
```text theme={null}
OP_RETH__SNAPSHOT=true
```
On first start this downloads the snapshot matching your `NODE_TYPE` (here, the archive snapshot) and continues from there. **On mainnet a snapshot is required** — it provides the pre-L2 (Celo L1) history. On **Celo Sepolia**, which has no pre-L2 history, you can instead leave `OP_RETH__SNAPSHOT=false` and execute every block from genesis. Either way, `NODE_TYPE=archive` is what keeps the full historical state available, and `DATADIR_PATH` must be empty on first start — a datadir written by `op-geth` cannot be reused.
#### Configure Historical RPC Service
To handle RPC requests for pre-hardfork state and execution, an L2 archive node proxies to a legacy archive node or "Historical RPC Service".
There are two ways to configure a Historical RPC Service for your archive node:
1. Supply a pre-hardfork archive datadir and let [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose) start a legacy archive node. To do this configure `.env` as follows:
```text theme={null}
HISTORICAL_RPC_DATADIR_PATH=
```
When you start your L2 node, a legacy archive node will also start using the pre-hardfork archive datadir. Your L2 node will be configured to use the legacy archive node as its Historical RPC Service.
2. Start the legacy archive node yourself and configure `.env` as follows:
```text theme={null}
OP_RETH__HISTORICAL_RPC=
```
This will cause any value you set for `HISTORICAL_RPC_DATADIR_PATH` to be ignored. The tool will not start a legacy archive node when it starts your L2 archive node.
If you choose to run your own legacy archive node, you should do so with different flags than before the hardfork, as the node will no longer be syncing blocks or communicating with other nodes. To see how we recommend re-starting a legacy archive node as a Historical RPC Service, see [this script](https://github.com/celo-org/celo-l2-node-docker-compose/blob/30ee2c4ec2dacaff10aaba52e59969053c652f05/scripts/start-historical-rpc-node.sh#L19).
#### Configure P2P for external network access
**Network Configuration**
If the following options are not configured correctly, your node will not be discoverable or reachable to other nodes on the network. This is likely to impair your node's ability to stay reliably connected to and synced with the network.
* `OP_NODE__P2P_ADVERTISE_IP` - Specifies the public IP to be shared via discovery so that other nodes can connect to your node. If unset, other nodes on the network will not be able to discover and connect to your op-node.
* `PORT__OP_NODE_P2P` - Specifies the port to be shared via discovery so that other nodes can connect to your node. Defaults to 9222.
* `OP_RETH__NAT` - Controls how op-reth determines its public IP that is shared via the discovery mechanism. If the public IP is not correctly configured then other nodes on the network will not be able to discover and connect to your node. The default value of `any` will try to automatically determine the public IP, but the most reliable approach is to explicitly set the public IP using `extip:`. Other acceptable values are `(any|none|upnp|publicip|extip:|stun:)`.
* `PORT__OP_RETH_P2P` - Specifies the port to be shared via discovery so that other nodes can connect to your node. Defaults to 30303.
3. Start the node(s).
```bash theme={null}
docker compose up -d --build
```
4. Check the progress of your L2 archive node as it syncs.
```bash theme={null}
docker compose logs -n 50 -f op-reth
```
This will display and follow the last 50 lines of logs. As the node syncs you will see `op-reth` executing blocks and its head advancing toward the network's latest block.
5. Check that node is fully synced.
You can validate that your node is following the network by fetching the current block number via the RPC API and seeing that it climbs as the node syncs and then tracks the network's latest block.
```bash theme={null}
cast block-number --rpc-url http://localhost:9993
```
6. Try querying historical state to test archive functionality.
```bash theme={null}
cast balance --block --rpc-url http://localhost:9993
```
Until your network's [switch date](/infra-partners/notices/op-geth-deprecation), you can keep running an `op-geth` archive node from an existing checkout of [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose). The flow above is the same, with these differences:
* **Sync mode instead of a snapshot.** `op-geth` archive nodes should run `full` sync against a migrated pre-hardfork datadir — `snap` sync only stores archive data from the point it completes, leaving a gap after the hardfork:
```text theme={null}
OP_GETH__SYNCMODE=full
DATADIR_PATH=
```
* **Historical RPC variable.** Use `OP_GETH__HISTORICAL_RPC` in place of `OP_RETH__HISTORICAL_RPC`.
* **P2P variables.** Use `OP_GETH__NAT` (values `any|none|upnp|pmp|pmp:|extip:|stun:`) and `PORT__OP_GETH_P2P` (default `30303`).
* **Logs.** Follow `docker compose logs -n 50 -f op-geth`; a syncing node shows `Syncing beacon headers downloaded=...` and later `"Syncing: chain download in progress","synced":"21.07%"`.
# Configuration Reference
Source: https://docs.celo.org/infra-partners/operators/configuration
This page documents the `.env` variables and the key client flags used by the [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose) setup. For the exhaustive command-line flag references, see the Optimism [op-reth config](https://docs.optimism.io/node-operators/reference/op-reth-config) and [op-node config](https://docs.optimism.io/node-operators/reference/op-node-config) docs.
**Execution client: op-reth**
The variables below configure `op-reth`, Celo's primary execution client. The `op-geth` equivalents remain valid until your network's switch date — see the **op-geth variables** accordion below and [End of Support for op-geth](/infra-partners/notices/op-geth-deprecation).
## Node type and sync
| Variable | Values | Description |
| ------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `NODE_TYPE` | `full` (default), `archive` | A `full` node stores historical state only for recent blocks. An `archive` node stores historical state for the entire chain (roughly 10x the storage). |
| `OP_RETH__SNAPSHOT` | `true`, `false` (default) | When `true`, an empty datadir is bootstrapped from a published snapshot (`snapshots.celo.org`). Required on mainnet, which needs the pre-L2 history; optional on Celo Sepolia, which can sync from genesis. Ignored once the datadir holds data. |
`op-reth` syncs by executing every block. A new node starts from an empty datadir (see [Run a node with Docker](/infra-partners/operators/run-node)); datadirs written by `op-geth` cannot be reused. For archive nodes, see [Running an archive node](/infra-partners/operators/archive-node).
## L1 connection
| Variable | Description |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `OP_NODE__RPC_ENDPOINT` | Layer 1 RPC endpoint. For reliability, use a paid plan or a self-hosted node. |
| `OP_NODE__L1_BEACON` | Layer 1 beacon endpoint. For reliability, use a paid plan or a self-hosted node. |
| `OP_NODE__RPC_TYPE` | Provider type for the L1 RPC endpoint: `alchemy`, `quicknode` (ETH only), `erigon`, or `basic` for other providers. |
| `HEALTHCHECK__REFERENCE_RPC_PROVIDER` | Public L2 RPC endpoint to compare against in the healthcheck (defaults to `https://forno.celo.org`). |
## Historical state (pre-hardfork)
An L2 archive node serves pre-hardfork state by proxying to a legacy Celo L1 archive node.
| Variable | Description |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `HISTORICAL_RPC_DATADIR_PATH` | Path to a pre-hardfork archive datadir. If set, a Celo L1 node runs in archive mode and op-reth proxies pre-migration requests to it. |
| `OP_RETH__HISTORICAL_RPC` | RPC endpoint of a running legacy archive node. If set, this overrides `HISTORICAL_RPC_DATADIR_PATH` and no local Celo L1 node is started. |
See [Running an archive node](/infra-partners/operators/archive-node) for the full setup.
## Networking (P2P)
Configure these so other nodes can discover and reach yours. If they are wrong, your node may fail to stay connected and synced.
| Variable | Description |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OP_NODE__P2P_ADVERTISE_IP` | Public IP that op-node advertises via discovery. If unset, other nodes cannot discover yours. |
| `OP_RETH__NAT` | How op-reth determines its public IP for discovery. One of `any`, `none`, `upnp`, `publicip`, `extip:`, `stun:`. The default `any` auto-detects; the most reliable option is `extip:`. |
## Ports
Each `PORT__*` variable overrides a default exposed in `docker-compose.yml`. Defaults:
| Variable | Default | Service |
| -------------------------------- | ------- | ---------------------------------- |
| `PORT__OP_RETH_HTTP` | `9993` | op-reth JSON-RPC (HTTP) |
| `PORT__OP_RETH_WS` | `9994` | op-reth JSON-RPC (WebSocket) |
| `PORT__OP_RETH_P2P` | `30303` | op-reth P2P |
| `PORT__OP_NODE_HTTP` | `9545` | op-node RPC |
| `PORT__OP_NODE_P2P` | `9222` | op-node P2P |
| `PORT__HEALTHCHECK_METRICS` | `7300` | Healthcheck metrics |
| `PORT__PROMETHEUS` | `9090` | Prometheus |
| `PORT__GRAFANA` | `3000` | Grafana |
| `PORT__INFLUXDB` | `8086` | InfluxDB |
| `PORT__HISTORICAL_RPC_NODE_HTTP` | `9991` | Legacy L1 archive node (HTTP) |
| `PORT__HISTORICAL_RPC_NODE_WS` | `9992` | Legacy L1 archive node (WebSocket) |
| `PORT_EIGENDA_PROXY` | `4242` | EigenDA proxy |
## Data directory
| Variable | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `DATADIR_PATH` | Datadir location (defaults to `./envs//datadir`). Must be empty on first start — `op-reth` initialises a new datadir there and cannot reuse one written by `op-geth`. |
## Key client flags
These flags are set for you by the compose start scripts; they are listed here because they are the Celo-specific ones operators most often need to know about.
* **`--rollup.sequencer`** (op-reth, set via `OP_RETH__SEQUENCER_URL`) — the sequencer that transactions submitted to your node are forwarded to. Mainnet: `https://cel2-sequencer.celo.org`; Celo Sepolia: `https://sequencer.celo-sepolia.celo-testnet.org`. If this is wrong, transactions submitted to your node are not executed.
* **`--syncmode=execution-layer`** (op-node) — op-node syncs via the execution client rather than the deprecated consensus-layer req/resp path. See [Deprecation of Req/Res CL P2P Sync](/infra-partners/notices/req-resp-cl-sync-deprecation).
* **`--l2.enginekind=reth`** (op-node) — tells op-node which execution client it is driving. It is set to `reth` for `op-reth`.
* **`--metrics.enabled`** (op-node) — exposes Prometheus metrics on port `7300`. See [Monitoring & metrics](/infra-partners/operators/monitoring).
For every other op-reth/op-node flag, see the Optimism [op-reth config](https://docs.optimism.io/node-operators/reference/op-reth-config) and [op-node config](https://docs.optimism.io/node-operators/reference/op-node-config) references.
If you are still running `op-geth` from an older checkout of [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose), use these equivalents in place of their `OP_RETH__` counterparts. They stop working once your network reaches its [switch date](/infra-partners/notices/op-geth-deprecation).
| Variable | Description |
| --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `OP_GETH__SYNCMODE` | `snap` or `full`. If unset, a `full` node defaults to `snap` and an `archive` node to `full`. `full` requires a migrated pre-hardfork datadir. |
| `OP_GETH__NAT` | How op-geth determines its public IP for discovery. One of `any`, `none`, `upnp`, `pmp`, `pmp:`, `extip:`, `stun:`. |
| `OP_GETH__HISTORICAL_RPC` | RPC endpoint of a running legacy archive node for pre-hardfork state. |
| `PORT__OP_GETH_HTTP` / `PORT__OP_GETH_WS` / `PORT__OP_GETH_P2P` | op-geth JSON-RPC (HTTP `9993`, WebSocket `9994`) and P2P (`30303`) ports. |
| `IPC_PATH` | Alternative location for the geth IPC file, if the datadir disk does not support unix domain sockets. |
| `IMAGE_TAG__OP_GETH` | Pin a specific op-geth image version. |
Key op-geth flags: `--rollup.sequencerhttp` (sequencer endpoint), `--history.transactions=0` (index the full transaction history), and `--l2.enginekind=geth` on op-node.
## Monitoring
Set `MONITORING_ENABLED=true` to start the Grafana, Prometheus, InfluxDB, and healthcheck stack. See [Monitoring & metrics](/infra-partners/operators/monitoring).
# Serving Historical Proofs
Source: https://docs.celo.org/infra-partners/operators/historical-proofs
**An op-reth feature**
Historical proofs is an `op-reth` capability. `op-geth` served deep `eth_getProof`
from full archive state; on `op-reth` it is configured separately, as described
here. See [End of Support for op-geth](/infra-partners/notices/op-geth-deprecation)
for the migration timeline.
## Overview
Some workloads need `eth_getProof` (and `debug_executePayload` /
`debug_executionWitness`) for blocks that are no longer at the chain tip:
* **Withdrawal proving.** Proving an L2 withdrawal calls `eth_getProof` on the L2
block where the withdrawal was included, regardless of the dispute-game model.
* **Fault proofs and challenges.** Constructing or verifying proofs over the
dispute-game window needs historical state for blocks within that window.
On `op-reth`, serving `eth_getProof` for an older block rebuilds that block's
state by reverting state diffs backward from the chain tip. Retrieval time is
**linear in the age of the block**: queries a few days back load many changesets,
which is slow and can crash the node with out-of-memory (OOM) errors. This makes
deep historical proofs impractical on a standard node.
The **historical proofs** sidecar fixes this. It maintains a separate database of
versioned Merkle-trie nodes and serves `eth_getProof` for any block inside a
configured window directly from that store: bounded response time and bounded
memory, instead of linear-in-age reverts. This benefits any node that answers
deep `eth_getProof` (public RPC providers, bridge and withdrawal services,
fault-proof proposers), **including archive nodes**: an archive node keeps
historical state but still pays the slow revert to build a proof.
## Two ways to serve historical proofs
| | `--rpc.eth-proof-window` | `--proofs-history` (v2) |
| -------------- | ----------------------------------------- | --------------------------------------- |
| Extra database | No | Yes (separate MDBX store) |
| Retrieval cost | Grows with query depth (in-memory revert) | Bounded within the window |
| Memory | Grows with depth (OOM risk deep) | Bounded |
| Storage | None | Window-sized, can be large |
| Best for | Short lookback (hours) | Full dispute / withdrawal window (days) |
* **`--rpc.eth-proof-window `** widens the in-memory revert window
without a separate database. It is the lighter option when you only need a few
hours of lookback, but cost and memory still grow the further back you query,
and it is capped at roughly two weeks of 1-second blocks.
* **`--proofs-history` with `--proofs-history.storage-version=v2`** adds the
sidecar database. `v2` is the current, more performant on-disk format, built on
reth's v2 storage layout, and the version the Celo node setup uses by default.
It is the option that covers Celo's full dispute and withdrawal window with
bounded cost, at the price of extra disk. The rest of this guide configures it.
## Window sizing for Celo
The window is a **time** requirement (the dispute-game lifecycle plus your
withdrawal-proving lookback), so size it in blocks from Celo's **1-second** block
time:
```
--proofs-history.window = retention_seconds / 1
```
Celo's op-succinct dispute-game lifecycle (max challenge + max prove + finality
delay, plus proposal cadence and margin) lands on the order of **8 to 15 days**.
The default `--proofs-history.window=1296000` is about **15 days at 1-second
blocks** and covers that comfortably. Note this differs from Optimism's
documentation, whose `1296000` default is \~30 days because it assumes 2-second
blocks: on Celo the same block count is half the time, so size from Celo's
1-second block time rather than copying a day count.
## Enable with Docker Compose (recommended)
The [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose)
setup wires historical proofs behind a single opt-in variable. It is **off by
default**.
1. Follow [Run a node with Docker](/infra-partners/operators/run-node) to get a
node configured and syncing.
2. Enable historical proofs in your `.env`:
```text theme={null}
OP_RETH__PROOFS_HISTORY_ENABLED=true
```
Optionally tune the retention window and the database location (defaults
shown):
```text theme={null}
OP_RETH__PROOFS_HISTORY_WINDOW=1296000
PROOFS_HISTORY_DATADIR_PATH=./envs//proofs
```
Keep `PROOFS_HISTORY_DATADIR_PATH` on a **separate volume** from the
chaindata datadir.
3. Start (or restart) the node:
```bash theme={null}
docker compose up -d --build
```
When enabled, `op-reth` initializes the proofs store **once**, before it starts
following the chain, by anchoring it at the datadir's current head, then fills
proofs forward up to the window as new blocks arrive.
**The datadir must be synced past genesis before proofs are initialized**
The proofs store is anchored at the datadir's head. Anchoring it at the genesis
block (block 0 on Celo Sepolia, the L2 migration block on Mainnet) wedges the
node with repeated `StateRootMismatch` errors, so the startup script refuses to
initialize a datadir that is still at genesis: it logs a warning and starts
**without** proofs. This gives three cases:
* **Bootstrapped from a snapshot (`OP_RETH__SNAPSHOT=true`, the default):** the
datadir is already synced, so proofs initialize automatically on first start.
* **An existing synced datadir:** point `DATADIR_PATH` at it and enable proofs;
the store initializes on the next start.
* **Syncing from scratch (`OP_RETH__SNAPSHOT=false`):** the first start has
nothing to anchor, so proofs are skipped with a warning and the node syncs
without them. Once it has caught up, run `docker compose up -d` again to
initialize proofs against the now-synced datadir.
## Enable from source
If you run `op-reth` (`celo-reth`) directly instead of through the compose setup,
configure it in two steps. The proofs store must be initialized **before** the
node starts with `--proofs-history`.
1. With the node **stopped** and the datadir synced past genesis, initialize the
proofs store at the current head. It is idempotent: re-running is a no-op
once initialized, so it is safe to run on every start.
```bash theme={null}
celo-reth proofs init \
--datadir= \
--chain= \
--proofs-history.storage-path= \
--proofs-history.storage-version=v2
```
The first run takes minutes to hours; later runs take seconds. It does **not**
backfill: it marks the current head as the starting point and fills forward.
2. Start the node with the proofs-history flags:
```bash theme={null}
celo-reth node \
--chain= \
--datadir= \
--proofs-history \
--proofs-history.storage-path= \
--proofs-history.storage-version=v2 \
--proofs-history.window=1296000
```
| Flag | Default | Description |
| ---------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------- |
| `--proofs-history` | off | Enable the historical-proofs sidecar. |
| `--proofs-history.storage-path` | required | Path to the proofs database. Keep it on a separate volume from chaindata. |
| `--proofs-history.storage-version` | `v1` | On-disk format. Use **`v2`** (more performant; incompatible with `v1`). Must match between `proofs init` and the node. |
| `--proofs-history.window` | `1296000` | Retention window, in blocks. About 15 days at 1-second blocks. |
| `--proofs-history.verification-interval` | `0` | Advanced/testing. `0` trusts the ExEx; `1` re-executes every block to verify (much slower). |
## Verify
With proofs history running, the startup log shows the override being installed:
```
INFO Installing proofs-history RPC overrides (eth_getProof, debug_executePayload)
```
Check the window that is currently served with `debug_proofsSyncStatus` (the
`debug` RPC namespace is enabled in the compose setup):
```bash theme={null}
curl -s http://localhost:9993 \
-H 'Content-Type: application/json' \
--data '{"jsonrpc":"2.0","method":"debug_proofsSyncStatus","params":[],"id":1}'
```
It returns the earliest and latest blocks held in the store:
```json theme={null}
{ "jsonrpc": "2.0", "id": 1, "result": { "earliest": 27026987, "latest": 28411347 } }
```
Right after `proofs init` both values equal the head; the window then grows
forward until it spans `--proofs-history.window` blocks. `eth_getProof` is served
from the sidecar for any block in `[earliest, latest]`; requests outside that
range fall back to the standard (slow) path or error. A historical
`eth_getProof` inside the window should return promptly:
```bash theme={null}
cast proof --block --rpc-url http://localhost:9993
```
If [monitoring](/infra-partners/operators/monitoring) is enabled, the same window
is exported as Prometheus gauges on op-reth's metrics port:
* `reth_optimism_trie_proof_window_earliest`
* `reth_optimism_trie_proof_window_latest`
## Maintenance
* **Pruning is automatic.** A background task drops blocks that fall outside the
window. If the store ever holds more than \~1000 blocks beyond the window,
`op-reth` refuses to start; prune once, then restart:
```bash theme={null}
celo-reth proofs prune \
--datadir= \
--proofs-history.storage-path= \
--proofs-history.storage-version=v2 \
--proofs-history.window=1296000
```
* **Recover from a corrupted store.** `celo-reth proofs unwind` is planned but
not yet available. To recover, stop the node, remove the proofs database
directory, and start again: the store re-anchors at the current head and
refills forward.
* **Disk.** Storage scales with the window (and with per-block activity), not
with the node's prune tier. As a reference point, a \~15-day window measured
about **73 GB** on a celo-sepolia full node (a low-traffic testnet, \~53
bytes/block); a busier network such as mainnet is proportionally larger. Put
the proofs database on its own volume and size capacity from your chosen
window.
## Limitations
* **Forward-only.** The store records from its initialization point onward and
cannot backfill earlier blocks. After initialization the window grows forward
as new blocks arrive and reaches full depth once the node has been running for
about the window duration. Bootstrapping from a snapshot whose tip is old
enough to already span the window (so catching up to live re-fills it) lets you
reach a full window much faster; such older-tip snapshots are planned but not
yet available. Blocks before the initialization point, or older than the
window, are not served from the sidecar.
* **op-reth only.** This feature does not exist on `op-geth`, which relied on
full archive state instead.
## Reference
* Optimism: [Historical proofs tutorial](https://docs.optimism.io/node-operators/tutorials/reth-historical-proofs)
(sizing and flags in detail; note its day counts assume 2-second blocks).
* [Running an archive node](/infra-partners/operators/archive-node): the
full-archive alternative when you need every historical-state call, not just
proofs.
# Upgrades & Maintenance
Source: https://docs.celo.org/infra-partners/operators/maintenance
Routine operational tasks for a running Celo L2 node, using the [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose) setup.
## Upgrading your node
To upgrade to the latest client versions:
```sh theme={null}
git pull
docker compose pull
docker compose up -d --build
```
This pulls the latest changes from GitHub and the latest images from the registry, rebuilds the containers, and restarts the node.
**Hardfork upgrades are time-sensitive**
Network hardforks require running a compatible client version *before* the fork block, or your node will stop following the chain. Watch the [Notices](/infra-partners/notices/archive/l2-migration) for each upgrade's required versions and timing. The next major required migration is the move from op-geth to op-reth — see [End of Support for op-geth](/infra-partners/notices/op-geth-deprecation).
To pin a specific image version instead of tracking the latest, set the matching `IMAGE_TAG__*` variable in your `.env` (for example `IMAGE_TAG__OP_RETH` or `IMAGE_TAG__OP_NODE`).
## Restarting and stopping
```sh theme={null}
# Restart with minimal downtime (no upgrade)
docker compose restart
# Stop the node without wiping any data; safe to start again afterwards
docker compose down
```
**`docker compose down -v` wipes all data**
The `-v` flag deletes the node's volumes, including the chaindata. Only use it when you intend to discard everything and re-sync from scratch.
## Backing up your data
The chaindata lives in `DATADIR_PATH` (default `./envs//datadir`). To back it up, stop the node first so the database is in a consistent state, then copy the datadir:
```sh theme={null}
docker compose down
cp -a ./envs//datadir /path/to/backup
```
## Re-syncing
If you need to rebuild a node, start from an empty `DATADIR_PATH` — a datadir written by op-geth cannot be reused. Bootstrap from a published snapshot (`OP_RETH__SNAPSHOT=true`, required on mainnet) or, on Celo Sepolia, execute every block from genesis; see [Run a node with Docker](/infra-partners/operators/run-node). Pre-L2 historical state for archive nodes is served separately — see [Running an archive node](/infra-partners/operators/archive-node).
# Migrating a Celo L1 Node
Source: https://docs.celo.org/infra-partners/operators/migrate-node
**Legacy path — not needed for op-reth**
`op-reth`, Celo's primary execution client, cannot use a migrated datadir — the migration tool produces geth-format data. Run `op-reth` from an empty datadir instead — bootstrap it from a published snapshot (see [Run a node with Docker](/infra-partners/operators/run-node)) — and serve pre-L2 historical state via the historical RPC service (see [Running an archive node](/infra-partners/operators/archive-node)). The instructions below apply only to the legacy `op-geth` setup, until your network's [switch date](/infra-partners/notices/op-geth-deprecation).
Unless you need to migrate your own Celo L1 data, we recommend using a snapshot instead.
You can find the latest snapshot in the [Network Config & Assets](/infra-partners/operators/network-config) section.
This guide helps Celo L1 node operators migrate their nodes to Celo L2. It describes how to use the [migration tool](https://github.com/celo-org/optimism/tree/celo-rebase-12/op-chain-ops/cmd/celo-migrate) to transform pre-migration database snapshots into a format that Celo L2 nodes can use for a `full` sync.
**Alternative options:**
* **Fresh L2 node**: Skip to the [node operator guide](/infra-partners/operators/run-node) — a new `op-reth` node starts from an empty datadir and bootstraps from a published snapshot (or syncs from genesis on Celo Sepolia)
* **Pre-migrated data**: Download migrated datadirs from [Network Config & Assets](/infra-partners/operators/network-config)
**Terminology**
The terms L1 and pre-hardfork are used interchangeably to reference Celo before the L2 transition. L1 does not refer to Ethereum in this document.
## Migration Overview
Migrating a pre-hardfork datadir involves these high-level steps:
1. Upgrade your L1 node to the [latest client release](/infra-partners/operators/network-config#mainnet) so it will stop producing blocks at the hardfork.
2. Restart your node and wait for the hardfork.
3. Shut down your node once the hardfork block number is reached.
4. Run the migration tool to migrate your L1 datadir and produce the hardfork block.
5. Launch your L2 node with the migrated datadir.
### Important Notes
* The migration tool can be run multiple times as the L1 chain data grows and will continue migrating from where it last left off.
* While the pre-migration can be run multiple times and will get faster each time, you should avoid running the full migration more than once as it will be slower the second time.
* All migrations writing to a given destination datadir must use the same node's source datadir. That is, you should not run the pre-migration with a db snapshot from node A and then run the full migration with a db snapshot from node B.
* Your node must be stopped before the migration tool is run, even once it has reached the hardfork.
* You should not attempt to migrate archive node data, only full node data.
## Preparation Steps
### 1. Upgrade L1 Nodes
All node operators must upgrade their L1 (`celo-blockchain`) nodes to the required version before the hardfork. This release defines migration block numbers so nodes will stop producing blocks at the right time.
### 2. Run a Pre-Migration (Recommended)
**Archive Node Limitation**
Both pre-migration and full migration require **full node data only**. If you only have archive nodes, sync a full node before the hardfork. You cannot migrate archive data, even for L2 archive nodes. See [Running an archive node](/infra-partners/operators/archive-node) for details.
You can use either Docker or build from source.
The pre-migration may take several hours to complete.
#### Using Docker (Recommended)
1. Stop your L1 node
2. Clone the migration repository:
```bash theme={null}
git clone https://github.com/celo-org/celo-l2-node-docker-compose.git
cd celo-l2-node-docker-compose
```
3. Run the pre-migration where `` is `alfajores`, `baklava`, or `mainnet`:
```bash theme={null}
./migrate pre []
```
If a destination datadir is specified, ensure that `DATADIR_PATH` inside `.env` is updated to match when you start your node.
4. Restart your L1 node and wait for the hardfork
#### Using Source Code
1. Stop your L1 node
2. Build the migration tool:
```bash theme={null}
git clone https://github.com/celo-org/optimism.git
cd optimism/op-chain-ops
make celo-migrate
```
3. Run the pre-migration:
```bash theme={null}
go run ./cmd/celo-migrate pre \
--old-db /celo/chaindata \
--new-db /geth/chaindata
```
4. Restart your L1 node and wait for the hardfork
### Key Information
#### Alfajores testnet
* Block number: `26384000`
* Date: September 26, 2024
* Minimum `celo-blockchain` version: [v1.8.7](https://github.com/celo-org/celo-blockchain/releases/tag/v1.8.7)
* `op-geth`: [celo-v2.0.0-rc4](https://github.com/celo-org/op-geth/releases/tag/celo-v2.0.0-rc4)
* `op-node`: [celo-v2.0.0-rc4](https://github.com/celo-org/optimism/releases/tag/celo-v2.0.0-rc4)
#### Baklava testnet
* Block number: `28308600`
* Date: February 20, 2025
* Minimum `celo-blockchain` version: [v1.8.8](https://github.com/celo-org/celo-blockchain/releases/tag/v1.8.8)
* `op-geth`: [celo-v2.0.0-rc4](https://github.com/celo-org/op-geth/releases/tag/celo-v2.0.0-rc4)
* `op-node`: [celo-v2.0.0-rc4](https://github.com/celo-org/optimism/releases/tag/celo-v2.0.0-rc4)
#### Mainnet
* Block number: `31056500`
* Date: March 26, 2025 (3:00 AM UTC)
* Minimum `celo-blockchain` version: [v1.8.9](https://github.com/celo-org/celo-blockchain/releases/tag/v1.8.9)
* `op-geth`: [celo-v2.0.0](https://github.com/celo-org/op-geth/releases/tag/celo-v2.0.0)
* `op-node`: [celo-v2.0.0](https://github.com/celo-org/optimism/releases/tag/celo-v2.0.0)
## Full Migration Process
When the hardfork block number is reached, complete the migration using either Docker (recommended) or source code.
### Hardware Requirements
* Make sure you have enough storage to accommodate 2x the pre-hardfork chaindata. Chaindata size can vary, so please double check your node.
* We recommend using local storage for the source and destination datadirs.
* 16GB+ RAM recommended
### Run Migration with Docker
Once the hardfork block is reached, run the full migration using the same repository:
1. Stop your L1 node when the hardfork block number is reached
2. If you haven't already, clone the migration repository:
```bash theme={null}
git clone https://github.com/celo-org/celo-l2-node-docker-compose.git
cd celo-l2-node-docker-compose
```
3. Run the full migration where `` is `alfajores`, `baklava`, or `mainnet`:
```bash theme={null}
./migrate full []
```
If a destination datadir is specified, ensure that `DATADIR_PATH` inside `.env` is updated to match when you start your node.
### Run Migration from Source
If you prefer not to use Docker, run the migration directly from source:
1. Stop your L1 node when the hardfork block number is reached
2. If you haven't already, build the migration tool:
```bash theme={null}
git clone https://github.com/celo-org/optimism.git
cd optimism/op-chain-ops
make celo-migrate
```
3. Run the full migration:
```bash theme={null}
go run ./cmd/celo-migrate full \
--deploy-config \
--l1-deployments \
--l1-rpc \
--l2-allocs \
--outfile.rollup-config \
--outfile.genesis \
--migration-block-number \
--old-db /celo/chaindata \
--new-db /geth/chaindata \
--l1-beacon-rpc=
```
Note the L1-beacon-RPC-URL must support querying historical `finality_checkpoints`. We are using [https://ethereum-beacon-api.publicnode.com](https://ethereum-beacon-api.publicnode.com) in [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose).
You can check support for historical `finality_checkpoints` by retrieving some suitably old finality\_checkpoints, for example slot 5000000.
```bash theme={null}
curl https://ethereum-beacon-api.publicnode.com/eth/v1/beacon/states/5000000/finality_checkpoints | jq
```
```bash theme={null}
go run ./cmd/celo-migrate full \
--deploy-config \
--l1-deployments \
--l1-rpc \
--l2-allocs \
--outfile.rollup-config \
--outfile.genesis \
--migration-block-number \
--old-db /celo/chaindata \
--new-db /geth/chaindata
```
You can find the required input artifacts in the [Network config & Assets](/infra-partners/operators/network-config) section.
We recommend using the [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose) codebase as an additional reference for running the migration from source.
The full migration process will take at least 5 minutes to complete for mainnet, assuming most data has been pre-migrated. If no pre-migration was performed, it could take several hours.
Congrats! Your datadir is now ready to use with a Celo L2 node. See [Running a Celo Node](/infra-partners/operators/run-node) for instructions on how to start your Celo L2 node.
## Troubleshooting
If you encounter difficulties during the migration that are not covered below, please reach out to our team. You can also check the `celo-l2-node-docker-compose` [README](https://github.com/celo-org/celo-l2-node-docker-compose/blob/main/README.md) and the `celo-migrate` [README](https://github.com/celo-org/optimism/blob/celo-rebase-12/op-chain-ops/cmd/celo-migrate/README.md) for more information on how the migration tooling works.
### Database Error (EOF)
If you encounter this error during migration:
```shell theme={null}
CRIT [03-19|10:38:17.229] error in celo-migrate err="failed to run full migration: failed to get head header: failed to open database at \"/datadir/celo/chaindata\" err: failed to open leveldb: EOF"
```
**Solution:** Start up the celo-blockchain client with the same datadir, wait for it to fully load, then shut it down. This repairs inconsistent shutdown states.
Alternatively, open a console and exit:
```bash theme={null}
geth console --datadir
# Wait for console to load, then exit
```
It seems that this issue is caused by the celo-blockchain client sometimes shutting down in an inconsistent state, which is repaired upon the next startup.
### Missing Data / DB Continuity Check Failures
Both the `pre` and `full` migration commands will first run a script to check whether the source db provided has any gaps in data. This check may fail with an error indicating that data is missing from your source db.
To resolve this:
* Try re-running the migration with a different source datadir if available.
* A full pre-hardfork database snapshot is available in the [Network config & Assets](/infra-partners/operators/network-config) section; we still recommend having your own backup datadir available as well.
* Ensure the datadir is fully synced to just before the hardfork block.
To check if a db has gaps, you can simply re-run the migration command which will automatically perform the check each time.
If needed, you can also run the `check-db` script on its own as follows.
1. Check out and build the latest version of the script in [celo optimism monorepo](https://github.com/celo-org/optimism).
```bash theme={null}
git clone https://github.com/celo-org/optimism
cd optimism/op-chain-ops
make celo-migrate
```
2. Run the script
```bash theme={null}
go run ./cmd/celo-migrate check-db --db-path [--fail-fast]
```
This command takes in an optional `--fail-fast` flag that will make it exit at the first gap detected like it does when run via [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose). If the `--fail-fast` flag is not provided then the script will collect all the gaps it finds and print them out at the end.
# Monitoring & Metrics
Source: https://docs.celo.org/infra-partners/operators/monitoring
The [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose) setup ships with a monitoring stack so you can watch your node's health and sync status.
## Enable monitoring
Set the following in your `.env` file and restart:
```text theme={null}
MONITORING_ENABLED=true
```
This starts four services alongside your node: **Healthcheck**, **Prometheus**, **Grafana**, and **InfluxDB**.
## Grafana dashboards
With monitoring enabled, Grafana is available at [http://localhost:3000](http://localhost:3000) (configurable via `PORT__GRAFANA`).
* **Username:** `admin`
* **Password:** `optimism`
The **Simple Node Dashboard** (Dashboards → Manage → Simple Node Dashboard) shows basic node information and sync status. If you run the challenger, the **Succinct Challenger** dashboard shows challenger activity.
## Where metrics come from
* **op-node** exposes Prometheus metrics on port `7300` (`--metrics.enabled`). Prometheus (port `9090`, configurable via `PORT__PROMETHEUS`) scrapes op-node, op-reth, the healthcheck, and the challenger.
* **op-reth** exposes Prometheus metrics that Prometheus scrapes.
* Grafana reads from Prometheus.
## Key metrics to watch
From **op-node** (Prometheus, `http://localhost:7300/metrics`):
* **`op_node_default_refs_number`** — the op-node's current L1/L2 reference block numbers. If it stops increasing, your node is not syncing; if it goes backwards, your node is reorging.
* **`op_node_default_peer_count`** — how many peers op-node is connected to. Without peers, op-node cannot sync unsafe blocks and your node will lag behind the sequencer.
* **`op_node_default_rpc_client_request_duration_seconds`** — latency of the RPC calls op-node makes to L1 and to the execution client; useful for finding sync bottlenecks.
From the **healthcheck** service:
* **`healthcheck_reference_height - healthcheck_target_height`** — how far your node lags the reference RPC (`HEALTHCHECK__REFERENCE_RPC_PROVIDER`, default `https://forno.celo.org`).
* **`healthcheck_is_currently_diverged`** — non-zero if your node has diverged from the reference chain.
For the full op-node metrics catalog, see the Optimism [Node Metrics and Monitoring](https://docs.optimism.io/node-operators/guides/monitoring/metrics) reference.
## What healthy sync looks like
Even without the Grafana stack, you can confirm your node is syncing:
```sh theme={null}
# Follow op-reth logs — watch it execute blocks toward the chain tip
docker compose logs -n 50 -f op-reth
# Check sync progress (requires foundry)
./progress.sh
# As the node syncs, the head block number climbs and then tracks the network
cast block-number --rpc-url http://localhost:9993
```
In the logs, a syncing node shows `op-reth` importing and executing blocks, with its head advancing toward the network's latest block.
If your node is not syncing or has no peers, see [Troubleshooting](/infra-partners/operators/troubleshooting).
# Network Config & Assets
Source: https://docs.celo.org/infra-partners/operators/network-config
Bootnodes, container images, and downloadable artifacts needed to run a Celo L2 node on each network.
**You don't need to supply `genesis.json` or `rollup.json`**
The recommended [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose) setup selects the chain by name: op-node loads the rollup config from the superchain registry with `--network` (`celo-mainnet` / `celo-sepolia`), and op-reth loads the chain spec — genesis included — with `--chain` (`celo` / `celo-sepolia`). The `genesis.json` and `rollup.json` files below are listed for reference and for custom or from-source setups.
## Mainnet
* op-reth snapshots — published at [`snapshots.celo.org`](https://snapshots.celo.org); a mainnet node must bootstrap from one (`OP_RETH__SNAPSHOT=true`) for the pre-L2 history (see [Run a node](/infra-partners/operators/run-node))
* [Rollup deploy config](https://storage.googleapis.com/cel2-rollup-files/celo/config.json)
* [L1 contract addresses](https://storage.googleapis.com/cel2-rollup-files/celo/deployment-l1.json)
* [L2 allocs](https://storage.googleapis.com/cel2-rollup-files/celo/l2-allocs.json)
* [rollup.json](https://storage.googleapis.com/cel2-rollup-files/celo/rollup.json)
* [Genesis](https://storage.googleapis.com/cel2-rollup-files/celo/genesis.json)
* [Full migrated chaindata](https://storage.googleapis.com/cel2-rollup-files/celo/celo-mainnet-migrated-chaindata.tar.zst) — geth-format, for legacy `op-geth` full/archive sync
* P2P peers
* Execution-client bootnodes, used by op-reth (`OP_RETH__BOOTNODES`) and op-geth (`--bootnodes`):
```text theme={null}
enode://28f4fcb7f38c1b012087f7aef25dcb0a1257ccf1cdc4caa88584dc25416129069b514908c8cead5d0105cb0041dd65cd4ee185ae0d379a586fb07b1447e9de38@34.169.39.223:30303
enode://a9077c3e030206954c5c7f22cc16a32cb5013112aa8985e3575fadda7884a508384e1e63c077b7d9fcb4a15c716465d8585567f047c564ada2e823145591e444@34.169.212.31:30303
enode://029b007a7a56acbaa8ea50ec62cda279484bf3843fae1646f690566f784aca50e7d732a9a0530f0541e5ed82ba9bf2a4e21b9021559c5b8b527b91c9c7a38579@34.82.139.199:30303
enode://f3c96b73a5772c5efb48d5a33bf193e58080d826ba7f03e9d5bdef20c0634a4f83475add92ab6313b7a24aa4f729689efb36f5093e5d527bb25e823f8a377224@34.82.84.247:30303
enode://daa5ad65d16bcb0967cf478d9f20544bf1b6de617634e452dff7b947279f41f408b548261d62483f2034d237f61cbcf92a83fc992dbae884156f28ce68533205@34.168.45.168:30303
enode://c79d596d77268387e599695d23e941c14c220745052ea6642a71ef7df31a13874cb7f2ce2ecf5a8a458cfc9b5d9219ce3e8bc6e5c279656177579605a5533c4f@35.247.32.229:30303
enode://4151336075dd08eb6c75bfd63855e8a4bd6fd0f91ae4a81b14930f2671e16aee55495c139380c16e1094a49691875e69e40a3a5e2b4960c7859e7eb5745f9387@35.205.149.224:30303
enode://ab999db751265c714b171344de1972ed74348162de465a0444f56e50b8cfd048725b213ba1fe48c15e3dfb0638e685ea9a21b8447a54eb2962c6768f43018e5c@34.79.3.199:30303
enode://9d86d92fb38a429330546fe1aefce264e1f55c5d40249b63153e7df744005fa3c1e2da295e307041fd30ab1c618715f362c932c28715bc20bed7ae4fc76dea81@34.77.144.164:30303
enode://c82c31f21dd5bbb8dc35686ff67a4353382b4017c9ec7660a383ccb5b8e3b04c6d7aefe71203e550382f6f892795728570f8190afd885efcb7b78fa398608699@34.76.202.74:30303
enode://3bad5f57ad8de6541f02e36d806b87e7e9ca6d533c956e89a56b3054ae85d608784f2cd948dc685f7d6bbd5a2f6dd1a23cc03e529ea370dd72d880864a2af6a3@104.199.93.87:30303
enode://1decf3b8b9a0d0b8332d15218f3bf0ceb9606b0efe18f352c51effc14bbf1f4f3f46711e1d460230cb361302ceaad2be48b5b187ad946e50d729b34e463268d2@35.240.26.148:30303
```
* op-node bootnodes, to be used with op-node `--p2p.bootnodes` flag:
```text theme={null}
enr:-J64QJipvmFhMq6DVh6RR4HvIiiBtyy1NUg_QlnAAbf18SMqCxCPZtLgUiWED5p0HRVPv69Wth4YPsvdKXSUyh57mWuGAZXRp6HjgmlkgnY0gmlwhCJTtG-Hb3BzdGFja4TsyQIAiXNlY3AyNTZrMaECKPT8t_OMGwEgh_eu8l3LChJXzPHNxMqohYTcJUFhKQaDdGNwgiQGg3VkcIIkBg
enr:-J64QCxBGS49IQbkbwsUuVWt9CkMctMCRe0b-4dqRsLr4QJ1S52urWPUk2uhBU5uerRGpxWTZZW5FtJC-9gSBHN3cSiGAZXRp4rbgmlkgnY0gmlwhCKph0CHb3BzdGFja4TsyQIAiXNlY3AyNTZrMaECqQd8PgMCBpVMXH8izBajLLUBMRKqiYXjV1-t2niEpQiDdGNwgiQGg3VkcIIkBg
enr:-J64QLG71bmmljNbLFx3qim6zXohKA3jbK_4C4d1cwixI-7VMoBIlnM6kWZVvvdWcbjTQ6QXB1LAO39eZWC4Heztj1-GAZXRpzUGgmlkgnY0gmlwhCKpySSHb3BzdGFja4TsyQIAiXNlY3AyNTZrMaEDApsAenpWrLqo6lDsYs2ieUhL84Q_rhZG9pBWb3hKylCDdGNwgiQGg3VkcIIkBg
enr:-J64QKFU-u1x1gt3WmNP88EDUMQ316ymbzdGy83QjkBDqVSsJBn6-nipuqYQDeHYoLBLVJUMdyAiwxVbbDm14qQSf5qGAZXRppmIgmlkgnY0gmlwhCJTfzOHb3BzdGFja4TsyQIAiXNlY3AyNTZrMaEC88lrc6V3LF77SNWjO_GT5YCA2Ca6fwPp1b3vIMBjSk-DdGNwgiQGg3VkcIIkBg
enr:-J64QIXTVl0Opbdn20TSrkzpIZ4xQ54bERRlTmSeZ05dFLdlSbuRY7yn5tJeTPzsSldTw5V5E0qjEQcsfr20vMjTUDyGAZXRpiWygmlkgnY0gmlwhCPjrx6Hb3BzdGFja4TsyQIAiXNlY3AyNTZrMaED2qWtZdFrywlnz0eNnyBUS_G23mF2NORS3_e5RyefQfSDdGNwgiQGg3VkcIIkBg
enr:-J64QFAsbeR4xRSyVyQOk7bILUCoMjI2EnbZvo4UAK3842HMYw41-UZXdnQJH8lwvzWn7qsY3Vu73NuxzxWKn4XB5wiGAZXRpYPAgmlkgnY0gmlwhCJSxmKHb3BzdGFja4TsyQIAiXNlY3AyNTZrMaEDx51ZbXcmg4flmWldI-lBwUwiB0UFLqZkKnHvffMaE4eDdGNwgiQGg3VkcIIkBg
enr:-J64QFQSrL3mfG-i64T-5DgVE5V9dGKC5A0JrEvD6CRpZvuLK3feg4bPaqFWfqXyNN_6IgY2z1Jkr4Mf2Zx-GdWlWquGAZXQkMdSgmlkgnY0gmlwhCImtd-Hb3BzdGFja4TsyQIAiXNlY3AyNTZrMaEDQVEzYHXdCOtsdb_WOFXopL1v0Pka5KgbFJMPJnHhau6DdGNwgiQGg3VkcIIkBg
enr:-J64QAp3g1m-5uX-_mBXWyo6ZQqAlnRcAt11Xwy0-ZzqaSrDSlg4adyOz6v9flzLgxYkVvXI50nJGs8GjLgT5bwDLtyGAZXQrD69gmlkgnY0gmlwhCJMJgaHb3BzdGFja4TsyQIAiXNlY3AyNTZrMaECq5mdt1EmXHFLFxNE3hly7XQ0gWLeRloERPVuULjP0EiDdGNwgiQGg3VkcIIkBg
enr:-J64QFCZs1ePThNEsRxIIzbfDxYfap1nEyuPPpSUeeWOoPFWOp0zSEPwLEtXhG1eH-ipsB5CgtaVzcXOyT9hKeAeVVaGAZXQkaZ3gmlkgnY0gmlwhCO7ajaHb3BzdGFja4TsyQIAiXNlY3AyNTZrMaEDnYbZL7OKQpMwVG_hrvziZOH1XF1AJJtjFT5990QAX6ODdGNwgiQGg3VkcIIkBg
enr:-J64QJ9LY8m9AjNgujuVT0juX8T6PHKojZEIqd-7_vhBasfiT2xUUJoUfWga_xVJGFECFcN6hPKB4TjihmYFxHXelwOGAZXQkclrgmlkgnY0gmlwhCJMELeHb3BzdGFja4TsyQIAiXNlY3AyNTZrMaEDyCwx8h3Vu7jcNWhv9npDUzgrQBfJ7HZgo4PMtbjjsEyDdGNwgiQGg3VkcIIkBg
enr:-J64QGJFPZzLj2GLFgB4JhTde7rXChMNFERNbzrwYYTG7CY2SCSggFrU3VXczzWBvOoJWdbOMOzPuCI2klknGjruUxeGAZXQkf1LgmlkgnY0gmlwhGjHJzuHb3BzdGFja4TsyQIAiXNlY3AyNTZrMaEDO61fV62N5lQfAuNtgGuH5-nKbVM8lW6JpWswVK6F1giDdGNwgiQGg3VkcIIkBg
enr:-J64QEXleDl25w0qEG__wmDgwnzB0F5zapu00D_jM4qkCbA3WIcLC8rXPm8dcrKdZNBuNXJOtNE6c2_ZDkuQMvIuhjCGAZXQwDjFgmlkgnY0gmlwhCKMdU-Hb3BzdGFja4TsyQIAiXNlY3AyNTZrMaECHezzuLmg0LgzLRUhjzvwzrlgaw7-GPNSxR7_wUu_H0-DdGNwgiQGg3VkcIIkBg
```
* Container images:
* [op-reth](https://us-west1-docker.pkg.dev/devopsre/celo-blockchain-public/op-reth:celo-v1.0.0-rc.1)
* [op-node](https://us-west1-docker.pkg.dev/devopsre/celo-blockchain-public/op-node:celo-v2.1.0)
* [eigenda-proxy](https://ghcr.io/layr-labs/eigenda-proxy:v1.8.2)
* [op-geth](https://us-west1-docker.pkg.dev/devopsre/celo-blockchain-public/op-geth:celo-v2.1.0) — legacy, until the switch date
* [Celo L1 client](https://us-docker.pkg.dev/celo-org/us.gcr.io/geth-all:1.8.9) — legacy archive / historical RPC service
## Celo Sepolia
* op-reth snapshots — published at [`snapshots.celo.org`](https://snapshots.celo.org); optional, enable with `OP_RETH__SNAPSHOT=true` to skip syncing from genesis (see [Run a node](/infra-partners/operators/run-node))
* [L1 contract addresses](https://storage.googleapis.com/cel2-rollup-files/celo-sepolia/deployment-l1.json)
* [rollup.json](https://storage.googleapis.com/cel2-rollup-files/celo-sepolia/rollup.json)
* [Genesis](https://storage.googleapis.com/cel2-rollup-files/celo-sepolia/genesis.json)
* P2P peers:
* Execution-client bootnodes, used by op-reth (`OP_RETH__BOOTNODES`) and op-geth (`--bootnodes`):
```text theme={null}
enode://7fd35dfea27042fe008c74ea97c7a41254b293152730419a6e9bcd84bb03c7ced418c1043e2ef6ad63d2facca6fbdacfbf7c4bfcf33ee7e9a0e6b7eb0617595d@34.169.104.197:30303
enode://151bcf170585971fc78129d9c16af355a1a53e1c825ce1ac20700ea754aa33eda60ca83de6f954bfed8d36c53f33295d93dbc3da9d549d6547d09467806b4b3d@104.199.124.11:30303
enode://aa5fb766438ac5a0354eb2eec1c0c002b56bb2ce7ed44f0e76e019cbb931222faa9ecfb0fa0055c0c62a2fcf04492d4129349a1045dfef140585250281885e4b@34.83.115.97:30303
enode://27c81ca466c99016d1595429afc68d66afb3ed9d5a2dd7f6a7797db23a4c826546a177b69b4932f3a75ce374b09d8ccc5b52dad615b3c47dbb8f6217d79ded22@35.247.1.226:30303
enode://c0f8188765317e75616525c34a10de4c54eb060fcaa4ba30010bd2d3cb8cb1f2b5f6245916ef5cea677226e000ab12df7d99cc5d056983fa4668a9502e74b5cd@34.82.193.240:30303
enode://bd330aee83982989bfc04bf32d2a36912c600c74177a8d9d2889992636fed98ffa2f75a70385e123c5f6744dd9ca7685779670fec135248834aba2d3875ba4e0@136.117.28.173:30303
```
* op-node static peers, to be used with op-node `--p2p.bootnodes` flag:
```text theme={null}
enr:-J-4QF7_9Y18cQSQ2wXHD_e65Qy82L1DpfVK4TlOuTDC9oAxeFxmvAn877A2ZXXfc08eLFgZP1mrRjkF4Kts1eGPGbKGAZg2ao5CgmlkgnY0gmlwhCKRF6aHb3BzdGFja4XMiKgFAIlzZWNwMjU2azGhA3_TXf6icEL-AIx06pfHpBJUspMVJzBBmm6bzYS7A8fOg3RjcIIkBoN1ZHCCJAY
enr:-J-4QEbMTKrBfyAeq9hWlEchulzvt1gWA-wAGa_kUdWw1K-faR-AjFNzhcVGG7yDnRb1RptLDGWVpl-WXWhrgJ4TKEaGAZg2XFFugmlkgnY0gmlwhCKotN-Hb3BzdGFja4XMiKgFAIlzZWNwMjU2azGhAxUbzxcFhZcfx4Ep2cFq81WhpT4cglzhrCBwDqdUqjPtg3RjcIIkBoN1ZHCCJAY
enr:-J-4QEawPak_hVU3h1wPZEGu7zLOv1C3k4WI8nHLUc83RqsRMauPtOPt8hYDFyxeJeaUyp0OUM0oyq-_9CEdshE1oWaGAZg2XLgDgmlkgnY0gmlwhCJSX5OHb3BzdGFja4XMiKgFAIlzZWNwMjU2azGhA6pft2ZDisWgNU6y7sHAwAK1a7LOftRPDnbgGcu5MSIvg3RjcIIkBoN1ZHCCJAY
enr:-J-4QCDpfivb0y0Sne1sZOqm1_WOKWWyJ6fo9j93jrxGVm0CcG6tScy3oQAaUuUbh-SmS_cQTO9ciw0_R3q1rpcjGLmGAZg2cWjGgmlkgnY0gmlwhCPFR5uHb3BzdGFja4XMiKgFAIlzZWNwMjU2azGhAifIHKRmyZAW0VlUKa_GjWavs-2dWi3X9qd5fbI6TIJlg3RjcIIkBoN1ZHCCJAY
```
* Container images:
* [op-reth](https://us-west1-docker.pkg.dev/devopsre/celo-blockchain-public/op-reth:celo-v1.0.0-rc.1)
* [op-node](https://us-west1-docker.pkg.dev/devopsre/celo-blockchain-public/op-node:celo-v2.1.0)
* [eigenda-proxy](https://ghcr.io/layr-labs/eigenda-proxy:v1.8.2)
* [op-geth](https://us-west1-docker.pkg.dev/devopsre/celo-blockchain-public/op-geth:celo-v2.1.2) — legacy, until the switch date
# Node Operators
Source: https://docs.celo.org/infra-partners/operators/overview
This section helps you run and operate a Celo L2 node. If you are starting fresh, the fastest path is to [run a full node with Docker](/infra-partners/operators/run-node) — a new node bootstraps from a published snapshot (or, on Celo Sepolia, syncs from genesis), with no L1 data migration required.
## What is a Celo L2 node?
A Celo L2 node is made up of two core services, plus an optional third:
* **Rollup node** (`op-node`) — derives L2 blocks from L1 data, analogous to a consensus client.
* **Execution client** — executes those blocks and exposes the standard Ethereum JSON-RPC API.
* **Legacy L1 (optional)** — serves stateful queries for blocks and transactions from before the L2 transition.
See [Architecture](/infra-partners/operators/architecture) for how these fit together.
## Node types
* **Full node** — follows the chain and serves recent state. Starts from an empty datadir — bootstrap it from a published snapshot (or sync from genesis on Celo Sepolia), with no migrated L1 datadir required. This is the right choice for most operators.
* **Archive node** — additionally preserves all historical state, at the cost of terabytes of storage. See [Running an archive node](/infra-partners/operators/archive-node).
## Execution client
* **op-reth** — Celo's primary execution client, built on `reth`. The guides in this section use `op-reth`.
* **op-geth** — the previous execution client. It is deprecated in favor of `op-reth` and remains supported only until your network's switch date.
**op-geth is being deprecated**
Celo is switching its execution client from `op-geth` to `op-reth`. All node operators must migrate to `op-reth` by their network's switch date. See [End of Support for op-geth](/infra-partners/notices/op-geth-deprecation) for the switch dates and details, and follow the [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose) repository for release updates.
## Guides
* [Run a node with Docker](/infra-partners/operators/run-node) — the fastest way to get a full node syncing (also covers building from source).
* [Run an archive node](/infra-partners/operators/archive-node) — preserve access to all historical state.
* [Run a public RPC node](/infra-partners/operators/public-rpc-node) — operate a public JSON-RPC endpoint (and optionally earn rewards).
* [Monitoring & metrics](/infra-partners/operators/monitoring) — enable the Grafana/Prometheus stack and watch sync health.
* [Upgrades & maintenance](/infra-partners/operators/maintenance) — upgrade clients, restart safely, and back up your data.
* [Troubleshooting](/infra-partners/operators/troubleshooting) — fixes for common node issues.
* [Configuration reference](/infra-partners/operators/configuration) — the `.env` variables and key client flags.
* [Network Config & Assets](/infra-partners/operators/network-config) — bootnodes, container images, and downloadable artifacts.
* [Migrate an L1 node](/infra-partners/operators/migrate-node) — for operators moving existing Celo L1 data to L2 (legacy path).
## Getting help
Please reach out to our team on [Discord](https://chat.celo.org) in the [#celo-L2-support](https://discord.com/channels/600834479145353243/1286649605798367252) channel if you have any questions.
# Running a Public RPC Node
Source: https://docs.celo.org/infra-partners/operators/public-rpc-node
A public RPC node serves JSON-RPC requests to external clients. This page covers the settings specific to operating one; to get a node running first, see [Run a node with Docker](/infra-partners/operators/run-node).
## Serve transaction lookups by hash
A public RPC endpoint should return any transaction by its hash. op-reth exposes the standard `eth` namespace, so transactions are retrievable by hash within the node's retained history, and the [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose) setup needs no extra configuration for this. (On the legacy op-geth setup this instead requires `--history.transactions=0`, which the compose setup sets for you.)
## Forward transactions to the sequencer
op-reth forwards transactions submitted to your endpoint to the sequencer so they are executed, via the `--rollup.sequencer` flag. The sequencer endpoint is set for you by the compose setup (from `OP_RETH__SEQUENCER_URL`):
* Mainnet: `--rollup.sequencer=https://cel2-sequencer.celo.org`
* Celo Sepolia: `--rollup.sequencer=https://sequencer.celo-sepolia.celo-testnet.org`
If it is missing or wrong, transactions submitted to your node are accepted but never executed.
## Exposing the endpoint
op-reth serves JSON-RPC over HTTP on port `9993` and WebSocket on `9994` by default (configurable via `PORT__OP_RETH_HTTP` and `PORT__OP_RETH_WS` — see the [Configuration reference](/infra-partners/operators/configuration#ports)). The compose setup enables the `web3,debug,eth,txpool,net` namespaces on these endpoints.
When exposing this publicly, put a reverse proxy or load balancer with rate limiting in front of it, and be deliberate about which RPC namespaces you expose to untrusted clients.
## Earning rewards
If you want to earn protocol rewards for operating a public RPC endpoint, register it with the Community RPC program:
* [How it works](/contribute-to-celo/community-rpc-nodes/how-it-works)
* [Registering as an RPC node](/contribute-to-celo/community-rpc-nodes/registering-as-rpc-node)
* [Operating a Community RPC Node](/contribute-to-celo/community-rpc-nodes/community-rpc-node) (rewards and claiming)
# Running a Celo Node with Docker
Source: https://docs.celo.org/infra-partners/operators/run-node
This guide is designed to help node operators run a Celo L2 node with Docker.
**Execution client: op-reth**
These instructions use `op-reth`, the execution client Celo is adopting as its primary client. A fresh node starts from an empty datadir and bootstraps from a published snapshot (required on mainnet) or, on Celo Sepolia, syncs from genesis — no L1 data migration required.
`op-geth` remains supported until your network's switch date — see the **Still running op-geth?** notes at the end of this guide, and [End of Support for op-geth](/infra-partners/notices/op-geth-deprecation) for the switch dates.
## Recommended Hardware
### Mainnet
* 16GB+ RAM
* 1TB+ SSD (NVME Recommended)
* Minimum 4 CPU, recommended 8 CPU
* 100mb/s+ Download
### Celo Sepolia Testnet
* 16GB+ RAM
* 500GB SSD (NVME Recommended)
* Minimum 4 CPU, recommended 8 CPU
* 100mb/s+ Download
**Storage Requirements**
Storage size requirements will increase over time, especially for archive nodes.
If running an archive node, please make sure you also have enough storage for the legacy Celo L1 archive datadir. See [Running an archive node](/infra-partners/operators/archive-node).
## Run Node with Docker
To simplify running nodes, Celo has created the [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose) repository with all the necessary configuration files and docker compose templates to make running a Celo L2 node easy.
### Running a Full Node
Follow these steps to run a full node. If you would like to run an archive node, see [Running an archive node](/infra-partners/operators/archive-node).
1. Pull the latest version of [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose) and `cd` into the root of the project.
```bash theme={null}
git clone https://github.com/celo-org/celo-l2-node-docker-compose.git
cd celo-l2-node-docker-compose
```
2. Configure your `.env` file.
#### Copy default configurations
The [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose) repo contains a `.env` file for each Celo network (`celo-sepolia`, `mainnet`). Start by copying the default configuration for the appropriate network.
```bash theme={null}
export NETWORK=
cp $NETWORK.env .env
```
#### Bootstrap your datadir
`op-reth` syncs by executing every block. A new node starts from an **empty** datadir, populated in one of two ways depending on your network:
* **From a snapshot.** Set `OP_RETH__SNAPSHOT=true` in `.env`. On first start with an empty datadir, your node downloads a recent published snapshot (from `snapshots.celo.org`) and continues from there. Once the datadir holds data, the snapshot step is skipped.
```text theme={null}
OP_RETH__SNAPSHOT=true
```
**On mainnet a snapshot is required** — it provides the pre-L2 (Celo L1) history, which `op-reth` cannot reproduce by executing blocks.
* **From genesis.** On **Celo Sepolia**, which has no pre-L2 history, you can leave `OP_RETH__SNAPSHOT=false` (the default) and execute every block from genesis. This needs no external data but takes considerably longer to reach the chain tip.
**Datadirs from op-geth cannot be reused**
`op-reth` uses a different on-disk format. A datadir written by `op-geth` — including one produced by the [L1→L2 migration](/infra-partners/operators/migrate-node) — cannot be used with `op-reth`. Start from an empty `DATADIR_PATH`. Pre-L2 historical state is served separately; see [Running an archive node](/infra-partners/operators/archive-node).
#### Configure node type
Your node will run as a `full` node by default, but can also be configured as an `archive` node if you wish to preserve access to all historical state. See [Running an archive node](/infra-partners/operators/archive-node) for more information.
#### Configure P2P for external network access
**Network Configuration**
If the following options are not configured correctly, your node will not be discoverable or reachable to other nodes on the network. This is likely to impair your node's ability to stay reliably connected to and synced with the network.
* `OP_NODE__P2P_ADVERTISE_IP` - Specifies the public IP to be shared via discovery so that other nodes can connect to your node. If unset, other nodes on the network will not be able to discover and connect to your op-node.
* `PORT__OP_NODE_P2P` - Specifies the port to be shared via discovery so that other nodes can connect to your node. Defaults to 9222.
* `OP_RETH__NAT` - Controls how op-reth determines its public IP that is shared via the discovery mechanism. If the public IP is not correctly configured then other nodes on the network will not be able to discover and connect to your node. The default value of `any` will try to automatically determine the public IP, but the most reliable approach is to explicitly set the public IP using `extip:`. Other acceptable values are `(any|none|upnp|publicip|extip:|stun:)`.
* `PORT__OP_RETH_P2P` - Specifies the port to be shared via discovery so that other nodes can connect to your node. Defaults to 30303.
3. Start the node.
```bash theme={null}
docker compose up -d --build
```
4. Check the progress of the node as it syncs.
```bash theme={null}
docker compose logs -n 50 -f op-reth
```
This will display and follow the last 50 lines of logs. As the node syncs you will see `op-reth` executing blocks and its head advancing toward the network's latest block.
5. Check that node is fully synced.
You can validate that your node is following the network by fetching the current block number via the RPC API and seeing that it climbs as the node syncs and then tracks the network's latest block.
```bash theme={null}
cast block-number --rpc-url http://localhost:9993
```
Until your network's [switch date](/infra-partners/notices/op-geth-deprecation), you can keep running `op-geth` from an existing checkout of [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose) (the latest version runs `op-reth` only). The steps above are the same, with these differences:
* **Sync mode instead of a snapshot.** `op-geth` starts with `snap` sync by default, which downloads pre-hardfork block data from peers — no migrated L1 datadir required. To run `full` sync against a migrated L1 datadir instead, set:
```text theme={null}
OP_GETH__SYNCMODE=full
DATADIR_PATH=
```
* **P2P variables.** Use `OP_GETH__NAT` (values `any|none|upnp|pmp|pmp:|extip:|stun:`) and `PORT__OP_GETH_P2P` (default `30303`) in place of their `OP_RETH__` equivalents.
* **Logs.** Follow `docker compose logs -n 50 -f op-geth`. A syncing node shows `Syncing beacon headers downloaded=...` and later `"Syncing: chain download in progress","synced":"21.07%"`; until fully synced the RPC API returns `0` for the head block number.
After your network's switch date, `op-geth` will no longer follow the chain — migrate to `op-reth` before then.
## Build from source
Docker images are the easiest way to run a Celo node, but you can also build from source — for example to run on a specific architecture or to inspect the code. The [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose) codebase is the best reference, and the [Network Config & Assets](/infra-partners/operators/network-config) page lists everything you need to participate in the network.
## Next steps
* [Run an archive node](/infra-partners/operators/archive-node) — preserve access to all historical state.
* [Network Config & Assets](/infra-partners/operators/network-config) — bootnodes, container images, and downloadable artifacts.
* [Troubleshooting](/infra-partners/operators/troubleshooting) — fixes for common node issues, plus how to get help.
# Troubleshooting
Source: https://docs.celo.org/infra-partners/operators/troubleshooting
## Transactions Are Not Being Executed When Submitted to a Node
If your node is synced but transactions submitted to it are not executed, make sure the sequencer endpoint is correctly set. op-reth forwards transactions to the sequencer via the `--rollup.sequencer` flag, which the compose setup sets for you from `OP_RETH__SEQUENCER_URL`:
* Mainnet: `--rollup.sequencer=https://cel2-sequencer.celo.org`
* Celo Sepolia: `--rollup.sequencer=https://sequencer.celo-sepolia.celo-testnet.org`
If you are hosting a public RPC node, see [Run a public RPC node](/infra-partners/operators/public-rpc-node) for serving transaction lookups by hash.
## Checking Sync Progress
If you are unsure whether your node is syncing, follow the op-reth logs and watch it execute blocks toward the chain tip:
```sh theme={null}
docker compose logs -n 50 -f op-reth
```
You can also run `./progress.sh` from the [celo-l2-node-docker-compose](https://github.com/celo-org/celo-l2-node-docker-compose) repo, or query the head block number — it climbs as the node syncs and then tracks the network's latest block:
```sh theme={null}
cast block-number --rpc-url http://localhost:9993
```
See [Monitoring & metrics](/infra-partners/operators/monitoring) for the Grafana dashboard and the metrics that show sync health.
## Node Is Not Syncing or Has No Peers
If your node stalls or falls behind the sequencer, it usually has too few peers. Check `op_node_default_peer_count` (see [Monitoring & metrics](/infra-partners/operators/monitoring)); if it is low or zero, your node cannot discover or reach other nodes. This is almost always a P2P configuration problem:
* Set `OP_NODE__P2P_ADVERTISE_IP` to your node's public IP.
* Set `OP_RETH__NAT` to `extip:` rather than relying on auto-detection.
* Make sure the P2P ports are reachable (op-reth `30303`, op-node `9222` by default).
See the [Configuration reference](/infra-partners/operators/configuration#networking-p2p) for these variables. Because op-node now syncs via the execution layer, healthy execution-client peer connectivity is required — see [Deprecation of Req/Res CL P2P Sync](/infra-partners/notices/req-resp-cl-sync-deprecation).
## Getting Help
Please reach out to our team on [Discord](https://chat.celo.org) in the [#celo-L2-support](https://discord.com/channels/600834479145353243/1286649605798367252) channel if you have any questions.
# Cel2 FAQ
Source: https://docs.celo.org/legacy/faq
## Mainnet
A couple of issues could be causing this.
* If you are running multiple instances of op-node, make sure to check that they each have a unique and persisted private key at `--p2p.priv.path`
* Ensure that your node is accessible to other nodes, check the **Configure P2P for external network access** section under [Running a full node](/infra-partners/operators/run-node#running-a-full-node)
See the guides for [running a node](/infra-partners/operators/run-node) or the guide on [how to migrate an L1 node](/infra-partners/operators/migrate-node).
Yes. This is part of [running a node](/infra-partners/operators/run-node).
If you're using the [Docker Compose Setup](https://github.com/celo-org/celo-l2-node-docker-compose), it's included.
All balances have been carried over to the L2, unchanged.
There is no change and it continues to work in the same way as before.
Yes, same as with Ethereum.
Have a look at the [changes from L1 to L2 in the specs](/specs/l2-migration#changes-for-json-rpc-users).
Validators are becoming [Community RPC providers](/contribute-to-celo/community-rpc-nodes/community-rpc-node).
There are multiple options.
* Install [Celo CLI](/cli/index) at version 6.1.0 or later. Then run: `celocli network:community-rpc-nodes`.
* [Vido Node Explorer](https://dev.vido.atalma.io/celo/rpc)
* [Celo Community RPC Gateway](https://celo-community.org/)
[Governance](/home/protocol/governance/overview) remains a pillar of the Celo blockchain. The Validator Hotfix process has been adapted, see [Updated Governance Hotfix](/specs/l2-migration#updated-governance-hotfix) for the changes.
* CELO token duality? Supported, see [Token Duality](/specs/token-duality).
* Fee currencies? Supported, see [Fee Abstraction](/specs/fee-abstraction).
* Epoch rewards? Epochs now work differently, but rewards stay, see [Epochs and Rewards](/specs/smart-contract-updates-from-l1#epochs-and-rewards).
See [What's Changed Optimism -> Celo L2](/legacy/transition/optimism/op-l2).
Also see [Celo L2 Specification](/specs) for greater detail.
See [What's changed section covering L1 fees](/legacy/transition/optimism/op-l2#l1-fees).
The block period is 1 second.
The gas limit per block is 30 million, so the maximum throughput is 30M gas/s.
See [What's Changed Celo L1 -> L2](/legacy/transition/whats-changed/l1-l2) and [L1 -> L2 Migration Changes](/specs/l2-migration) in the spec for greater detail.
# Architecture
Source: https://docs.celo.org/legacy/l1-architecture
Overview of the Celo Stack including it's blockchain, core contracts, and applications.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## Introduction to the Celo Stack
Celo is oriented around providing the simplest possible experience for end-users, who may have no familiarity with cryptocurrencies and may be using low-cost devices with limited connectivity.
## A Full-Stack Approach
To achieve this, Celo takes a full-stack approach, where each layer of the stack is designed with the end-user in mind while considering other stakeholders (e.g. operators of nodes in the network) involved in enabling the end-user experience.

## Celo Blockchain
An open cryptographic protocol that allows applications to make transactions with and run smart contracts in a secure and decentralized fashion. The Celo blockchain code has shared ancestry with[ Ethereum](https://www.ethereum.org/) and maintains full EVM compatibility for smart contracts. However, it uses a[ Byzantine Fault Tolerant](http://pmg.csail.mit.edu/papers/osdi99.pdf) (BFT) consensus mechanism (Proof-of-Stake) rather than Proof-of-Work and has different block format, transaction format, client synchronization protocols, and gas payment and pricing mechanisms.
## Celo Core Contracts
A set of smart contracts running on the Celo blockchain that comprise much of the logic of the platform features including ERC-20 stable currencies, identity attestations, proof-of-stake, and governance. These smart contracts are upgradeable and managed by the decentralized governance process.
## Applications
Applications for end users built on the Celo Platform. The Celo Wallet app, the first of an ecosystem of applications, allows end-users to manage accounts and make payments securely and simply by taking advantage of the innovations in the Celo Protocol. Applications take the form of external mobile or backend software: they interact with the Celo blockchain to issue transactions and invoke code that forms the Celo Core Contracts’ API. Third parties can also deploy custom smart contracts that their own applications can invoke, which in turn can leverage Celo Core Contracts. Applications may use centralized cloud services to provide some of their functionality: in the case of the Celo Wallet, push notifications, and a transaction activity feed.
The Celo blockchain and Celo Core Contracts together comprise the Celo Protocol.
## Celo Network Topology
The topology of a Celo network consists of machines running the Celo blockchain software in several distinct configurations:

## Validators
Validators gather transactions received from other nodes and execute any associated smart contracts to form new blocks, then participate in a Byzantine Fault Tolerant (BFT) consensus protocol to advance the state of the network. Since BFT protocols can scale only to a few hundred participants and can tolerate at most a third of the participants acting maliciously, a proof-of-stake mechanism admits only a limited set of nodes to this role.
## Full Nodes
Most machines running the Celo blockchain software are either not configured to be, or not elected as, validators. Celo nodes do not do "mining" as in Proof-of-Work networks. Their primary role is to serve requests from light clients and forward their transactions, for which they receive the fees associated with those transactions. These payments create a ‘permissionless onramp’ for individuals in the community to earn currency. Full nodes maintain at least a partial history of the blockchain by transferring new blocks between themselves and can join or leave the network at any time.
## Light Clients
Applications including the Celo Wallet will also run on each user's device an instance of the Celo blockchain software operating as a ‘light client’. Light clients connect to full nodes to make requests for account and transaction data and to sign and submit new transactions, but they do not receive or retain the full state of the blockchain.
## Celo Wallet
The Celo Wallet application is a fully unmanaged wallet that allows users to self custody their funds using their own keys and accounts. All critical features such as sending transactions and checking balances can be done in a trustless manner using the peer-to-peer light client protocol. However, the wallet does use a few centralized cloud services to improve the user experience where possible, e.g.:
* **Google Play Services:** to pre-load invitations in the app
* **Celo Wallet Notification Service:** sends device push notifications when a user receives a payment or requests for payment
* **Celo Wallet Blockchain API:** provides a GraphQL API to query transactions on the blockchain on a per-account basis, used to implement a user's activity feed.
When end-users download the Celo Wallet from, for example, the Google Play Store, users are trusting both cLabs (or the entity that has made the application available in the Play Store) and Google to deliver a correct binary, and most users would feel that relying on these centralized services to provide this additional functionality is worthwhile.
# Run a Full Node
Source: https://docs.celo.org/legacy/node/run-mainnet
How to run on the Mainnet Network using a prebuilt Docker image.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
Full nodes play a special purpose in the Celo ecosystem, acting as a bridge between the mobile wallets (running as light clients) and the validator nodes.
## Prerequisites
* **You have Docker installed.** If you don’t have it already, follow the instructions here: [Get Started with Docker](https://www.docker.com/get-started). It will involve creating or signing in with a Docker account, downloading a desktop app, and then launching the app to be able to use the Docker CLI. If you are running on a Linux server, follow the instructions for your distro [here](https://docs.docker.com/install/#server). You may be required to run Docker with `sudo` depending on your installation environment.
Code you'll see on this page is bash commands and their output.
When you see text in angle brackets \<>, replace them and the text inside with your own value of what it refers to. Don't include the \<> in the command.
## Celo Networks
First we are going to setup the environment variables required for the `mainnet` network. Run:
```bash theme={null}
export CELO_IMAGE=us.gcr.io/celo-org/geth:mainnet
```
## Pull the Celo Docker image
We're going to use a Docker image containing the Celo node software in this tutorial.
If you are re-running these instructions, the Celo Docker image may have been updated, and it's important to get the latest version.
```bash theme={null}
docker pull $CELO_IMAGE
```
## Set up a data directory
First, create the directory that will store your node's configuration and its copy of the blockchain. This directory can be named anything you'd like, but here's a default you can use. The commands below create a directory and then navigate into it. The rest of the steps assume you are running the commands from inside this directory.
```bash theme={null}
mkdir celo-data-dir
cd celo-data-dir
```
## Create an account and get its address
In this step, you'll create an account on the network. If you've already done this and have an account address, you can skip this and move on to configuring your node.
Run the command to create a new account:
```bash theme={null}
docker run -v $PWD:/root/.celo --rm -it $CELO_IMAGE account new
```
It will prompt you for a passphrase, ask you to confirm it, and then will output your account address: `Public address of the key: `
Save this address to an environment variables, so that you can reference it below (don't include the braces):
```bash theme={null}
export CELO_ACCOUNT_ADDRESS=
```
This environment variable will only persist while you have this terminal window open. If you want this environment variable to be available in the future, you can add it to your `~/.bash_profile`
## Start the node
This command specifies the settings needed to run the node, and gets it started.
```bash theme={null}
docker run --name celo-fullnode -d --restart unless-stopped --stop-timeout 300 -p 127.0.0.1:8545:8545 -p 127.0.0.1:8546:8546 -p 30303:30303 -p 30303:30303/udp -v $PWD:/root/.celo $CELO_IMAGE --verbosity 3 --syncmode full --http --http.addr 0.0.0.0 --http.api eth,net,web3,debug,admin,personal --light.serve 90 --light.maxpeers 1000 --maxpeers 1100 --etherbase $CELO_ACCOUNT_ADDRESS --datadir /root/.celo
```
You'll start seeing some output. After a few minutes, you should see lines that look like this. This means your node has started syncing with the network and is receiving blocks.
```text theme={null}
INFO [07-16|14:04:24.924] Imported new chain segment blocks=139 txs=319 mgas=61.987 elapsed=8.085s mgasps=7.666 number=406 hash=9acf16…4fddc8 age=6h58m44s cache=1.51mB
INFO [07-16|14:04:32.928] Imported new chain segment blocks=303 txs=179 mgas=21.837 elapsed=8.004s mgasps=2.728 number=709 hash=8de06a…77bb92 age=6h33m37s cache=1.77mB
INFO [07-16|14:04:40.918] Imported new chain segment blocks=411 txs=0 mgas=0.000 elapsed=8.023s mgasps=0.000 number=1120 hash=3db22a…9fa95a age=5h59m30s cache=1.92mB
INFO [07-16|14:04:48.941] Imported new chain segment blocks=335 txs=0 mgas=0.000 elapsed=8.023s mgasps=0.000 number=1455 hash=7eb3f8…32ebf0 age=5h31m43s cache=2.09mB
INFO [07-16|14:04:56.944] Imported new chain segment blocks=472 txs=0 mgas=0.000 elapsed=8.003s mgasps=0.000 number=1927 hash=4f1010…1414c1 age=4h52m31s cache=2.34mB
```
You will have fully synced with the network once you have pulled the latest block number, which you can lookup by visiting the [Block Explorer](https://celo.blockscout.com/).
**Security**: The command line above includes the parameter `--http.addr 0.0.0.0` which makes the Celo Blockchain software listen for incoming RPC requests on all network adaptors. Exercise extreme caution in doing this when running outside Docker, as it means that any unlocked accounts and their funds may be accessed from other machines on the Internet. In the context of running a Docker container on your local machine, this together with the `docker -p` flags allows you to make RPC calls from outside the container, i.e from your local host, but not from outside your machine. Read more about [Docker Networking](https://docs.docker.com/network/network-tutorial-standalone/#use-user-defined-bridge-networks) here.
## Running an Archive Node
If you would like to run an archive node for `celo-blockchain`, you can run the following command:
```bash theme={null}
docker run --name celo-fullnode -d --restart unless-stopped --stop-timeout 300 -p 127.0.0.1:8545:8545 -p 127.0.0.1:8546:8546 -p 30303:30303 -p 30303:30303/udp -v $PWD:/root/.celo $CELO_IMAGE --verbosity 3 --syncmode full --gcmode archive --txlookuplimit=0 --cache.preimages --http --http.addr 0.0.0.0 --http.api eth,net,web3,debug,admin,personal --light.serve 90 --light.maxpeers 1000 --maxpeers 1100 --etherbase $CELO_ACCOUNT_ADDRESS --datadir /root/.celo
```
We add the following flags: `--gcmode archive --txlookuplimit=0 --cache.preimages`
In `celo-blockchain`, this is called gcmode which refers to the concept of garbage collection. Setting it to archive basically turns it off.
## Command Line Interface
Once the full node is running, it can serve the [Command Line Interface](/cli/) tool `celocli`. For example:
```bash theme={null}
$ npm install -g @celo/celocli
...
$ celocli node:synced
true
$ celocli account:new
...
```
# Overview
Source: https://docs.celo.org/legacy/overview
Celo was launched in 2020 as a mobile-first Layer 1 blockchain designed to advance global financial inclusion through smartphone-accessible crypto payments and phone number-based addressing. Built on proof-of-stake consensus with a commitment to carbon neutrality, Celo's L1 featured fast, low-cost transactions and native stablecoins like cUSD that powered a vibrant DeFi ecosystem.
In 2024, Celo began migrating from its Layer 1 architecture to become an Ethereum Layer 2 network built on the OP-Stack. This migration aimed to achieve greater scalability and interoperability while preserving Celo's core mission and complete transaction history.
The migration was completed in March 2025 at block 31,056,500.
This section documents the historical Celo Layer 1 blockchain before its completed migration to Layer 2 and does not reflect Celo's current L2 architecture.
### Technical Changes
The table below summarizes the technical changes involved in transitioning from Celo's Layer 1 to Layer 2:
| **Aspect** | **Layer 1** | **Layer 2** |
| --------------------- | ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| **Architecture** | Single service, providing execution, consensus, and data availability. | Multiple services built on the op-stack with separate execution, data availability, and settlement layers. |
| **Bridging** | Third-party bridges connecting to various chains. | Additional native bridge with Ethereum alongside existing third-party bridges. |
| **CELO Token** | Lived on the Celo L1. | Lives on Ethereum; CELO on L2 represents CELO bridged from Ethereum. |
| **Blocks** | 5s long, 50M gas. | 1s long, 30M gas. |
| **Extra Fields** | — | Withdrawals & withdrawalsRoot, blobGasUsed & excessBlobGas, parentBeaconBlockRoot. |
| **Removed Fields** | — | Randomness, epochSnarkData. |
| **Validator Duties** | Operated the consensus protocol. | Validators will temporarily operate community RPC nodes. |
| **Validator Rewards** | Distributed at epoch blocks. | Distributed periodically via smart contract execution. |
| **Sequencing** | Determined by the output of consensus, run by validators. | Initially handled by a centralized sequencer with plans for decentralized sequencing later. |
| **Precompiles** | — | All Celo precompiles removed except for the transfer precompile which supports token duality. |
| **EIP1559** | Governable implementation on-chain. | Upgraded implementation with modified parameters across networks. |
| **Hardforks** | — | Cel2 hardfork for transition to L2 alongside other op-stack hardforks. |
| **Transactions** | — | Deprecated transactions include Type 0 with feeCurrency field and Type 124. |
| **Finality** | One block finality, instantaneous once block is produced. | Finality depends on trust in sequencer, batcher, proposer, and eigenDA, or ultimately on Ethereum. |
For more detailed technical changes, see [Celo's L2 Migration Documentation](/specs/l2-migration).
# Consensus
Source: https://docs.celo.org/legacy/protocol/consensus/index
Overview of Celo's consensus protocol and network validators.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## Protocol
Celo’s consensus protocol is based on an implementation called Istanbul, or IBFT. IBFT was developed by AMIS and [proposed](https://github.com/ethereum/EIPs/issues/650) as an extension to [go-ethereum](https://github.com/ethereum/go-ethereum) but never merged. Variants of IBFT exist in both the [Quorum](https://github.com/jpmorganchase/quorum) and [Pantheon](https://github.com/PegaSysEng/pantheon) clients. We’ve modified Istanbul to bring it up to date with the latest [go-ethereum](https://github.com/ethereum/go-ethereum) releases and we’re fixing [correctness and liveness issues](https://arxiv.org/abs/1901.07160) and improving its scalability and security.
## Finality
Blocks in IBFT protocol are final, which means that there are no forks and any valid block must be somewhere in the main chain. The only way to revert a block would be to utilise social coordination to get all participants to manually revert the block.
## Validators
Celo’s consensus protocol is performed by nodes that are selected as validators. There is a maximum cap on the number of active validators that can be changed by governance proposal, which is currently set at 110 validators. The active validator set is determined via the proof-of-stake process and is updated at the end of each epoch, a fixed period of approximately one day.
# Locating Nodes
Source: https://docs.celo.org/legacy/protocol/consensus/locating-nodes
How Celo nodes join the network, establish a connection, and communiate their IP address.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## V4 Discovery Protocol
All Celo nodes (including our validators) are using a variant of Ethereum's V4 discovery protocol to find other nodes within the network. Details of Ethereum's protocol can be found [here](https://github.com/ethereum/devp2p/blob/master/discv4.md).
## Joining the Network
When a node attempts to join the network, it will execute Celo's discovery protocol.
It will first send a request to the bootnodes to retrieve a list of other nodes of the network. The bootnodes will then reply with that list, and then the joining node will then send additional requests to nodes in that list to find additional nodes in the network. The main difference in Celo's discovery protocol compared to Ethereum's is that it will require that the joining node's networkID be the same as the bootnodes' (and the same as all other network's nodes).
Also, all of the messages in Celo's discovery protocol must be hashed with a special salt to be accepted by other nodes. The reason why these changes were made is so that each node within a network will only store information of other nodes that have the same networkID (to distinguish nodes from other networks) and the same special salt (to distinguish nodes from other blockchains, such as Ethereum).
## Establishing a Connection
Once a joining node finds other nodes, it will establish direct TCP connections to a subset of them. This will allow that node to sync it's blockchain and transactions. Validators will additionally attempt to establish TCP connections to the rest of the validators, so that it can send consensus messages directly to them, instead of via gossip. The reason that the validators do this is to minimize the latency of messages that are sent and received among the validators, and to ultimately help minimize block time.
## Communicating IP Address
The way that validators communicate their IP address to other validators is by periodically gossiping a subprotocol message that we call an *IstanbulAnnounce* message.
That message will contain `n` copies (where `n` is the total number of validators for the current epoch) of the sending validator's IP address where each copy is encrypted with the other validators' public key. Once a validator receives a gossiped *IstanbulAnnounce* message, it will decrypt the encrypted IP address that was encrypted with its public key, and then establish a TCP connection to it. All consensus related messages will then sent via those direct TCP connections.
When an epoch ends, a validator will establish new connections with any newly elected validator and disconnect from any removed validators. If the validator itself is removed from the new epoch's validator set, then it will disconnect with all the validators.
# Validator Set Differences
Source: https://docs.celo.org/legacy/protocol/consensus/validator-set-differences
How validator sets are elected and managed with the Celo protocol.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## Computing Set Differences
The validator set for a given epoch is elected at the end of the last block of the previous epoch. The new validator set is written to the **extradata** field of the header for this block. As an optimization, the validator set is encoded as the difference between the new and previous validator sets. Nodes that join the network are able to compute the validator set for the current epoch by starting with the initial validator set (encoded in the genesis block) and iteratively applying these diffs.
# Add a contract in celo-monorepo
Source: https://docs.celo.org/legacy/protocol/contracts/add-contract
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
## Adding a contract in celo-monorepo
Set up a unit/migration test suit for the contract you just created in celo-monorepo and a short guide to running it successfully on celo test net. We’ll be using `Accounts.sol` as an example.
## After initial contract creation
After the contract is created and it’s ready to be tested, run `yarn build` to trigger typechain which is essentially a TS wrapper for the contract. Keep in mind that everytime you change your contract you have to run `yarn build` once again.
## Unit tests
The test directory is organized the same way as the contracts directory so feel free to navigate to the parent folder of your currently created contract and create a corresponding(.ts) file for it. For example: `celo-monorepo/packages/protocol/contracts/common/Accounts.sol → celo-monorepo/packages/protocol/test/common/accounts.ts`.
Some build issues can be resolved by simply deleting the `build` and the `typechain` folder. Don’t forget to run `yarn build` once again.
# PEAR 🍐
Source: https://docs.celo.org/legacy/protocol/identity/encrypted-cloud-backup
Pin/Password Encrypted Account Recovery.
***
Secure and reliable account key backups are critical to the experience of non-custodial wallets, and Celo more generally.
Day-to-day, users store their account keys on their mobile device, but if they lose their phone, they need a way to recover access to their account.
Described in this document is a protocol for encrypted backups of a user's account keys in their cloud storage account.
## Summary
Using built-in support for iOS and Android, mobile apps can save data backups to Apple iCloud and Google Drive respectively.
When a user installs the wallet onto a new device, possibly after losing their old device, or reinstalls the app on the same device, it can check the user's Drive or iCloud account for account backup data.
If available, this data can be downloaded and used to initialize the application with the recovered account information.
Access to the user's cloud storage requires logging in to their Google or Apple account.
This provides a measure of security as only the owner of the cloud storage account can see the data, but is not enough to confidently store the wallet's account key.
In order to provide additional security, the account key backup should be encrypted with a secret, namely a PIN or password, that the user has memorized or stored securely.
This way, the users account key backup is only accessible to someone who can access their cloud storage account *and* knows their secret.
Because user-chosen secrets, especially PINs, are susceptible to guessing, this secret must be [hardened](https://wikipedia.org/wiki/Hardening_\(computing\)) before it can be used as an encryption key.
Using [ODIS](/legacy/protocol/identity/odis) for [key hardening](/legacy/protocol/identity/odis-use-case-key-hardening), this scheme derives an encryption key for the account key backup that is resistant to guessing attacks.
With these core components, we can construct an account recovery system that allows users who remember their password or PIN, and maintain access to a cloud storage account, to quickly and reliably recover their account while providing solid security guarantees.
Valora is currently working to implement encrypted account recovery, using the user's access PIN for encryption.
### Similar protocols
* [iCloud Keychain](https://support.apple.com/guide/security/secure-icloud-keychain-recovery-secdeb202947/web) uses 6-digit PIN, hardened by an HSM app, and encrypt iCloud Keychain backups.
* [Signal SVR](https://support.apple.com/guide/security/secure-icloud-keychain-recovery-secdeb202947/web) uses a 4-digit PIN or alphanumeric password, hardened by an Intel SGX app, to encrypt contacts and metadata.
* [Coinbase Wallet](https://blog.coinbase.com/backup-your-private-keys-on-google-drive-and-icloud-with-coinbase-wallet-3c3f3fdc86dc) uses a password encrypted cloud backup to store user account keys. It is unclear if any hardening is used.
* [WhatsApp E2E Encrypted Backups](https://engineering.fb.com/2021/09/10/security/whatsapp-e2ee-backups/) uses [OPAQUE](https://datatracker.ietf.org/doc/draft-irtf-cfrg-opaque/) to harden a password encrypted backup
* [MixIn Network TIP](https://github.com/MixinNetwork/tip) uses 6-digit PINs, hardened by a set of signers, to derive account keys
## User experience
Here we describe the user experience of the protocol as designed.
Wallets may alter this flow to suite the needs of their users.
### Onboarding
During onboarding on a supported device, after the PIN or password is set and the account key is created, the user should be informed about the account backup and given a chance opt-out of backup system for their account.
If they opt out, the rest of the setup should be skipped as they will not be using this account recovery system.
On Android, when the user opts-in, they should be prompted to select a Google account that they would like to use to store the backup.
On iOS, the user need not be prompted as there is a single Apple account on the device and the permissions architecture allows access to application-specific iCloud data without prompting the user.
In the background, the chosen PIN or password and a locally generated salt value should be used to query ODIS.
The resulting hardened key should be used to encrypt the BIP-39 account key mnemonic.
The encrypted mnemonic and metadata, including the salt, should be stored in the user's cloud storage.
### Recovery
During recovery, the application should determine if a backup is available in their cloud account.
On iOS, this can be done automatically.
On Android, the user may choose to restore from a cloud backup, at which point they should be prompted to choose their Google account.
If a backup is available the user may select to restore from a cloud backup, at which point they should be asked for their PIN or password.
Given the PIN or password, the application should combine it with the salt value and query ODIS to retrieve the hardened key for decrypting the account key backup.
If successful, the user will be sent to the home screen.
If unsuccessful, the user will be given the option to try again or enter their mnemonic phrase instead.
Users should, by requirement of security, be given a limited number of attempts to enter their PIN or password.
Attempts should be rate limited with a certain number of attempts available immediately (e.g. 3-5 attempts within the first 24 hours), and a limited number of additional attempts available after one or more waiting periods (e.g. up to 10-15 attempts over 3 days).
Once all attempts are exhausted, the backup will become unrecoverable and the user will only be able to recover their account if they have their mnemonic phrase written down.
## Implementation
Client support for the encrypted backup protocol described here is implemented in the [`@social-connect/encrypted-backup` package](https://github.com/celo-org/social-connect/tree/main/packages/encrypted-backup).
Creating a backup file consists of a number of steps to derive the encryption key, and assemble the backup file.
1. Generate a random nonce and hash it with the password or PIN input to get the initial key.
2. Generate a random fuse key and hash it with the initial key to get an updated key.
Encrypt this fuse key to the public key of the circuit breaker service and discard the plaintext fuse key.
3. Send the key as a blinded message to the ODIS to be hashed under a [password hardening domain](/legacy/protocol/identity/odis-use-case-key-hardening).
Use an authentication key derived from the backup nonce such that only a user with access to the backup can make queries to ODIS.
Hash the response from ODIS together with the key to generate the hardened key.
4. Encrypt the account mnemonic phrase with the hardened encryption key, and assemble it together with the nonce, ODIS domain information, encrypted fuse key, and environment metadata for ODIS and the circuit breaker.
If the implementing service does not wish to include a circuit breaker, which is described in more detail below, step two can be skipped.
The backup file created in this protocol can then be stored by the wallet that implements this protocol in some authenticated storage, such as iCloud or Google Drive.
In order to open the backup and recover the users account mnemonic the encrypted backup file is first retrieved from authenticated storage, then the decryption key is derived in the following steps similar to the steps above.
1. Hash the password or PIN input with the nonce in the backup to get the initial key.
2. Query the circuit breaker to unwrap the encrypted fuse key and hash it with the initial key to get an updated key.
3. Send the key as a blinded message to the ODIS to be hashed under the included [password hardening domain](/legacy/protocol/identity/odis-use-case-key-hardening).
Use an authentication key derived from the backup nonce.
Hash the response from ODIS together with the key to generate the hardened key.
4. Decrypt the backup data with the hardened decryption key and return it as the account mnemonic.
### Circuit breaker
In order to handle the event of an ODIS service compromise, this is protocol includes a recommended circuit breaker service.
A circuit breaker service is essentially an online decryption service with a well-known public key that can be taken offline if needed to prevent access to the decryption key.
By using a fuse key which is decrypted to the circuit breaker service, and therefore can only be accessed if the service is online, as a step to derive the encryption key for the backup, the circuit breaker service operator is able to disable decryption of backup files in case of an emergency to protect user funds.
In particular, if the ODIS key hardening service is discovered to be compromised, the circuit breaker operator will take their service offline, preventing backups using the circuit breaker from being opened.
This ensures that an attacker who has compromised ODIS cannot leverage their attack to forcibly open backups created with this function.
### PIN Blocklist
When using a 4 or 6 digit PIN code to encrypt a backup, there are a number of PINs that are far more common than common than others.
Sequences (123456), patterns (124578) and important dates (110989) are chosen most frequently.
Within 30 guesses, an attacker has a 5-9% chance of guessing a users first-choice PIN code, as suggested by [research into PIN security](https://this-pin-can-be-easily-guessed.github.io/).
In order to address this, it is highly recommended to block the most easily guessed PINs.
One way to do this is to block PINs that are most popular.
A suggested implementation, which is [implemented by the Valora wallet](https://github.com/valora-inc/wallet/blob/3940661c40d08e4c5db952bd0abeaabb0030fc7a/packages/mobile/src/pincode/authentication.ts#L56-L108), is to create a blocklist from the top 25k most frequently seen PINs in the HIBP Passwords dataset.
# Identity Overview
Source: https://docs.celo.org/legacy/protocol/identity/index
How Celo maps wallet addresses to phone numbers to make financial tools more accessible to mobile phone users.
***
Celo's Identity protocol has moved to [docs.self.xyz](https://docs.self.xyz/).
## Introduction to Identity on Celo
Celo’s unique purpose is to make financial tools accessible to anyone with a mobile phone. One barrier for the usage of many other platforms is their required usage of 30+ hexadecimal-character-long strings as addresses. It’s like bank account numbers, but worse. Hard to remember, easy to mess up. They are so hard to use that the predominant way of exchanging addresses is usually via copy-paste over an existing messaging channel or via QR-codes in person. Both approaches are practically interactive protocols and thus do not cover many use cases in which people would like to transact. Celo offers an optional lightweight identity layer that starts with a decentralized mapping of phone numbers to wallet addresses, allowing users to transact with one another via the most common identity scheme everyone is familiar with: their address book.

### Adding their phone number to the mapping
To allow Bob to find an address mapped to her phone number, Alice can use the decentralized attestations protocol to link an account address to her phone number. Alice starts by making a request to the `Attestations` contract; transferring a fee along with her request. After a brief waiting time of `4` blocks (20 seconds), the `Attestations` contract will use the `Random` contract to produce a random selection of validators, from the current elected set in the `Validators` contract, to issue the attestation challenges.
As part of the expectation of validators, they run the attestation service whose endpoint they register in their [Metadata](/legacy/protocol/identity/metadata). After attestation issuers have been selected for their requests, Alice determine the validators' attestation service URLs from her [Metadata](/legacy/protocol/identity/metadata) and requests an attestation message to her phone number by sending a direct HTTPS request. In turn, the attestation service produces a signed secret message attesting to the ownership of the given phone number by the requesting account. The validator sends the message to Alice's phone number via SMS. Read more under [attestation service](#attestation-service).
When Alice receives the text message, she can take that signed message to the `Attestations` contract, which can verify that the attestation came from the validator indeed. Upon a successful attestation, the validator can redeem for the attestation request fee to pay them for the cost of sending the SMS. In the end, we have recorded an attestation by the validator to a mapping of Alice’s phone number to her account address.
### Using the mapping for payment
Once Alice has completed attestations for their phone number/address, Bob, who has her phone number in his contact book, can see that Alice has an attested account address with her phone number. He can use that address to send funds to Alice, without her having to specifically communicate her address to Bob.
The `Attestations` contract records all attestations of a phone number to any number of addresses. That for example could happen when a user loses their private key and wants to map a new wallet address. However, it could also happen through the collusion of a validator with Alice. Therefore, it is important that clients of the identity protocol highlight possible conflicting attestations.
Some risk exists for attestations to be added without the permission of the "legitimate" owner of the phone number. One such risk is that the phone service provider or [SIM swap](https://wikipedia.org/wiki/SIM_swap_scam) attacker could take control of the phone number and complete a number of attestations. Another risk is that a sufficient number of Attestation Service providers may collude to complete fake attestations. Notably, completing malicious attestations does not lead to a loss of funds, as the private key is still the necessary and sufficient condition for transactions of an account. However, without proper care, future senders may be tricked into sending funds to the newly associated address. In general the number and age of attestations for an address should be taken into account to identify the valid owner of a phone number.
There are additional measures we can take to further secure the integrity of the mapping’s usage. In the future we plan to provide reference implementations in the wallet for some of these. For example, we plan to detect remapping of wallet addresses. Many users are already accustomed to sending small amounts first and verifying the receipt of those funds before attempting to transfer larger amounts.
### Preventing harvesting of phone numbers
To protect user privacy by preventing mass harvesting of phone numbers, the Celo platform includes a service that obfuscates the information saved on the blockchain. The service is enabled by default for all Celo Wallet users. Details of its functionality and architecture are explained in [Phone Number Privacy](/legacy/protocol/identity/odis-use-case-phone-number-privacy)
### Attestation service
The attestation service is a simple Node.js service that validators run to send signed messages for attestations. It can be configured with SMS providers, as different providers have different characteristics like reliability, trustworthiness and performance in different regions. The attestation service currently supports [Twilio](https://www.twilio.com) and [Nexmo](https://nexmo.com). Celo should widen the number of supported providers over time.
### Future improvements to privacy
Celo is committed to meet the privacy needs of its users. More details about areas for future research can be found in [Privacy Research](/legacy/protocol/identity/privacy-research)
# Metadata and Claims
Source: https://docs.celo.org/legacy/protocol/identity/metadata
How the Celo protocol's **metadata and claims** feature makes it possible to connect on-chain with off-chain identities.
***
## Use Cases
* Tools want to present public metadata supplied by a validator or validator group as part of a list of candidate groups, or a list of current elected validators.
* Governance Explorer UIs may want to present public metadata about the creators of governance proposals
* The Celo Foundation receives notice of a security vulnerability and wants to contact elected validators to facilitate them to make a decision on applying a patch.
* A DApp makes a request to the Celo Wallet for account information or to sign a transaction. The Celo Wallet should provide information about the DApp to allow the user to make a decision whether to sign the transaction or not.
Furthermore, these tools may want to include user chosen information such as names or profile pictures that would be expensive to store on-chain. For this purpose, the Celo protocol supports **metadata** that allows accounts to make both verifiable as well as non-verifiable claims. The design is described in [CIP3](https://github.com/celo-org/CIPs/pull/4).
On the `Accounts` smart contract, any account can register a URL under which their metadata file is available. The metadata file contains an unordered list of claims, signed by the account.
## Types of Claim
ContractKit currently supports the following types of claim:
* **Name Claim** - An account can claim a human-readable name. This claim is not verifiable.
* **Attestation Service URL Claim** - For the [lightweight identity layer](/legacy/protocol/identity), validators can make a claim under which their Attestation Service is reachable to provide attestations. This claim is not verifiable.
* **Keybase User Claim** - Accounts can make claims on [Keybase](https://keybase.io) usernames. This claim is verifiable by signing a message with the account and hosting it on the publicly accessible path of the Keybase file system.
* **Domain Claim** - Accounts can make claims on domain names. This claim is verifiable by signing a message with the account and embedding it in a [TXT record](https://wikipedia.org/wiki/TXT_record).
In the future ContractKit may support other types of claim, including:
* **X User Claim** - Accounts can make claims on [X](https://x.com/) usernames. This claim is verifiable by signing a message with the account and posting it as a tweet. Any client can verify the claim with a reference to the tweet in the claim.
## Handling Metadata
You can interact with metadata files easily through the [CLI](/cli/account), or in your own scripts, tools or DApps via [ContractKit](/developer/contractkit/). Most commands require a node being available under `http://localhost:8545` to make view calls, and to modify metadata files, you'll need the relevant account to be unlocked to sign the files.
You can create an empty metadata file with:
```bash theme={null}
celocli account:create-metadata ./metadata.json --from $ACCOUNT_ADDRESS
```
You can add claims with various commands:
```bash theme={null}
celocli account:claim-attestation-service-url ./metadata.json --from $ACCOUNT_ADDRESS --url $ATTESTATION_SERVICE_URL
```
You can display the claims in your file and their status with:
```bash theme={null}
celocli account:show-metadata ./metadata.json
```
Once you are satisfied with your claims, you can upload your file to your own web site or a site that will host the file (for example, [https://gist.github.com](https://gist.github.com) and then register it with the `Accounts` smart contract by running:
```bash theme={null}
celocli account:register-metadata --url $METADATA_URL --from $ACCOUNT_ADDRESS
```
Then, anyone can lookup your claims and verify them by running:
```bash theme={null}
celocli account:get-metadata $ACCOUNT_ADDRESS
```
# ODIS Domains
Source: https://docs.celo.org/legacy/protocol/identity/odis-domain
Domain API features described here are not deployed to Mainnet ODIS as of April 1, 2022.
In order to support use cases such as password hardening, and future applications, ODIS implements Domains.
A Domain instance is structured message sent to ODIS along with the secret blinded message.
Unlike the blinded message, the Domain instance is visible to the ODIS service and allows the client to specify context information about their request.
This context information is used to decide what rate limit and/or authentication should be applied to the request, and is combined into the result to ensure output is unique to the context.
The Domain instance and blinded message are both passed to the ODIS partially oblivious pseudorandom function (POPRF), which is a new construction extending upon the [OPRF function](/legacy/protocol/identity/odis) used in the [phone number privacy service](/legacy/protocol/identity/odis-use-case-phone-number-privacy).
As an example, a Domain for hashing an account password might specify an application username of "vitalik.eth" (context) and a cap of 10 password attempts (rate-limiting parameter).
These would be combined with the user's password (blinded input) in the POPRF, which acts as a one-way function, to form the final output.
As a result the rate limiting parameters, in this case allowing a total of 10 queries, can be set to arbitrary values but are effectively binding once chosen.
This allows the parameters to be tuned to the needs of the individual user or application and prevents potential overlap of different use cases.
Queries with distinct domain specifiers will receive uncorrelated output.
For example, output from ODIS with the phone number domain and message `18002738255` will be distinct from and unrelated to the output when requesting with a password domain and message `18002738255`.
In order to make this scheme flexible, allowing for user-defined tuning of rate-limits and the introduction of new rate limiting and authorization rules in the future, domains are defined as serializeable structs.
New domain types, with associated rate-limiting rules, may be added in the future to meet the needs of new applications.
## Specification
A full specification of Domains and the related ODIS APIs is available in CIP-40.
* [CIP-40](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0040.md)
## Implemented Domains
* [Sequential Delay Domain](/legacy/protocol/identity/odis-domain-sequential-delay-domain)
## Creating a Domain Type
The Domains interface is designed to be flexible to facilitate new applications for the ODIS POPRF function.
If you have an application that would benefit from a new Domain type and rate limiting ruleset, the first step is to open an extension to the CIP-40 standard.
New Domain types are standardized through a lighter version of the [general CIP process](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0000.md).
Open a PR against the celo-org/celo-proposals repository to add a specification for your new domain to the [CIP-40 extensions folder](https://github.com/celo-org/celo-proposals/tree/master/CIPs/CIP-0040).
As an example for what you should include, take a look at the [specification](https://github.com/celo-org/celo-proposals/blob/master/CIPs/CIP-0040/sequentialDelayDomain.md) for the `SequentialDelayDomain`.
When it is ready for review, contact a [CIP editor](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0000.md#cip-editors) to help get reviews from the ODIS core development team.
Implementing a new Domain type, which includes new rate limiting to be enforced by the ODIS operators, requires an upgrade to the ODIS server implementation.
Once the new domain type is standardized, this implementation can be written and deployed to the staging and production ODIS service operators.
# Sequential Delay Domain
Source: https://docs.celo.org/legacy/protocol/identity/odis-domain-sequential-delay-domain
The Sequential Delay Domains is an [ODIS Domain](/legacy/protocol/identity/odis-domain) supporting signature-authenticated rate limits defined as a series of time-delayed stages.
The motivating use case is allowing wallets to define how often users can attempt to recover their account via the scheme outlined in [Pin/Password Encrypted Account Recovery](/legacy/protocol/identity/encrypted-cloud-backup), but can be used in any other application that need an authenticated rate limit represented as a series of time delayed stages.
## Specification
A full specification of the Sequential Delay Domain is available in an extension to CIP-40.
* [Sequential Delay Domain Specification](https://github.com/celo-org/celo-proposals/blob/master/CIPs/CIP-0040/sequentialDelayDomain.md)
# Key Hardening
Source: https://docs.celo.org/legacy/protocol/identity/odis-use-case-key-hardening
Passwords are useful primitive in a number of applications, allowing a user to authenticate themselves by knowing the secret information.
Unfortunately, effective offline password cracking techniques limit the use of passwords to derive encryption or authentication keys.
An attacker with access to a signature or encrypted file that used a password, or the hash of a password, as the key can make repeated guesses until they find the password.
Given advanced tools such as [`hashcat`](https://hashcat.net/hashcat/) and extensive experience, hackers are very good at guessing passwords.
Rate-limited or expensive hashing can be used to make it much more difficult to crack a password.
Computationally expensive password hashing functions, such as PBKDF and scrypt, are commonly used for this purpose, but provide [limited protection](https://arxiv.org/abs/2006.05023) and are expensive to run on end-user devices.
ODIS implements hashing (i.e. PRF evaluation) with a rate limit controlled by the committee of ODIS operators, and can be used to harden a password into a stronger cryptographic key.
As long as this committee remains collectively honest and secure, an attacker cannot make more guesses at a users password than ODIS allows, making it extremely unlikely a good password will be broken.
Using ODIS for key hardening allows passwords to be used in a number of applications, including to create [encrypted account backups](/legacy/protocol/identity/encrypted-cloud-backup) and as a factor in [smart contract account recovery](/legacy/protocol/identity/smart-contract-accounts).
## Rate limiting
Choosing an appropriately restrictive rate limit is crucial.
Using a rate limit that is too restrictive may cause users to become frustrated as their access is denied if they take too many tries to recall their password, and a rate limit that is too loose can allow an attacker a much better chance at guessing the users password.
The appropriate rate limit is related to how much entropy the user secret has.
* A strong user password can tolerate a loose rate limit, allowing millions of attempts without significant chance of attacker success.
* An average user password can tolerate a moderate rate limit, allowing hundreds of attempts.
* A 4 or 6 digit PIN can tolerate tens of attempts before the attacker has a significant chance of success.
Because the right rate limit is context specific, [Domains](/legacy/protocol/identity/odis-domain) can be configured to the needs of the user.
The [Sequential Delay Domain](/legacy/protocol/identity/odis-domain-sequential-delay-domain) is designed for the use case of PIN and password hashing, and can be used to allow for a fixed number of attempts over a configurable time period (e.g. 15 attempts over 3 days).
The Sequential Delay Domain additionally supports signature-based authentication to prevent quota from being consumed by any except the intended user.
## Salting
Even with the use of ODIS to prevent brute-force guessing of a password, it remains important to include a user-specific value in the hashing request as a salt to prevent [rainbow table attacks](https://wikipedia.org/wiki/Rainbow_table).
A salt can be included in the Domain parameter of the request to ODIS to ensure a rate limit is enforced specific to the user's context.
Using a random salt value is recommended, however a client identifier such as a username or [phone number hash](/legacy/protocol/identity/odis-use-case-phone-number-privacy) can also be used.
## Password filtering
In addition to using ODIS to harden passwords chosen by users, it is recommended that the application help the user choose a good password during onboarding.
Password filtering, blocking the user from setting a password which may be weak, can greatly improve the quality of a user's password and prevent it being broken by guessing the most common passwords (e.g. "password").
[NIST 800-63](https://pages.nist.gov/800-63-3/sp800-63-3.html) recommends that passwords should be checked against a list of known compromised passwords, such as [HIBP Passwords](https://haveibeenpwned.com/Passwords).
Additional research has found other [practical techniques for increasing the strength of passwords chosen by users](https://www.andrew.cmu.edu/user/nicolasc/publications/Tan-CCS20.pdf).
# Phone Number Privacy
Source: https://docs.celo.org/legacy/protocol/identity/odis-use-case-phone-number-privacy
Celo's [identity protocol](/legacy/protocol/identity) allows users to associate their phone number with one or more addresses on the Celo blockchain.
This allows users to find each other on the Celo network using phone number instead of cumbersome hexadecimal addresses.
The Oblivious Decentralized Identifier Service (ODIS) was created to help preserve the privacy of phone numbers and addresses.
* [ODIS](/legacy/protocol/identity/odis)
## Understanding the problem
When a user sends a payment to someone in their phone's address book, the mobile client must look up the identifier for that phone number on-chain to find the corresponding Celo blockchain address.
This address is needed in order to create a payment transaction, and the user may only know the phone number of the person they want to pay.
If cleartext phone numbers were used as identifiers directly on the Celo network, then anyone would be able to associate all phone numbers with blockchain accounts and balances (e.g. After searching for addresses with a high balance, they could look up the associated phone number to [phish](https://wikipedia.org/wiki/Phishing) the account owner).
If instead, the identifier was the hash of the recipient's phone number, attackers would still be able to associate phone numbers with accounts and balances via a [rainbow table attack](https://wikipedia.org/wiki/Rainbow_table).
## The solution
The basis of the solution is to derive a user's identifier from both their phone number and a secret pepper that is provided by the Oblivious Decentralized Identifier Service (ODIS).
In order to associate a phone number with a Celo blockchain address, the mobile wallet first queries ODIS for the pepper.
It then uses the pepper to compute the unique identifier that's used on-chain.
Peppers produced by ODIS are cryptographically strong, and so cannot be guessed in a brute force or rainbow table attack.
ODIS imposes a rate limit controlling how many peppers any individual can request, and so prevents an attacker from scanning a large number of phone numbers in an attempt to compromise user privacy.
### Pepper request rate limiting
ODIS imposes a rate limit on requests for peppers in order to limit the feasibility of rainbow table attacks.
When ODIS receives a request for a pepper, it authenticates the request and ensures the requester has not exceeded their quota.
Since blockchain accounts and phone numbers are not naturally Sybil-resistant (i.e. individuals can have many accounts or phone numbers), ODIS bases request quota on the following factors:
* Requester transaction history
* Requester phone number attestation count and success rate
* Requester account balance
The requirements for these factors are configured to make it prohibitively expensive to scrape large quantities of phone numbers while still allowing typical user flows to remain unaffected.
In particular, it should be possible for a user to look up their contacts in order to send them payments.
# Future Privacy Research
Source: https://docs.celo.org/legacy/protocol/identity/privacy-research
Celo is committed to meet the privacy needs of its users. This section describes future plans for delivering on this commitment, while also sharing the current limitations of the Celo networks.
### Privacy mode
One downside to this identity protocol is that knowledge of a phone number can let anyone quickly determine the balance of the associated wallet, which of course may be unacceptable for many use cases. For these circumstances, the contract allows users to use the `Attestations` contract in privacy mode. In this mode, the user does not map their phone number to their wallet address, but to an account that is not meant to be the recipient of transfers. Through a registered encryption key on the user’s account on the contract, schemes can be derived to allow users to selectively reveal their true wallet addresses to authorized participants.
# Smart Contract Accounts
Source: https://docs.celo.org/legacy/protocol/identity/smart-contract-accounts
Smart contract accounts are used to enable features beyond what can be accomplished with an externally owned account (EOA) alone.
In this document, we'll describe some of the features and considerations associated with smart contract accounts in general, and the architecture used by the Valora wallet in particular as an example of how smart contract accounts can be used.
EOAs are what most people think of when they imagine a blockchain wallet.
EOAs are comprised of an ECDSA public/private key pair from which the on-chain address is derived.
The account address is derived from the public key, and transactions are authorized by the private key.
In most wallets, the EOA is generated and stored on the user's mobile device and backed up via a BIP-39 mnemonic phrase.
A smart contract account on the other hand is a smart contract that can be used to interact with other smart contracts on behalf of the owner.
Celo provides an open-source implementation of a smart contract account; the [meta-transaction wallet](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/common/MetaTransactionWallet.sol) (MTW).
In general, ownership can be determined in arbitrary ways, but most commonly an EOA is designated as the owner and can authorize transactions my signing a meta-transaction containing the details of the authorized transaction.
This is how the meta-transaction wallet works.
In this case you can think of the smart contract account as the primary account, and the EOA as the controller of this account.
## Benefits of a smart contract account
### Separation of signer and payer
When new users create a wallet, they start with an empty balance.
This makes it difficult for the new users to verify their phone number as they need to pay for both the Celo transactions and the Attestation Service fees ([see here for more details](/legacy/protocol/identity/)).
To make this experience more intuitive and frictionless for new users, cLabs operates an [onboarding service called Komenci](https://github.com/celo-org/komenci/) that pays for the transactions on behalf of the user.
It does this by first deploying a meta-transaction wallet contract and setting the wallet EOA address as the signer.
At this point, the EOA can sign transactions and submit them to Komenci.
Komenci will wrap the signed transaction into a meta-transaction, which it pays for and submits to the network.
In general, smart contract accounts allow the someone other than the account owner to pay for the transaction fees required to submit a transaction to the blockchain, enabling a number of useful operations not otherwise possible.
### Account recovery
Smart contract accounts can also be useful if a user ever loses their phone and recovery phrase.
Unlike EOAs, smart contract accounts can support account recovery methods that do not rely solely on recovering the underlying keys.
The meta-transaction wallet implements [a function](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/common/MetaTransactionWallet.sol#L101-L108) to assign another Celo address as the Guardian of the account.
This Guardian can be a simple backup key or a smart contract implementing social recovery, [KELP](https://eprint.iacr.org/2021/289), or another account recovery protocol.
With the authorization of the Guardian, the meta-transaction wallet will update the owner of the account to replace the lost key.
Any funds or privileges held by the meta-transaction wallet are then recovered to the user who can control the account using their new key.
### Transaction batching
With smart contract accounts, including the meta-transaction wallet, transactions can be batched together to execute atomically.
This makes for a better user experience, as transactions can be guaranteed to execute all together or entirely revert.
It can also prevent some cases where front-running would be possible by splitting the user's transactions.
## Valora accounts
Behind every Valora wallet are two types of accounts: an externally owned account (EOA) and a meta-transaction wallet.
Valora generates the EOA during onboarding, and has a meta-transaction wallet deployed for it by Komenci with the generated EOA as the signer.
Using this configuration, Valora users gain the benefits listed above, including having Valora pay for the transaction fees associated with onboarding.
## Sending to a Valora wallet
When performing a payment to a Valora wallet, it's important that the address that is receiving funds is the EOA, and not the MTW since funds in the MTW are not displayed or directly accessible to Valora users.
To look up a wallet using a phone number:
1. Use ODIS to query the phone number pepper
2. Use the phone number pepper to get the on-chain identifier
3. Use the on-chain identifier to get the account address
4. Use the account address to get the wallet address (EOA)
The first two steps are covered extensively in [this guide](/developer/contractkit/odis).
To get the account address (step 3) you can use the [Attestation contract method `lookupAccountsForIdentifier`](https://github.com/celo-org/celo-monorepo/blob/e6fdaf798a662ffe2c12f9a74b28e0fa1c1f8101/packages/sdk/contractkit/src/wrappers/Attestations.ts#L472).
To get the wallet address from the account (step 4) you can use the [Account contract method `getWalletAddress`](https://github.com/celo-org/celo-monorepo/blob/e6fdaf798a662ffe2c12f9a74b28e0fa1c1f8101/packages/sdk/contractkit/src/wrappers/Accounts.ts#L318).
It may also be necessary to lookup the data encryption key (ex. [for comment encryption](/legacy/protocol/transaction/tx-comment-encryption)). This key can similarly be queried with the account by using the [Account contract method `getDataEncryptionKey`](https://github.com/celo-org/celo-monorepo/blob/e6fdaf798a662ffe2c12f9a74b28e0fa1c1f8101/packages/sdk/contractkit/src/wrappers/Accounts.ts#L310).
You can view a working example of this all tied together in [the `celocli` command `identity:get-attestations`](https://github.com/celo-org/celo-monorepo/blob/master/packages/cli/src/commands/identity/get-attestations.ts).
## Enabling Valora to interact with your dApp
### Signatures
Since all Valora users will have the use a meta-transaction wallet, it's important to keep in mind that transactions may originate from an EOA as well as a smart contract.
If your contract relies upon EIP-712 signed typed data, be sure to also support typed data originating from contracts.
This data can't be signed by the `msg.sender` since it's originating from a contract, but is implicitly authorized by originating from the contract.
## Implementation
The implementation of the meta-transaction wallet can be [found here](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/common/MetaTransactionWallet.sol).
# Epoch Rewards
Source: https://docs.celo.org/legacy/protocol/pos/epoch-rewards
Introduction to Celo epoch rewards and the target reward release schedule.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## What are Epoch Rewards?
**Epoch Rewards** are similar to the familiar notion of block rewards in other blockchains, minting and distributing new units of CELO as blocks are produced, to create several kinds of incentives.
**Epoch rewards are paid in the final block of the epoch and are used to:**
* Distributed [rewards for validators and validator groups](/legacy/protocol/pos/epoch-rewards-validator)
* Distribute [rewards to holders of Locked CELO](/home/protocol/epoch-rewards/index) voting for groups that elected validators
* Make payments into a [Community Fund](/home/protocol/epoch-rewards/community-fund) for protocol infrastructure grants
* Make payments into a [Carbon Offsetting Fund](/home/protocol/epoch-rewards/carbon-offsetting-fund) for carbon offsetting projects
A total of 400 million CELO will be released for epoch rewards over time. CELO is a utility and governance asset on Celo, and also the reserve collateral for Celo Dollar (and possibly in the future other whitelisted tokens). It has a fixed total supply and in the long term will exhibit deflationary characteristics similarly to Ethereum.
### Reward Disbursement
The total amount of disbursements is determined at the end of every epoch via a two step process.
**Step 1**
In step one, economically desired **on-target rewards** are derived. These are explained in the following pages. Several factors can increase or decrease the value of the payments that would ideally be made in a given epoch (including the CELO to Dollar exchange rate, the collateralization of the reserve, and whether payments to validators or groups are held back due to poor uptime or prior slashing).
**Step 2**
In step two, these on-target rewards are adjusted to generate a drift towards a predefined target epoch rewards schedule. This process aims to solve the trade-off between paying reasonable rewards in terms of purchasing power and avoiding excessive over- or underspending with respect to a predefined epoch rewards schedule. More detail about the two steps is provided below.
## Adjusting Rewards for Target Schedule
There is a target schedule for the release of CELO epoch rewards. The proposed target curve (subject to change) of remaining epoch rewards declines linearly over 15 years to 50% of the initial 400 million CELO, then decays exponentially with half life of $h = ln(2)\times15 =10.3$ afterwards. The choice of $h$ guarantees a smooth transition from the linear to the exponential regime.

The total **actual rewards** paid out at the end of a given epoch result from multiplying the total on-target rewards with a `Rewards Multiplier`. This adjustment factor is a function of the percentage deviation of the remaining epoch rewards from the target epoch rewards remaining. It evaluates to `1` if the remaining epoch rewards are at the target and to smaller (or larger) than `1` if the remaining rewards are below (or above, respectively) the target. This creates a drag towards the target schedule.
The sensitivity of the adjustment factor to the percentage deviation from the target are governable parameters: one for an underspend, one for an overspend.
# Locked CELO Rewards
Source: https://docs.celo.org/legacy/protocol/pos/epoch-rewards-locked-gold
How to earn locked CELO rewards and adjust the rate for voting participation, target schedule, and deductions.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## Introduction to Locked CELO Rewards
Holders of Locked CELO that voted in the previous epoch for a group that elected one or more validators and have activated their votes are eligible for rewards. Rewards are added directly to the Locked CELO voting for that group, and re-applied as votes for that same group, so future rewards are compounded without the account holder needing to take any action. The voting process is described further [here](/home/protocol/epoch-rewards/index).
Rewards to Locked CELO are totally independent from validator and validator group rewards, and are not subject to the **group share**.

## Adjusting the Reward Rate for Voting Participation
The protocol has a target for the proportion of circulating CELO that is locked and used for voting. An on-target reward rate is determined and then adjusted at every epoch to increase or reduce the attractiveness of locking up additional supply. This aims to balance having sufficient liquidity for CELO, while making it more challenging to buy enough CELO to meaningfully influence the outcome of a validator election.
The reward rate is adjusted as follows:

where $rr$ is the reward rate or voting yield, $vf$ is the voting fraction calculated as locked CELO for voting divided by circulating CELO supply, and $af$ is the adjustment factor. If the voting participation is below the target at the end of an epoch, the on-target reward rate is increased; if the voting participation is above the target at the end of an epoch, the reward is decreased.
## Adjusting the Reward Rate for Target Schedule and Deductions
Adjusting the on-target reward rate to account for under- or over-spending against the target schedule gives a baseline reward, essentially the percentage increase for a unit of Locked CELO voting for a group eligible for rewards.
The reward for activated Locked CELO voting for a given group is determined as follows. First, if the group elected no validators in the current epoch, rewards are zero. Otherwise, the baseline reward rate factors in two deductions. It is multiplied by the slashing penalty for the group, and by the average epoch uptime score for validators in the group elected in the current epoch. Finally, the group's activated pool of Locked CELO is increased by this rate.
# Validator Rewards
Source: https://docs.celo.org/legacy/protocol/pos/epoch-rewards-validator
Overview of epoch rewards for Validators and Validator Groups.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
The protocol aims to incentivize validator uptime performance and penalize past poor behavior in future rewards, while ensuring that payments are economically reasonable in size independent of fluctuations of the price of CELO.
**Five factors affect validator and group rewards:**
* The on-target reward amount for this epoch
* The protocol's [overall spending vs target of epoch rewards](/legacy/protocol/pos/epoch-rewards)
* The validator’s ‘uptime score’
* The current value of the slashing penalty for the group of which it was a member at the last election
* The group share for the group of which it was a member at the last election
Epoch rewards to validators and validator groups are denominated in Celo Dollars, since it is anticipated that most of their expenses will be incurred in fiat currencies, allowing organizations to understand their likely return regardless of volatility in the price of CELO. To enable this, the protocol mints new Celo Dollars that correspond to the epoch reward equivalent of CELO which are maintained on chain to preserve the collateralization ratio. Of course, the effect on the target schedule depends on the prevailing exchange rate.

## On-target Rewards
The on-target validator reward is a constant value (as block rewards typically would be) and is intended to cover costs plus an attractive margin for amortized capital and operating expenses associated with a recommended set up that includes redundant hosts with hardware wallets in a secure co-lo facility, proxy nodes at cloud or edge hosting providers, as well as security audits. As with most parameters of the Celo protocol, it can be changed by governance proposal.
In the usual case where no validator in the group has been slashed recently, and the validator has signed almost every block in the epoch, then the validator receives the full amount of the on-target reward, less the fraction sent to the validator group based on the group share. Unlike in some other proof-of-stake schemes, epoch rewards to validators do not depend on the number of votes the validator’s group has received.
## Calculating Uptime Score
The Celo protocol tracks an ‘uptime score’ for each validator. When a validator proposes a block, it also includes in the block body every signature that it has received from validators committing the previous block.

For a validator to be ‘up’ at a given block, it must have its signature included in at least one in the previous twelve blocks. This cannot be done during the first 11 blocks of the epoch. At each epoch, this counter is reset to 0. Because the proposer order is shuffled at each election, it is very hard for a malicious actor withholding an honest validator’s signatures to affect this measure.
Then, a validator’s uptime for the epoch is the proportion of blocks in the epoch for which it is ‘up’: `u = (counter + downtime_grace_period) / (epoch_size - 11)`. Its epoch uptime score `S_ve = u ^ k`, where `downtime_grace_period` and `k` are a governable constants. This means that even repeated downtimes of less than around a minute are ignored and longer downtimes also won't count against the validator as long as their total duration stays below `downtime_grace_period`. After that the score will reduce rapidly due to the exponent `k`.
The validator’s overall uptime score is an exponential moving average of the uptime score from this and previous epochs. `S_{v} = min(S_ve, S_ve * x + S_{v-1} * (1 -x))` where `0 < x < 1` and is governable. Since `S_v` starts out at zero, validators have a disincentive to change identities and an incentive to prioritize activities that improve long-term availability.
## Calculating Slashing Penalty
The protocol also tracks for each group a ‘slashing penalty’, initially equal to one but successively reduced on each occasion a validator in that group is slashed. The penalty returns to one 30 days after it was last reduced.
This factor is applied to all rewards to validators in that group, to the group itself, and to voters for the group.
The slashing penalty gives groups a further incentive to vet validators they accept as members, not only to avoid reducing their own future rewards from existing validators but to attract and retain the best validators.
Validators have an incentive to be elected through groups with a high value, so a recent slashing makes a group less attractive. Validators also have an incentive to select groups where they believe careful vetting processes are in place, because poor vetting of other validators in the group reduces their own expectation of future rewards.
When a validator is slashed, reduced rewards may lead other validators in the same group to consider equivalently ‘safe’ slots in other groups, if they are available. A validator disassociating from the group would cause the group’s rewards to further decline. While that may cause churn in the set of groups through which validators are elected, it is unlikely that a validator would move to a group where they could not be elected (since in this case they would receive no rewards, as opposed to fewer rewards), hence making the votes by which they were previously elected unproductive.
## Group Share
Validator groups are compensated by taking a share of the rewards allocated to validators. Validator groups set a **group share** rate when they register, and can change that at any time. The protocol automatically deducts this share, sending that portion of the epoch rewards to the validator group of which they were a member at the time of the last election.
Since the sum of a validator’s reward and its validator group’s reward are the same regardless of the ‘group share’ that the group chooses, no side-channel collusion is possible to avoid deductions for downtime or previous slashing.
# Proof of Stake
Source: https://docs.celo.org/legacy/protocol/pos/index
Overview of Celo's proof-of-stake algorithm, mechanisms, and implementation.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## Mastering the Art of Validating
## Validator Types
Celo uses a Byzantine Fault Tolerant [consensus protocol](/legacy/protocol/consensus/index) to agree on new blocks to append to the blockchain. The instances of the Celo software that participate in this consensus protocol are known as **validators**. More accurately, they are **active validators** or **elected validators**, to distinguish them from **registered validators** which are configured to participate but are not actively selected.
## Proof-of-Stake
Celo's proof-of-stake mechanism is the set of processes that determine which nodes become active validators and how incentives are arranged to secure the network.
## Active Validators
The first set of active validators are determined in the genesis block. Thereafter at the end of every epoch, a fixed number of blocks fixed at network creation time, an election is run that may lead to validators being added or removed.

## Validator Elections
In Celo's [Validator Elections](/legacy/protocol/pos/validator-elections), holders of the native asset, CELO, may participate and earn rewards for doing so. Accounts do not make votes for validators directly, but instead vote for [validator groups](/legacy/protocol/pos/validator-groups).
Before they can vote, holders of CELO move balances into the [Locked Gold](/legacy/protocol/pos/locked-gold) smart contract. Locked Gold can be used concurrently for: placing votes in Validator Elections, maintaining a stake to satisfy the requirements of registering as a validator or validator group, and also voting in on-chain [Governance](/home/protocol/governance/overview) proposals. This means that validators and groups can vote and earn rewards with their stake.
**note**
Unlike in other proof-of-stake systems, holding Locked Gold or voting for a group does not put that amount 'at risk' from slashing due to the behavior of validators or validator groups. Only the stake put up by a validator or group may be slashed.
## Implementation
Most of Celo's proof-of-stake mechanism is implemented as smart contracts, and as such can be changed through Celo's on-chain [Governance](/home/protocol/governance/overview) process.
* [`Accounts.sol`](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/common/Accounts.sol) manages key delegation and metadata for all accounts including Validators, Groups and Locked Gold holders.
* [`LockedGold.sol`](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/governance/LockedGold.sol) manages the lifecycle of Locked Gold.
* `Validators.sol` handles registration, deregistration, staking, key management and epoch rewards for validators and validator groups, as well as routines to manage the members of groups.
* [`Election.sol`](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/governance/Election.sol) manages Locked Gold voting and epoch rewards and runs Validator Elections.
In Celo blockchain:
* [`consensus/istanbul/backend/backend.go`](https://github.com/celo-org/celo-blockchain/blob/master/consensus/istanbul/backend/backend.go) performs validator elections in the last block of the epoch and calculates the new [validator set diff](/legacy/protocol/consensus/validator-set-differences).
* [`consensus/istanbul/backend/pos.go`](https://github.com/celo-org/celo-blockchain/blob/master/consensus/istanbul/backend/pos.go) is called in the last block of the epoch to process validator uptime scores and make epoch rewards.
# Locked CELO and Voting
Source: https://docs.celo.org/legacy/protocol/pos/locked-gold
Introduction to Celo locked gold (CELO) and how to use validator elections to participate in voting.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
**Terminology**
This page references "Locked Gold". The native asset of Celo was called Celo Gold (cGLD), but is now called CELO. Many references have been updated, but code and smart contract references may still mention Gold as it is more difficult to reliably and securely update the protocol code.
***
## Validator Election Participation
To participate in validator elections, users must first make a transfer of CELO to the `LockedGold` smart contract.
## Concurrent Use of Locked CELO
Locking up CELO guarantees that the same asset is not used more than once in the same vote. However every unit of Locked CELO can be deployed in several ways at once. Using an amount for voting for a validator does not preclude that same amount also being used to vote for a governance proposal, or as a stake at the same time. Users do not need to choose whether to have to move funds from validator elections in order to vote on a governance proposal.
## Unlocking Period
Celo implements an **unlocking period**, a delay of 3 days after making a request to unlock Locked CELO before it can be recovered from the escrow.
This value balances two concerns. First, it is long enough that an election will have taken place since the request to unlock, so that those units of CELO will no longer have any impact on which validators are managing the network. This deters an attacker from manipulations in the form of borrowing funds to purchase CELO, then using it to elect malicious validators, since they will not be able to return the borrowed funds until after the attack, when presumably it would have been detected and the borrowed funds’ value have fallen.
Second, the unlocking period is short enough that it does not represent a significant liquidity risk for most users. This limits the attractiveness to users of exchanges creating secondary markets in Locked CELO and thereby pooling voting power.
## Locking and Voting Flow

The flow is as follows:
* An account calls `lock`, transferring an amount of CELO from their balance to the `LockedGold` smart contract. This increments the account's 'non-voting' balance by the same amount.
* Then the account calls `vote`, passing in an amount and the address of the group to vote for. This decrements the account's 'non-voting' balance and increments the 'pending' balance associated with that group by the same amount. This counts immediately towards electing validators. Note that the vote may be rejected if it would mean that the account would be voting for more than 3 distinct groups, or that the [voting cap](/legacy/protocol/pos/validator-elections#group-voting-caps) for the group would be exceeded.
* At the end of the current epoch, the protocol will first deliver [epoch rewards](/legacy/protocol/pos/epoch-rewards) to validators, groups and voters based on the current epoch (pending votes do not count for these purposes), and then run an [election](/legacy/protocol/pos/validator-elections) to select the active validator set for the following epoch.
* The pending vote continues to contribute towards electing validators until it is changed, but the account must call `activate` (in a subsequent epoch to the one in which the vote was made) to convert the pending vote to one that earns rewards.
* At the end of that epoch, if the group for which the vote was made had elected one or more validators in the prior election, then the activated vote is eligible for [Locked CELO rewards](/home/protocol/epoch-rewards/index). These are applied to the pool of activated votes for the group. This means that activated voting Locked CELO automatically compounds, with the rewards increasing the account's votes for the same group, thereby increasing future rewards, benefitting participants who have elected to continuously participate in governance.
* The account may subsequently choose to `unvote` a specific amount of voting Locked CELO from a group, up to the total balance that the account has accrued there. Due to rewards, this Locked CELO amount may be higher than the original value passed to `vote`.
* This Locked CELO immediately becomes non-voting, receives no further Epoch Rewards, and can be re-used to vote for a different group.
* The account may choose to `unlock` an amount of Locked CELO at any time, provided that it is inactive: this means it is non-voting in Validator Elections, the `deregistrationPeriod` has elapsed if the amount has been used as a validator or validator group stake, and not active in any [Governance proposals](/home/protocol/governance/overview). Once an unlocking period of 3 days has passed, the account can call `withdraw` to have the `LockedGold` contract transfer them that amount.
Votes persist between epochs, and the same vote is applied to each election unless and until it is changed. Vote withdrawal, vote changes, and additional CELO being used to vote have no effect on the validator set until the election finalizes at the end of the epoch.
## Vote Delegation
[Contract Release 10](https://github.com/celo-org/celo-monorepo/issues/10375) introduced vote delegation, which allows the governance participant to delegate their voting power.
Validators and Validator groups cannot delegate.
The governance participants who cannot actively participate to vote on governance proposals in the Celo ecosystem can now delegate their votes to utilize the dormant votes.
Currently, participants can only delegate to 10 other delegatees.
Participants can follow the steps [here](/home/protocol/governance/voting-in-governance#vote-delegation) to perform delegation using CeloCLI.
# Validator Penalties
Source: https://docs.celo.org/legacy/protocol/pos/penalties
Introduction to validator penalties, enforcement mechanisms, and conditions.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## What is Slashing?
Slashing accomplishes punishment of misbehaving validators by seizing a portion of their stake. Without these punishments, for example, the Celo Protocol would be subject to the nothing at stake problem. Validator misbehavior is classified as a set of slashing conditions below.
## Enforcement Mechanisms
The protocol has three means of recourse for validator misbehavior. Each slashing condition applies a combination of these, as described below.
* **Slashing of validator and group stake -** Some slashing conditions take a fixed amount of the Locked Gold stake put up by a validator. In these cases, the group through which that validator was elected for the epoch in which the slashing condition was proven is also slashed the same fixed amount. A validator or group's stake may be forfeit while it is registered or, after being deregistered, during the notice period (60 days for validators, 180 days for groups) and before the amount is withdrawn from the `LockedGold` contract.
* **Suppression of future rewards -** Every validator group has a **slashing penalty**, initially `1.0`. All rewards to the group and to voters for the group are weighted by this factor. If a validator is slashed, the group through which that validator was elected for the epoch in which it misbehaved has the value of its slashing penalty halved. So long as no further slashing occurs, the slashing penalty is reset to `1.0` after `slashing_penalty_reset_epochs` epochs.
* **Ejection -** When a validator is slashed, it is immediately removed from the group of which it is currently a member (even if this group is not the group that elected the validator at the point the misbehavior was recorded). Since no changes in the active validator set are made during an epoch, this means an elected validator continues participate in consensus until the end of the epoch. The group can choose to re-add the validator at any point, provided the usual conditions are met (including that the validator has sufficient Locked Gold as stake).
## Slashing Conditions
There are three categories of slashing conditions:
* Provable (initiated off-chain, verifiable on-chain)
* Governed (verified only by off-chain knowledge)
### Provable
Provable slashing conditions cannot be initiated automatically on chain but information provided from an external source can be definitively verified on-chain.
In exchange for sending a transaction which initiates a successful provable slashing condition on-chain, the reporter receives a "reward", a portion of the slashed amount (which will always be greater than the gas costs of the proof). The reward is added to the reporter's balance of non-voting LockedGold. The remainder of the slashed amount is sent to the [Community Fund](/home/protocol/epoch-rewards/community-fund).
* **Persistent downtime -** A validator which can be shown to be absent from 8640 consecutive BLS signatures will be slashed 100 CELO, have future rewards suppressed, and (most importantly in this case) will be ejected from its current group.
* **Double Signing -** A validator which can be shown to have produced BLS signatures for 2 distinct blocks at the same height and in the same consensus round but with different hashes will be slashed 9000 CELO, have future rewards suppressed, and will be ejected from its current group. Note that unlike some proof-of-stake networks, Celo does not penalize validators for double signing regular consensus messages. In particular, one side-effect of how Celo provides liveness can result in cases where honest validators may legitimately double sign blocks across different rounds at the same height (Cosmos terms this [amnesia](https://github.com/tendermint/spec/blob/fa3430ad163a2a0ed77aa3f624a70cd9b8b84b78/spec/consensus/signing.md#other-rules) and also specifically excludes it from slashing).
### **Governed**
For misbehavior which is harder to formally classify and requires some off-chain knowledge, slashing can be performed via [governance proposals](/home/protocol/governance/overview). These conditions are important for preventing nuanced validator attacks.
# Validator Elections
Source: https://docs.celo.org/legacy/protocol/pos/validator-elections
Introduction to Celo validator elections and management of groups and votes throughout the process.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## Updating the Active Validator Set
The active validator set is updated by running an election in the final block of each epoch, after processing transactions and [Epoch Rewards](/legacy/protocol/pos/epoch-rewards).
### Group Voting Caps
One way to consider the security of a proof-of-stake system is the marginal cost of getting a malicious validator elected. In a steady state, assuming the Celo community set the incentives appropriately, a full complement of validators is likely to be elected, which means the attack cost is the cost of acquiring sufficient CELO to receive more votes than the currently elected validator with fewest votes, and thereby supplant it.
### Goal of Validator Elections
The objective of Celo’s validator elections differs from real-world elections: they aim to translate voter preferences into representation while promoting decentralization and creating a moat around existing, well-performing elected validators. Two design choices influence this: a limit on the maximum number of member validator that a group can list, and a **voting cap** on the number of votes that any one group can receive.
### Handling Excess Votes
Since voting for a group can cause only the group’s member validators to get elected, and no more, votes in excess of the number needed to achieve that are unproductive in the sense that they do not raise the number of votes needed to get the least-voted-for validator elected. This would translate into a lower cost for a malicious actor to acquire enough CELO to supplant that validator. This is particularly true because the protocol limits the maximum number of members in a group, to promote decentralization.
### Per-Group Vote Cap
The Celo protocol addresses this by enforcing a per-group vote cap. This cap is set to be the number of votes that would be needed to elect all of its validators, plus one more validator. The cap is enforced at the point of voting: a user can only cast a vote for a group if it currently has fewer votes than this cap. An account holder may not set or increase the amount of gold they have voting for a particular validator group `j`, if it already has at least `[(group_members_j + 1) / min(total_group_members, max_validators)]` of the total Locked Gold.
### Adding New Validators
If a group adds a new validator, or the total amount of voting Locked Gold increases, the group’s cap rises and new votes are permitted. If a group removes a validator or a validator chooses to leave, or the total amount of voting Locked Gold falls, then the group’s cap falls: if it has more votes than this new cap, then new votes are no longer permitted, but all existing votes continue to be counted.
The Celo protocol allows an account to divide its vote between up to ten groups, since there may be cases where the vote cap prevents an account allocating its entire vote to its first choice group.
## Running the Election

The `Election` contract is called from the IBFT block finalization code to select the validators for the following epoch. The contract maintains a sorted list of the Locked Gold voting (either pending or activated) for each Validator Group. The [D’Hondt method](https://wikipedia.org/wiki/D'Hondt_method), a closed party list form of proportional representation, is applied to iteratively select validators from the Validator Groups with the greatest associated vote balances.
### Filtering Groups
The list of groups is first filtered to remove those that have not achieved a certain fraction of the votes of the total voting Locked Gold.
### Assigning Seats
Then, in the first iteration, the algorithm assigns the first seat to the group that has at least one member and with the most votes. Thereafter, it assigns the seat to the group that would ‘pay’, if its next validator were elected, the highest vote averaged over its candidates that have been selected so far plus the one under consideration.
### Number of Active Validators
There is a minimum target and a maximum cap on the number of active validators that may be selected. If the minimum target is not reached, the election aborts and no change is made to the validator set this epoch.
# Validator Groups
Source: https://docs.celo.org/legacy/protocol/pos/validator-groups
Celo's proof-of-stake mechanism introduces the concept of **Validator Groups** as intermediaries between voters and validators.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## What is a Validator Group?
A validator group has **members**, an ordered list of candidate validators. There is a fixed limit to the number of members that a group may have.
## Why use a Validator Group?
Validator groups can help mitigate the information disparity between voters and validators. It is anticipated that groups might emerge that do not necessarily operate validators themselves but attract votes for their reputation for ensuring their associated validators have known real-world identities, have high uptime, are well maintained and regularly audited. Since every validator needs to be accepted by a single group to stand for election, that group will be more able to build up long-term judgements on their validators’ operational practices and security setups than each of the numerous CELO holders that might vote for it would.
## Fielding Multiple Validators
Equally, a number of organizations may want to attempt to field multiple validators under their own control, or be able to interchange the specific machines or keys under which they validate in the case of hardware or connectivity failure. By switching out validators in the list, groups can accomplish this without users having to change their votes.
## Validator Group Limits
Validator groups can have no more than a small, fixed maximum number of validators -- currently 5 in Mainnet. This means an organization wanting to get more validators elected than this maximum has the added challenge of managing multiple group identities and reputations simultaneously. This further promotes decentralization and strengthens operational security, making it more likely that the validator set will be composed of nodes operated in different fashions by independent individuals and organizations.
## Registration
Any account that has at least the minimum stake requirement in Locked Gold, whether voting or non-voting, can register an empty validator group. If a validating key is specified it may be used for this registration.
## Deregistration
The account that creates a validator group is able to deregister that group if it has no members.
While an account has a registered validator group, or for up to a `deregistrationPeriod` after it is deregistered, attempts to `unlock` the account's amount of Locked Gold will fail if they would cause the remaining amount to fall below the minimum stake requirement.
## Group Share
Validator groups are compensated by taking a share (the 'Group Share') of the [validator rewards](/legacy/protocol/pos/epoch-rewards-validator) from any of its member validators that are elected during an epoch. This value is set at registration time and can be changed later.
## Changing Group Members
The account owner controls the list of validators in their group and can at any time add, remove, or re-order validators.
For a validator to be added to a group, several conditions must hold: the number of members in the group must be less than the maximum; the Locked Gold balance of the group's account must be sufficient (the stake is per-member validator); and the validator must first have set its affiliation to the group.
This means that while a group can unilaterally remove a validator, and a validator can unilaterally leave by changing its affiliation, both parties have to agree before a validator can become a member of a group.
## Votes and Voting Cap
Validator Groups can receive votes from Locked Gold up to a [voting cap](/legacy/protocol/pos/validator-elections#group-voting-caps). This value is set to be the number of votes that would be needed to elect all of its validators, plus one more validator. The cap is enforced at the point of voting: a user can only cast a vote for a group if it currently has fewer votes than this cap.
## Slashing Penalty
A [slashing penalty](/legacy/protocol/pos/penalties), initially `1.0`, is also tracked for each validator group. This value may be reduced as a penalty for misbehavior of the validator in the group. It affects the future rewards of the group, its validators, and Locked Gold holders receiving rewards for voting for the group.
## Metadata
Both validators and validator groups can use [Accounts Metadata](/legacy/protocol/identity/metadata) to provide unverified metadata (such as name and organizational affiliation) as well as claims that can be verified off-chain for control of third-party accounts. All validators are encouraged to make a verifiable claim for [domain names](/legacy/validator/validator-explorer).
## Dissolving of a Validator Group
There is a 180 day unlocking period for Celo locked when creating a validator group.
# Randomness
Source: https://docs.celo.org/legacy/protocol/randomness
How unpredictable pseudo-randomness is achieved on the Celo blockchain and offered as a service for dapp developers.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## Producing Pseudo-randomness
Producing unpredictable pseudo-randomness without a trusted third party is not trivial. Several solutions for this problem exist or are being currently researched. They include Verifiable Random Functions (for example, based on BLS threshold signatures), Verifiable Delay Functions, and commit-reveal schemes.
Currently, Celo implements a simple [RANDAO](https://eth2book.info/altair/part2/building_blocks/randomness#the-randao) commit-reveal scheme which is secure enough for many uses, offering validators only 1 bit of influence: a validator can affect randomness only by choosing *not to propose* a block, which results in the next validator revealing their pre-commited randomness. A more sophisticated solution might be implemented as the network evolves, especially if randomness becomes necessary for other purposes that require stronger assumptions about the randomness’s security (for example if it was decided that a randomized leader election algorithm should replace the current round robin).
In a proposed block, the proposer attaches two values related to the randomness scheme - randomness corresponding to their previous commitment, and a new commitment to freshly generated random bytes that will be revealed in the future. The revealed randomness is added to an entropy pool accessible on-chain from the Random smart contract.
## Randomness Equation
More formally, the $n * {th} $ block proposed by a given validator contains values $(r_n, s_n)$ such that $\text{keccack256}(r_n) = s*{n-1}$. The one exception to this is the validator’s first block, the case where $n = 1$, since they have not previously committed to randomness yet. Here, the protocol instead requires that $r_1 = 1$.
## Using Onchain Randomness
This randomness can be used by any smart contracts deployed to a Celo network using the Random core contract, e.g.:
```solidity theme={null}
import "celo-monorepo/packages/protocol/identity/interfaces/IRandom.sol";
import "celo-monorepo/packages/protocol/common/interfaces/IRegistry.sol";
contract Example {
function test() external view returns (bytes32 randomness) {
randomness = IRandom(
IRegistry(0x000000000000000000000000000000000000ce10)
.getAddressFor(keccak256(abi.encodePacked("Random")))
).random();
}
}
```
Alternatively, through inheritance of [UsingRegistry](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/common/UsingRegistry.sol).
```solidity theme={null}
import "celo-monorepo/packages/protocol/common/UsingRegistryV2.sol";
contract Example is UsingRegistryV2 {
function test() external view returns (bytes32 randomness) {
randomness = getRandom().random();
}
}
```
# Add Stable Assets
Source: https://docs.celo.org/legacy/protocol/stability/adding-stable-assets
Overview of the requirements and steps to add a new stable asset to the Celo platform.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
**Note**
This example assumes we want to add to the platform a new stable asset `cX` tracking the value of X (where X can be a fiat currency like ARS or MXN), using the [Mento exchange](/legacy/protocol/stability/doto).
## Requirements
**Liquidity**
The asset X has to be liquidly traded against CELO, in a CELO/X ticker. In absence of that, X has to be liquidly traded, including weekends, against well known assets that trade 24/7, like BTC or ETH, such that the price of X with respect to Celo can be inferred. In this second case, an implicit pair can be calculated for the oracle reports.
**Determine pre-mint addresses and amounts**
It is possible to pre-mint a fixed amount at the time of launching a new stable asset, good candidates to receive the pre-mint are the community fund and other entities commited to distribute this initial allocation to grant recipients and liquidity providers.
A good criteria to a successfully decide a pre-mint amount is to check by how much it would affect the reserve collateralization ratio, this is, the ratio of all stable assets, divided by all the reserve holdings. Reserve information, as well as the collateralization ration can be found on the [Reserve website](https://reserve.mento.org/).
## Procedure
### Including contracts on the registry
Currently, the addition of new assets is tied to the [Contract Release Cycle](/contribute-to-celo/release-process/smart-contracts), as the contracts `ExchangeX` and `StableTokenX` need to be checked in \[^1]. These new contracts inherit from Exchange and StableToken, that are the ones originally used for `cUSD`. As StableToken `cX` will be initialized by the contract release, key parameters like `spread` and `reserveFraction` should be included, although they can be later modified by setters in the following governance proposals. The only value that can't be changed is the pre-mint amount.
### Freezing
These contracts should be set as frozen to prevent `cX` from being transferable before Mento supports it in a governance proposal. At this point, as there are no oracles, the contract `ExchangeX` can't update buckets and it is thus impossible to mint and burn `cX`. There is [an issue open](https://github.com/celo-org/celo-monorepo/issues/7331) to include this step as part of the Contract Release.
For the [deployment of cEUR](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0033.md), this was included as part of the [Oracle activation](#oracle-activation) proposal.
### Constitutional parameters
As new contracts are added to the registry, new **constitution parameters** need to be set. There's an [issue open](https://forum.celo.org/t/governance-proposals-for-march-2021/816) to include this in the tooling to support it as part of the Contract Release.
### Oracle activation
A following governance proposal needs to be submitted to enable [oracles](/legacy/protocol/stability/oracles) to report. This oracle proposal needs to enable addresses to report to the `StableTokenX` address and, optionally, fund them to pay for gas fees. An example of this proposal is the [cEUR oracle activation proposal](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0033.md)\[^2].
### Full activation
The last governance proposal is expected to unfreeze the contract and attach the last strings in the process to get a fully transferable asset stabilized by the Reserve. This propose involves:
1. Unfreezing both `StableTokenX` & `ExchangeX`.
2. Making `ExchangeX` able to pull CELO out of the Reserve for the buckets `Reserve.addExchangeSpender`
3. Declaring the token to the Reserve as an asset to be stabilized calling `Reserve.addToken`
4. Enable `StableTokenX` as a fee currency, so that it can be used to pay for gas `FeeCurrencyWhitelist.addToken`.
5. In case necessary, parameters such as `reserveFraction` and `spread` can also be updated in this governance proposal.
6. Granda Mento activation
After passing this last proposal, `cX` should be fully activated.
## Tooling
Adding a new stable asset involves updating many parts of the tooling, such as:
* Update the Ledger app integration such that it displays the names of the newly added token.
* Update oracles and generating their keys and addresses.
* Adding support on `contractkit`.
* Adding support on [kliento](https://github.com/celo-org/kliento).
* Adding support on [eksportisto](https://github.com/celo-org/eksportisto).
* Update on the cli, an example list of things to add are included on [this issue](https://github.com/celo-org/celo-monorepo/issues/6793).
* Supporting on Dapp kit.
\[^1] There are opened issues trying to de-couple the addition of new assets to the reserve to the release cycle.
\[^2] Please note this example proposal also includes freezing, this is because, at the time of writing (22-march-2021), the tooling for proposing a contract release doesn't support freezing those contracts on the same proposal. Proposals shall not be modified manually given that the tool is meant to run verifications.
# Stability Algorithm (Mento)
Source: https://docs.celo.org/legacy/protocol/stability/doto
How the supply of the Celo Dollar is achieved in the Celo protocol using the constant-product decentralized one-to-one mechanism.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
## What is Mento?
On a high level, Mento (previously known as CP-DOTO) allows user demand to determine the supply of celo stable assets by enabling users to create, for example, a new Celo Dollar by sending 1 US Dollar worth of CELO to the reserve, or to burn a Celo Dollar by redeeming it for 1 US Dollar worth of CELO. The mechanism requires an accurate [Oracle](./oracles) value of the CELO to US Dollar market rate to work.
## Incentives
This creates incentives such that when demand for the Celo Dollar rises and the market price is above the peg, users can profit using their own efforts by buying 1 US Dollar worth of CELO on the market, exchanging it with the protocol for one Celo Dollar, and selling that Celo Dollar for the market price.
Similarly, when demand for the Celo Dollar falls and the market price is below the peg, users can profit using their own efforts by purchasing Celo Dollar at the market price, exchanging it with the protocol for 1 US Dollar worth of CELO, and selling the CELO to the market.
## Mitigating Risk
In cases in which the CELO to US Dollar oracle value is not an accurate reflection of the market price, exploiting such discrepancies can lead to a depletion of the reserve. Mento, inspired by the [Uniswap](https://uniswap.io/) system, mitigates this risk of depletion as follows: The Celo protocol maintains two virtual buckets of CELO and Celo Dollar. The amounts in these virtual buckets are recalibrated every time the reported oracle value is updated, provided the difference between the current time and the oracle timestamp is less than $oracle\_staleness\_threshold$.
## Model Equations
The equation for the constant-product-market-maker model fixes the product of the wallet quantities.
$$
G_t \times D_t = k
$$
where $G_t$ and $D_t$denote the quantities in the CELO and Celo Dollar buckets respectively and $k$ is some constant. Given the above rule, it can be shown that the price of CELO, to be paid in Celo Dollar units, is
$P_t = \frac{D_t}{G_t}$
for traded amounts that are small relative to the bucket quantities.
## Oracle Rates
Whenever the CELO to US Dollar oracle rate is updated, the protocol adjusts the bucket quantities such that they equalize the on-chain CELO to Celo Dollar exchange rate $P_t$ to the current oracle rate. During such a reset, the CELO bucket must remain smaller than the total reserve gold balance. To achieve this, the CELO bucket size is defined as the total reserve balance times $gold\_bucket\_size$, with $0 < gold\_bucket\_size < 1$ and the Celo Dollar bucket size is then chosen such that $P_t$ mirrors the oracle price. To discourage excessive on-chain trading, a transaction fee is imposed by adding small spread around the above exchange rate.
If the oracle precisely mirrors the market rate, the on-chain CELO to Celo Dollar rate will equal the CELO to US Dollar market rate and no profit opportunity will exist as long as Celo Dollar precisely tracks the US Dollar. If the oracle price is imprecise, the two rates will differ, and a profit opportunity will be present even if Celo Dollar accurately tracks the US Dollar. However, as traders exploit this opportunity, the on-chain price $P_t$ will dynamically adjust in response to changes in the tank quantities until the opportunity ceases to exist. This limits the depletion potential in Mento in the case of imprecise or manipulated oracle rates.
For a more detailed explanation, read the article [Zooming in on the Celo Expansion & Contraction Mechanism](https://medium.com/celoorg/zooming-in-on-the-celo-expansion-contraction-mechanism-446ca7abe4f "Zooming in on the Celo Expansion & Contraction Mechanism").
## Multi-mento Deployment
Many instances of mento can be deployed in parallel for different stable assets. Currently, `cEUR` and `cUSD` live side-by-side, with independent buckets and oracle reports (although both of them are using the same `SortedOracles` instance). They all fill the CELO bucket with funds from the Reserve, but not necessarily at the same time.
# Granda Mento
Source: https://docs.celo.org/legacy/protocol/stability/granda-mento
Introduction to Granda Mento (CIP 38), its design, and how to manage exchange proposals.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
## What is Granda Mento?
Granda Mento, described in [CIP 38](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0038.md), is a mechanism for exchanging large amounts of CELO for Celo stable tokens that aren't suitable for [Mento](./doto) or over-the-counter (OTC).
Mento has proven effective at maintaining the stability of Celo's stable tokens, but the intentionally limited liquidity of its constant-product market maker results in meaningful slippage when exchanging tens of thousands of tokens at a time. Slippage is the price movement experienced by a trade. Generally speaking, larger volume trades will incur more slippage and execute at a less favorable price for the trader.
Similar to Mento, exchanges through Granda Mento are effectively made against the reserve. Purchased stable tokens are created into existence ("minted"), and sold stable tokens are destroyed ("burned"). Purchased CELO is taken from the reserve, and sold CELO is given to the reserve. For example, a sale of 50,000 CELO in exchange for 100,000 cUSD would involve the 50,000 CELO being transferred to the reserve and the 100,000 cUSD being created and given to the exchanger.
At the time of writing, exchanging about 50,000 cUSD via Mento results in a slippage of about 2%. Without Granda Mento, all launched Celo stable tokens can only be minted and burned using Mento, with the exception of cUSD that is minted as validator rewards each epoch. Granda Mento was created to enable institutional-grade liquidity to mint or burn millions of stable tokens at a time.
The Mainnet Granda Mento contract address is `0x03f6842B82DD2C9276931A17dd23D73C16454a49` ([link](https://celo.blockscout.com/address/0x03f6842B82DD2C9276931A17dd23D73C16454a49)), was introduced in [Contract Release 5](https://github.com/celo-org/governance/blob/main/CGPs/cgp-0037.md), and activated in [CGP 31](https://github.com/celo-org/governance/blob/main/CGPs/cgp-0031.md).
## How it works
A Granda Mento exchange requires rough consensus from the Celo community and, unlike the instant and atomic Mento exchanges, involves the exchanger locking their funds to be sold for multiple days before they are exchanged.
### Design
At a high level, the life of an exchange is:
1. Exchanger creates an "exchange proposal" on-chain that locks their funds to be sold and calculates the amount of the asset being purchased according the current oracle price and a configurable spread.
2. If rough consensus from the community is achieved, a multi-sig (the "approver") that has been set by Governance approves the exchange proposal on-chain.
3. To reduce trust in the approver multi-sig, a veto period takes place where any community member can create a governance proposal to "veto" an approved exchange proposal.
4. After the veto period has elapsed, the exchange is executable by any account. The exchange occurs with the price locked in at stage (1).
### Processes
Processes surrounding Granda Mento exchanges, like how to achieve rough consensus from the community, are outlined in [CIP 46](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0046.md). At the minimum, it takes about 7 days to achieve rough consensus.
The approver multi-sig that is ultimately responsible for approving an exchange proposal that has achieved rough consensus from the community is `0xf10011424A0F35B8411e9abcF120eCF067E4CF27` ([link](https://celo.blockscout.com/address/0xf10011424A0F35B8411e9abcF120eCF067E4CF27/transactions)) and has the following signers:
| **Name** | **Affiliation** | **Discord Handle** | **Address** |
| --------------- | ----------------------------- | ------------------------- | -------------------------------------------- |
| Andrew Shen | Bi23 Labs | `Shen \| Bi23 Labs #6675` | `0xBecc041a5090cD08AbD3940ab338d4CC94d2Ed3c` |
| Pinotio | Pinotio | `Pinotio.com #5357` | `0x802FE32083fD341D8e9A35E3a351291d948a83E6` |
| Serge Kiema | DuniaPay | `serge_duniapay #5152` | `0xdcac99458a3c5957d8ae7b92e4bafc88a32b80e4` |
| Will Kraft | Celo Governance Working Group | `Will Kraft #2508` | `0x169E992b3c4BE08c42582DAb1DCFb2549d9C23E1` |
| Zviad Metreveli | WOTrust | `zm #1073` | `0xE267D978037B89db06C6a5FcF82fAd8297E290ff` |
| human | OpenCelo | `human #6811` | `0x91f2437f5C8e7A3879e14a75a7C5b4CccC76023a` |
| Deepak Nuli | Kresko | `Deepak \| Kresko#3647` | `0x099f3F5527671594351E30B48ca822cc90778a11` |
# Stability Mechanism
Source: https://docs.celo.org/legacy/protocol/stability/index
Find updated information on Celo's Stability Protocol at [mento.org](https://mento.org).
Overview of the Celo protocol's Stability Mechanisms.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
## Stability of Mento Stablecoin Protocol
The Celo protocol's stability mechanism comprises the following:
* [Stability Algorithm (Mento)](/legacy/protocol/stability/doto)
* [Granda Mento](/legacy/protocol/stability/granda-mento)
* [Oracles](/legacy/protocol/stability/oracles)
* [Stability Fees](/legacy/protocol/stability/stability-fees)
* [Adding Stable Tokens](/legacy/protocol/stability/adding-stable-assets)
# Oracles
Source: https://docs.celo.org/legacy/protocol/stability/oracles
How the **SortedOracles** smart contract uses governance to collect reports and maintain the oraclized rate or the Celo dollar.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
## SortedOracles Smart Contract
As mentioned in the previous section, the stability mechanism needs to know the market price of CELO with respect to the US dollar. This value is made available on-chain in the [SortedOracles smart contract](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/stability/SortedOracles.sol).
## Collecting Reports
Through governance, a whitelist of reporters is selected. These addresses are allowed to make reports to the SortedOracles smart contract. The smart contract keeps a list of most recent reports from each reporter. To make it difficult for a dishonest reporter to manipulate the oraclized rate, the official value of the oracle is taken to be the *median* of this list.
## Maintaining Oracle Values
To ensure the oracle's value doesn't go stale due to inactive reporters, any reports that are too old can be removed from the list. "Too old" here is defined based on a protocol parameter that can be modified via governance.
## Celo-Oracle Repository
You can find more information about the technical specification of the Celo Oracles feeding data to the reserve in the [GitHub repository here](https://github.com/celo-org/celo-oracle).
# Stability Fees
Source: https://docs.celo.org/legacy/protocol/stability/stability-fees
Overview of stability fee parameters, timing, frequency, amounts, management, and updates.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
### Parameters Governing the Stability Fee
`inflationPeriod` how long to wait between rounds of applying inflation
`inflationRate` the multiplier by which the inflation factor is adjusted per `inflationPeriod`
### Timing, Frequency, and Amount of Fee
The `inflationRate` is the multiplier by which the `inflationFactor` is increased per `inflationPeriod`. It is initially set to `1` which leaves it to governance to enable the stability fee later on.
Both, the `inflationRate` as well as the `inflationPeriod`, are specified for a given stable token and subject to changes based on governance decisions.
### Stability Fee Levied on Balance
Each account’s stable token balance is stored as ‘units’, and `inflationFactor` describes the units/value ratio. The Celo Dollar value of an account can therefore be computed as follows.
`Account cUSD Value = Account cUSD Units / inflationFactor`
When a transaction occurs, a modifier checks if the stability fee needs updating and, if so, the `inflationFactor` is updated.
### Updates to the Inflation Factor
To apply periodic inflation, the inflation factor must be updated at regular intervals. Every time an event triggering an `inflationFactor` update(eg a transfer) occurs, the `updateInflationFactor` modifier is called (pseudocode below), which does the following:
1. Decide if on or more `inflationPeriod` have passed since the last time `inflationFactor` was updated
2. If so, find out how many have passed
3. Compute the new `inflationFactor` and update the last updated time:
`inflationFactor` = `inflationFactor` \* `inflationRate` ^ `# inflationPeriods since last update`
### Changes to Inflation Factor
Desired inflation rates may vary over time. When a new rate needs to be set, a governance proposal is required to update the inflation rate. If successful, the above function is called, which ensures `inflationFactor` is up to date, then updates the `inflationRate` and `inflationPeriod` parameters.
### Inflation Factor Update Schedule
The `updateInflationFactor` modifier is called by the following functions:
* `setInflationParameters`
* `approve`
* `mint`
* `transferWithComment`
* `burn`
* `transferFrom`
* `transfer`
* `debitFrom`
# Introduction
Source: https://docs.celo.org/legacy/protocol/transaction/erc20-transaction-fees
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
In most L1 and L2 networks, transaction fees can only be paid with one asset, typically, the native asset for the ecosystem which is often volatile in nature. In order to simplify the process of sending funds on Celo, these fees can be paid with allowlisted ERC20 tokens such as USDT, USDC, cUSD, and others, in addition to CELO. This means that a user sending a stablecoin to friends or family will be able to pay the transaction fee out of their stablecoin balance, and will not need to hold a separate CELO balance in order to transact. Critically, Celo supports this functionality natively without Account Abstraction, Pay Masters, or Relay Services. Instead, wallets simply need to add an extra `feeCurrency` field on transaction objects to take advantage of this feature.
## Fee Currency Field
The protocol maintains a governable allowlist of smart contract addresses which can be used to pay for transaction fees. These smart contracts implement an extension of the ERC20 interface, with additional functions that allow the protocol to debit and credit transaction fees. When creating a transaction, users can specify the address of the currency they would like to use to pay for gas via the `feeCurrency` field. Leaving this field empty will result in the native currency, CELO, being used. Note that transactions that specify non-CELO gas currencies will cost approximately 50k additional gas.
## Allowlisted Gas Fee Addresses
To obtain a list of the gas fee addresses that have been allowlisted using [Celo's Governance Process](/home/protocol/governance/overview), you can run the `getCurrencies` method on the `FeeCurrencyDirectory` contract. All other notable Mainnet core smart contracts are listed [here](/contracts/core-contracts#celo-mainnet).
### Tokens with Adapters
After Contract Release 11, addresses in the allowlist are no longer guaranteed to be full ERC20 tokens and can now also be [adapters](https://github.com/celo-org/celo-monorepo/blob/release/core-contracts/11/packages/protocol/contracts-0.8/stability/FeeCurrencyAdapter.sol). Adapters are allowlisted in-lieu of tokens in the scenario that a ERC20 token has decimals other than 18 (e.g. USDT and USDC).
The Celo Blockchain natively works with 18 decimals when calculating gas pricing, so adapters are needed to normalize the decimals for tokens that use a different one. Some stablecoins use 6 decimals as a standard.
Transactions with those ERC20 tokens are performed as usual (using the token address), but when paying gas currency with those ERC20 tokens, the adapter address should be used. This adapter address is also the one that should be used when querying [Gas Price Minimum](/legacy/protocol/transaction/gas-pricing).
Adapters can also be used to query `balanceOf(address)` of an account, but it will return the balance as if the token had 18 decimals and not the native ones. This is useful to calculate if an account has enough balance to cover gas after multiplying `gasPrice * estimatedGas` without having to convert back to the token's native decimals.
#### Adapters by network
##### Mainnet
| Name | Token | Adapter |
| ------ | --------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `USDC` | [`0xcebA9300f2b948710d2653dD7B07f33A8B32118C`](https://celoscan.io/address/0xcebA9300f2b948710d2653dD7B07f33A8B32118C#code) | [`0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B`](https://celoscan.io/address/0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B#code) |
| `USDT` | [`0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e`](https://celoscan.io/address/0x48065fbbe25f71c9282ddf5e1cd6d6a887483d5e#code) | [`0x0e2a3e05bc9a16f5292a6170456a710cb89c6f72`](https://celoscan.io/address/0x0e2a3e05bc9a16f5292a6170456a710cb89c6f72#code) |
##### Alfajores (testnet)
| Name | Token | Adapter |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `USDC` | [`0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B`](https://alfajores.celoscan.io/address/0x2f25deb3848c207fc8e0c34035b3ba7fc157602b#code) | [`0x4822e58de6f5e485eF90df51C41CE01721331dC0`](https://alfajores.celoscan.io/address/0x4822e58de6f5e485eF90df51C41CE01721331dC0#code) |
##### Baklava (testnet)
N/A
### Enabling Transactions with ERC20 Token as fee currency in a wallet
We recommend using the [viem](https://viem.sh/) library as it has support for the `feeCurrency` field in the transaction required for sending transactions where the gas fees will be paid in ERC20 tokens. Ethers.js and web.js currently don't support `feeCurrency`.
#### Estimating gas price
To estimate gas price use the token address (in case of cUSD, cEUR and cREAL) or the adapter address (in case of USDC and USDT) as the value for `feeCurrency` field in the transaction.
The Gas Price Minimum value returned from the RPC has to be interpreted in 18 decimals.
#### Preparing a transaction
When preparing a transaction that uses ERC20 token for gas fees, use the token address (in case of cUSD, cEUR and cREAL) or the adapter address (in case of USDC and USDT) as the value for `feeCurrency` field in the transaction.
The recommended transaction `type` is `123`, which is a CIP-64 compliant transaction read more about it [here](/legacy/protocol/transaction/transaction-types).
Here is how a transaction would look like when using USDC as a medium to pay for gas fees.
```js theme={null}
let tx = {
// ... other transaction fields
feeCurrency: "0x2f25deb3848c207fc8e0c34035b3ba7fc157602b", // USDC Adapter address
type: "0x7b",
};
```
To get details about the underlying token of the adapter you can call `adaptedToken` function on the adapter address, which will return the underlying token address.
# Escrow
Source: https://docs.celo.org/legacy/protocol/transaction/escrow
Introduction to the Celo Escrow contract and how to use it to withdraw, revoke, and reclaim funds.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
## What is the Escrow Contract?
The `Escrow` contract utilizes Celo’s Lightweight identity feature to allow users to *send payments to other users who don’t yet have a public/private key pair or an address*. These payments are stored in this contract itself and can be either withdrawn by the intended recipient or reclaimed by the sender. This functionality supports *both* versions of Celo’s lightweight identity: identifier-based (such as a phone number to address mapping) and privacy-based. This gives applications that intend to use this contract some flexibility in deciding which version of identity they prefer to use.
## How it works
If Alice wants to send a payment to Bob, who doesn’t yet have an associated address, she will send that payment to this `Escrow` contract and will also create a temporary public/private key pair. The associated temporary address will be referred to as the `paymentId`. Alice will then externally share the newly created temporary private key, also known as an *invitation*, to Bob, who will later use it to claim the payment. This paymentId will now be stored in this contract and will be mapped to relevant details related to this specific payment such as: the value of the payment, an optional identifier of the intended recipient, an optional amount of `attestations` the recipient must have before being able to withdraw the payment, an amount of time after which the sender can revoke the payment (via the `expirySeconds` field - more on that in the “withdrawing” section below), which asset is being transferred in this payment, etc.
## Withdrawing
The recipient of an escrowed payment can choose to withdraw their payment assuming they have successfully created their own public/private key pair and now have an address. To prove their identity, the recipient must be able to prove ownership of the paymentId’s private key, which should have been given to them by the original sender. If the sender set a minimum number of attestations required to withdraw the payment, that will also be checked in order to successfully withdraw. Following the same example as above, if Bob wants to withdraw the payment Alice sent him, he must sign a message with the private key given to him by Alice. The message will be the address of Bob’s newly created account. Bob will then be able to withdraw his payment by providing the paymentId and the v, r, and s outputs of the generated ECDSA signature. An escrowed payment may have `expirySeconds` set, which references the amount of time that must pass before the sender can revoke the payment. Note that after `expirySeconds` have passed, the payment recipient may *still withdraw the payment as long as it has not already been revoked*.
## Revoking & Reclaiming
Alice sends Bob an escrowed payment. Let’s say Bob never withdraws it, or worse, the temporary private key he needs to withdraw the payment gets lost or sent to the wrong person. For this purpose, Celo’s protocol also allows for senders to reclaim any unclaimed escrowed payment that they sent. After an escrowed payment's `expirySeconds` (set by the sender on creation of the payment) has passed, the sender of the payment can revoke the payment and reclaim their funds with just the paymentId.
# Gas Pricing
Source: https://docs.celo.org/legacy/protocol/transaction/gas-pricing
Introduction to gas prices, calculations, transactions, and fees on the Celo network.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
## Gas Price Minimum
Celo uses a gas market based on [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559). The protocol establishes a **gas price minimum** that applies to all transactions regardless of which validator processes them.
The gas price minimum will respond to demand, increasing during periods of sustained demand, but allowing temporary spikes in gas demand without price shocks. The Celo protocol aims to have blocks filled at the `target_density`, a certain proportion of the total block gas limit. When blocks are being filled more than the target, the gas price minimum will be raised until demand subsides. If blocks are being filled at less than the target rate, the gas price minimum will decrease until demand rises.
## Calculating Gas Price
In the Celo protocol, the gas price minimum for the next block is calculated based on the current block:
```
gas_price_minimum' = gas_price_minimum * (1 + ((total_gas_used / block_gas_limit) − target_density) * adjustment_speed) + 1
```
Every transaction is required to pay for gas at or above the gas price minimum in order to be processed. Full nodes will reject transactions whose gas price is below the current gas price minimum, and will discard outstanding transactions if the gas price minimum subsequently falls below the gas price that the transactions specify.
## Selecting a Transaction Gas Price
This approach provides a simple mechanism for clients to determine what gas price they should pay. A `GasPriceMinimum` smart contract provides access to the current gas price minimum. For example, with the parameters specified for the Celo testnets, a gas price of 3x the current gas price minimum will be valid in all scenarios for the following 30 seconds.
When the client wants to ensure that their transaction is processed quickly, they may wish to further increase the gas price to encourage validators proposing new blocks to include it in preference to other transactions.
## Transaction Fee Recipients
The required portion of gas fee, known as the **base**, is set as `base = gas_price_minimum * gas_used` and is sent to the Gas Fee Handler smart contract, which is controlled by governance and handles how the fees are used (e.g., for carbon removal and burning). The rest of the gas fee, known as the **tip**, is rewarded to the validator that proposes the block. Block producers only receive the tip and not the base of the gas fee, which means that they do not have an incentive to artificially inflate the gas price minimum by flooding the network with transactions.
# Transactions
Source: https://docs.celo.org/legacy/protocol/transaction/index
Introduction to Celo transactions and gas prices.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
## Celo vs Ethereum Transactions
Transactions in the Celo protocol include payments, contract calls, and other operation which modifies state. They are similar to Ethereum transaction with the following key differences.
* Gas prices must meet or exceed the [gas price minimum](/legacy/protocol/transaction/gas-pricing).
* Gas fees may be paid in currencies other than the native CELO.
# Native Currency
Source: https://docs.celo.org/legacy/protocol/transaction/native-currency
Introduction to CELO and its compliance to the ERC20 standard.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
## What is CELO?
The native currency in the Celo protocol, CELO, conforms to the ERC20 interface. This is made possible by way of a permissioned “Transfer” precompile, which only the CELO ERC20 smart contract can call. The address of the contract exposing this interface can be looked up via the Registry smart contract, and has the “GoldToken” identifier.
**note**
As the native currency of the protocol, CELO, much like Ether, can still be sent directly via transactions by specifying a non-zero “value”, bypassing the ERC20 interface.
# Transaction types on Celo
Source: https://docs.celo.org/legacy/protocol/transaction/transaction-types
This page contains an explainer on transaction types supported on Celo and a demo to make specific transactions.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
> **IMPORTANT**
> This repo is for educational purposes only. The information provided here may be inaccurate.
> Please don’t rely on it exclusively to implement low-level client libraries.
## Summary
Celo has support for all Ethereum transaction types (i.e. "100% Ethereum compatibility")
and a single Celo transaction type.
### Actively supported on Celo
| Chain | Transaction type | # | Specification | Recommended | Support | Comment |
| --------------- | -------------------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | --------- | -------------------------------------------------------- |
| | Dynamic fee transaction v2 | `123` | [CIP-64](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0064.md) | ✅ | Active 🟢 | Supports paying gas in custom fee currencies |
| | Dynamic fee transaction | `2` | [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) ([CIP-42](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0042.md)) | ✅ | Active 🟢 | Typical Ethereum transaction |
| | Access list transaction | `1` | [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930) ([CIP-35](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0035.md)) | ❌ | Active 🟢 | Does not support dynamically changing *base fee* per gas |
| | Legacy transaction | `0` | [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf) ([CIP-35](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0035.md)) | ❌ | Active 🟢 | Does not support dynamically changing *base fee* per gas |
### Scheduled for deprecation on Celo
| Chain | Transaction type | # | Specification | Recommended | Support | Comment |
| --------------- | ----------------------- | ----- | -------------------------------------------------------------------------------------------------------------- | ----------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| | Dynamic fee transaction | `124` | [CIP-42](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0042.md) | ❌ | Security 🟠 | Deprecation warning published in [Gingerbread hard fork](https://github.com/celo-org/celo-proposals/blob/8260b49b2ec9a87ded6727fec7d9104586eb0752/CIPs/cip-0062.md#deprecation-warning) |
| | Legacy transaction | `0` | Celo Mainnet launch ([Blockchain client v1.0.0](https://github.com/celo-org/celo-blockchain/tree/celo-v1.0.0)) | ❌ | Security 🟠 | Deprecation warning published in [Gingerbread hard fork](https://github.com/celo-org/celo-proposals/blob/8260b49b2ec9a87ded6727fec7d9104586eb0752/CIPs/cip-0062.md#deprecation-warning) |
The stages of support are:
* **Active support** 🟢: the transaction type is supported and recommended for use.
* **Security support** 🟠: the transaction type is supported but not recommended for use
because it might be deprecated in the future.
* **Deprecated** 🔴: the transaction type is not supported and not recommended for use.
### Client library support
Legend:
* =
support for the recommended Ethereum transaction type (`2`)
* = support
for the recommended Celo transaction type (`123`)
* ✅ = available
* ❌ = not available
| Client library | Language | | since | | since | Comment |
| --------------------- | :------: | :-------------: | :---: | :-------------- | --------------------------------------------------------------------------- | ------------------------------------------------ |
| `viem` | TS/JS | ✅ | | ✅ | >[1.19.5][1] | --- |
| `ethers` | TS/JS | ✅ | | ❌ | | Support via fork in `celo-ethers-wrapper` |
| `celo-ethers-wrapper` | TS/JS | ✅ | | ✅ | >[2.0.0](https://github.com/jmrossy/celo-ethers-wrapper/releases/tag/2.0.0) | --- |
| `web3js` | TS/JS | ✅ | | ❌ | | Support via fork in `contractkit` |
| `contractkit` | TS/JS | ✅ | | ✅ | >[5.0.0](https://github.com/celo-org/celo-monorepo/releases/tag/v5.0) | --- |
| `Web3j` | Java | ✅ | | ❌ | | --- |
| `rust-ethers` | Rust | ✅ | | ❌ | | --- |
| `brownie` | Python | ✅ | | ❌ | | --- |
[1]: https://github.com/wevm/viem/blob/main/src/CHANGELOG.md#1195
## Background
### Legacy transactions
Ethereum originally had one format for transactions (now called "legacy transactions").
A legacy transaction contains the following transaction parameters:
`nonce`, `gasPrice`, `gasLimit`, `recipient`, `amount`, `data`, and `chaindId`.
To produce a valid "legacy transaction":
1. the **transaction parameters** are [RLP-encoded](https://eth.wiki/fundamentals/rlp):
```
RLP([nonce, gasprice, gaslimit, recipient, amount, data, chaindId, 0, 0])
```
2. the RLP-encoded transaction is hashed (using Keccak256).
3. the hash is signed with a private key using the ECDSA algorithm, which generates the `v`, `r`,
and `s` **signature parameters**.
4. the transaction *and* signature parameters above are RLP-encoded to produce a valid **signed
transaction**:
```
RLP([nonce, gasprice, gaslimit, recipient, amount, data, v, r, s])
```
A valid signed transaction can then be submitted on-chain, and its raw parameters can be
parsed by RLP-decoding the transaction.
### Typed transactions
Over time, the Ethereum community has sought to add new types of transactions
such as dynamic fee transactions
([EIP-1559: Fee market change for ETH 1.0 chain](https://eips.ethereum.org/EIPS/eip-1559))
or optional access list transactions
([EIP-2930: Optional access lists](https://eips.ethereum.org/EIPS/eip-2930))
to supported new desired behaviors on the network.
To allow new transactions to be supported without breaking support with the
legacy transaction format, the concept of **typed transactions** was proposed in
[EIP-2718: Typed Transaction Envelope](https://eips.ethereum.org/EIPS/eip-2718), which introduces
a new high-level transaction format that is used to implement all future transaction types.
### Distinguishing between legacy and typed transactions
Whereas a valid "legacy transaction" is simply an RLP-encoded list of
**transaction parameters**, a valid "typed transactions" is an arbitrary byte array
prepended with a **transaction type**, where:
* a **transaction type**, is a number between 0 (`0x00`) and 127 (`0x7f`) representing
the type of the transaction, and
* a **transaction payload**, is arbitrary byte data that encodes raw transaction parameters
in compliance with the specified transaction type.
To distinguish between legacy transactions and typed transactions at the client level,
the EIP designers observed that the **first byte** of a legacy transaction would never be in the range
`[0, 0x7f]` (or `[0, 127]`), and instead always be in the range `[0xc0, 0xfe]` (or `[192, 254]`).
With that observation, transactions can be decoded with the following heuristic:
* read the first byte of a transaction
* if it's bigger than `0x7f` (`127`), then it's a **legacy transaction**. To decode it, you
must read *all* bytes (including the first byte just read) and interpret them as a
legacy transaction.
* else, if it's smaller or equal to `0x7f` (`127`), then it's a **typed transaction**. To decode
it you must read the *remaining* bytes (excluding the first byte just read) and interpret them
according to the specified transaction type.
Every transaction type is defined in an EIP, which specifies how to *encode* as well as *decode*
transaction payloads. This means that a typed transaction can only be interpreted with knowledge of
its transaction type and a relevant decoder.
## List of transaction types on Celo
### Legacy transaction (`0`)
> **NOTE**
> This transaction type is 100% compatible with Ethereum and has no Celo-specific parameters.
Although legacy transactions are never formally prepended with the `0x00` transaction type,
they are commonly referred to as "type 0" transactions.
* This transaction is defined as follows:
```
RLP([nonce, gasprice, gaslimit, recipient, amount, data, v, r, s])
```
* It was introduced on Ethereum during Mainnet launch on [Jul 30, 2015](https://en.wikipedia.org/wiki/Ethereum)
as specified in the [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf).
* It was introduced on Celo during the
[Celo Donut hard fork](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0027.md)
on [May 19, 2021](https://blog.celo.org/donut-hardfork-is-live-on-celo-585e2e294dcb)
as specified in [CIP-35: Support for Ethereum-compatible transactions](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0035.md).
### Access list transaction (`1`)
> **NOTE**
> This transaction type is 100% compatible with Ethereum and has no Celo-specific parameters.
* This transaction is defined as follows:
```
0x01 || RLP([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, signatureYParity, signatureR, signatureS])
```
* It was introduced on Ethereum during the Ethereum Berlin hard fork on
[Apr, 15 2021](https://ethereum.org/en/history/#berlin) as specified in
[EIP-2930: Optional access lists](https://eips.ethereum.org/EIPS/eip-2930).
* It was introduced on Celo during the
[Celo Donut hard fork](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0027.md)
on [May 19, 2021](https://blog.celo.org/donut-hardfork-is-live-on-celo-585e2e294dcb)
as specified in [CIP-35: Support for Ethereum-compatible transactions](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0035.md).
### Dynamic fee transaction (`2`)
> **NOTE**
> This transaction type is 100% compatible with Ethereum and has no Celo-specific parameters.
* This transaction is defined as follows:
```
0x02 || RLP([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, data, accessList, signatureYParity, signatureR, signatureS])
```
* It was introduced on Ethereum during the Ethereum London hard fork on
[Aug, 5 2021](https://ethereum.org/en/history/#london) as specified in
[EIP-1559: Fee market change for ETH 1.0 chain](https://eips.ethereum.org/EIPS/eip-1559).
* It was introduced on Celo during the
[Celo Espresso hard fork](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0041.md)
on [Mar 8, 2022](https://blog.celo.org/brewing-the-espresso-hardfork-92a696af1a17) as specified
in [CIP-42: Modification to EIP-1559](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0042.md)
### Legacy transaction (`0`)
> **NOTE**
> This transaction is not compatible with Ethereum and has three Celo-specific
> parameters: `feecurrency`, `gatewayfeerecipient`, and `gatewayfee`.
> **Warning**
> This transaction type is scheduled for deprecation. A deprecation warning was published in the
> [Gingerbread hard fork](https://github.com/celo-org/celo-proposals/blob/8260b49b2ec9a87ded6727fec7d9104586eb0752/CIPs/cip-0062.md#deprecation-warning)
> on [Sep 26, 2023](https://forum.celo.org/t/mainnet-alfajores-gingerbread-hard-fork-release-sep-26-17-00-utc/6499).
* This transaction is defined as follows:
```
RLP([nonce, gasprice, gaslimit, feecurrency, gatewayfeerecipient, gatewayfee, recipient, amount, data, v, r, s])
```
* It was introduced on Celo during Mainnet launch on
[Apr 22, 2020](https://dune.com/queries/3106924/5185945) as specified in
[Blockchain client v1.0.0](https://github.com/celo-org/celo-blockchain/tree/celo-v1.0.0).
### Dynamic fee transaction (`124`)
> **NOTE**
> This transaction is not compatible with Ethereum and has three Celo-specific
> parameters: `feecurrency`, `gatewayfeerecipient`, and `gatewayfee`.
> **Warning**
> This transaction type is scheduled for deprecation. A deprecation warning was published in the
> [Gingerbread hard fork](https://github.com/celo-org/celo-proposals/blob/8260b49b2ec9a87ded6727fec7d9104586eb0752/CIPs/cip-0062.md#deprecation-warning)
> on [Sep 26, 2023](https://forum.celo.org/t/mainnet-alfajores-gingerbread-hard-fork-release-sep-26-17-00-utc/6499).
* This transaction is defined as follows:
```
0x7c || RLP([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, feecurrency, gatewayfeerecipient, gatewayfee, destination, amount, data, access_list, v, r, s])
```
* It was introduced on Celo during the
[Celo Espresso hard fork](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0041.md)
on [Mar 8, 2022](https://blog.celo.org/brewing-the-espresso-hardfork-92a696af1a17) as specified
in [CIP-42: Modification to EIP-1559](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0042.md).
### Dynamic fee transaction v2 (`123`)
> **NOTE**
> This transaction is not compatible with Ethereum and has one Celo-specific
> parameter: `feecurrency`.
* This transaction is defined as follows:
```
0x7b || RLP([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, data, accessList, feeCurrency, v, r, s])
```
* It was introduced on Celo during the
[Celo Gingerbread hard fork](https://github.com/celo-org/celo-proposals/blob/8260b49b2ec9a87ded6727fec7d9104586eb0752/CIPs/cip-0062.md)
on [Sep 26, 2023](https://forum.celo.org/t/mainnet-alfajores-gingerbread-hard-fork-release-sep-26-17-00-utc/6499)
as specified in
[CIP-64: New Transaction Type: Celo Dynamic Fee v2](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0064.md)
## How to Send Transactions
### Import Dependencies
```ts theme={null}
import {
createPublicClient,
createWalletClient,
hexToBigInt,
http,
parseEther,
parseGwei,
} from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { celoAlfajores } from "viem/chains";
import "dotenv/config"; // use to read private key from environment variable
```
### Create Public and Wallet Client
```ts theme={null}
const PRIVATE_KEY = process.env.PRIVATE_KEY;
/**
* Boilerplate to create a viem client
*/
const account = privateKeyToAccount(`0x${PRIVATE_KEY}`);
const publicClient = createPublicClient({
chain: celoAlfajores,
transport: http(),
});
const walletClient = createWalletClient({
chain: celoAlfajores, // Celo testnet
transport: http(),
});
```
### Function to print Transaction receipt
```ts theme={null}
function printFormattedTransactionReceipt(transactionReceipt: any) {
const {
blockHash,
blockNumber,
contractAddress,
cumulativeGasUsed,
effectiveGasPrice,
from,
gasUsed,
logs,
logsBloom,
status,
to,
transactionHash,
transactionIndex,
type,
feeCurrency,
gatewayFee,
gatewayFeeRecipient
} = transactionReceipt;
const filteredTransactionReceipt = {
type,
status,
transactionHash,
from,
to
};
console.log(`Transaction details:`, filteredTransactionReceipt, `\n`);
}
```
### Code to send Transaction Type (0)
```ts theme={null}
/**
- Transation type: 0 (0x00)
- Name: "Legacy"
- Description: Ethereum legacy transaction
*/
async function demoLegacyTransactionType() {
console.log(`Initiating legacy transaction...`);
const transactionHash = await walletClient.sendTransaction({
account, // Sender
to: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", // Recipient (illustrative address)
value: parseEther("0.01"), // 0.01 CELO
gasPrice: parseGwei("20"), // Special field for legacy transaction type
});
const transactionReceipt = await publicClient.waitForTransactionReceipt({
hash: await transactionHash,
});
printFormattedTransactionReceipt(transactionReceipt);
}
```
### Code to send Transaction Type (2)
```ts theme={null}
/**
* Transaction type: 2 (0x02)
* Name: "Dynamic fee"
* Description: Ethereum EIP-1559 transaction
*/
async function demoDynamicFeeTransactionType() {
console.log(`Initiating dynamic fee (EIP-1559) transaction...`);
const transactionHash = await walletClient.sendTransaction({
account, // Sender
to: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", // Recipient (illustrative address)
value: parseEther("0.01"), // 0.01 CELO
maxFeePerGas: parseGwei("10"), // Special field for dynamic fee transaction type (EIP-1559)
maxPriorityFeePerGas: parseGwei("10"), // Special field for dynamic fee transaction type (EIP-1559)
});
const transactionReceipt = await publicClient.waitForTransactionReceipt({
hash: await transactionHash,
});
printFormattedTransactionReceipt(transactionReceipt);
}
```
### Code to send Transaction Type (123)
```ts theme={null}
/**
* Transaction type: 123 (0x7b)
* Name: "Dynamic fee"
* Description: Celo dynamic fee transaction (with custom fee currency)
*/
async function demoFeeCurrencyTransactionType() {
console.log(`Initiating custom fee currency transaction...`);
const transactionHash = await walletClient.sendTransaction({
account, // Sender
to: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", // Recipient (illustrative address)
value: parseEther("0.01"), // 0.01 CELO
feeCurrency: "0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1", // cUSD fee currency
maxFeePerGas: parseGwei("10"), // Special field for dynamic fee transaction type (EIP-1559)
maxPriorityFeePerGas: parseGwei("10"), // Special field for dynamic fee transaction type (EIP-1559)
});
const transactionReceipt = await publicClient.waitForTransactionReceipt({
hash: await transactionHash,
});
printFormattedTransactionReceipt(transactionReceipt);
}
```
# Encrypted Payment Comments
Source: https://docs.celo.org/legacy/protocol/transaction/tx-comment-encryption
Overview of encrypted payment comments and its technical details related to symmetric and asymmetric encryption.
As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo is no longer a standalone Layer 1 blockchain—it is now an Ethereum Layer 2!
Some documentation may be outdated as updates are in progress. If you encounter issues, please [file a bug report](https://github.com/celo-org/docs/issues/new/choose).
For the most up-to-date information, refer to our [Celo L2 documentation](/build#celo-l2-mainnet).
***
### Introduction to Comment Encryption
As part of Celo’s identity protocol, a public encryption key is stored along with a user’s address in the `Accounts` contract.
Both the address key pair and the encryption key pair are derived from the backup phrase. When sending a transaction the encryption key of the recipient is retrieved when getting his or her address. The comment is then encrypted using a 128 bit hybrid encryption scheme (ECDH on secp256k1 with AES-128-CTR). This system ensures that comments can only be read by the sending and receiving parties and that messages will be recovered when restoring a wallet from its backup phrase.
### Comment Encryption Technical Details
A 128 bit randomly generated session key, sk, is generated and used to symmetrically encrypt the comment. sk is asymmetrically encrypted to the sender and to the recipient.
`Encrypted = ECIES(sk, to=pubSelf) | ECIES(sk, to=pubOther) | AES(ke=sk, km=sk, comment)`
#### Symmetric Encryption (AES-128-CTR)
* Takes encryption key, ke, and MAC key, km, and the data to encrypt, plaintext
* Cipher: AES-128-CTR using a randomly generated iv
* Authenticate iv | ciphertext using HMAC with SHA-256 and km
* Return iv | ciphertext | mac
#### Asymmetric Encryption (ECIES)
1. Takes data to encrypt, plaintext, and the public key of the recipient, pubKeyTo
2. Generate an ephemeral keypair, ephemPubKey and ephemPrivKey
3. Derive 32 bytes of key material, k, from ECDH between ephemPrivKey and pubKeyTousing ConcatKDF (specified as NIST 800-56C Rev 1 One Step KDF) with SHA-256 for H(x)
4. The encryption key, ke, is the first 128 bits of k
5. The MAC key, km, is SHA-256 of the second 128 bits of k
6. Encrypt the plaintext symmetrically with AES-128-CTR using ke, km, and a random iv
7. Return ephemPubKey | AES-128-CTR-HMAC(ke, km, plaintext) where the public key needs to be uncompressed (current limitation with decrypt).
# Bridging CELO from L1 to L2
Source: https://docs.celo.org/legacy/transition/guides/bridging-celo-from-l1-to-l2
In this guide, you'll learn how to programmatically bridge CELO from Sepolia to Celo Sepolia using the [viem OP Stack](https://viem.sh/op-stack).
## Steps to Bridge CELO
Before transferring tokens, you must authorize the `OptimismPortalProxy` contract to spend CELO on your behalf. Without this approval, the bridging transaction cannot proceed.
Call the [`depositERC20Transaction`](https://viem.sh/op-stack/actions/depositTransaction#deposittransaction) function on the `OptimismPortalProxy` contract on Sepolia. This function moves CELO tokens from your account to the Celo Sepolia.
## Code Example
The following example demonstrates how to configure a file with all the details you need for interacting with the Celo Sepolia.
```js index.js theme={null}
import { createWalletClient, createPublicClient, http, parseEther } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { celoSepolia, sepolia } from "viem/chains";
import { getL2TransactionHashes, publicActionsL2 } from "viem/op-stack";
const CELOL1 = "0xDEd08f6Ec0A57cE6Be62d1876d2CE92AF37eddA0";
// https://docs.celo.org/cel2/contract-addresses
const OptimismPortalProxy = "0xB29597c6866c6C2870348f1035335B75eEf79d07";
const account = privateKeyToAccount(
"...",
);
export const walletClientL1 = createWalletClient({
account,
chain: sepolia,
transport: http(),
});
export const publicClientL1 = createPublicClient({
account,
chain: sepolia,
transport: http(),
});
export const publicClientL2 = createPublicClient({
chain: celoSepolia,
transport: http(),
}).extend(publicActionsL2());
async function main() {
// Approve OptimismPortal to pull CELO on Sepolia
const approve = await walletClientL1.writeContract({
address: CELOL1,
abi: [
{
inputs: [
{ name: "spender", type: "address" },
{ name: "amount", type: "uint256" },
],
name: "approve",
type: "function",
},
],
functionName: "approve",
args: [OptimismPortalProxy, parseEther("0.0001")],
});
console.log(`Approval TX Hash: ${approve}`);
let approveReceipt = await publicClientL1.waitForTransactionReceipt({
hash: approve,
});
console.log(`Approve Transaction Receipt: ${approveReceipt}`);
// Call depositERC20Transaction on OptimismPortal
const deposit = await walletClientL1.writeContract({
address: OptimismPortalProxy,
abi: [
{
inputs: [
{
name: "_to",
type: "address",
},
{
name: "mint",
type: "uint256",
},
{
name: "_value",
type: "uint256",
},
{
name: "_gasLimit",
type: "uint64",
},
{
name: "_isCreation",
type: "bool",
},
{
name: "_data",
type: "bytes",
},
],
name: "depositERC20Transaction",
type: "function",
},
],
functionName: "depositERC20Transaction",
args: [
account.address, // Account where you want to receive CELO on L2
parseEther("0.0001"), // Amount you are transferring to the Portal
parseEther("0.0001"), // Amount you want on L2
100_000, // Amount of L2 gas to purchase by burning gas on L1.
false, // Whether the transaction is a contract creation
"", // Data to trigger the recipient with
],
});
console.log(`Deposit Transaction: ${deposit}`);
let depositReceipt = await publicClientL1.waitForTransactionReceipt({
hash: deposit,
});
console.log(`Deposit Transaction Receipt: ${depositReceipt}`);
// Get the L2 transaction hash from the L1 transaction receipt.
const [l2Hash] = getL2TransactionHashes(depositReceipt);
// Wait for the L2 transaction to be processed.
const l2Receipt = await publicClientL2.waitForTransactionReceipt({
hash: l2Hash,
});
console.log(`L2Receipt: ${l2Receipt}`);
}
main();
```
# Withdrawing CELO from L2 to L1
Source: https://docs.celo.org/legacy/transition/guides/withdrawing-celo-from-l2-to-l1
In this tutorial, you will learn how to programmatically withdraw CELO from Celo Sepolia to Sepolia using the [viem OP Stack](https://viem.sh/op-stack).
## Steps to Withdraw CELO
Withdrawals require the user to submit three transactions:
1. [Withdrawal initiating a transaction](https://viem.sh/op-stack/actions/initiateWithdrawal), which the user submits on L2.
2. [Withdrawal proving transaction](https://viem.sh/op-stack/actions/proveWithdrawal), which the user submits on L1 to prove that the withdrawal is legitimate.
3. [Withdrawal finalizing transaction](https://viem.sh/op-stack/actions/finalizeWithdrawal), which the user submits on L1 after the fault challenge period has passed, to actually run the transaction on L1.
## Code Example
The following example demonstrates how to configure a file with all the details you need for interacting with the Celo Sepolia.
```js index.js theme={null}
import {
createPublicClient,
createWalletClient,
http,
parseEther,
} from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { celoSepolia, sepolia } from "viem/chains";
import {
publicActionsL1,
walletActionsL2,
walletActionsL1,
publicActionsL2,
} from "viem/op-stack";
const account = privateKeyToAccount(
"[PRIVATE_KEY]",
);
const value = parseEther("0.0001"); // Amount to Withdraw
export const publicClientL1 = createPublicClient({
chain: sepolia,
transport: http(),
}).extend(publicActionsL1());
export const publicClientL2 = createPublicClient({
chain: celoSepolia,
transport: http(),
}).extend(publicActionsL2());
export const walletClientL1 = createWalletClient({
chain: sepolia,
transport: http(),
account,
}).extend(walletActionsL1());
export const walletClientL2 = createWalletClient({
chain: celoSepolia,
transport: http(),
account,
}).extend(walletActionsL2());
export default async function main() {
console.log("Building Initiate Withdrawal...");
const args = await publicClientL1.buildInitiateWithdrawal({
account,
to: account.address, // Receive on the same address on L1.
value,
});
console.log("Initiaiting Withdrawal...");
const hash = await walletClientL2.initiateWithdrawal(args);
const initiateWithdrawalReceipt = await publicClientL2.waitForTransactionReceipt({
hash
});
console.log(`Withdrawal Initiated: ${initiateWithdrawalReceipt}`);
/**
* The below step can take upto 2 hours!
*
* Hence, you may want to use viem's `getTimeToProve`.
*
* https://viem.sh/op-stack/actions/getTimeToProve
*
* Store the wait time in a database
* and let the user know to come back later.
*
* */
console.log("Waiting to prove...");
const { output, withdrawal } = await publicClientL1.waitToProve({
receipt: initiateWithdrawalReceipt,
targetChain: walletClientL2.chain,
});
console.log("Building Prove Withdrawal...");
const proveArgs = await publicClientL2.buildProveWithdrawal({
output,
withdrawal,
});
console.log("Proving Withdrawal...");
const proveHash = await walletClientL1.proveWithdrawal(proveArgs);
const proveReceipt = await publicClientL1.waitForTransactionReceipt({
hash: proveHash,
});
console.log(`Withdrawal Proved: ${proveReceipt}`);
/**
* The below step can take a few minutes, ideally 2 minutes.
*
* Hence, you may want to use viem's `getTimeToFinalize`.
*
* https://viem.sh/op-stack/actions/getTimeToFinalize
*
* Store the wait time in a database
* and let the user know to come back later.
*
*
*/
console.log("Waiting To Finalize...");
await publicClientL1.waitToFinalize({
targetChain: walletClientL2.chain,
withdrawalHash: withdrawal.withdrawalHash,
});
console.log("Finalizing Withdrawal...");
const finalizeWithdrawalHash = await walletClientL1.finalizeWithdrawal({
targetChain: walletClientL2.chain,
withdrawal,
});
const finalizeWithdrawalReceipt = await publicClientL1.waitForTransactionReceipt({
hash: finalizeWithdrawalHash,
});
console.log(`Withdrawal Finalized: ${finalizeWithdrawalReceipt}`)
}
```
# Optimism → Celo L2
Source: https://docs.celo.org/legacy/transition/optimism/op-l2
## Blocks
Celo L2 block times are 1s as opposed to 2s for Optimism. The gas limit per block remains the same.
## Native token
The native token is CELO as opposed to ETH. The native token is also an ERC20 token.
## New transaction type
Type 123 (`0x7b`) transaction type allows paying for gas in currencies other than the native asset (CELO). It has an additional field `feeCurrency` which allows the sender to choose the gas currency. See [here](/specs/fee-abstraction) for details on using fee currencies.
The fee currencies available at Mainnet launch will be:
* USDC (USDC)
* Tether USD (USD₮)
* PUSO (PUSO)
* ECO CFA (eXOF)
* Celo Kenyan Shilling (cKES)
* Celo Dollar (cUSD)
* Celo Euro (cEUR)
* Celo Brazilian Real (cREAL)
More details on supported transaction types [here](/specs/transaction-types).
## L1 fees
In the Optimism model, an extra fee is added in order to cover the cost of transactions on the L1. This can be surprising to users as it is not included in the results of calling `eth_estimateGas` and is challenging to predict.
The Celo L2 improves upon this experience by always keeping the L1 fee at zero. The L1 costs are covered by raising or lowering the [base fee floor](#eip-1559-implementation). This approach allows the full transaction cost to be estimated ahead of time.
## EIP-1559 implementation
The Celo L2 adds a base fee floor, which imposes a lower limit on the base fee. This is currently configured via the chain config. The **starting base fee floor** values are currently **25 gwei** for Celo Sepolia Testnet.
## MaxCodeSize
The hardcoded protocol parameter `MaxCodeSize` is raised from 24576 to 65536.
## Improved finality guarantees
Celo L2 blocks reference L1 blocks that are finalized, which fully protects against L1 re-orgs. In contrast, Optimism blocks reference only 4 blocks behind the L1 head.
# Celo L1 → L2
Source: https://docs.celo.org/legacy/transition/whats-changed/l1-l2
## Node operators
In the Celo L1 node, operators simply needed to run the celo-blockchain client, a single service that was a fork of go-ethereum. Moving to the Celo L2 node operators need to run an op-geth instance for execution, an op-node instance for consensus and an eigenda-proxy for data availability. Instructions on operating nodes are [here](/infra-partners/operators/overview).
## Deprecated transaction types
Sending these transaction types is no longer be supported, however you can still retrieve any historical instances of these transactions.
* **Type 0 (`0x0`) *Celo* legacy transaction**. These are type 0 transactions that had some combination of the following fields set ("feeCurrency", "gatewayFee", "gatewayFeeRecipient") and "ethCompatible" set to false.
* **Type 124 (`0x7c`) Celo dynamic fee transaction**.
More details on supported transaction types [here](/specs/transaction-types).
## Native bridge to Ethereum
An important benefit of becoming an L2 is having a native bridge to Ethereum.
CELO is now an ERC20 token native on Ethereum and users will be able to use the native bridge to move between the Celo L2 and Ethereum.
The Celo Mainnet bridge can be accessed at [Superbridge](https://superbridge.app/celo).
## Consensus
The BFT consensus protocol has been removed and replaced with a centralized sequencer. Although validators are no longer needed to secure consensus, the election / voting mechanism and validator set will remain for the time being.
This is a temporary situation, and we will be working on re-introducing active roles for validators after Mainnet launch. For now, validators will serve as community rpc providers and do not need to run any special L2 infrastructure beyond full nodes.
## Validator fees and staking rewards
After the L2 transition, transaction fees will go to the sequencer but validators and stakers will still receive some rewards. Previously, rewards were emitted on epoch blocks but as Celo L2 does not have epoch blocks, rewards will be distributed through periodic calls to a smart contract.
The amount of rewards to be distributed has not been decided. However, rewards will likely be lower than in the Celo L1 to reflect lower infrasture requirements.
## Hardforks
See [here](/specs/l2-migration#changes-for-contracts-developers) for the list of hardforks that will be enabled in the first block of the L2.
## Precompiled contracts
All Celo specific precompiles have been removed except for the transfer precompile which supports Celo [token duality](/specs/token-duality) (the native asset CELO is also an ERC20 token)
## Randomness
The random contract has been removed. If randomness is needed then the PREVRANDAO opcode can be used. See [here](/specs/l2-migration#deactivated-random-contract) for more details.
## Blocks
* Block interval has changed from 5s to 1s
* Block gas limit has changed from 50m to 30m
Note this results in a 300% increase in gas per second due to the shortened block time
### Added fields
* **withdrawals** & **withdrawalsRoot** - These fields are inherited from Ethereum but not used by the op-stack or Celo. Withdrawals will always be an empty list and `withdrawalsRoot` will always be the empty withdrawals root (`0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421`).
* **blobGasUsed** & **excessBlobGas** - These fields are also inherited from Ethereum but not used by the op-stack or Celo. They will always be zero.
* **parentBeaconBlockRoot** - Set to the `parentBeaconRoot` of the L1 origin block.
### Removed fields
* **randomness** - Not needed since the [randomness](#randomness) feature has been removed
* **epochSnarkData** - Not needed since the Celo L2 does not support Plumo.
* **extraData** - The BLS aggregated signature has been removed as it is no longer required.
## EIP-1559 implementation
Previously our implementation used a smart contract [(here)](https://github.com/celo-org/celo-monorepo/blob/faca88f6a48cc7c8e6104393e49ddf7c2d7d20e3/packages/protocol/contracts-0.8/common/GasPriceMinimum.sol#L162) to calculate the base fee which allowed for governable parameters. Now we use the standard EIP1559 algorithm with the parameter values being defined in the chain config.
For chain specific parameters see the [deployment information in the Celo specs](/specs/deployments).
## RPC API
### Pre-transition data
Old blocks, transactions, receipts and logs are still be accessible via the RPC API but differ a bit from the corresponding objects retrieved from the L1 RPC API.
In general the changes involve additional extra unset fields that have been added upstream but were not present on historical Celo L1 objects, and the removal of some unnecessarily set fields on Celo L1 objects.
For in depth details of what has changed see [here](/specs/l2-migration).
### Block receipts
Historically, the Celo L1 generated block receipts when system contract calls emitted logs. The Celo L2 does not have block receipts, but pre-migration block receipts are still retrievable via the RPC API `eth_getBlockReceipt` method.
### Pre-transition execution and state access
RPC API calls for pre-transition blocks that are performing execution or accessing state are not directly supported by the new Celo L2 implementation. However, you can configure your Celo L2 node to proxy to an archive Celo L1 node for these calls. See the [archive node docs](/infra-partners/operators/archive-node).
## Unsupported geth keystore API
The old geth keystore API is not supported anymore, but you can extract your private key by using [cast](https://book.getfoundry.sh/cast/)'s `decrypt-keystore` keystore command.
Just give it the path to your keystore and the name of your key, e.g.
```
> cast wallet decrypt-keystore -k validator-00/keystore/ testkey
Enter password:
testkey's private key is: 0x2089e0db913b30b1c4084f3bd32ca3fd53e28437d76dbd0e609b0884b2c540ef
```
# What's changed?
Source: https://docs.celo.org/legacy/transition/whats-changed/overview
Celo is moving from being a POS (proof of stake) based L1 blockchain to an L2 built on the OP Stack. In Celo L1 both ordering and data availability were provided by the validators participating in the POS consensus mechanism, being an L2 means that Celo will instead rely on the L1 (Ethereum) for ordering and on [EigenDA](https://www.eigenda.xyz/) for data availability. Outsourcing those components allows Celo to offer increased scalability while focussing on providing value for users. See below for more details about all the changes involved.
## Details
* [Celo L1 → L2 changes](/legacy/transition/whats-changed/l1-l2)
* [Optimism → Celo L2 changes](/legacy/transition/optimism/op-l2)
# Celo Foundation Voting Policy
Source: https://docs.celo.org/legacy/validator/celo-foundation-voting-policy
How the Celo Foundation anticipates allocating its votes to validator groups, with special attention to the first allocated groups at the Celo Mainnet release and the months thereafter.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
The policy described here can change at any time as determined by the Foundation Board.
## Policy Objectives
The Foundation voting policy aims to:
* Be fair by avoiding preferential treatment to certain groups;
* Vote in-line with the Foundation’s purpose, which is to encourage financial inclusion and prosperity for all;
* Encourage professional, secure, and reliable validators;
* Be equal opportunity by enabling new groups to have validators elected; and
* Promote network stability by encouraging a gradual turnover in elected validators instead of abrupt election changes
## Process
Every 4 months, the Foundation, through its Board, will distribute a portion of its total available votes to a cohort of validator groups. These validators must meet certain basic standards (details below) and alignment with the Foundation’s purpose. The total number of validator groups in a cohort can vary.
Validator groups who will be selected for a cohort (and will thus receive a portion of the Foundation’s votes) will be informed by the following (non-exhaustive) considerations:
1. The number of elected validators in earlier cohorts;
2. Network stability;
3. CELO governance participation (e.g., how many CELO holders are actively participating in voting); and
4. The quality of validator group applicants
Each validator group selected in the cohort will receive a portion of the Foundation votes for a period of 12 months. During this period, so long as a validator in the group is not slashed or otherwise engages in misbehavior, the validator group will continue to receive these votes. If the validator group is slashed or engages in misbehavior, however, the votes for that validator group will be withdrawn for the remainder of the period. If the validator group is slashed, it may reapply to the Foundation after a 6 month period. In addition, the Foundation may also withdraw its votes if the validator group or the validators in the group fail to meet other standards, including running an attestation service.

## Eligibility Criteria
### Network Criteria
To support effective and responsible validators, the Foundation considers the following, main criteria for network performance, which must be met by all applicants who receive Foundation votes.
* **Zero Slashing Incidents.** The validator members of any applying group must not have been slashed within the last 6 months of application. (Note, there are a variety of reasons for slashing, including downtime, security issues, etc. At the outset, and because groups can re-apply at 6 months and 1 day of the slashing, all slashing will be considered equal at this stage)
* **Attestation Performance.** Ability and commitment to running attestation services with high completion rates.
* **Uptime Performance.** High performance uptime score over the past 30 days on Mainnet (or Baklava if not elected on Mainnet)
**Note**: If you are NOT ELECTED on Mainnet, you must be validating on Baklava testnet for at least 30 days. If you are ELECTED you must run validators and attestation service for at least one month (30 days) on Mainnet. If you are ELECTED on Mainnet but for less than 30 days, you must be validating on Baklava for 30 days at least.
### Supporting Criteria
On top of the main criteria outlined in the previous example, the Foundation considers the following, supporting criteria, which must be met by all applicants who receive Foundation votes:
* **Audit Checklist and Self Reporting.** As part of the application process, the Foundation will publish a list of recommended validator settings. The members of every group applying will self attest to complying with the recommended checklist.
* **Education.** An effective validator must be secure. Applicants’ members will take an education course. The course must be completed annually.
* **Basic Diligence.** Because the Foundation holds a substantial number of votes, and its voting may determine whether a validator is elected, the Foundation will conduct a basic diligence process for voted groups. The diligence would include name, location, entity information. This diligence would occur on an annual basis for any group receiving votes.
### Additional Criteria
In addition to meeting the main and supporting criteria, outlined above, the Foundation anticipates prioritizing validator groups who are mission aligned and/or will provide greater network resilience. These criteria may include:
* The geographical location of the validator group
* Non-profit organizations
* Organizations who commit to donating a percentage of rewards to non-profit organizations
* The likelihood of the validator group having substantial network support from other voters
This criteria assumes the validators perform well in the main and supporting criteria. It is used as an additional way to evaluate validator applicants assuming there’s a limited number of seats in a cohort and that the validators being evaluated all performed well in network performance as outlined in the main criteria.
## Application
The following new deadlines will be established for the next 3 cohorts as fixed dates.
Each cohort will last 12 months, there’s a 4 months gap between each cohort.
* Cohort 11: November 1 new date for voting in
* Cohort 12: March 1 new date for voting in
* Cohort 13: July 1 new date for voting in
For each cohort, the deadline to apply/be evaluated (if you are reapplying) is exactly 1 month prior to the date of being voted in. So for Cohort 8, it’ll be October 1 for the deadline, etc.
## New Applicants
### Application Prerequisites
Before applying all validator group members should have:
* **Important**: Run at least one Validator and Validator Group on Baklava
* **Important**: Run an Attestation Service on Baklava
* **Important**: Register a validator group on Mainnet and get 150k CELO voted for your validator group
* Completed the [Mastering the Art of Validating](https://youtu.be/3UIudzzCb8o) and [Validator Group Marketing](https://www.youtube.com/watch?v=0_veGIugCGQ) courses
* Completed the [Security Self Assessment Audit](https://docs.google.com/presentation/d/e/2PACX-1vRdKNpXI2mvqwQF6L5LRrxPW2qRK-5MDce5EhqXqLC1MSYmupZMFnhp6YEP0gLYuRKW-FF0fcAqhEAp/pub?start=true\&loop=false\&delayms=10000\&slide=id.g76d52a0216_0_333), which includes completing this [checklist](https://docs.google.com/spreadsheets/d/1FqmUfleCoyNIUep7PoVu3ujHd-OkHZJ8o6p7Affr93w/edit?usp=sharing)
### Application Details
Before applying be ready to share the following:
* A personal statement telling the Foundation why your group should get votes (max 1,500 characters)
* Validator Group details: email, name, website, address on Mainnet and Baklava, and geographic location
* Information about your team: full names, link to professional profiles such as LinkedIn or GitHub, and an explanation of the team’s relevant experience
* Whether your Group:
* Is validating or has validated in the past 1 month on the Baklava Testnet (Need to provide validator group address and validator address on Baklava)
* Has been slashed in the past 6 months and if so why (for reapplicants)
* Members have all completed the online training (see prerequisites)
* Members have all completed the self-audit (see prerequisites)
* Optional:
* The list of contributions made to the Celo ecosystem
* Date, audit firm name, and report of your last security audit if your Group has been audited by an external firm in the past 12 months
## Reapplicants
If you’re part of an existing cohort with expiring votes and interested in reapplying, the re-application process is much more simpler as an existing cohort.
You will receive an email from Celo Foundation asking you if you are interested in reapplying for the new Cohort.
At the application deadline date for new applicants, your validator group will be evaluated on Performance Score and Attestation Score. If you score above the Foundation’s threshold, you will be considered for the new cohort along with the new applicants reapplying, limited by seat availability in that cohort. If you don’t make the new cohort, you are invited to reapply for the next cohort application.
### Cohort Information
Past Foundation votes recipients:
* **Cohort 1:** The Great Celo Stake Off [leaderboard](https://docs.google.com/spreadsheets/d/1Me56YkCHYmsN23gSMgDb1hZ_ezN0sTjNW4kyGbAO9vc/edit#gid=1970613133) participants at ranking 26-50 -- votes expired on Aug 1, 2020
* **Cohort 2:** The Great Celo Stake Off [leaderboard](https://docs.google.com/spreadsheets/d/1Me56YkCHYmsN23gSMgDb1hZ_ezN0sTjNW4kyGbAO9vc/edit#gid=1970613133) participants at ranking 1-25 -- votes expired on Nov 1, 2020
* **Cohort 3:** [6 validator groups](https://docs.google.com/spreadsheets/d/1OkWnr6EOeFn4pIv0zxmXFNtHLmKWf_qCJOJ4iacov-A/edit?usp=sharing) -- votes expired on Feb 1, 2021
* **Cohort 4:** [22 validator groups](https://docs.google.com/spreadsheets/d/1bp2nJUxqhWner-uOffBohKQc3N93e--eMpP7XOBrbGI/edit?usp=sharing) -- votes expired on May 1, 2021
* **Cohort 5:** [24 validator groups](https://docs.google.com/spreadsheets/d/1n2lwFsAsFaohng4Bo_FEWcoXzZl5CrLFxA6EK0nuFSA/edit#gid=0) -- votes expired on November 1, 2021
* **Cohort 6:** [7 validator groups](https://docs.google.com/spreadsheets/d/1HT_fN-mSAL2etF0Po_h122jeU1zpEtdpb_khogOfBCg/edit?usp=sharing) -- votes will expire on March 1, 2022
* **Cohort 7:** [23 validator groups](https://docs.google.com/spreadsheets/d/1eYBzQMObTAy-WKs5CHHFnGGl_k1rQo0MBHinV3OgSik/edit#gid=1466530578) -- votes will expire on July 1, 2022
* **Cohort 8:** [24 validator groups](https://docs.google.com/spreadsheets/d/11fTPMa_2FXAye_mgidE_3Ub-xY_aJLo0WXee_Qn5mC8/edit#gid=0) -- votes will expire on November 1, 2022
* **Cohort 9:** [7 validator groups](https://docs.google.com/spreadsheets/d/1NcIMKvZnxyqzgbnaICisMR1y0eyxpr0HvCHFCHH-EDA/edit?pli=1#gid=0) -- votes will expire on March 1, 2023
Currently receiving Foundation votes:
* **Cohort 10:** [24 validator groups](https://docs.google.com/spreadsheets/d/1q0FhZJ2wYxg0JaZ-hbdIodRGwZPPNgf3aqD3ubArtj0/edit#gid=0) -- votes will expire on July 1, 2023
* **Cohort 11:** [24 validator groups](https://docs.google.com/spreadsheets/d/1CPbZmaS_e-dvPu1fujMYhaiUY_1sNqi3nYaYTIIBK6E/edit#gid=0) -- votes will expire on November 1, 2023
* **Cohort 12:** 5 validator groups -- votes will expire on March 1, 2024
Coming soon:
* **Cohort 13:** 24 validator groups -- votes will expire on July 1, 2024
If you would like to keep up-to-date with all the news happening in the Celo community, including validation, node operation and governance, please sign up to our [Celo Signal mailing list here](https://share.hsforms.com/1Qrhush1vSA2WIamd_yL4ow53n4j).
You can add the [Celo Signal public calendar](https://calendar.google.com/calendar/u/0/embed?src=c_9su6ich1uhmetr4ob3sij6kaqs@group.calendar.google.com) as well which has relevant dates.
# Celo Website
Source: https://docs.celo.org/legacy/validator/celo-website
# DevOps Best Practices
Source: https://docs.celo.org/legacy/validator/devops-best-practices
Best practices for running cloud infrastructure for Celo nodes and services.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## Cloud Infrastructure Best Practices
### Node Redundancy
If you are running your celo-blockchain nodes for mainnet in the cloud as a validator, then we recommend having more than one node running.
You can use the redundant validator node as a backup node. It's important that it should only be used as a backup node so you must not enable block-signing with it (to avoid double signing).
In case your primary validator node fails for some reason, then having the redundant node is extremely valuable as you can add the validator keys to it and point it to your proxy to continue signing blocks.
### Snapshotting
Another useful thing you can do is enabling snapshotting on your redundant node.
There's no best answer on cadence for snapshotting your redundant node, but one snapshot a week is a good estimate, depending on budget and how the cloud provider charges for snapshotting.
That way, in the event of a node or instance failure on your validator box, which can potentially lead to database failure and requiring you to resync your validator node, then you can use your snapshot as a starting point for syncing and don't have to wait too long to sync.
### Kubernetes
We are working on getting a Kubernetes recommended specification and will update this section once we have a recommended spec. If you are using Kubernetes with your validator node, feel free to submit a PR to update this section with your setup.
# Celo Discord
Source: https://docs.celo.org/legacy/validator/discord
# Celo Validators
Source: https://docs.celo.org/legacy/validator/index
Secure the Celo network by participating in the consensus of the Celo protocol.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
Celo Validators participate in the consensus of the Celo protocol. They help secure the Celo network by verifying transactions and proposing blocks to add to the Celo blockchain.
Not ready to become a Celo Validator? [Learn more about Celo](/).
## Important Information
* [Key Management](/legacy/validator/key-management/summary)
## Nodes and Services
* [Securing Celo Nodes and Services](/legacy/validator/security)
* [Upgrading a Node](/legacy/validator/node-upgrade)
* [Monitoring](/legacy/validator/monitoring)
* [Running Proxies](/legacy/validator/proxy)
## Validator Tools
* [Validator Explorer](/legacy/validator/validator-explorer)
## Voting Policy
* [Celo Foundation Voting Policy](/legacy/validator/celo-foundation-voting-policy)
For questions, comments, and discussions please use the [Celo Forum](https://forum.celo.org/) or [Discord](https://chat.celo.org/).
# Detailed Role Descriptions
Source: https://docs.celo.org/legacy/validator/key-management/detailed
Detailed descriptions of the various account roles as found in the Celo protocol with examples of how to designate an account as playing a particular role.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## Celo Accounts
Any private key generated for use in the Celo protocol has a corresponding address. The account address is the last 20 bytes of the hash of the corresponding public key, just as in Ethereum. Celo account keys can be used to sign and send transactions on the Celo network.
Celo Accounts can be designated as Locked Gold Accounts or authorized as signer keys on behalf of a Locked Gold Account by sending special transactions using [celocli](/cli/). Note that Celo accounts that have not been designated as Locked Gold Accounts or authorized signers may not be able to send certain transactions related to proof-of-stake.
## Locked CELO Accounts
[Locked CELO](/legacy/protocol/pos/locked-gold) Account keys have the highest level of privilege in the Celo protocol. These keys can be used to lock and unlock CELO in order to be used in proof-of-stake. Furthermore, Locked CELO Account keys can be used to authorize other keys to sign transactions and messages on behalf of the Locked CELO Account.
In *most* cases, the Locked CELO Account key has all the privileges as any authorized signers. For example, if a voter signer is authorized, a user can place votes on behalf of the Locked CELO Account with both the authorized vote signer *and* the Locked CELO Account.
Because of the significant privileges afforded to the Locked CELO Account, it is best to store this key securely and access it as infrequently as is possible. Authorizing other signers is one way to minimize how frequently you need to access your Locked CELO Account key. The Locked CELO Account key will only be used to send transactions and **can be stored on a Ledger hardware wallet.**
### Creating a Locked CELO Account
A Celo account may be designated as a Locked CELO Account by running the following command:
```shell theme={null}
# Designate the Celo account as a Locked CELO Account
celocli account:register --from $ADDRESS_TO_DESIGNATE --useLedger
# Confirm the address was designated as a Locked CELO Account
celocli account:show $ADDRESS_TO_DESIGNATE
```
Note that [ReleaseGold](/home/manage/release-gold) beneficiary keys are considered vanilla Celo accounts with respect to proof-of-stake, and that the `ReleaseGold` contract address is what ultimately gets designated as a Locked CELO Account.
## Authorized Vote Signers
Any Locked CELO Account may optionally authorize a Celo account as a vote signer. Authorized vote signers can vote for validator groups and for on-chain governance proposals on behalf of the Locked CELO Account.
Note that the vote signer must first generate a "proof-of-possession" indicating that signer's willingness to be authorized on behalf of the Locked CELO Account.
Authorized vote signers can only be used to send voting transactions and **can be stored on a Ledger hardware wallet**.
### Authorizing a Vote Signer
A Celo account may be authorized as a vote signer on behalf of a Locked CELO Account by running the following commands:
```shell theme={null}
# Create a proof-of-possession. Note that the signer private key must be available.
celocli account:proof-of-possession --account $LOCKED_GOLD_ACCOUNT --signer $SIGNER_TO_AUTHORIZE --useLedger
# Authorize the vote signer. Note that the Locked Gold Account private key must be available.
celocli account:authorize --from $LOCKED_GOLD_ACCOUNT --role vote --signer $SIGNER_TO_AUTHORIZE --signature $SIGNER_PROOF_OF_POSSESSION --useLedger
# Confirm that the vote signer was authorized
celocli account:show $LOCKED_GOLD_ACCOUNT
# You can also look up account info via the authorized signer
celocli account:show $SIGNER_TO_AUTHORIZE
```
## Authorized Validator Signers
Any Locked CELO Account may optionally authorize a Celo account as a validator signer. Authorized validator signers can be used to register and manage a validator or validator group on behalf of the Locked CELO Account. If the authorized validator signer is used to register and run a validator, the signer key is also used to sign consensus messages.
### Authorized Validator Signers for Validator Groups
An authorized validator signer key that will be used to register a validator group can be used to send group management transactions (e.g. register, add member A, queue commission update to 0.25, etc.) Because this key does not participate directly in consensus it **can be stored on a Ledger hardware wallet.**
### Authorized Validator Signers for Validators
An authorized validator signer key that will be used to register a validator can be used to send validator management transactions (e.g. register, affiliate with group A, etc.) This key will also be used to sign consensus messages and thus **cannot be stored on a Ledger hardware wallet** as signing consensus messages is not currently supported by the Celo Ledger App.
Note that the validator signer must first generate a "proof-of-possession" indicating the signer's willingness to be authorized on behalf of the Locked CELO Account.
### Authorizing a Validator Signer
A Celo account may be authorized as a validator signer on behalf of a Locked CELO Account by running the following commands:
```shell theme={null}
# Create a proof-of-possession. Note that the signer private key must be available.
# Note that the signing key can be kept on a Ledger if it will be used to run a Validator Group.
celocli account:proof-of-possession --account $LOCKED_GOLD_ACCOUNT --signer $SIGNER_TO_AUTHORIZE
# Authorize the validator signer. Note that the Locked CELO Account private key must be available.
# Note that if a Validator has previously been registered on behalf of the Locked CELO Account it
# may be desirable to include the BLS key here as well. Please see the documentation on
# validator key rotation for more information.
celocli account:authorize --from $LOCKED_GOLD_ACCOUNT --role validator --signer $SIGNER_TO_AUTHORIZE --signature $SIGNER_PROOF_OF_POSSESSION --useLedger
# Confirm that the vote signer was authorized
celocli account:show $LOCKED_GOLD_ACCOUNT
# You can also look up account info via the authorized signer
celocli account:show $SIGNER_TO_AUTHORIZE
```
## Authorized Validator BLS Signers
The Celo protocol uses BLS signatures in consensus to ultimately determine whether or not a particular block is valid. Many BLS signatures over the same content can be combined into a single "aggregated signature", allowing several kilobytes of signatures to be compressed into fewer than 100 bytes, ensuring that the block headers remain compact and light client friendly.
When registering a Validator on behalf of a Locked CELO Account, users must provide a BLS public key, as well as a proof-of-possession to protect against [rogue key attacks](https://crypto.stanford.edu/~dabo/pubs/papers/BLSmultisig.html).
By default users can derive the BLS key directly from their authorized validator signer key. From a key management and security perspective, this means that the authorized BLS signer key is **exactly the same** as the authorized validator signer key.
Most users will only need to think about BLS signer keys when registering a validator, or when authorizing a new validator signer *after* registering a validator. It follows that when a validator authorizes a new validator signer, the BLS public key and proof-of-possession for the new authorized validator signer should be provided as well.
Advanced users may optionally derive their BLS key separately, but that is out of the scope of this documentation.
### Deriving a BLS public key
To derive a BLS public key and proof-of-possession from the authorized validator signer key, and use that information to register a validator, run the following commands:
```shell theme={null}
# Derive the BLS public key and create a proof-of-possession. Note that the signer private key must be available.
# Also note that BLS proof-of-possessions are not currently supported by celocli
docker run -v $PWD:/root/.celo --rm -it $CELO_IMAGE account proof-of-possession $AUTHORIZED_VALIDATOR_SIGNER $LOCKED_GOLD_ACCOUNT --bls
# Register the Validator with the authorized validator signer on behalf of the Locked CELO Account
celocli validator:register --from $AUTHORIZED_VALIDATOR_SIGNER --blsKey $BLS_SIGNER_PUBLIC_KEY --blsSignature $BLS_SIGNER_PROOF_OF_POSSESSION
# Confirm that the validator was registered
celocli validator:show $LOCKED_GOLD_ACCOUNT
# You can also look up the validator via the authorized signer
celocli validator:show $AUTHORIZED_VALIDATOR_SIGNER
```
## Authorized Attestation Signers
Any Locked CELO Account may optionally authorize a Celo account as an attestation signer. Authorized attestation signers can sign attestation messages on behalf of the Locked Gold Account in Celo's [lightweight identity protocol](/legacy/protocol/identity/).
Note that the Celo Ledger App does yet not support signing attestation messages and as such attestation signer keys **cannot be stored on a Ledger hardware wallet**.
Note that the attestation signer must first be used to generate a "proof-of-possession" indicating the signer's willingness to be authorized on behalf of the Locked Gold Account.
### Authorizing an Attestation Signer
A Celo account may be authorized as a vote signer on behalf of a Locked CELO Account by running the following commands:
```shell theme={null}
# Create a proof-of-possession. Note that the signer private key must be available.
celocli account:proof-of-possession --account $LOCKED_GOLD_ACCOUNT --signer $SIGNER_TO_AUTHORIZE
# If celocli is unavailable on the attestations node, the proof-of-possession can be generated with celo-blockchain
docker run -v $PWD:/root/.celo --rm -it $CELO_IMAGE account proof-of-possession $SIGNER_TO_AUTHORIZE $LOCKED_GOLD_ACCOUNT
# Authorize the attestation signer. Note that the Locked CELO Account private key must be available.
celocli account:authorize --from $LOCKED_GOLD_ACCOUNT --role attestations --signer $SIGNER_TO_AUTHORIZE --signature $SIGNER_PROOF_OF_POSSESSION --useLedger
# Confirm that the vote signer was authorized
celocli account:show $LOCKED_GOLD_ACCOUNT
# You can also look up account info via the authorized signer
celocli account:show $SIGNER_TO_AUTHORIZE
```
# Validator Signer Key Rotation
Source: https://docs.celo.org/legacy/validator/key-management/key-rotation
How to manage signer key rotations as a Celo Validator.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## Why Rotate Keys?
As detailed in [the Celo account roles description page](/legacy/validator/key-management/detailed), Celo Locked CELO accounts can authorize separate signer keys for various roles such as voting or validating. This way, if an authorized signer key is lost or compromised, the Locked CELO account can authorize a new signer to replace the old one, without risking the key that custodies funds. This prevents losing an authorized signer key from becoming a catastrophic event. In fact, it is recommended as an operational best practice to regularly rotate keys to limit the impact of keys being silently compromised.
### Validator Signer Rotation
Because the Validator signer key is constantly in use to sign consensus messages, special care must be taken when authorizing a new Validator signer key. The following steps detail the recommended procedure for rotating the validator signer key of an active and elected validator:
1. Create a new Validator instance as detailed in the [Deploy a Validator](/legacy/validator/run/mainnet) section of the getting started documentation. When using a proxy, additionally create a new proxy and peer it with the new validator instance, as described in the same document. Wait for the new instances to sync before proceeding. Please note that when running the proxy, the `--proxy.proxiedvalidatoraddress` flag should reflect the new validator signer address. Otherwise, the proxy will not be able to peer with the validator.
Before proceeding to step 2 ensure there is sufficient time until the end of the epoch to complete key rotation.
2. Authorize the new Validator signer key with the Locked CELO Account to overwrite the old Validator signer key.
```bash theme={null}
# With $SIGNER_TO_AUTHORIZE as the new validator signer:
# On the new validator node which contains the new $SIGNER_TO_AUTHORIZE key
docker run -v $PWD:/root/.celo --rm -it $CELO_IMAGE account proof-of-possession $SIGNER_TO_AUTHORIZE $VALIDATOR_ACCOUNT_ADDRESS
docker run -v $PWD:/root/.celo --rm -it $CELO_IMAGE account proof-of-possession $SIGNER_TO_AUTHORIZE $VALIDATOR_ACCOUNT_ADDRESS --bls
```
1. If `VALIDATOR_ACCOUNT_ADDRESS` corresponds to a key you possess:
```bash theme={null}
# From a node with access to the key for VALIDATOR_ACCOUNT_ADDRESS
celocli account:authorize --from $VALIDATOR_ACCOUNT_ADDRESS --role validator --signer $SIGNER_TO_AUTHORIZE --signature 0x$SIGNER_PROOF_OF_POSSESSION --blsKey $BLS_PUBLIC_KEY --blsPop $BLS_PROOF_OF_POSSESSION
```
2. If `VALIDATOR_ACCOUNT_ADDRESS` is a `ReleaseGold` contract:
```bash theme={null}
# From a node with access to the beneficiary key of VALIDATOR_ACCOUNT_ADDRESS
celocli releasecelo:authorize --contract $VALIDATOR_ACCOUNT_ADDRESS --role validator --signer $SIGNER_TO_AUTHORIZE --signature 0x$SIGNER_PROOF_OF_POSSESSION --blsKey $BLS_PUBLIC_KEY --blsPop $BLS_PROOF_OF_POSSESSION
```
Please note that the BLS key will change along with the validator signer ECDSA key on the node. If the new BLS key is not authorized, then the validator will be unable to process aggregated signatures during consensus, **resulting in downtime**. For more details, please read [the BLS key section of the Celo account role descriptions](/legacy/validator/key-management/detailed#authorized-validator-bls-signers).
1. **Leave all validator and proxy nodes running** until the next epoch change. At the start the next epoch, the new Validator signer should take over participation in consensus.
2. Verify that key rotation was successful. Here are some ways to check:
* Open `baklava-blockscout.celo-testnet.org/address//validations` to confirm that blocks are being proposed.
* Open `baklava-celostats.celo-testnet.org` to confirm that your node is signing blocks.
* Run `celocli validator:signed-blocks --signer $SIGNER_TO_AUTHORIZE` with the new validator signer address to further confirm that your node is signing blocks.
The newly authorized keys will only take effect in the next epoch, so the instance operating with the old key must remain running until the end of the current epoch to avoid downtime.
5. Shut down the validator instance with the now obsolete signer key.
# Overview
Source: https://docs.celo.org/legacy/validator/key-management/summary
Introduction to the philosophy and account roles related to key management on Celo.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## Philosophy
The Celo protocol was designed with the understanding that there is often an inherent tradeoff between the convenience of accessing a private key and the security with which that private key can be custodied. In general Celo is unopinionated about how keys are custodied, but also allows users to authorize private keys with specific, limited privileges. This allows users to custody each private key according to its sensitivity (i.e. what is the impact of this key being lost or stolen?) and usage patterns (i.e. how often and under which circumstances will this key need to be accessed).
## Summary
The table below outlines a summary of the various account roles in the Celo protocol. Note that these roles are often *mutually exclusive*. An account that has been designated as one role can often not be used for a different purpose. Also note that under the hood, all of these accounts) are based on secp256k1 ECDSA private keys with the exception of the BLS signer. The different account roles are simply a concept encoded into the Celo proof-of-stake smart contracts, specifically [Accounts.sol](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/common/Accounts.sol).
For more details on a specific key type, please see the more detailed sections below.
| Role | Description | Ledger compatible |
| ----------------------------------- | ------------------------------------------------------------------------------------------------ | ----------------- |
| Celo Account | An account used to send transactions in the Celo protocol | Yes |
| Locked CELO Account | Used to lock and unlock CELO and authorize signers | Yes |
| Authorized vote signer | Can vote on behalf of a Locked CELO Account | Yes |
| Authorized validator (group) signer | Can register and manage a validator group on behalf of a Locked CELO Account | Yes |
| Authorized validator signer | Can register, manage a validator, and sign consensus messages on behalf of a Locked CELO Account | No |
| Authorized validator BLS signer | Used to sign blocks as a validator | No |
| Authorized attestation signer | Can sign attestation messages on behalf of a Locked CELO account | No |
A Locked CELO Account may have at most one authorized signer of each type at any time. Once a signer is authorized, the only way to deauthorize that signer is to authorize a new signer that has never previously been used as an authorized signer or Locked CELO Account. It follows then that a newly deauthorized signer cannot be reauthorized.
# Monitoring
Source: https://docs.celo.org/legacy/validator/monitoring
Commands, metrics, APIs, and services for monitoring Validators and Proxies.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## Monitoring Validators and Proxies
### Logging
Several command line options control logging:
* `--verbosity`: Sets logging verbosity. `3` outputs logs up to `INFO` level and is recommended. `4` outputs up to `DEBUG` level; `5` is `TRACE`.
* `--vmodule`: Overrides this verblosity in specific modules. For example, to configure `TRACE` level logging of consensus activity, use `consensus/istanbul/*=5`.
* `--consoleoutput`: Sends output to the given path, or to `stdout`.
* (Deprecatedin v1.5) `--consoleformat`: Formats logs for easy viewing in a terminal (`term`), or as structured JSON (`json`).
* (Introduced in v1.5) `--log.json`: Formats logs as structured JSON (`true`), or for easy viewing in a terminal (`false`, default option).
Useful messages to record or set up log-based metrics on:
* `msg="Validator Election Results"`: When the last block of any epoch (`number`) has been agreed, `elected` shows whether the validator was selected in the validator election.
* `msg="Elected but didn't sign block"`: This validator was elected but did not have its signature included in the block given by `number` (in fact, in the child's parent seal). This block could count towards downtime if 12 successive blocks are missed.
### Metrics
Celo Blockchain inherits [go-ethereum's metrics](https://github.com/ethereum/go-ethereum/wiki/Metrics-and-Monitoring) system, but additional Celo-specific metrics have been added.
Metrics reporting is enabled with the `--metrics` flag.
Pull-based metrics are available using the `--pprof` flag. This enables the `pprof` debugging HTTP server, by default on `http://localhost:6060`. The `--pprof.addr` and `--pprof.port` options can be used to configure the interface and port respectively. If the node is running inside a Docker container, you will need to set `--pprof.addr 0.0.0.0`, then on your Docker command line add `-p 127.0.0.1:6060:6060`.
Be sure never to expose the `pprof` service to the public internet.
[Prometheus](https://prometheus.io) format metrics are available at `http://localhost:6060/debug/metrics/prometheus`.
[ExpVar](https://golang.org/pkg/expvar/) format metrics are available at `http://localhost:6060/debug/metrics`.
Support for pushing metrics to [InfluxDB](https://www.influxdata.com/products/influxdb-overview/) is available via `--metrics.influxdb` and related flags. This works without the `pprof` server.
Note that metric name separators differ between these endpoints.
All metrics are soft-state and are cleared when the process is restarted.
### Memory metrics
Memory metrics derived from [mstats](https://godoc.org/github.com/go-graphite/carbonzipper/mstats):
* `system_memory_held`: Gauge of virtual address space allocated by the Celo Blockchain process, measured in bytes.
* `system_memory_used`: Gauge of Memory in use by the Celo Blockchain process, measured as bytes of allocated heap objects.
* `system_memory_allocs`: Counter for memory allocations made, measured in bytes. Consider monitoring the rate.
* `system_memory_pauses`: Counter for stop-the-world Garbage Collection pauses, measured in nanoseconds. Consider monitoring the rate.
### CPU metrics
* `system_cpu_sysload`: Gauge of load average for the system.
* `system_cpu_syswait`: Gauge of IO wait time for the system.
* `system_cpu_procload`: Gauge of load average for the Celo Blockchain process.
### Network metrics
* `p2p_peers`: The number of connected peers. This should remain at exactly `1` for a proxied validator (just its proxy). It should remain at a relatively steady level for proxy nodes.
* `p2p_ingress`: Counter for total inbound traffic, measured in bytes. Consider monitoring the rate.
* `p2p_egress`: Counter for total outbound traffic, measured in bytes. Consider monitoring the rate.
* `p2p_dials`: Counter for outbound connection attempts. Consider monitoring the rate.
* `p2p_serves`: Counter for accepted inbound connection attempts. Consider monitoring the rate.
### Blockchain metrics
* `chain_inserts_count`: The count of insertions of new blocks into this node's chain. The rate of this metric should be close to constant at `0.2` /second.
### Validator health metrics
A number of metrics are tracked for the parent of the last sealed block received (i.e. this is always two fewer than the current consensus sequence):
* `consensus_istanbul_blocks_elected`: Counts the number of blocks for which this validator has been elected
* `consensus_istanbul_blocks_signedbyus`: Counts the blocks for which this validator was elected and its signature was included in the seal. This means the validator completed consensus correctly, sent a `COMMIT`, its commit was received in time to make the seal of the parent received by the next proposer, or was received directly by the next proposer itself, and so the block will not count as downtime. Consider monitoring the rate.
* `consensus_istanbul_blocks_missedbyus`: Counts the blocks for which this validator was elected but not included in the child's parent seal (this block could count towards downtime if 12 successive blocks are missed). Consider monitoring the rate.
* `consensus_istanbul_blocks_missedbyusinarow`: (*since 1.0.2*) Counts the blocks for which this validator was elected but not included in the child's parent seal in a row. Consider monitoring the gauge.
* `consensus_istanbul_blocks_proposedbyus`: (*since 1.0.2*) Counts the blocks for which this validator was elected and for which a block it proposed was succesfully included in the chain. Consider monitoring the rate.
* `consensus_istanbul_blocks_downtimeevent`: (*since 1.0.2*) Counts the blocks for which this validator was elected and for blocks where it is considered down (occurs when `missedbyusinarow` is >= 12). Consider monitoring the rate.
### Consensus metrics
* `consensus_istanbul_core_desiredround`: Current desired round for this validator, i.e the round we are waiting to see a quorum of validators send `RoundChange` messages for. Usually this value should be `0`. Desired rounds increment with each timeout, which backoff exponentially. A value of `5` indicates consensus has stalled for more than 30 seconds. Values above that means the validator is unable to participate in quorum (either because it is disconnected, out of sync, etc, or because of network partition or failure of other validators).
* `consensus_istanbul_core_round`: : Current consensus round for this validator, i.e the round for which this validator has received a quorum of `RoundChange` messages. Usually this value should be `0`. If this value is less than `consensus_istanbul_core_desiredround` the validator is not connected to a quorum of other validators that are also unable to participate (for instance, they did see a proposed block, but this validator did not). If it is equal, it means the validator remains connected to a quorum of other validators but cannot agree on a block.
* `consensus_istanbul_core_sequence`: Current consensus sequence number, i.e the block number currently being proposed.
### Network consensus health metrics
* `consensus_istanbul_blocks_totalsigs`: The number of validators whose signatures were included in the child's parent seal. This can be used to determine how many validators are up and contributing to consensus. If this number falls towards two thirds of validator set size, network block production is at risk.
* `consensus_istanbul_blocks_missedrounds`: Sum of the `round` included in the `parentAggregatedSeal` for the blocks seen. That is, the cumulative number of consensus round changes these blocks needed to make to get to this agreed block. This metric is only incremented when a block is succesfully produced after consensus rounds fails, indicating down validators or network issues.
* `consensus_istanbul_blocks_missedroundsasproposer`: (*since 1.0.2*) A meter noting when this validator was elected and could have proposed a block with their signature but did not. In some cases this could be required by the Istanbul BFT protocol.
* `consensus_istanbul_blocks_validators`: (*since 1.0.2*) Total number of validators eligible to sign blocks.
* `consensus_istanbul_core_consensus_count`: Count and timer for succesful completions of consensus (Use `quantile` tag to find percentiles: `0.5`, `0.75`, `0.95`, `0.99`, `0.999`)
### Management APIs
Celo blockchain inherits and extends go-ethereum's Javascript console, exposing [management APIs](https://geth.ethereum.org/docs/rpc/server) and web3 DApp APIs.
Connect a client using a variant of the `attach` command line option:
```bash theme={null}
geth attach --datadir DATADIR
geth attach ipc:PATH/TO/geth.ipc
geth attach http://localhost:8545
geth attach ws://localhost:8546
```
## Community Monitoring Tools
### [Atalma Signature & Attestation Viewer (Celo Vido)](https://vido.atalma.io/celo/block-map)
* Visualizer of current and historic data on validator signatures collected in each block on Mainnet and Baklava.
* Visualizer of current and historic attestation requests and completions, and attestation endpoint versions and status on Mainnet and Baklava.
### [Virtual Hive Celo Network Validator Exporter](https://github.com/virtualhive/celo-network-validator-exporter)
Prometheus exporter that scrapes downtime and meta information for a specified validator signer address from the Celo blockchain. All data is collected from a blockchain node via RPC.
# Upgrade a Node
Source: https://docs.celo.org/legacy/validator/node-upgrade
How to upgrade to the newest available version of a Celo node.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## Recent Releases
* [You can view the latest releases here.](https://github.com/celo-org/celo-blockchain/releases)
## When an upgrade is required
Upgrades to the Celo node software will often be optional improvements, such as improvements to performance, new useful features, and non-critical bug fixes. Occasionally, they may be required when the upgrade is necessary to continue operating on the network, such as hard forks, or critical bug fixes.
## Upgrading a non-validating node
Use these instructions to update non-validating nodes, such as your account node or your attestation node on the Baklava testnet. Also use these instructions to upgrade your proxy node, but remember not to stop the proxy of a running validator.
### Pull the latest Docker image
```bash theme={null}
export CELO_IMAGE=us.gcr.io/celo-org/geth:mainnet
docker pull $CELO_IMAGE
```
### Stop and remove the existing node
Stop and remove the existing node. Make sure to stop the node gracefully (i.e. giving it time to shut down and complete any writes to disk) or your chain data may become corrupted.
Note: The `docker run` commands in the documentation have been updated to now include `--stop-timeout 300`, which should make the `-t 300` in `docker stop` below redundant. However, it is still recommended to include it just in case.
```bash theme={null}
docker stop -t 300 celo-fullnode
docker rm celo-fullnode
```
## Upgrading a Validating Node
Upgrading a validating node is much the same, but requires extra care to be taken to prevent validator downtime.
One option to complete a validating node upgrade is to perform a key rotation onto a new node. Pull the latest Docker image, as mentioned above, then execute a Validator signing key rotation, using the latest image as the new Validator signing node. A recommended procedure for key rotation is documented in the [Key Management](/legacy/validator/key-management/key-rotation) guide.
A second option is to perform a hot-swap to switch over to a new validator node. The new validator node **must** be configured with the same set of proxies as the existing validator node.
### Hotswapping Validator Nodes
Hotswap is being introduced in version 1.2.0. When upgrading nodes that are not yet on 1.2.0 refer to the guide to perform a key rotation.
Validators can be configured as primaries or replicas. By default validators start as primaries and will persist all changes around starting or stopping. Through the istanbul management RPC API the validator can be configured to start or stop at a specified block. The validator will participate in consensus for block numbers in the range `[start, stop)`.
Note that the replica node **must** use the same set of proxies as the primary node. If it does not it will not be able to switchover without downtime due to needing to the complete the announce protocol from scratch. Replicas behind the same set of proxies as the primary node will be able to switchover without downtime.
#### RPC Methods
* `istanbul.start()` and `istanbul.startAtBlock()` start validating immediately or at a block
* `istanbul.stop()` and `istanbul.stopAtBlock()` stop validating immediately or at a block
* `istanbul.replicaState` will give you the state of the node and the start/stop blocks
* `istanbul.validating` will give you true/false if the node is validating
`startAtBlock` and `stopAtBlock` must be given a block in the future.
#### Geth Flags
* `--istanbul.replica` flag which starts a validator in replica mode.
On startup, nodes will look to see if there is a `replicastate` folder inside it's data directory. If that folder exists the node will configure itself as a validator or replica depending on the previous stored state. The stored state will take precedence over the command line flags. If the folder does not exists the node will stored it's state as configured by the command line. When RPC calls are made to start or stop validating, those changes will be persisted to the `replicastate` folder.
If reconfiguring a node to be a replica or reusing a data directory, make sure that the node was previously configured as replica or that the `replicastate` folder is removed. If there is an existing `replicastate` folder from a node that was not configured as a replica the node will attempt to start validating.
#### Steps to upgrade
1. Pull the latest docker image.
2. Start a new validator node on a second host in replica mode (`--istanbul.replica` flag). It should be otherwise configured exactly the same as the existing validator.
* It needs to connect to the existing proxies and the validator signing key to connect to other validators in listen mode.
* If reconfiguring a node to be a replica or reusing a data directory, make sure that the node was previously configured as replica or that the `replicastate` folder is removed.
3. Once the replica is synced and has validator enode urls for all validators, it is ready to swapped in.
* Check validator enode urls with `istanbul.valEnodeTableInfo` in the geth console. The field `enode` should be filled in for each validator peer.
4. In the geth console on the primary run `istanbul.stopAtBlock(xxxx)`
* Make sure to select a block number comfortably in the future.
* You can check what the stop block is with `istanbul.replicaState` in the geth console.
* You can run `istanbul.start()` to clear the stop block
5. In the geth console of the replica run `istanbul.startAtBlock(xxxx)`
* You can check what the start block is with `istanbul.replicaState` in the geth console.
* You can run `istanbul.stop()` to clear the start block
6. Confirm that the transition occurred with `istanbul.replicaState`
* The last block that the old primary will sign is block number `xxxx - 1`
* The first block that the new primary will sign is block number `xxxx`
7. Tear down the old primary once the transition has occurred.
Example geth console on the old primary.
```bash theme={null}
> istanbul.replicaState
{
isPrimary: true,
startValidatingBlock: null,
state: "Primary",
stopValidatingBlock: null
}
> istanbul.stopAtBlock(21000)
null
> istanbul.replicaState
{
isPrimary: true,
startValidatingBlock: null,
state: "Primary in given range",
stopValidatingBlock: 21000
}
> istanbul.replicaState
{
isPrimary: false,
startValidatingBlock: null,
state: "Replica",
stopValidatingBlock: null
}
```
Example geth console on the replica being promoted to primary. Not shown is confirming the node is synced and connected to validator peers.
```bash theme={null}
> istanbul.replicaState
{
isPrimary: false,
startValidatingBlock: null,
state: "Replica",
stopValidatingBlock: null
}
> istanbul.startAtBlock(21000)
null
> istanbul.replicaState
{
isPrimary: false,
startValidatingBlock: 21000,
state: "Replica waiting to start",
stopValidatingBlock: null
}
> istanbul.replicaState
{
isPrimary: true,
startValidatingBlock: null,
state: "Primary",
stopValidatingBlock: null
}
```
### Upgrading Proxy Nodes
Release 1.2.0 is backwards incompatible in the Validator and Proxy connection. Validators and proxies must be upgraded to 1.2.0 at the same time.
With multi-proxy, you can upgrade proxies one by one or can add newly synced proxies with the latest Docker image and can remove the old proxies. If upgrading the proxies in place, a rolling upgrade is recommended as the validator will re-assign direct connections as proxies are added and removed. These re-assignments will allow the validator to continue to participate in consensus.
# Running Proxies
Source: https://docs.celo.org/legacy/validator/proxy
How to ensure Validator uptime by running proxy nodes.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## Why run a Proxy?
Validator uptime is essential for the health of the Celo blockchain. To help with validator uptime, operators can use the proxy node, which will provide added security for the validator. It allows the validator to run within a private network, and to communicate to the rest of the Celo network via the proxy.
Also, starting from the Celo client 1.2 release, we will support assigning multiple proxies per validator. This provides better uptime for the validator for the case of a proxy going down. Also, it will help with making each proxy enode URL less public by only sharing it with a subset of the other validators.
The communication protocol between the validator and it's proxies implemented in release 1.2 is NOT backwards compatible to the pre-1.2 protocol. So if the proxy or validator is being upgraded to 1.2, then both needs to be upgraded to that version. Note that validators and proxies using release 1.2 are still compatible with remote nodes.
There are two ways to specify the proxy information to a validator. It can be done on validator startup via the command line argument, or by the rpc api when the validator is running.
## RPC API
* `istanbul.addProxy(, )` can be used on the validator to add a proxy to the validator's proxy set
* `istanbul.removeProxy()` can be used on the validator to remove a proxy from the validator's proxy set
* `istanbul.proxies` can be used on the validator to list the validator's proxy set
* `istanbul.proxiedValidators` can be used on the proxies to list the proxied validators
# Running a Validator
Source: https://docs.celo.org/legacy/validator/run/mainnet
How to get a Validator node running on the Celo Mainnet.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## What is a Validator?
Validators help secure the Celo network by participating in Celo’s proof-of-stake protocol. Validators are organized into Validator Groups, analogous to parties in representative democracies. A Validator Group is essentially an ordered list of Validators.
Just as anyone in a democracy can create their own political party, or seek to get selected to represent a party in an election, any Celo user can create a Validator group and add themselves to it, or set up a potential Validator and work to get an existing Validator group to include them.
While other Validator Groups will exist on the Celo Network, the fastest way to get up and running with a Validator will be to register a Validator Group, register a Validator, and affliate that Validator with your Validator Group. The addresses used to register Validator Groups and Validators must be unique, which will require that you create two accounts in the step-by-step guide below.
Because of the importance of Validator security and availability, Validators are expected to run a "proxy" node in front of each Validator node. In this setup, the Proxy node connects with the rest of the network, and the Validator node communicates only with the Proxy, ideally via a private network.
[Read more about Celo's mission and why you may want to become a Validator.](https://medium.com/celoorg/calling-all-chefs-become-a-celo-validator-c75d1c2909aa) - This article still uses the term Celo Gold which is the deprecated name for the Celo native asset, which now is referred to simply as "Celo" or preferably "CELO".
# Run Secure Nodes and Services
Source: https://docs.celo.org/legacy/validator/security
Recommendations for running secure Celo nodes and services.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
Running Celo nodes and services securely, especially as part of running a validator, is of utmost importance. Failure to do so can lead to severe consequences including, but not limited to loss of funds, slashing due to double signing, etc.
### RPC Endpoints
Celo nodes can be interacted with through an RPC interface for common interactions such as querying the blockchain, inspecting network connectivity and much more. The RPC interface is exposed via HTTP, WebSockets or a local IPC socket. There are two considerations:
1. There is no authentication in the RPC interface. Anyone with access to the interface will be able to execute any actions that are enabled with the command-line options. This includes sensitive RPC modules like `personal` which interacts with the private keys stored on the node (`admin` is another one). It is not recommended to enable RPC modules unless you explicitly need them. Other RPC modules might be less sensitive but could create unnecessary load on your machine (like the `debug` module) to execute a DoS attack.
2. If you do need access to the RPC modules (for example to use `celocli` or the attestation service), use a firewall and similar mechanisms to restrict access to the RPC interface. You almost never want the interface to be accessible from outside the machine itself.
### Public Endpoints
Beyond the RPC interface, Celo nodes and services have other interfaces that actually need to be exposed to the public internet. While varying degrees of protection exist within the software, such as validating attestation requests against the blockchain or monitoring connections in the discovery protocol, additional measures are recommended to reduce the impact of malicious traffic. Examples include, but are not limited to:
* **DDoS protection:** Protected public endpoints from a DDoS attack is highly recommended to allow valid requests to be served
* **Whitelist endpoints:** The attestation service exposes a limited number of paths to function correctly. You could use a reverse proxy to reject paths that don't match them.
# Validator FAQ
Source: https://docs.celo.org/legacy/validator/troubleshooting-faq
Answers to frequently asked questions while troubleshooting issues as a Validator.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## How do I reset my local Celo state?
You may desire to reset your local chain state when updating parameters or wishing to perform a clean reset. Note that this will cause the node to resync from the genesis block which will take a couple hours.
```bash theme={null}
# Remove the celo state directory
sudo rm -rf celo
```
## How do I backup a local Celo private key?
It's important that local accounts are properly backed up for disaster recovery. The local keystore files are encrypted with the specified account password and stored in the keystore directory. To copy this file to your local machine you may use ssh:
```bash theme={null}
ssh USERNAME@IPADDRESS "sudo cat /root/.celo/keystore/" > ./nodeIdentity
```
You can then back this file up to a cloud storage for redundancy.
It's important that you use a strong password to encrypt this file since it will be held in potentially insecure environments.
## How do I install and use celocli on my node?
To install celocli on a Linux machine, run the following:
```bash theme={null}
sudo apt-get update
sudo apt-get install libusb-1.0-0 -y
sudo npm install -g @celo/celocli --unsafe-perm
```
To install celocli on a Mac/Windows machine, run the following:
```bash theme={null}
npm install @celo/celocli
```
You can then run celocli and point it to your local geth.ipc file:
```bash theme={null}
# Check if node is synced using celocli
sudo celocli node:synced --node geth.ipc
```
# Validator Explorer
Source: https://docs.celo.org/legacy/validator/validator-explorer
How to use the Validator Explorer to view Validator performance.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## Introduction to the Explorer - **Deprecated**
You can interact with the Validator Explorer that allows you to have a complete view of how the different validators are performing. This is one resource voters may use to find validator groups to vote for.
All of the existing validators and groups in the Celo network are included in this view. The default view shows all registered validator groups - if you click on any of the group names it will expand to show the validators affiliated with that group. You can also sort results by each column's value by clicking on the header field.
If you are looking to see how your validator is performing, you should first find the group your validator is affiliated with. Then you can click on the group name to see your validator and the rest of the validators affiliated with this group.
If you are running a validator group, one way to demonstrate your credibility to voters is claiming your validator badges by following the instructions [here](https://github.com/celo-org/website/blob/master/validator-badges/README.md).
A critical element of this explorer is the Validator Group name, which can help voters recognize organizations or active community members. This name is fetched from the `account` information registered on-chain for your validator and validator group. In order to combat name impersonation, a group can register a domain claim within their metadata. This verification is done by adding a [TXT record](https://wikipedia.org/wiki/TXT_record) to their domain which includes a signature of their domain claim signed by their associated account. This claim is then verified by the validator explorer. Individual users may also verify a claim using `celocli account:get-metdata`.
For example, if a group was run by the owners of `example.com`, they may want to register their Validator Group with the name `Example`. The name does not need to be the same as the name of your domain, but for simplicity we do so here. To give credence to this name, they may want to add a DNS claim. They can do this by adding a DNS claim to their metadata, claiming the URL `example.com`, while simultaneously adding a `TXT Record` to `example.com` that includes this claim signed by their group address. Let’s go through this example in detail, using a `ReleaseGold` contract as our validator group.
Assuming you have already deployed your Validator Group via a `ReleaseGold` contract, you will need these environment variables set to claim your domain.
### Environment variables
| Variable | Explanation |
| --------------------------------------- | ------------------------------------------------------------------------------- |
| CELO\_VALIDATOR\_GROUP\_RG\_ADDRESS | The `ReleaseGold` contract address for the Validator Group |
| CELO\_VALIDATOR\_RG\_ADDRESS | The `ReleaseGold` contract address for the Validator |
| CELO\_VALIDATOR\_SIGNER\_ADDRESS | The address of the validator signer authorized by the validator account |
| CELO\_VALIDATOR\_GROUP\_SIGNER\_ADDRESS | The address of the validator (group) signer authorized by the validator account |
First let's create the metadata file:
```bash theme={null}
# On your local machine
celocli account:create-metadata ./group_metadata.json --from $CELO_VALIDATOR_GROUP_RG_ADDRESS
```
Now we can set the group's name:
```bash theme={null}
# On your local machine
celocli releasecelo:set-account --contract $CELO_VALIDATOR_GROUP_RG_ADDRESS --property name --value Example.com
```
Now we can generate a claim for the domain associated with this name `example.com`:
```bash theme={null}
# On your local machine
celocli account:claim-domain ./group_metadata.json --domain example.com --from $CELO_VALIDATOR_GROUP_SIGNER_ADDRESS
```
This will output your claim signed under the provided signer address. This output should then be recorded via a `TXT Record` on your desired domain, so in this case we should add a `TXT Record` to `example.com` with this signed output.
You can now view and simultaneously verify the claims on your metadata:
```bash theme={null}
# On your local machine
celocli account:show-metadata ./group_metadata.json
```
Take a look at the output and verify these claims look right to you. This tool also automatically verifies the signatures on claims you've added.
Once that record is added, we can then register this metadata under on our `Validator Group` account for external validation.
Before we do this, you may also want to associate some validators with this domain. The benefit of doing this is to extend your DNS claim to your validators as well, meaning your validators can also verifiably be associated with your domain. You could also do this by adding individual DNS claims for each validator, but this would require separate `TXT Record`s for each, which is inconvenient. Instead, you can simply associate the group and validators together under a single claim.
In order to do so, you will need to claim each validator address on your group's metadata. You will also need to claim your group account on each of your validator's metadata to complete the association. We will run through an example of a single validator now:
First lets claim the `validator` address from the `group` account:
```bash theme={null}
# On your local machine
celocli account:claim-account ./group_metadata.json --address $CELO_VALIDATOR_RG_ADDRESS --from $CELO_VALIDATOR_GROUP_SIGNER_ADDRESS
```
Now let's submit the corresponding claim from the `validator` account on the `group` account (note: if you followed the directions to set up the attestation service, you may have already registered metadata for your validator. If that is the case, skip the steps to create the `validator`'s metadata and just add the account claim.)
```bash theme={null}
# On your local machine
celocli account:create-metadata ./validator_metadata.json --from $CELO_VALIDATOR_RG_ADDRESS
celocli account:claim-account ./validator_metadata.json --address $CELO_VALIDATOR_GROUP_RG_ADDRESS --from $CELO_VALIDATOR_SIGNER_ADDRESS
```
And then host both metadata files somewhere reachable via HTTP. You can use a service like gist.github.com. Create two gists, each with the contents of the respective files and then click on the Raw button to receive the permalinks to the machine-readable file. If you had already registered a metadata URL for your `validator` you just need to update that registerd gist, so you can skip the `validator` metadata registration below.
Now we can register these URLs on each account:
```bash theme={null}
# On your local machine
celocli releasecelo:set-account --contract $CELO_VALIDATOR_GROUP_RG_ADDRESS --property metaURL --value
celocli releasecelo:set-account --contract $CELO_VALIDATOR_RG_ADDRESS --property metaURL --value
```
If everything goes well users should be able to see your claims by running:
```bash theme={null}
# On your local machine
celocli account:get-metadata $CELO_VALIDATOR_GROUP_RG_ADDRESS
```
If everything went well, you should now have your group and validator associated with each other and with your associated domain!
# Voting for Validator Groups
Source: https://docs.celo.org/legacy/validator/voting
Resources for Validator Groups elections including technical details, policies, and Validator explorers.
This page describes the historical Celo Layer 1 blockchain. It is useful for understanding Celo’s history, but does not reflect the current state of the network. As of block height 31,056,500 (March 26, 2025, 3:00 AM UTC), Celo has transitioned to an Ethereum Layer 2.
***
## What are Validators?
Validators play a critical role in the Celo protocol, determining which transactions get applied and producing new blocks. Selecting organizations that operate well-run infrastructure to perform this role effectively is essential for Celo's long-term success.
The Celo community makes these decisions by locking CELO and voting for [Validator Groups](/legacy/protocol/pos/validator-groups), intermediaries that sit between voters and Validators. Every Validator Group has an ordered list of up to 5 candidate Validators. Some organizations may operate a group with their own Validators in it; some may operate a group to which they have added Validators run by others.
If you would like to keep up-to-date with all the news happening in the Celo community, including validation, node operation and governance, please sign up to our [Celo Signal mailing list here](https://share.hsforms.com/1Qrhush1vSA2WIamd_yL4ow53n4j).
You can add the [Celo Signal public calendar](https://calendar.google.com/calendar/u/0/embed?src=c_9su6ich1uhmetr4ob3sij6kaqs@group.calendar.google.com) as well which has relevant dates.
## Validator Elections
[Validator elections](/legacy/protocol/pos/validator-elections) are held every epoch (approximately once per day). The protocol elects a maximum of 110 Validators. At each epoch, every elected Validator must be re-elected to continue. Validators are selected [in proportion](/legacy/protocol/pos/validator-elections#running-the-election) to votes received for each Validator Group.
If you hold CELO, or are a beneficiary of a [`ReleaseGold` contract](/home/manage/release-gold) that allows voting, you can vote for Validator Groups. A single account can split their LockedGold balance to have outstanding votes for up to 10 groups.
CELO that you lock and use to vote for a group that elects one or more Validators receives [epoch rewards](/legacy/protocol/pos/epoch-rewards) every epoch (approximately every day) once the community passes a governance proposal enabling rewards. The initial level of rewards is anticipated to be around 6% per annum equivalent (but is subject to change).
Unlike a number of Proof of Stake protocols, **CELO used for voting is never at risk**. The actions of the Validator Groups or Validators you vote for can cause you to receive lower or higher rewards, but the CELO you locked will always be available to be unlocked in the future. [Slashing](/legacy/protocol/pos/penalties) in the Celo protocol applies only to Validators and Validator Groups.
## Choosing a Validator Group
As a CELO holder, you have the opportunity to impact the Celo network by voting for Validator Groups. As Validators play an integral role in securing Celo, it is crucial that voters choose groups that contribute to both the technical health of the network, as well as the community. Some factors to consider when deciding which Validator Group to vote for include:
### Technical
* **Proven identity:** Validators and groups can supply [verifiable DNS claims](/legacy/validator/validator-explorer). You can use these to securely identify that the same entity has access both to the account of a Validator or group and the supplied DNS records.
* **Can receive votes**: Validator Groups can receive votes up to a certain [voting cap](/legacy/protocol/pos/validator-elections#group-voting-caps). You cannot vote for groups with a balance that would put it beyond its cap.
* **Will get elected**: CELO holders only receive voter rewards during an epoch if their CELO is used to vote for a Validator Group that elects at least one Validator during that epoch. Put another way, your vote does not contribute to securing the network or earning you rewards if your group does not receive enough other votes to elect at least one Validator.
* **Secure**: The operational security of Validators is essential for everyone's use of the Celo network. You can see scores under the "Master Validator Challenge" column in the Stake Off leaderboard. Scores of 80% or greater were awarded the "Master Validator" badge, indicating a serious proven commitment to operational security.
* **Reliable**: Celo's consensus protocol relies on two-thirds of elected Validators being available in order to produce blocks and process transactions. Voter rewards are directly tied to the [uptime score](/legacy/protocol/pos/epoch-rewards-validator#calculating-uptime-score) of all elected Validators in the group for which the vote was made. Any period of consecutive downtime greater than a minute reduces a Validator's uptime score.
* **No recent slashing:** When Validators and groups register, their Locked Gold becomes "staked", in that it is subject to penalties for conduct that could seriously adversely affect the health of the network. Voters' Locked Gold is never slashed, but voter rewards are affected by a group's [slashing penalty](/legacy/protocol/pos/epoch-rewards-validator#calculating-slashing-penalty), which is halved when a group or one of its Validators is slashed. Look for groups with a last slashing time long in the past, ideally `0` (never), and a slashing penalty value of `1.0`.
* **Runs an Attestation Service**: The [Attestation Service](/legacy/protocol/identity/) is an important service that Validators can run that allows users to verify that they have access to a phone number and map it to an address. Supporting Validators that run this service makes it easier for new users to begin using Celo.
* **Runs a Validator on Baklava**: A group that runs a Validator on the [Baklava](/build-on-celo/network-overview) helps maintain the testnet and verify that upgrades to the Celo Blockchain software can be deployed smoothly.
### Community
* **Promotes the Celo mission**: Celo's mission is to [build a monetary system that creates the conditions of prosperity for all](https://medium.com/celoorg/an-introductory-guide-to-celo-b185c62d3067). Consider Validator Groups that further this mission through their own activities or initiatives around financial inclusion, education and sustainability.
* **Broadens Diversity**: The Celo community aims to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. Support that diversity by considering what new perspectives and strengths the teams you support offer. As well as the backgrounds and experiences of the team, consider that the network security and availability is improved by Validators operating at different network locations, on different platforms, and with different toolchains.
* **Contributes to Celo:** Support Validator Groups that strengthen the Celo developer community, for example through building or operating services for the Celo ecosystem, participating actively in on-chain governance, and answering questions and supporting others, on [Discord](https://chat.celo.org) or the [Forum](https://forum.celo.org).
## The Celo Foundation Voting Policy
As described above, there are many criteria to consider when deciding which group to vote for. While it is highly recommended that all CELO holders do their independent research when deciding which group to vote for, another option is to vote for Validator Groups that have received votes from the Celo Foundation.
The Celo Foundation has a [Validator Group voting policy](/legacy/validator/celo-foundation-voting-policy) that it follows when voting with the CELO that it holds. This policy has been developed by the Foundation board and technical advisors with the express goal of promoting the long-term security and decentralization of the network. Validator Groups have an opportunity to apply for Foundation votes every 3 months, and a new cohort is selected based on past performance and contributions.
You can find the [full set of Validator Groups currently receiving votes, and their addresses linked here](https://docs.google.com/spreadsheets/d/1ltVNkQfXW3lIZxXU52R3IXeD6w21oacWFVb3a-FYRBY/edit?usp=sharing).
## Validator Explorers
The Celo ecosystem includes a number of great services for browsing registered Validator Groups and Validators.
**Warning**: Exercise caution in relying on Validator-supplied names to determine their real-world identity. Malicious participants may attempt to impersonate other Validators in order to attract votes.
Validators and groups can also supply [verifiable DNS claims](/legacy/validator/validator-explorer), and the Celo Validator Explorer displays these. You can use these to securely identify that the same entity has access both to the account of a Validator or group and the supplied DNS records.
### [Celo Mondo Validator Explorer](https://mondo.celo.org/) ([cLabs](https://clabs.co))
The Celo Mondo "Staking" tab displays information for Mainnet Validators.
### [Celovote Scores](https://celovote.com/scores) (WOTrust | celovote.com)
Celovote shows a ranking of Validator groups based on their estimated annual rate of return (ARR).
The estimate is calculated based on past performance.
### [Vido](https://vido.atalma.io/celo/block-map) ([Atalma](https://www.atalma.io/))
Vido is a block visualization and monitoring suite for Mainnet and the Baklava testnet.
It shows missed blocks and downtime for the Validator group set and subscribable metrics to get alerted if your Validator is no longer signing.
# Whitepapers
Source: https://docs.celo.org/legacy/whitepapers
# Deployments
Source: https://docs.celo.org/specs/deployments
## Mainnet
Celo Mainnet was migrated to an L2 on March 26, 2025, around 3:00 AM UTC, at block *31056500*. For this, the L1 chain was stopped at a block height of *31056499* and the existing state was migrated to work with the L2 nodes. The migration process preserved the full L1 history while updating it to work with the Celo L2 stack. More technical details are available in the [migration docs](/specs/l2-migration).
The Celo L2 network has the following chain properties:
* Block period: 1 second
* Block gas limit: 30,000,000 gas
* Block gas target: 6,000,000 gas (see EIP-1559 elasticity multiplier)
* EIP-1559 elasticity multiplier: 5
* EIP-1559 denominator: 400
* EIP-1559 floor: 25 Gwei
### Parameters
* [ProxyOwner owner](https://mondo.celo.org/governance/cgp-171): [`0x4092A77bAF58fef0309452cEaCb09221e556E112`](https://app.safe.global/home?safe=eth:0x4092A77bAF58fef0309452cEaCb09221e556E112)
* Guardian address (can pause/unpause the bridge): `0x6E226fa22e5F19363d231D3FA048aaBa73CC1f47`
### Contract addresses
L1 and L2 contract addresses are listed in the documentation.
* [L1 contracts](/tooling/contracts/l1-contracts#celo-mainnet)
* [Core contracts](/tooling/contracts/core-contracts#celo-mainnet)
* [Fee currencies](/tooling/contracts/fee-currencies#celo-mainnet)
## Celo Sepolia testnet
The Celo Sepolia testnet has the same chain properties as Celo Mainnet:
* Block period: 1 second
* Block gas limit: 30,000,000 gas
* Block gas target: 6,000,000 gas (see EIP-1559 elasticity multiplier)
* EIP-1559 elasticity multiplier: 5
* EIP-1559 denominator: 400
* EIP-1559 floor: 25 Gwei
### Contract addresses
L1 and L2 contract addresses are listed in the documentation.
* [L1 contracts](/tooling/contracts/l1-contracts#celo-sepolia-testnet)
* [Core contracts](/tooling/contracts/core-contracts#celo-sepolia-testnet)
* [Fee currencies](/tooling/contracts/fee-currencies#celo-sepolia-testnet)
## OP stack config
| Config | Celo | OP |
| --------------------------------- | ----------- | ------ |
| `maxSequencerDrift` | 2892 | 1800 |
| `sequencerWindowSize` | 3600 | 3600 |
| `channelTimeout` | 300 | 300 |
| `finalizationPeriodSeconds` | 12 | 12 |
| `enableGovernance` | `false` | `true` |
| `eip1559Denominator` | 400 | 50 |
| `eip1559DenominatorCanyon` | 400 | 250 |
| `eip1559Elasticity` | 5 | 6 |
| `eip1559BaseFeeFloor` | 25000000000 | - |
| `gasPriceOracleBaseFeeScalar` | 0 | 1368 |
| `gasPriceOracleBlobBaseFeeScalar` | 0 | 810949 |
# EigenDA
Source: https://docs.celo.org/specs/eigenda
In contrast to OP Mainnet sequencer which writes TX batches to Ethereum in the form of calldata or, more recently, EIP-4844 blobs to commit to the transactions included in the canonical L2 chain, Celo uses [EigenDA](https://docs.eigenlayer.xyz/eigenda/overview) as an alternative data availability layer in order to minimize the TX fees. EigenDA is a data availability store made by [EigenLabs](https://www.eigenlabs.org) and built on top of [EigenLayer](https://docs.eigenlayer.xyz/eigenlayer/overview/). With EigenDA, TX data is stored by EigenDA operators off-chain, only DA commitments used for verficiation and subsequent data retrieval are stored On Ethereum which significantly reduces DA costs and L2 TX fees.
The integration is done in accordance with the [Optimism's Alt-DA spec](https://specs.optimism.io/experimental/alt-da.html) which contains a more in-depth description of this interface.
## Testnet and Contract Addresses
The Celo Sepolia testnet uses the [EigenDA Sepolia testnet](https://docs.eigencloud.xyz/products/eigenda/networks/sepolia).
# Fee Abstraction: Paying Gas With ERC20 Tokens
Source: https://docs.celo.org/specs/fee-abstraction
Fee Abstraction is a Celo feature that allows users to send transactions without spending any native CELO tokens. Instead, ERC20 tokens are used to pay for the transaction's gas cost.
## As a User
### Sending Fee Abstraction Transactions
To pay gas via Fee Abstraction, the gas token must be specified in a [CIP-64](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0064.md) transaction. This tx type has an additional `feeCurrency` field that specifies which token is used for the `maxFeePerGas` and `maxPriorityFeePerGas` fields. See [CIP-64](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0064.md) for details.
Client library support is [described in docs.celo.org](/home/protocol/transactions/transaction-types#client-library-support).
### JSON-RPC Changes
To make it easier to reliably send Fee Abstraction transactions, the JSON-RPC interface has been extended in two ways:
* `eth_estimateGas` takes an optional `feeCurrency` parameter to get Fee Abstraction specific gas estimates (the gas price for the fee token transfers depends on the token)
* `eth_gasPrice` and `eth_maxPriorityFeePerGas` take an optional `feeCurrency` parameter for getting CIP-64 gas prices.
### The Fee Currency Directory
Only tokens that have been registered in the `FeeCurrencyDirectory` contract using Celo's governance process can be used for Fee Abstraction. The directory entry shows that the token is trustworthy and contains additional information about the token:
* The token address
* An oracle address, conforming to the [`IOracle`](https://github.com/celo-org/celo-monorepo/blob/2ace1d08b9da5d2618e945eef7663cc385917a2d/packages/protocol/contracts-0.8/common/interfaces/IOracle.sol) interface, to get the current exchange rate
* The amount of intrinsic gas for Fee Abstraction gas calculation (see ["Gas Calculation for Fee Abstraction Transactions"](#gas-calculation-for-fee-abstraction-transactions))
You can run the `getCurrencies()` method on the `FeeCurrencyDirectory` contract to get a list of all registered tokens and use `getExchangeRate(token address)` to fetch the current exchange rate for a token. The `IOracle` interface is only intended for parties providing Fee Abstraction tokens, not for users or client libraries.
### Tokens using FeeCurrencyAdapter
Tokens with a low number of `decimals` (USDC, USDT, and USA₮) would cause problems during the gas calculation, because the cost per gas can only be accurately given in fractions and not integers. To avoid this issue, the tokens are not directly added to the `FeeCurrencyDirectory`. Instead, a `FeeCurrencyAdapter` contracts wraps these tokens, calculates the costs per gas in a higher accuracy and only converts it back to the lower accuracy once the total gas costs for a transaction is determined.
This only really impacts the user in a single way: Instead of using the USDC, USDT, or USA₮ token addresses, you have to pass their `FeeCurrencyAdapter` addresses in the `feeCurrency` field for CIP-64 txs.
## For Token Authors
### Requirements for Registering a Fee Abstraction Token
To become registered as a Fee Abstraction currency, the following requirements have to be met:
* Implement the [IFeeCurrency interface](https://github.com/celo-org/fee-currency-example/blob/master/src/IFeeCurrency.sol)
* Ensure exchange rates are kept up to date in the oracle with the `IOracle` interface
* Pass a Celo governance vote for the `FeeCurrencyDirectory` addition
The [fee-currency-example repository](https://github.com/celo-org/fee-currency-example) contains the interface description and an example Fee Abstraction token implementation with tests.
### Tokens With Non-18 Decimals
Tokens that do not use 18 decimal places (e.g. USDT with 6 decimals) cannot be registered directly in the `FeeCurrencyDirectory`. The low precision causes problems during gas price calculation, where the cost per gas can only be accurately represented as a fraction, not an integer with few decimal places.
To support Fee Abstraction, the token deployer must deploy a [`FeeCurrencyAdapter`](https://github.com/celo-org/celo-monorepo/blob/874eeacf65c64de097c2d5c44a4d849961aeccfd/packages/protocol/contracts-0.8/stability/FeeCurrencyAdapter.sol) contract that wraps the token. The adapter performs gas cost calculations at higher precision (18 decimals) and only converts back to the token's native decimal precision when the total gas cost for a transaction has been determined. It is the adapter contract address, not the underlying token address, that gets registered in the `FeeCurrencyDirectory`.
The `FeeCurrencyAdapter` contract has been [audited by Trail of Bits](https://github.com/celo-org/celo-monorepo/files/14377164/cLabs.Equivalent.Tokens.Review.-.Summary.Report.pdf) and was released as part of [Core Contracts v11](https://github.com/celo-org/celo-monorepo/releases/tag/core-contracts.v11).
## Inside the Celo Blockchain
### Exchange Rate Handling Inside the Blockchain Client
Before each block, the blockchain client reads the list of all registered Fee Abstraction tokens from the `FeeCurrencyDirectory` and fetches the currency exchange rate for each of them. If the Oracle for a token reverts or returns invalid exchange rates (numerator or denominator are zero), the token is treated as if it was not registered. Token registrations and exchange rates stay the same within a block and are only updated before the next block.
Transactions with unregistered `feeCurrency` values are not accepted into the tx pool and dropped from the pool if they have been previously accepted. The same is true if the `maxFeePerGas` falls below the current base fee.
### Gas Calculation for Fee Abstraction Transactions
Ethereum transactions pay a fixed fee of 21000 gas ("intrinsic gas") in addition to the cost for executing the transaction. This is meant to cover the operating expenses during tx processing outside the actual tx execution, like debiting the gas cost from the tx sender's account, refunding the unused gas or transferring the base fee and tip to the respective receivers.
When using Fee Abstraction, the fees are transferred by executing functions on the respective token contract, which is computationally more expensive than native token transfers. The exact costs will vary by token and can change over time. Therefore, a token-specific intrinsic gas value is used for Fee Abstraction txs in addition to Ethereum's intrinsic gas. This value is stored in the `FeeCurrencyDirectory` contract and can be changed by Celo governance. It should be set to at least the maximum gas cost of executing all function calls for debiting and crediting fees for a single transaction.
Addresses warmed during the debit will keep their warm status for the execution of the main tx.
If fetching the intrinsic gas for a token from the `FeeCurrencyDirectory` reverts, the token is treated as unregistered. Values exceeding `2^64-1` are capped at that value.
### EIP-7623 Implementation and Intrinsic Gas Considerations
Celo L2 implements [EIP-7623](https://eips.ethereum.org/EIPS/eip-7623) to mitigate transaction spam by enforcing a minimum gas cost floor for transactions with significant calldata. This floor is calculated as:
```
21_000 + TOTAL_COST_FLOOR_PER_TOKEN * tokens_in_calldata
```
The `21_000` value represents the **standard Ethereum intrinsic gas** and is used consistently across all transaction types for EIP-7623 floor calculations, regardless of whether the transaction uses Fee Abstraction or not.
### Block Space Limits Per Fee Abstraction Token
As described above, Celo allows users to pay for gas using ERC20 tokens. There is a governable list of accepted tokens. However, the Celo blockchain client starting with version 1.8.1 implements a protective mechanism that allows validators to control the percentage of available block space used by transactions paid with an alternative fee currency (other than CELO) more precisely.
There are two new flags that control this behavior:
1. `celo.feecurrency.limits` with a comma-separated `currency_address_hash=limit` mappings for currencies listed in the `FeeCurrencyDirectory` contract, where `limit` represents the maximal fraction of the block gas limit as a float point number available for the given fee currency. The addresses are not expected to be checksummed.
For example, `0x765DE816845861e75A25fCA122bb6898B8B1282a=0.1,0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73=0.05,0xEd6961928066D3238134933ee9cDD510Ff157a6e=0`.
2. `celo.feecurrency.default` - an overridable default value (initially set to `0.5`) for currencies not listed in the limits map, meaning that if not specified otherwise, a transaction with a given fee currency can take up to `50%` of the block space. CELO token doesn't have a limit.
Based on historical data, the following default configuration is proposed:
```bash theme={null}
--celo.feecurrency.default=0.5
--celo.feecurrency.limits="0x765DE816845861e75A25fCA122bb6898B8B1282a=0.9,0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73=0.5,0xe8537a3d056DA446677B9E9d6c5dB704EaAb4787=0.5"
```
It imposes the following limits:
* cUSD up to 90%
* cEUR up to 50%
* cREAL up to 50%
* any other token except CELO - 50%
* CELO doesn't have a limit
# Finality
Source: https://docs.celo.org/specs/finality
## Overview
The Celo L2 provides two layers of economic security — Celo-economic security and Ethereum-economic security. Celo-economic security is the security the L2 blockchain provides until data has been written to an L1 block and that block has been finalized. In order to provide reorg resistance at Celo-economic security in the L2 design, we need to address two sources of possible reorgs:
1. Avoid discrepancies in what the sequencer shares over the p2p network and posts to the L1.
2. Avoid those caused by Ethereum reorgs.
The first section below describes the standard OP Stack finality model and where reorgs can occur. The second section describes the modifications Celo L2 makes on top of the OP Stack to mitigate these reorgs.
## Finality and Reorgs in Optimism (Baseline)
Optimism L2 blocks have three levels of finality:
* **Unsafe:** Blocks are shared by the sequencer over the p2p network and can be reorged with no penalty.
* **Safe:** Blocks are deterministically derived from inputs and L2 data posted to not-yet-finalized Ethereum blocks. These blocks are susceptible to Ethereum reorgs.
* **Finalized:** Blocks are derived from finalized blocks on Ethereum and can practically not be reorged without massive economic costs. This is Ethereum-economic security.
Once an L2 block is finalized, it has the same security guarantees as the underlying L1 and is highly unlikely to be reorged. Therefore, our focus lies on avoiding reorgs at the unsafe and safe levels.
**Unsafe head reorgs** could happen in the following scenarios:
* The sequencer shares an unsafe block on the p2p network but misses the sequencing window to post the corresponding transaction data to Ethereum. As a result, there won't be valid block data for that height, and the unsafe head will reorg to use a generated empty block.
* The sequencer distributes an unsafe block on the p2p network but posts different transaction data for the same block height to Ethereum. The unsafe head will reorg to use the data on Ethereum.
These cases are controlled by the sequencer. If the user trusts the sequencer and its actions, it can follow unsafe blocks. If not, it can completely avoid those by only following safe blocks.
**Safe head reorgs** can occur in the following situations:
* An L1 block is reorged, then the corresponding sequencing epoch's blocks will need to be updated to account for the changes in the L1 origin (specifically, deposit transactions). This situation can also cause an unsafe head reorg.
* If Ethereum reorgs such that transaction data posted either no longer exists or now falls outside of the sequencing window, then the corresponding (previously safe) L2 block will become an empty block.
## Celo L2 Changes to the OP Stack
The following describes modifications Celo L2 makes to the standard OP Stack derivation pipeline to achieve safe-head reorg resistance. In the standard OP Stack, the sequencer follows the unsafe L1 head, which leaves safe blocks susceptible to Ethereum reorgs. Celo L2 changes this behavior.
### 1. Sequencer Uses Finalized L1 Origin
Celo L2 configures the sequencer to follow only finalized blocks on Ethereum by enabling the `--sequencer.use-finalized` flag on the op-node. In the standard OP Stack, the sequencer follows the unsafe L1 head; by contrast, Celo L2 restricts the L1 origin to finalized blocks only. The L1 origin is still incremented in steps of one, so that all invariants relying on this behavior in the Optimism codebase are preserved.
**Trade-off:** This increases the time for user-deposited and (native) bridging transactions to be included in the L2 from the standard \~4 blocks (48 seconds) to at least 2 Ethereum epochs (64 slots, \~12.8 minutes).
### 2. Sequencer Stalling on L1 Finalization Lag
If the Ethereum L1 fails to finalize blocks, the sequencer would continue to create unsafe L2 blocks without a finalized L1 origin to anchor to. To handle this, Celo L2 introduces a safeguard: the sequencer must stall and avoid producing blocks until L1 finalization catches up to below some threshold.
### 3. Fast Finality via Espresso (In Progress)
We are actively working with [Espresso](https://www.espressosys.com/) to provide 1–5 second finality backed by Espresso's economic security guarantees. This will allow Celo L2 users to receive fast confirmation of transactions with meaningful economic backing, significantly improving on the current trade-off between finality speed and reorg resistance.
***
### Summary of Changes
| Change | Standard OP Stack Behavior | Celo L2 Behavior |
| ----------------------------- | ------------------------------------ | -------------------------------------------------------------- |
| **L1 origin for sequencing** | Follows the unsafe L1 head | Follows only finalized L1 blocks (`--sequencer.use-finalized`) |
| **L1 finalization failure** | Sequencer continues producing blocks | Sequencer stalls until finalization catches up |
| **Deposit inclusion latency** | \~48 seconds (4 blocks) | \~12.8 minutes (2 epochs) |
| **Fast finality** | None | 1–5s finality via Espresso (in progress) |
# Celo L2 Specification
Source: https://docs.celo.org/specs/index
This document describes the differences between the Celo L2 implementation and [Optimism's](https://optimism.io) OP Stack, on which it is based. Refer to the [OP Stack specs](https://specs.optimism.io/) for details on the unmodified OP Stack.
The [L1→L2 migration changes page](/specs/l2-migration) details the differences compared to the Celo L1 blockchain. The Celo L2 is a continuation of the L1 by using its state and providing a high level of compatibility with it.
## Background
Since May 2024, the Celo Community has decided to transition from an L1 blockchain to a L2 solution using the OP Stack. This move, detailed and [approved](https://mondo.celo.org/governance/cgp-133) in [CGP-133](https://github.com/celo-org/governance/blob/main/CGPs/cgp-0133.md), aims to enhance scalability, security, and interoperability with Ethereum. The proposal aligns with Celo's mission to create a more accessible and inclusive financial system. By leveraging the OP Stack, Celo L2 will retain the benefits of the existing ecosystem while integrating with Ethereum's robust infrastructure, fostering greater innovation and user engagement.
## New Features
* [Token duality](/specs/token-duality), access native tokens via ERC20
* [Fee Abstraction](/specs/fee-abstraction), pay gas with ERC20 tokens
## Technical Differences
* New [transaction types](/specs/transaction-types) to support Fee Abstraction
* [One new precompile](/specs/token-duality#the-transfer-precompile) to support token duality
* [Changes to finality](/specs/finality)
* The `MaxCodeSize` for newly deployed contracts is increased from 24576 to 65536.
## Deployments
* [Mainnet](/specs/deployments#mainnet)
* [Celo Sepolia testnet](/specs/deployments#celo-sepolia-testnet)
# L1 Deploy Verification
Source: https://docs.celo.org/specs/l1-smart-contract-verification
This guide walks through verifying Celo L1 (Ethereum) smart contracts deployment. It contains steps to verify contracts in the `packages/contracts-bedrock` folder. L2 (Celo) contracts became available with the [transition](https://x.com/cLabs/status/1900625559090328062).
## 1. Prerequisites
* **Foundry Installed:** Ensure you have Foundry installed and updated (via [foundryup](https://github.com/foundry-rs/foundry)).
* **JQ Installed:** jq cli tool for handling json files is required later.
* **API Key:** Obtain an Etherscan (or corresponding block explorer) API key.
## 2. Verify Smart Contracts bytecode
Check that on chain bytecode correspond to compiled bytecode from smart contract release.
Smart contract release is: [https://github.com/celo-org/optimism/releases/tag/celo-contracts.L1%2Fv1.8.0--1](https://github.com/celo-org/optimism/releases/tag/celo-contracts.L1%2Fv1.8.0--1)
Clone the `celo-org/optimism` repository and checkout release tag
```bash theme={null}
git clone https://github.com/celo-org/optimism
cd optimism
git checkout celo-contracts.L1/v1.8.0--1
```
Enter the contract folder & compile contracts
Navigate to the Contracts Folder
```bash theme={null}
cd packages/contracts-bedrock
forge build
```
To verify contract, will compare onchain bytecode with compiled one using a script.
For that, create `scripts/compare_bytecode.sh` with following content:
```bash theme={null}
#!/bin/bash
# Usage: ./compare_bytecode_ignore_immutables.sh
if [ "$#" -lt 2 ]; then
echo "Usage: $0 "
exit 1
fi
CONTRACT_ADDRESS=$1
ARTIFACT_FILE=$2
# Fetch deployed bytecode from chain
DEPLOYED_BYTECODE=$(cast code "$CONTRACT_ADDRESS" --rpc-url https://eth.llamarpc.com | tr -d '\n')
if [ -z "$DEPLOYED_BYTECODE" ]; then
echo "Error: Failed to fetch bytecode."
exit 1
fi
# Get local bytecode
LOCAL_BYTECODE=$(jq -r '.deployedBytecode.object' "$ARTIFACT_FILE" | tr -d '\n')
if [ -z "$LOCAL_BYTECODE" ]; then
echo "Error: Failed to extract local bytecode."
exit 1
fi
# Special exception for SuperchainConfig version diff
if grep -q "SuperchainConfig" "$ARTIFACT_FILE"; then
# Replace metadata version "1.1.1-beta.1" with "1.1.0" since SuperchainConfig was deployed with version "1.1.0" instead of "1.1.1-beta.1" (no other changes)
LOCAL_BYTECODE=$(echo "$LOCAL_BYTECODE" | sed 's/600c81526020017f312e312e312d626574612e31/600581526020017f312e312e3000000000000000/g')
fi
# Replace immutables with 0000
IMMUTABLES=$(jq -c '.deployedBytecode.immutableReferences' "$ARTIFACT_FILE")
replace_with_zeros() {
local BYTECODE=$1
local START=$2
local LENGTH=$3
local PREFIX=${BYTECODE:0:START}
local SUFFIX=${BYTECODE:START+LENGTH}
local ZEROS=$(printf '%*s' "$LENGTH" '' | tr ' ' '0')
echo "$PREFIX$ZEROS$SUFFIX"
}
if [ "$IMMUTABLES" != "null" ]; then
for entry in $(echo "$IMMUTABLES" | jq -c '.[] | .[]'); do
START=$(($(echo "$entry" | jq '.start * 2')))
LENGTH=$(($(echo "$entry" | jq '.length * 2')))
DEPLOYED_BYTECODE=$(replace_with_zeros "$DEPLOYED_BYTECODE" "$((START + 2))" "$LENGTH")
done
fi
# Now compare ignoring immutables and version diff
if [ "$DEPLOYED_BYTECODE" = "$LOCAL_BYTECODE" ]; then
echo "$ARTIFACT_FILE Success: Deployed bytecode matches local artifact (excluding immutables/version diff)."
else
echo "$ARTIFACT_FILE Mismatch: Bytecode differs beyond immutables/version diff."
echo "Deployed: $DEPLOYED_BYTECODE"
echo "Local: $LOCAL_BYTECODE"
fi
```
And make sure can be executed:
```bash theme={null}
chmod +x scripts/compare_bytecode.sh
```
Then to verify each contract:
```bash theme={null}
./scripts/compare_bytecode.sh 0xde47b113e4157ed15fa46c5572562ac11146c5ea forge-artifacts/L1CrossDomainMessenger.sol/L1CrossDomainMessenger.json
./scripts/compare_bytecode.sh 0x783A434532Ee94667979213af1711505E8bFE374 forge-artifacts/ProxyAdmin.sol/ProxyAdmin.json
./scripts/compare_bytecode.sh 0x55093104b76FAA602F9d6c35A5FFF576bE78d753 forge-artifacts/AddressManager.sol/AddressManager.json
./scripts/compare_bytecode.sh 0x693cfd911523ccae1a14ade2501ae4a0a463b446 forge-artifacts/CeloSuperchainConfig.sol/CeloSuperchainConfig.json
./scripts/compare_bytecode.sh 0x64fe3f9201e6534d2d744c7c57d134e709131a6e forge-artifacts/CeloTokenL1.sol/CeloTokenL1.0.8.15.json
./scripts/compare_bytecode.sh 0xe8b013bee7bd603e2f0b4825638559d645a4c4cb forge-artifacts/DisputeGameFactory.sol/DisputeGameFactory.json
./scripts/compare_bytecode.sh 0xde47b113e4157ed15fa46c5572562ac11146c5ea forge-artifacts/L1CrossDomainMessenger.sol/L1CrossDomainMessenger.json
./scripts/compare_bytecode.sh 0xad5d111e961a5e451c8172034115bcc0551b6551 forge-artifacts/L1ERC721Bridge.sol/L1ERC721Bridge.json
./scripts/compare_bytecode.sh 0x5e21245e97A7BB4733f72c412DcdDCED1f408587 forge-artifacts/L1StandardBridge.sol/L1StandardBridge.json
./scripts/compare_bytecode.sh 0xff53e1a6885b5a90b24327e13b04b95e2b97bd6c forge-artifacts/ProtocolVersions.sol/ProtocolVersions.json
./scripts/compare_bytecode.sh 0x6322C2f2D6a4305Fc033754d486A5A067Ee5F9b1 forge-artifacts/StorageSetter.sol/StorageSetter.json
./scripts/compare_bytecode.sh 0x7b5a84f818b6fc3f079ee87c214f369062188d2a forge-artifacts/SystemConfig.sol/SystemConfig.json
./scripts/compare_bytecode.sh 0x53c165169401764778f780a69701385eb0ff19b7 forge-artifacts/SuperchainConfig.sol/SuperchainConfig.json
./scripts/compare_bytecode.sh 0xfaB0F466955D87e596Ca87E20c505bB6470D0DC4 forge-artifacts/PreimageOracle.sol/PreimageOracle.json
./scripts/compare_bytecode.sh 0x8A12E1754f729C0856E2E32D4821577f0B245bfA forge-artifacts/Mips.sol/Mips.json
./scripts/compare_bytecode.sh 0xDFBB69681F217aB3221E94AFCA4fEa51f5c6a779 forge-artifacts/DelayedWETH.sol/DelayedWETH.json
./scripts/compare_bytecode.sh 0x3Da872782f9fB696fD72Af2ec9313a56bDA6f06d forge-artifacts/OptimismPortal2.sol/OptimismPortal2.json
```
## 3. Verify Contract are correctly configured
**Preliminary**. On a terminal set up RPC and Etherscan variables:
```bash theme={null}
export ETH_RPC_URL="https://mainnet.infura.io/v3/<>"
export ETHERSCAN_API_KEY="<>"
```
### 3.1 ProxyAdmin is owned by SystemOwnerSafe
```bash theme={null}
$ cast call 0x783A434532Ee94667979213af1711505E8bFE374 "owner() (address)"
0x4092A77bAF58fef0309452cEaCb09221e556E112
```
This mean every proxy is indirectly owned by SystemOwnerSafe
### 3.2 Check SystemConfigProxy is correctly configured
SystemConfigProxy is `0x89E31965D844a309231B1f17759Ccaf1b7c09861`
```bash theme={null}
# Check its owned by SystemOwnerSafe
$ cast call 0x89E31965D844a309231B1f17759Ccaf1b7c09861 "owner() (address)"
0x4092A77bAF58fef0309452cEaCb09221e556E112
# Check all bridge addresses are correctly configured
$ cast call 0x89E31965D844a309231B1f17759Ccaf1b7c09861 "l1CrossDomainMessenger() (address)"
0x1AC1181fc4e4F877963680587AEAa2C90D7EbB95
$ cast call 0x89E31965D844a309231B1f17759Ccaf1b7c09861 "l1ERC721Bridge() (address)"
0x3C519816C5BdC0a0199147594F83feD4F5847f13
$ cast call 0x89E31965D844a309231B1f17759Ccaf1b7c09861 "l1StandardBridge() (address)"
0x9C4955b92F34148dbcfDCD82e9c9eCe5CF2badfe
$ cast call 0x89E31965D844a309231B1f17759Ccaf1b7c09861 "optimismPortal() (address)"
0xc5c5D157928BDBD2ACf6d0777626b6C75a9EAEDC #should match the optimismPortalProxy
```
### 3.3 Check SuperChainConfig correctly configured
CeloSuperChainConfig is `0xa440975E5A6BB19Bc3Bee901d909BB24b0f43D33`
```bash theme={null}
#CeloSuperChainConfig managed by ProxyAdmin
$ cast call 0xa440975E5A6BB19Bc3Bee901d909BB24b0f43D33 "admin() (address)"
0x783A434532Ee94667979213af1711505E8bFE374
#CeloSuperChainConfig depends on OP SuperChainConfig
$ cast call 0xa440975E5A6BB19Bc3Bee901d909BB24b0f43D33 "superchainConfig() (address)"
0x95703e0982140D16f8ebA6d158FccEde42f04a4C
#OP's SuperChainConfig managed by their ProxyAdmin
$ cast call 0x95703e0982140D16f8ebA6d158FccEde42f04a4C "admin() (address)"
0x543bA4AADBAb8f9025686Bd03993043599c6fB04
#Bridge is not paused
cast call 0xa440975E5A6BB19Bc3Bee901d909BB24b0f43D33 "paused() (bool)"
false
#Guardian for SuperChain Bridge Status is a address controlled by cLabs
$ cast call 0xa440975E5A6BB19Bc3Bee901d909BB24b0f43D33 "guardian() (address)"
0x6E226fa22e5F19363d231D3FA048aaBa73CC1f47
```
### 3.4 Bridge Contracts are correctly configured
Bridge Contracts:
* L1CrossDomainMessengerProxy `0x1AC1181fc4e4F877963680587AEAa2C90D7EbB95`
* L1ERC721BridgeProxy `0x3C519816C5BdC0a0199147594F83feD4F5847f13`
* L1StandardBridgeProxy `0x9C4955b92F34148dbcfDCD82e9c9eCe5CF2badfe`
* OptimismPortalProxy `0xc5c5D157928BDBD2ACf6d0777626b6C75a9EAEDC`
* OptimismPortal2 `0x3Da872782f9fB696fD72Af2ec9313a56bDA6f06d`
Note: L1CrossDomainMessengerProxy is old kind of proxy that depends on AddressManager, it does not have an owner that can be queried.
```bash theme={null}
# Check L1ERC721BridgeProxy is owned by ProxyAdmin
$ cast call 0x3C519816C5BdC0a0199147594F83feD4F5847f13 "admin() (address)"
0x783A434532Ee94667979213af1711505E8bFE374
# Check it uses the right SuperChainConfig
$ cast call 0x3C519816C5BdC0a0199147594F83feD4F5847f13 "superchainConfig() (address)"
0xa440975E5A6BB19Bc3Bee901d909BB24b0f43D33
# Check L1StandardBridgeProxy is owned by ProxyAdmin
# The L1StandardBridgeProxy uses a L1ChugSplashProxy
# To check the owner one must check the storage key 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103
$ cast storage 0x9C4955b92F34148dbcfDCD82e9c9eCe5CF2badfe 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103
0x000000000000000000000000783a434532ee94667979213af1711505e8bfe374
$ cast parse-bytes32-address 0x000000000000000000000000783a434532ee94667979213af1711505e8bfe374
0x783A434532Ee94667979213af1711505E8bFE374
# Check it uses the right SuperChainConfig
$ cast call 0x9C4955b92F34148dbcfDCD82e9c9eCe5CF2badfe "superchainConfig() (address)"
0xa440975E5A6BB19Bc3Bee901d909BB24b0f43D33
# Check it uses the right SystemConfig
$ cast call 0x9C4955b92F34148dbcfDCD82e9c9eCe5CF2badfe "systemConfig() (address)"
0x89E31965D844a309231B1f17759Ccaf1b7c09861
# Check OptimismPortalProxy is managed by ProxyAdmin
$ cast call 0xc5c5D157928BDBD2ACf6d0777626b6C75a9EAEDC "admin() (address)"
0x783A434532Ee94667979213af1711505E8bFE374
# Check it points to OptimismPortal2
$ cast call 0xc5c5D157928BDBD2ACf6d0777626b6C75a9EAEDC "implementation() (address)"
0x3Da872782f9fB696fD72Af2ec9313a56bDA6f06d
# Check it has a 7 days delay window
$ cast call 0xc5c5D157928BDBD2ACf6d0777626b6C75a9EAEDC "proofMaturityDelaySeconds() (uint256)"
604800
# Check it uses the right SuperChainConfig
$ cast call 0xc5c5D157928BDBD2ACf6d0777626b6C75a9EAEDC "superchainConfig() (address)"
0xa440975E5A6BB19Bc3Bee901d909BB24b0f43D33
# Check it uses the right SystemConfig
$ cast call 0xc5c5D157928BDBD2ACf6d0777626b6C75a9EAEDC "systemConfig() (address)"
0x89E31965D844a309231B1f17759Ccaf1b7c09861
# Check is has a cLabs Managed Account as guardian
$ cast call 0xc5c5D157928BDBD2ACf6d0777626b6C75a9EAEDC "guardian() (address)"
0x6E226fa22e5F19363d231D3FA048aaBa73CC1f47
```
## 4 Verify CELO L1 Token is correctly deployed
Start by checking on `SystemConfig` that customGasToken is enabled and pointing to CELO ERC20
```bash theme={null}
# Check custom gas token is enabled
$ cast call 0x89E31965D844a309231B1f17759Ccaf1b7c09861 "isCustomGasToken() (bool)"
true
# Check ERC20 Address points to CELO with right number of decimals
cast call 0x89E31965D844a309231B1f17759Ccaf1b7c09861 "gasPayingToken() (address,uint8)"
0x057898f3C43F129a17517B9056D23851F124b19f
18
# Check the symbol
cast call 0x89E31965D844a309231B1f17759Ccaf1b7c09861 "gasPayingTokenSymbol() (string)"
"CELO"
```
Check the ERC20 has correct ownership and all supply is locked on the bridge
```bash theme={null}
# CELO is implemented as a proxy managed by the ProxyAdmin
$ cast call 0x057898f3C43F129a17517B9056D23851F124b19f "admin() (address)"
0x783A434532Ee94667979213af1711505E8bFE374
# check the totalSupply is 1Billion
$ cast call 0x057898f3C43F129a17517B9056D23851F124b19f "totalSupply() (uint256)"
1000000000000000000000000000 [1e27]
# 1e27 / 1e18 = 1e9 = 1billion CELO
# check balance of OptimismPortalProxy to be total supply (only true before first withdrawal on Celo L2)
$ cast call 0x057898f3C43F129a17517B9056D23851F124b19f "balanceOf(address) (uint256)" 0xc5c5D157928BDBD2ACf6d0777626b6C75a9EAEDC
1000000000000000000000000000 [1e27]
```
## 5. Verifying SecurityCouncil Configuration
Based on [this forum post](https://forum.celo.org/t/proposing-celo-l2s-security-council/10578), tied to [CGP-171](https://mondo.celo.org/governance/cgp-171); the security council is a 2/2 multisig whose members are a cLabsMultisig and "Celo Community Security Council"
### 5.1 Verify the SystemOwnerSafe multisig
During migration, this will be a 1/3 multisig, later becomes a 2/2. The third member is a cLabs managed account used during migraiton
```bash theme={null}
# Check members
$ cast call 0x4092A77bAF58fef0309452cEaCb09221e556E112 "getOwners()(address[])"
[0xC03172263409584f7860C25B6eB4985f0f6F4636, 0x9Eb44Da23433b5cAA1c87e35594D15FcEb08D34d, 0xbcA67eE5188efc419c42C91156EcC888b20664f3]
# Check threshold
$ cast call 0x4092A77bAF58fef0309452cEaCb09221e556E112 "getThreshold()(uint256)"
1
```
### 5.2 Verify the cLabs Multisig
cLabs Multisig is a 6/8 multisig, and is a member of the SystemOwnerSafe multisig
```bash theme={null}
# Check members
$ cast call 0x9Eb44Da23433b5cAA1c87e35594D15FcEb08D34d "getOwners()(address[])"
[0x0Bd06B2b192BD9eC316f2880A0c296D9Bc3225e0, 0x21e595451bDD69a85cf946f37f5A6A356C3F875D, 0x09c0B069100F5d880a596605b94Cc9493D96e797, 0x326b764CEb4FE11e70af538D3CB997Bb2e16659d, 0x48139512241D32047760E7481eBf0b6BF3390f8F, 0x4D89adf3a4a71b25FB1a6D702Cf059CF5BebD02d, 0x8b4b85f78F799F8364198FFEd2266d3cb3EA0daE, 0xE0024dCadff414fCb0AAfBB475e92Ccc367E1A84]
# Check threshold
$ cast call 0x9Eb44Da23433b5cAA1c87e35594D15FcEb08D34d "getThreshold()(uint256)"
6
```
### 5.3 Verify the Celo Community Security Council
Celo Community Security Council is a 6/8 multisig, and is a member of the SystemOwnerSafe multisig
```bash theme={null}
# Check members
$ cast call 0xC03172263409584f7860C25B6eB4985f0f6F4636 "getOwners()(address[])"
[0xB963047c5D875b7FE777339B1E6B61ac4df1f3e2, 0x6FDb3eA186981aA32DD8e7B782d95733Ca3c13A1, 0xd0cE4D055d04bDA69b20815A3F796019bB68c6Db, 0x148dfaC5dF51Ab1D7b02a3B53f1e2Da1F0A6B5Ca, 0x5f70938aA8d2fd91EE3959998E5DdaACFb6Ffb85, 0xD1C635987B6Aa287361d08C6461491Fa9df087f2, 0x2BE5E223E368E8c0f404a1f3Eb4eB09f99C8FaD8, 0xc3E966E79eF1aA4751221F55fB8A36589C24C0cA]
# Check threshold
$ cast call 0xC03172263409584f7860C25B6eB4985f0f6F4636 "getThreshold()(uint256)"
6
```
# L1 to L2 Migration
Source: https://docs.celo.org/specs/l2-migration
The switch from the Celo L1 blockchain to the Celo L2 introduces a variety of changes, most of which are not visible to the majority of developers and even less to the end users. However, tool developers, infrastructure operators and some developers will have to take a few of these changes into account. This page contains all information to check if this is the case for you or not.
## Changes for Contracts Developers
* [Removed precompiles](/specs/smart-contract-updates-from-l1#precompiles-deprecation) (all except the `transfer` precompile)
* During the migration the following hardforks are enabled:
* [Berlin](https://github.com/ethereum/execution-specs/blob/mainnet/src/ethereum/forks/berlin/__init__.py)
* [London](https://github.com/ethereum/execution-specs/blob/mainnet/src/ethereum/forks/london/__init__.py)
* [Arrow Glacier](https://github.com/ethereum/execution-specs/blob/mainnet/src/ethereum/forks/arrow_glacier/__init__.py)
* [Gray Glacier](https://github.com/ethereum/execution-specs/blob/mainnet/src/ethereum/forks/gray_glacier/__init__.py)
* [Shanghai](https://github.com/ethereum/execution-specs/blob/mainnet/src/ethereum/forks/shanghai/__init__.py)
* [Cancun](https://github.com/ethereum/execution-specs/blob/mainnet/src/ethereum/forks/cancun/__init__.py)
* The following Optimism specific hardforks are enabled:
* [Canyon](https://specs.optimism.io/protocol/canyon/overview.html)
* [Delta](https://specs.optimism.io/protocol/delta/overview.html)
* [Ecotone](https://specs.optimism.io/protocol/ecotone/overview.html)
* [Fjord](https://specs.optimism.io/fjord/overview.html)
* Notably, this hardfork also enables the [`P256VERIFY`](https://specs.optimism.io/protocol/precompiles.html#p256verify) precompile, which performs signature verification for the secp256r1 elliptic curve. This curve has widespread adoption. It's used by Passkeys, Apple Secure Enclave and many other systems.
* [Granite](https://specs.optimism.io/protocol/granite/overview.html)
### Precompile Deprecation and Epoch Management
As part of Celo's transition to a L2 network, the following Celo precompiles, except the `Transfer` precompile, will be deprecated.
* `FRACTION_MUL`
* `PROOF_OF_POSSESSION`
* `GET_VALIDATOR`
* `NUMBER_VALIDATORS`
* `EPOCH_SIZE`
* `BLOCK_NUMBER_FROM_HEADER`
* `HASH_HEADER`
* `GET_PARENT_SEAL_BITMAP`
* `GET_VERIFIED_SEAL_BITMAP`
This means that the geth client is no longer responsible for processing epochs. Instead, processing of epochs, rewards distribution and storage of currently elected validators is now handled by the `EpochManager` contract.
Any contract supporting the use of precompiles will now revert on Celo as a L2. This includes the `UsingPrecompiles` contract. More details [here](https://github.com/celo-org/celo-monorepo/blob/release/core-contracts/12/packages/protocol/contracts/common/UsingPrecompiles.sol)
To keep costs of processing epochs low, only the following key functions (used for querying the current epoch or elected validators) have been ported over to the `EpochManager` contract.
* `getEpochNumberOfBlock(uint256)`
* `getEpochNumber()`
* `validatorSignerAddressFromCurrentSet()`
* `numberValidatorsInCurrentSet()`
Read more on new [epoch management and reward distribution](/specs/smart-contract-updates-from-l1#epochs-and-rewards) or [deprecated precompiles](/specs/smart-contract-updates-from-l1#precompiles-deprecation).
### FeeCurrencyDirectory
We introduced a new contract, `FeeCurrencyDirectory`, which is responsible for managing the fee currencies used in the Celo network. This contract is replacement for `FeeCurrencyWhitelist` and keeps track of ERC-20 tokens that can be used as gas currencies on Celo network with additional setup of intrinsic gas cost of transactions for these fee currencies.
### FeeCurrencyWhitelist
The `FeeCurrencyWhitelist` contract has been replaced by the `FeeCurrencyDirectory` contract.
### Deactivated Random Contract
The `Random` core contract has been deactivated. The [EIP-4399](https://eips.ethereum.org/EIPS/eip-4399) `PREVRANDAO` opcode provide some pseudo-randomness now. Please be aware of the limitations mentioned in the EIP, as well as the following OP Stack specific limitations:
* The randao value is read from the L1, it is known a longer time in advance.
* Since multiple L2 blocks are derived from the same L1 block, the `PREVRANDAO` value will not change with every L2 block, but only with the L1 block.
### Deactivated BlockchainParameters Contract
The `BlockchainParameters` core contract has been deactivated.
The `blockGasLimit` can now be found by querying the Optimism L1 `SystemConfig` contract and calling the `gasLimit()` getter.
The `intrinsicGasForAlternativeFeeCurrency` can now be found by querying the [FeeCurrencyDirectory contract](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts-0.8/common/FeeCurrencyDirectory.sol) function `getCurrencyConfig(token).intrinsicGas`.
### Updated Governance Hotfix
The Governance Hotfix process has undergone several changes due to the absence of validators on L2, now using a multisig approach. Here’s a detailed explanation of these changes:
#### Original Hotfix Process
Previously, the hotfix process relied heavily on a set of validators:
1. **Validator Approval**: A byzantine quorum of validators was needed to whitelist a hotfix. Validators had financial incentives to act in the network's best interest, ensuring that any approved hotfix had been vetted by a trustworthy group.
2. **Dynamic Validator Set**: The list of validators who approved the hotfix changed with each epoch. This dynamic nature made it difficult for validators to collude and approve a malicious hotfix.
3. **Epoch-Dependent**: If a hotfix was not executed within the same epoch it was approved, it needed to be reapproved by the new set of validators in the next epoch.
4. **Prepare Step**: The hotfix required a "prepare" step, ensuring that the current set of validators had approved the hotfix before it could be executed.
#### Updated Hotfix Process
Due to the absence of validators on L2, the process now incorporates a multisig approach:
1. **Multisig Approval**: The new process requires the approval of an approver multisig, but now also includes the Security Council multisig.
2. **Fixed Signers**: Unlike the previous dynamic set of validators, the list of Security Council signers remains fixed. This change simplifies the approval process but also increases the risk of collusion among the fixed set of signers.
3. **Execution Time Limit**: If a hotfix is not executed within the specified `executionTimeLimit`, it must be reset and re-approved. This keeps the time constraint but no longer depends on epoch changes.
4. **Collusion Risk**: The fixed list of Security Council signers introduces a new risk factor. Without clear incentives for the signers to act in the network's best interest, there is a higher risk of collusion and the potential for malicious hotfixes being approved.
## Changes for JSON-RPC Users
### Removed Tx Types
New transactions can't be submitted using the following transaction types, see also the [tx types page](/specs/transaction-types):
* Celo legacy tx
* CIP-42
Information about existing transactions of these types can still be retrieved via RPC.
### Block and Tx changes in RPC Responses
To match the Ethereum and OP-Stack responses more closely, the RPC responses for historical blocks and transactions have been updated.
The following examples show the difference between the old (Celo L1) and the new (Celo L2) responses.
#### Blocks
##### Pre Gingerbread Block
The new representation will lack the no longer needed `randomness` and `epochSnarkData` fields and gain `sha3Uncles`, `uncles`, `mixHash` and `nonce`.
The choice was taken to add `sha3Uncles`, `uncles`, `mixHash` and `nonce` even though they have zero values or are empty, in order to align better with the
ethereum block structure and increase compatibility with ethereum tooling. For example foundry's cast does not support fetching blocks that lack `sha3Uncles`.
The `extraData` does not include the validator signatures ("Istanbul aggregated seal") anymore. That data has never been included when calculating the block hash, so removing it from the response makes it easier to reproduce the block hash.
Note that the `size` will be different because of the missing `epochSnarkData` and `randomness` fields and also the underlying RLP datastructure in CeL2 differs from the RLP datastructure in Celo.
```diff theme={null}
{
+ "baseFeePerGas": "0x5f5e100",
"difficulty": "0x0",
- "epochSnarkData": null,
- "extraData": "0xd983010000846765746889676f312e31332e3130856c696e7578000000000000f8b6c0c080b841d97776193d6a3e3bf8319a47ac44e4489212e02a584035f58adb153e1da2a49215bdf6983d8b08c53e22dbe776fb489063eaf3a4e581d9c124b1745154ec875e01f78427da3f2fb01b4d9a10b3ff2c620b0b5dc4e3fbee3210c082012524fe8347e8369943ab5d68b43d1874af789493e974eb43bd47698180f7843fffffffb0aa91da2fe7d6b89d3e7c5f8d812c9e20f4dde29404975a5a4d68476c2cb0ff5500788d239a8729413c3adb43d9fb878180",
+ "extraData": "0xd983010000846765746889676f312e31332e3130856c696e7578000000000000f882c0c080b841d97776193d6a3e3bf8319a47ac44e4489212e02a584035f58adb153e1da2a49215bdf6983d8b08c53e22dbe776fb489063eaf3a4e581d9c124b1745154ec875e01c3808080f7843fffffffb0aa91da2fe7d6b89d3e7c5f8d812c9e20f4dde29404975a5a4d68476c2cb0ff5500788d239a8729413c3adb43d9fb878180",
"gasLimit": "0x989680",
"gasUsed": "0x9a972",
"hash": "0x4ef93291167de948057e6644016b4270aa922a04ae97f37ea471852cc13046e0",
"logsBloom": "0x00000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000010000000400000000000000000000000000000000100000000000000000000000000080000000008000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000080000000000000000000008000000000000001000000000000000000010000000000000000000080000000000000000000000000000000000000000000000",
"miner": "0xef0186b8eda17be7d1230eeb8389fa85e157e1fb",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
"number": "0xb8d",
"parentHash": "0x48e4a4ba167e5b9a9af46b07882cac5d514b3d38bfec5f8f0cf09bc50c574876",
- "randomness": {
- "committed": "0x3654af1e4c47b230e06c37f3f49163f1ae3284b127d977bcadae6c8b809df86c",
- "revealed": "0xeec3298014c360628da382013379c53b58b339a89bb4c1437db7446250472f57"
- },
"receiptsRoot": "0xffc520613572e5e655a13b5bb74a0dabcc4e5fc132cce6c193d1f9c419eb05f5",
+ "sha3Uncles": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "size": "0xea0",
+ "size": "0xe26",
"stateRoot": "0x57f9dd4504d6142b099da5b0e7a8b1fc911af9293a48cdd0750111d7c19ed943",
"timestamp": "0x5ef3ab5e",
"totalDifficulty": "0xb8e",
"transactions": [
"0xea2d6ace4848a91065f029f2cf403d6d3c4a3835ca3cb7e9f3c943f00cbfa759"
],
"transactionsRoot": "0xbb3c1f1fe49abff6b98de7b3629fa1d94ad1fa01f2b0c85e22e4f69c419e5dfe",
+ "uncles": []
}
```
##### Post Gingerbread, Pre CeL2 Block
In this case, the new representation will lack the no longer needed `randomness` and `epochSnarkData` fields.
The `extraData` does not include the validator signatures ("Istanbul aggregated seal") anymore. That data has never been included when calculating the block hash, so removing it from the response makes it easier to reproduce the block hash.
Note that the `size` will be different because of the missing `epochSnarkData` and `randomness` fields and also the underlying RLP datastructure in CeL2 differs from the RLP datastructure in Celo.
```diff theme={null}
{
"baseFeePerGas": "0x12a05f200",
"difficulty": "0x0",
- "epochSnarkData": null,
- "extraData": "0xd983010804846765746889676f312e31392e3133856c696e7578000000000000f8b2c0c080b8412ba9e02862ac252968922b40998bf81ad3365573eb1022d6299fb4fc0556258d62369eaa1dbefa22537d78d1be4a75bdb182d7dd36d314ab13ac9933a3ae657b01f58202f9b0b125dcff9f90b02acffcd7a2a2c1b5855bcaea233aac4242659dbf217e23cd72a43626efc0f145191fdf298734c53f8080f58203ffb09fe8e166bcd22854dece60b93a2e59eb964778647fb5ba375386c9051f009b394aa46be3e039dbd78b9fa6e7e048d78080",
+ "extraData": "0xd983010804846765746889676f312e31392e3133856c696e7578000000000000f880c0c080b8412ba9e02862ac252968922b40998bf81ad3365573eb1022d6299fb4fc0556258d62369eaa1dbefa22537d78d1be4a75bdb182d7dd36d314ab13ac9933a3ae657b01c3808080f58203ffb09fe8e166bcd22854dece60b93a2e59eb964778647fb5ba375386c9051f009b394aa46be3e039dbd78b9fa6e7e048d78080",
"gasLimit": "0x2160ec0",
"gasUsed": "0x4468e",
"hash": "0x9374dd975e7a59cdf89e4fb1f6e75b168a5d5d95c2ce1c11209578a7561ef1bd",
"logsBloom": "0x00800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000040000000000000002000000000000000000000000000100000000000004000000000000000000000000000000000000000000000000008000000000000000400000000000000000000000000000000000400000000000000000000000000000000000000000000000000000800000000000000000008000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0xa910ffc6294e96c6a7cac175621d4b1991f53120",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0x186f055",
"parentHash": "0x6fd1b8122bbbdcab8ec82e44397929ab164584dce061d50f657d6f21962fd13a",
- "randomness": {
- "committed": "0xafb35e688710867bef9bf982ecff9cdbd9e8c19a687fa9bb2bdbb9341b79b237",
- "revealed": "0x6d6c35073bc7bee1f037c1f8225a4fbffbfdcf978c6af85c56f3e7b4a0ecf0f1"
- },
"receiptsRoot": "0xf6193f8bea9c51a5ec6f65e644d3bc30df7414d08914b17f3543e0463aee4abb",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "size": "0x418",
+ "size": "0x3a0",
"stateRoot": "0x4ce545e412947838ab85b0e560b339cc4a903dc3b0364ee39d382c04a79c4df4",
"timestamp": "0x66babd40",
"totalDifficulty": "0x186f056",
"transactions": [
"0xafb85e106fceea010ed9b1f9f50fbbdcfa4308f3a398aa4f31d35370e9cea300"
],
"transactionsRoot": "0x392de6ef9cfb6047bad717b943c6397666c1cca2321c3d9fadd76ceaca0d1e57",
"uncles": []
}
```
##### Post Cel2 Block
Since the blocks after the migration are not available in a Celo L1 node, we can't show the diff between the response of a Celo L1 and a Celo L2 node. Instead, the following is a fictional diff between an L1 block right before the L2 migration and the same block if it was an L2 block instead. This illustrates the following changes for new blocks after the migration:
* The `extraData` field is empty
* `mixHash` is used to provide pseudo-randomness for the `PREVRANDAO` opcode and is not empty anymore
* `parentBeaconBlockRoot` field added
* `totalDifficulty` removed
* `withdrawals` and `withdrawalsRoot` fields added
Note that `withdrawals` will be empty for the foreseeable future, because there is no staking mechanism or beacon chain in the celo L2.
```diff theme={null}
{
"baseFeePerGas": "0x5d21dba00",
"blobGasUsed": "0x0",
"difficulty": "0x0",
"excessBlobGas": "0x0",
- "extraData": "0xd983010804846765746889676f312e31392e3133856c696e7578000000000000f880c0c080b8412ba9e02862ac252968922b40998bf81ad3365573eb1022d6299fb4fc0556258d62369eaa1dbefa22537d78d1be4a75bdb182d7dd36d314ab13ac9933a3ae657b01c3808080f58203ffb09fe8e166bcd22854dece60b93a2e59eb964778647fb5ba375386c9051f009b394aa46be3e039dbd78b9fa6e7e048d78080",
+ "extraData": "0x",
"gasLimit": "0x1c9c380",
"gasUsed": "0xaaee",
"hash": "0xa2f404d653c22969acb3785db12df02604c2f6bc767f22b2c4ff8662f03ba305",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x4200000000000000000000000000000000000011",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "mixHash": "0x08229a0e20d3896f829595d4e5c9eece4279ba7e45e38b492a3d99003c47c32b",
"nonce": "0x0000000000000000",
"number": "0x2549326",
+ "parentBeaconBlockRoot": "0x7606b339839b9ab700cfadc9cb0b105d33388f4f2755c2c7c7168af0c37a429f",
"parentHash": "0x914bda6eb9cb5866fa76607df3483d442f5d28d517245f592780aaf0ab2c6065",
"receiptsRoot": "0x766157eaef643639c1b76e03f157ffdd1ec6c7583ee2c85561916161ac964e3e",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x34c",
"stateRoot": "0x4723c7d986d7e7bb91818048b5ebcb64101db4395d9401d6a25901808ff33816",
"timestamp": "0x67b717df",
- "totalDifficulty": "0x186f056",
"transactions": [
"0x246cb5812aab652a205e5d05145cdc8a5bbaa5d8e1eeae9fef43397c011666d9"
],
"transactionsRoot": "0x8ef09de185b4ae02e2c42fe9b8dc1ff58fff9dffd91a8940197374005ccba057",
"uncles": [],
+ "withdrawals": [],
+ "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
}
```
#### Transactions
See [this page](/home/protocol/transactions/transaction-types#summary) for a summary of transaction types in Celo.
At genesis, type 0 transactions on Celo contained 3 extra fields compared to Ethereum. Those were `feeCurrency`, `gatewayFee` and `gatewayFeeRecipient`. These extra fields rendered Celo transactions incompatible with any existing Ethereum wallets. To mitigate this and allow use of existing ethereum wallets we extended the definition of type 0 transactions to support the original ethereum transaction format (i.e. without the 3 extra fields).
Since it was valid for the celo type 0 transaction to not set the three extra fields in order to distinguish between the two forms of type 0 transaction an extra field (`ethCompatible`) was added to RPC API responses for type 0 transactions.
Historically, we would return these 3 extra fields and `ethCompatible` on RPC API responses for all transaction types. But this was leading to some confusion since those fields were only relevant for some transaction types.
In CeL2, we have updated the RPC API to omit the `feeCurrency`, `gatewayFee` and `gatewayFeeRecipient` fields when `ethCompatible` is true, meaning that ethereum compatible transactions should have no additional fields.
In addition to the previous data, the CeL2 node will return `yParity` for all non 0 transaction types.
##### Type 0 Eth Compatible
```diff theme={null}
{
"blockHash": "0x06613bb2a5c75748035e20c06c577669cd4d78f9a1d36ae79eb26ce72dda9c18",
"blockNumber": "0x16b8f4a",
- "ethCompatible": true,
"chainId": "0xaef3",
"from": "0x994532b8f186949d7217d7b843509c19e78b9584",
"gas": "0xa5c6",
"gasPrice": "0x2540be400",
- "gatewayFee": "0x0",
"hash": "0xe152376f4b2d3a81f3631cf5830fb820118de3cb3ef5ddb068978829c2712b08",
"input": "0x3798c7f2000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000066318fd2000000000000000000000000000000000000000000000000000000000160543a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000345555200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000003f8e3083",
"nonce": "0x2b714",
"r": "0x1cbba1e5b0c6d9155a56f7f690d59ca46a7deab2bc6aefa4fe89542dbc779c5f",
"s": "0x66aff5220a9228352bee2a7ac07e9c723bc6bc00311d02338d15ed106b07a608",
"to": "0x3d00dea966314e47ac3d4acd2f00121351cec1c5",
"transactionIndex": "0x0",
"type": "0x0",
"v": "0x15e09",
"value": "0x0"
}
```
##### Type 0 Not Eth Compatible With No Fee Currency And Gateway Fee Recipeint
```diff theme={null}
{
"blockHash": "0x11d497cf96f94c62db173e27a9aebe7db559d9675e58a9ac268c5c934bffe441",
"blockNumber": "0x16b8efc",
"chainId": "0xaef3",
"ethCompatible": false,
"from": "0x473a3be7c2a42452ed0b521614b3b76bc59d2d1d",
"gas": "0x8160d",
"gasPrice": "0x1bf08eb00",
"gatewayFee": "0x0",
"hash": "0x6ba6fb0f75a38112bada3a8d3e789d9a5fdce4ea11f35a7ef8b550bcc356d202",
"input": "0x80e50744000000000000000000000000874069fa1eb16d44d622f2e0ca25eea172369bc1000000000000000000000000000000000000000000009fc8476fe32ad9dd7cd0000000000000000000000000dd5cb02066fde415dda4f04ee53fbb652066afee0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x72ce1",
"r": "0x28ec2e7d544ad737ce7ee4c7d756f00335a764451b5036b44a5bd06cf50262af",
"s": "0x1d62168d50945e7457d74c095ccca0fbcafb6e5f86d30d1725fad089d1a4c435",
"to": "0xfdd8bd58115ffbf04e47411c1d228ecc45e93075",
"transactionIndex": "0x0",
"type": "0x0",
"v": "0x15e0a",
"value": "0x0"
}
```
##### Type 0 Not Eth Compatible With Fee Currency
```diff theme={null}
{
"blockHash": "0x3cd3ee79cd8e1a97e8979ee4d896256a5e369d6c7e3f66e631c8387f561bbbe8",
"blockNumber": "0x16b8ef1",
"chainId": "0xaef3",
"ethCompatible": false,
"feeCurrency": "0x874069fa1eb16d44d622f2e0ca25eea172369bc1",
"from": "0x0ac70692e0146522dd89dbf99831beaddcd57e8c",
"gas": "0x31e9e",
"gasPrice": "0x464abf343",
"gatewayFee": "0x0",
"hash": "0x86ba696a70eaf0f973313b0877f611f6500d9673eb51952a4a99c3200af0d249",
"input": "0xe1d6aceb000000000000000000000000e5f5363e31351c38ac82dbadead91fd5a7b08846000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x1",
"r": "0xb3fdfa10b8faaf1642e7e6e7c04f8e1d3051e61a4e79c4da1bb1f112e72607d2",
"s": "0x6114be273d1dcb45e485a8f7731666e3c36bfde385c8b47439c92b92d8ceb47f",
"to": "0x874069fa1eb16d44d622f2e0ca25eea172369bc1",
"transactionIndex": "0x0",
"type": "0x0",
"v": "0x15e09",
"value": "0x0"
}
```
##### Type 2 (dynamic fee transaction)
```diff theme={null}
{
"accessList": [],
"blockHash": "0x5b77a681e7ff2fc015e074ece54877c50a6ed1e093cc76aabb109846e4544420",
"blockNumber": "0x16b8f3f",
"chainId": "0xaef3",
"from": "0x48cc4c4133cbf40def64b95b002d4ee4d24df846",
"gas": "0x1ff04",
"gasPrice": "0x1a13b8600",
- "gatewayFee": "0x0",
"hash": "0x169500202b491733092159a496f535a9364f69d4059b9b26f39ea8896364ab26",
"input": "0xa87a20ce0000000000000000000000000000000000000000000000000000000000000068",
"maxFeePerGas": "0x1dcd65000",
"maxPriorityFeePerGas": "0x77359400",
"nonce": "0x6779",
"r": "0xe76c97eb3184a45d96563bfeca470e9c5f4410f6815a81e1df42ecc2f84d9f7c",
"s": "0x550fede7177a20024a76cc02dc5fbd6cdefa163ff861441cd9617afceee824",
"to": "0x4330b35a355c24ac8e544ade2d531050b5b9be7b",
"transactionIndex": "0x0",
"type": "0x2",
"v": "0x1",
"value": "0x0",
"yParity": "0x1"
}
```
##### Type 123 (Celo dynamic fee transaction v2)
```diff theme={null}
{
"accessList": [],
"blockHash": "0x9abe488547e2e3195dc6e69fbf7e378056f98b3608b69309ef99c358a825cf37",
"blockNumber": "0x16b8f03",
"chainId": "0xaef3",
"feeCurrency": "0x874069fa1eb16d44d622f2e0ca25eea172369bc1",
"from": "0x06502700eac7123676a7332ba2015dffba021af6",
"gas": "0x1ec78",
"gasPrice": null,
- "gatewayFee": "0x0",
"hash": "0xbe98d102295d6a5c7a26487a6ed7a5d2278cc30c2c8fb065f46bb78a6258090e",
"input": "0xe1d6aceb0000000000000000000000005fe1407f47b1310ff232a8d368b36099eff61604000000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001cc4242484b6e2f42695479437171736a47646f6a686c687631456654617035786177577453447476412f784172695a6d7557774b6f6273735a6344356b4c414f7141436965737474516732616c4e7a6d68673866714f776a5651483761513273594968482b6f4d384669486364746768304e4f6a6e2b59365345306c434c62695a7a6a667143763277426878636834524634384d6639446530436a4e2b65704e4f52414431622f544d4d682b47424e4472736a3642724e43506f6c3432366375424f6273383578633378704938632f7144576c526f554d6c4456774c4370446a79505578746c2b4b515170415a70567a414a664d783867635257727a505936546644545554374b4b3954444979783461657558576a50765776442f46584b72414f546e6f394c3050427061582b7162734d3147394e2b39497274426133486476566f396b5744364454622f567767727752636d4b41656970416551346a6c415850556979376656623373324c5839655462626937654a2b514e616c78314d75522f4d38554f3178756547793330474c672b71695370434c4451626167314d74576565555645625269517a4b58484c6f4348704f357a4a6f4b2f5a50452b635558392f44354479513258557a453d0000000000000000000000000000000000000000",
"maxFeePerGas": "0x21b83c7d5",
"maxPriorityFeePerGas": "0x59eb4bf9",
"nonce": "0x1f9b",
"r": "0x68940dd91c0574638344927b53015752c78bc9cf67387f0d0c1f6d22559eeec3",
"s": "0x412aa02bd215cd0353dd1ffa1f99bbe2ee218e9e7ae3c5b462a568b705534f46",
"to": "0x874069fa1eb16d44d622f2e0ca25eea172369bc1",
"transactionIndex": "0x1",
"type": "0x7b",
"v": "0x1",
"value": "0x0",
+ "yParity": "0x1"
}
```
## State Changes during the Migration
The migration is the process of converting the Celo L1 chain into an L2 based on Ethereum.
This migration involves different steps and requires the blockchain to shortly pause block production.
During the migration the following things are done:
* Historic blockchain data such as blocks, headers and transactions are transformed into a version readable by the updated execution client. During this process some data, such as data required for the Istanbul consensus algorithm, is removed as it is no longer required.
* OP Stack L2 contracts are deployed.
* The new Celo unreleased treasury core contract is initialized.
### Historical data migration
Celo started as a fork of `go-ethereum` but initially some significant changes to the structure of headers and blocks were made because it was operating with a Proof of Stake consensus mechanism.
At the outset Celo blocks lacked the following fields that Ethereum blocks had:
* `sha3Uncles`
* `uncles`
* `difficulty`
* `gasLimit` (the `gasLimit` was defined by a contract and so had to be retrieved from state)
* `mixHash`
* `nonce`
Later in the [Espresso hardfork](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0041.md), dynamic fee transactions were introduced. Instead of relying on the `baseFeePerGas` field on the block header, the `baseFeePerGas` was also retrieved from state via a contract call similar to `gasLimit`.
In the [Gingerbread hardfork](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0062.md) (block `21616000`) all the fields listed above plus `baseFeePerGas` were added to the internal block representation to bring future blocks into alignment with Ethereum.
A constant difficulty field of `0x0` was added to all pre-Gingerbread RPC API block responses.
Celo added the following fields to block bodies:
* `randomness`
* `epochSnarkData`
As additions they do not damage compatibility at the RPC API level as API clients would generally ignore them. However, in the transition to L2 these fields are planned for removal because they will no longer be needed.
In the transition to L2 as an attempt to improve the situation with RPC API compatibility for historical blocks, all post-Gingerbread fields will be returned for **all** blocks.
Both pre-Gingerbread and post-Gingerbread blocks retrieved from the L2 RPC API would look the same with the exception of `baseFeePerGas` which for now will not be returned for pre-Gingerbread blocks.
#### L2 Block Structure
Going forward, blocks occurring after the transition point will gain an extra field, `parentBeaconBlockRoot`, which will bring our block structure fully up to date with Ethereum’s block structure.
As Ethereum evolves in the time before we make the transition to L2 we could end up with additional fields being added to the L2 Block Structure, and this document will be updated accordingly.
### State migration
The OP stack requires a number of contracts to be available on the L2. Those contracts have predefined addresses and cannot be deployed like normal contracts. Instead they are written to the state during the migration.
As this process touches the blockchain state, it is important that it is transparent and can be verified by every node operator and user. Therefore, every node operator can do the migration locally and check the resulting state against Celo L2 state.
#### OP predeploys
The predeploys to be added to the state are supplied in form of an allocation file which contains a mapping of account addresses to their state. In the state migration tool this file is read and every account copied into the Celo L1 state.
There's a number of checks to make sure this doesn't end up causing problems.
* If an account to be written to the state already has a balance, this balance is added to the copied account balance. This makes sure the total amount of Celo doesn't change.
* If an account already contains code, it is checked that the code is the same.
#### `CeloUnreleasedTreasury` set up
The `CeloUnreleasedTreasury` is a new contract available on the migrated Celo L2. See [the spec](/specs/smart-contract-updates-from-l1#celo-minting) for more information.
During the migration it needs to be setup with the remaining unminted Celo.
This is done by first reading the total supply of Celo tokens at the time of the migration. This value is then subtracted from the max supply of Celo tokens, which is *1,000,000,000*. This difference is the remaining amount of tokens that gets set as the balance of the distribution schedule contract.
## Other Changes
### Validators
Until Celo has decentralized sequencing, validators will no longer validate blocks, but instead operate community RPC nodes.
Refer to the [proposal](https://forum.celo.org/t/proposal-validator-engagement-during-the-transition-to-celo-l2/9700) in the context of [The Great Celo Halvening Temperature Check](https://mondo.celo.org/governance/cgp-164).
### CIP-64 Receipts Now Contain the `baseFee`
For the Celo L1, the `effectiveGasPrice` for CIP-64 txs is only available until the block state is pruned. Afterwards, the blockchain client is unable to get the `baseFee` for the relevant `feeCurrency`, which is required to calculate the `effectiveGasPrice`. To avoid this and make the `effectiveGasPrice` available permanently, the `baseFee` is [included as the last field in the RLP-encoded CIP-64 receipt](https://github.com/celo-org/op-geth/commit/6a1996f17b2ae22fcb3c24b82acbaffa1753f667) for CIP-64 txs submitted after the L2 migration. The EIP-2718 `ReceiptPayload` for this transaction type is now `rlp([status, cumulativeGasUsed, logsBloom, logs, baseFee])`.
### CIP diff
For a full list of changes by CIP, refer to the forum post: [Executed CIPs and Key Changes in Celo’s transition to L2](https://forum.celo.org/t/executed-cips-and-key-changes-in-celo-s-transition-to-l2/10664).
# Native Bridge
Source: https://docs.celo.org/specs/native-bridge
With the L2 migration, the Celo blockchain gained a native bridge to Ethereum based on [OP Stack's Standard Bridge](https://docs.optimism.io/app-developers/guides/bridging/standard-bridge). Specifically we use Custom Gas Token feature. This page describes the process of bridging assets between L1 and L2.
The Celo token now exists in both L1 and L2 versions. The L1 version is a standard ERC20 token with a total supply of 1 billion, fully minted to the `OptimismPortal` smart contract, which is part of the bridge (this setup allows any Celo token holder on L2 to bridge their tokens to L1). The L2 version is the native token on the L2 Celo chain, preserving the balances from the Celo L1 chain. Tokens that have not yet been minted on the Celo L1 chain, such as tokens for Community Fund, are now minted to the `CeloUnreleasedTreasury`, which manages further distribution.
## Bridging CELO from L1 to L2
To deposit ERC20 Celo tokens onto the chain, users should use the `OptimismPortalProxy.depositERC20Transaction` method. Before depositing tokens with `depositERC20Transaction`, users must first call `approve()` on the `OptimismPortal`. After the deposit is made, L1 tokens are bridged, and an equivalent amount of tokens is minted as native Celo tokens in the user's account on Layer 2 (L2).
## Bridging CELO from L2 to L1
To withdraw Celo from the L2 chain, users should use the `L2ToL1MessagePasser.initiateWithdrawal` method. The process for proving and finalizing withdrawals is the [same](https://docs.optimism.io/op-stack/bridging/withdrawal-flow) as it is on OP chains that use ETH as the native token.
## Bridging ETH
Native ETH bridging is not supported for now since L1 bridge considers L1 Celo ERC20 as native token for Celo L2 and actively rejects any native ETH sent to the bridge. It is possible to bridge WETH (wrapped ETH) which behaves as standard ERC20 token both on L1 and L2.
## Bridged ERC20 Tokens
ERC20 tokens can be bridged the same way as in the unmodified OP Stack, see [Bridging ERC-20 Tokens to OP Mainnet With the Optimism SDK](https://docs.optimism.io/app-developers/tutorials/bridging/cross-dom-bridge-erc20) for a tutorial on this.
## Using Bridged Tokens as Fee Abstraction
The `OptimismMintableERC20` (used to represent ERC20 tokens from L1 on L2) supports the [`IFeeCurrency`](https://github.com/celo-org/fee-currency-example/blob/master/src/IFeeCurrency.sol) interface, which is a requirement to use them as a Fee Abstraction token. Before a new `OptimismMintableERC20` instance can actually be used as Fee Abstraction, it still has to be added to the `FeeCurrencyDirectory` (`0x71FFbD48E34bdD5a87c3c683E866dc63b8B2a685`) by Celo governance. This is currently only the case for `WETH`.
# Smart Contract Updates From L1
Source: https://docs.celo.org/specs/smart-contract-updates-from-l1
Smart contract changes that have been deployed to Celo before the transition can be seen in this diff: [https://github.com/celo-org/celo-monorepo/pull/11035/files](https://github.com/celo-org/celo-monorepo/pull/11035/files)
## Epochs And rewards
### Overview of rewards and epochs in L1
The Celo L1 produces a special block ("epoch block”) every 17280 blocks (approximately one day). This blocks includes "epoch transactions” that are triggered by the blockchain itself.
During these epoch transactions, the protocol does:
* Updates target voting yield
* Calculates validator rewards
* Update validators' scores
* Mints Celo:
* For validator rewards (then exchanged for cUSD using Mento)
* For voter rewards
* For CarbonOffsetting fund
* For Community Fund (Celo Governance)
* Distributing validator rewards to the validators, groups and delegator (in cUSD)
* Distributing voter rewards
* Running validator elections (the result is the addresses of the signers, then stored in the blockchain storage and accessed via a precompile)
### Overview of rewards and epochs in L2
In the L2 "epoch blocks” no longer exist. There are no transactions triggered by the blockchain itself. Precompiles that were used to query epoch state are also not longer available.
The concept for epochs still remains, but they are determined to be at least as long as "epoch duration” (targeted to be set as one day on mainnet), but there's no guaranteed limit of the maximal duration. The size of an epoch can no longer be deterministically calculated based on block numbers alone.
The logic for processing epochs is now fully implemented in Solidity in the [EpochManager contract](https://github.com/celo-org/celo-monorepo/blob/release/core-contracts/12/packages/protocol/contracts-0.8/common/EpochManager.sol) introduced in Contract Release 12. cLabs runs a bot that calls the functions to trigger the epoch change and rewards distributions as soon as they are ready to be called, in a best-effort way.
Epochs are now processed using multiple calls, as the gas consumption of the process involved uses is relatively high.
Celo is no longer minted when processing the epoch, it is now transferred from the `CeloUnreleasedTreasury`. The contract `CeloUnreleasedTreasury` is allocated the full amount of unminted Celo at the time of the transition to L2.
When "epoch duration" has elapsed since the current epoch started, the function `startNextEpochProcess` can be called. This function:
1. Is permissionless, every EOA or contract can call it given that certain conditions are met:
1. Enough time has elapsed after the beginning of the epoch.
2. The epoch is not currently processing.
2. Updates target voting yield
3. Calculates epoch rewards (`EpochRewards.calculateTargetEpochRewards()`)
4. Allocates validator rewards:
1. mints CELO and exchanges it to cUSD
2. Sets an internal mapping with the allocation for each validator. Validators can later claim it calling `sendValidatorPayment`
5. Starts a block that prevents certain actions to be performed, notable lock Celo, unlock Celo and change validator locks.
6. Emits events:
1. EpochRewards: `TargetVotingYieldUpdated(uint256 fraction)`
2. CeloUnreleasedTreasury: `Released(address indexed to, uint256 amount)`
3. cUSD: `Transfer(address indexed from, address indexed to, uint256 value)`
4. EpochManager `EpochProcessingStarted(uint256 indexed epochNumber)`
After `startNextEpochProcess` is called, the epoch can be fully finished by calling `finishNextEpochProcess` . This function:
1. Is permissionless, every EOA or contract can call it given that certain conditions are met:
1. `startNextEpochProcess` has been called before.
2. Distributes rewards to voters (Celo)
3. Elects validators (the result is stored as an array of accounts of the elected validators, signers are also stored for backwards compatibility purposes)
4. Unblocks all actions blocked in `startNextEpochProcess` .
5. Updates the Epoch state.
6. Emits events:
1. Election: `EpochRewardsDistributedToVoters(address indexed group, uint256 value)`
2. CeloUnreleasedTreasury: `Released(address indexed to, uint256 amount)`
3. EpochManager: `EpochProcessingEnded(uint256 indexed epochNumber)`
> In the unlikely case that `startNextEpochProcess` needs to use more gas than available in a block, the same result can be achieved using multiple calls to `processGroup` .
### Scoring
The rewards for a validator, its group and its voters were previously based on the score of the validator, and the downtime the validator. The score itsef was defined by the downtime the validator had over multiple epochs.
The scoring is now managed by a contract called `ScoreManager`. This contract is a placeholder for a more complex implementation, meanwhile Governance and [a multisig](https://mondo.celo.org/governance/cgp-169) has the power to change the score of a validator. The score is now fully proportional to the rewards the validator and its voters will get at the end of the epoch.
## Celo minting
In the L1 Celo used to be minted using the well known `mint` function, that was using the `transfer` precompile under the hood.
In the L2, the Celo in the L2 is a bridged token from the L1. At the moment of the transition the whole total supply of Celo (1 billion tokens) is allocated to the bridge contract in the L1. In the L2, all holders (contracts and EOAs) will remain with their balance in their account, but tokens that were previously unallocated in Celo as a L1 will now be allocated to a new contract called `CeloUnreleasedTreasury`.
This comes with the implication that the `totalSuply()` function of the Celo Token (contract name `GoldToken`) will return 1 billion Celo after the L2 transition.
This means that the Celo token is now an ERC20 on the Ethereum network, and the tokens available on the Celo chain are a bridged representation of the tokens in the L1. This is achieved by using the custom gas token functionality of the OP stack.
## Governance Hotfix
The hot fix mechanism has been changed from a consensus of validators to a security council multisig.
## FeeCurrencyDirectory
The contract `FeeCurrencyWhitelist` is now deprecated. Fee currencies are now stored in a new contract called `FeeCurrencyDirectory`. To add a new token to the directory, an address for an oracle needs to be provided, as well as the intrinsic gas for transactions paid with this token as fee. Changes can only be made by Celo Governance.
The intrinsic gas is the amount of gas that it will be added to all transactions paying for fees with this token. It is meant to accurately represent the cost of the functions `debitGasFees`and `creditGasFees`, that were used to collect the fees involved while validating the transaction.
## FeeHandler
The [FeeHandler](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0052.md) was extended to support multiple beneficiaries. On the L1, only a carbon fund beneficiary and the burn fraction could be set.
Since Contract Release 12, many beneficiaries can be set, and the burn fraction is the remainder of all the allocations of the beneficiaries.
## Slashing
DowntimeSlasher and DoubleSigningSlasher were deprecated with the L2 transition, as the validators were replaced by RPC providers. GovernanceSlasher remains available and now supports removing members of a validator group and changing the slash multiplier. Governance slasher now supports to enable a multisig with the slasher role.
## Deprecated contracts
The following contracts have been deprecated:
1. Attestations (withdraws still enabled).
2. FeeCurrencyWhitelist
3. GasPriceMinimum
4. BlockChainParameters
5. DowntimeSlasher
6. DoubleSigningSlasher
7. Random
8. UsingPrecompiles
Deprecation means that they do not fulfill any purpose as a required primitive to run the chain. Deprecated contracts still remain on-chain, although their functions are supposed to revert with a [L2 check](https://github.com/celo-org/celo-monorepo/blob/release/core-contracts/12/packages/protocol/contracts-0.8/common/IsL2Check.sol).
They still remain in the Celo Registry, but are scheduled for deletion after the L2 fully activates.
Some functionality that was provided by precompiles (notably epoch number and elected validators) can be found in the EpochManager contract.
Some contracts had functions that exposed precompiles; these revert on the L2, at least where the contract still internally uses those functions. For more details, please refer to this [forum post](https://forum.celo.org/t/upcoming-changes-deprecation-of-celo-precompiles-and-usingprecompilescontract-functions-in-l2-migration/9421/2).
### Deprecated Contract Methods with Replacements Table
| Deprecated Contract Method | Replacement |
| -------------------------------------------- | ----------------------------------------- |
| BlockchainParams#getEpochNumberOfBlock | EpochManager#getEpochNumberOfBlock |
| BlockchainParams#getFirstBlockNumberForEpoch | EpochManager#getFirstBlockAtEpoch |
| FeeCurrencyWhitelist#getAddresses | FeeCurrencyDirectory#getAddresses |
| Election#getCurrentValidatorSigners | EpochManager#getElectedSigners |
| Election#getGroupEpochRewards | Election#getGroupEpochRewardsBasedOnScore |
| GovernanceSlasher#slash | GovernanceSlasher#slashL2 |
| Validators#registerValidator | Validators#registerValidatorNoBLS |
## Precompiles deprecation
On the L2, the `transfer` precompile is the only supported Celo-specific precompile.
Also, the `transfer` precompile can no longer mint Celo. There's an ongoing effort to push the transfer precompile upstream to the OP stack to guarantee full Superchain compatibility.
All other Celo-specific precompiles are deprecated, so the L2 migration removes support for the following precompiles:
* `fractionMulExp`
* `proofOfPossession`
* `getValidator`
* `numberValidators`
* `epochSize`
* `blockNumberFromHeader`
* `hashHeader`
* `getParentSealBitmap`
* `getVerifiedSealBitmap`
## Transition
Contracts for the L2 were deployed before the transition, while Celo was still an L1. The contracts changed behaviour automatically at the time of the transition.
## Update March 24th 2025
Contract Release 12 has been [successfully deployed](https://mondo.celo.org/governance/cgp-166) to Celo Mainnet.
# Token Duality
Source: https://docs.celo.org/specs/token-duality
## What is token duality?
Token duality means that the CELO token is both the native currency of the Celo blockchain as well as an ERC20 compatible token.
This means CELO tokens can be moved both by doing a native transfer as well as ERC20 transfers and will show up in both in the native account balance and the ERC20 balance, no matter how they were transferred. In contrast to ETH/WETH, no token wrapping or unwrapping is necessary.
## Implementation
The native transfers and balances behave exactly as on Ethereum and are stored in the same way. The CELO contract reads native balances and triggers native transfers via its ERC20 interface.
### Reading balances via ERC20
The ERC20 token does not store the balances in the contract storage, it uses the native balance as the source of truth. The `balanceOf` function just passes through the native balance.
### Transfers via ERC20
Similarly, the ERC20 `transfer` and `transferFrom` functions do not change the contract storage, but initiate a native transfer instead. Since there is no way to trigger native transfers from within a contract in Ethereum, Celo adds a `transfer` precompile for this purpose. This precompile can only be called by the CELO token.
### The `transfer` precompile
The precompile directly manipulates the account balances in the EVM’s statedb. It checks the caller address to verify that it has been called by the CELO token. Since the [Jovian hardfork](/specs/upgrades/jovian), the `from` and `to` addresses get warmed (added to the access list) during precompil execution. Before Jovian, warmness stayed unchanged.
Precompile address: `0xff - 2` == `253`\
Parameters (abi-encoded): `address from, address to, uint256 value`\
Gas costs: 9000\
No return value
# Transaction Fees
Source: https://docs.celo.org/specs/transaction-fees
## Overview
While you can send transactions on Celo as you do on any Ethereum or OP-Stack chain, there are some key differences that are relevant if you want a deeper understanding:
* **[Fee Abstraction](/specs/fee-abstraction)**, which allows users to pay for transaction fees in ERC20 tokens instead of CELO and is covered in its own chapter
* **[Zero L1 & Operator Fees](#zero-l1--operator-fees)**, meaning that the OP-Stack L1 & Operator fees are configured to always be zero, so that Celo chains don't incur any fees on top of the normal Ethereum transaction fees
* The **[base fee floor](#base-fee-floor)**, which sets a lower limit for a block's base fee
* The **[FeeHandler](#feehandler)** contract that decides what to do with the collected base fees
## Zero L1 & Operator Fees
OP-Stack supports charging transaction senders an [L1 data fee](https://docs.optimism.io/stack/transactions/fees#l1-data-fee), which is added on top of the normal transaction fees and can't be directly influenced or limited by the tx sender. The fee is meant to cover the cost of L1 transactions, especially for data availability. Since CELO uses EigenDA, the data availability costs are low and predictable, so that this mechanism is not needed.
The L1 fees are configured to zero by setting the `gasPriceOracleBaseFeeScalar` and `gasPriceOracleBlobBaseFeeScalar` to zero, so that the L1 fee formula always returns zero. The `GasPriceOracle` will also correctly return zero as a result, so that you don't have to change your code if you are already relying on the `GasPriceOracle` due to supporting other OP-Stack chains.
The [Isthmus](/specs/upgrades/isthmus) upgrade also introduces an [Operator fee](https://specs.optimism.io/protocol/isthmus/exec-engine.html#operatorfees), which is a configurable cost designed to price chain-specific resources such as Alt-DA storage or ZK proving. Celo disables this charge as well by setting both `operatorFeeScalar` and `operatorFeeConstant` to `0`.
If you are coming from Ethereum, not having L1 data and operator fees is what you are used to, and you will feel right at home on Celo.
## Base Fee Floor
Celo follows the usual [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) rules to determine a block's base fee with on modification: The base fee can't fall below a certain limit, the base fee floor. This prevents the chain to be spammed with unimportant transactions that will make the chain state grow rapidly and make future scaling harder. The floor is set sufficiently low to still keep average transactions below 0.01 USD.
The base fee floor is set in the `eip1559BaseFeeFloor` rollup configuration variable and is denominated in native CELO token. If Fee Abstraction is used to pay in other tokens, the base fee is converted to the token's value at the current exchange rate.
## FeeHandler
All base fees are sent to the FeeHandler contract, which is responsible for deciding what to eventually do with the fees. The final behavior for Celo L2 mainnet has not been confirmed yet (as of 2024-11-15). On Celo L1, the FeeHandler:
* burns 80% of the fees (after converting non-CELO fees to CELO)
* sends 20% of the fees to carbon offsetting projects as part of the Ultragreen Money initiative.
# Transaction Types On Celo L2
Source: https://docs.celo.org/specs/transaction-types
Different categories of transaction types are relevant to Celo. Some are inherited from Ethereum, others were added to support Celo's Fee Abstraction feature, and some older ones have been superseded and are no longer supported. When developing new applications, please use the tx types marked as "recommended" below.
The [docs.celo.org page about tx types](/home/protocol/transactions/transaction-types) contains additional information on how to handle different tx types, their differences and tooling support.
## Ethereum Compatible Tx Types
To achieve its high level of Ethereum compatibility, Celo supports all Ethereum tx types relevant for an L2. The following transaction types can be used in exactly the same way as on Ethereum and don't require any changes to client libraries or other tooling.
* [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) (recommended), type 2
* [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930), type 1
* [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702), type 4 (available post-Isthmus)
* Legacy Ethereum transaction as described in the [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf), type 0
The [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) tx type 3, which provides blobs for data availability on Ethereum, is not supported.
## OP Stack Specific Tx Types
OP Stack has deposited transactions, which are L2 transactions derived from L1 and included in an L2 block. Celo also utilizes this transaction type and introduces the following additional transaction type.
* [Deposited transaction](https://specs.optimism.io/glossary.html#deposited-transaction), type 126
## Celo-Specific Tx Types
The following tx type is an essential part of Celo's Fee Abstraction feature. For more details, read the CIP linked below, and the [Fee Abstraction section](/specs/fee-abstraction).
* [CIP-64](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0064.md) (recommended), type 123
## Older, Unsupported Tx Types
These tx types won't be accepted anymore, but transactions in blocks before the L2 migration can still contain transactions of these types.
* [CIP-42](https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0042.md), type 124
* Legacy Celo transaction, type 0, but with different fields than the Ethereum legacy tx
### Details on Celo Legacy Transactions
For historic reasons, the Celo legacy txs are not prefixed with a tx type number, just like Ethereum legacy txs. To tell these two legacy tx types apart, you have to look at the tx content, which contains additional `feeCurrency`, `gatewayFeeRecipient`, and `gatewayFee` fields for Celo legacy txs:
```text theme={null}
RLP([nonce, gasPrice, gasLimit, feeCurrency, gatewayFeeRecipient, gatewayFee, recipient, amount, data, v, r, s])
```
There is no CIP number for this tx type because it was included in version 1 of the Celo blockchain and CIPs only describe changes introduced after that point in time.
# Ice Cream Upgrade
Source: https://docs.celo.org/specs/upgrades/ice-cream
## Overview
The Ice Cream upgrade for the Celo network upgrades the DA layer to use EigenDA v2, also known as Blazar, to further innovate and strengthen the network’s data availability layer.
Blazar represents a major architectural upgrade to the EigenDA protocol, introducing improved system throughput and stability, alongside new capabilities like permissionless DA payments and enhanced resource throttling.
Most notably for Celo:
* End-to-end confirmation latency is significantly reduced, moving from minutes to near real-time. Blazar’s design enables rollups to reference blocks in their own logic without waiting for L1 confirmations.
* System throughput and network stability are greatly improved through more efficient chunk distribution, optimized request routing, and horizontal scalability of DA nodes. Support for decentralized dispersal is unlocked by eliminating DDoS attack surfaces inherent in the original push-based mode.
## Specifications
After the Celo Ice Cream update, the Celo sequencer will use EigenDA v2 for distributing transaction data. Therefore, any node following the network must upgrade it's EigenDA proxy to a version compatible with EigenDA v2. For more details see the [Upgrade notice](/infra-partners/notices/archive/eigenda-v2-upgrade).
## Upgrade Timelines
The Ice Cream upgrade was activated on Mainnet, Alfajores, and Baklava, with the activation process for each network occurring independently. As this upgrade was activated on the sequencer, no detailed activation times can be given.
| Network | Date & Time (UTC) |
| --------- | :----------------------: |
| Mainnet | Wed Sep 10 2025 15:00:00 |
| Alfajores | Wed Aug 20 2025 15:00:00 |
| Baklava | Wed Jul 30 2025 15:00:00 |
# Isthmus Upgrade
Source: https://docs.celo.org/specs/upgrades/isthmus
## Overview
The Isthmus upgrade for the Celo network adopts features from the **Holocene** and **Isthmus** upgrades of Optimism, incorporating important improvements.
This upgrade aligns Celo architecture closely with the Optimism ecosystem, bringing established and tested improvements to our network.
## Specifications
The Celo Isthmus upgrade brings in all consensus and execution changes from Optimism’s Holocene and Isthmus hardforks. For full technical details, see the Optimism specs linked below.
* [Optimism's Holocene Upgrade Specifications](https://specs.optimism.io/protocol/holocene/overview.html)
* [Optimism's Isthmus Upgrade Specifications](https://specs.optimism.io/protocol/isthmus/overview.html)
### Holocene Highlights
* Upgraded derivation pipeline – A stricter, simpler derivation pipeline enhances the Fault Proof System's worst-case behaviour and compatibility.
* EIP-1559 configurability - The `SystemConfig` L1 contract lets operators adjust the elasticity and denominator parameters, so the gas target and gas limit can be tuned independently.
### Isthmus Highlights
Isthmus incorporates the execution-layer EIPs from Ethereum’s Prague upgrade, along with several Optimism-specific enhancements.
#### Ethereum Prague's EIPs
* [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702): Allows an EOA to function as a smart-contract wallet for a single transaction.
* [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537): Adds operations on BLS12-381 curve as a precompile.
* [EIP-2935](https://eips.ethereum.org/EIPS/eip-2935): Introduces a system contract that stores the last 8,191 block hashes.
* [EIP-7623](https://eips.ethereum.org/EIPS/eip-7623): Increases the calldata gas cost, making calldata-intensive transactions more expensive.
* [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685): Extends the block header with a 32-byte `requests_hash` commitment for conveying execution-layer requests to the consensus layer. **In Celo, this field is always `sha256("")`.**
> **Note:** Although **EIP-6110**, **EIP-7002**, and **EIP-7251** exist in the execution-layer codebase, they remain **disabled** in the Isthmus upgrade.
#### Optimism-Specific Improvements
* Updated `withdrawalsRoot`: The `withdrawalsRoot` in block header points to the storage root of `L2ToL1MessagePasser`, simplifying proof generation.
* Operator Fee: A flexible surcharge that can be tuned to cover chain-specific costs such as Alt-DA storage, ZK proving, or custom gas-token overhead. **In Celo, as with the L1 data fee, the Operator Fee is set to zero by setting `operatorFeeScalar` and `operatorFeeConstant` in `SystemConfig` contract to 0.**
## Upgrade Timelines
The Isthmus upgrade was activated on Mainnet, Alfajores, and Baklava, with the activation process for each network occurring independently.
The table below shows the UNIX timestamp at which the Isthmus upgrade activated for each network, the accompanying UTC date and time, and the approximate L2 block height.
| Network | Unix Timestamp | Date & Time (UTC) | Block Height |
| --------- | :------------: | :----------------------: | ------------: |
| Mainnet | 1752073200 | Wed Jul 09 2025 15:00:00 | \~ 40,172,440 |
| Alfajores | 1750863600 | Wed Jun 25 2025 15:00:00 | \~ 49,908,280 |
| Baklava | 1749654000 | Wed Jun 11 2025 15:00:00 | \~ 37,881,140 |
# Jello Upgrade
Source: https://docs.celo.org/specs/upgrades/jello
## Overview
The Jello upgrade for the Celo network enables OP Succinct Lite, a production-ready, zero-knowledge-powered fault proof system built in collaboration with OP Labs and Succinct.
## Specifications
### L1 Contract changes
The Jello upgrade included L1 contract changes. They have been been accepted by governance in [CGP-265](https://mondo.celo.org/governance/265) and executed by the Celo Security Council.
### Execution Layer changes
There's no execution layer changes in the Jello upgrade.
## Upgrade Timelines
The Jello upgrade activated on Mainnet and Celo Sepolia, with the activation process for each network occurring independently.
| Network | Date & Time (UTC) | Upgrade transaction |
| ------------ | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Celo Sepolia | Wed, Nov 05 2025 11:16:00 | [`0x736deb757f4708eeafecc961f36e14f3711c1d9f944e45c933b666329743b31a`](https://eth-sepolia.blockscout.com/tx/0x736deb757f4708eeafecc961f36e14f3711c1d9f944e45c933b666329743b31a) |
| Mainnet | Wed, Dec 10 2025 10:24:22 | [`0x5fb3f2225dd2ba91efe941d4c9151df120ab06f6611b7b494bdecc96ff84c44b`](https://eth.blockscout.com/tx/0x5fb3f2225dd2ba91efe941d4c9151df120ab06f6611b7b494bdecc96ff84c44b) |
# Jovian Upgrade
Source: https://docs.celo.org/specs/upgrades/jovian
## Overview
The Jovian upgrade for the Celo network adopts features from Optimism's Jovian hardfork, along with Celo-specific improvements to the transfer precompile and gas pricing mechanism.
## Specifications
The Celo Jovian upgrade brings in consensus and execution changes from Optimism's Jovian hardfork. For full technical details, see the Optimism documentation linked below.
* [Optimism's Jovian Upgrade Notice](https://docs.optimism.io/notices/archive/upgrade-17)
### Optimism Jovian Features
* **Cannon Go 1.24 Support**: The on-chain fault proof virtual machine implementation is upgraded to support Go 1.24.
* **Configurable Minimum Base Fee**: Allows chain operators to specify a minimum base fee to shorten the length of priority fee auctions (disabled by default).
* **Data Availability Footprint Block Limit**: An in-protocol limit on estimated DA usage prevents spam and priority fee auctions. The `blobGasUsed` property now stores DA footprint values instead of remaining zero. **Celo does not make use of this feature.**
### Celo-Specific Changes
#### Transfer Precompile Address Warming
The [transfer precompile](/specs/token-duality) now warms the `from` and `to` addresses during execution. This aligns with standard EVM behavior where address accesses during value transfers are warmed, ensuring correct gas accounting for subsequent operations on the same address.
Related implementation:
* [op-geth #433](https://github.com/celo-org/op-geth/pull/433)
* [op-geth #435](https://github.com/celo-org/op-geth/pull/435) (tracing improvements)
* [celo-kona #115](https://github.com/celo-org/celo-kona/pull/115)
#### Minimum Base Fee
Celo transitions from its Celo-specific gas price floor mechanism to Optimism's Minimum Base Fee. This aligns Celo's gas pricing with the OP Stack standard while maintaining the ability to set a floor on transaction costs.
Related implementation:
* [op-geth #445](https://github.com/celo-org/op-geth/pull/445)
## Upgrade Timelines
The Jovian upgrade was activated on Mainnet and Celo Sepolia, with the activation process for each network occurring independently.
The table below shows the UNIX timestamp at which the Jovian upgrade activated for each network, along with the accompanying UTC date and time.
| Network | Unix Timestamp | Date & Time (UTC) |
| ------------ | :------------: | :-----------------------: |
| Celo Sepolia | 1773749037 | Tue, Mar 17 2026 12:03:57 |
| Mainnet | 1774958788 | Tue, Mar 31 2026 12:06:28 |
# Bridging
Source: https://docs.celo.org/tooling/bridges/bridges
Blockchain bridges are protocols that facilitate the transfer of assets and data between different blockchains.
Be sure you understand and review the risks pages when bridging assets between chains.
## Superbridge
[Superbridge](https://superbridge.app/celo) is a cross-chain interoperability platform that enables seamless asset transfers and communication between different blockchain networks. It simplifies bridging tokens, data, and liquidity across ecosystems, enhancing connectivity and usability in decentralized finance (DeFi).
**Supported chains**
* Celo Mainnet
* Celo Sepolia (Testnet)
[https://superbridge.app/celo](https://superbridge.app/celo)
## Layerswap
[Layerswap](https://layerswap.io/app) is a cost-efficient and secure solution for transferring assets across EVM and non-EVM blockchain networks. The app supports fast cross-chain transfers between 60+ chains as well as direct transfers between networks and 15+ Centralized Exchanges.
**Supported chains**
* Celo Mainnet
[https://layerswap.io/app](https://layerswap.io/app)
## Squid Router
[Squid Router](https://v2.app.squidrouter.com/) is a cross-chain liquidity routing protocol that enables seamless token swaps and transfers across multiple blockchain networks. It leverages the Axelar network for secure cross-chain communication, allowing users to swap tokens between blockchains without relying on centralized intermediaries. The protocol aggregates liquidity from various decentralized exchanges (DEXs) to provide optimal rates for users.
**Supported chains**
* Celo Mainnet
[https://v2.app.squidrouter.com/](https://v2.app.squidrouter.com/)
## Jumper Exchange
[Jumper Exchange](https://jumper.exchange/) is a cross-chain decentralized exchange (DEX) platform that enables seamless swapping of assets across multiple blockchain networks. It focuses on user-friendly, low-cost, and efficient transactions, supporting interoperability and liquidity across ecosystems like Ethereum, Polygon, and Celo.
**Supported chains**
* Celo Mainnet
[https://jumper.exchange/](https://jumper.exchange/)
## Hyperlane Nexus
[Hyperlane Nexus](https://www.usenexus.org/) is a cross-chain messaging and interoperability platform designed to connect decentralized applications (dApps) across multiple blockchains. It enables secure communication, data sharing, and asset transfers between ecosystems, enhancing scalability and collaboration in the decentralized web.
**Supported chains**
* Celo Mainnet
* Celo Sepolia (Testnet)
[https://www.usenexus.org/](https://www.usenexus.org/)
## Portal (Wormhole)
[Portal (formerly known as Wormhole)](https://portalbridge.com/) is a cross-chain messaging and token bridge protocol that enables the transfer of assets and data between different blockchain networks. It acts as a decentralized interoperability layer, allowing users to move tokens and interact with applications across multiple blockchains seamlessly. Portal leverages a secure, and decentralized network of validators to ensure trustless cross-chain communication.
**Supported chains**
* Celo Mainnet
[https://portalbridge.com/](https://portalbridge.com/)
## AllBridge
[AllBridge](https://app.allbridge.io/bridge?from=ETH\&to=CELO\&asset=ABR) is a decentralized, multi-chain bridge designed to facilitate the transfer of assets and data between different blockchain networks. It enables seamless cross-chain interoperability, allowing users to move tokens and interact with decentralized applications (dApps) across various ecosystems. AllBridge supports both EVM (Ethereum Virtual Machine) and non-EVM compatible chains, making it a versatile tool for cross-chain transactions.
**Supported chains**
* Celo Mainnet
[https://app.allbridge.io/bridge?from=ETH\&to=CELO\&asset=ABR](https://app.allbridge.io/bridge?from=ETH\&to=CELO\&asset=ABR)
## Satellite (Axelar)
[Satellite by Axelar](https://satellite.money/) is a cross-chain bridge and interoperability platform that enables seamless transfer of assets and data between different blockchain networks. Built on the Axelar network, Satellite provides a secure and decentralized way to connect various blockchains, allowing users to move tokens and interact with decentralized applications (dApps) across multiple ecosystems. It emphasizes ease of use, security, and broad blockchain compatibility.
**Supported chains**
* Celo Mainnet
[https://satellite.money/](https://satellite.money/)
## Transporter (Chainlink CCIP)
[Transporter](https://www.transporter.io/) (built on Chainlink Cross-Chain Interoperability Protocol, or CCIP) is a cross-chain communication and token transfer protocol designed to enable secure and seamless interactions between different blockchain networks. Leveraging Chainlink's decentralized oracle network, Transporter provides a trustless and reliable way to transfer assets and data across chains, ensuring high security and interoperability for decentralized applications (dApps).
**Supported chains**
* Celo Mainnet
[https://www.transporter.io/](https://www.transporter.io/)
## Galaxy
[Galaxy](https://galaxy.exchange/swap) is a decentralized exchange (DEX) built on the Celo blockchain, designed for fast, low-cost, and user-friendly trading of digital assets. It supports a wide range of tokens, including Celo-native assets and stablecoins, while prioritizing accessibility and financial inclusion.
**Supported chains**
* Celo Mainnet
[https://galaxy.exchange/swap](https://galaxy.exchange/swap)
## SmolRefuel
[SmolRefuel (Gassless Bridging)](https://smolrefuel.com/?outboundChain=42220) SmolRefuel is a tool that automates small gas top-ups for blockchain transactions, ensuring seamless interactions with dApps by keeping wallets funded and reducing interruptions. It simplifies gas management for users.
**Supported chains**
* Celo Mainnet
[https://smolrefuel.com/?outboundChain=42220](https://smolrefuel.com/?outboundChain=42220)
# Cross-Chain Messaging
Source: https://docs.celo.org/tooling/bridges/cross-chain-messaging
Cross-Chain Messaging enables seamless communication and data transfer between different blockchain networks, allowing decentralized applications (dApps) to interact and share information across multiple ecosystems.
## Chainlink CCIP
[Chainlink Cross-Chain Interoperability Protocol (CCIP)](https://chain.link/cross-chain) is a decentralized messaging protocol designed to enable secure and seamless communication between different blockchain networks. Built on Chainlink's proven oracle infrastructure, CCIP allows smart contracts to send and receive messages, data, and tokens across chains, facilitating cross-chain decentralized finance (DeFi), interoperability, and multi-chain application development.
### Supported chains
* [Celo Mainnet](https://docs.chain.link/ccip/directory/mainnet/chain/celo-mainnet)
### More information
* [Chainlink CCIP Docs](https://docs.chain.link/ccip)
* [NFT Minting from Celo to Ethereum Using Chainlink CCIP](https://github.com/celo-org/celo-ccip-workshop)
* [Chainlink Functions](https://docs.chain.link/chainlink-functions/supported-networks#celo)
[https://chain.link/cross-chain](https://chain.link/cross-chain)
## Hyperlane
[Hyperlane (formerly known as Abacus)](https://www.hyperlane.xyz/) is a permissionless cross-chain messaging protocol that enables decentralized applications (dApps) to communicate and share data across multiple blockchain networks. It provides developers with the tools to build interoperable smart contracts that can send and receive messages between chains, facilitating cross-chain DeFi, governance, and other multi-chain use cases.
### Supported chains
* Celo Mainnet
* Celo Sepolia
### More information
* [Hyperlane Docs](https://docs.hyperlane.xyz/)
* [Retiring Carbon Credits on Celo from any EVM-chain](https://medium.com/@hierzilena/retiring-carbon-credits-on-celo-from-any-evm-chain-e4966add6bd0)
[https://www.hyperlane.xyz/](https://www.hyperlane.xyz/)
## Wormhole
[Wormhole](https://wormhole.com/) is a decentralized cross-chain messaging protocol that enables the transfer of assets and data between different blockchain networks. It acts as a universal interoperability layer, allowing tokens, NFTs, and smart contract messages to move seamlessly across chains. Wormhole uses a network of decentralized guardians (validators) to securely verify and relay messages between blockchains.
### Supported chains
* Celo Mainnet
### More information
* [Wormhole Docs](https://wormhole.com/docs/)
* [Demo Cross-Chain Messaging with Wormhole](https://github.com/wormhole-foundation/demo-wormhole-messaging)
[https://wormhole.com/](https://wormhole.com/)
## Layer Zero
[LayerZero](https://layerzero.network/) is an omnichain interoperability protocol designed to enable seamless communication and asset transfers between different blockchain networks. It uses a lightweight messaging layer to connect blockchains, allowing smart contracts to send and receive data and tokens across chains without relying on intermediaries. LayerZero emphasizes security, efficiency, and decentralization.
### Supported chains
* Celo Mainnet
### More information
* [LayerZero Docs](https://docs.layerzero.network/v2)
[https://layerzero.network/](https://layerzero.network/)
## Axelar Network
[Axelar Network](https://axelar.network/) is a decentralized cross-chain communication platform that enables seamless interoperability between different blockchain networks. It provides a universal messaging protocol and decentralized gateway for transferring assets and data across chains. Axelar uses a proof-of-stake (PoS) consensus mechanism and a network of validators to securely route messages and enable cross-chain smart contract calls.
### Supported chains
* Celo Mainnet
### More information
* [Axelar Network Docs](https://docs.axelar.dev/)
[https://axelar.network/](https://axelar.network/)
# Verify Smart Contract using Blockscout
Source: https://docs.celo.org/tooling/contract-verification/blockscout
Verifying a smart contract allows developers to review your code from within the [Celo Blockscout instance](https://celo.blockscout.com).
* For detailed instructions follow the official documentation from [docs.blockscout.com](https://docs.blockscout.com/devs/verification)
# Verify Smart Contract using CeloScan
Source: https://docs.celo.org/tooling/contract-verification/celoscan
Verifying a smart contract allows developers to review your code from within the CeloScan Block Explorer
* Navigate to the **Contract** tab at the Explorer page for your contract's address
* Click **Verify & Publish** to enter the smart contract verification page
* Select the **Compile** type, **version** and **license**.
* Enter the Solidity Code of the contract along with the constructor arguments.
* Complete Captcha and click **Verify and Publish**.
* If done correctly, you should see the following screen.
# Verify Smart Contract using Hardhat
Source: https://docs.celo.org/tooling/contract-verification/hardhat
Verifying a smart contract allows developers to review your code from within the CeloScan Block Explorer
If you use [Celo Composer](https://github.com/celo-org/celo-composer) all the configuration is done for you out of the box, all you need is the CeloScan API keys!
## Prerequisites
Before the installation steps you need to have your hardhat project initialized using the command
```bash theme={null}
npx hardhat init
```
Make sure to have dependencies installed and the hardhat config file is importing `@nomicfoundation/hardhat-toolbox`
### Hardhat Configuration
Use environment variables for secrets. Install `dotenv`, create a `.env`, and load it at the top of `hardhat.config.js`.
```bash theme={null}
npm i -D dotenv
```
```js theme={null}
// hardhat.config.js
require("dotenv").config();
```
```bash theme={null}
# .env
PRIVATE_KEY=0xYOUR_PRIVATE_KEY
ETHERSCAN_API_KEY=your_celoscan_api_key
```
Then add the following configuration to the `config` object in `hardhat.config.js`.
```js theme={null}
networks: {
celoSepolia: {
// can be replaced with the RPC url of your choice.
url: "https://forno.celo-sepolia.celo-testnet.org/",
accounts: [process.env.PRIVATE_KEY],
},
celo: {
url: "https://forno.celo.org",
accounts: [process.env.PRIVATE_KEY],
}
},
etherscan: {
apiKey: process.env.ETHERSCAN_API_KEY,
customChains: [
{
network: "celoSepolia",
chainId: 11142220,
urls: {
apiURL: "https://api.etherscan.io/v2/api",
browserURL: "https://sepolia.celoscan.io",
},
},
{
network: "celo",
chainId: 42220,
urls: {
apiURL: "https://api.etherscan.io/v2/api",
browserURL: "https://celoscan.io/",
},
},
]
},
```
## Verifying Contracts
Use the following command (Make sure your contracts are compiled before verification)
Celo Sepolia Testnet
```bash theme={null}
npx hardhat verify [CONTRACT_ADDRESS] [...CONSTRUCTOR_ARGS] --network celoSepolia
```
Celo Mainnet
```bash theme={null}
npx hardhat verify [CONTRACT_ADDRESS] [CONSTRUCTOR_ARGS] --network celo
```
# Verify Contract Deployed on Celo
Source: https://docs.celo.org/tooling/contract-verification/index
How to verify contracts deployed on Celo.
***
The fastest way to verify on Celo is to use [hardhat-celo](/developer/verify/hardhat). Alternatively, you can use the Celo Explorer and CeloScan to verify contracts using a user interface.
## Verify Contracts on Celo
* [Using Blockscout](/developer/verify/blockscout)
* [Using Remix](/developer/verify/remix)
* [Using CeloScan](/developer/verify/celoscan)
* [Using Hardhat](/developer/verify/hardhat)
# Verify Smart Contract using Remix
Source: https://docs.celo.org/tooling/contract-verification/remix
* Verifying a smart contract allows anyone to review your code from within the Celo Block Explorer. This can be done using the Remix Sourcify Plugin.
* Navigate back to the **Remix IDE**, select **Plugin Manager** from the left side menu.
* Search for **Sourcify**, click Activate, and open the newly installed **Sourcify Plugin**.
* Choose Verifier, select the dropdown menu, and choose the location for your deployed contract (example **Celo Sepolia**).
* Paste your contract address into the **Contract Address** field and select **Verify**.
The source code of the contract that you are verifying will need to be in Remix. Contracts deployed with Hardhat, and other tools can also be verified using the Remix Sourcify plugin, but you will need to copy your contract source code into Remix first.
* Navigate to the **Contract Address Details Page** in the block explore to, use the **Code, Read Contract**, and **Write Contract** panels to view and interact with your deployed smart contract.
# Core Contracts
Source: https://docs.celo.org/tooling/contracts/core-contracts
[comment]: <> "DO NOT EDIT THIS FILE MANUALLY"
[comment]: <> "Autogenerated by `scripts/update_contracts.py`"
Core contract addresses for the Celo networks.
## Celo Mainnet
| Contract | Proxy |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| Accounts | [`0x7d21685C17607338b313a7174bAb6620baD0aaB7`](https://celo.blockscout.com/address/0x7d21685C17607338b313a7174bAb6620baD0aaB7) |
| Attestations | [`0xdC553892cdeeeD9f575aa0FBA099e5847fd88D20`](https://celo.blockscout.com/address/0xdC553892cdeeeD9f575aa0FBA099e5847fd88D20) |
| CeloToken | [`0x471EcE3750Da237f93B8E339c536989b8978a438`](https://celo.blockscout.com/address/0x471EcE3750Da237f93B8E339c536989b8978a438) |
| CeloUnreleasedTreasury | [`0x7A8c7a833565fc428cdFBa20FE03fAfb178A434f`](https://celo.blockscout.com/address/0x7A8c7a833565fc428cdFBa20FE03fAfb178A434f) |
| Election | [`0x8D6677192144292870907E3Fa8A5527fE55A7ff6`](https://celo.blockscout.com/address/0x8D6677192144292870907E3Fa8A5527fE55A7ff6) |
| EpochManager | [`0xF424B5e85B290b66aC20f8A9EAB75E25a526725E`](https://celo.blockscout.com/address/0xF424B5e85B290b66aC20f8A9EAB75E25a526725E) |
| EpochManagerEnabler | [`0x2d4148c3500F696aA5a83dd4cc35c289b738B687`](https://celo.blockscout.com/address/0x2d4148c3500F696aA5a83dd4cc35c289b738B687) |
| EpochRewards | [`0x07F007d389883622Ef8D4d347b3f78007f28d8b7`](https://celo.blockscout.com/address/0x07F007d389883622Ef8D4d347b3f78007f28d8b7) |
| Escrow | [`0xf4Fa51472Ca8d72AF678975D9F8795A504E7ada5`](https://celo.blockscout.com/address/0xf4Fa51472Ca8d72AF678975D9F8795A504E7ada5) |
| FederatedAttestations | [`0x0aD5b1d0C25ecF6266Dd951403723B2687d6aff2`](https://celo.blockscout.com/address/0x0aD5b1d0C25ecF6266Dd951403723B2687d6aff2) |
| FeeCurrencyDirectory | [`0x15F344b9E6c3Cb6F0376A36A64928b13F62C6276`](https://celo.blockscout.com/address/0x15F344b9E6c3Cb6F0376A36A64928b13F62C6276) |
| FeeHandler | [`0xcD437749E43A154C07F3553504c68fBfD56B8778`](https://celo.blockscout.com/address/0xcD437749E43A154C07F3553504c68fBfD56B8778) |
| Freezer | [`0x47a472F45057A9d79d62C6427367016409f4fF5A`](https://celo.blockscout.com/address/0x47a472F45057A9d79d62C6427367016409f4fF5A) |
| GoldToken | [`0x471EcE3750Da237f93B8E339c536989b8978a438`](https://celo.blockscout.com/address/0x471EcE3750Da237f93B8E339c536989b8978a438) |
| Governance | [`0xD533Ca259b330c7A88f74E000a3FaEa2d63B7972`](https://celo.blockscout.com/address/0xD533Ca259b330c7A88f74E000a3FaEa2d63B7972) |
| GovernanceSlasher | [`0xf2a347F184b0Fef572C7CBd2c392359eCcf43F3c`](https://celo.blockscout.com/address/0xf2a347F184b0Fef572C7CBd2c392359eCcf43F3c) |
| LockedCelo | [`0x6cC083Aed9e3ebe302A6336dBC7c921C9f03349E`](https://celo.blockscout.com/address/0x6cC083Aed9e3ebe302A6336dBC7c921C9f03349E) |
| LockedGold | [`0x6cC083Aed9e3ebe302A6336dBC7c921C9f03349E`](https://celo.blockscout.com/address/0x6cC083Aed9e3ebe302A6336dBC7c921C9f03349E) |
| MentoFeeHandlerSeller | [`0x4eFa274B7e33476C961065000D58ee09F7921A74`](https://celo.blockscout.com/address/0x4eFa274B7e33476C961065000D58ee09F7921A74) |
| OdisPayments | [`0xAE6B29f31B96e61DdDc792f45fDa4e4F0356D0CB`](https://celo.blockscout.com/address/0xAE6B29f31B96e61DdDc792f45fDa4e4F0356D0CB) |
| Registry | [`0x000000000000000000000000000000000000ce10`](https://celo.blockscout.com/address/0x000000000000000000000000000000000000ce10) |
| Reserve | [`0x9380fA34Fd9e4Fd14c06305fd7B6199089eD4eb9`](https://celo.blockscout.com/address/0x9380fA34Fd9e4Fd14c06305fd7B6199089eD4eb9) |
| ScoreManager | [`0xef3B9CC0FA4717aF6f412d39dBcEb89bf92f603B`](https://celo.blockscout.com/address/0xef3B9CC0FA4717aF6f412d39dBcEb89bf92f603B) |
| SortedOracles | [`0xefB84935239dAcdecF7c5bA76d8dE40b077B7b33`](https://celo.blockscout.com/address/0xefB84935239dAcdecF7c5bA76d8dE40b077B7b33) |
| StableToken | [`0x765DE816845861e75A25fCA122bb6898B8B1282a`](https://celo.blockscout.com/address/0x765DE816845861e75A25fCA122bb6898B8B1282a) |
| StableTokenBRL | [`0xe8537a3d056DA446677B9E9d6c5dB704EaAb4787`](https://celo.blockscout.com/address/0xe8537a3d056DA446677B9E9d6c5dB704EaAb4787) |
| StableTokenEUR | [`0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73`](https://celo.blockscout.com/address/0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73) |
| UniswapFeeHandlerSeller | [`0x399e78488ecC13794f4a4d9534c20a8c1A6e5A8b`](https://celo.blockscout.com/address/0x399e78488ecC13794f4a4d9534c20a8c1A6e5A8b) |
| Validators | [`0xaEb865bCa93DdC8F47b8e29F40C5399cE34d0C58`](https://celo.blockscout.com/address/0xaEb865bCa93DdC8F47b8e29F40C5399cE34d0C58) |
## Celo Sepolia Testnet
| Contract | Proxy |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| Accounts | [`0x44957232699ca060B607E77083bDACD350d6b6d1`](https://celo-sepolia.blockscout.com/address/0x44957232699ca060B607E77083bDACD350d6b6d1) |
| CeloToken | [`0x471EcE3750Da237f93B8E339c536989b8978a438`](https://celo-sepolia.blockscout.com/address/0x471EcE3750Da237f93B8E339c536989b8978a438) |
| CeloUnreleasedTreasury | [`0xB76D502Ad168F9D545661ea628179878DcA92FD5`](https://celo-sepolia.blockscout.com/address/0xB76D502Ad168F9D545661ea628179878DcA92FD5) |
| Election | [`0xeB8B626f3A76174f4576bb47429c47EfDED7C211`](https://celo-sepolia.blockscout.com/address/0xeB8B626f3A76174f4576bb47429c47EfDED7C211) |
| EpochManager | [`0x6f2D4BD55BbD70c5E30F747e1d35Ba97Ad7d60Eb`](https://celo-sepolia.blockscout.com/address/0x6f2D4BD55BbD70c5E30F747e1d35Ba97Ad7d60Eb) |
| EpochManagerEnabler | [`0xd4793ae71de2c2d9Ad71649da5D31dE05f79251D`](https://celo-sepolia.blockscout.com/address/0xd4793ae71de2c2d9Ad71649da5D31dE05f79251D) |
| EpochRewards | [`0x68c261DBe59c591717d6Cc0D15Bbc1da25E6E6dC`](https://celo-sepolia.blockscout.com/address/0x68c261DBe59c591717d6Cc0D15Bbc1da25E6E6dC) |
| Escrow | [`0x498a2F6C9cF7bdDbd643558a1CA2976F1E72edC4`](https://celo-sepolia.blockscout.com/address/0x498a2F6C9cF7bdDbd643558a1CA2976F1E72edC4) |
| FederatedAttestations | [`0xb0Fe4466f288A3BbE5C2736B081B2021080DF703`](https://celo-sepolia.blockscout.com/address/0xb0Fe4466f288A3BbE5C2736B081B2021080DF703) |
| FeeCurrencyDirectory | [`0x9212Fb72ae65367A7c887eC4Ad9bE310BAC611BF`](https://celo-sepolia.blockscout.com/address/0x9212Fb72ae65367A7c887eC4Ad9bE310BAC611BF) |
| FeeHandler | [`0xcD437749E43A154C07F3553504c68fBfD56B8778`](https://celo-sepolia.blockscout.com/address/0xcD437749E43A154C07F3553504c68fBfD56B8778) |
| Freezer | [`0x1521e2E533a99f4D11A0498aB965e3d72CE49Ef8`](https://celo-sepolia.blockscout.com/address/0x1521e2E533a99f4D11A0498aB965e3d72CE49Ef8) |
| GoldToken | [`0x471EcE3750Da237f93B8E339c536989b8978a438`](https://celo-sepolia.blockscout.com/address/0x471EcE3750Da237f93B8E339c536989b8978a438) |
| Governance | [`0x50d2f15CcF5E97999bDf9D6760d0208b00D14ad1`](https://celo-sepolia.blockscout.com/address/0x50d2f15CcF5E97999bDf9D6760d0208b00D14ad1) |
| GovernanceSlasher | [`0xbfc560E23339Af382dFEA4F4f4F44e2cE111B821`](https://celo-sepolia.blockscout.com/address/0xbfc560E23339Af382dFEA4F4f4F44e2cE111B821) |
| LockedCelo | [`0x3DB0F0850c5b5f42fe30d68778C8958fC5EE7951`](https://celo-sepolia.blockscout.com/address/0x3DB0F0850c5b5f42fe30d68778C8958fC5EE7951) |
| LockedGold | [`0x3DB0F0850c5b5f42fe30d68778C8958fC5EE7951`](https://celo-sepolia.blockscout.com/address/0x3DB0F0850c5b5f42fe30d68778C8958fC5EE7951) |
| MentoFeeHandlerSeller | [`0x978e29d10AC1383A226aA8276D9d9b05CeDB7965`](https://celo-sepolia.blockscout.com/address/0x978e29d10AC1383A226aA8276D9d9b05CeDB7965) |
| OdisPayments | [`0x96AfaE75F12A759c1dFB364ce93548c3Bd242D58`](https://celo-sepolia.blockscout.com/address/0x96AfaE75F12A759c1dFB364ce93548c3Bd242D58) |
| Registry | [`0x000000000000000000000000000000000000ce10`](https://celo-sepolia.blockscout.com/address/0x000000000000000000000000000000000000ce10) |
| Reserve | [`0xA4caA391bD23b538A96BBd9eaea825A60A6F79c1`](https://celo-sepolia.blockscout.com/address/0xA4caA391bD23b538A96BBd9eaea825A60A6F79c1) |
| ScoreManager | [`0x9acF6A707B8d1b880D0357389C5ebCAf5ED6b94D`](https://celo-sepolia.blockscout.com/address/0x9acF6A707B8d1b880D0357389C5ebCAf5ED6b94D) |
| SortedOracles | [`0xAb077999e5fA13bCda1599926F8927dDEADe533C`](https://celo-sepolia.blockscout.com/address/0xAb077999e5fA13bCda1599926F8927dDEADe533C) |
| StableToken | [`0xEF4d55D6dE8e8d73232827Cd1e9b2F2dBb45bC80`](https://celo-sepolia.blockscout.com/address/0xEF4d55D6dE8e8d73232827Cd1e9b2F2dBb45bC80) |
| StableTokenBRL | [`0x13d68A1Bf4a8cB7d9feF54EF70401871b666269c`](https://celo-sepolia.blockscout.com/address/0x13d68A1Bf4a8cB7d9feF54EF70401871b666269c) |
| StableTokenEUR | [`0x6B172e333e2978484261D7eCC3DE491E79764BbC`](https://celo-sepolia.blockscout.com/address/0x6B172e333e2978484261D7eCC3DE491E79764BbC) |
| UniswapFeeHandlerSeller | [`0x82f08A9f4993CBa538D95A3d58d58C070145eC87`](https://celo-sepolia.blockscout.com/address/0x82f08A9f4993CBa538D95A3d58d58C070145eC87) |
| Validators | [`0x5E7b295bd8D80625e2cCac97C98123aaEB5E7Ea5`](https://celo-sepolia.blockscout.com/address/0x5E7b295bd8D80625e2cCac97C98123aaEB5E7Ea5) |
# Fee Currencies
Source: https://docs.celo.org/tooling/contracts/fee-currencies
[comment]: <> "DO NOT EDIT THIS FILE MANUALLY"
[comment]: <> "Autogenerated by `scripts/update_contracts.py`"
Celo lets you pay gas fees in ERC20 tokens instead of CELO. The tables below list the tokens currently on the governable on-chain allowlist, read from the `FeeCurrencyDirectory` core contract. See [Fee Abstraction](/build-on-celo/fee-abstraction/overview) for how this works.
This is not a list of every token on Celo. For stablecoin addresses, see [Stablecoin Contracts](/tooling/contracts/stablecoin-contracts). For an overview of Celo's stablecoin ecosystem, see [Build with Local Stablecoins](/build-on-celo/build-with-local-stablecoin).
Pass the **feeCurrency address** as the `feeCurrency` field on a transaction, and use the **token address** when transferring the token itself. The two differ for tokens that do not use 18 decimals — such as USDC, USD₮ and USA₮ — which are allowlisted through an adapter. See [Adapters for Non-18-Decimal Tokens](/build-on-celo/fee-abstraction/using-fee-abstraction#adapters-for-non-18-decimal-tokens).
You can also query the list of allowlisted fee currencies with the Celo CLI:
```sh theme={null}
celocli network:whitelist
```
***
## Celo Mainnet
| Token | Symbol | feeCurrency Address | Token Address |
| ---------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
| Mento Australian Dollar | AUDm | [`0x7175504C455076F15c04A2F90a8e352281F492F9`](https://celo.blockscout.com/address/0x7175504C455076F15c04A2F90a8e352281F492F9) | [`0x7175504C455076F15c04A2F90a8e352281F492F9`](https://celo.blockscout.com/address/0x7175504C455076F15c04A2F90a8e352281F492F9) |
| Mento Brazilian Real | BRLm | [`0xe8537a3d056DA446677B9E9d6c5dB704EaAb4787`](https://celo.blockscout.com/address/0xe8537a3d056DA446677B9E9d6c5dB704EaAb4787) | [`0xe8537a3d056DA446677B9E9d6c5dB704EaAb4787`](https://celo.blockscout.com/address/0xe8537a3d056DA446677B9E9d6c5dB704EaAb4787) |
| Mento Canadian Dollar | CADm | [`0xff4Ab19391af240c311c54200a492233052B6325`](https://celo.blockscout.com/address/0xff4Ab19391af240c311c54200a492233052B6325) | [`0xff4Ab19391af240c311c54200a492233052B6325`](https://celo.blockscout.com/address/0xff4Ab19391af240c311c54200a492233052B6325) |
| Mento Swiss Franc | CHFm | [`0xb55a79F398E759E43C95b979163f30eC87Ee131D`](https://celo.blockscout.com/address/0xb55a79F398E759E43C95b979163f30eC87Ee131D) | [`0xb55a79F398E759E43C95b979163f30eC87Ee131D`](https://celo.blockscout.com/address/0xb55a79F398E759E43C95b979163f30eC87Ee131D) |
| Mento Colombian Peso | COPm | [`0x8A567e2aE79CA692Bd748aB832081C45de4041eA`](https://celo.blockscout.com/address/0x8A567e2aE79CA692Bd748aB832081C45de4041eA) | [`0x8A567e2aE79CA692Bd748aB832081C45de4041eA`](https://celo.blockscout.com/address/0x8A567e2aE79CA692Bd748aB832081C45de4041eA) |
| Mento Euro | EURm | [`0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73`](https://celo.blockscout.com/address/0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73) | [`0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73`](https://celo.blockscout.com/address/0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73) |
| Mento British Pound | GBPm | [`0xCCF663b1fF11028f0b19058d0f7B674004a40746`](https://celo.blockscout.com/address/0xCCF663b1fF11028f0b19058d0f7B674004a40746) | [`0xCCF663b1fF11028f0b19058d0f7B674004a40746`](https://celo.blockscout.com/address/0xCCF663b1fF11028f0b19058d0f7B674004a40746) |
| Mento Ghanaian Cedi | GHSm | [`0xfAeA5F3404bbA20D3cc2f8C4B0A888F55a3c7313`](https://celo.blockscout.com/address/0xfAeA5F3404bbA20D3cc2f8C4B0A888F55a3c7313) | [`0xfAeA5F3404bbA20D3cc2f8C4B0A888F55a3c7313`](https://celo.blockscout.com/address/0xfAeA5F3404bbA20D3cc2f8C4B0A888F55a3c7313) |
| Mento Japanese Yen | JPYm | [`0xc45eCF20f3CD864B32D9794d6f76814aE8892e20`](https://celo.blockscout.com/address/0xc45eCF20f3CD864B32D9794d6f76814aE8892e20) | [`0xc45eCF20f3CD864B32D9794d6f76814aE8892e20`](https://celo.blockscout.com/address/0xc45eCF20f3CD864B32D9794d6f76814aE8892e20) |
| Mento Kenyan Shilling | KESm | [`0x456a3D042C0DbD3db53D5489e98dFb038553B0d0`](https://celo.blockscout.com/address/0x456a3D042C0DbD3db53D5489e98dFb038553B0d0) | [`0x456a3D042C0DbD3db53D5489e98dFb038553B0d0`](https://celo.blockscout.com/address/0x456a3D042C0DbD3db53D5489e98dFb038553B0d0) |
| Mento Nigerian Naira | NGNm | [`0xE2702Bd97ee33c88c8f6f92DA3B733608aa76F71`](https://celo.blockscout.com/address/0xE2702Bd97ee33c88c8f6f92DA3B733608aa76F71) | [`0xE2702Bd97ee33c88c8f6f92DA3B733608aa76F71`](https://celo.blockscout.com/address/0xE2702Bd97ee33c88c8f6f92DA3B733608aa76F71) |
| Mento Philippine Peso | PHPm | [`0x105d4A9306D2E55a71d2Eb95B81553AE1dC20d7B`](https://celo.blockscout.com/address/0x105d4A9306D2E55a71d2Eb95B81553AE1dC20d7B) | [`0x105d4A9306D2E55a71d2Eb95B81553AE1dC20d7B`](https://celo.blockscout.com/address/0x105d4A9306D2E55a71d2Eb95B81553AE1dC20d7B) |
| Tether America USD | USA₮ | [`0x0357EE22278c922e1D36cFe6b899269b161880C4`](https://celo.blockscout.com/address/0x0357EE22278c922e1D36cFe6b899269b161880C4) | [`0xD2ab3C9A02DBBAB236BfEC45D1d755DF4267F771`](https://celo.blockscout.com/address/0xD2ab3C9A02DBBAB236BfEC45D1d755DF4267F771) |
| USDC | USDC | [`0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B`](https://celo.blockscout.com/address/0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B) | [`0xcebA9300f2b948710d2653dD7B07f33A8B32118C`](https://celo.blockscout.com/address/0xcebA9300f2b948710d2653dD7B07f33A8B32118C) |
| Mento Dollar | USDm | [`0x765DE816845861e75A25fCA122bb6898B8B1282a`](https://celo.blockscout.com/address/0x765DE816845861e75A25fCA122bb6898B8B1282a) | [`0x765DE816845861e75A25fCA122bb6898B8B1282a`](https://celo.blockscout.com/address/0x765DE816845861e75A25fCA122bb6898B8B1282a) |
| Tether USD | USD₮ | [`0x0E2A3e05bc9A16F5292A6170456A710cb89C6f72`](https://celo.blockscout.com/address/0x0E2A3e05bc9A16F5292A6170456A710cb89C6f72) | [`0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e`](https://celo.blockscout.com/address/0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e) |
| Wrapped Ether (Celo native bridge) | WETH | [`0xD221812de1BD094f35587EE8E174B07B6167D9Af`](https://celo.blockscout.com/address/0xD221812de1BD094f35587EE8E174B07B6167D9Af) | [`0xD221812de1BD094f35587EE8E174B07B6167D9Af`](https://celo.blockscout.com/address/0xD221812de1BD094f35587EE8E174B07B6167D9Af) |
| XAUt0 | XAUt0 | [`0x857BF24e29da0773687E804a743c2E421a394C16`](https://celo.blockscout.com/address/0x857BF24e29da0773687E804a743c2E421a394C16) | [`0xaf37E8B6C9ED7f6318979f56Fc287d76c30847ff`](https://celo.blockscout.com/address/0xaf37E8B6C9ED7f6318979f56Fc287d76c30847ff) |
| Mento West African CFA franc | XOFm | [`0x73F93dcc49cB8A239e2032663e9475dd5ef29A08`](https://celo.blockscout.com/address/0x73F93dcc49cB8A239e2032663e9475dd5ef29A08) | [`0x73F93dcc49cB8A239e2032663e9475dd5ef29A08`](https://celo.blockscout.com/address/0x73F93dcc49cB8A239e2032663e9475dd5ef29A08) |
| Mento South African Rand | ZARm | [`0x4c35853A3B4e647fD266f4de678dCc8fEC410BF6`](https://celo.blockscout.com/address/0x4c35853A3B4e647fD266f4de678dCc8fEC410BF6) | [`0x4c35853A3B4e647fD266f4de678dCc8fEC410BF6`](https://celo.blockscout.com/address/0x4c35853A3B4e647fD266f4de678dCc8fEC410BF6) |
## Celo Sepolia Testnet
| Token | Symbol | feeCurrency Address | Token Address |
| ---------------------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| Mento Australian Dollar | AUDm | [`0x5873Faeb42F3563dcD77F0fbbdA818E6d6DA3139`](https://celo-sepolia.blockscout.com/address/0x5873Faeb42F3563dcD77F0fbbdA818E6d6DA3139) | [`0x5873Faeb42F3563dcD77F0fbbdA818E6d6DA3139`](https://celo-sepolia.blockscout.com/address/0x5873Faeb42F3563dcD77F0fbbdA818E6d6DA3139) |
| Mento Brazilian Real | BRLm | [`0x2294298942fdc79417DE9E0D740A4957E0e7783a`](https://celo-sepolia.blockscout.com/address/0x2294298942fdc79417DE9E0D740A4957E0e7783a) | [`0x2294298942fdc79417DE9E0D740A4957E0e7783a`](https://celo-sepolia.blockscout.com/address/0x2294298942fdc79417DE9E0D740A4957E0e7783a) |
| Mento Canadian Dollar | CADm | [`0xF151c9a13b78C84f93f50B8b3bC689fedc134F60`](https://celo-sepolia.blockscout.com/address/0xF151c9a13b78C84f93f50B8b3bC689fedc134F60) | [`0xF151c9a13b78C84f93f50B8b3bC689fedc134F60`](https://celo-sepolia.blockscout.com/address/0xF151c9a13b78C84f93f50B8b3bC689fedc134F60) |
| Celo Euro | cEUR | [`0x6B172e333e2978484261D7eCC3DE491E79764BbC`](https://celo-sepolia.blockscout.com/address/0x6B172e333e2978484261D7eCC3DE491E79764BbC) | [`0x6B172e333e2978484261D7eCC3DE491E79764BbC`](https://celo-sepolia.blockscout.com/address/0x6B172e333e2978484261D7eCC3DE491E79764BbC) |
| Mento Swiss Franc | CHFm | [`0x284E9b7B623eAE866914b7FA0eB720C2Bb3C2980`](https://celo-sepolia.blockscout.com/address/0x284E9b7B623eAE866914b7FA0eB720C2Bb3C2980) | [`0x284E9b7B623eAE866914b7FA0eB720C2Bb3C2980`](https://celo-sepolia.blockscout.com/address/0x284E9b7B623eAE866914b7FA0eB720C2Bb3C2980) |
| Mento Colombian Peso | COPm | [`0x5F8d55c3627d2dc0a2B4afa798f877242F382F67`](https://celo-sepolia.blockscout.com/address/0x5F8d55c3627d2dc0a2B4afa798f877242F382F67) | [`0x5F8d55c3627d2dc0a2B4afa798f877242F382F67`](https://celo-sepolia.blockscout.com/address/0x5F8d55c3627d2dc0a2B4afa798f877242F382F67) |
| Celo Brazilian Real | cREAL | [`0x13d68A1Bf4a8cB7d9feF54EF70401871b666269c`](https://celo-sepolia.blockscout.com/address/0x13d68A1Bf4a8cB7d9feF54EF70401871b666269c) | [`0x13d68A1Bf4a8cB7d9feF54EF70401871b666269c`](https://celo-sepolia.blockscout.com/address/0x13d68A1Bf4a8cB7d9feF54EF70401871b666269c) |
| Celo Dollar | cUSD | [`0xEF4d55D6dE8e8d73232827Cd1e9b2F2dBb45bC80`](https://celo-sepolia.blockscout.com/address/0xEF4d55D6dE8e8d73232827Cd1e9b2F2dBb45bC80) | [`0xEF4d55D6dE8e8d73232827Cd1e9b2F2dBb45bC80`](https://celo-sepolia.blockscout.com/address/0xEF4d55D6dE8e8d73232827Cd1e9b2F2dBb45bC80) |
| Mento Euro | EURm | [`0xA99dC247d6b7B2E3ab48a1fEE101b83cD6aCd82a`](https://celo-sepolia.blockscout.com/address/0xA99dC247d6b7B2E3ab48a1fEE101b83cD6aCd82a) | [`0xA99dC247d6b7B2E3ab48a1fEE101b83cD6aCd82a`](https://celo-sepolia.blockscout.com/address/0xA99dC247d6b7B2E3ab48a1fEE101b83cD6aCd82a) |
| Mento British Pound | GBPm | [`0x85F5181Abdbf0e1814Fc4358582Ae07b8eBA3aF3`](https://celo-sepolia.blockscout.com/address/0x85F5181Abdbf0e1814Fc4358582Ae07b8eBA3aF3) | [`0x85F5181Abdbf0e1814Fc4358582Ae07b8eBA3aF3`](https://celo-sepolia.blockscout.com/address/0x85F5181Abdbf0e1814Fc4358582Ae07b8eBA3aF3) |
| Mento Ghanaian Cedi | GHSm | [`0x5e94B8C872bD47BC4255E60ECBF44D5E66e7401C`](https://celo-sepolia.blockscout.com/address/0x5e94B8C872bD47BC4255E60ECBF44D5E66e7401C) | [`0x5e94B8C872bD47BC4255E60ECBF44D5E66e7401C`](https://celo-sepolia.blockscout.com/address/0x5e94B8C872bD47BC4255E60ECBF44D5E66e7401C) |
| Mento Japanese Yen | JPYm | [`0x85Bee67D435A39f7467a8a9DE34a5B73D25Df426`](https://celo-sepolia.blockscout.com/address/0x85Bee67D435A39f7467a8a9DE34a5B73D25Df426) | [`0x85Bee67D435A39f7467a8a9DE34a5B73D25Df426`](https://celo-sepolia.blockscout.com/address/0x85Bee67D435A39f7467a8a9DE34a5B73D25Df426) |
| Mento Kenyan Shilling | KESm | [`0xC7e4635651E3e3Af82b61d3E23c159438daE3BbF`](https://celo-sepolia.blockscout.com/address/0xC7e4635651E3e3Af82b61d3E23c159438daE3BbF) | [`0xC7e4635651E3e3Af82b61d3E23c159438daE3BbF`](https://celo-sepolia.blockscout.com/address/0xC7e4635651E3e3Af82b61d3E23c159438daE3BbF) |
| Mento Nigerian Naira | NGNm | [`0x3d5ae86F34E2a82771496D140daFAEf3789dF888`](https://celo-sepolia.blockscout.com/address/0x3d5ae86F34E2a82771496D140daFAEf3789dF888) | [`0x3d5ae86F34E2a82771496D140daFAEf3789dF888`](https://celo-sepolia.blockscout.com/address/0x3d5ae86F34E2a82771496D140daFAEf3789dF888) |
| Mento Philippine Peso | PHPm | [`0x0352976d940a2C3FBa0C3623198947Ee1d17869E`](https://celo-sepolia.blockscout.com/address/0x0352976d940a2C3FBa0C3623198947Ee1d17869E) | [`0x0352976d940a2C3FBa0C3623198947Ee1d17869E`](https://celo-sepolia.blockscout.com/address/0x0352976d940a2C3FBa0C3623198947Ee1d17869E) |
| USDC | USDC | [`0xbf1441Ea57f43f35f713431001f35742c88071c7`](https://celo-sepolia.blockscout.com/address/0xbf1441Ea57f43f35f713431001f35742c88071c7) | [`0x01C5C0122039549AD1493B8220cABEdD739BC44E`](https://celo-sepolia.blockscout.com/address/0x01C5C0122039549AD1493B8220cABEdD739BC44E) |
| Mento Dollar | USDm | [`0xdE9e4C3ce781b4bA68120d6261cbad65ce0aB00b`](https://celo-sepolia.blockscout.com/address/0xdE9e4C3ce781b4bA68120d6261cbad65ce0aB00b) | [`0xdE9e4C3ce781b4bA68120d6261cbad65ce0aB00b`](https://celo-sepolia.blockscout.com/address/0xdE9e4C3ce781b4bA68120d6261cbad65ce0aB00b) |
| Tether USD | USD₮ | [`0xe19447B12cb0d0220B2a501D8382be2f61CcF92a`](https://celo-sepolia.blockscout.com/address/0xe19447B12cb0d0220B2a501D8382be2f61CcF92a) | [`0xd077A400968890Eacc75cdc901F0356c943e4fDb`](https://celo-sepolia.blockscout.com/address/0xd077A400968890Eacc75cdc901F0356c943e4fDb) |
| Wrapped Ether (Celo native bridge) | WETH | [`0x2cE73DC897A3E10b3FF3F86470847c36ddB735cf`](https://celo-sepolia.blockscout.com/address/0x2cE73DC897A3E10b3FF3F86470847c36ddB735cf) | [`0x2cE73DC897A3E10b3FF3F86470847c36ddB735cf`](https://celo-sepolia.blockscout.com/address/0x2cE73DC897A3E10b3FF3F86470847c36ddB735cf) |
| Mento West African CFA franc | XOFm | [`0x5505b70207aE3B826c1A7607F19F3Bf73444A082`](https://celo-sepolia.blockscout.com/address/0x5505b70207aE3B826c1A7607F19F3Bf73444A082) | [`0x5505b70207aE3B826c1A7607F19F3Bf73444A082`](https://celo-sepolia.blockscout.com/address/0x5505b70207aE3B826c1A7607F19F3Bf73444A082) |
| Mento South African Rand | ZARm | [`0x10CCfB235b0E1Ed394bACE4560C3ed016697687e`](https://celo-sepolia.blockscout.com/address/0x10CCfB235b0E1Ed394bACE4560C3ed016697687e) | [`0x10CCfB235b0E1Ed394bACE4560C3ed016697687e`](https://celo-sepolia.blockscout.com/address/0x10CCfB235b0E1Ed394bACE4560C3ed016697687e) |
# L1 Contracts
Source: https://docs.celo.org/tooling/contracts/l1-contracts
[comment]: <> "DO NOT EDIT THIS FILE MANUALLY"
[comment]: <> "Autogenerated by `scripts/update_contracts.py`"
L1 contract addresses for the Celo networks.
## Celo Mainnet
| Contract | Address |
| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| AddressManager | [`0x55093104b76FAA602F9d6c35A5FFF576bE78d753`](https://eth.blockscout.com/address/0x55093104b76FAA602F9d6c35A5FFF576bE78d753) |
| AnchorStateRegistryProxy | [`0x8fE58d2168b5412Cf1Bd212cE6137f8b7300222d`](https://eth.blockscout.com/address/0x8fE58d2168b5412Cf1Bd212cE6137f8b7300222d) |
| AnchorStateRegistryImpl | [`0xeb69cc681e8d4a557b30dffbad85affd47a2cf2e`](https://eth.blockscout.com/address/0xeb69cc681e8d4a557b30dffbad85affd47a2cf2e) |
| CeloSuperchainConfigProxy | [`0x25035d2233d099f0BA710ca1e5a3834842870C66`](https://eth.blockscout.com/address/0x25035d2233d099f0BA710ca1e5a3834842870C66) |
| CeloSuperchainConfigImpl | [`0xa59b2ebf8231f0e31508bd18e9185beb5ab1c038`](https://eth.blockscout.com/address/0xa59b2ebf8231f0e31508bd18e9185beb5ab1c038) |
| CeloTokenProxy | [`0x057898f3C43F129a17517B9056D23851F124b19f`](https://eth.blockscout.com/address/0x057898f3C43F129a17517B9056D23851F124b19f) |
| CeloTokenImpl | [`0x64fe3f9201e6534d2d744c7c57d134e709131a6e`](https://eth.blockscout.com/address/0x64fe3f9201e6534d2d744c7c57d134e709131a6e) |
| DisputeGameFactoryProxy | [`0xFbAC162162f4009Bb007C6DeBC36B1dAC10aF683`](https://eth.blockscout.com/address/0xFbAC162162f4009Bb007C6DeBC36B1dAC10aF683) |
| DisputeGameFactoryImpl | [`0x74fac1d45b98bae058f8f566201c9a81b85c7d50`](https://eth.blockscout.com/address/0x74fac1d45b98bae058f8f566201c9a81b85c7d50) |
| L1CrossDomainMessengerProxy | [`0x1AC1181fc4e4F877963680587AEAa2C90D7EbB95`](https://eth.blockscout.com/address/0x1AC1181fc4e4F877963680587AEAa2C90D7EbB95) |
| L1CrossDomainMessengerImpl | [`0xE45D2d835d0b2D3C7f4fEe1eaa19A068d0ba8A88`](https://eth.blockscout.com/address/0xE45D2d835d0b2D3C7f4fEe1eaa19A068d0ba8A88) |
| L1ERC721BridgeProxy | [`0x3C519816C5BdC0a0199147594F83feD4F5847f13`](https://eth.blockscout.com/address/0x3C519816C5BdC0a0199147594F83feD4F5847f13) |
| L1ERC721BridgeImpl | [`0x74f1ac50eb0be98853805d381c884f5f9abdecf9`](https://eth.blockscout.com/address/0x74f1ac50eb0be98853805d381c884f5f9abdecf9) |
| L1StandardBridgeProxy | [`0x9C4955b92F34148dbcfDCD82e9c9eCe5CF2badfe`](https://eth.blockscout.com/address/0x9C4955b92F34148dbcfDCD82e9c9eCe5CF2badfe) |
| L1StandardBridgeImpl | [`0xfa707f45a23370d9154af4457401274e38fa2d8a`](https://eth.blockscout.com/address/0xfa707f45a23370d9154af4457401274e38fa2d8a) |
| MIPS | [`0x6463dEE3828677F6270d83d45408044fc5eDB908`](https://eth.blockscout.com/address/0x6463dEE3828677F6270d83d45408044fc5eDB908) |
| OptimismMintableERC20FactoryProxy | [`0x6f0E4f1EB98A52EfaCF7BE11d48B9d9d6510A906`](https://eth.blockscout.com/address/0x6f0E4f1EB98A52EfaCF7BE11d48B9d9d6510A906) |
| OptimismMintableERC20FactoryImpl | [`0x149bd036f5f57d0ff4b5f102c9d46e3c0eb2c016`](https://eth.blockscout.com/address/0x149bd036f5f57d0ff4b5f102c9d46e3c0eb2c016) |
| OptimismPortalProxy | [`0xc5c5D157928BDBD2ACf6d0777626b6C75a9EAEDC`](https://eth.blockscout.com/address/0xc5c5D157928BDBD2ACf6d0777626b6C75a9EAEDC) |
| OptimismPortalImpl | [`0x2c431080fc733e259654f3b91e39468d9a85ac9b`](https://eth.blockscout.com/address/0x2c431080fc733e259654f3b91e39468d9a85ac9b) |
| PermissionedDelayedWETHProxy | [`0x91FA5B653aFe81A79890A93ad83768A04cc011b4`](https://eth.blockscout.com/address/0x91FA5B653aFe81A79890A93ad83768A04cc011b4) |
| PermissionedDelayedWETHImpl | [`0xb86a464cc743440fddaa43900e05318ef4818b29`](https://eth.blockscout.com/address/0xb86a464cc743440fddaa43900e05318ef4818b29) |
| PermissionedDisputeGame | [`0xa83a2E8595b602aD98C928E9cD123c0E05C84FD9`](https://eth.blockscout.com/address/0xa83a2E8595b602aD98C928E9cD123c0E05C84FD9) |
| PreimageOracle | [`0x1fb8cdfc6831fc866ed9c51af8817da5c287add3`](https://eth.blockscout.com/address/0x1fb8cdfc6831fc866ed9c51af8817da5c287add3) |
| ProtocolVersionsProxy | [`0x1b6dEB2197418075AB314ac4D52Ca1D104a8F663`](https://eth.blockscout.com/address/0x1b6dEB2197418075AB314ac4D52Ca1D104a8F663) |
| ProtocolVersionsImpl | [`0x37e15e4d6dffa9e5e320ee1ec036922e563cb76c`](https://eth.blockscout.com/address/0x37e15e4d6dffa9e5e320ee1ec036922e563cb76c) |
| ProxyAdmin | [`0x783A434532Ee94667979213af1711505E8bFE374`](https://eth.blockscout.com/address/0x783A434532Ee94667979213af1711505E8bFE374) |
| SuperchainConfigProxy | [`0x95703e0982140D16f8ebA6d158FccEde42f04a4C`](https://eth.blockscout.com/address/0x95703e0982140D16f8ebA6d158FccEde42f04a4C) |
| SuperchainConfigImpl | [`0xb08cc720f511062537ca78bdb0ae691f04f5a957`](https://eth.blockscout.com/address/0xb08cc720f511062537ca78bdb0ae691f04f5a957) |
| SystemConfigProxy | [`0x89E31965D844a309231B1f17759Ccaf1b7c09861`](https://eth.blockscout.com/address/0x89E31965D844a309231B1f17759Ccaf1b7c09861) |
| SystemConfigImpl | [`0xe5dc3c0a3489b81a6f3ae3bb49bf9ccbfb85a3db`](https://eth.blockscout.com/address/0xe5dc3c0a3489b81a6f3ae3bb49bf9ccbfb85a3db) |
| SystemOwnerSafe | [`0x4092A77bAF58fef0309452cEaCb09221e556E112`](https://eth.blockscout.com/address/0x4092A77bAF58fef0309452cEaCb09221e556E112) |
## Celo Sepolia Testnet
| Contract | Address |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| AddressManager | [`0x8f0c6fc85a53551d87899ac2a5af2b48c793eb63`](https://eth-sepolia.blockscout.com/address/0x8f0c6fc85a53551d87899ac2a5af2b48c793eb63) |
| AnchorStateRegistryProxy | [`0xe689F6d101a6aFeBddB093c59D4fB5B3087561a7`](https://eth-sepolia.blockscout.com/address/0xe689F6d101a6aFeBddB093c59D4fB5B3087561a7) |
| AnchorStateRegistryImpl | [`0xeb69cc681e8d4a557b30dffbad85affd47a2cf2e`](https://eth-sepolia.blockscout.com/address/0xeb69cc681e8d4a557b30dffbad85affd47a2cf2e) |
| CeloSuperchainConfigProxy | [`0x7934c0D58df75F597F62dB898Ec537B5945BA643`](https://eth-sepolia.blockscout.com/address/0x7934c0D58df75F597F62dB898Ec537B5945BA643) |
| CeloSuperchainConfigImpl | [`0xa59b2ebf8231f0e31508bd18e9185beb5ab1c038`](https://eth-sepolia.blockscout.com/address/0xa59b2ebf8231f0e31508bd18e9185beb5ab1c038) |
| CeloTokenProxy | [`0x3c7011fd5e6aed460caa4985cf8d8caba435b092`](https://eth-sepolia.blockscout.com/address/0x3c7011fd5e6aed460caa4985cf8d8caba435b092) |
| CeloTokenImpl | [`0x93ec064ad109077d42b1581c8fa4e8eba34b2d13`](https://eth-sepolia.blockscout.com/address/0x93ec064ad109077d42b1581c8fa4e8eba34b2d13) |
| DisputeGameFactoryProxy | [`0x57C45d82D1a995F1e135B8D7EDc0a6BB5211cfAA`](https://eth-sepolia.blockscout.com/address/0x57C45d82D1a995F1e135B8D7EDc0a6BB5211cfAA) |
| DisputeGameFactoryImpl | [`0x74fac1d45b98bae058f8f566201c9a81b85c7d50`](https://eth-sepolia.blockscout.com/address/0x74fac1d45b98bae058f8f566201c9a81b85c7d50) |
| L1CrossDomainMessengerProxy | [`0x70b0e58e6039831954ede2ea1e9ef8a51680e4fd`](https://eth-sepolia.blockscout.com/address/0x70b0e58e6039831954ede2ea1e9ef8a51680e4fd) |
| L1CrossDomainMessengerImpl | [`0xE45D2d835d0b2D3C7f4fEe1eaa19A068d0ba8A88`](https://eth-sepolia.blockscout.com/address/0xE45D2d835d0b2D3C7f4fEe1eaa19A068d0ba8A88) |
| L1ERC721BridgeProxy | [`0xb8c8dcbccd0f7c5e7a2184b13b85d461d8711e96`](https://eth-sepolia.blockscout.com/address/0xb8c8dcbccd0f7c5e7a2184b13b85d461d8711e96) |
| L1ERC721BridgeImpl | [`0x74f1ac50eb0be98853805d381c884f5f9abdecf9`](https://eth-sepolia.blockscout.com/address/0x74f1ac50eb0be98853805d381c884f5f9abdecf9) |
| L1StandardBridgeProxy | [`0xec18a3c30131a0db4246e785355fbc16e2eaf408`](https://eth-sepolia.blockscout.com/address/0xec18a3c30131a0db4246e785355fbc16e2eaf408) |
| L1StandardBridgeImpl | [`0xfa707f45a23370d9154af4457401274e38fa2d8a`](https://eth-sepolia.blockscout.com/address/0xfa707f45a23370d9154af4457401274e38fa2d8a) |
| MIPS | [`0x6463dee3828677f6270d83d45408044fc5edb908`](https://eth-sepolia.blockscout.com/address/0x6463dee3828677f6270d83d45408044fc5edb908) |
| OptimismMintableERC20FactoryProxy | [`0x261be2ed7241fed9c746e0b5dff3a4a335991377`](https://eth-sepolia.blockscout.com/address/0x261be2ed7241fed9c746e0b5dff3a4a335991377) |
| OptimismMintableERC20FactoryImpl | [`0x149bd036f5f57d0ff4b5f102c9d46e3c0eb2c016`](https://eth-sepolia.blockscout.com/address/0x149bd036f5f57d0ff4b5f102c9d46e3c0eb2c016) |
| OptimismPortalProxy | [`0x44ae3d41a335a7d05eb533029917aad35662dcc2`](https://eth-sepolia.blockscout.com/address/0x44ae3d41a335a7d05eb533029917aad35662dcc2) |
| OptimismPortalImpl | [`0x2c431080fc733e259654f3b91e39468d9a85ac9b`](https://eth-sepolia.blockscout.com/address/0x2c431080fc733e259654f3b91e39468d9a85ac9b) |
| PermissionedDelayedWETHProxy | [`0x5D27C0E30b0e9cEa56936e9326AdCEE480D2ab08`](https://eth-sepolia.blockscout.com/address/0x5D27C0E30b0e9cEa56936e9326AdCEE480D2ab08) |
| PermissionedDelayedWETHImpl | [`0xb86a464cc743440fddaa43900e05318ef4818b29`](https://eth-sepolia.blockscout.com/address/0xb86a464cc743440fddaa43900e05318ef4818b29) |
| PermissionedDisputeGame | [`0x865Fc858bC76B8132bBF744dd5ac95D30A5F490D`](https://eth-sepolia.blockscout.com/address/0x865Fc858bC76B8132bBF744dd5ac95D30A5F490D) |
| PreimageOracle | [`0x1fb8cdfc6831fc866ed9c51af8817da5c287add3`](https://eth-sepolia.blockscout.com/address/0x1fb8cdfc6831fc866ed9c51af8817da5c287add3) |
| ProtocolVersionsProxy | [`0x0e2d45F3393C3A02ebf285F998c5bF990A1541cd`](https://eth-sepolia.blockscout.com/address/0x0e2d45F3393C3A02ebf285F998c5bF990A1541cd) |
| ProtocolVersionsImpl | [`0x9a7ca01b64ce656b927248af08692ed2714c68e0`](https://eth-sepolia.blockscout.com/address/0x9a7ca01b64ce656b927248af08692ed2714c68e0) |
| ProxyAdmin | [`0xf7d7a3d3bb8abb6829249b3d3ad3d525d052027e`](https://eth-sepolia.blockscout.com/address/0xf7d7a3d3bb8abb6829249b3d3ad3d525d052027e) |
| SuperchainConfigProxy | [`0x31bEef32135c90AE8E56Fb071B3587de289Aaf77`](https://eth-sepolia.blockscout.com/address/0x31bEef32135c90AE8E56Fb071B3587de289Aaf77) |
| SuperchainConfigImpl | [`0xb08cc720f511062537ca78bdb0ae691f04f5a957`](https://eth-sepolia.blockscout.com/address/0xb08cc720f511062537ca78bdb0ae691f04f5a957) |
| SystemConfigProxy | [`0x760a5f022c9940f4a074e0030be682f560d29818`](https://eth-sepolia.blockscout.com/address/0x760a5f022c9940f4a074e0030be682f560d29818) |
| SystemConfigImpl | [`0xe5dc3c0a3489b81a6f3ae3bb49bf9ccbfb85a3db`](https://eth-sepolia.blockscout.com/address/0xe5dc3c0a3489b81a6f3ae3bb49bf9ccbfb85a3db) |
| SystemOwnerSafe | [`0x5e60d897Cd62588291656b54655e98ee73f0aabF`](https://eth-sepolia.blockscout.com/address/0x5e60d897Cd62588291656b54655e98ee73f0aabF) |
# Stablecoin Contracts
Source: https://docs.celo.org/tooling/contracts/stablecoin-contracts
[comment]: <> "DO NOT EDIT THIS FILE MANUALLY"
[comment]: <> "Autogenerated by `scripts/update_contracts.py`"
Contract addresses for stablecoins on Celo Mainnet and the Celo Sepolia Testnet. For an overview of the ecosystem these assets belong to, see [Build with Local Stablecoins](/build-on-celo/build-with-local-stablecoin). To find out which of them can also pay gas fees, see [Fee Currencies](/tooling/contracts/fee-currencies).
These addresses are listed for convenience and do not imply any endorsement of the issuer or the asset. Verify an address against a block explorer before using it in production.
| Stablecoin | Issuer | Celo Mainnet | Celo Sepolia Testnet |
| ---------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| **AUDm** | [Mento](https://www.mento.org/) | [`0x7175504C455076F15c04A2F90a8e352281F492F9`](https://celo.blockscout.com/address/0x7175504C455076F15c04A2F90a8e352281F492F9) | [`0x5873Faeb42F3563dcD77F0fbbdA818E6d6DA3139`](https://celo-sepolia.blockscout.com/address/0x5873Faeb42F3563dcD77F0fbbdA818E6d6DA3139) |
| **BRLm** | [Mento](https://www.mento.org/) | [`0xe8537a3d056DA446677B9E9d6c5dB704EaAb4787`](https://celo.blockscout.com/address/0xe8537a3d056DA446677B9E9d6c5dB704EaAb4787) | [`0x2294298942fdc79417DE9E0D740A4957E0e7783a`](https://celo-sepolia.blockscout.com/address/0x2294298942fdc79417DE9E0D740A4957E0e7783a) |
| **CADm** | [Mento](https://www.mento.org/) | [`0xff4Ab19391af240c311c54200a492233052B6325`](https://celo.blockscout.com/address/0xff4Ab19391af240c311c54200a492233052B6325) | [`0xF151c9a13b78C84f93f50B8b3bC689fedc134F60`](https://celo-sepolia.blockscout.com/address/0xF151c9a13b78C84f93f50B8b3bC689fedc134F60) |
| **CHFm** | [Mento](https://www.mento.org/) | [`0xb55a79F398E759E43C95b979163f30eC87Ee131D`](https://celo.blockscout.com/address/0xb55a79F398E759E43C95b979163f30eC87Ee131D) | [`0x284E9b7B623eAE866914b7FA0eB720C2Bb3C2980`](https://celo-sepolia.blockscout.com/address/0x284E9b7B623eAE866914b7FA0eB720C2Bb3C2980) |
| **COPm** | [Mento](https://www.mento.org/) | [`0x8A567e2aE79CA692Bd748aB832081C45de4041eA`](https://celo.blockscout.com/address/0x8A567e2aE79CA692Bd748aB832081C45de4041eA) | [`0x5F8d55c3627d2dc0a2B4afa798f877242F382F67`](https://celo-sepolia.blockscout.com/address/0x5F8d55c3627d2dc0a2B4afa798f877242F382F67) |
| **EURm** | [Mento](https://www.mento.org/) | [`0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73`](https://celo.blockscout.com/address/0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73) | [`0xA99dC247d6b7B2E3ab48a1fEE101b83cD6aCd82a`](https://celo-sepolia.blockscout.com/address/0xA99dC247d6b7B2E3ab48a1fEE101b83cD6aCd82a) |
| **GBPm** | [Mento](https://www.mento.org/) | [`0xCCF663b1fF11028f0b19058d0f7B674004a40746`](https://celo.blockscout.com/address/0xCCF663b1fF11028f0b19058d0f7B674004a40746) | [`0x85F5181Abdbf0e1814Fc4358582Ae07b8eBA3aF3`](https://celo-sepolia.blockscout.com/address/0x85F5181Abdbf0e1814Fc4358582Ae07b8eBA3aF3) |
| **GHSm** | [Mento](https://www.mento.org/) | [`0xfAeA5F3404bbA20D3cc2f8C4B0A888F55a3c7313`](https://celo.blockscout.com/address/0xfAeA5F3404bbA20D3cc2f8C4B0A888F55a3c7313) | [`0x5e94B8C872bD47BC4255E60ECBF44D5E66e7401C`](https://celo-sepolia.blockscout.com/address/0x5e94B8C872bD47BC4255E60ECBF44D5E66e7401C) |
| **JPYm** | [Mento](https://www.mento.org/) | [`0xc45eCF20f3CD864B32D9794d6f76814aE8892e20`](https://celo.blockscout.com/address/0xc45eCF20f3CD864B32D9794d6f76814aE8892e20) | [`0x85Bee67D435A39f7467a8a9DE34a5B73D25Df426`](https://celo-sepolia.blockscout.com/address/0x85Bee67D435A39f7467a8a9DE34a5B73D25Df426) |
| **KESm** | [Mento](https://www.mento.org/) | [`0x456a3D042C0DbD3db53D5489e98dFb038553B0d0`](https://celo.blockscout.com/address/0x456a3D042C0DbD3db53D5489e98dFb038553B0d0) | [`0xC7e4635651E3e3Af82b61d3E23c159438daE3BbF`](https://celo-sepolia.blockscout.com/address/0xC7e4635651E3e3Af82b61d3E23c159438daE3BbF) |
| **NGNm** | [Mento](https://www.mento.org/) | [`0xE2702Bd97ee33c88c8f6f92DA3B733608aa76F71`](https://celo.blockscout.com/address/0xE2702Bd97ee33c88c8f6f92DA3B733608aa76F71) | [`0x3d5ae86F34E2a82771496D140daFAEf3789dF888`](https://celo-sepolia.blockscout.com/address/0x3d5ae86F34E2a82771496D140daFAEf3789dF888) |
| **PHPm** | [Mento](https://www.mento.org/) | [`0x105d4A9306D2E55a71d2Eb95B81553AE1dC20d7B`](https://celo.blockscout.com/address/0x105d4A9306D2E55a71d2Eb95B81553AE1dC20d7B) | [`0x0352976d940a2C3FBa0C3623198947Ee1d17869E`](https://celo-sepolia.blockscout.com/address/0x0352976d940a2C3FBa0C3623198947Ee1d17869E) |
| **USA₮** | [Anchorage Digital Bank](https://usat.io/) | [`0xD2ab3C9A02DBBAB236BfEC45D1d755DF4267F771`](https://celo.blockscout.com/address/0xD2ab3C9A02DBBAB236BfEC45D1d755DF4267F771) | - |
| **USDC** | [Circle](https://www.circle.com/usdc) | [`0xcebA9300f2b948710d2653dD7B07f33A8B32118C`](https://celo.blockscout.com/address/0xcebA9300f2b948710d2653dD7B07f33A8B32118C) | [`0x01C5C0122039549AD1493B8220cABEdD739BC44E`](https://celo-sepolia.blockscout.com/address/0x01C5C0122039549AD1493B8220cABEdD739BC44E) |
| **USDm** | [Mento](https://www.mento.org/) | [`0x765DE816845861e75A25fCA122bb6898B8B1282a`](https://celo.blockscout.com/address/0x765DE816845861e75A25fCA122bb6898B8B1282a) | [`0xdE9e4C3ce781b4bA68120d6261cbad65ce0aB00b`](https://celo-sepolia.blockscout.com/address/0xdE9e4C3ce781b4bA68120d6261cbad65ce0aB00b) |
| **USD₮** | [Tether](https://tether.to/en/) | [`0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e`](https://celo.blockscout.com/address/0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e) | [`0xd077A400968890Eacc75cdc901F0356c943e4fDb`](https://celo-sepolia.blockscout.com/address/0xd077A400968890Eacc75cdc901F0356c943e4fDb) |
| **XOFm** | [Mento](https://www.mento.org/) | [`0x73F93dcc49cB8A239e2032663e9475dd5ef29A08`](https://celo.blockscout.com/address/0x73F93dcc49cB8A239e2032663e9475dd5ef29A08) | [`0x5505b70207aE3B826c1A7607F19F3Bf73444A082`](https://celo-sepolia.blockscout.com/address/0x5505b70207aE3B826c1A7607F19F3Bf73444A082) |
| **ZARm** | [Mento](https://www.mento.org/) | [`0x4c35853A3B4e647fD266f4de678dCc8fEC410BF6`](https://celo.blockscout.com/address/0x4c35853A3B4e647fD266f4de678dCc8fEC410BF6) | [`0x10CCfB235b0E1Ed394bACE4560C3ed016697687e`](https://celo-sepolia.blockscout.com/address/0x10CCfB235b0E1Ed394bACE4560C3ed016697687e) |
| **BRLA** | [BRLA](https://brla.digital/) | [`0xfecb3f7c54e2caae9dc6ac9060a822d47e053760`](https://celo.blockscout.com/address/0xfecb3f7c54e2caae9dc6ac9060a822d47e053760) | - |
| **cNGN** | [Africa Stablecoin Consortium](https://cngn.co/) | [`0xF6829D7393dAe24509eb1E52eE8e572e2E271a4f`](https://celo.blockscout.com/address/0xF6829D7393dAe24509eb1E52eE8e572e2E271a4f) | - |
| **COPM** | [Minteo](https://minteo.com/) | [`0xC92E8Fc2947E32F2B574CCA9F2F12097A71d5606`](https://celo.blockscout.com/address/0xC92E8Fc2947E32F2B574CCA9F2F12097A71d5606) | - |
| **EURA** | [Angle](https://www.angle.money/) | [`0xC16B81Af351BA9e64C1a069E3Ab18c244A1E3049`](https://celo.blockscout.com/address/0xC16B81Af351BA9e64C1a069E3Ab18c244A1E3049) | - |
| **G\$** | [GoodDollar](https://www.gooddollar.org/) | [`0x62b8b11039fcfe5ab0c56e502b1c372a3d2a9c7a`](https://celo.blockscout.com/address/0x62b8b11039fcfe5ab0c56e502b1c372a3d2a9c7a) | - |
| **USDA** | [Angle](https://www.angle.money/) | [`0x0000206329b97DB379d5E1Bf586BbDB969C63274`](https://celo.blockscout.com/address/0x0000206329b97DB379d5E1Bf586BbDB969C63274) | - |
| **USDGLO** | [Glo Foundation](https://www.glodollar.org/) | [`0x4f604735c1cf31399c6e711d5962b2b3e0225ad3`](https://celo.blockscout.com/address/0x4f604735c1cf31399c6e711d5962b2b3e0225ad3) | - |
| **USDM** | [Mountain Protocol](https://mountainprotocol.com/) | [`0x59D9356E565Ab3A36dD77763Fc0d87fEaf85508C`](https://celo.blockscout.com/address/0x59D9356E565Ab3A36dD77763Fc0d87fEaf85508C) | - |
| **vCHF** | [VNX](https://vnx.li/) | [`0xc5ebea9984c485ec5d58ca5a2d376620d93af871`](https://celo.blockscout.com/address/0xc5ebea9984c485ec5d58ca5a2d376620d93af871) | - |
| **vGBP** | [VNX](https://vnx.li/) | [`0x7ae4265ecfc1f31bc0e112dfcfe3d78e01f4bb7f`](https://celo.blockscout.com/address/0x7ae4265ecfc1f31bc0e112dfcfe3d78e01f4bb7f) | - |
| **wARS** | [Ripio](https://ripio.com/) | [`0x0dc4f92879b7670e5f4e4e6e3c801d229129d90d`](https://celo.blockscout.com/address/0x0dc4f92879b7670e5f4e4e6e3c801d229129d90d) | - |
| **wBRL** | [Ripio](https://ripio.com/) | [`0xd76f5faf6888e24d9f04bf92a0c8b921fe4390e0`](https://celo.blockscout.com/address/0xd76f5faf6888e24d9f04bf92a0c8b921fe4390e0) | - |
| **wCLP** | [Ripio](https://ripio.com/) | [`0x61D450a098b6a7f69fC4b98CE68198fe59768651`](https://celo.blockscout.com/address/0x61D450a098b6a7f69fC4b98CE68198fe59768651) | - |
| **wCOP** | [Ripio](https://ripio.com/) | [`0x8a1d45e102e886510e891d2ec656a708991e2d76`](https://celo.blockscout.com/address/0x8a1d45e102e886510e891d2ec656a708991e2d76) | - |
| **wMXN** | [Ripio](https://ripio.com/) | [`0x337e7456b420bd3481e7fa61fa9850343d610d34`](https://celo.blockscout.com/address/0x337e7456b420bd3481e7fa61fa9850343d610d34) | - |
| **wPEN** | [Ripio](https://ripio.com/) | [`0x4F34c8b3b5FB6D98Da888F0feA543d4d9C9F2eBE`](https://celo.blockscout.com/address/0x4F34c8b3b5FB6D98Da888F0feA543d4d9C9F2eBE) | - |
# Uniswap Contracts
Source: https://docs.celo.org/tooling/contracts/uniswap-contracts
The latest versions of Uniswap v4 and v3 contracts are deployed at the addresses listed below, on both Celo mainnet and the Celo Sepolia testnet. Integrators should no longer assume that they are deployed to the same addresses across chains and be extremely careful to confirm mappings below.
## Uniswap V4 Contracts
Uniswap v4 introduces a new modular architecture with hooks and singleton pool manager design. The core contracts are deployed on Celo mainnet and on the Celo Sepolia testnet.
| Contract | CELO Address | Celo Sepolia Address |
| ------------------ | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| PoolManager | [0x288dc841A52FCA2707c6947B3A777c5E56cd87BC](https://celoscan.io/address/0x288dc841A52FCA2707c6947B3A777c5E56cd87BC) | [0x2af85C83CFe7bC5182F81E5aE82661b4E9F15A1e](https://celo-sepolia.blockscout.com/address/0x2af85C83CFe7bC5182F81E5aE82661b4E9F15A1e) |
| PositionManager | [0xf7965f3981e4d5bc383bfbcb61501763e9068ca9](https://celoscan.io/address/0xf7965f3981e4d5bc383bfbcb61501763e9068ca9) | [0xB104b7c42DAB49d31fe3Ea91Dd80305348Cc37C1](https://celo-sepolia.blockscout.com/address/0xB104b7c42DAB49d31fe3Ea91Dd80305348Cc37C1) |
| PositionDescriptor | [0x5727E22b25fEEe05E8dFa83C752B86F19D102D8A](https://celoscan.io/address/0x5727E22b25fEEe05E8dFa83C752B86F19D102D8A) | [0x3B13783e319Be24E2b9Db588745eA3202723B497](https://celo-sepolia.blockscout.com/address/0x3B13783e319Be24E2b9Db588745eA3202723B497) |
| V4Quoter | [0x28566da1093609182dff2cb2a91cfd72e61d66cd](https://celoscan.io/address/0x28566da1093609182dff2cb2a91cfd72e61d66cd) | [0xca5E523FA87c7dC67762c8E7f4a65783899b3c72](https://celo-sepolia.blockscout.com/address/0xca5E523FA87c7dC67762c8E7f4a65783899b3c72) |
| StateView | [0xbc21f8720babf4b20d195ee5c6e99c52b76f2bfb](https://celoscan.io/address/0xbc21f8720babf4b20d195ee5c6e99c52b76f2bfb) | [0xF7e0Ba08d608cE1c90498c763e9fa001404e2a4b](https://celo-sepolia.blockscout.com/address/0xF7e0Ba08d608cE1c90498c763e9fa001404e2a4b) |
| UniversalRouter | [0xcb695bc5d3aa22cad1e6df07801b061a05a0233a](https://celoscan.io/address/0xcb695bc5d3aa22cad1e6df07801b061a05a0233a) | [0x8891A0A682cC7f0bda7912E79C80167403d96103](https://celo-sepolia.blockscout.com/address/0x8891A0A682cC7f0bda7912E79C80167403d96103) |
| Permit2 | [0x000000000022D473030F116dDEE9F6B43aC78BA3](https://celoscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3) | [0x000000000022D473030F116dDEE9F6B43aC78BA3](https://celo-sepolia.blockscout.com/address/0x000000000022D473030F116dDEE9F6B43aC78BA3) |
On Celo Sepolia the `UniversalRouter` and `PositionManager` use the CELO ERC-20 (`0x471EcE3750Da237f93B8E339c536989b8978a438`) as their wrapped-native (`weth9`) slot, matching Celo mainnet. CELO does not implement `deposit()` / `withdraw()` on the L2, so the router's `WRAP_ETH` / `UNWRAP_WETH` commands will revert. Pools using the native asset (`address(0)`) or CELO as an ERC-20 are unaffected.
Two test routers (`PoolSwapTest` at [0x42592B9fFA3be9351cf06EC499e28b88a4A99f50](https://celo-sepolia.blockscout.com/address/0x42592B9fFA3be9351cf06EC499e28b88a4A99f50), `PoolModifyLiquidityTest` at [0x643ddc282cD4C65a40cd96c27968B63a2e31cF6d](https://celo-sepolia.blockscout.com/address/0x643ddc282cD4C65a40cd96c27968B63a2e31cF6d)) are also deployed on Celo Sepolia for convenience.
## Uniswap V3 Contracts
| Contract | CELO Address | Alfajores Address |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| UniswapV3Factory | [0xAfE208a311B21f13EF87E33A90049fC17A7acDEc](https://celoscan.io/address/0xAfE208a311B21f13EF87E33A90049fC17A7acDEc) | [0x229Fd76DA9062C1a10eb4193768E192bdEA99572](https://alfajores.celoscan.io/address/0x229Fd76DA9062C1a10eb4193768E192bdEA99572) |
| Multicall2 | [0x633987602DE5C4F337e3DbF265303A1080324204](https://celoscan.io/address/0x633987602DE5C4F337e3DbF265303A1080324204) | [0x692A12C7C167c44e54c3d381CA3EE91F058Dc404](https://alfajores.celoscan.io/address/0x692A12C7C167c44e54c3d381CA3EE91F058Dc404) |
| ProxyAdmin | [0xc1b262Dd7643D4B7cA9e51631bBd900a564BF49A](https://celoscan.io/address/0xc1b262Dd7643D4B7cA9e51631bBd900a564BF49A) | [0xE4d1eBb97Fe5fabFaBbB8C004C424EE12dE8A07d](https://alfajores.celoscan.io/address/0xE4d1eBb97Fe5fabFaBbB8C004C424EE12dE8A07d) |
| TickLens | [0x5f115D9113F88e0a0Db1b5033D90D4a9690AcD3D](https://celoscan.io/address/0x5f115D9113F88e0a0Db1b5033D90D4a9690AcD3D) | [0xFdACaEfB0f85C9BE9d319023453cC85C812d7e1E](https://alfajores.celoscan.io/address/0xFdACaEfB0f85C9BE9d319023453cC85C812d7e1E) |
| NFTDescriptor | [0xa9Fd765d85938D278cb0b108DbE4BF7186831186](https://celoscan.io/address/0xa9Fd765d85938D278cb0b108DbE4BF7186831186) | [0xE3da4F834D45b27AF95600e6546991dC3B50adAC](https://alfajores.celoscan.io/address/0xE3da4F834D45b27AF95600e6546991dC3B50adAC) |
| NonfungibleTokenPositionDescriptor | [0x644023b316bB65175C347DE903B60a756F6dd554](https://celoscan.io/address/0x644023b316bB65175C347DE903B60a756F6dd554) | [0xB00B8C3aB078EB0f7DeC6cE19c1a1da5bf4f8d7e](https://alfajores.celoscan.io/address/0xB00B8C3aB078EB0f7DeC6cE19c1a1da5bf4f8d7e) |
| TransparentUpgradeableProxy | [0x505B43c452AA4443e0a6B84bb37771494633Fde9](https://celoscan.io/address/0x505B43c452AA4443e0a6B84bb37771494633Fde9) | [0x9ddD6325FBE93A715B422883cED853CD843f217C](https://alfajores.celoscan.io/address/0x9ddD6325FBE93A715B422883cED853CD843f217C) |
| NonfungiblePositionManager | [0x3d79EdAaBC0EaB6F08ED885C05Fc0B014290D95A](https://celoscan.io/address/0x3d79EdAaBC0EaB6F08ED885C05Fc0B014290D95A) | [0x0eC9d3C06Bc0A472A80085244d897bb604548824](https://alfajores.celoscan.io/address/0x0eC9d3C06Bc0A472A80085244d897bb604548824) |
| V3Migrator | [0x3cFd4d48EDfDCC53D3f173F596f621064614C582](https://celoscan.io/address/0x3cFd4d48EDfDCC53D3f173F596f621064614C582) | [0x245d3F47F55c532dbE9340368855Be631B162cfd](https://alfajores.celoscan.io/address/0x245d3F47F55c532dbE9340368855Be631B162cfd) |
| QuoterV2 | [0x82825d0554fA07f7FC52Ab63c961F330fdEFa8E8](https://celoscan.io/address/0x82825d0554fA07f7FC52Ab63c961F330fdEFa8E8) | [0x3c1FCF8D6f3A579E98F4AE75EB0adA6de70f5673](https://alfajores.celoscan.io/address/0x3c1FCF8D6f3A579E98F4AE75EB0adA6de70f5673) |
| SwapRouter02 | [0x5615CDAb10dc425a742d643d949a7F474C01abc4](https://celoscan.io/address/0x5615CDAb10dc425a742d643d949a7F474C01abc4) | [0x8C456F41A3883bA0ba99f810F7A2Da54D9Ea3EF0](https://alfajores.celoscan.io/address/0x8C456F41A3883bA0ba99f810F7A2Da54D9Ea3EF0) |
| Permit2 | [0x000000000022D473030F116dDEE9F6B43aC78BA3](https://celoscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3) | [0x000000000022D473030F116dDEE9F6B43aC78BA3](https://alfajores.celoscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3) |
| UniversalRouter | [0x643770E279d5D0733F21d6DC03A8efbABf3255B4](https://celoscan.io/address/0x643770E279d5D0733F21d6DC03A8efbABf3255B4) | [0x84904B9E85F76a421223565be7b596d7d9A8b8Ce](https://alfajores.celoscan.io/address/0x84904B9E85F76a421223565be7b596d7d9A8b8Ce) |
| v3StakerAddress | [0x6586FB35393abF7Ff454977a9b3c912d218791C6](https://celoscan.io/address/0x6586FB35393abF7Ff454977a9b3c912d218791C6) | [0x8AC47D3e65a3e6aD14596ee7d18ad1d1aA53208F](https://alfajores.celoscan.io/address/0x8AC47D3e65a3e6aD14596ee7d18ad1d1aA53208F) |
# Deploy on Celo with Foundry
Source: https://docs.celo.org/tooling/dev-environments/foundry
How to deploy a smart contract to Celo testnet, Mainnet, or a local network using [Foundry](https://book.getfoundry.sh/).
***
## Introduction to Foundry
Foundry is a smart contract development toolchain.
Foundry manages your dependencies, compiles your project, runs tests, deploys, and lets you interact with the chain from the command-line and via Solidity scripts.
## Prerequisites
You will need the Rust compiler and Cargo, the Rust package manager. The easiest way to install both is with [rustup.rs](https://rustup.rs).
## Using Foundryup
Foundryup is the Foundry toolchain installer. You can find more about it here.
Open your terminal and run the following command:
```bash theme={null}
curl -L https://foundry.paradigm.xyz | bash
```
This will install Foundryup, then simply follow the instructions on-screen, which will make the foundryup command available in your CLI.
Running `foundryup` by itself will install the latest (nightly) precompiled binaries: `forge`, `cast`, `anvil`, and `chisel`.
## Create a new project using Forge
To start a new project with Foundry, use:
```bash theme={null}
forge init hello_foundry
```
If you initializing project in an already initialized git repo use:
```bash theme={null}
forge init project_name --no-git
```
## Adding a dependency
To add a dependency, use:
```bash theme={null}
forge install openzeppelin/openzeppelin-contracts
```
### Remapping dependencies
Forge can remap dependencies to make them easier to import. Forge will automatically try to deduce some remappings for you
```bash theme={null}
$ forge remappings
ds-test/=lib/solmate/lib/ds-test/src/
forge-std/=lib/forge-std/src/
solmate/=lib/solmate/src/
weird-erc20/=lib/weird-erc20/src/
```
These remappings mean:
* To import from `forge-std` we would write: import `forge-std/Contract.sol`;
* To import from `ds-test` we would write: import `ds-test/Contract.sol`;
* To import from `solmate` we would write: import `solmate/Contract.sol`;
* To import from `weird-erc20` we would write: import `weird-erc20/Contract.sol`;
You can customize these remappings by creating a `remappings.txt` file in the root of your project.
### Removing dependencies
You can remove dependencies using
```bash theme={null}
forge remove openzeppelin/openzeppelin-contracts
```
## Adding Celo specific config to `foundry.toml`
Add the following configuration to `foundry.toml` file in the root level of your project.
```toml theme={null}
[rpc_endpoints]
celo-sepolia = "https://forno.celo-sepolia.celo-testnet.org/"
celo = "https://forno.celo.org"
```
## Deploying contract
Forge can deploy smart contracts to a given network using:
The below example deploys `Counter` contract at location `src/Counter.sol` in the project to the Celo Sepolia Testnet.
```bash theme={null}
forge create --rpc-url celo-sepolia --private-key src/Counter.sol:Counter
```
Notice the contract name after `:`, this is because a single solidity file can have multiple contracts.
It is recommended to use `--verify` flag so that the contract gets verified right after deployment, this requires [etherscan configuration](/developer/verify/foundry) in the `foundry.toml` file.
On successful deployment, you should a following output!
# Deploy on Celo with Hardhat
Source: https://docs.celo.org/tooling/dev-environments/hardhat
How to deploy a smart contract to Celo testnet, Mainnet, or a local network using [Hardhat](https://hardhat.org/).
***
## Introduction to Hardhat
[Hardhat](https://hardhat.org/) is a development environment to compile, deploy, test, and debug your Ethereum or Celo software. It helps developers manage and automate the recurring tasks that are inherent to the process of building smart contracts and dApps, as well as easily introducing more functionality around this workflow. This means compiling, running, and testing smart contracts at the very core.
## Prerequisites
To deploy on Celo using Hardhat, you should have Celo set up Celo in your local environment. If you prefer to deploy without a local environment, you can deploy using Remix or Replit.
* [Using Windows](/tooling/overview/setup/windows)
* [Using Mac](/tooling/overview/setup/mac)
* [Using Replit](/tooling/overview/setup/replit)
## Create Hardhat Project
Choose one of the following items to prepare a dApp to deploy on Celo.
* Follow the [installation instructions and quickstart](https://hardhat.org/getting-started/#installation) to build and deploy your smart contract.
## Update the hardhat.config.js file
Open [hardhat.config.js](https://hardhat.org/config/) in a text editor and replace its contents with this [Celo configuration code](https://github.com/celo-org/celo-composer/blob/main/templates/contracts/hardhat/hardhat.config.ts.hbs). This code is similar to Hardhat settings with a few configuration updates needed to deploy to a Celo network. You will need to create a `.env` file in the project root directory and install `dotenv` with npm or yarn in order to read the `process.env.MNEMONIC` variable in the config file.
### Connect to Testnet using Forno
Using [Forno](/tooling/nodes/forno) allows you to connect to the Celo test blockchain without running a local node. The testnet configuration uses Forno to connect you to the Celo Sepolia Testnet using HDWalletProvider and the mnemonic stored in your **.env** file.
```js theme={null}
celoSepolia: {
url: "https://forno.celo-sepolia.celo-testnet.org/",
accounts: {
mnemonic: process.env.MNEMONIC,
path: "m/44'/52752'/0'/0"
},
chainId: 11142220
}
```
Celo uses a different account derivation path than Ethereum, so you have to specify "m/44'/52752'/0'/0" as the path.
### Connect to Mainnet using Forno
Using [Forno](/tooling/nodes/forno) also allows you to connect to the Celo main blockchain without running a local node. The Mainnet configuration uses Forno to connect you to the Celo Mainnet using HDWalletProvider and the mnemonic stored in your **.env** file.
```js theme={null}
celo: {
url: "https://forno.celo.org",
accounts: {
mnemonic: process.env.MNEMONIC,
path: "m/44'/52752'/0'/0"
},
chainId: 42220
}
```
[Forno](/tooling/nodes/forno) is a cLabs hosted node service for interacting with the Celo network. This allows you to connect to the Celo Blockchain without having to run your own node.
## Deploy to Celo
Run the following command from your root project directory to deploy to Celo Sepolia testnet.
```shell theme={null}
npx hardhat run scripts/sample-script.js --network celoSepolia
```
...or run this command to deploy to Celo Mainnet.
```shell theme={null}
npx hardhat run scripts/sample-script.js --network celo
```
## View Contract Deployment
Copy your **contract address** from the terminal and navigate to the [block explorer](https://celo.blockscout.com/) to search for your deployed contract. Switch between networks to find your contract using the dropdown by the search bar.
Learn more about building and deploying dApps using the HardHat documentation.
## Verify Contracts on Celo
* [Using Blockscout](/developer/verify/blockscout)
* [Using Remix](/developer/verify/remix)
* [Using CeloScan](/developer/verify/celoscan)
* [Using Hardhat](/developer/verify/hardhat)
# Build with Celo
Source: https://docs.celo.org/tooling/dev-environments/index
How to build and deploy a dApp with Celo.
***
## Using Celo Composer
[Celo Composer](https://github.com/celo-org/celo-composer) allows you to quickly build, deploy, and iterate on decentralized applications using Celo. It provides a number of frameworks, examples, and Celo specific functionality to help you get started with your next dApp.
```jsx theme={null}
npx @celo/celo-composer@latest create
```
Learn more about Celo Composer in the [README](https://github.com/celo-org/celo-composer) and [Documentation](https://celo-composer.gitbook.io/docs/)
## Using EVM Tools
```mdx-code-block theme={null}
Developers can build with Celo using many [Ethereum](https://ethereum.org/en/) compatible tools including Remix, Hardhat, and others. By making a few adjustments to your project’s network configuration settings, you can deploy your new or existing dApp on Celo.
```
* [Using thirdweb](/developer/deploy/thirdweb/overview)
* [Using Remix](/developer/deploy/remix)
* [Using Hardhat](/developer/deploy/hardhat)
# Smart Contracts
Source: https://docs.celo.org/tooling/dev-environments/multibaas/contracts
Deploy, link, and call smart contracts on Celo using the MultiBaas REST API and SDK.
MultiBaas manages contracts in two layers:
* **[Library](https://docs.curvegrid.com/multibaas/manage-contracts#smart-contract-library)** — contract definitions (ABI and bytecode)
* **[On-chain](https://docs.curvegrid.com/multibaas/manage-contracts#on-chain-smart-contracts)** — deployed instances linked to a blockchain address
## Adding a Contract to the Library
You can add a contract to the library in four ways:
1. **Direct ABI upload** — paste an ABI JSON directly
2. **Solidity source upload** — MultiBaas compiles it for you
3. **Address lookup** — MultiBaas fetches the ABI from Blockscout or Etherscan by contract address
4. **Framework plugin** — automated via the [Hardhat](#hardhat) or [Forge](#foundry--forge) plugin during deployment (see below)
## Deploying or Linking a Contract
### Deploy a new contract
1. Go to **Contracts → On-chain → + → Deploy Contract**
2. Select a contract from the library
3. Fill in constructor parameters
4. Optionally enable **Sync Events** and set a starting block for event indexing
5. Submit — if using a Cloud Wallet, MultiBaas signs and submits the transaction automatically
### Link an existing contract
1. Go to **Contracts → On-chain → + → Link Contract**
2. Enter the contract address (MultiBaas can auto-fetch the ABI from a block explorer)
3. Select the contract definition from the library
4. Optionally enable **Sync Events**
## Calling Contract Methods
Once a contract is linked, MultiBaas exposes all its functions via the [REST API](https://docs.curvegrid.com/multibaas/api/multibaas-api). Toggle on Developer Mode in the contract functions UI to see sample payload, curl, TypeScript, or golang code. The base URL for all API calls is:
```
https://.multibaas.com/api/v0
```
The API path uses `/chains/ethereum/` as a fixed prefix regardless of the actual EVM network. This is a MultiBaas convention — it works correctly for Celo.
### Using the TypeScript SDK
Install the [TypeScript SDK](https://www.npmjs.com/package/@curvegrid/multibaas-sdk):
```bash theme={null}
npm install @curvegrid/multibaas-sdk
```
Configure the client:
```typescript theme={null}
import * as MultiBaas from '@curvegrid/multibaas-sdk';
const config = new MultiBaas.Configuration({
basePath: `${process.env.MULTIBAAS_DEPLOYMENT_URL}/api/v0`,
accessToken: process.env.MULTIBAAS_API_KEY,
});
const contractsApi = new MultiBaas.ContractsApi(config);
```
**Read a contract function:**
```typescript theme={null}
const response = await contractsApi.callContractFunction(
'my-contract-alias', // address alias configured in MultiBaas
'MyContract', // contract label in the library
'balanceOf', // method name
{
args: ['0xRecipientAddress'],
signAndSubmit: false,
},
);
console.log(response.data.result.output);
```
**Write to a contract using a Cloud Wallet:**
```typescript theme={null}
const response = await contractsApi.callContractFunction(
'my-contract-alias',
'MyContract',
'transfer',
{
args: ['0xRecipientAddress', '1000000000000000000'],
from: process.env.CLOUD_WALLET_ADDRESS,
signAndSubmit: true,
},
);
console.log(response.data.result.tx.hash);
```
Setting `signAndSubmit: true` with a configured Cloud Wallet address instructs MultiBaas to sign and broadcast the transaction on your behalf.
**Write to a contract with an external wallet (viem):**
```typescript theme={null}
import { createWalletClient, custom } from 'viem';
import { celo } from 'viem/chains';
const walletClient = createWalletClient({
chain: celo,
transport: custom(window.ethereum),
});
// Get the unsigned transaction from MultiBaas
const response = await contractsApi.callContractFunction(
'my-contract-alias',
'MyContract',
'transfer',
{
args: ['0xRecipientAddress', '1000000000000000000'],
signAndSubmit: false,
},
);
const tx = response.data.result.tx;
// Sign and submit with the user's connected wallet
await walletClient.sendTransaction({
to: tx.to,
data: tx.data,
value: BigInt(tx.value ?? 0),
account: userAddress,
});
```
## Framework Plugins
### Hardhat
The `hardhat-multibaas-plugin` automatically uploads and links contracts in your MultiBaas deployment as part of your Hardhat deploy scripts.
```bash theme={null}
npm install --save-dev hardhat hardhat-multibaas-plugin @nomicfoundation/hardhat-ignition
```
See the [plugin repository](https://github.com/curvegrid/hardhat-multibaas-plugin) for setup instructions.
### Foundry / Forge
The `forge-multibaas` plugin provides the same integration for Foundry-based projects.
```bash theme={null}
forge install curvegrid/forge-multibaas
```
See the [plugin repository](https://github.com/curvegrid/forge-multibaas) for setup instructions.
# MultiBaas by Curvegrid
Source: https://docs.celo.org/tooling/dev-environments/multibaas/overview
Blockchain middleware for building dApps on Celo with a REST API, smart contract management, and real-time event webhooks.
[MultiBaas](https://www.curvegrid.com/blockchain-platform) by [Curvegrid](https://www.curvegrid.com) is a blockchain middleware platform that wraps your smart contracts in a REST API and advanced feature toolkit. It handles contract management, transaction signing, event indexing, and webhook delivery so you can focus on building your application without managing low-level blockchain infrastructure.
## Key Features
* **[REST API](https://docs.curvegrid.com/multibaas/api/multibaas-api)** — interact with any linked smart contract over HTTPS using standard HTTP clients or the TypeScript/Go SDK
* **[Contract Management](https://docs.curvegrid.com/multibaas/manage-contracts)** — deploy, link, and manage contracts via the dashboard or API; import ABIs from Blockscout or Etherscan by address
* **[Event Webhooks](https://docs.curvegrid.com/multibaas/webhooks)** — receive real-time HTTP callbacks whenever a contract event is emitted on-chain
* **[Cloud Wallets](https://docs.curvegrid.com/multibaas/cloud-wallets)** — server-side signing via Azure Key Vault (AWS KMS and Google Cloud KMS available on request)
* **[Transaction Manager](https://docs.curvegrid.com/multibaas/txm)** — monitors Cloud Wallet transactions and auto-resubmits stuck transactions
* **[Event Indexing](https://docs.curvegrid.com/multibaas/event-indexing)** — built-in indexer with a query and aggregation API for historical event data
* **[Framework Plugins](https://docs.curvegrid.com/multibaas/plugins)** — Hardhat and Foundry Forge plugins to automate contract uploads during deployment
## Getting Started
### 1. Create a Deployment
1. Sign up at [console.curvegrid.com](https://console.curvegrid.com) using Google, GitHub, Microsoft, or email
2. Click **New Deployment**
3. Enter a label, description, and select **Celo** (Mainnet or Sepolia) as the network
The network cannot be changed after a deployment is created. Create separate deployments for mainnet and testnet environments.
Your deployment will be available at `https://.multibaas.com`.
### 2. Generate an API Key
In your deployment, go to **Admin → API Keys → New Key**.
MultiBaas has multiple key types with different permission levels. The most frequently used are Administrator and DApp User:
| Key Type | Use Case |
| ----------------- | ---------------------------------------------------------------------------- |
| **Administrator** | Server-side code only, full deployment control |
| **DApp User** | Safe to use in frontend apps, read-only and unsigned transaction composition |
Never expose an Administrator key in client-side code.
### 3. Configure CORS (Frontend Apps)
If you are building a frontend application, add your origin at **Admin → CORS**.
## Resources
* [MultiBaas Documentation](https://docs.curvegrid.com/multibaas/)
* [Curvegrid Console](https://console.curvegrid.com)
* [TypeScript SDK (`@curvegrid/multibaas-sdk`)](https://www.npmjs.com/package/@curvegrid/multibaas-sdk)
* [Go SDK](https://github.com/curvegrid/multibaas-sdk-go)
* [Sample App](https://github.com/curvegrid/multibaas-sample-app)
* [Curvegrid Discord](https://discord.gg/ud9U7nP)
# Event Webhooks
Source: https://docs.celo.org/tooling/dev-environments/multibaas/webhooks
Receive real-time HTTP callbacks for on-chain contract events using MultiBaas webhooks.
MultiBaas webhooks deliver real-time HTTP POST callbacks to your server whenever a configured on-chain event fires. This lets you react to contract activity without polling the blockchain.
## Supported Event Types
| Type | Trigger |
| ---------------------- | --------------------------------------------------------------------------------------- |
| `event.emitted` | A contract event is emitted on-chain (requires **Sync Events** enabled on the contract) |
| `transaction.included` | A Cloud Wallet transaction is mined in a block |
## Creating a Webhook
### In the Dashboard
1. Go to **Blockchain → Webhooks → +**
2. Enter a label and your publicly accessible HTTPS endpoint URL
3. Save
### Via API
```bash theme={null}
curl -X POST \
"https://.multibaas.com/api/v0/webhooks" \
-H "Authorization: Bearer " \
-H "Content-Type: application/json" \
-d '{
"label": "my-webhook",
"url": "https://your-app.example.com/api/webhooks/multibaas"
}'
```
## Webhook Payload
Each request delivers a JSON array of one or more events:
```typescript theme={null}
type MultiBaasEvent = {
id: string;
event: 'event.emitted' | 'transaction.included';
data: {
triggeredAt: string;
event: {
name: string;
signature: string;
inputs: {
name: string;
value: string;
hashed: boolean;
type: string;
}[];
rawFields: string;
contract: {
address: string;
addressLabel: string;
name: string;
label: string;
};
indexInLog: number;
};
};
};
```
## Verifying Signatures
Every webhook request includes two headers:
* **`X-MultiBaas-Signature`** — HMAC-SHA256 of the raw request body concatenated with the timestamp
* **`X-MultiBaas-Timestamp`** — Unix timestamp as a string
Always verify the signature before processing an event to confirm the request originated from MultiBaas.
```typescript theme={null}
import { createHmac } from 'node:crypto';
function verifyWebhookSignature(
payload: string,
signature: string | null,
timestamp: string | null,
): boolean {
if (!payload || !signature || !timestamp) return false;
const hmac = createHmac('sha256', process.env.MULTIBAAS_WEBHOOK_SECRET!);
hmac.update(Buffer.from(payload));
hmac.update(timestamp);
const expected = hmac.digest().toString('hex');
return signature === expected;
}
```
The webhook secret is shown once when you create the webhook in the MultiBaas dashboard.
## Example: Next.js Webhook Handler
The following is based on how [Celo Mondo](https://mondo.celo.org/) uses MultiBaas webhooks to process Celo governance events in real time.
```typescript theme={null}
// app/api/webhooks/multibaas/route.ts
import { NextRequest } from 'next/server';
import { createHmac } from 'node:crypto';
type MultiBaasEvent = {
id: string;
event: 'event.emitted';
data: {
triggeredAt: string;
event: {
name: string;
signature: string;
inputs: { name: string; value: string; hashed: boolean; type: string }[];
rawFields: string;
contract: {
address: string;
addressLabel: string;
name: string;
label: string;
};
indexInLog: number;
};
};
};
export async function POST(request: NextRequest): Promise {
const rawBody = await request.text();
const signature = request.headers.get('X-MultiBaas-Signature');
const timestamp = request.headers.get('X-MultiBaas-Timestamp');
if (!rawBody || !signature || !timestamp) {
return new Response(null, { status: 403 });
}
// Verify the signature before processing
const hmac = createHmac('sha256', process.env.MULTIBAAS_WEBHOOK_SECRET!);
hmac.update(Buffer.from(rawBody));
hmac.update(timestamp);
const expected = hmac.digest().toString('hex');
if (signature !== expected) {
return new Response(null, { status: 403 });
}
const events: MultiBaasEvent[] = JSON.parse(rawBody);
for (const { data: { event } } of events) {
console.log(`Received ${event.name} from ${event.contract.address}`);
// Handle each event...
}
return new Response(null, { status: 200 });
}
```
For a full production example — including governance proposal processing, multisig approval handling, progressive historical backfill, and database integration — see the [Celo Mondo webhook handler](https://github.com/celo-org/celo-mondo/tree/main/src/app/api/webhooks/multibaas).
## Environment Variables
```bash theme={null}
MULTIBAAS_DEPLOYMENT_URL=https://.multibaas.com
MULTIBAAS_API_KEY=
MULTIBAAS_WEBHOOK_SECRET=
```
# Deploy on Celo with Remix
Source: https://docs.celo.org/tooling/dev-environments/remix
How to deploy a smart contract to Celo testnet, Mainnet, or a local network using [Remix](https://remix.ethereum.org/).
***
## Introduction to Remix
The [Remix IDE](https://remix-project.org/) is an open-source web and desktop application for creating and deploying Smart Contracts. Originally created for Ethereum, it fosters a fast development cycle and has a rich set of plugins with intuitive GUIs. Remix is used for the entire journey of contract development and is a playground for learning and teaching Celo.
In this guide, you will learn to deploy a smart contract on Celo using [remix.ethereum.org](http://remix.ethereum.org).
For Celo L1 Remix does not support Solidity compiler version `0.8.20` and above for EVM versions above **Paris**. If you try to deploy a smart contract with a higher version, you will receive this error message:
```bash theme={null}
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
invalid opcode: opcode 0x5f not defined
The EVM version used by the selected environment is not compatible with the compiler EVM version.
```
A **workaround** is to go into the advanced settings for the compiler in Remix and choose Paris as the EVM version.
For Celo Sepolia everything should be working as on every other EVM compatible chain.
To learn more about the features available to you as a smart contract developer with Remix, visit the [Remix documentation](https://remix-ide.readthedocs.io/en/latest/).
## Create a Smart Contract
* Navigate to [remix.ethereum.org](http://remix.ethereum.org) and select **contracts > 1\_Storage.sol** from the **File Explorers** pane.
* Review the smart contract code and learn more using the [Solidity docs](https://docs.soliditylang.org/en/latest/) or with [Solidity by Example](https://solidity-by-example.org/).
* Complete any changes to your smart contract and save the final version (Command/Ctrl + S).
## Compile the Contract
* Choose the **Solidity Compiler Icon** on the left side menu.
* Check that your compiler version is within the versions specified in the **pragma solidity statement**.
* Select the **Compile** button to compile your smart contract.
## Deploy the Contract
* Click the **Deploy and Run Transactions Icon** on the left side menu.
* Choose **Injected Web3** as your environment.
* [Connect MetaMask to Celo](/wallet/metamask/use) testnet and verify that the environment reads:
* **Custom (11142220) network** for Celo Sepolia testnet
* **Custom (42220) network** for Celo Mainnet
* Click **Deploy** and select **Confirm** in the MetaMask notification window to pay for the transaction
## Interacting with the Contract
* Select the **dropdown** on the newly deployed contract at the bottom of the left panel.
* View the deployed contract’s functions using the **Deployed Contracts** window.
* Select functions to read or write on the Celo testnet using the function inputs as needed.
* Confirm write transactions in the **MetaMask Notification Window** to pay the transaction’s gas fee.
## View Contract Details
* Copy the contract address from the **Deployed Contracts** window on the left panel.
* Navigate to the [Celo Block Explorer](https://celo.blockscout.com/) and use the contract address to search for your contract.
* Explore the details of your deployed smart contract and learn more about the explorer [here](http://docs.blockscout.com).
## Verify Contracts on Celo
* [Using Blockscout](/developer/verify/blockscout)
* [Using Remix](/developer/verify/remix)
* [Using CeloScan](/developer/verify/celoscan)
* [Using Hardhat](/developer/verify/hardhat)
# One-Click Deploy
Source: https://docs.celo.org/tooling/dev-environments/thirdweb/one-click-deploy
Create and deploy Web3 apps effortlessly with Thirdweb and Celo.
***
## Objectives
By the end of this tutorial, you will:
* Be able to **transfer Celo** to another address
* Have a mintable **NFT Drop**.
* Build an **NFT gallery**
## Prerequisites
* Node (v20 or higher)
* A wallet with some test tokens (more on this later)
## Fund Your Wallet
1. Ensure there are sufficient funds to cover the transaction fees.
2. Visit the [Celo Sepolia Faucet](https://faucet.celo.org/celo-sepolia) to claim test tokens using a wallet address. ***Remember to claim only what is needed.***
## Create a Contract on Thirdweb
1. Visit [Thirdweb](https://thirdweb.com/login?utm_source=celo\&utm_medium=documentation\&utm_campaign=chain_docs) and log in or create a new account.
2. Navigate to **`Contracts`** and click **`Deploy Contract`**.
3. Since multiple smart contracts have already been audited, there's no need to write them from scratch.
4. Select **`NFT Drop`** and click **`Deploy`**.
5. Configure the token by setting its **Name** (mandatory), **Symbol**, and optionally adding an **Image** and **Description**.
6. In the **Deploy Options** section, choose **`Celo Sepolia`** as the Chain (if not selected by default).
7. Click **`Deploy Now`** to finalize the process.
8. After deployment, well’ll be redirected to the dashboard to upload your NFTs.
9. Provide a **name**, upload an **image**, add a **description**, and define **traits** for the NFT.
10. **Lazy Mint** the NFT.
11. Repeat steps 9 and 10 a few times—we need at least **3 NFTs**.
12. Copy your **`contract address`** from the NFT dashboard.
13. Copy the **`contract address`** from the NFT dashboard.
## Make the NFT Mintable
1. On the dashboard, go to **Claim Conditions**
2. Click on **Add Phase**.
3. Specify the **Default Price (0.1)** and the **Limit per wallet (3)**.
4. Click on **Save Phases**.
## Get a Thirdweb Client ID
1. Open the **Thirdweb Dashboard** and click **`Add New`** in the **Projects** section.
2. Select **`Project`** from the dropdown menu.
3. Enter a **project name** and add **`localhost:5173`** under **`Allowed Domains`**. Click **`Create`**.
4. A **`Client ID`** and **`Secret ID`** will be generated. Copy both to a secure location—we’ll only need the **`Client ID`**.
## Clone the Thirdweb Celo NFT Repository
1. Clone the repository:
```sh theme={null}
git https://github.com/atejada/celo-one-click-deploy
cd celo-one-click-deploy
```
2. Install dependencies:
```sh theme={null}
npm install
```
3. Create a .env file with the following content:
```sh theme={null}
VITE_CLIENTID = THIRD_WEB_CLIENT_ID
VITE_ADDRESS = MINTABLE_NFT_CONTRACT
VITE_GALLERY_ADDRESS = NFT_GALLERY_CONTRACT
VITE_ADDRESS_TO = ACCOUNT_TO_SEND_CELO_TO
```
4. Run the project:
```sh theme={null}
npm run dev
```
Once the project is running, there will be three links, the first named **Send Celo**, the second **NFT Gallery** and the third
named **Mint NFT**.
The first one will be displayed by default. Click on the **Connect** button to connect the wallet. Enter an
address and an amount of Celo to transfer. The second link will display an NTF with a combo box at the top, to choose between 3 different
NFTs. The third and last link will display an NFT along with its description and by pressing the mint button, 0.1 Celo will be paid.
## Join Build with Celo - Proof of Ship
1. Create a project profile on [Karma GAP](https://docs.gap.karmahq.xyz/how-to-guides/integrations/celo-proof-of-ship)\*\*.
2. Sign up to join [Proof of Ship](https://celo-devs.beehiiv.com/subscribe).
3. You can win up to **`5k USDm`** + Track Bounties.
4. Build with **`Celo`**.
# Getting Started with Thirdweb
Source: https://docs.celo.org/tooling/dev-environments/thirdweb/overview
***
## Table of Contents
* [Introduction](#introduction)
* [Why Thirdweb?](#why-thirdweb)
* [Thirdweb documentation](#thirdweb-docs)
* [Resources](#resources)
## Introduction
Thirdweb streamlines blockchain development with pre-built contracts, SDKs, and a user-friendly dashboard. Deploy dApps, NFTs, and tokens effortlessly across multiple chains—fast, secure, and developer-friendly.
## Why Thirdweb?
Using Thirdweb is recommended because it eliminates the complexity of Web3 development, focusing on building rather than managing blockchain intricacies.
* Pre-built Smart Contracts
* SDKs & APIs
* Multi-chain Support
* Wallet & Payments
* Dashboard Management
## Thirdweb documentation
* Build
* [Wallets](https://portal.thirdweb.com/wallets?utm_source=celo\&utm_medium=documentation\&utm_campaign=chain_docs)
* [Transactions](https://portal.thirdweb.com/transactions?utm_source=celo\&utm_medium=documentation\&utm_campaign=chain_docs)
* [Contracts](https://portal.thirdweb.com/contracts?utm_source=celo\&utm_medium=documentation\&utm_campaign=chain_docs)
* [AI](https://portal.thirdweb.com/ai/chat?utm_source=celo\&utm_medium=documentation\&utm_campaign=chain_docs)
* Monetize
* [Payments](https://portal.thirdweb.com/payments?utm_source=celo\&utm_medium=documentation\&utm_campaign=chain_docs)
* [Bridge](https://portal.thirdweb.com/bridge?utm_source=celo\&utm_medium=documentation\&utm_campaign=chain_docs)
* [Tokens](https://portal.thirdweb.com/payments?utm_source=celo\&utm_medium=documentation\&utm_campaign=chain_docs)
* References
* [thirdweb API](https://portal.thirdweb.com/reference?utm_source=celo\&utm_medium=documentation\&utm_campaign=chain_docs)
## Resources
* [Thirdweb main page](https://thirdweb.com/?utm_source=celo\&utm_medium=documentation\&utm_campaign=chain_docs)
* [Thirdweb Docs](https://portal.thirdweb.com/?utm_source=celo\&utm_medium=documentation\&utm_campaign=chain_docs)
* [Playground](https://playground.thirdweb.com/?utm_source=celo\&utm_medium=documentation\&utm_campaign=chain_docs)
* [Templates](https://thirdweb.com/templates?utm_source=celo\&utm_medium=documentation\&utm_campaign=chain_docs)
# Using thirdweb
Source: https://docs.celo.org/tooling/dev-environments/thirdweb/thirdweb
## Create Contract
To create a new smart contract using thirdweb CLI, follow these steps:
1. In your CLI run the following command:
```
npx thirdweb create contract
```
2. Input your preferences for the command line prompts:
1. Give your project a name
2. Choose your preferred framework: Hardhat or Foundry
3. Name your smart contract
4. Choose the type of base contract: Empty, [ERC20](https://portal.thirdweb.com/solidity/base-contracts/erc20base), [ERC721](https://portal.thirdweb.com/solidity/base-contracts/erc721base), or [ERC1155](https://portal.thirdweb.com/solidity/base-contracts/erc1155base)
5. Add any desired [extensions](https://portal.thirdweb.com/solidity/extensions)
3. Once created, navigate to your project’s directory and open in your preferred code editor.
4. If you open the `contracts` folder, you will find your smart contract; this is your smart contract written in Solidity.
The following is code for an ERC721Base contract without specified extensions. It implements all of the logic inside the [`ERC721Base.sol`](https://github.com/thirdweb-dev/contracts/blob/main/contracts/base/ERC721Base.sol) contract; which implements the [`ERC721A`](https://github.com/thirdweb-dev/contracts/blob/main/contracts/eip/ERC721A.sol) standard.
```bash theme={null}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@thirdweb-dev/contracts/base/ERC721Base.sol";
contract Contract is ERC721Base {
constructor(
string memory _name,
string memory _symbol,
address _royaltyRecipient,
uint128 _royaltyBps
) ERC721Base(_name, _symbol, _royaltyRecipient, _royaltyBps) {}
}
```
This contract inherits the functionality of ERC721Base through the following steps:
* Importing the ERC721Base contract
* Inheriting the contract by declaring that our contract is an ERC721Base contract
* Implementing any required methods, such as the constructor.
5. After modifying your contract with your desired custom logic, you may deploy it to Celo using [Deploy](https://portal.thirdweb.com/deploy).
***
Alternatively, you can deploy a prebuilt contract for NFTs, tokens, or marketplace directly from the thirdweb Explore page:
1. Go to the thirdweb Explore page: [https://thirdweb.com/explore](https://thirdweb.com/explore)
2. Choose the type of contract you want to deploy from the available options: NFTs, tokens, marketplace, and more.
3. Follow the on-screen prompts to configure and deploy your contract.
> For more information on different contracts available on Explore, check out [thirdweb’s documentation.](https://portal.thirdweb.com/pre-built-contracts)
## Deploy Contract
Deploy allows you to deploy a smart contract to any EVM compatible network without configuring RPC URLs, exposing your private keys, writing scripts, and other additional setup such as verifying your contract.
1. To deploy your smart contract using deploy, navigate to the root directory of your project and execute the following command:
```bash theme={null}
npx thirdweb deploy
```
Executing this command will trigger the following actions:
* Compiling all the contracts in the current directory.
* Providing the option to select which contract(s) you wish to deploy.
* Uploading your contract source code (ABI) to IPFS.
2. When it is completed, it will open a dashboard interface to finish filling out the parameters.
* `_name`: contract name
* `_symbol`: symbol or "ticker"
* `_royaltyRecipient`: wallet address to receive royalties from secondary sales
* `_royaltyBps`: basis points (bps) that will be given to the royalty recipient for each secondary sale, e.g. 500 = 5%
3. Select Celo as the network
4. Manage additional settings on your contract’s dashboard as needed such as uploading NFTs, configuring permissions, and more.
For additional information on Deploy, please reference [thirdweb’s documentation](https://portal.thirdweb.com/deploy).
If you have any further questions or encounter any issues during the process, please reach out to thirdweb support at [support.thirdweb.com](http://support.thirdweb.com/).
# Analytics
Source: https://docs.celo.org/tooling/explorers/analytics
## Dune Analytics
Dune Analytics allows anyone to create dashboards that present information about [Celo](https://dune.com/blockchains/celo).
See [Dune docs](https://docs.dune.com/) for more info.
You can find a list of [community created dashboards for Celo here](https://dune.com/discover/content/relevant?q=blockchain%3A%27Celo%27\&resource-type=dashboards), or create your own dashboard.
## Token Terminal
Token Terminal tracks many industry relevant metrics.
See [Token Terminal docs](https://docs.tokenterminal.com/) for more info.
You can find the metrics filtered for Celo [here](https://tokenterminal.com/terminal/projects/celo).
## Artemis
Artemis tracks many industry relevant metrics.
See [Artemis docs](https://docs.artemis.xyz/) for more info.
You can find the metrics filtered for Celo [here](https://app.artemis.xyz/project/celo).
## dAppLooker
dAppLooker provides comprehensive analytics and visualization tools for decentralized applications.
It supports multiple blockchains, including Celo.
See [dAppLooker docs](https://docs.dapplooker.com/) for more info.
You can explore Celo-specific analytics on dAppLooker [here](https://dapplooker.com/analytics/celo).
## Additional Resources
For more detailed analytics and insights, consider exploring the following resources:
* [Messari](https://messari.io/asset/celo): In-depth market research and analytics on Celo.
* [L2BEAT](https://l2beat.com/scaling/projects/celo): L2 analytics and research on Celo.
* [growthepie](https://www.growthepie.xyz/chains/celo): Ethereum ecosystem analytics and research on Celo.
* [DefiLlama](https://defillama.com/chain/celo): Open and transparent DeFi analytics on Celo.
# Block Explorer
Source: https://docs.celo.org/tooling/explorers/block-explorers
## [Blockscout](https://celo.blockscout.com/)
Blockscout explorer is available for [Celo](https://celo.blockscout.com/blocks). If your contract is verfied on Blockscout, you can interact with and debug smart contracts.
* Search by address, transaction hash, batch, or token
* View, verify, and interact with smart contract source code.
* View detailed transaction information
A testnet explorer for [Celo Sepolia](https://celo-sepolia.blockscout.com/) is also available.
## [Celoscan](https://celoscan.io/)
Celoscan block explorer is available for [Celo](https://celoscan.io/).If your contract is verfied on Celoscan, you can interact with and debug smart contracts.
* Search by address, transaction hash, batch, or token
* View, verify, and interact with smart contract source code
* View detailed transaction information
A testnet explorer for Celo Sepolia is also available.
# Blockscout
Source: https://docs.celo.org/tooling/explorers/blockscout
# Celoscan
Source: https://docs.celo.org/tooling/explorers/celoscan
# Explorer on Celo
Source: https://docs.celo.org/tooling/explorers/overview
If you are looking to check your recent transactions or check and interact with a smart contract, check out our [Block Explorer](/developer/explorers/block-explorers).
If you need historical data for building your dapp, you can find that in the [Data Indexer](/developer/indexers/overview) and if you are looking to get an overview on what is happening on Celo, top applications and TVL, check out the [Analytics](/developer/explorers/analytics) page.
* [Block Explorers](/developer/explorers/block-explorers)
* [Data Indexers](/developer/indexers/overview)
* [Analytics](/developer/explorers/analytics)
# Codex
Source: https://docs.celo.org/tooling/indexers/codex
## Codex
[Codex](https://www.codex.io/) is a blockchain data API that provides real-time and historical DeFi data across 80+ networks via GraphQL, including Celo. With access to over 70 million tokens and 700 million wallets, Codex delivers sub-second data for building token explorers, trading bots, portfolio trackers, and DeFi dashboards.
### GraphQL API
Codex exposes a single GraphQL endpoint with 73 query operations for fetching current and historical data. All requests are sent as HTTPS POST to `https://graph.codex.io/graphql`.
Key query capabilities include:
| **Category** | **Data Available** |
| ------------------------ | --------------------------------------------------------------------------------------- |
| **Token Data** | Real-time and historical prices, OHLCV candlestick charts, metadata, and scam filtering |
| **DEX Trades** | Swap events across decentralized exchanges with pair-level detail |
| **Liquidity Pools** | Pool reserves, volume, fees, and newly created pairs |
| **Wallet Activity** | Token balances, transaction history, and holdings across 80+ networks |
| **Analytics** | Aggregated volume, liquidity, unique wallet metrics, and holder tracking |
| **Launchpad Monitoring** | Alerts for new token launches and early token discovery |
### Real-Time Subscriptions
Codex supports 25 real-time data streams via WebSocket (`wss://graph.codex.io/graphql`), enabling live updates for:
* Token price changes and trade events
* New and updated DEX pairs
* Wallet activity and balance changes
* Launchpad and new token events
### Webhooks
Webhooks provide push-based notifications for on-chain events, delivering data to your server as events occur without requiring persistent WebSocket connections.
### SDK
Codex provides a TypeScript/JavaScript SDK that acts as a thin wrapper around the GraphQL API with predefined queries, mutations, and built-in subscription connection handling.
```bash theme={null}
npm install @codex-data/sdk
```
Alternatively, you can write custom GraphQL queries directly against the API for more flexibility.
### Getting Started
#### 1. Create an account
Sign up at [dashboard.codex.io](https://dashboard.codex.io/signup) to create your Codex account.
#### 2. Get your API key
Copy your API key from the API Keys page in the dashboard.
#### 3. Make your first request
All requests require an `Authorization` header with your API key.
```bash theme={null}
curl -X POST https://graph.codex.io/graphql \
-H "Content-Type: application/json" \
-H "Authorization: YOUR_API_KEY" \
-d '{"query": "{ getNetworks { name id } }"}'
```
#### 4. Explore the API
Use the [GraphQL Explorer](https://docs.codex.io/explore) to interactively build and test queries.
### Recipes & Guides
* [Token Discovery](https://docs.codex.io/recipes/discover-tokens) — Build token discovery pages with trending data, advanced filtering, and search
* [Price Charts](https://docs.codex.io/recipes/charts) — Render token charts with OHLCV data and real-time updates
* [Wallet Analytics](https://docs.codex.io/recipes/wallets) — Analyze wallet performance and discover high-performing traders
* [Token Swap Events](https://docs.codex.io/recipes/events) — Fetch and display token swaps with filtering, sorting, and real-time updates
* [Launchpad Monitoring](https://docs.codex.io/recipes/launchpads) — Build a launchpad dashboard with filtering, sorting, and real-time updates
* [Real-Time Price Tracking](https://docs.codex.io/recipes/realtime) — Build a Node.js app that listens for token price changes in real time
### Resources
* [Codex API Documentation](https://docs.codex.io/)
* [GraphQL API Reference](https://docs.codex.io/api-reference)
* [GraphQL Explorer](https://docs.codex.io/explore)
* [GitHub](https://github.com/Codex-Data)
* [Dashboard](https://dashboard.codex.io/)
* [Discord Community](https://discord.com/invite/mFpUhT3vAq)
# Envio
Source: https://docs.celo.org/tooling/indexers/envio
Envio is a modern, multi-chain EVM blockchain indexing framework speed-optimized
for querying real-time and historical data.
### Understanding Envio
#### Envio HyperIndex
Envio [HyperIndex](https://docs.envio.dev/docs/overview) is a feature-rich
indexing solution that provides Celo applications with a seamless and
efficient way to index and aggregate real-time or historical blockchain data.
The indexed data is easily accessible through custom GraphQL queries, giving
developers the flexibility and power to retrieve specific information for their
blockchain application.
Envio offers native support for Celo networks (testnet and mainnet) and has been designed
to support high-throughput blockchain applications that rely on real-time data
for their business requirements.
Designed to optimize the developer experience, Envio offers automatic code
generation, flexible language support, quickstart templates, and a reliable
cost-effective [hosted service](https://envio.dev/explorer) with reference implementations. Indexers on Envio can be written in JavaScript, TypeScript, or ReScript.
#### Envio HyperSync
Envio [HyperSync](https://docs.envio.dev/docs/overview-hypersync) is supported on Celo mainnet.
HyperSync is a real-time data query layer for Celo, providing APIs
that bypass traditional JSON-RPC for up to 1000x faster syncing of historical
data. HyperSync is used as the default data source in Envio's indexing framework (HyperIndex),
with standard RPC being optional.
Using HyperSync, Celo developers do not need to worry about RPC URLs,
rate-limiting, or managing their infrastructure - and can easily sync large
datasets in a few minutes, something that would usually take hours or days using
traditional indexing solutions.
HyperSync is also available as a standalone API for data analytic use cases.
Data analysts can interact with the HyperSync API using JavaScript, Python, or
Rust clients and extract data in JSON, Arrow, or Parquet formats, or use the [RPC interface](https://docs.envio.dev/docs/HyperSync/overview-hyperrpc).
## Quick Start
Developers can choose to start from a template (e.g. Blank, ERC-20, etc.), or
use Contract Import, when running the `envio init` command.
[Contract Import](https://docs.envio.dev/docs/contract-import) is a quick start that allows Celo developers to quickly autogenerate a basic indexer. This walkthrough explains how to initialize an indexer using a single or multiple contracts that are already deployed on Celo.
This process allows a user to quickly and easily start up a basic indexer and a queryable GraphQL API for their application in less than 5 minutes.
The following files are required to run the Envio indexer:
* Configuration (defaults to `config.yaml`)
* GraphQL Schema (defaults to `schema.graphql`)
* Event Handlers (defaults to `src/EventHandlers.*` depending on the language chosen)
These files are auto-generated according to the template and language chosen by running the `envio init` command.
#### Initialize your indexer
`cd` into the folder of your choice and run
```bash theme={null}
envio init
```
Name your indexer
```bash theme={null}
? Name your indexer:
```
Choose the directory where you would like to setup your project (default is the current directory)
```bash theme={null}
? Set the directory: (.) .
```
Select `Contract Import` as the initialization option.
```bash theme={null}
? Choose an initialization option
Template
> ContractImport
SubgraphMigration
[↑↓ to move, enter to select, type to filter]
```
```bash theme={null}
? Would you like to import from a block explorer or a local abi?
> Block Explorer
Local ABI
[↑↓ to move, enter to select, type to filter]
```
`Block Explorer` option only requires user to input the contracts address and chain of the contract. If the contract is verified and deployed on one of the supported chains, this is the quickest setup as it will retrieve all needed contract information from a block explorer.
`Local ABI` option will allow you to point to a JSON file containing the smart contract ABI. The Contract Import process will then populate the required files from the ABI.
#### Select the blockchain that the contract is deployed on
```bash theme={null}
? Which blockchain would you like to import a contract from?
arbitrum-one
arbitrum-nova
bsc
> celo
ethereum
gnosis
v goerli
[↑↓ to move, enter to select, type to filter]
```
#### Enter in the address of the contract to import
```bash theme={null}
? What is the address of the contract?
[Use the proxy address if your abi is a proxy implementation]
```
Note: if you are using a proxy contract with an implementation, the address should be for the proxy contract.
#### Choose which events to include in the `config.yaml` file
```bash theme={null}
? Which events would you like to index?
> [x] ClaimRewards(address indexed from, address indexed reward, uint256 amount)
[x] Deposit(address indexed from, uint256 indexed tokenId, uint256 amount)
[x] NotifyReward(address indexed from, address indexed reward, uint256 indexed epoch, uint256 amount)
[x] Withdraw(address indexed from, uint256 indexed tokenId, uint256 amount)
[↑↓ to move, space to select one, → to all, ← to none, type to filter]
```
#### Select the continuation option
```bash theme={null}
? Would you like to add another contract?
> I'm finished
Add a new address for same contract on same network
Add a new network for same contract
Add a new contract (with a different ABI)
[Current contract: BribeVotingReward, on network: Celo]
```
The `Contract Import` process will prompt the user whether they would like to finish the import process or continue adding more addresses for same contract on same network, addresses for same contract on different network or a different contract.
**Envio Indexer Examples**
View the Envio [Explorer](https://envio.dev/explorer) for reference implementations, or visit the Envio docs for [video and written tutorials](https://docs.envio.dev/docs/HyperIndex/tutorial-op-bridge-deposits).
**Getting support**
Indexing can be a rollercoaster, especially for more complex use cases. The
Envio engineers are available to help you with your data availability needs.
* [Discord](https://discord.gg/mZHNWgNCAc)
* Email: [hello@envio.dev](mailto:hello@envio.dev)
# Goldrush
Source: https://docs.celo.org/tooling/indexers/goldrush
## GoldRush (powered by Covalent)
GoldRush offers the most comprehensive Blockchain Data API suite for developers, analysts, and enterprises. Whether you are building a DeFi dashboard, a wallet, a trading bot, an AI agent or a compliance platform, the Data APIs provide fast, accurate, and developer-friendly access to the essential on-chain data you need.
GoldRush consists of the following self-serve products that can be used independently or together to power your application:
| **Product Name** | **Description** | **Key Data Feeds** | **Use Cases** |
| -------------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| **Foundational API** | Access structured historical blockchain data across 100+ chains via REST APIs |
Token balances (spot & historical)
Token transfers
Token holders (spot & historical)
Token prices (onchain)
Wallet transactions
Get logs
|
Wallets
Portfolio trackers
Crypto accounting & tax tools
DeFi dashboards
Activity feeds
|
| **Streaming API** | Subscribe to real-time blockchain events with sub-second latency using GraphQL over WebSockets |
OHLCV tokens & pairs
New & updated DEX pairs
Wallet activity
Token balances
|
Trading dashboards
Sniper bots
Gaming
Agentic workflows
|
The **[GoldRush TypeScript SDK](https://www.npmjs.com/package/@covalenthq/client-sdk)** is the fastest way to integrate the GoldRush APIs. Install with:
```bash theme={null}
npm install @covalenthq/client-sdk
```
Learn more about GoldRush's integration with Celo [here](https://goldrush.dev/docs/chains/celo?utm_source=celo\&utm_medium=partner-docs) .
# Indexing Co
Source: https://docs.celo.org/tooling/indexers/indexing-co
[Indexing Co](https://indexing.co) provides custom blockchain data pipelines with JavaScript transformation logic, sub-second latency, and delivery to Postgres, webhooks, or Kafka. Indexing Co supports Celo and 100+ other blockchains, making it easy to build cross-chain data workflows from a single platform.
## How It Works
Indexing Co pipelines have three stages:
| Stage | Description |
| ------------------ | -------------------------------------------------------------------------------------------------------- |
| **Filter** | Select which blocks and transactions to process by contract address, event signature, or other criteria. |
| **Transformation** | Write JavaScript functions that extract and reshape the data you need from each block. |
| **Destination** | Deliver processed data to Postgres, HTTP webhooks, WebSockets, or other adapters. |
## Key Features
* **Celo support** — Native support for Celo mainnet with real-time and historical data.
* **Custom JavaScript transformations** — Write `function main(block)` handlers with full control over how data is extracted and shaped.
* **Multiple destinations** — Deliver data to Postgres, HTTP endpoints, WebSockets, or Kafka.
* **Backfills** — Replay historical blocks through your pipeline to populate your database from any starting point.
* **Cross-chain** — Run the same pipeline logic across 100+ supported blockchains.
* **Built-in helpers** — Use `templates.tokenTransfers(block)`, `utils.evmDecodeLog()`, and other utilities to accelerate development.
## Quick Start
All API requests use the base URL `https://app.indexing.co/dw` and require an `X-API-KEY` header for authentication. Sign up at [indexing.co](https://indexing.co) to get your API key.
### Step 1: Create a Filter
Create a filter to select which Celo transactions to process. This example filters for a specific contract address:
```bash theme={null}
curl -X POST https://app.indexing.co/dw/filters/my-celo-filter \
-H "Content-Type: application/json" \
-H "X-API-KEY: YOUR_API_KEY" \
-d '{
"addresses": ["0xYOUR_CONTRACT_ADDRESS"]
}'
```
### Step 2: Create a Transformation
Create a transformation with a JavaScript `function main(block)` handler that processes each block:
```bash theme={null}
curl -X POST https://app.indexing.co/dw/transformations/my-celo-transform \
-H "Content-Type: application/json" \
-H "X-API-KEY: YOUR_API_KEY" \
-d '{
"code": "function main(block) {\n const transfers = templates.tokenTransfers(block);\n return transfers.map(t => ({\n from: t.from,\n to: t.to,\n value: t.value,\n token: t.address,\n block_number: block.number,\n timestamp: block.timestamp\n }));\n}"
}'
```
### Step 3: Test the Transformation
Test your transformation against a real Celo block to verify the output:
```bash theme={null}
curl -X POST "https://app.indexing.co/dw/transformations/test?network=celo&beat=BLOCK_NUMBER" \
-H "Content-Type: application/json" \
-H "X-API-KEY: YOUR_API_KEY" \
-d '{
"code": "function main(block) {\n const transfers = templates.tokenTransfers(block);\n return transfers.map(t => ({\n from: t.from,\n to: t.to,\n value: t.value,\n token: t.address,\n block_number: block.number,\n timestamp: block.timestamp\n }));\n}"
}'
```
### Step 4: Create a Pipeline
Combine the filter, transformation, and a destination into a pipeline that delivers data to Postgres:
```bash theme={null}
curl -X POST https://app.indexing.co/dw/pipelines \
-H "Content-Type: application/json" \
-H "X-API-KEY: YOUR_API_KEY" \
-d '{
"name": "my-celo-pipeline",
"network": "celo",
"filter": "my-celo-filter",
"transformation": "my-celo-transform",
"adapter": {
"type": "POSTGRES",
"config": {
"connection_url": "postgresql://user:password@host:5432/dbname",
"table": "celo_transfers"
}
}
}'
```
## Backfilling Historical Data
Once your pipeline is running, you can backfill historical data from any starting block:
```bash theme={null}
curl -X POST https://app.indexing.co/dw/pipelines/my-celo-pipeline/backfill \
-H "Content-Type: application/json" \
-H "X-API-KEY: YOUR_API_KEY" \
-d '{
"start_block": 20000000
}'
```
## Claude Code Integration
Indexing Co provides first-class support for [Claude Code](https://docs.anthropic.com/en/docs/claude-code) through an MCP server and a pipeline skill, enabling you to build and query Celo data pipelines directly from your AI coding workflow.
### MCP Server
The [Indexing Co MCP server](https://github.com/indexing-co/indexing-co-mcp) streams real-time blockchain data from your pipelines into Claude Code. Events are stored in local SQLite and queryable with SQL — no external database needed for development.
```bash theme={null}
# Install
git clone https://github.com/indexing-co/indexing-co-mcp.git
cd indexing-co-mcp && npm install && npm run build
# Register with Claude Code
claude mcp add indexing-co -- node /path/to/indexing-co-mcp/dist/index.js
```
Once registered, Claude Code gains tools to subscribe to pipeline channels, query event data with SQL, and manage pipelines, filters, and transformations — all through natural conversation.
To stream Celo data into Claude Code, set the pipeline destination to the `DIRECT` adapter:
```json theme={null}
{
"adapter": "DIRECT",
"connectionUri": "my-celo-channel",
"table": "my-celo-channel"
}
```
### Claude Code Skill
The [Indexing Co pipeline skill](https://github.com/indexing-co/indexing-co-pipeline-skill) guides Claude through building and deploying pipelines via conversation. Install it to let Claude help you write transformation functions, generate SQL schemas, and manage pipelines:
```bash theme={null}
git clone https://github.com/indexing-co/indexing-co-pipeline-skill.git
cp -r indexing-co-pipeline-skill/skills/indexing-co-pipelines ~/.claude/skills/
```
## Resources
* [Documentation](https://docs.indexing.co)
* [Platform](https://indexing.co)
* [GitHub](https://github.com/indexing-co)
* [MCP Server](https://github.com/indexing-co/indexing-co-mcp)
* [Claude Code Skill](https://github.com/indexing-co/indexing-co-pipeline-skill)
* [Support](mailto:support@indexing.co)
# Data Indexer
Source: https://docs.celo.org/tooling/indexers/overview
## Data Indexer
Getting historical data on a smart contract can be frustrating when you’re building a dapp. For example the [The Graph](https://thegraph.com/) provides an easy way to query smart contract data through APIs known as subgraphs. The Graph’s infrastructure relies on a decentralized network of indexers, enabling your dapp to become truly decentralized.
### Indexer on Celo
* [The Graph](https://thegraph.com/)
* [Quickstart](https://thegraph.com/docs/en/)
* The Graph provides a quickstart guide to help developers get up and running with subgraphs. This guide covers everything from setting up a development environment to deploying your first subgraph.
* [Subgraph Explorer](https://thegraph.com/explorer)
* The Subgraph Explorer allows you to search and explore subgraphs that have been deployed to The Graph's decentralized network. You can use it to find subgraphs relevant to your dapp and see how they are structured.
* [Envio](https://envio.dev/)
* Envio is a modern, multi-chain EVM blockchain indexing framework speed-optimized
for querying real-time and historical data.
* [SubQuery](https://subquery.network/)
* SubQuery is a fast, flexible, and reliable data indexing solution for blockchain developers. It allows you to index and query blockchain data with ease, providing a powerful tool for building decentralized applications.
* [Documentation](https://academy.subquery.network/)
* The SubQuery Academy provides comprehensive documentation and tutorials to help you get started with SubQuery. It covers everything from basic concepts to advanced usage, ensuring you have all the information you need to build with SubQuery.
* [Codex](https://www.codex.io/)
* Codex is a blockchain data API that provides real-time and historical DeFi data across 80+ networks via GraphQL, including Celo. With access to over 70 million tokens and 700 million wallets, Codex delivers sub-second data for building token explorers, trading bots, portfolio trackers, and DeFi dashboards.
* [Bitquery](https://bitquery.io/blockchains/celo-blockchain-api)
* Bitquery offers comprehensive historical and real-time Celo blockchain data, including token transfers, address balances, DEX trades, and more. Their GraphQL APIs provide a unified way to access this data, making it easier to build reliable Celo products.
* [Goldsky](https://goldsky.com/)
* Goldsky provides live-streamed crypto data, enabling developers to build rich, instant, data-driven experiences. Their tools include Subgraphs for live data through custom endpoints and Mirror for syncing data to databases or warehouses.
* [Chainbase](https://chainbase.com/)
* Chainbase's primary objective is to offer a unique and decentralized Layer 1 infrastructure that directly addresses the problem of interoperability across various blockchain networks. This architecture will facilitate the utilization of the full capabilities of blockchain data by eliminating any constraints.
* [OnFinality](https://indexing.onfinality.io)
* Industry leading SubQuery and Subgraph data indexer hosting, so you can sleep easy.
* [GoldRush(powered by Covalent)](https://goldrush.dev/docs/chains/celo)
* GoldRush offers the most comprehensive Blockchain Data API suite for developers, analysts, and enterprises. Whether you are building a DeFi dashboard, a wallet, a trading bot, an AI agent or a compliance platform, the Data APIs provide fast, accurate, and developer-friendly access to the essential on-chain data you need.
* [Indexing Co](https://indexing.co)
* Indexing Co provides custom data pipelines for Celo and 100+ other blockchains, with JavaScript transformation logic, sub-second latency, and delivery to Postgres, webhooks, or Kafka.
# SubQuery
Source: https://docs.celo.org/tooling/indexers/subquery
SubQuery is a leading blockchain data indexer that provides developers with fast, flexible, universal, open source and decentralised APIs for web3 projects. SubQuery SDK allows developers to get rich indexed data and build intuitive and immersive decentralised applications in a faster and more efficient way.
Another one of SubQuery's competitive advantages is the ability to aggregate data not only within a chain but across multiple blockchains all within a single project. This allows the creation of feature-rich dashboard analytics and multi-chain block scanners.
## Useful resources:
* [SubQuery Academy (Documentation)](https://academy.subquery.network/)
* [Celo Mainnet Starter](https://github.com/subquery/ethereum-subql-starter/tree/main/Celo/celo-starter)
* [Celo Mainnet Quick Start Guide](https://academy.subquery.network/indexer/quickstart/quickstart_chains/celo.html)
For technical questions and support reach out to us `start@subquery.network`
## Running and Hosting your Asset Chain SubQuery APIs
SubQuery is open-source, meaning you have the freedom to run it in the following three ways:
* [Locally on your own computer or on your cloud provider of choice.](https://academy.subquery.network/indexer/run_publish/introduction.html#locally-run-it-yourself)
* [By publishing it to the decentralised SubQuery Network](https://academy.subquery.network/indexer/run_publish/introduction.html#publish-to-the-subquery-network), the most open, performant, reliable, and scalable data service for dApp developers.
* [Leveraging a centralised hosting partner in the SubQuery community](https://academy.subquery.network/indexer/run_publish/introduction.html#other-hosting-providers-in-the-subquery-community), like OnFinality or Traceye.
# The Graph
Source: https://docs.celo.org/tooling/indexers/the-graph
Getting historical data on a smart contract can be frustrating when you’re building a dapp. [The Graph](https://thegraph.com/) provides an easy way to query smart contract data through APIs known as subgraphs. The Graph’s infrastructure relies on a decentralized network of indexers, enabling your dapp to become truly decentralized.
## Quick Start
It takes just a few minutes to start indexing subgraphs on Celo. To get started, follow these three steps:
1. Initialize your subgraph project
2. Deploy & Publish
3. Query from your dapp
Pricing: **All developers receive 100K free queries per month on the decentralized network**. After these free queries, you only pay based on usage at \$4 for every 100K queries.
Here’s a step by step walk through:
## 1. Initialize your subgraph project
### Create a subgraph on Subgraph Studio
Go to the [Subgraph Studio](https://thegraph.com/studio/) and connect your wallet. Once your wallet is connected, you can begin by clicking “Create a Subgraph”. Please choose a good name for the subgraph because this name can’t be edited later. It is recommended to use Title Case: “Subgraph Name Chain Name.”

You will then land on your subgraph’s page. All the CLI commands you need will be visible on the right side of the page:

### Install the Graph CLI
On your local machine run the following:
```
npm install -g @graphprotocol/graph-cli
```
### Initialize your Subgraph
You can copy this directly from your subgraph page to include your specific subgraph slug:
```
graph init --studio
```
You’ll be prompted to provide some info on your subgraph like this:

Simply have your contract verified on the block explorer and the CLI will automatically obtain the ABI and set up your subgraph. The default settings will generate an entity for each event.
## 2. Deploy & Publish
### Deploy to Subgraph Studio
First run these commands:
```bash theme={null}
$ graph codegen
$ graph build
```
Then run these to authenticate and deploy your subgraph. You can copy these commands directly from your subgraph’s page in Studio to include your specific deploy key and subgraph slug:
```bash theme={null}
$ graph auth --studio
$ graph deploy --studio
```
You will be asked for a version label. You can enter something like v0.0.1, but you’re free to choose the format.
### Test your subgraph
You can test your subgraph by making a sample query in the playground section. The Details tab will show you an API endpoint. You can use that endpoint to test from your dapp.

### Publish Your Subgraph to The Graph’s Decentralized Network
Once your subgraph is ready to be put into production, you can publish it to the decentralized network. On your subgraph’s page in Subgraph Studio, click on the Publish button:

Before you can query your subgraph, Indexers need to begin serving queries on it. In order to streamline this process, you can curate your own subgraph using GRT.
When publishing, you’ll see the option to curate your subgraph. As of May 2024, it is recommended that you curate your own subgraph with at least 3,000 GRT to ensure that it is indexed and available for querying as soon as possible.

> **Note:** The Graph's smart contracts are all on Arbitrum One, even though your subgraph is indexing data from Ethereum, BSC or any other [supported chain](https://thegraph.com/docs/en/developing/supported-networks/).
## 3. Query your Subgraph
Congratulations! You can now query your subgraph on the decentralized network!
For any subgraph on the decentralized network, you can start querying it by passing a GraphQL query into the subgraph’s query URL which can be found at the top of its Explorer page.
Here’s an example from the [CryptoPunks Ethereum subgraph](https://thegraph.com/explorer/subgraphs/HdVdERFUe8h61vm2fDyycHgxjsde5PbB832NHgJfZNqK) by Messari:

The query URL for this subgraph is:
[https://gateway-arbitrum.network.thegraph.com/api/\*\*\[api-key\]\*\*/subgraphs/id/HdVdERFUe8h61vm2fDyycHgxjsde5PbB832NHgJfZNqK](https://gateway-arbitrum.network.thegraph.com/api/**\[api-key]**/subgraphs/id/HdVdERFUe8h61vm2fDyycHgxjsde5PbB832NHgJfZNqK)
Now, you simply need to fill in your own API Key to start sending GraphQL queries to this endpoint.
### Getting your own API Key

In Subgraph Studio, you’ll see the “API Keys” menu at the top of the page. Here you can create API Keys.
## Appendix
### Sample Query
This query shows the most expensive CryptoPunks sold.
```graphql theme={null}
{
trades(orderBy: priceETH, orderDirection: desc) {
priceETH
tokenId
}
}
```
Passing this into the query URL returns this result:
```
{
"data": {
"trades": [
{
"priceETH": "124457.067524886018255505",
"tokenId": "9998"
},
{
"priceETH": "8000",
"tokenId": "5822"
},
// ...
```
### Sample code
```jsx theme={null}
const axios = require('axios');
const graphqlQuery = `{
trades(orderBy: priceETH, orderDirection: desc) {
priceETH
tokenId
}
}`;
const queryUrl = 'https://gateway-arbitrum.network.thegraph.com/api/[api-key]/subgraphs/id/HdVdERFUe8h61vm2fDyycHgxjsde5PbB832NHgJfZNqK'
const graphQLRequest = {
method: 'post',
url: queryUrl,
data: {
query: graphqlQuery,
},
};
// Send the GraphQL query
axios(graphQLRequest)
.then((response) => {
// Handle the response here
const data = response.data.data
console.log(data)
})
.catch((error) => {
// Handle any errors
console.error(error);
});
```
### Additional resources:
* To explore all the ways you can optimize & customize your subgraph for a better performance, read more about [creating a subgraph here](https://thegraph.com/docs/en/developing/creating-a-subgraph/).
* For more information about querying data from your subgraph, read more [here](https://thegraph.com/docs/en/querying/querying-the-graph/).
# Celo Libraries & SDKs
Source: https://docs.celo.org/tooling/libraries-sdks/celo-sdks
Because Celo is compatible with Ethereum any ethereum package can be used with Celo. Packages with specific support for Celo include:
***
## Web3 Libraries
* [viem](/tooling/libraries-sdks/viem)
* [ethers](/tooling/libraries-sdks/ethers)
* [thirdweb SDK](/tooling/libraries-sdks/thirdweb-sdk)
* [ContractKit (deprecated - only for internal use)](/tooling/libraries-sdks/contractkit)
* [web3.js (deprecated)](/tooling/libraries-sdks/web3)
## Wallet Libraries
* [Reown](/tooling/libraries-sdks/reown)
* [Portal](/tooling/libraries-sdks/portal)
* [JAW](/tooling/libraries-sdks/jaw)
# celocli account
Source: https://docs.celo.org/tooling/libraries-sdks/cli/account
# `celocli account`
Manage your account, keys, and metadata
* [`celocli account:authorize`](#celocli-accountauthorize)
* [`celocli account:balance ARG1`](#celocli-accountbalance-arg1)
* [`celocli account:claim-account ARG1`](#celocli-accountclaim-account-arg1)
* [`celocli account:claim-domain ARG1`](#celocli-accountclaim-domain-arg1)
* [`celocli account:claim-keybase ARG1`](#celocli-accountclaim-keybase-arg1)
* [`celocli account:claim-name ARG1`](#celocli-accountclaim-name-arg1)
* [`celocli account:claim-rpc-url ARG1`](#celocli-accountclaim-rpc-url-arg1)
* [`celocli account:claim-storage ARG1`](#celocli-accountclaim-storage-arg1)
* [`celocli account:create-metadata ARG1`](#celocli-accountcreate-metadata-arg1)
* [`celocli account:deauthorize`](#celocli-accountdeauthorize)
* [`celocli account:delete-payment-delegation`](#celocli-accountdelete-payment-delegation)
* [`celocli account:get-metadata ARG1`](#celocli-accountget-metadata-arg1)
* [`celocli account:get-payment-delegation`](#celocli-accountget-payment-delegation)
* [`celocli account:list`](#celocli-accountlist)
* [`celocli account:lock ARG1`](#celocli-accountlock-arg1)
* [`celocli account:new`](#celocli-accountnew)
* [`celocli account:proof-of-possession`](#celocli-accountproof-of-possession)
* [`celocli account:register`](#celocli-accountregister)
* [`celocli account:register-data-encryption-key`](#celocli-accountregister-data-encryption-key)
* [`celocli account:register-metadata`](#celocli-accountregister-metadata)
* [`celocli account:set-name`](#celocli-accountset-name)
* [`celocli account:set-payment-delegation`](#celocli-accountset-payment-delegation)
* [`celocli account:set-wallet`](#celocli-accountset-wallet)
* [`celocli account:show ARG1`](#celocli-accountshow-arg1)
* [`celocli account:show-claimed-accounts ARG1`](#celocli-accountshow-claimed-accounts-arg1)
* [`celocli account:show-metadata ARG1`](#celocli-accountshow-metadata-arg1)
* [`celocli account:unlock ARG1`](#celocli-accountunlock-arg1)
* [`celocli account:verify-proof-of-possession`](#celocli-accountverify-proof-of-possession)
## `celocli account:authorize`
Keep your locked Gold more secure by authorizing alternative keys to be used for signing attestations, voting, or validating. By doing so, you can continue to participate in the protocol while keeping the key with access to your locked Gold in cold storage. You must include a "proof-of-possession" of the key being authorized, which can be generated with the "account:proof-of-possession" command.
```sh theme={null}
USAGE
$ celocli account:authorize --from 0xc1912fEE45d61C87Cc5EA59DaE31190FFFFf232d -r
vote|validator|attestation --signature 0x --signer
0xc1912fEE45d61C87Cc5EA59DaE31190FFFFf232d [-k | --useLedger | ] [-n
] [--gasCurrency 0x1234567890123456789012345678901234567890]
[--ledgerAddresses ] [--ledgerLiveMode ] [--globalHelp]
FLAGS
-k, --privateKey=
Use a private key to sign local transactions with
-n, --node=
URL of the node to run commands against or an alias
-r, --role=