Migration Receivers
Receive a source withdrawal, credit a fixed private account and recover uncredited funds after a deadline.
Source and receiving account#
FuyuMigrationReceiver credits the existing Fuyu funding interface with immutable Terms. These include source kind, contract and code hash, target Pool/domain, chain, asset, private owner commitment, recovery salt, encrypted profile hash, output attachment, expected amount, refund recipient and deadline.
The source protocol checks its own proof, and Fuyu keeps its existing screening rules. When the receiver deposits into Fuyu, the Pool records the receiver as the funding source. The configured source identifies the withdrawal route; it cannot replace that deposit-source record.
Receiver terms#
The constructor rejects an unknown source kind, missing source/Pool code, a different source runtime or wrong chain/domain. It also rejects an invalid owner commitment, missing salt/profile hash, zero or over-uint128 expected amount, invalid refund recipient or elapsed deadline. The Pool must admit an ERC-20 settlement asset; address(0) means native ETH.
The source-kind enum contains TornadoClassic, PrivacyPoolsV1, PrivacyPoolsV2, ZkMoney and AztecConnect. Each source deployment still needs a working withdrawal executor. Check its adapter, recipient, calldata and recovery path before enabling that source in the UI.
| Term | What it fixes |
|---|---|
| source / sourceCodeHash | The withdrawal call target and its reviewed runtime |
| pool / poolDomain / chainId | The receiving deployment and note domain |
| asset / expectedAmount | The token and atomic amount to credit |
| ownerCommitment / recoverySalt | The private receiving account |
| encryptedProfileHash / policyCommitment | The recovery bytes and note attachment |
| refundRecipient / refundAfter | Who receives public recovery funds, and when |
Credit funds or execute a withdrawal#
complete takes the encrypted profile matching the stored full hash and deposits expectedAmount from funds already at the receiver. This confirms available funds without authenticating their origin. The receiver allows multiple completions, so a donation cannot consume it permanently before the intended withdrawal arrives.
execute calls the fixed source and measures the new asset balance. It accepts no source allowance, escrowed call value, arbitrary target or replacement destination. For ordinary source kinds, the new receipt must equal expectedAmount. PrivacyPoolsV2 can return more than its reviewed minimum; the receiver credits the whole new receipt, up to uint128.
If the receipt check or Fuyu deposit fails, the transaction rolls back the source withdrawal and its nullifier. Completed includes the completion sequence, termsHash, amount and sourceCallVerified. Use that flag to tell an atomic source call from completion of a balance already held.
function available() public view returns (uint256);
function complete(bytes calldata encryptedProfile) external;
function execute(bytes calldata sourceCalldata,
bytes calldata encryptedProfile) external;
function completeRemainder(bytes calldata encryptedProfile) external;
function refund() external;
function recover(address recoveryAsset, uint256 amount) external;Credit a remainder or resume a flow#
After at least one reviewed amount has been credited, completeRemainder deposits the full remaining balance to the same private owner. It must be nonzero and no larger than expectedAmount. The caller cannot change the amount, asset or destination.
The first credit publishes the stored profile in the same transaction. Later credits use the receiver's existing Pool profile pointer and funding nonce. Save the account's recovery material and test reopening it; the contract checks a ciphertext hash, not whether the holder can decrypt it.
If a withdrawal is interrupted, check the source receipt, receiver balance, completionCount and Fuyu deposit events. Find the outcome at the original receiver before funding another. Confirm both that the source withdrawal succeeded and that the private account recovered its Fuyu note.
Recover after the deadline#
At refundAfter, anyone can call refund. It marks the receiver cancelled and sends its available settlement balance to refundRecipient. Already credited Pool notes stay private and cannot be recovered this way. Tokens arriving after cancellation can still be recovered.
recover can return a wrong asset at any time or the settlement asset after cancellation. Every payout uses the fixed destination. Save the receiver address, terms, profile and source operation reference before starting a withdrawal.
| Error | Check before retrying |
|---|---|
| SourceChanged | The source runtime on the selected chain |
| InexactSourceReceipt | The new receipt amount against expectedAmount or its minimum |
| InvalidProfile | The profile bytes and full hash |
| InexactDeposit / InsufficientFunds | The receiver balance and Pool token changes |
| Expired / RecoveryNotAllowed | Cancellation state and refund deadline |
| RemainderNotAllowed | Whether a prior completion exists and the full remainder fits the limit |
Receiver factory#
FuyuMigrationReceiverFactory has initCodeHash, predict and create for Terms plus userSalt. The address includes the factory and constructor data. Before funding, compute the terms hash independently and compare the factory runtime and deployed receiver fields.
Enable migration separately for each source. The receiver handles funding and credit, but a working route also needs a source withdrawal method and proof, a supported target asset and an account the holder can recover. Verify those pieces before advertising the source as integrated.