Skip to content
Lattice

IShieldedPool

Git Source

Title: IShieldedPool

Author: David Dada <daveproxy80@gmail.com> (https://github.com/dadadave80)

External interface for fixed-denomination shielded (private) ERC-20 transfers. A depositor inserts a commitment into a Poseidon incremental Merkle tree; later, anyone holding the secret withdraws to an arbitrary recipient by proving, in zero knowledge, that their commitment is in the tree — without revealing which — and publishing a one-time nullifier hash that blocks double-spends.

Tornado-style. The pool provides the on-chain mechanics (commitment tree + nullifier set + fixed-denomination ERC-20 escrow); the WITHDRAW CIRCUIT + its verifier are supplied by the consumer (set per pool), so the cryptography is wrapped, not hand-rolled. The circuit's 5 public signals MUST be [root, nullifierHash, recipient, relayer, fee]; the commitment is Poseidon(nullifier, secret), the tree is the shared Poseidon LeanIMT, and nullifierHash blocks reuse. SECURITY: this module escrows funds and must be deployed with an AUDITED circuit + verifier and an honest trusted setup before any mainnet-with-funds use.

Functions

createPool

Creates a fixed-denomination shielded pool. Gated on the default admin role.

function createPool(address token, uint256 denomination, address verifier) external returns (uint256 poolId);

Parameters

NameTypeDescription
tokenaddressThe ERC-20 token escrowed.
denominationuint256The fixed deposit/withdraw amount.
verifieraddressThe withdraw-circuit verifier; it MUST pin its key (see IShieldedWithdrawVerifier).

Returns

NameTypeDescription
poolIduint256The new pool id (1-based).

deposit

Deposits one denomination and inserts commitment = Poseidon(nullifier, secret).

Pulls denomination of the pool token from msg.sender (requires prior approval).

function deposit(uint256 poolId, uint256 commitment) external;

Parameters

NameTypeDescription
poolIduint256The pool.
commitmentuint256The commitment to insert.

withdraw

Withdraws denomination - fee to recipient and fee to relayer, against a proof.

function withdraw(
        uint256 poolId,
        WithdrawProof calldata proof,
        uint256 root,
        uint256 nullifierHash,
        address recipient,
        address relayer,
        uint256 fee
    ) external;

Parameters

NameTypeDescription
poolIduint256The pool.
proofWithdrawProofThe Groth16 withdrawal proof.
rootuint256A known recent Merkle root the proof was built against.
nullifierHashuint256The one-time spend tag (blocks double-spends).
recipientaddressThe withdrawal recipient.
relayeraddressThe relayer paid fee (may be the recipient; fee may be 0).
feeuint256The relayer fee, &lt;= denomination.

poolCount

Returns the number of pools created.

function poolCount() external view returns (uint256);

Returns

NameTypeDescription
<none>uint256

getPool

Returns pool config + state: token, denomination, verifier, current root, leaf count.

function getPool(uint256 poolId)
        external
        view
        returns (address token, uint256 denomination, address verifier, uint256 merkleRoot, uint256 numLeaves);

Parameters

NameTypeDescription
poolIduint256

Returns

NameTypeDescription
tokenaddress
denominationuint256
verifieraddress
merkleRootuint256
numLeavesuint256

isSpent

Returns whether nullifierHash has been spent in poolId.

function isSpent(uint256 poolId, uint256 nullifierHash) external view returns (bool);

Parameters

NameTypeDescription
poolIduint256
nullifierHashuint256

Returns

NameTypeDescription
<none>bool

isKnownRoot

Returns whether root is a known recent root of poolId.

function isKnownRoot(uint256 poolId, uint256 root) external view returns (bool);

Parameters

NameTypeDescription
poolIduint256
rootuint256

Returns

NameTypeDescription
<none>bool

Events

PoolCreated

Emitted when a pool is created.

event PoolCreated(uint256 indexed poolId, address indexed token, uint256 denomination, address indexed verifier);

Parameters

NameTypeDescription
poolIduint256
tokenaddress
denominationuint256
verifieraddress

Deposit

Emitted on a deposit.

event Deposit(uint256 indexed poolId, uint256 indexed commitment, uint256 leafIndex, uint256 merkleRoot);

Parameters

NameTypeDescription
poolIduint256The pool.
commitmentuint256The inserted commitment.
leafIndexuint256The commitment's leaf index.
merkleRootuint256The new tree root.

Withdrawal

Emitted on a withdrawal.

event Withdrawal(
        uint256 indexed poolId, uint256 indexed nullifierHash, address indexed recipient, address relayer, uint256 fee
    );

Parameters

NameTypeDescription
poolIduint256
nullifierHashuint256
recipientaddress
relayeraddress
feeuint256

Errors

ShieldedPoolDoesNotExist

Thrown when the pool id does not exist.

error ShieldedPoolDoesNotExist();

ShieldedPoolInvalidConfig

Thrown when creating a pool with a token that has no code, a zero verifier, or a zero denomination.

error ShieldedPoolInvalidConfig();

ShieldedPoolUnknownRoot

Thrown when the withdrawal root is not a known recent root of the pool.

error ShieldedPoolUnknownRoot();

ShieldedPoolNullifierAlreadySpent

Thrown when the nullifier hash has already been spent.

error ShieldedPoolNullifierAlreadySpent();

ShieldedPoolFeeExceedsDenomination

Thrown when the relayer fee exceeds the pool denomination.

error ShieldedPoolFeeExceedsDenomination();

ShieldedPoolInvalidProof

Thrown when the withdrawal proof does not verify.

error ShieldedPoolInvalidProof();

ShieldedPoolTransferFailed

Thrown when an ERC-20 transfer / transferFrom reverts, returns false, or token has no code.

error ShieldedPoolTransferFailed(address token);

Parameters

NameTypeDescription
tokenaddressThe token whose transfer failed.

Structs

WithdrawProof

A Groth16 withdrawal proof.

struct WithdrawProof {
        uint256[2] a;
        uint256[2][2] b;
        uint256[2] c;
    }

Properties

NameTypeDescription
auint256[2]
buint256[2][2]
cuint256[2]