Skip to main content
Version: 1.2.0

Transfers and compliance

Every send on CenterChain — bank, NFT, and swap settlement alike — passes through one function. The first rule that matches decides.

The blacklist​

A blacklist is a per-denom list of addresses. Being blocked on one token has no effect on any other, and a denom with no authority metadata is never subject to it.

  • Only the denom admin can add or remove an entry, and an account cannot blacklist itself.
  • Adding is idempotent; removing decrements a global counter.
  • The cap is 100,000 blacklisted addresses across the whole chain.
  • The check is absolute. It applies under an open policy, to admins, to delegates, and to the module authority.

The restricted-denom rule​

is_restricted is set by the denom admin. When it is set, a denom can only be sent to an address that already holds a balance of it, unless the sender is the admin, one of the delegates, or the send is an internal leg of a swap.

This is the on-chain circulation control: an issuer can close a token to new addresses while leaving existing holders able to trade among themselves.

:::note This is not a KYC list The rule tests a balance, not an identity. The chain can prove that a recipient already holds the token; it cannot prove who that recipient is. Treating this as an identity check would be a mistake in both directions — it blocks nothing extra, and it claims an assurance the chain cannot make. :::

The ante checks​

Three decorators wrap the ante handler, all from tokenfactory:

DecoratorWhenWhat it does
FeePayerDecoratorEvery transactionFor a MsgExecute*, redirects the network fee to the authorization holder in ucen, enforces max_fee, rejects a second attempt, and rejects nested or multi-message executions.
NFTSendCheckDecoratorEvery transactionWalks nft.MsgSend, including ones nested inside an authz.MsgExec up to eight levels deep, and rejects locked, blacklisted, or unknown-counterparty transfers.
ZeroBalanceCheckDecoratorCheckTx and simulate onlyRe-applies CanSendTokens to every MsgSend after the rest of the ante chain, so a simulation shows the true result.

The fee decorator is outermost, then the NFT check, then the zero-balance check. The zero-balance decorator does not run in DeliverTx. It exists so that a dry run and a real transaction agree, not to change consensus behaviour.

No reservations​

A two-phase authorization no longer reserves max_from or locks an NFT. Since v1.2, TX1 stores the terms and the expiry only. A holder can spend the same balance or transfer the same token while the authorization is open; settlement fails closed if the asset is no longer there.

The only exception is a read-only check at TX1: an NFT already locked by nftmarket cannot be promised to a tokenfactory executor.

Ordering with income​

Income prepends its send restriction and tokenfactory appends its own, so the order on every bank send is:

1. income settle both sides against their pre-transfer balances
2. tokenfactory blacklist, then restriction

Income must run first: a holder's entitlement is a function of the balance they had before the transfer. Checking compliance first would mean settling a balance that no longer exists.

Blocklist versus freeze​

The chain has no separate account-level freeze. What exists is:

MechanismScopeEffect
Per-denom blacklistOne denom, one addressNo send in that denom, by anyone
is_restrictedThe whole denomNo transfer to a new address, by anyone except the admin and delegates
Income blocklist checkThe claimantA claim is rejected outright for a blocklisted holder

A transfer barrier is not seizure. An admin can change the admin of a restricted denom, mint new supply, or block an address — but since v1.1 it cannot burn or move another holder's balance or token. Restriction controls circulation; holder consent controls disposal. See Holder asset protection.