The Tokenization Precompile provides full access to the BitBadges tokenization module from Solidity contracts. All methods use a JSON-based interface for maximum flexibility and compatibility with the underlying Cosmos SDK protobuf messages.
The executeMultiple method allows executing multiple tokenization messages in a single atomic transaction. This is particularly useful for workflows like "Create Collection + Transfer Tokens":
Key Features:
Atomic Execution: All messages succeed or all fail (no partial execution)
Sequential Order: Messages execute in the order provided
Dynamic Routing: Message type string determines which handler to use
Result Decoding: Results are returned as bytes[] - decode based on message type
See API Reference for complete executeMultiple documentation.
Query Methods
Query methods return structs (ABI-encoded; define matching struct types in your contract) or uint256 for amount/supply queries:
See API Reference for complete method documentation.
Struct Return Types
Query methods (except getBalanceAmount and getTotalSupply) return ABI-encoded structs. Define struct types in your contract that match the precompileβs response layout:
When using executeMultiple, build individual message JSONs using the helpers above, then construct the MessageInput array in Solidity.
Return Value Handling
Direct Returns (uint256)
Some methods return uint256 directly:
Struct Returns (Query Methods)
Query methods (e.g. getCollection, getBalance, getCollectionStats, getDynamicStore, getDynamicStoreValue, getAddressList) return ABI-encoded structs. Define matching struct types in your contract and use an interface that declares those return types; then use the returned struct fields directly in your logic. See Struct Return Types for supported types and examples.
Security Considerations
Automatic Creator Field: The creator field is automatically set from msg.sender and cannot be spoofed
JSON Validation: Invalid JSON will revert with clear error messages
Type Safety: Use helper functions to ensure correct JSON structure
Gas Optimization: JSON construction is efficient, but cache complex JSON strings when possible
Best Practices
1. Always Use Helper Functions
2. Cache Complex JSON
3. Validate Inputs Before Building JSON
4. Handle Errors Gracefully
5. Multi-Message Execution Best Practices
When using executeMultiple, follow these guidelines:
Key Points:
Validate all inputs before building messages
Use auto-prev (collectionId: "0") to reference previous message results
Always check result count matches message count
Decode and validate each result
Handle errors with clear messages
Examples
See the example contracts for complete implementations:
uint256 public kycRegistryId;
function initializeKYCRegistry() external {
string memory createJson = TokenizationJSONHelpers.createDynamicStoreJSON(
false, // defaultValue: not KYC'd by default
"ipfs://kyc-registry-metadata",
"{\"type\":\"kyc\"}"
);
kycRegistryId = TOKENIZATION.createDynamicStore(createJson);
}
function setKYCStatus(address user, bool isKYCd) external {
string memory setValueJson = TokenizationJSONHelpers.setDynamicStoreValueJSON(
kycRegistryId,
user,
isKYCd
);
TOKENIZATION.setDynamicStoreValue(setValueJson);
}
function isKYCVerified(address user) external view returns (bool) {
string memory getValueJson = TokenizationJSONHelpers.getDynamicStoreValueJSON(
kycRegistryId,
user
);
DynamicStoreValueResult memory result = TOKENIZATION.getDynamicStoreValue(getValueJson);
// Use the field that matches your store's value type (e.g. for a boolean store, the struct's bool field)
return result.verified; // field name depends on your DynamicStoreValueResult definition
}
}
// β Good - Type-safe and readable
string memory json = TokenizationJSONHelpers.transferTokensJSON(...);
// β Bad - Error-prone manual construction
string memory json = string(abi.encodePacked('{"collectionId":"', ...));
// β Good - Cache for reuse
string memory tokenIdsJson = TokenizationJSONHelpers.uintRangeToJson(1, 1000);
// Use tokenIdsJson multiple times
// β Bad - Reconstruct every time
// Rebuilding JSON on every call wastes gas