Skip to content

The full approvalCriteria interface, which fields exist on which approval level, one line per criterion with a link, and the require* address flags.

approvalCriteria holds every extra condition an approval can impose beyond who, when, and what. All criteria on an approval must pass for that approval to match.

Shape

ts
export interface iApprovalCriteria<T extends NumberType> {
  /** The BADGE or sdk.coin transfers to be executed upon every approval. */
  coinTransfers?: iCoinTransfer<T>[];
  /** The list of merkle challenges that need valid proofs to be approved. */
  merkleChallenges?: iMerkleChallenge<T>[];
  /** The list of must own tokens that need valid proofs to be approved. */
  mustOwnTokens?: iMustOwnToken<T>[];
  /** The predetermined balances for each transfer. These allow approvals to use predetermined balance amounts rather than an incrementing tally system. */
  predeterminedBalances?: iPredeterminedBalances<T>;
  /** The maximum approved amounts for this approval. */
  approvalAmounts?: iApprovalAmounts<T>;
  /** The max num transfers for this approval. */
  maxNumTransfers?: iMaxNumTransfers<T>;
  /** Whether the approval should be deleted after one use. */
  autoDeletionOptions?: iAutoDeletionOptions;
  /** Whether the to address must equal the initiatedBy address. */
  requireToEqualsInitiatedBy?: boolean;
  /** Whether the from address must equal the initiatedBy address. */
  requireFromEqualsInitiatedBy?: boolean;
  /** Whether the to address must not equal the initiatedBy address. */
  requireToDoesNotEqualInitiatedBy?: boolean;
  /** Whether the from address must not equal the initiatedBy address. */
  requireFromDoesNotEqualInitiatedBy?: boolean;
  /** Whether this approval overrides the from address's approved outgoing transfers. */
  overridesFromOutgoingApprovals?: boolean;
  /** Whether this approval overrides the to address's approved incoming transfers. */
  overridesToIncomingApprovals?: boolean;
  /** Issuer-imposed constraints on user-level approvals. Includes royalties, allowed denoms, and coin transfer restrictions. */
  userApprovalSettings?: iUserApprovalSettings<T>;
  /** The list of dynamic store challenges that the initiator must pass for approval. */
  dynamicStoreChallenges?: iDynamicStoreChallenge<T>[];
  /** The list of ETH signature challenges that the initiator must pass for approval. */
  ethSignatureChallenges?: iETHSignatureChallenge[];
  /** Address checks for sender */
  senderChecks?: iAddressChecks;
  /** Address checks for recipient */
  recipientChecks?: iAddressChecks;
  /** Address checks for initiator */
  initiatorChecks?: iAddressChecks;
  /** Alternative time-based checks for approval denial (offline hours/days). */
  altTimeChecks?: iAltTimeChecks<T>;
  /** If true, this approval must be explicitly prioritized in PrioritizedApprovals to be used. */
  mustPrioritize?: boolean;
  /** The list of voting challenges that must be satisfied for approval. */
  votingChallenges?: iVotingChallenge<T>[];
  /** EVM query challenges that must pass for approval. Read-only contract queries that verify external EVM state. */
  evmQueryChallenges?: iEVMQueryChallenge<T>[];
  /** If true, this collection approval allows backed minting operations (CosmosCoinBackedPath). When false, this approval cannot be used for transfers involving backed minting addresses. This prevents accidental allowances when toListIds is "All". */
  allowBackedMinting?: boolean;
  /** If true, this collection approval allows special wrapping operations (CosmosCoinWrapperPath). When false, this approval cannot be used for transfers involving wrapping addresses. This prevents accidental allowances when toListIds is "All". */
  allowSpecialWrapping?: boolean;
}

Royalties are inside userApprovalSettings.userRoyalties. There is no top-level userRoyalties field (proto field 13 is reserved).

Token Ownership Requirements
Off
No ownership check
Coin Transfers per Use
On
  • 1 BADGEbb1p0rrel3...w70d
Merkle Challenges
Off
No proof required
Predetermined Balances
On
Start: x1 of IDs 1, then +1 ID per transfer
Order: useOverallNumTransfers
Amount Restrictions
Off
No amount limit
Max Transfers
On
Overall: 100
Per initiator: 1
Address Checks
On
Recipient must be the initiator
Sender and Recipient Approvals
On
Skips the sender's outgoing approvals
Must satisfy the recipient's incoming approvals

A paid mint on bitbadges.io: the criteria that are set show as on, the rest are dimmed.

Criteria

CriterionOne lineAuto-scannable
approvalAmounts, maxNumTransfersIncrement-only tallies that cap amounts and transfer counts, overall or per address, with optional periodic resetsyes
predeterminedBalancesForce each transfer to move exact balances, in order, computed manually or by incrementsno
merkleChallengesRequire a SHA256 Merkle proof (whitelist or claim code) with per-leaf use limitsno
ethSignatureChallengesRequire a one-time Ethereum signature from a named signerno
votingChallengesRequire a weighted quorum of on-chain votes, with optional timelock and resetyes
dynamicStoreChallengesRequire a party to be true in an address-to-bool store with a global kill switchyes
evmQueryChallengesRequire a read-only EVM call to return an expected valueyes
mustOwnTokensRequire a party to hold tokens from some collectionyes
coinTransfersMove x/bank coins every time the approval is usedno
overridesFromOutgoingApprovals, overridesToIncomingApprovalsSkip the sender's or recipient's user-level approvals (collection only)yes
require* flags (below)Constrain equality between initiator and sender or recipientyes
senderChecks, recipientChecks, initiatorChecksRequire or forbid EVM contracts and liquidity poolsyes
altTimeChecksDeny by hour, weekday, month, day of month, or ISO week, with a timezone offsetyes
autoDeletionOptionsDelete the approval after use or allow others to purge ityes
mustPrioritizeRemove the approval from auto-scann/a
allowBackedMinting, allowSpecialWrappingOpt an approval into backed-path and wrapper-path transfers (collection only)requires prioritization
userApprovalSettingsConstrain user-level coin transfers and add royalties (collection only)yes

Post-transfer EVM checks that live on the collection rather than an approval are on Invariants.

Which Level Has Which Fields

The proto defines three criteria types. Fields missing from a level cannot be set there.

FieldCollectionOutgoingIncoming
merkleChallenges, predeterminedBalances, approvalAmounts, maxNumTransfers, coinTransfers, autoDeletionOptions, mustOwnTokens, dynamicStoreChallenges, ethSignatureChallenges, initiatorChecks, altTimeChecks, mustPrioritize, votingChallenges, evmQueryChallengesyesyesyes
requireToEqualsInitiatedBy, requireToDoesNotEqualInitiatedBy, recipientChecksyesyesno (recipient is the owner)
requireFromEqualsInitiatedBy, requireFromDoesNotEqualInitiatedBy, senderChecksyesno (sender is the owner)yes
overridesFromOutgoingApprovals, overridesToIncomingApprovals, allowBackedMinting, allowSpecialWrapping, userApprovalSettingsyesnono

Ask your agent:

text
Add a collection approval to collection 1 that lets anyone mint one token each, and show me the full approvalCriteria it generates.

The MCP builder tools (add_approval, add_preset_approval) produce the objects on this page.

How It Works

require flags

ts
interface ApprovalCriteria<T extends NumberType> {
  requireToEqualsInitiatedBy?: boolean;
  requireToDoesNotEqualInitiatedBy?: boolean;
  requireFromEqualsInitiatedBy?: boolean;
  requireFromDoesNotEqualInitiatedBy?: boolean;
}
FlagRequires
requireToEqualsInitiatedByrecipient == initiator (self-claims)
requireToDoesNotEqualInitiatedByrecipient != initiator
requireFromEqualsInitiatedBysender == initiator (no delegated sends)
requireFromDoesNotEqualInitiatedBysender != initiator

These apply after the address lists match. An address must be in the relevant list and then satisfy the flag.

Tracker IDs

Trackers (amount, transfer count, Merkle leaf use, ETH signature use, votes) are keyed by the approval they belong to plus a user-chosen ID. Full key formats are on each page. Two rules hold everywhere:

  • Trackers are increment-only and never deleted. Changing an approval does not reset its trackers.
  • To start from zero, use an ID with no history (change amountTrackerId, challengeTrackerId, or proposalId). Reusing an old ID resumes the old tally.

Evaluation Order

The chain evaluates criteria in a fixed pipeline for each approval that matches the core fields. Any failure rejects that approval for this transfer; the scan then moves to the next candidate. Side effects (coin transfers, tracker increments, auto-deletion) run only after every check on the chosen approval passes.

Edit this page on GitHub