Skip to main content

Creating Regulated Coins with Deny Lists on IOTA

Regulated coins on IOTA allow you to control access by restricting certain addresses, which is crucial for assets like stablecoins. These coins are similar to standard IOTA coins but provide additional control through a deny list.

The IOTA Coin standard offers the create_regulated_currency function to create such coins. This function not only creates the coin but also generates a DenyCap object, \enabling you to manage a deny list via a DenyList object. The process is akin to using create_currency, with the added step of handling the DenyCap object.

regcoin.move
module examples::regcoin {
use iota::coin;

public struct REGCOIN has drop {}

fun init(witness: REGCOIN, ctx: &mut TxContext) {
let (treasury, deny_cap, metadata) = coin::create_regulated_currency(witness, 6, b"REGCOIN", b"", b"", option::none(), ctx);
transfer::public_freeze_object(metadata);
transfer::public_transfer(treasury, tx_context::sender(ctx));
transfer::public_transfer(deny_cap, tx_context::sender(ctx))
}
}

Deploying this module with iota client publish results in transaction effects that include the creation of several objects:

...

Object Changes

Created Objects:

ObjectID: <OBJECT-ID>
Sender: <SENDER-ADDR>
Owner: Immutable
ObjectType: 0x2::coin::CoinMetadata<<PACKAGE-ID>::regcoin::REGCOIN>
Version: <VERSION-NUMBER>
Digest: <DIGEST-HASH>

ObjectID: <OBJECT-ID>
Sender: <SENDER-ADDR>
Owner: Account Address ( <PUBLISHER-ADDRESS )
ObjectType: 0x2::package::UpgradeCap
Version: <VERSION-NUMBER>
Digest: <DIGEST-HASH>

ObjectID: <OBJECT-ID>
Sender: <SENDER-ADDR>
Owner: Immutable
ObjectType: 0x2::coin::RegulatedCoinMetadata<<PACKAGE-ID>::regcoin::REGCOIN>
Version: <VERSION-NUMBER>
Digest: <DIGEST-HASH>

ObjectID: <OBJECT-ID>
Sender: <SENDER-ADDR>
Owner: Account Address ( <PUBLISHER-ADDRESS )
ObjectType: 0x2::coin::DenyCap<<PACKAGE-ID>::regcoin::REGCOIN>
Version: <VERSION-NUMBER>
Digest: <DIGEST-HASH>


ObjectID: <OBJECT-ID>
Sender: <SENDER-ADDR>
Owner: Account Address ( <PUBLISHER-ADDRESS )
ObjectType: 0x2::coin::TreasuryCap<PACKAGE-ID>::regcoin::REGCOIN>
Version: <VERSION-NUMBER>
Digest: <DIGEST-HASH>

...

Notice that a RegulatedCoinMetadata object is created alongside the standard CoinMetadata object. You don't need to explicitly freeze the RegulatedCoinMetadata object because create_regulated_currency does this automatically.

The output also shows three objects now owned by the publisher:

Understanding the DenyList

The IOTA framework provides a DenyList singleton shared object, identified by the address 0x403. Holders of a DenyCap can specify addresses prohibited from using certain IOTA core types, which is particularly useful for regulated coins needing to comply with regulations.

info

You cannot create the DenyList object yourself; it is a system object at address 0x403.

Managing the Deny List

To manipulate the deny list for your coin, add these functions to your module:

public fun add_address_to_deny_list(denylist: &mut DenyList, denycap: &mut DenyCap<REGCOIN>, address_to_deny: address, ctx: &mut TxContext){
coin::deny_list_add(denylist, denycap, address_to_deny, ctx);
}

public fun remove_address_from_deny_list(denylist: &mut DenyList, denycap: &mut DenyCap<REGCOIN>, address_to_allow: address, ctx: &mut TxContext){
coin::deny_list_remove(denylist, denycap, address_to_allow, ctx);
}

To use these functions, pass the DenyList object (0x403), your DenyCap object ID, and the address you wish to add or remove.

Using the IOTA CLI:

iota client call --function add_address_to_deny_list --module regcoin --package <PACKAGE-ID> --args <DENY-LIST> <DENY-CAP> <ADDRESS-TO-DENY>
Transaction Digest: <DIGEST-HASH>

The console will display the network response, confirming that the DenyList object has been mutated:

...

MutatedObjects:

ObjectID: 0x0...403
Sender: <SENDER-ADDRESS>
Owner: Shared
ObjectType: 0x2::deny_list::DenyList
Version: <VERSION-NUMBER>
Digest: <DIGEST-HASH>

...

For a complete list of available Coin functions, refer to the IOTA framework coin module documentation.

Question 1/3

What is the main difference between `create_regulated_currency` and `create_currency` in the IOTA Coin standard?