Was this helpful?
Configure your stablecoin's permissions, supply limits, and compliance policies after deployment. This guide covers granting roles to manage token operations, setting supply caps, configuring transfer policies, and controlling token transfers through pause/unpause functionality.
TIP-20 tokens use a role-based access control system that allows you to delegate different administrative functions to different addresses. For detailed information about the role system, see the TIP-20 specification.
In this guide, we'll walk through how to assign and check the issuer role, but the process is identical for other roles like pause, unpause, burnBlocked, and defaultAdmin.
Set or update the token's on-chain logoURI so wallets and explorers can read the icon directly from the token contract via logoURI(). This requires the DEFAULT_ADMIN_ROLE and is done by calling setLogoURI(string newLogoURI) on the token (TIP-1026). For the recommended format, use a square, rasterized PNG or WebP (max 256 bytes; https, http, ipfs, or data scheme).
Limit the maximum total supply of your token. Setting supply caps requires the DEFAULT_ADMIN_ROLE. The new cap cannot be less than the current total supply.
Control who can send and receive your stablecoin for compliance and regulatory requirements. Setting transfer policies requires the DEFAULT_ADMIN_ROLE.
Transfer policies can be:
Learn more about configuring transfer policies in the TIP-403 specification.
Temporarily halt all token transfers during emergency situations or maintenance windows. Pausing transfers requires the PAUSE_ROLE. Unpausing transfers requires the UNPAUSE_ROLE.
The Burn Blocked role allows your team to burn tokens from blocked or frozen addresses. This is useful for regulatory compliance when you need to remove tokens from addresses that violate terms of service or legal requirements.
Use different addresses for different roles to enhance security. For example, assign the issuer role to your treasury address for minting, and the pause role to your security team for emergency controls.
Monitor onchain events for role changes, mints, burns, and administrative actions to maintain visibility into token operations and detect unauthorized activities.
Ensure pause and unpause roles are assigned to trusted addresses and that your team has documented procedures for responding to security incidents requiring token transfers to be halted.
Before you can manage roles on your stablecoin, you need to create one. Follow the Create a Stablecoin guide to deploy your token.
Once you've created your token, you can proceed to grant roles to specific addresses.
Assign roles to specific addresses to delegate token management capabilities.
import React from 'react'
import { } from 'wagmi/tempo'
import { } from '@tanstack/react-query'
export function () {
const = ()
const = '0x...' // Your token address
const = '0x...' // Address to grant the issuer role
const = ..({})
const = async () => {
await .({
: ,
: ['issuer'],
: ,
})
}
return (
<
={.}
={}
="button"
>
{. ? 'Granting...' : 'Grant Issuer Role'}
</> {}
)
}import { , } from 'wagmi'
import { }
import React from 'react'
import { } from 'wagmi/tempo'
import { } from 'viem'
export function () {
const = '0x...' // Your token address
const { : , :
..({ : })
const = ..({
: { : () =>
})
const = () => {
.({
: ,
: ('1000', ?. || 6),
})
}
return (
<
={.}
={}
="button"
>
{. ? 'Setting...' : 'Set Cap'}
</> {}
)
}import { , } from 'wagmi'
import { }
import React from 'react'
import { } from 'wagmi/tempo'
export function () {
const = '0x...' // Your token address
const = ..({
: {
() {
// Store policyId for the next step
.('Policy ID:', .)
},
},
})
const = async () => {
await .({
: [
'0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
],
: 'blacklist',
})
}
return (
<
={.}
={}
="button"
>
{. ? 'Creating...' : 'Create Policy'}
</> {}
)
}import React from 'react'
import { } from 'wagmi/tempo'
export function () {
const = '0x...' // Your token address
import { , } from 'wagmi'
import { }
import React from 'react'
import { } from 'wagmi/tempo'
export function () {
const = '0x...' // Your token address
const { : , :
..({ : })
const = ..({
: { : () =>
})
const = ..({
: { : () =>
})
const = ?. || false
const = () => {
if () {
.({
: ,
})
} else {
.({
: ,
})
}
}
const = . || .
return (
<
={}
={}
="button"
>
{ ? 'Processing...' : ? 'Unpause' : 'Pause'}
</> {}
)
}import { , } from 'wagmi'
import { }
import React from 'react'
import { } from 'wagmi/tempo'
import { } from 'viem'
export function () {
const = '0x...' // Your token address
const = '0x...' // The blocked address to burn tokens from
const { : } = ..
: ,
})
const = ..()
const = async () => {
if (!) return
await .({
: ,
: ,
: ('100', .),
})
}
return (
<
={.}
={}
="button"
>
{. ? 'Burning...' : 'Burn Blocked Tokens'}
</> {}
)
}import { , } from 'wagmi'
import { }
import React from 'react'
import { } from 'wagmi/tempo'
import { } from '@tanstack/react-query'
export function () {
const = ()
const = '0x...' // Your token address
const = '0x...' // Address to grant the issuer role
// Grant the issuer role
const = ..({
: {
() {
.({ : ['hasRole'] })
},
},
})
const = async () => {
await .({
: ,
: ['issuer'],
: ,
})
}
const { : } = ..
: ,
: ,
: 'issuer',
})
return (
<>
<
={.}
={}
="button"
>
{. ? 'Granting...' : 'Grant Issuer Role'}
</>
{ !== && (
<>
Treasury { ? 'has' : 'does not have'} the issuer role // [!code ++]
</> {}
)}
</>
)
}import { , } from 'wagmi'
import { }
import React from 'react'
import { } from 'wagmi/tempo'
import { } from '@tanstack/react-query'
export function () {
const = ()
const = '0x...' // Your token address
const = '0x...' // Address to grant/revoke the issuer role
// Grant the issuer role
const = ..({
: {
() {
.({ : ['hasRole'] })
},
},
})
const = async () => {
await .({
: ,
: ['issuer'],
: ,
})
}
// Check if the treasury has the issuer role
const { : } = ..
: ,
: ,
: 'issuer',
})
// Revoke the issuer role
const = ..({
: {
() {
.({ : ['hasRole'] })
},
},
})
const = async () => {
await .({
: ,
: ['issuer'],
: ,
})
}
return (
<>
<
={.}
={}
="button"
>
{. ? 'Granting...' : 'Grant Issuer Role'}
</>
<
={. || !}
={}
="button"
>
{. ? 'Revoking...' : 'Revoke Issuer Role'}
</>
{ !== && (
<>
Treasury { ? 'has' : 'does not have'} the issuer role
</>
)}
</>
)
}import { , } from 'wagmi'
import { }