Post
Share your knowledge.
Can modules generate multiple coins onchain seamlessly?
I’m working on a module for prediction markets and need it to generate coins onchain through a factory class in a permissionless and verifiable way. Currently, modules have limitations like only one coin per module due to One Time Witness, which means I had to create an equivalent coin standard that users' wallets don't recognize as a coin. Can we resolve this in the next update?
- Move CLI
- Move Module
Answers
3While modules currently have limitations such as the restriction to only publish one coin per module because of One Time Witness, consider using a single deployed contract like WASM, which allows for the creation of multiple coin types as described in this guide: https://docs.sui.io/guides/developer/nft/asset-tokenization.
If you're building a prediction market module and want to generate new coins onchain using a factory pattern, you're running into a known limitation in the current Move coin framework—specifically, the One Time Witness (OTW) rule, which restricts each module to defining only one coin type. Because of this, when you try to create multiple coins dynamically, you're forced to use a custom structure that wallets don't recognize as native coins, making user interactions less smooth.
To work around this, you can build a custom coin-like struct that mimics the behavior of the native Coin<T>
but isn't treated as one by the Sui wallet interface. Unfortunately, until Sui updates its coin model to allow for multi-coin support per module or introduces a more flexible factory system with proper wallet support, this limitation will persist. However, you can still ensure the system remains verifiable and permissionless by emitting events for coin creation and storing metadata in a registry that wallets or indexers can read.
In the meantime, here's a simple conceptual structure for a factory-based coin generator that mimics native coin behavior:
public entry fun create_prediction_token(
admin: &signer,
name: vector<u8>,
symbol: vector<u8>,
decimals: u8
): (CustomCoin, CustomCoinMetadata) {
let token = CustomCoin { id: object::new(admin), value: 0 };
let metadata = CustomCoinMetadata {
name,
symbol,
decimals,
creator: signer::address_of(admin)
};
// Emit an event or store in registry for traceability
event::emit<NewTokenCreated>(&metadata);
(token, metadata)
}
Sui may offer a more flexible or native solution in the future, possibly with multi-coin factories or updated wallet recognition logic for factory-generated coins. Until then, you can follow developments and propose enhancements on the official repo or community discussions.
https://github.com/MystenLabs/sui/discussions
https://docs.sui.io/devnet/build/coin
This is a growing area in the ecosystem, so your feedback could directly influence future updates.
Right now, the one-time witness (OTW) rule in Sui's Move language limits you to creating just one coin type per module, which can be a hassle for something like a prediction market where you might want a factory class to churn out multiple coin types onchain in a permissionless and verifiable way. This restriction comes from how the coin::create_currency function uses the OTW to ensure a unique TreasuryCap for each coin type, which wallets recognize as standard coins, but it means you can’t easily spin up multiple coins in one module without workarounds like creating separate modules or custom types that wallets might not see as proper coins. For your prediction market, you could try a factory pattern where a single module manages multiple coin-like objects by wrapping them in a custom struct, but this often leads to non-standard tokens that don’t play nice with wallets, as you’ve noticed. There’s no confirmed fix in the next Sui update to lift the OTW limit or allow seamless multi-coin creation in a single module, as the roadmap focuses more on things like ZK login and storage optimizations. A practical move is to deploy a factory that spawns new modules dynamically for each coin type, using the coin::create_currency function to keep them wallet-compatible, and verify their creation through events emitted onchain. This approach stays permissionless since anyone can call the factory, and it’s verifiable via Sui’s event system or explorer, though it’s a bit clunky with extra module publishing.
Do you know the answer?
Please log in and share it.
Move is an executable bytecode language used to implement custom transactions and smart contracts.
