Skip to content
Open
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
11 changes: 11 additions & 0 deletions SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,17 @@
* [Cookbook: private investor allocations with PoD](privacy-on-avalanche/cookbook-private-investor-allocations.md)
* [Tutorial: private Adder on Avalanche Fuji](privacy-on-avalanche/tutorial-private-adder-fuji.md)
* [Tutorial: custom privacy logic with PoD](privacy-on-avalanche/tutorial-custom-logic.md)
* [COTI confidential tokens & ERC-7984 compatibility](coti-erc7984/README.md)
* [Compatibility and divergence](coti-erc7984/compatibility-and-divergence.md)
* [On-chain data availability](coti-erc7984/on-chain-data-availability.md)
* [Decryption trust model](coti-erc7984/decryption-trust-model.md)
* [Input validation](coti-erc7984/input-validation.md)
* [Precision and decimals](coti-erc7984/precision-and-decimals.md)
* [Host-chain deployment](coti-erc7984/host-chain-deployment.md)
* [Transaction economics](coti-erc7984/transaction-economics.md)
* [Transfer semantics](coti-erc7984/transfer-semantics.md)
* [Concurrency](coti-erc7984/concurrency.md)
* [Deployed contracts](coti-erc7984/deployed-contracts.md)

## Security

Expand Down
59 changes: 59 additions & 0 deletions coti-erc7984/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# COTI confidential tokens & ERC-7984 compatibility

[ERC-7984](https://eips.ethereum.org/EIPS/eip-7984) is a **Draft** ERC (created 3 July 2025) for confidential fungible tokens via `bytes32` pointers. The interface is technology-agnostic; the widely used reference stack is Zama FHEVM plus [OpenZeppelin confidential contracts](https://docs.openzeppelin.com/confidential-contracts/token). COTI does **not** implement ERC-7984 as a complete standard. It offers a confidential-token alternative with overlapping transfer shapes where that helps explorers and integrators, and a different ciphertext format, allowance model, and (on native COTI) decrypt path.

This section compares ciphertext formats, input registration, decrypt paths, numeric range, and host-chain deployment.

## Sources and versions

Compared **6 September 2026** against:

| Item | Version / status |
| :--- | :--------------- |
| ERC-7984 | Draft ([EIP-7984](https://eips.ethereum.org/EIPS/eip-7984)) |
| `@zama-fhe/sdk` | 3.5.1 (depends on `@fhevm/sdk` 0.13.2; TFHE WASM v1.6.2) |
| `@fhevm/solidity` | 0.13.3 |
| `@openzeppelin/confidential-contracts` | 0.5.3 (`ERC7984` stores `euint64`; `decimals()` returns `6`) |
| Zama Sepolia relayer | `https://relayer.testnet.zama.org` |
| Input-size measurement | Relayer `POST /v2/input-proof` plus live `confidentialTransfer` calldata on [cUSDCMock](https://sepolia.etherscan.io/address/0x7c5BF43B851c1dff1a4feE8dB225b87f2C223639) |

Zama figures below are for that stack. Protocol details can change; re-check the pinned packages before treating a number as current.

## Why COTI is not “an ERC-7984 implementation”

| Reason | What it means |
| :----- | :------------ |
| **Draft standard** | ERC-7984 is still a Draft ERC. Implementations already disagree on crypto formats and trust assumptions. |
| **Ciphertext format** | COTI `it*` / `gt*` / `ct*` is not Zama `euint*` / handles. Drop-in interface compatibility is blocked by crypto, not only API taste. |
| **Allowances, not operators** | ERC-7984 replaces amount-bounded `approve` with time-boxed **unlimited** `setOperator`. COTI keeps encrypted allowances (ERC-20 / ERC-2612-like) because private state lives on-chain and can be compared. |

Compatibility where useful: familiar transfer shapes, metadata, and explorer-facing confidential-transfer signals — **without** claiming full ERC-7984 compliance.

## Comparison

| Dimension | COTI confidential tokens | Zama / FHE ERC-7984-style (pinned stack) |
| :-------- | :----------------------- | :---------------------------------------- |
| Private state | Encrypted values **on-chain** (`gt*` / user `ct*`) | 32-byte handles on-chain; ciphertext held by coprocessors |
| Delegation | Encrypted **amount-bounded** `approve` / `transferFrom` | Public **time-boxed operator** (any amount until `until`) |
| User decrypt | Client AES decrypt of on-chain `ct*` | Relayer HTTPS → Gateway / threshold KMS re-encrypt → client |
| Contract decrypt → public logic | Native COTI: [synchronous decrypt](../how-coti-works/advanced-topics/coti-vs-others.md#advantages-over-fhe) in the same call. PoD host-chain apps: [async request/callback](../privacy-on-demand/async-private-operations.md) | Encrypted branching via `FHE.select` in the same tx. Public branching needs a **later** tx with KMS signatures ([Zama branching](https://docs.zama.org/protocol/solidity-guides/smart-contract/logics/conditions)) |
| Input validity | On-chain `validateCiphertext` (precompile `0x64`) | Client ZKPoK sent to the Relayer; coprocessors verify; host chain checks **signed handles** |
| Typical encrypted input on the host chain | `itUint256`: two 32-byte limbs + ~65-byte signature (**~192 bytes** payload) | `externalEuint64` handle (32 bytes) + `inputProof` attestation (**230 bytes** for 1 handle / 3 signers) |
| Off-chain input blob | None for native encrypt; PoD HTTP encrypt is a separate helper | Packed ciphertext + ZKPoK to Relayer: **18,794 bytes** in this measurement |
| Numeric type in the token reference | **256-bit** (`itUint256` / `gtUint256`) | **`euint64`** in OpenZeppelin `ERC7984`; `decimals()` = **6**. `euint128` has the same arithmetic ops at higher [HCU](https://docs.zama.org/protocol/solidity-guides/development-guide/hcu); `euint256` has **no** add/mul |
| Trust | MPC / garbled-circuit network (threshold network key); user AES key on the client; PoD encryption HTTP helper **does** receive plaintext | Threshold coprocessors (InputVerifier signatures); threshold KMS; Relayer is a liveness path (documented as untrusted for plaintext) |
| Host deployment | Any EVM with a PoD Inbox (computation on COTI) | FHEVM host contracts + coprocessor / Gateway assumptions |
| Concurrency | PoD: multiple in-flight requests per account, applied by request id / nonce | Host txs follow ordinary EVM account nonces; overlapping writes to the same handle are ordered by coprocessor execution of host events. Unwrap is two host txs |

## In this section

1. [**Compatibility and divergence**](compatibility-and-divergence.md) — draft standard, format mismatch, operators vs allowances.
2. [**On-chain data availability**](on-chain-data-availability.md) — private state as contract state; private → public control flow.
3. [**Decryption trust model**](decryption-trust-model.md) — client AES vs Relayer/KMS; encryption helper plaintext.
4. [**Input validation**](input-validation.md) — `validateCiphertext` vs Relayer ZKPoK + on-chain signatures.
5. [**Precision and decimals**](precision-and-decimals.md) — 256-bit vs `euint64` / 6 decimals / `euint128` cost.
6. [**Host-chain deployment**](host-chain-deployment.md) — PoD Inbox; token on your chain.
7. [**Transaction economics**](transaction-economics.md) — measured calldata vs off-chain proof size.
8. [**Transfer semantics**](transfer-semantics.md) — encrypted allowances and silent insufficient-balance handling.
9. [**Concurrency**](concurrency.md) — in-flight PoD requests vs Zama handle updates.
10. [**Deployed contracts**](deployed-contracts.md) — live pTokens on Fuji and Sepolia.
43 changes: 43 additions & 0 deletions coti-erc7984/compatibility-and-divergence.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Compatibility and divergence

COTI offers confidential fungible tokens. It does **not** ship a complete [ERC-7984](https://eips.ethereum.org/EIPS/eip-7984) implementation. ERC-7984 is a **Draft** ERC (created 3 July 2025; citation still `[DRAFT]` as of 6 September 2026).

## 1. Draft interface, multiple cryptosystems

ERC-7984 standardises names and `bytes32` **pointers**. Pointer resolution, ciphertext format, and trust assumptions are implementation-specific. The common reference is [OpenZeppelin confidential contracts](https://docs.openzeppelin.com/confidential-contracts/token) on Zama FHEVM (`@openzeppelin/confidential-contracts` 0.5.3, balances as `euint64`).

COTI uses a different crypto (`it*` / `gt*` / `ct*`). Selective compatibility (transfer shapes, metadata, explorer-facing confidential-transfer signals) is not byte-compatible ERC-7984.

## 2. Encrypted data formats

| Role | COTI | Zama / FHE ERC-7984-style (pinned stack) |
| :--- | :--- | :---------------------------------------- |
| User input | `it*` (ciphertext + signature) | `externalEuint*` handle + `inputProof` (**coprocessor signatures**, not the ZKPoK — [Input validation](input-validation.md)) |
| Network private state | `gt*` (network-key / garbled) | Handle; ciphertext with coprocessors; ACL |
| User-readable output | `ct*` (account AES key) | Handle; decrypt via Relayer / KMS ([Decryption trust model](decryption-trust-model.md)) |

## 3. Operators vs encrypted allowances

ERC-7984 replaces amount-bounded `approve` with:

```solidity
// Public relationship. Operator may transfer any amount until `until`.
function setOperator(address operator, uint48 until) external;
function isOperator(address holder, address spender) external view returns (bool);
```

While the grant is live, the operator can move **any** amount of the holder’s token. `OperatorSet` / `isOperator` are **plaintext**. Balances and transfer amounts stay encrypted. The EIP rationale is to avoid tracking encrypted approval amounts on the external system.

COTI keeps **encrypted, amount-bounded** allowances (ERC-20 / ERC-2612-like `approve` / `transferFrom`):

- Allowance values are ciphertext.
- Compare-and-subtract runs in private execution ([on-chain data availability](on-chain-data-availability.md)).
- There is no public “unlimited until time T” grant as the primary delegation model.

| | COTI | ERC-7984 / OpenZeppelin `ERC7984` |
| :- | :--- | :-------------------------------- |
| Delegation | Encrypted amount-bounded allowance | Time-boxed operator |
| Amount the delegate may spend | The approved encrypted amount | Any amount until `until` |
| Relationship on-chain | Allowance ciphertext | Public `isOperator` / `OperatorSet` |

[Transfer semantics](transfer-semantics.md) covers silent insufficient-balance handling. Native PrivateERC20 and PoD pERC20 developer guides live under COTI Privacy Portal and Build on COTI.
21 changes: 21 additions & 0 deletions coti-erc7984/concurrency.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Concurrency

How overlapping confidential transfers are ordered.

## COTI PoD (host-chain pTokens)

A user can submit **multiple** Inbox requests while earlier ones are still in flight. Each request has a **request id**. A **monotonic nonce** on the COTI-side token applies results in order so two in-flight transfers from the same account do not clobber each other.

The host-chain mental model is still **async**: submit → wait → callback. See [Async private operations](../privacy-on-demand/async-private-operations.md).

## Zama / FHEVM ERC-7984-style tokens

Host-chain transactions follow the ordinary **EVM account nonce**. One account cannot have two pending host txs mined out of nonce order.

Coprocessors execute FHE ops in the order of host events for a given handle. There is no PoD-style in-flight **request queue** on the token: a `confidentialTransfer` that already passed Relayer input registration is a single host transaction.

Flows that need a **public** result take **two host transactions** (for example `unwrap` then `finalizeUnwrap`). Those two txs are sequenced by the EVM nonce and by waiting for KMS signatures in between — not by a PoD request id.

## Transfer semantics

Silent insufficient-balance handling (encrypted amount → effective zero) is independent of this queueing model. See [Transfer semantics](transfer-semantics.md).
69 changes: 69 additions & 0 deletions coti-erc7984/decryption-trust-model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Decryption trust model

Who can see plaintext, and which services sit on the path?

**Decrypt of user `ct*` on COTI is local:** the client reads ciphertext from chain and AES-decrypts with the account key. That step does not send ciphertext to a server for plaintext recovery.

**Encrypt is a separate path.** Native COTI SDKs can encrypt locally with the same AES key. PoD dApps that call `CotiPodCrypto.encrypt` **POST the plaintext** to the PoD encryption HTTP service (`buildEncryptedInputs`). That helper **does receive plaintext**. Do not treat “client-side decrypt” as “no server ever sees the value.”

Zama user decrypt goes Relayer HTTPS → Gateway / threshold KMS (re-encrypt to the user’s transport key) → client. The Relayer is documented as untrusted for plaintext; the KMS and coprocessors are the cryptographic trust base.

## Trust assumptions

| | COTI | Zama / FHEVM (pinned stack, 6 Sep 2026) |
| :- | :--- | :-------------------------------------- |
| Who holds the network key | MPC / garbled-circuit nodes hold **threshold shares** of the network AES key. No single node is documented as able to reconstruct it ([AES keys](../how-coti-works/advanced-topics/aes-keys.md)). | Threshold **coprocessors** attest inputs (`InputVerifier` signatures). Threshold **KMS** decrypts under the FHE network key. |
| User key | Account AES key from onboarding (`GetUserKey` / wallet plugin). The client must store it; loss means those `ct*` values cannot be decrypted. | User transport key for KMS re-encrypt. ACL on handles controls who may request decrypt. |
| Encrypt-time plaintext | **PoD:** encryption HTTP service reads the plaintext. **Native COTI:** `encryptValue` can stay on the client. | Client WASM encrypts under the FHE public key. Relayer sees packed ciphertext + ZKPoK, not the plaintext. |
| Decrypt-time plaintext | Client AES on `ct*`. No Relayer decrypt hop. | Client recovers plaintext after KMS re-encrypt. Relayer/Gateway are on the path (liveness). |
| Liveness | PoD also depends on Inbox / relayer for **request and callback**. Native COTI decrypt does not. | Relayer + Gateway for **input registration and decrypt**. Failure can happen before a host tx exists ([Input validation](input-validation.md)). |

## COTI: local AES decrypt

1. Onboard → account AES key.
2. Contract returns or stores `ct*` for that user (`offBoardToUser` / PoD callback).
3. Client reads the ciphertext from chain and decrypts locally (AES + XOR).

```typescript
import { CotiPodCrypto, DataType } from "@coti-io/pod-sdk";

// Ciphertext already on-chain (e.g. from balanceOf / offBoardToUser).
const ciphertextHex = await token.balanceOf(userAddress);

// Decrypt is in-process with the user's AES key.
const plain = CotiPodCrypto.decrypt(
ciphertextHex.toString(),
accountAesKey,
DataType.Uint256
);
```

```typescript
// PoD encrypt: plaintext is in the HTTP body. The encryption service reads it.
const enc = await CotiPodCrypto.encrypt(
"1000",
"testnet",
DataType.itUint256
);
```

## Zama: Relayer HTTPS → KMS re-encrypt → client

Typical TypeScript ([Zama encrypt & decrypt](https://docs.zama.org/protocol/sdk/guides/encrypt-decrypt)):

```typescript
import { ZamaSDK } from "@zama-fhe/sdk";

const { encryptedValues, inputProof } = await sdk.encrypt({
values: [{ value: 1000n, type: "euint64" }],
contractAddress,
userAddress,
});

// User decrypt of a handle: Relayer HTTPS → Gateway / KMS re-encrypt.
const decrypted = await sdk.decryption.decryptValues([
{ encryptedValue: handleFromChain, contractAddress },
]);
```

**Public** decrypt (plaintext that a contract can `require` on) is a different flow: off-chain KMS signatures, then a **later** host transaction. See [On-chain data availability](on-chain-data-availability.md) and COTI native [synchronous decrypt](../how-coti-works/advanced-topics/coti-vs-others.md#advantages-over-fhe).
21 changes: 21 additions & 0 deletions coti-erc7984/deployed-contracts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Deployed contracts

Six PoD pTokens on public testnets (addresses as of this documentation; redeploys can change them). These are **COTI confidential wrappers**, not ERC-7984 deployments.

**Avalanche Fuji**

| Token | Address | Decimals |
| :------- | :------------------------------------------- | :------: |
| `p.MTT` | `0x02f284a1968160E1d3e4bC2BA3261be49725E765` | 18 |
| `p.USDC` | `0x21576D8CCE47d044C5815bd59eca1F6DA94c65A5` | 6 |
| `p.AVAX` | `0x74d47cD68203066c97BA99787Fe1e0c68Ce42b04` | 18 |

**Ethereum Sepolia**

| Token | Address | Decimals |
| :------- | :------------------------------------------- | :------: |
| `p.MTT` | `0x0510F0b32828D5fB472dE5A5bE30b370c5D1a056` | 18 |
| `p.USDC` | `0xD7B3D49F85000489708B7db5B0f1a8693Fc707f3` | 6 |
| `p.ETH` | `0xd33A363459c6Ee0C4F8504E380E8D3Aa4F209116` | 18 |

Each pair is a `PrivacyPortalFactory` minimal-proxy clone: one portal and one pToken per asset. Decimals match the underlying (see [Precision and decimals](precision-and-decimals.md)).
14 changes: 14 additions & 0 deletions coti-erc7984/host-chain-deployment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Host-chain deployment

Privacy on Demand puts the **confidential wrapper on the host chain**. Encrypted computation runs on COTI. The host does not need FHE precompiles, a forked EVM, or an ERC-7984 stack.

| | |
| :--- | :--- |
| Host requirement | An EVM chain with a PoD Inbox |
| Live testnets (6 Sep 2026) | Avalanche Fuji, Ethereum Sepolia |
| Token contract | Ordinary host-chain bytecode (portal + pToken clone) |
| Private execution | COTI MPC / garbled-circuit path, via Inbox request/callback |

Zama FHEVM confidential tokens instead assume FHEVM host contracts, Relayer/Gateway, and coprocessors on that host.

Inbox and executor roles: [Architecture and main components](../privacy-on-demand/architecture-and-components.md). Live addresses: [Deployed contracts](deployed-contracts.md). ERC-7984 relationship: [Compatibility and divergence](compatibility-and-divergence.md).
Loading