Smart contracts

Senddy's on-chain contracts — pool, verifiers, and yield strategies.

Overview#

Senddy's smart contracts are deployed on Base (Coinbase's Layer 2). The system is centered around a single pool contract that manages all deposits, shields, spends, and withdrawals.

Core Contracts#

Pool Contract#

The main contract. All user funds are held here.

Key capabilities:

  • Gasless deposit and shield in one transaction, authorized by an EIP-3009 signature whose nonce is bound to the new note. This is the only deposit path: there is no approval step, no Permit2, no escrow and no separate shield call.
  • Two entry points for it: depositAndShieldWithEIP3009 (EOAs, v/r/s) and depositAndShieldWithEIP3009Sig (smart wallets, ERC-1271)
  • Execute private spends (transfers between users)
  • Execute spends with a public withdrawal
  • Accrue yield from the strategy
  • Screen deposits against the Chainalysis sanctions oracle — OFAC-sanctioned addresses are blocked at the contract level

State:

  • Known Merkle tip ring (currentRoot + recent roots) — the full commitment tree is maintained in the attestor enclave; the pool checks membership via isKnownRoot
  • Nullifier accumulator (tracks spent notes)
  • Asset configuration and strategy addresses
  • Attestor address (authorized proof verifier)

Verifier Contracts#

Senddy uses dedicated verifier contracts for each proof type:

  • Shield Verifier — Verifies zero-knowledge proofs for shield operations, generated from the Noir shield circuit using the UltraHonk proving system
  • Spend Verifier — Verifies zero-knowledge proofs for spend operations

Yield Strategy#

The pool deploys funds to trusted DeFi lending protocols for yield generation. The strategy contract manages deposits, withdrawals, and yield reporting back to the pool.

The pool supports a modular strategy interface, allowing multiple yield strategies to be used in the future.

Security#

  • Contracts are upgradeable with access-controlled owner functions. The owner is a single key with no on-chain delay; hardening it is tracked internally as an open item.
  • Spends require a known Merkle tip (isKnownRoot) bound in the attestor EIP-712 digest
  • Spend authorization: spending a note requires the recipient's spend key, not merely knowledge of the note's secrets
  • Reviewed in internal security audits; open findings tracked internally