Privacy Pools
The PrivacyPool contract is an abstract contract that implements core privacy pools functionality for both native ETH and ERC20 tokens. It:
- Manages commitments and nullifiers
- Processes deposits and withdrawals
- Handles merkle tree state
- Validates zero-knowledge proofs
The contract extends the State base contract which manages the merkle tree and nullifier state.
Key Components
State Management
Inherits key state variables from the State contract:
string public constant VERSION = '0.1.0';
uint32 public constant ROOT_HISTORY_SIZE = 30;
IEntrypoint public immutable ENTRYPOINT;
IVerifier public immutable WITHDRAWAL_VERIFIER;
IVerifier public immutable RAGEQUIT_VERIFIER;
uint256 public nonce;
bool public dead;
And adds pool-specific state:
uint256 public immutable SCOPE;
address public immutable ASSET;
Core Data Structures
Withdrawal Struct
struct Withdrawal {
address processooor; // Allowed address to process withdrawal
uint256 scope; // Unique pool identifier
bytes data; // Encoded arbitrary data used by Entrypoint
}
Core Functionality
1. Deposit Processing
function deposit(
address _depositor,
uint256 _value,
uint256 _precommitmentHash
) external payable onlyEntrypoint returns (uint256 _commitment)
The deposit flow:
- Validates pool is active
- Computes unique label from scope and nonce
- Records deposit details and ragequit cooldown
- Computes and stores commitment hash
- Updates merkle tree state
- Pulls funds from depositor
2. Withdrawal Processing
function withdraw(
Withdrawal memory _withdrawal,
ProofLib.WithdrawProof memory _proof
) external validWithdrawal(_withdrawal, _proof)
Handles withdrawals by:
- Validating withdrawal proof
- Verifying state root and ASP root
- Spending nullifier hash
- Inserting new commitment
- Transferring funds to processor
3. Ragequit Functionality
function ragequit(ProofLib.RagequitProof memory _proof) external
Allows original depositors to:
- Reclaim funds when ASP excludes them
- Verify they are original depositor
- Spend nullifier hash
- Receive back deposited funds
4. Wind Down Capability
function windDown() external onlyEntrypoint
Allows graceful shutdown:
- Marks pool as dead
- Prevents new deposits
- Allows existing withdrawals
Security Features
- Access Control:
onlyEntrypoint
modifier for sensitive operationsvalidWithdrawal
modifier for proof validation
- Withdrawal Validation:
modifier validWithdrawal(Withdrawal memory _withdrawal, ProofLib.WithdrawProof memory _proof) {
// Check caller is allowed processor
if (msg.sender != _withdrawal.processooor) revert InvalidProcesooor();
// Verify context integrity
if (_proof.context() != uint256(keccak256(abi.encode(_withdrawal, SCOPE)))) {
revert ContextMismatch();
}
// Validate roots
if (!_isKnownRoot(_proof.stateRoot())) revert UnknownStateRoot();
if (_proof.ASPRoot() != ENTRYPOINT.latestRoot()) revert IncorrectASPRoot();
_;
}
- Proof Verification:
- Validates zero-knowledge proofs using Groth16 verifiers
- Verifies nullifier hash uniqueness
- Checks commitment existence
Asset Handling
The contract is abstract and requires implementation of two key functions:
function _pull(address _sender, uint256 _value) internal virtual;
function _push(address _recipient, uint256 _value) internal virtual;
These are implemented differently for:
- Native ETH (PrivacyPoolSimple)
- ERC20 tokens (PrivacyPoolComplex)
The PrivacyPool contract provides a robust foundation for implementing privacy-preserving asset pools, with strong security guarantees and efficient state management. It's designed to be extended for specific asset types while maintaining consistent privacy and security properties.