Skip to main content

Token Policy

TokenPolicy is a shared object that a token owner can create using the TreasuryCap. Having a publicly available TokenPolicy enables onchain discovery of allowed actions and their conditions. This is useful for wallets and other services that want to provide a better user experience for token holders.

Creating a TokenPolicy also returns a TokenPolicyCap. The TokenPolicyCap is required to manage the policy: allowing and disallowing actions, and adding or removing rules. Consuming spent balance with token::flush requires the TreasuryCap.

How do I create and share a TokenPolicy?​

You create a new TokenPolicy using the token::new_policy function. The function takes the TreasuryCap as an argument and returns a TokenPolicy object and a managing capability.

// module: sui::token
public fun new_policy<T>(
treasury_cap: &TreasuryCap<T>,
ctx: &mut TxContext
): (TokenPolicy<T>, TokenPolicyCap<T>);

You must use the token::share_policy function to share the TokenPolicy object.

How do I allow or disallow an action on my token?​

To allow methods without any conditions, use the token::allow function. The function takes a TokenPolicy and TokenPolicyCap as arguments, along with the name of the action as a String (for example, "transfer" or "to_coin"). If allowed, the action can be confirmed in the TokenPolicy using the token::confirm_request function (see ActionRequest).

// module sui::token
public fun allow<T>(
policy: &mut TokenPolicy<T>,
policy_cap: &TokenPolicyCap<T>,
action: String,
ctx: &mut TxContext
);

Similarly, you can use the token::disallow function to completely disable an action; it takes the same arguments as token::allow.

How do I add rules to an action?​

TokenPolicy can specify custom conditions for each action. These conditions are called rules and are typically implemented as separate Move modules. The identifier of the rule is its type. See Rules for more information.

The pseudo-code structure of the TokenPolicy is as follows. Each action can have multiple rules associated with it. In this example, 0x0... is a placeholder; each rule is identified by its full type.

TokenPolicy
rules:
- action: "transfer"
rules:
- 0x0...::denylist::Denylist
- action: "to_coin"
rules:
- 0x0...::limiter::Limiter
- 0x0...::allowlist::Allowlist
...

To add a rule for an action, use the token::add_rule_for_action function. The function takes a TokenPolicy and TokenPolicyCap as arguments. The rule is specified by its type (for example, 0x0...::denylist::Denylist).

// module: sui::token
public fun add_rule_for_action<T, Rule: drop>(
policy: &mut TokenPolicy<T>,
policy_cap: &TokenPolicyCap<T>,
action: String,
ctx: &mut TxContext
);

Signature for the reverse operation token::remove_rule_for_action is symmetrical to token::add_rule_for_action.

How do I consume a spent token balance?​

Spent balance can be consumed from the TokenPolicy using the token::flush function. It requires a TreasuryCap. For more on spent balance, see Spending.

// module sui::token
public fun flush<T>(
policy: &mut TokenPolicy<T>,
treasury_cap: &mut TreasuryCap<T>,
ctx: &mut TxContext
): u64;

Cheat sheet: TokenPolicy API​

FunctionNote
new_policyCreate a new TokenPolicy using the TreasuryCap
allowAllow an action in the TokenPolicy
disallowDisallow an action in the TokenPolicy
add_rule_for_actionAdd a rule for an action in the TokenPolicy
remove_rule_for_actionRemove a rule for an action in the TokenPolicy
confirm_requestConfirm an ActionRequest with a TokenPolicy. This function is in the sui::token module and is a step in the ActionRequest confirmation flow (see ActionRequest).
confirm_request_mutSimilar to confirm_request but only works for spend action
flushFlush the spent balance from the TokenPolicy (see Spending)