Privacy Precompile
Shielded OKRW transfers via a policy-aware precompile at 0x1000…000b. Deposits are payable; withdrawals settle to a public recipient; transfers stay inside the pool.
The Privacy precompile at 0x100000000000000000000000000000000000000b exposes shielded OKRW operations — deposit, transfer, withdraw, their authorization variants, and two batch variants — as an EVM-callable surface wrapped by the policy-aware precompile framework. Deposits are payable and take their amount from native msg.value in aokrw; the request struct itself carries only the note commitment, encrypted note, and ZK proof. Every mutating call exposes exactly one contract-scoped PolicyOperation that PCL evaluates before and after execution, so contract policies (denylists, periodic caps) apply uniformly to shielded flows.
Architecture
flowchart LR
User[User dApp]:::evm
Relayer[Relayer / Executor]:::evm
Privacy[Privacy Precompile<br/>0x1000…000b]:::precompile
Recipient[Transparent Recipient]:::evm
User -- deposit / transfer / withdraw --> Privacy
User -- EIP-712 signed intent --> Relayer
Relayer -- ...WithAuthorization --> Privacy
Privacy -- withdraw payout --> Recipient
classDef evm fill:#0096AA,stroke:#0096AA,color:#fff;
classDef precompile fill:#FF8C50,stroke:#FF8C50,color:#fff; Direct callers hit the Privacy precompile from their own wallet; delegated callers sign an EIP-712 authorization off-chain and let a relayer submit the `…WithAuthorization` variant. Withdrawals settle to a transparent EVM recipient.
Method surface
| Method | Payable | Purpose |
|---|---|---|
deposit | yes | Shield native OKRW; amount comes from msg.value. |
transfer | no | Move shielded notes inside the pool. |
withdraw | no | Unshield to a public recipient. |
transferWithAuthorization | no | Same as transfer, executed by a delegate under a signed authorization. |
withdrawWithAuthorization | no | Same as withdraw, delegated. |
batchTransfer | no | Multiple independent transfers under one batch id. |
batchTransferWithAuthorization | no | Delegated batch transfer. |
singleProofBatchTransfer | no | One aggregated ZK proof covering many inputs/outputs. |
singleProofBatchTransferWithAuthorization | no | Delegated single-proof batch. |
There is no
depositWithAuthorization. Deposits require the operator (msg.sender) to be the effective sender, so the depositor's own signature secures the operation directly.Deposit amount lives in msg.value
deposit is { bytes noteCommitment; bytes encryptedNote; bytes proof; } — no amount field. The deposit amount is derived from msg.value under the runtime native denom (aokrw). The PrivacyDeposit event still records the amount as a Cosmos-coin-formatted string ("10000000000000000000000000aokrw" for 10,000,000 OKRW) so downstream indexers see a canonical value.// Shield 10,000,000 OKRW.
PRIVACY.deposit{value: 10_000_000 ether}(PrivacyDepositRequest({
noteCommitment: commitment,
encryptedNote: encNote,
proof: zkProof
})); Policy-aware wrapping
vm.PrecompiledContract directly. It is composed of a raw executor plus the policy-aware wrapper described in privacy-policy-aware-precompile. The wrapper takes the single PolicyOperation the executor prepares for each call and drives PCL through evaluate-before → execute → evaluate-after → record. A shielded transfer's hidden amount is modeled with value = 0 in that operation so identity and denylist policies still run without recording unverifiable periodic volume; a public deposit carries the true msg.value and does count toward volume caps.