This document maps all smart contract error codes defined in the creator-keys contract to their numeric discriminants, variant names, human-readable descriptions, and exact source code trigger conditions.
Error codes in Soroban contracts are defined using the #[contracterror] attribute on u32 enums. The numeric values are part of the contract's fixed ABI and are returned directly to callers during transaction simulation and execution.
Defined in creator-keys/src/lib.rs as pub enum ContractError.
| Code | Name | Description | Trigger Condition |
|---|---|---|---|
1 |
AlreadyRegistered |
Creator address is already registered in contract storage | Triggered in register_creator when profile already exists for creator. |
2 |
NotRegistered |
Creator profile does not exist for the specified address | Triggered in read_registered_creator_profile when looking up an unregistered creator address across trade, quote, dividend, and management entrypoints. |
3 |
Overflow |
Integer arithmetic would exceed storage or type bounds (u32::MAX or i128::MAX) |
Triggered in checked_accumulate, increment_creator_supply, increment_key_balance, calculate_buy_quote_fees, or compute_buy_price_for_amount on integer overflow. |
4 |
InsufficientPayment |
Payment supplied is less than the required price plus fees | Triggered in buy_key, buy_keys, or buy_keys_for when provided payment < total_amount. |
5 |
KeyPriceNotSet |
Pricing or trading attempted before setting a key price | Triggered in read_key_price when key price storage is empty for creator. |
6 |
NotPositiveAmount |
Amount or payment argument is zero or negative | Triggered in set_key_price, register_creator, buy_key, airdrop_keys, or buyback when amount <= 0 or payment <= 0. |
7 |
FeeConfigNotSet |
Trade or quote attempted before initializing global protocol fees | Triggered in read_protocol_fee_config when protocol fee configuration has not been set by an admin. |
8 |
InvalidFeeConfig |
Fee basis points sum is invalid (creator_bps + protocol_bps != 10000) |
Triggered in assert_valid_fee_bps when basis points do not sum to 10_000 (100%). |
9 |
InsufficientBalance |
Seller, sender, or buyback address does not hold enough keys | Triggered in sell_key, sell_keys, buyback, or transfer_keys when balance < requested_amount. |
10 |
SellUnderflow |
Net sell payout subtraction resulted in a negative proceeds value | Triggered in calculate_sell_quote_fees or calculate_quote_response when total fees exceed gross key price. |
11 |
ProtocolFeeExceedsCap |
Protocol fee share exceeds the maximum cap (protocol_bps > 5000) |
Triggered in assert_valid_fee_bps when protocol_bps > 5000 (50%). |
12 |
HandleTooShort |
Creator handle string length is below minimum bound (< 3 chars) |
Triggered in validate_handle when handle.len() < 3. |
13 |
HandleTooLong |
Creator handle string length exceeds maximum bound (> 32 chars) |
Triggered in validate_handle when handle.len() > 32. |
14 |
InvalidHandleCharacter |
Handle contains invalid characters (allowed: a-z, 0-9, _) |
Triggered in validate_handle when handle contains disallowed characters. |
15 |
ZeroAddress |
Target address is the Stellar zero address | Triggered in require_non_zero_address when configuring target addresses. |
16 |
SlippageExceeded |
Execution cost or proceeds violated caller-specified min/max bounds | Triggered in buy_key, sell_key, or buy_keys when execution price violates slippage parameters. |
17 |
ProtocolPaused |
State-changing transaction attempted while contract is paused | Triggered in require_not_paused when emergency pause mode is enabled. |
18 |
Unauthorized |
Caller lacks required authorization (admin, creator, or caller match) | Triggered in require_admin, require_creator, buy_keys_for, or airdrop_keys. |
19 |
NoDividendClaimable |
Holder has no accumulated dividend balance to claim | Triggered in claim_dividend when claimable dividend is 0. |
20 |
ZeroDistributionAmount |
Dividend distribution attempted with an amount of 0 |
Triggered in distribute_dividend when amount == 0. |
21 |
NoKeyHolders |
Dividend distribution attempted for creator with zero key holders | Triggered in distribute_dividend when holder count or total supply is 0. |
22 |
AllocationLocked |
Creator locked allocation claimed before lockup ledger sequence | Triggered in register_creator or claim_locked_allocation when current ledger < lockup_ledger. |
23 |
AlreadyClaimed |
Creator locked allocation was already claimed previously | Triggered in claim_locked_allocation when locked allocation flag is true. |
24 |
SupplyCapExceeded |
Action would cause total key supply to exceed the creator supply cap | Triggered in register_creator, buy_key, or airdrop_keys when supply + amount > supply_cap. |
25 |
InsufficientSupply |
Buyback quantity requested exceeds current circulating total supply | Triggered in get_buyback_quote or buyback when amount > total_supply. |
26 |
SelfTransfer |
Attempted key transfer to sender's own address (from == to) |
Triggered in transfer_keys when from == to. |
27 |
ZeroTransferAmount |
Attempted key transfer with an amount of 0 |
Triggered in transfer_keys when amount == 0. |
28 |
InsufficientTreasuryBalance |
Requested withdrawal exceeds protocol or creator treasury balance | Triggered in withdraw_protocol_treasury or withdraw_creator_treasury when withdrawal > treasury_balance. |
29 |
BatchClaimExceedsLimit |
Batch dividend claim request exceeds max batch size limit | Triggered in batch_claim_dividends when creators.len() > MAX_BATCH_CLAIM_LIMIT. |
30 |
InvalidCoCreatorShare |
Co-creator revenue split share bps exceeds bounds (> 10000) |
Triggered in validate_co_creator_config when share_bps > 10000. |
31 |
WhitelistOnly |
Buyer address is not in creator whitelist during whitelist window | Triggered in check_whitelist when whitelist is active and buyer is not allowed. |
32 |
WhitelistTooLarge |
Whitelist configuration address count exceeds maximum limit | Triggered in validate_whitelist_config when address count > MAX_WHITELIST_SIZE. |
33 |
AirdropRecipientLimitExceeded |
Airdrop recipient list length exceeds max limit per transaction | Triggered in airdrop_keys when recipients.len() > MAX_AIRDROP_RECIPIENT_LIMIT. |
Defined in creator-keys/src/events.rs as pub enum PollError.
| Code | Name | Description | Trigger Condition |
|---|---|---|---|
20 |
NotRegistered |
Poll creation attempted for an unregistered creator address | Triggered in create_poll when creator profile lookup fails. |
21 |
Overflow |
Poll counter or vote accumulation integer overflowed | Triggered in create_poll or vote_poll on arithmetic overflow. |
22 |
InvalidOptionCount |
Poll options list length is invalid (< 2 or > MAX_OPTIONS) |
Triggered in validate_poll_options when options count is out of range. |
23 |
QuestionTooLong |
Poll question string exceeds maximum character/byte length | Triggered in create_poll when question string length is too long. |
24 |
OptionTooLong |
Poll option text string exceeds maximum character/byte length | Triggered in validate_poll_options when any option text string is too long. |
25 |
PollNotFound |
Requested poll ID does not exist for the specified creator | Triggered in read_poll when poll record is missing. |
26 |
PollExpired |
Voting attempted on a poll after its expiration timestamp | Triggered in vote_poll when current_ledger_time > expires_at. |
27 |
NotAHolder |
Voter does not hold any keys for the poll creator (balance == 0) |
Triggered in vote_poll when voter key balance is zero. |
28 |
InvalidOption |
Selected option index is out of bounds for the target poll | Triggered in vote_poll when option_index >= options.len(). |
Read-only quote functions defined in creator-keys/src/quote_view_errors.rs return string error identifiers for off-chain calculation paths:
| String Constant | Value | Context |
|---|---|---|
ERR_NOT_REGISTERED |
"not_registered" |
Creator address is not registered |
ERR_FEE_CONFIG_NOT_SET |
"fee_config_not_set" |
Protocol fee configuration has not been set |
ERR_OVERFLOW |
"overflow" |
Quote math overflowed i128 bounds |
ERR_SELL_UNDERFLOW |
"sell_underflow" |
Sell quote fee subtraction underflowed proceeds |
ERR_ZERO_CLAIMABLE |
"zero_claimable" |
Dividend claimable quote amount is zero |
ERR_NO_HOLDERS |
"no_holders" |
Creator has no key holders |
ERR_DIVIDEND_AMOUNT_ZERO |
"dividend_amount_zero" |
Dividend distribution quote amount is zero |
When invoking a contract method via standard Soroban RPC (simulateTransaction), contract reverts with a ContractError return a JSON response containing Error(Contract, #<code>).
Below is a representative example of a simulateTransaction RPC response when buy_key reverts due to SlippageExceeded (ContractError Code 16):
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"error": "HostError: Error(Contract, #16)",
"transactionData": "AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...",
"events": [],
"minResourceFee": "1000",
"results": [
{
"auth": [],
"xdr": "AAAAAAGAAAAD"
}
]
}
}In JavaScript/TypeScript using @stellar/stellar-sdk or Soroban Client libraries, contract error codes are decoded from simulation or submission results:
try {
const simResult = await server.simulateTransaction(tx);
if (simResult.error) {
// Extract numeric code from "Error(Contract, #16)" pattern
const match = simResult.error.match(/Error\(Contract, #(\d+)\)/);
if (match) {
const errorCode = parseInt(match[1], 10);
console.log(`Contract reverted with error code: ${errorCode}`);
// Mapping to ContractError enum: 16 -> SlippageExceeded
}
}
} catch (err) {
// Handle network or RPC errors
}AlreadyRegistered(Code 1) guards against re-registering an existing creator. Off-chain apps should callis_registered(creator)orget_creator(creator)prior to registration.NotRegistered(Code 2) applies to trades, quotes, and management. Callers must register creators prior to key trading.HandleTooShort(12),HandleTooLong(13), andInvalidHandleCharacter(14) are deterministic handle validation checks. Validate handles client-side (/^[a-z0-9_]{3,32}$/) before submission.
FeeConfigNotSet(7) andKeyPriceNotSet(5) are initialization gates. Detect these and inform users that pricing/fees are not yet configured.InvalidFeeConfig(8) requirescreator_bps + protocol_bps == 10000.ProtocolFeeExceedsCap(11) enforcesprotocol_bps <= 5000(50% max protocol share).
InsufficientPayment(4) applies to buys when payment is less than total price + fees.InsufficientBalance(9) applies to sells, transfers, and buybacks when caller balance is insufficient.SlippageExceeded(16) indicates market movement between quote generation and execution. Refresh quotes and retry with wider slippage bounds.
- Poll errors use numeric codes 20–28 under
PollError. PollExpired(26) occurs when voting on a poll past its ledger expiration.NotAHolder(27) requires non-zero creator key ownership to vote.
- Numeric Stability: Error codes are fixed contract ABI discriminants.
- Safe Extension: New variants MUST be appended at the end of the
ContractErrorenum with the next unused numeric value. - No Reordering: Never insert error variants mid-enum, reorder existing variants, or re-assign retired numbers.