Accounts and Receiving Directory
Store encrypted account records and publish receiving descriptors with wallet approval.
Account records and receiving descriptors#
FuyuAccountRegistry catalogs optional, independently recoverable accounts under recovery wallet A. FuyuReceiveDirectory publishes the public owner's opt-in private receiving descriptor. Both store public records or encrypted data; neither stores plaintext private balances, decrypts profiles or replaces note ownership proofs.
During construction, the Pool uses FuyuAccountRegistryFactory to fix its accountRegistry. Each account row includes Pool/domain, recovery wallet, nonzero accountId, revision, fixed spending controller and encrypted profile/recovery envelope. A directory entry instead links a public owner to the current controller, receiving owner root and KEM key hash.
Read account records#
Use accountCount and accountIdAt to discover wallet A's account IDs, or accountIds to read pages of up to 100 IDs. account returns revision, update block, controller and both encrypted records. profilePointer returns the revision and profile hash needed for guarded funding.
Your client creates the recovery envelope. The contract checks its length and approval but cannot check whether it decrypts. Before publishing, reopen the profile with the intended recovery method and verify the account you derive. Registration confirms the write was authorized; you must test recovery separately.
| Field or limit | Meaning |
|---|---|
| revision | A uint64 version that increases and must match before an update |
| updateBlock | The block where the record was published |
| controller | Wallet B chosen at registration; zero uses the ownership proof alone |
| profile | Encrypted profile, between 48 and 2,048 bytes |
| recoveryEnvelope | Encrypted wallet recovery material, between 48 and 32,768 bytes |
| accountId | A nonzero independent ID under wallet A |
| MAX_PAGE_SIZE | Read at most 100 IDs per page |
Register or update an account#
Recovery wallet A calls register for an unused accountId, creating revision one. If controller B is nonzero, B must sign the FuyuAccountConfig digest. update takes the expected current revision and keeps the controller chosen at registration. B approves the next revision and hashes of both replacement ciphertexts.
The EIP-712 configuration includes Pool, Pool domain, recovery wallet, accountId, controller, revision, profile hash, recovery-envelope hash and deadline. The deadline is inclusive; uint256 maximum means no expiry. Wallet checks are static and run before storage writes. A stale revision or rejected approval leaves the row unchanged.
Use empty signature bytes when controller is zero. Otherwise, use the shared EOA, Safe or explicitly selected ERC-1271 signature format. Registry approval and Pool-spend approval sign different types, domains and payloads, so get a separate signature for each.
function register(
bytes32 _accountId, address _controller,
bytes calldata _profile, bytes calldata _recoveryEnvelope,
uint256 _deadline, bytes calldata _controllerSignature
) external;
function update(
bytes32 _accountId, uint64 _expectedRevision,
bytes calldata _profile, bytes calldata _recoveryEnvelope,
uint256 _deadline, bytes calldata _controllerSignature
) external;Publish a receiving descriptor#
FuyuReceiveDirectory fixes Pool and Pool domain. get(owner) returns version, active status, controller, ownerRoot and kemKeyHash. The descriptor hash covers the receiving terms; publishDigest also includes owner, active/revoked state, nonce and deadline.
Anyone can relay publish with the owner's signature. EOAs use canonical 65-byte ECDSA, and contract owners use ERC-1271 directly. The directory does not accept the Pool's FUYA envelope or compact-signature format. A publication increments version and requires nonce to equal the current version.
An active descriptor needs a nonzero scalar-field owner root and a 1,216-byte KEM public key. Validate the key encoding in your client before paying. To revoke, send zero controller, zero owner root and empty key bytes. That publishes an inactive entry; old notes and their controller requirements remain unchanged.
function get(address _owner) external view returns (
uint256 version, bool active, address controller,
uint256 ownerRoot, bytes32 kemKeyHash
);
function publish(
address _owner, address _controller, uint256 _ownerRoot,
bytes calldata _kemPublicKey, bool _active,
uint256 _nonce, uint256 _deadline, bytes calldata _signature
) external;Use the current record for funding#
depositWithAccount uses msg.sender and accountId to choose the account. Supply its current nonzero registry revision, full profile hash and guarded account deposit nonce. The Pool checks them before and after collecting tokens. A stale tab, concurrent update or callback therefore cannot redirect credit to another account record.
Wallet-scoped profile funding instead uses latestEncryptedProfilePointer: a uint64 publication block and the leading 24 bytes of the ciphertext hash. Keep this namespace separate from account-bound funding. A Portal publishes and deposits under its own caller address, not the address that sent it ERC-20 tokens.
For a directory payment, read an active descriptor at a known finalized block and validate its key before building delivery. Include its version/hash in an owner-linked Portal credit review. If the owner rotates the descriptor, refresh it before preparing the next payment.
Venue registry#
ReviewedVenueRegistry records reviewed ERC-4626 manifests onchain. It fixes governor and Pool and stores adapter, underlying/share identities, code hashes and guard digest under the manifest digest. Before governorActivate succeeds, the Pool must admit both supply and redemption routes with the reviewed adapter hash.
governorExitOnly can mark a venue ExitOnly only after both action routes are revoked. Holders can then use an ordinary public share-token exit; the external redemption adapter is disabled. effectiveState checks current code, identities and routes and returns Unknown if they disagree with the stored state. Use that check instead of trusting a stored Active row.
Events and errors#
AccountUpdated emits recovery wallet, accountId, revision, controller and ciphertexts. The directory's Published event emits descriptor version and receiving public key. Anyone can read these records to discover and recover published data, while the secret contents remain encrypted.
| Error | What to do |
|---|---|
| InvalidRevision | Reload the row and review its next revision |
| InvalidConfiguration | Check IDs, ciphertext lengths, deadline and Pool/registry connection |
| InvalidAuthorization | Request approval of the configuration from the fixed controller |
| InvalidNonce / NonceExhausted | Reload the directory version; an exhausted version cannot advance |
| InvalidDescriptor | Check active/revocation fields, scalar root and key length |
| Expired / InvalidSignature | Check signed terms and the owner's current policy |