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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions build-on-celo/attribution-tags.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
---
title: "Attribution Tags"
og:description: "Credit on-chain activity back to your app on Celo using ERC-8021 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.

<Note>
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.
</Note>

## Install

```bash
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
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
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
const tag = toDataSuffix(["your_own_code", "celo_assigned1234"]);
```

## Tagging a Contract Call

Concatenate your encoded calldata with the suffix:

```ts
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
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
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.

<Warning>
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.
</Warning>

## 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)
4 changes: 4 additions & 0 deletions build-on-celo/build-with-ai/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,7 @@ await sendUSDCWithFeeAbstraction("0xRecipient...", parseUnits("1", 6));
| 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.
61 changes: 61 additions & 0 deletions build-on-celo/build-with-ai/x402.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,65 @@ app.get("/api/premium", async (req, res) => {
});
```

## Celo x402 Facilitator

Celo runs its own self-hosted x402 facilitator at [x402.celo.org](https://x402.celo.org/), built on the open-source [`x402-rs`](https://github.com/x402-rs/x402-rs) implementation, as an alternative to thirdweb's facilitator. 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.

<Note>
Source: `celo-org/x402-facilitator` (private repo). The endpoints below are live at [x402.celo.org](https://x402.celo.org/).
</Note>

### Endpoints

| Method | Path | Purpose |
|--------|--------------|--------------------------------------------------------------------|
| `POST` | `/verify` | Off-chain signature and simulation check of a payment payload. |
| `POST` | `/settle` | Submit the buyer's authorization on-chain (facilitator pays gas). |
| `GET` | `/supported` | List supported `(network, scheme)` pairs. |
| `GET` | `/health` | Liveness probe. |

<Warning>
cUSD / USDm are **not** supported by this facilitator — Mento's `StableTokenV2` implements only EIP-2612 `permit`, not EIP-3009.
</Warning>

### Pointing a Resource Server at It

Any standard x402 middleware that accepts a custom facilitator URL can use the Celo facilitator. Example with `x402-express`:

```ts
import express from "express";
import { paymentMiddleware } from "x402-express";

const app = express();

app.use(
paymentMiddleware(
"0xYourSellerPayoutAddress", // where buyer funds land — not the facilitator's wallet
{
"GET /premium": {
price: {
amount: "10000", // smallest unit — USDC/USDT have 6 decimals, so 10000 = 0.01
asset: {
address: "0xcEBA9300f2b948710d2653dD7B07f33A8B32118C", // Celo mainnet USDC
decimals: 6,
eip712: { name: "USDC", version: "2" }, // must match the token exactly
},
},
network: "eip155:42220", // Celo mainnet
},
},
{ url: "https://x402.celo.org" }, // point at the Celo facilitator
),
);

app.get("/premium", (_req, res) => res.json({ data: "paid content" }));
app.listen(3000);
```

<Warning>
USDT has no `version()` method on-chain — its EIP-712 domain resolves to `name: "Tether USD"`, `version: "1"`. Set those exactly in `asset.eip712` or signature verification fails.
</Warning>

## x402 on Celo

Celo is an ideal network for x402 due to:
Expand Down Expand Up @@ -326,6 +385,7 @@ app.get("/articles/:id", async (req, res) => {
| Resource | Link |
|----------|------|
| x402 Official Website | [x402.org](https://www.x402.org) |
| Celo x402 Facilitator | [x402.celo.org](https://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) |
Expand All @@ -336,3 +396,4 @@ app.get("/articles/:id", async (req, res) => {
- [ERC-8004](/build-on-celo/build-with-ai/8004) - Trust layer for AI agents
- [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
2 changes: 1 addition & 1 deletion build-on-celo/fund-your-project.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Learn more about the programs below.

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.
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

Expand Down
1 change: 1 addition & 0 deletions build-on-celo/launch-checklist.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ A comprehensive guide to assist you in launching dapps on Celo.

### 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)
Expand Down
2 changes: 1 addition & 1 deletion contribute-to-celo/builders.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The Celo Builder Community is a global network of developers, entrepreneurs, and

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.
* [**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.

Expand Down
1 change: 1 addition & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
"build-on-celo/network-overview",
"build-on-celo/cel2-architecture",
"build-on-celo/launch-checklist",
"build-on-celo/attribution-tags",
"build-on-celo/scaling-your-app",
"build-on-celo/fund-your-project",
"build-on-celo/nightfall"
Expand Down