How do PoA fees work?
PoA fees here are the Privacy on Demand (PoD) fees you pay in native token on your EVM chain (for example Sepolia ETH) when you use a two-way Inbox message: your contract sends add(itUint64 a, itUint64 b), and the success path returns ctUint64 c through a callback. The same mechanics apply to other PodLib operations that use msg.value and callbackFeeLocalWei.
This page explains how that payment is split, converted (via oracles) into execution budgets on each side—often described as gas units—and consumed step by step.
The numbers below are a single worked example so you can follow the arithmetic. Live networks use oracle and Inbox policy to set conversion rates and minimums; use your deployment’s views (for example calculateTwoWayFeeRequiredInLocalToken) and the SDK’s Fees, gas, and oracle reference for production.
Example call
Solidity shape (conceptually):
Request:
add(itUint64 a, itUint64 b)withmsg.valueandcallbackFeeLocalWeiSuccess callback: receives
abi.encode(ctUint64 c)(encrypted sum)
Tables: fee flow and consumption
Serialized flow: ledgers open after the oracle; COTI spends first (relay + private add), then Sepolia (relay response + callback). sendTwoWayMessage binds the payment to outbound + return routes. Exact splits and minima are enforced on-chain (Inbox, fee manager).
From user fee to gas-unit ledgers (single table)
User-provided gas
0.007 ETH (
msg.value)0.0035 ETH (
callbackFeeLocalWei, Sepolia)0.0035 ETH (COTI-side)
5 gwei (reference)
Price at oracle (same quote, e.g. USD)
COTI: 0.017 per 1 COTI.
ETH: 2,170 per 1 ETH.
Converted to the chain gas (COTI — ETH)
COTI: 446.76 COTI
ETH: 0.0035 ETH
Convert to gas units (COTI — ETH)
COTI: 16,029,096
ETH: 615,701
Gas used and remaining (both legs)
—
—
Balances after oracle
—
16,029,096
615,701
1
COTI
Relayers relay request
12,000
16,017,096
615,701
2
COTI
Private add → ciphertext c
492,902
15,524,194
615,701
3
Sepolia
Miner relays response
8,000
15,524,194
607,000
4
Sepolia
addCallback stores ctUint64 c
230,000
15,524,194
377,000
Walkthrough
Read the first table top to bottom: user ETH is split by leg, oracles supply COTI and ETH prices, the COTI leg is expressed as quote → COTI tokens, then policy turns each leg into gas-unit budgets. The second table spends COTI first, then Sepolia after the result exists. Underspend remains are illustrative; production behavior depends on InboxMiner / InboxFeeManager and operator policy (see the SDK Fees, gas, and oracle doc).
Why this matters for add(a, b) → ctUint64 c
add(a, b) → ctUint64 cPrivate execution and callback execution happen in different environments, as separate steps in time: COTI runs first; the Sepolia relay and callback run after the result exists. Each leg needs its own paid work (compute + relay).
callbackFeeLocalWeiis structurally important: if the callback leg is under-funded,cmay never be written, and UIs stay pending (see Async private operations).Too little
msg.valuetends to hurt the outbound / COTI path; too little callback slice tends to hurt the return / Sepolia path.
Where to implement this in code
Solidity: payable
addwithmsg.valueandcallbackFeeLocalWei, as in Tutorial: private Adder on Sepolia (see Tutorials overview for how this fits the primitive-only model).Estimation: Inbox
calculateTwoWayFeeRequiredInLocalTokenand the Fees, gas, and oracle document in the PoD SDK repo.
Disclaimer
The rates, unit counts, and remainders on this page are pedagogical. They do not replace reading live on-chain configuration, oracles, and Inbox / miner behavior for your network.
Last updated
Was this helpful?