Skip to main content
Version: 1.1.0

Ownership and authority

CenterChain distinguishes three authorities that are often all called "owner". Keeping them apart is the difference between a correct integration and one that loses funds.

LayerHeld byGoverns
Denom adminThe account that created a token factory denomMint, burn its own balance, metadata, restriction, delegates, blacklist, poolability
Class issuerThe account named in an NFT class idMint, burn its own tokens, metadata, and the class market configuration
Pool ownerThe account that created a liquidity poolPause, fees, ownership transfer, emission schedules, coin recovery

Above them all is the module authority, the gov module account. It is the only signer that can change a module parameter, move a class issuer, register an IBC denom, emergency-pause or close a pool, or recover a pool's IBC-denom coins.

How an authority is bound to its scope​

A denom admin is stored in that denom's DenomAuthorityMetadata, so it travels with the denom and not with the account's other denoms.

A class issuer is bound structurally: the class id's first segment must be the issuer's own bech32 address, and MsgCreateClass only accepts a class id whose prefix is the sender. An account cannot create a class inside another account's namespace.

A pool owner is a field on the pool, and it can be transferred — with a cooldown, through a two-step request and accept.

In all three cases the check is a direct address comparison inside the message handler. There is no authz grant, and none of these modules calls the authz keeper.

Changing an authority​

TransitionHowDelay
Denom adminMsgChangeAdmin, signed by the current adminNone. It is immediate and irreversible by the old admin.
Class issuerMsgChangeClassIssuer, signed by the module authorityNone.
Pool ownerMsgRequestOwnershipTransfer then MsgAcceptOwnershipTransfer by the nomineeownership_cooldown_blocks, default 720. Either side can cancel.
Pool owner, emergencyMsgRequestEmergencyOwnershipTransfer then MsgActivateEmergencyOwnershipTransfer by the authorityemergency_ownership_cooldown_blocks, default 720. The owner has no cancel path.

The normal and emergency pool-ownership paths are deliberately separate: the first is a cooperative handover, the second is a recovery when the owner is unavailable. Governance can start the second but not the first, and the owner can cancel the first but not the second.

What an authority cannot do​

  • No authority bypasses a blacklist. A denom admin cannot send to a blacklisted address or from one, and neither can gov.
  • No authority can burn or move another holder's asset. Since v1.1 the denom admin, the class issuer, and gov alike are rejected when they try to burn or transfer an asset they do not hold. See Holder asset protection.
  • No authority can list an NFT on a market the class has not enabled. The class issuer sets secondary_enabled; nothing above it bypasses that.
  • No authority can change a class's metadata immutability flag. It is fixed at creation.
  • No authority can resurrect a consumed authorization. Single use is not revocable by any role.
  • Authority does not confer legitimacy. A denom can have an admin and still be one nobody wants to hold. The chain stores the fact; whether a token is trustworthy is not a question it answers.

Income authority​

The income module accepts a message from four sources:

  1. The module authority.
  2. An address in the module's configured income_admins list.
  3. The token factory admin of the eligibility denom.
  4. The class issuer, when the denom is an NFT class id.

On the default build the income_admins list is empty, so in practice only gov and the relevant denom admin or class issuer can register, distribute, or push.

Why the word owner is avoided​

A single "owner" field would have to mean minting, burning, transferring, pricing, and listing at once. Those are different powers with different blast radii and different failure modes. Separating them means a compromise of one is not a compromise of all.