Smart Contracts
Dogenado's core logic is implemented in Solidity smart contracts deployed on DogeOS.
Contract Overview
| Contract | Purpose |
|---|---|
| MixerPoolV2 | Main pool contract for deposits/withdrawals |
| Verifier | Groth16 ZK proof verification |
| Hasher | MiMC sponge hash function |
MixerPoolV2
The main mixer contract handling deposits and withdrawals.
Key Functions
deposit
function deposit(bytes32 _commitment) external
Deposits tokens into the pool:
- Transfers tokens from user to contract
- Inserts commitment into Merkle tree
- Emits
Depositevent
withdraw
function withdraw(
bytes calldata _proof,
bytes32 _root,
bytes32 _nullifierHash,
address payable _recipient,
address payable _relayer,
uint256 _fee,
uint256 _refund
) external
Withdraws tokens from the pool:
- Verifies the ZK proof
- Checks nullifier hasn't been spent
- Marks nullifier as spent
- Transfers tokens to recipient (minus fee)
scheduleWithdrawal
function scheduleWithdrawal(
bytes calldata _proof,
bytes32 _root,
bytes32 _nullifierHash,
address payable _recipient,
address payable _relayer,
uint256 _fee,
uint256 _delay
) external
Schedules a withdrawal with timelock:
- Verifies the ZK proof
- Stores withdrawal details with unlock timestamp
- Emits
WithdrawalScheduledevent
executeScheduledWithdrawal
function executeScheduledWithdrawal(bytes32 _nullifierHash) external
Executes a scheduled withdrawal after timelock:
- Checks unlock time has passed
- Marks nullifier as spent
- Transfers tokens to recipient
State Variables
// Immutable configuration
IVerifier public immutable verifier;
IHasher public immutable hasher;
IERC20 public immutable token;
uint256 public immutable denomination;
// Merkle tree
uint32 public constant MERKLE_TREE_HEIGHT = 20;
uint32 public currentRootIndex;
uint32 public nextIndex;
bytes32[MERKLE_TREE_HEIGHT] public filledSubtrees;
bytes32[ROOT_HISTORY_SIZE] public roots;
// Nullifier tracking
mapping(bytes32 => bool) public nullifierHashes;
// Commitment tracking
mapping(bytes32 => bool) public commitments;
// Scheduled withdrawals
mapping(bytes32 => ScheduledWithdrawal) public scheduledWithdrawals;
Events
event Deposit(
bytes32 indexed commitment,
uint32 leafIndex,
uint256 timestamp
);
event Withdrawal(
address to,
bytes32 nullifierHash,
address indexed relayer,
uint256 fee
);
event WithdrawalScheduled(
bytes32 indexed nullifierHash,
address recipient,
uint256 unlockTime
);
Verifier Contract
Auto-generated Groth16 verifier from the trusted setup.
Verification
function verifyProof(
uint[2] memory a,
uint[2][2] memory b,
uint[2] memory c,
uint[2] memory input
) public view returns (bool)
Inputs:
a,b,c: Proof componentsinput[0]: Root of Merkle treeinput[1]: Nullifier hash
Returns true if the proof is valid.
Hasher Contract
Implements MiMC sponge hash for Merkle tree operations.
function MiMCSponge(
uint256 in_xL,
uint256 in_xR
) public pure returns (uint256 xL, uint256 xR)
Used for:
- Computing commitment hashes
- Building Merkle tree
- Computing nullifier hashes
Security Considerations
Reentrancy Protection
All external calls happen after state updates (checks-effects-interactions pattern).
Overflow Protection
Uses Solidity 0.8+ built-in overflow checks.
Access Control
- No admin functions
- No upgradability
- Immutable after deployment
Front-running Protection
- Commitments are hashed (can't predict deposits)
- Nullifiers are hashed (can't predict withdrawals)
Gas Costs
| Operation | Approximate Gas |
|---|---|
| Deposit | ~900,000 gas |
| Withdraw | ~300,000 gas |
| Schedule Withdrawal | ~350,000 gas |
| Execute Scheduled | ~150,000 gas |
Next: Zero-Knowledge Proofs