For the complete documentation index, see llms.txt. This page is also available as Markdown.

Token

Token is the ERC-20 of an asset on the reference chain and the entry point of its cross-chain messages. It enforces the pause, the freezes, the eligibility of the recipient and the compliance rules on every transfer, and keeps the record of what is active on each satellite. The concepts are in The permissioned token and The balance model.

At a glance

Source

contracts/token/Token.sol, on the standard base contracts/ERC-3643/base/ERC3643Token.sol and on contracts/interop/TREXMessaging.sol

Interfaces

IToken, which extends IERC3643. ERC-20, ERC-20 metadata, ERC-2612 permit, ITREXMessaging, ERC-7786 recipient

Deployed as

A beacon proxy, at a CREATE3 address derived from the salt of the suite. version() returns 5.0.0

Access

The suite's TREXAccessManager. Roles are those of the asset's domain

Initial state

Paused. An AGENT_PAUSER calls unpause to open transfers

Information and wiring

Function
Access
Reverts with

init(tokenName, tokenSymbol, tokenDecimals, identityRegistryAddress, complianceAddress, trustedGatewayRegistryAddress, onchainIdAddress, accessManagerAddress)

Initializer, called once by the factory

EmptyString for an empty name or symbol, DecimalsOutOfRange above 18, ZeroAddress

setName(_name), setSymbol(_symbol)

TOKEN_MANAGER

EmptyString. A new name changes the ERC-712 domain of permit: signatures made under the previous name stop being valid

setOnchainID(_onchainID)

IDENTITY_MANAGER

setIdentityRegistry(_identityRegistry)

IDENTITY_MANAGER

InvalidIdentityRegistry. TokenCirculating when a registry is already set and the supply is not zero

setCompliance(_compliance)

IDENTITY_MANAGER

InvalidCompliance, ComplianceAlreadyBoundToToken when the compliance serves another token. TokenCirculating when a compliance is already set and the supply is not zero

name(), symbol(), decimals(), version(), onchainID(), identityRegistry(), compliance(), paused()

Anyone, read

The first three setters emit UpdatedTokenInformation. The last two emit IdentityRegistryAdded and ComplianceAdded.

Holder functions

Function
Access
Reverts with

transfer(to, value)

The holder of the sending address

In this order: EnforcedPause, FrozenWallet for the sender then the recipient, ERC20InsufficientBalance above the free balance, UnverifiedIdentity for the recipient, ComplianceNotFollowed, ZeroValue

transferFrom(from, to, value)

A spender with an allowance

SpenderNotAllowed when the spender policy refuses the caller, then ERC20InsufficientAllowance, then the checks of transfer

approve(spender, value), permit(owner, spender, value, deadline, v, r, s)

The holder, or anyone carrying its signature

The standard ERC-20 and ERC-2612 errors. The spender policy is not asked

batchTransfer(_toList, _amounts)

The holder of the sending address

ArrayLengthMismatch. Each entry is a transfer

identityTransfer(from, to, amount)

The ONCHAINID that from resolves to

NotLinkedIdentity, then the checks of transfer. No allowance is read. Emits IdentityTransfer after Transfer

The eligibility of the sender is not checked. See 10 Transfer between investors and 24 Transfer through the identity.

Agent functions

Function
Access
Checks and reverts

mint(_to, _amount), batchMint(_toList, _amounts)

AGENT_MINTER

UnverifiedIdentity for the recipient, ComplianceNotFollowed, ZeroValue, ArrayLengthMismatch. The pause and a freeze on the recipient do not stop a mint

burn(_userAddress, _amount), batchBurn(_userAddresses, _amounts)

AGENT_BURNER

ERC20InsufficientBalance, ZeroValue, ArrayLengthMismatch. No eligibility check and no rule. Frozen tokens are released when the burn needs them (TokensUnfrozen). The pause does not stop a burn

setAddressFrozen(_userAddress, _freeze), batchSetAddressFrozen(_userAddresses, _freeze)

AGENT_ADDRESS_FREEZER

ArrayLengthMismatch. Emits AddressFrozen

freezePartialTokens(_userAddress, _amount), batchFreezePartialTokens(_userAddresses, _amounts)

AGENT_PARTIAL_FREEZER

ERC20InsufficientBalance when the amount exceeds what is not already frozen. Emits TokensFrozen

unfreezePartialTokens(_userAddress, _amount), batchUnfreezePartialTokens(_userAddresses, _amounts)

AGENT_PARTIAL_FREEZER

AmountAboveFrozenTokens. Emits TokensUnfrozen

forcedTransfer(_from, _to, _amount), batchForcedTransfer(_fromList, _toList, _amounts)

AGENT_FORCED_TRANSFER

EnforcedPause, UnverifiedIdentity for the recipient, ERC20InsufficientBalance, ZeroValue. Freezes and rules are not checked. Frozen tokens are released when needed. Emits ForcedTransfer after Transfer

recoveryAddress(_lostWallet, _newWallet, _investorOnchainID)

AGENT_RECOVERY_ADDRESS

EnforcedPause, SameWalletRecovery, NoTokenToRecover, RecoveryNotPossible when neither address is known to the registry. Moves the whole balance, carries the freezes over, and emits RecoverySuccess

pause(), unpause()

AGENT_PAUSER

EnforcedPause, ExpectedPause. Emit Paused, Unpaused

Guides: 08, 09, 13, 14, 15, 16.

Balance views

View
Returns

balanceOf(address)

The tokens an address holds on the reference chain, frozen tokens included

getFrozenTokens(_userAddress)

The amount frozen at the address

freeBalanceOf(wallet)

balanceOf less the frozen amount: what the address can send

isFrozen(_userAddress)

Whether the address is frozen as a whole

allowance(owner, spender), nonces(owner), DOMAIN_SEPARATOR()

The ERC-20 and ERC-2612 reads

bridgedBalanceOf(wallet)

The position recorded for a satellite wallet (bytes)

reservedOf(wallet)

The part of that position promised to open validations

availableOf(wallet)

bridgedBalanceOf less reservedOf: what a new validation can draw on

totalBridged()

The sum of every bridged position, amounts in transit included

inTransitOf(validationId), totalInTransit()

The amount burned on one satellite and awaiting its mint on another, for one validation and in total

totalSupply()

The whole issuance: the supply of the reference chain plus totalBridged()

Cross-chain messaging

Function
Access
Reverts with

setRoute(chainType, chainReference, gateway)

IDENTITY_MANAGER

GatewayNotTrusted unless the gateway is trusted or zero, InvalidChainReference. Zero closes the chain. Emits ChainRegistered the first time, and RouteSet

setPeer(chainKey, peer)

IDENTITY_MANAGER

ChainNotRegistered, InvalidPeer, PeerChainMismatch. Emits PeerSet

dispatchMintInstruction(chainKey, body), dispatchRecallInstruction(chainKey, body)

AGENT

ChainNotOpen. Returns the sendId. Emits ProtocolMessageSent

dispatchComplianceValidation(chainKey, validationId, body)

The bound compliance

SenderNotCompliance, ChainNotOpen, ValidationAlreadyRouted. Emits ValidationRoutePinned and ProtocolMessageSent

receiveMessage(receiveId, sender, payload)

A gateway trusted by the TrustedGatewayRegistry

The checks of a delivery, listed in Build an ERC-7786 gateway adapter

trustedGatewayRegistry(), routeFor(chainKey), chainOf(chainKey), peerFor(chainKey), pinnedRouteFor(validationId, chainKey), isChainOpen(chainKey), messageReceived(gateway, receiveId)

Anyone, read

Functions reserved to the compliance

The compliance drives the bridged side of the ledger while it issues and settles validations. Each function reverts with OnlyBoundCompliance for any other caller.

Function
Called when
Reverts with

reserveForValidation(wallet, amount)

A validation is issued. Emits ReservedForValidation

releaseFromValidation(wallet, amount)

A reservation is given back, for example when a validation is discarded. Emits ReleasedFromValidation

holdInTransit(from, amount, validationId, reserved)

The burn of a transfer between two satellites is reported before its mint. Emits HeldInTransit

EnforcedPause, TransitAlreadyHeld, InsufficientBridgedBalance

returnHeldInTransit(to, validationId)

A stuck validation is resolved. Emits ReturnedInTransit

EnforcedPause, NothingInTransit

settleValidation(from, to, amount, validationId)

A settlement is applied. Emits BridgedTransfer, or SettledToNative for a recipient on the reference chain

EnforcedPause, InsufficientBridgedBalance, TransitAmountMismatch, UnverifiedIdentity for a recipient on the reference chain

The two reservation functions are not stopped by the pause: a reservation moves no token.

Events

Event
Emitted when

Transfer(address indexed from, address indexed to, uint256 value)

A balance of the reference chain changes

Approval(address indexed owner, address indexed spender, uint256 value)

approve, permit

Paused(address account), Unpaused(address account)

Halt, resume

UpdatedTokenInformation(string _newName, string _newSymbol, uint8 _newDecimals, string _newVersion, address indexed _newOnchainID)

Deployment, change of name, symbol or ONCHAINID

IdentityRegistryAdded(address indexed _identityRegistry), ComplianceAdded(address indexed _compliance)

The two setters

AddressFrozen(address indexed _userAddress, bool indexed _isFrozen, address indexed _owner)

An address is frozen or unfrozen. _owner is the caller

TokensFrozen(address indexed _userAddress, uint256 _amount), TokensUnfrozen(address indexed _userAddress, uint256 _amount)

An amount is frozen, released

RecoverySuccess(address indexed _lostWallet, address indexed _newWallet, address indexed _investorOnchainID)

End of a recovery

ForcedTransfer(address indexed agent)

After the Transfer of a forced transfer

IdentityTransfer(address indexed identity, address indexed from, address indexed to, uint256 amount)

After the Transfer of an identityTransfer

ReservedForValidation(bytes32 indexed walletKey, bytes wallet, uint256 amount), ReleasedFromValidation (same arguments)

A validation reserves part of a satellite wallet, gives it back

HeldInTransit(bytes32 indexed fromKey, uint256 indexed validationId, bytes fromWallet, uint256 amount)

A burn is reported before its mint

ReturnedInTransit(bytes32 indexed walletKey, uint256 indexed validationId, bytes wallet, uint256 amount)

A held amount returns to its wallet

BridgedTransfer(bytes32 indexed fromKey, bytes32 indexed toKey, uint256 indexed validationId, bytes from, bytes to, uint256 amount)

Settlement between two satellite wallets

SettledToNative(bytes32 indexed fromKey, address indexed to, uint256 indexed validationId, bytes fromWallet, uint256 amount)

Settlement to an address of the reference chain

ChainRegistered(bytes32 indexed chainKey, bytes2 chainType, bytes chainReference)

First route or peer for a chain

RouteSet(bytes32 indexed chainKey, address indexed gateway), PeerSet(bytes32 indexed chainKey, bytes peer)

The gateway, the peer, of a chain

TrustedGatewayRegistrySet(address trustedGatewayRegistry)

Once, at deployment

ValidationRoutePinned(uint256 indexed validationId, bytes32 indexed chainKey, address gateway)

First dispatch of a validation to a chain

ProtocolMessageSent(MessageTypesLib.Message indexed messageType, bytes32 indexed chainKey, bytes32 sendId)

A message leaves for a satellite

ProtocolMessageReceived(MessageTypesLib.Message indexed messageType, bytes32 indexed chainKey, bytes32 receiveId)

A message from a satellite was processed

BurnProofReceived(bytes32 indexed originChainKey, bytes burnedWallet, address indexed nativeWallet, uint256 amount)

A burn proof arrives

DelegatedOut(address indexed holder, bytes32 indexed toKey, bytes toWallet, uint256 amount), Recalled(bytes32 indexed fromKey, address indexed holder, bytes fromWallet, uint256 amount)

A position leaves for a satellite, returns from one

Last updated