Skip to main content
AccountCore holds custody and identifies every root and child by a nonzero uint40 account ID. Children are ledger entries, with no deployed contract, wallet address, or signer registry. This is a fresh-deployment model: its storage layout and API are incompatible with the former address-keyed model. Physical custody flows use an external global USD36 limiter with per-token price sources. Ordinary withdrawals consume 24-hour deposit credit, then a capped drip allowance. Approved root-owner-signed payouts bypass those pools but still require valid pricing and active releases. See WithdrawalLimiter.

Identity and custody

rootAccountIdOf(owner) resolves an owner’s one root ID, or zero before registration. Each ID stores its owner, root ID and sequence. A root points to itself and has sequence zero; children share the root owner and have consecutive sequences starting at one. IDs and sequences are never reused. There can be at most 65,535 children per root. getSubaccounts(rootId) returns their IDs in creation order. Free balances and active-order reserves are keyed by account ID and token. Native MON uses address(0). Trading and passive liquidity operate on each child’s own balance and reserves; sharing signers does not pool collateral. The existing root-wide builder and fee policies still resolve through the target account’s root ID. Positive builder fees credit the builder’s root free balance, registering that root if needed, and emit SpotReserveUpdated before BuilderFeeAccrued. Builders withdraw through the root-only withdrawal API; there is no separate builder-fee claim ledger. Zero-fee attribution does not register a builder root.

External funding

There are exactly two deposit entrypoints:
  • deposit(address rootOwner, address token, uint256 amount) registers the owner’s root if necessary.
  • deposit(uint40 rootAccountId, address token, uint256 amount) requires an existing root ID.
Anyone may fund a root. The payer receives no authority over it. Both overloads support ERC20 and native assets. A child ID is rejected, including when its owner is the caller. SpotPeriphery exposes the same two overloads. withdraw(uint40 rootAccountId, address token, uint256 amount, address recipient) only accepts roots and pays the explicit recipient. Reject zero and AccountCore itself. Recipients need no registration or permissions; registered recipients receive an external payout, not internal balance credit. This replaces the three-argument signature; callers must pass their own address explicitly to retain caller payouts. The caller must be the root owner or a live root WITHDRAW/ADMIN signer. No child can withdraw, even through its owner. transferBetweenAccounts(fromId, toId, token, amount) moves free balance within one family. It requires the root owner or a live root INTERNAL_TRANSFER, WITHDRAW or ADMIN signer. Root-to-child, child-to-root and sibling transfers use the same check. Thus funding a child and withdrawing its proceeds go through the root. Reserved assets must first be released. These restrictions apply to external funding; settlement and passive-liquidity releases can credit children normally.

One signer registry per root

All grants live under the root ID. There are no child-specific signers. The hierarchy is evaluated when checking authority: ADMIN includes TRADE, WITHDRAW and INTERNAL_TRANSFER; WITHDRAW includes INTERNAL_TRANSFER. Stored grants and authorization events retain the exact granted bits. TRADE and INTERNAL_TRANSFER do not imply higher permissions. Deposits remain permissionless funding. Expiry and revocation apply to the entire family immediately. Adding a child does not change existing grants. isAuthorizedAccountSignerById is the canonical trading authorization query. For delegated signers, child-ID queries only evaluate TRADE; check non-trading roles against the root ID. Internal family transfers authorize against that root rather than testing a child for INTERNAL_TRANSFER. A zero account ID in orderbook entrypoints retains the caller’s own root convenience path; it never selects a root based on delegated authority. Signer administration continues to identify the root by its owner address, including the EIP-712 grant/revoke flows. Only the owner can bootstrap an unregistered root. Each successful grant or revocation increments the root’s authorization epoch. accountAuthorizationEpoch(accountId) returns that epoch for either root or child and rejects unknown IDs. accountSignerAuthorizationNonces(rootOwner) provides the owner-address lookup, returning zero before registration. Signed trading actions bind both the actual target ID and this root epoch. Reauthorizing a revoked signer does not revive earlier intents or stored triggers. Creating a child does not invalidate trading intents.

Child creation

createSubaccount(rootOwner) accepts the owner or a live root ADMIN/TRADE signer. Only the owner can bootstrap a missing root. The signed entrypoint accepts the same authorizers, checked at execution time:
Its EIP-712 domain is KuruAccountCore, version 1, the current chain ID and AccountCore proxy address. The type is:
authNonce must match the root epoch. subaccountSeq must equal the next sequence, so both direct and signed creation consume it. Two requests for the same sequence compete: after one succeeds, the other must be signed again. This avoids another nonce mapping. Signatures support EOAs and ERC-1271 contract authorizers through Solady. The old child-address consent flow and its typed message are removed. Names and other display metadata remain offchain.

Contract boundaries and integration

IAccountCore owns identity, root authorization, custody and fee policy. ISpotBalanceAccount exposes verified orderbook reserve and settlement operations. SpotPeriphery is unprivileged. KuruTradingWallet validates signed intents against the target ID and root epoch before forwarding through normal orderbook checks. Token configuration, fee rounding, order packing and matching economics are unchanged. Integrators must regenerate ABIs, pass IDs for balances, transfers, withdrawals and trades, and use owner addresses only for root lookup/bootstrap and root administration. Read AccountRegistered(accountId, rootAccountId, rootOwner, subaccountSeq) to index every account and SubaccountCreated(rootAccountId, subaccountId, authorizer) for creation provenance. Child IDs are not deposit addresses. SDK/frontend/indexer changes must ship with the new deployment. Source: Account architecture at main.

Callable reference

Signatures and parameter types below are generated from the reviewed SDK 0.2.0 ABI (contract revision cdac5ae1). These are Solidity return values: SDK write methods return a transaction hash and require receipt reconciliation. Viem decodes small Solidity integers as numbers; the SDK normalizes account IDs to bigint on its account-client methods.
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: uint40.
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: address.
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: uint40.
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: uint16.
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: uint40[].
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: uint256.
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: uint256.
Mutability: payable. Permissionless funding of a root only. The owner-address overload registers a root if needed. ERC-20 assets require allowance; native MON requires exact transaction value. Pricing and token-enablement checks apply.Returns: No Solidity return value.
Mutability: payable. Permissionless funding of a root only. The owner-address overload registers a root if needed. ERC-20 assets require allowance; native MON requires exact transaction value. Pricing and token-enablement checks apply.Returns: No Solidity return value.
Mutability: nonpayable. Root owner or live root WITHDRAW/ADMIN authority. Debits root free balance and pays the explicit external recipient. Capacity, prices, release controls, and transfer checks apply.Returns: No Solidity return value.
Mutability: nonpayable. Root owner or live root INTERNAL_TRANSFER/WITHDRAW/ADMIN authority. Both IDs must share a root. Moves free balance only; no external token transfer.Returns: No Solidity return value.
Mutability: nonpayable. Root owner or live root TRADE/ADMIN authority; only the owner can bootstrap a missing root. Returns a new numeric child ID and does not advance the root epoch.Returns: uint40 subaccountId.
Mutability: nonpayable. The authorizer must still be the owner or a live root TRADE/ADMIN signer. Check the next child sequence, root epoch, deadline, and AccountCore signature domain.Returns: uint40 subaccountId.
Mutability: nonpayable. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: No Solidity return value.
Mutability: nonpayable. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: No Solidity return value.
Mutability: nonpayable. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: No Solidity return value.
Mutability: nonpayable. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: No Solidity return value.
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: uint256.
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: uint256.
Mutability: view. Check TRADE on the target ID. Delegated non-trading checks must use the root ID; a child query masks out those roles.Returns: bool.
Mutability: nonpayable. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: No Solidity return value.
Mutability: nonpayable. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: No Solidity return value.
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: (uint32 maxFeePps, uint64 expiry, bool active).
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: uint32.
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: uint32.
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: (uint32 makerFeePps, uint32 takerFeePps, bool active) tier.
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: (address builder, uint32 makerFeePps, uint32 takerFeePps, uint64 expiry) referral, bool active.
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: (uint32 makerFeePps, uint32 takerFeePps, uint64 expiry, bool active).
Mutability: nonpayable. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: uint40 rootAccountId.
Mutability: nonpayable. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: No Solidity return value.
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.Returns: uint256.
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.No parameters.Returns: uint64.
Mutability: view. Use the account, permission, and execution rules described above and in the linked SDK guide.No parameters.Returns: address.
Mutability: nonpayable. Only the configured withdrawal authority submits this call. It requires a root-owner signature; bypasses ordinary capacity but preserves prices, freezes, balance and transfer checks.Returns: No Solidity return value.
Mutability: nonpayable. Invalidates older approved-payout signatures. This nonce is distinct from the signer authorization epoch.Returns: No Solidity return value.