githubEdit

📄PrivateERC20.sol

Overview

PrivateERC20arrow-up-right is an abstract Solidity contract that implements a fully encrypted ERC20 token on the COTI network.

Unlike a standard ERC20, where balances and transfer amounts are publicly visible on-chain, PrivateERC20 stores balances and allowances as ciphertexts (encrypted values).

These values:

  • can only be decrypted by the token holder

  • use a personal AES key managed via the COTI Snap

All token operations, such as transfers, minting, and burning, are performed directly on encrypted data.

Encrypted Computation

Encryption and arithmetic on encrypted values are handled by COTI's MpcCore precompile at address 0x64.

This precompile enables the network to perform operations such as:

  • addition

  • subtraction

  • comparisons

on encrypted numbers without revealing the underlying plaintext, including to validators.

How PrivateERC20 differs from ERC20

PrivateERC20 follows the ERC20 interface, but changes how data is stored and exposed.

Feature
Standard ERC20
PrivateERC20

Balances visible on-chain

Yes (public)

No (encrypted ciphertext)

Transfer amounts visible

Yes

No

Allowances visible

Yes

No

totalSupply() returns real value

Yes

No — always returns 0 for privacy

Requires AES key to read balance

No

Yes

Supports plain uint256 operations

Yes

Yes

Supports encrypted operations

No

Yes (itUint256, gtUint256 variants)

How it works

Balances

Balances are stored on-chain as ctUint256 (ciphertext). Each account maintains two ciphertext values:

  • ciphertext - used by the MPC network

  • userCiphertext - re-encrypted for the user

Transfers

Transfers are executed via the MPC precompile using MpcCore.transfer(), which atomically updates both sender and receiver balances in encrypted form.

Reading your balance

To read a balance:

  • call balanceOf(address) to retrieve the ciphertext

  • decrypt it locally using your AES key via the COTI SDK

Writing encrypted amounts

Operations such as transfer, approve, mint, and burn require constructing an itUint256:

  • an AES-encrypted value

  • plus an ECDSA signature

This allows the MPC network to verify that the input was created by the rightful key holder.

Onboarding

Onboarding registers your wallet's encryption address on-chain via setAccountEncryptionAddress().

This enables the contract to re-encrypt balances specifically for your AES key.

Last updated

Was this helpful?