Two wallets total 90 units under one identity; an incoming 20 units exceeds a 100-unit limit.
Synthetic holding-limit example. The limit belongs to the identity, which may have several wallets.

A transfer screen can show enough tokens, a valid recipient address and a green identity badge, yet the transaction can still fail. Those checks describe different things. The address may belong to a verified investor while the proposed transfer exceeds a holding limit, uses locked tokens or relies on a claim that has just expired.

For an RWA application, a useful eligibility check evaluates the sender, recipient, amount and current offering rules together. It records the chain state used for that decision and gives the user a specific reason when the transfer cannot proceed. The contract still evaluates the transaction when it executes.

This walkthrough follows the local Aurum RWA implementation. It is a software design discussion using a prototype with simulated identities and assets. Passing these checks does not establish the legal eligibility of an asset offering.

Start with the proposed transfer

Consider a synthetic example. An investor has two wallets attached to one identity. The recipient wallet holds 40 units, but the identity already holds another 50 units elsewhere. An incoming transfer of 20 units would take the identity to 110. If the offering limit is 100 units per identity, looking only at the recipient wallet gives the wrong answer.

Aurum’s compliance module maintains both walletBalance and identityBalance. Its rule configuration includes a transfer unlock time, country rules, a maximum identity balance and an investor count limit. The API uses the identity totals when evaluating transfer limits. That distinction matters when a product lets one investor register more than one wallet.

Identity verification and transfer rules also have separate roles in ERC-3643. The identity registry evaluates the recipient’s required claims, while the compliance layer evaluates restrictions on the proposed transfer. A successful identity check should therefore remain one input to the decision.

Read one coherent chain state

Several independent reads can produce a misleading answer if they refer to different blocks. A balance from one block and a policy from another may never have been valid together.

Aurum’s transfer service reads a block, then uses its number for the contract reads and transfer simulation. The result includes the checked block number, block hash and policy version. Before returning, it checks that the block hash has not changed. It also checks the event indexer’s health and lag, configuration revision and reconciliation status.

These fields make a failure report useful. “Transfer check failed at block N under policy version P” gives an engineer something to reproduce. “The button was green a minute ago” does not.

Transfer precheck reads a single block, evaluates identity and transfer rules, then leaves final acceptance to execution.

The service currently gives the precheck result a 30-second expiry. That is an application freshness hint. It neither reserves the recipient’s capacity nor guarantees that a later transaction will succeed. Another transfer can arrive, a claim can expire or an operator can pause the token before execution.

Turn rejection codes into useful next actions

The prototype collects reason codes instead of returning only a Boolean. Some problems belong to the investor, some to an operator and some to the infrastructure team.

Example reason What it describes Useful next action
CLAIM_EXPIRED A required claim is no longer valid Route to the identity review flow
HOLDING_PERIOD_ACTIVE The offering’s transfer unlock time has not arrived Display the unlock condition
AMOUNT_LOCKED The requested amount cannot be transferred from the current balance Show available and locked amounts separately
INDEXER_STALE Indexed state is too far behind or unhealthy Ask the operator to inspect synchronization
RECONCILIATION_REQUIRED The system cannot rely on the current reconciled view Hold the operation for investigation

Avoid translating every code into “try again.” Repeating an expired-claim request will not repair the claim. The interface should explain the blocker without exposing identity documents or sensitive review notes.

Test the gap between checking and execution

A happy-path transfer is only the first case. Keep the input unchanged and alter one relevant fact between precheck and submission. Revoke a claim, increase the recipient’s holdings through another wallet, pause the token or consume the sender’s available balance.

The expected result is a fresh decision or a rejected transaction, with a clear explanation of the changed condition. Do not retain the original green status after a failed transaction. Keep the precheck evidence alongside the transaction result so support can distinguish a stale prediction from an incorrectly encoded request.

Aurum also tracks the submitted transaction against the expected sender, token, recipient and amount. Its tracking path distinguishes missing observations, replacements, mined receipts, reverts and confirmations. A transaction hash by itself is insufficient evidence that the intended transfer completed.

A review matrix for your own portal

Download the transfer eligibility review kit. It contains a reusable matrix covering identity expiry, multiple wallets, locked balances, state changes, stale indexing and transaction replacements. The expected outcomes are review targets, not claims that your deployment has passed them.

For a buyer evaluating an RWA portal, ask for a demonstration with a changed condition between the green check and execution. Ask which fields the support team receives when it fails. Those two questions reveal more than a screenshot of a successful transfer.

Aurum RWA connects investor onboarding, holdings and transfer checks in a local prototype. If you are scoping an implementation, bring one proposed transfer, the rules it must obey and the failure cases your operations team needs to handle. Those inputs are enough to start a concrete technical discussion.