AndCall functions transfer, then call the recipient, which can record the deposit or send the tokens back. Use them when a contract must act on what it received, such as crediting a deposit.
Which functions make the callback?
In the wallet forms,
inputProof comes right after the encrypted amount and before data. Both are bytes, so swapping them compiles and fails at runtime. data is passed to the recipient unchanged.
How does the callback work?
The token moves the amount first. Ifto has code, it then calls onConfidentialTransferReceived on it:
- The token shares the moved amount with
toas asharedEuint64and calls the receiver with the operator (the caller of the token function),from, that amount, anddata. - The receiver returns a
sharedEbool: true to keep the tokens, false to refuse them. - The token moves back whatever the receiver refused: the full amount on false, zero on true.
to has no code, there is no callback and the tokens stay with to.
The function returns sent - refund as a sharedEuint64. That is zero when the receiver refused, and also zero when the sender’s balance was too low.
How do you implement a receiver?
ImplementIERC7984Receiver. This receiver accepts deposits up to a cap and refuses larger ones:
CappedDepositBox.sol
- Check
msg.sender.FHE.receiveEuint64Paramaccepts any share whose sharer is the caller. A contract you do not know can share an amount it invented and call you directly, so only trust the token you expect. - Unwrap with
FHE.receiveEuint64Param. It reverts withNotSharedorUnexpectedSharerunless the caller shared the amount with this contract in this transaction. - Call
FHE.allowThison what you store. The received amount carries access for this transaction only. Values you derive from it and keep need a persistent grant. - Return
FHE.shareEbool(result, msg.sender). The token accepts the result only as a share from the address it called.
When does the transfer revert?
What does a callback transfer emit?
The refund step runs on everyAndCall, even when it refunds zero or to has no code. Each call therefore emits Transfer and ConfidentialTransfer twice: once from from to to, then once from to back to from.
The two steps also cancel out in the indicators. A callback transfer leaves both indicators where they were, except that a first-time recipient moves from 0 to 7984.0000.