Token Standards have been a sticky subject for the Internet Computer community. Everyone agrees on their importance, but with so many possibilities for their design, it has been a struggle for the ecosystem to reach a consensus and deliver on one.
InfinitySwap's mission has always been to bring core DeFi functionality to the Internet Computer. We are proud to detail the InfinitySwap Token Standard (IS20) specifications and how it has the potential to revolutionize DeFi on the Internet Computer, having introduced novel and essential features in the areas of interoperability, modularity, and decentralization.
Below we detail the IS20’s specifications and what makes it unique. Please check out our repo, as we’d love to hear your thoughts and suggestions and get as much developer integration as possible. We have a competent team ready to support your project if you want to launch a token on the Internet Computer.
Cross Canister Calls
Currently, cross-canister calls on the IC are unsafe and can lead to a situation where the called canister prevents the calling canister from being upgraded. This actually happened to the IC's ledger token standard, which led to an emergency upgrade to the node replicas that run the IC's consensus. At InfinitySwap, we went to great lengths to solve the issue by using the same Canister Signatures that power the Internet Identity as a replacement for cross-canister calls, which prevents this attack.
Cycles Drainage and DOS Attacks
Transactions in some different standards incur a fee, which is used to deter spammers. Still, unfortunately, this alone doesn’t prevent a spammer from draining your token of its cycles (the fuel used to run your token’s canister). Other token standards are not handling DOS attacks.
Before IS20, even if an attacker or spammer had none of your tokens, it would have been possible for them to drain a canister’s cycles through repeated transfer calls. These calls would, of course, be rejected, but their invocation would still consume cycles as per the Internet Computer specifications.
If an attacker had their way, they could incur network and computation fees with no impediments on the IC except for the transaction throughput of a canister, currently around 200 messages a second.
Our token standard is the first standard to completely block spam transactions by using the Internet Computer’s inspect_message to reject update calls from users who do not have a sufficient balance to pay the minimum transaction fee. Using the Internet Computer’s inspect_message ensures that token canisters won’t have to pay the fees for these calls.
By guarding update calls in such a way, we can prevent a token canister from being drained of cycles, going offline, and having an attacker steal your cycles; as with IS20, there is always a fee paid whether the update call is rejected or accepted.
Decentralized Cycles Top-Up
The IS20 token standard empowers the community to refuel the cycles of a canister in a decentralized way, enabling the community to support the running of token canisters. How it works:
Fees are collected in the native token that is being transferred, but those fees must be converted to cycles to fuel the token canister. In IS20, we have implemented a decentralized bidding market for cycles. During regularly hosted auctions, users can contribute cycles to the token canister.
They are later rewarded with the fees accumulated by the token canister in proportion to their share of cycles contributed. This ensures that token canisters have a decentralized way to fund computations and keep canisters running.
It’s problematic to have only one individual responsible for topping up a canister, both from a responsibility standpoint and a regulatory and legal perspective. The cycles’ marketplace provides a way for the community to be involved and incentivized to top up a canister.
We want the implementation of our token standard to be used as widely as possible, and so have made it compatible with the ERC20 standard, as well as the IC-based incarnations like DIP20, and also the Internet Computer’s native tokens such as the ledger canister.
IS20 will include parts of the interface for the IC-ledger Canister as part of its interface, which will consist of a way to verify that a transaction has been made through the ledger’s notify method.
When a transaction is made through the ledger, this information is journaled and can be used as a receipt for payments to other canisters and downstream DeFi applications. In essence, whether you want to follow the ERC20 route or the ledger canister’s way of making payments, that will be at your discretion with IS20.
The IS20 repo includes a registry-like utility called the factory, which can spawn other tokens and maintains a registry of all the tokens launched through the factory.
Registries will be super useful for wallets, as they will enhance the discoverability of tokens launched through our platform and through others if they wish to use their own factories. The question is: where are the tokens, and where can they be found? Our answer is factory-like registries.
IC_CDK Storage Bug Fix
IS20 fixes two other vulnerabilities found in prior implementations of token standards. There is a bug in the commonly used ic_cdk storage that can lead to memory corruption through dangling references. Please see the appendix for more details.
In other standards, a downstream canister has no way of knowing whether the token owner has changed the fees if the downstream canister is mid-execution when fees are changed. Although relatively infrequent, this can lead to anomalies where a downstream DeFi application, for instance, an AMM, pays one party more than their fair share of tokens.
In IS20, we have included a limit parameter in transfers to ensure that even if fees change mid-execution, a transfer will not cost more than the expected limit, where limit > transfer amount + original fee.
Our token implementation has gone through a suite of unit and functional tests and is actively maintained by our core developers.
As a DeFi-specific standard, IS20 is not designed for all token use cases on the Internet Computer, like governance and social applications. For that, it may be better to use the IC’s SNS when it becomes available.
IS20 will, however, enable applications to automatically integrate with an existing suite of DeFi services, such as the InfinitySwap AMM and won’t force users to choose between having an ERC20 or ledger-like API.
Our token standard is designed with the three pillars of safety, decentralization, and interoperability in mind. The security comes from having a great dev team that has managed to patch exploits - DOS attacks, internal bugs, and the transfer fee flow.
Decentralization will come from the fact that the owner of a canister will not be responsible for its top-up, which could be a barrier to adoption due to regulatory reasons. By creating a decentralized marketplace for cycles, we encourage community participation in running a token.
As a preview of what we are planning - you'll be able to launch an IS20 token from our platform in the next few weeks on our test net. Here’s a sneak peek of the wallet application.
Technical Appendix Follows
IC_CDK storage bug fix
In more detail, the ic_cdk storage internally uses a static mutable binary tree to store all its values. With the implementation, it’s possible to obtain two mutable references to the same value. This is problematic because:
- When loading the value from two separate function calls, the reference to its value may be broken by the first function call (as demonstrated in the bug report linked bug).
- Awaiting async calls in update methods will switch the execution context, which means another call could access and modify the stored value while we wait for the first.
To prevent unintentionally creating dangling references and other memory-related vulnerabilities, we wrote our own implementation of the canister state storage. It uses RefCell to control access to the stored value, removing the need for static mut for storage, and so we don’t rely on unsafe Rust code and can take full advantage of Rust’s safety guarantees.
Our implementation follows a clean and modular approach, making it easy for builders to upgrade the token standard to suit their needs. These include:
- An API module containing all external methods is divided into submodules according to the method's original source (DIP20 or IS20) and the functionality they perform.$
- dip20_transactoins.rs contains the core functionality for the ERC20 transfers.
- dip20_meta.rs contains the methods to set and retrieve meta-information about the token (name, symbol, logo, etc.).
- is20_notify.rs contains methods related to the ledger transaction notifications.
- is20_auction.rs contains methods for cycle bidding.
- is20_manageement.rs contains some additional methods for canister meta-data management.
- state.rs contains the canister state and methods to allow canister upgrade.
- ledger.rs contains helper methods for storing transaction history.
- types.rs contains the core types as well as the output types for the API methods.