Transfers & policies
Every issue and every transfer is checked against the effective policy of the kind: the kind’s override if it has one, the asset’s policy otherwise. The policy is evaluated on the post-state — the state as it would be after the transaction — so a holder cap counts the holders after the move.
| Rule | Allows when |
|---|---|
OPEN | always |
ALL[r…] | every rule allows |
ANY[r…] | at least one rule allows (left to right) |
CREDENTIAL(type, attesters) | the recipient holds a valid attestation of type from one of attesters |
ALLOWLIST(addresses) | the recipient is in the list |
MAX_HOLDERS(n) | the number of holders of the kind after the move is at most n |
Only the recipient is checked; sending is never restricted by policy.
A denial names the rule that refused (policy denied at <path>: <reason>,
codespace policy, code 3). The explorer’s transaction page shows it under
Status.
Policies in JSON
{ "all": { "rules": [
{ "credential": { "type": "investor.verified", "attesters": ["aeva1…"] } },
{ "max_holders": { "n": 500 } }
] } }Set at creation (--policy) or later with set-policy (issuer only; --kind-id
for one kind’s override, --clear-kind to remove it).
CLI
aevad tx rights transfer <to> <asset-id> 0:10 --from holder
aevad tx asset set-policy <asset-id> OPEN --from issuer
aevad tx asset set-policy <asset-id> '{"max_holders":{"n":2}}' --kind-id 0 --from issuer
aevad query asset asset <asset-id> # the asset policy and each kind's overrideOn the explorer
/assets/<id> → Kinds & Policy: the effective policy of each kind, in
words, with its source (asset or kind override). A refused transfer’s
transaction page shows the rule path.