Skip to main content

Assets

Native programmable assets are a core concept in MOI. Asset rules (minting, burning, transfers, approvals) are enforced at the protocol level through asset logic written in Coco.

Asset flow: User → Logic → Asset Logic → Asset Engine

Asset Logic

Declare an asset logic with the asset keyword:

coco asset MyToken

Asset logic has privileged access to the asset engine via the asset global object.

Asset Engine Methods

Lifecycle

MethodDescription
asset.Define(symbol, decimals, manager, creator, max_supply, enable_events)Define asset properties (call in deploy)

Transfers & Ownership

MethodDescription
asset.Transfer(token_id, beneficiary, amount)Transfer from Sender to beneficiary
asset.TransferFrom(token_id, benefactor, beneficiary, amount)Transfer from benefactor (requires approval)
asset.Mint(token_id, beneficiary, amount)Mint new tokens
asset.MintWithMetadata(token_id, beneficiary, amount, static_metadata)Mint with metadata
asset.Burn(token_id, amount)Burn tokens from Sender
asset.Lockup(token_id, beneficiary, amount)Lock tokens
asset.Release(token_id, benefactor, beneficiary, amount)Release locked tokens
asset.Approve(token_id, beneficiary, amount, expires_at)Approve spending
asset.Revoke(token_id, beneficiary)Revoke approval

Queries

MethodReturnsDescription
asset.BalanceOf(token_id, address)U256Balance of address
asset.Symbol()StringAsset symbol
asset.Creator()IdentifierCreator address
asset.Manager()IdentifierManager address
asset.Decimals()U64Decimal places
asset.MaxSupply()U256Maximum supply
asset.CirculatingSupply()U256Current supply
asset.EnableEvents()BoolWhether events enabled

Metadata

MethodDescription
asset.SetStaticMetadata(key, value)Set asset-level static metadata
asset.SetDynamicMetadata(key, value)Set asset-level dynamic metadata
asset.GetStaticMetadata(key)Read static metadata → Bytes
asset.GetDynamicMetadata(key)Read dynamic metadata → Bytes
asset.SetStaticTokenMetadata(token_id, key, value)Per-token static metadata
asset.SetDynamicTokenMetadata(token_id, key, value)Per-token dynamic metadata
asset.GetStaticTokenMetadata(token_id, key)Read per-token static → Bytes
asset.GetDynamicTokenMetadata(token_id, key)Read per-token dynamic → Bytes

Example

my_token.coco
coco asset MyToken

event TransferEvent:
topic from Identifier
topic to Identifier
field amount U256

endpoint Transfer(to Identifier, amount U256):
if asset.EnableEvents():
emit TransferEvent{from: Sender, to: to, amount: amount}

asset.Transfer(token_id: 0, beneficiary: to, amount: amount)

endpoint Mint(to Identifier, amount U256):
if Sender != asset.Manager():
throw "Unauthorized"

asset.Mint(token_id: 0, beneficiary: to, amount: amount)

Calling Asset Logic

Regular logic cannot access the asset engine directly. It must call asset logic through an interface.

payment.coco
coco Payment

interface Token:
asset:
Transfer(to Identifier, amount U256)

endpoint Pay(token_id Identifier, recipient Identifier, amount U256):
memory token = Token(token_id)
token.Transfer(to: recipient, amount: amount)

Creating Assets

Assets are created via MOI interactions, not directly in Coco. In Cocolab:

compile MyToken from manifest(mytoken.yaml)
create MyToken(symbol: "MTK", decimals: 18, manager: user1, max_supply: 1000000)
Key Points
  • Only asset logic can access the asset global object
  • Regular logic must use interfaces to interact with assets
  • This separation ensures security and programmability