Pallet Token Gateway
This is an ISMP module that allows standalone chains or parachains send and receive cross chain asset transfers.
Config
Let's look at the pallet specific components of the configuration trait:
Dispatcher
: The should be an implementation of theIsmpDispatcher
, it will be used by this pallet dispatch cross-chain requests.Assets
: This type should be configured with a component that implements the following interfaces, typically this will bepallet-assets
Currency
: This type should be configured with a component that implementsCurrency
interface, typicallypallet-balances
.AssetAdmin
: This pallet has some functionality for creating new assets. The account configured for this type would be the asset admin and also be responsible for paying the asset registration fees, therefore it should be funded before attempting to create any assets.AssetIdFactory
: This type should be configured with a component that implementspallet_token_gateway::types::CreateAssetId
. It should return a unique asset id each time theAssetIdFactory::create_asset_id
is called.NativeAssetId
: A constant value that represents the identifier of the native asset.Decimals
: A constant that represents the precision of the native currency.
Calls
teleport
: This call is used to initialize a cross-chain asset transfer. Any provided assets are custodied by the pallet and a cross-chain request is dispatched to the destination chain.set_token_gateway_addresses
: This priviledged call is used to set the token gateway address for EVM chains.create_erc6160_asset
: This call dispatches a request to Hyperbridge to create multi chain native assets on token gateway deploymentsupdate_erc6160_asset
: This call dispatches a request to Hyperbridge to update multi chain native assets on token gateway deployments
Priviledged calls must be dispatched by AdminOrigin
configured in pallet-ismp
.
Integrating the pallet into the Runtime
The first step is to implement the pallet config for the runtime.
use frame_support::parameter_types;
use ismp::module::IsmpModule;
use ismp::router::IsmpRouter;
parameter_types! {
// A constant that should represent the native asset id, this id must be unique to the native currency
pub const NativeAssetId: u32 = 0;
// Set the correct decimals for the native currency
pub const Decimals: u8 = 12;
}
/// Should provide an account that is funded and can be used to pay for asset creation
pub struct AssetAdmin;
impl Get<AccountId> for AssetAdmin {
fn get() -> AccountId {
Treasury::account_id()
}
}
impl pallet_token_gateway::Config for Runtime {
// configure the runtime event
type RuntimeEvent = RuntimeEvent;
// Configured as Pallet Ismp
type Dispatcher = Ismp;
// Configured as Pallet Assets
type Assets = Assets;
// Configured as Pallet balances
type Currency = Balances;
// AssetAdmin account
type AssetAdmin = AssetAdmin;
// The Native asset Id
type NativeAssetId = NativeAssetId;
// A type that provides a function for creating unique asset ids
// A concrete implementation for your specific runtime is required
type AssetIdFactory = ();
// The precision of the native asset
type Decimals = Decimals;
}
// Add the token gateway pallet to your ISMP router
#[derive(Default)]
struct Router;
impl IsmpRouter for Router {
fn module_for_id(&self, id: Vec<u8>) -> Result<Box<dyn IsmpModule>, anyhow::Error> {
let module = match id.as_slice() {
id if TokenGateway::is_token_gateway(&id) => Box::new(TokenGateway::default()),
_ => Err(Error::ModuleNotFound(id))?
};
Ok(module)
}
}
Setting up Token Gateway
Setting up token gateway for use involves a few simple steps.
-
Registering token gateway addresses on EVM chains
The pallet needs to know the addresses of the token gateway contracts on EVM chains, so it can validate the source of incoming messages.
This requires dispatching theset_token_gateway_addresses
extrinsic fromAdminOrigin
configured inpallet-ismp
.
This call accepts a map ofStateMachine
toVec<u8>
, this is only neccessary for validating messages coming from EVM chains, all substrate chains use a static token gateway address. Find the required addresses here -
Registering assets on token gateway deployments
For transfer of the native currency and other assets issued on your chain through token gateway, those assets need to be registered on the token gateway asset registry on hyperbridge The process of registering assets involves dispatching a request to create the asset on hyperbridge after which hyperbridge dispatches requests to deploy the asset on all chains specified in the initial request.The types involved in asset creation are described below:
pub struct GatewayAssetRegistration {
/// The asset name
pub name: BoundedVec<u8, ConstU32<20>>,
/// The asset symbol
pub symbol: BoundedVec<u8, ConstU32<20>>,
/// The list of chains to create the asset on
pub chains: Vec<StateMachine>,
/// Minimum balance for the asset, for substrate chains,
pub minimum_balance: Option<u128>,
}
pub struct AssetRegistration<AssetId> {
/// The asset must exist locally
pub local_id: AssetId,
/// Asset metadata
pub reg: GatewayAssetRegistration,
}
To register assets on token gateway you need to dispatch the create_erc6160_asset
extrinsic with an AssetRegistration<AssetId>
object.
The former contains the local asset id and the asset metadata.
GatewayAssetRegistration
This is the core struct that holds the metadata of the asset you need to register.
name
: This should be the full name of the asset, it's limited to 20 characters.
symbol
: This is the ticker for the asset, also limited to 20 characters. The asset Id will be derived from the keccak256
hash of this value.
chains
: This is a vector of the chains you want this asset deployed. It should be only chains supported by hyperbridge network.
minimum_balance
: This value is only necessary when you intend to deploy this asset on a substrate chain. It represents the minimum amount of the asset that an account can hold on susbtrate based chains.
A local asset id must be provided for the asset so it ca be mapped to the token gateway asset id.
To register the native currency(pallet-balances) on token gateway you need to set the local_id
field in the AssetRegistration<AssetId>
to the same constant that was specified as the NativeAssetId
in the pallet config along with the required metadata.
Assets can also be updated in the same way by dispatching update_erc6160_asset
.
Asset Ids
Token gateway protocol represents assets ids with a 32 byte hash which is derived from the keccak256
hash of the asset's symbol.
Teleporting assets
To make a crosschain transfer the teleport
extrinsic should must be dispatched with the correct parameters.
pub struct TeleportParams<AssetId, Balance> {
/// Asset Id registered on Hyperbridge
pub asset_id: AssetId,
/// Destination state machine
pub destination: StateMachine,
/// Receiving account on destination
pub recepient: H256,
/// Amount to be sent
pub amount: Balance,
/// Request timeout
pub timeout: u64,
/// Token gateway address
pub token_gateway: Vec<u8>,
/// Relayer fee
pub relayer_fee: Balance,
}
Let's explore what each parameter holds:
asset_id
: The local asset id for the asset that should be transferreddestination
: The destination chain that should receive the fundsrecepient
: The beneficiary account for the funds on the destination. (For EVM chains, the address should be left padded with zeros to fit into the required 32 bytes.)amount
: The amount that should be transferred.timeout
: The request timeout, this is the time after which the request cannot be delivered to the destination. It should represent the cumulative time for finalization on the source chain and hyperbridge with some additional buffer.token_gateway
: The address of the token gateway module on the destination chain.relayer_fee
: The amount to be paid to relayers for delivering the request, a value of zero means the dispatcher is responsible for relaying the request.
Funds from undelivered requests can be recovered by submitting a timeout message for the request through pallet-ismp
.