Parachain Implementation Guide

Parachain Implementation Guide

This guide will go over the process for integrating the Saturn XCM configs in a parachain, so that it may receive and correctly interpret multisig calls coming from InvArch/Tinkernet.

How does Saturn work?

Saturn executes multisig calls in remote chains through XCM using the same Transact process as usual, the key difference is in how the XCM Origin and it's respective account id are derived.

Since we want to maintain a consistent UX across all connected chains, the main thing we have to tackle is the multisig account address, which should be the same in every chain (except for those that use different account id types).

We achieve this by avoiding hashing the account id and deriving a new one form that hash, so instead of sending our messages with the multisig account id, we send them with the multisig integer id, which is the source for deriving the account id.

By doing that, the message receiver chains are then able to derive the exact same account id on their side, avoiding rehashing and avoiding account impersonation concerns.

How to implement this custom derivation process?

This process consists of two simple XCM configs, one for the MultiLocation to Origin converter and one for the MultiLocation to AccountId converter, let's go over how to add them to a parachain:

1. Getting the XCM configs

You have two options for doing this: using a crate or defining them in your own runtime:

This is the easier method, but requires you to introduce another crate to your runtime. The XCM configs needed for Saturn are defined in the ORML XCM Builder crate (opens in a new tab) under the Open Web3 Stack GitHub Organization, here's how to set it all up:

This step should be fairly simple, just add the crate to your Cargo.toml and point it to the correct Substrate version for your runtime.

# For Kusama parachains
orml-xcm-builder-kusama = { git = "https://github.com/open-web3-stack/orml-xcm-builder", default-features = false, branch = "polkadot-v0.9.43" } # Or the Substrate version you'r runtime is on.
 
# For Polkadot parachains
# Soon!

2. Adding the converters to your XCM configs

Now all you have to do is add the configs for both the MultiLocation to AccountId and the MultiLocation to Origin converters in their respective type declarations.

āš ļø

Make sure to have them above any converter that might match with any MultiLocation, like XcmPassthrough for example.

ā„¹ļø

The example will have the types prefixed with the crate path (orml_xcm_builder_kusama::), if you defined them manually in your runtime you should use the path where they were defined.

pub type LocationToAccountId = (
	ParentIsPreset<AccountId>,
	SiblingParachainConvertsVia<Sibling, AccountId>,
	AccountId32Aliases<RelayNetwork, AccountId>,
+	// Mapping Tinkernet multisig to the correctly derived AccountId32.
+	orml_xcm_builder_kusama::TinkernetMultisigAsAccountId<AccountId>,
);
 
...
 
pub type XcmOriginToTransactDispatchOrigin = (
	SovereignSignedViaLocation<LocationToAccountId, RuntimeOrigin>,
	RelayChainAsNative<RelayOrigin, RuntimeOrigin>,
	SiblingParachainAsNative<cumulus_pallet_xcm::Origin, RuntimeOrigin>,
	SignedAccountId32AsNative<RelayNetwork, RuntimeOrigin>,
+	// Derives signed AccountId32 origins for Tinkernet multisigs.
+	orml_xcm_builder_kusama::TinkernetMultisigAsNativeOrigin<RuntimeOrigin>,
	XcmPassthrough<RuntimeOrigin>,
);

3. Setting up your barriers

It might be the case that your XCM config has strict barriers, in which case you might want to add a new barrier to allow Saturn Multisigs rather than allowing everything.

If you do want to safely allow everything, you would set up your barriers like this:

pub type Barrier = (
	AllowKnownQueryResponses<PolkadotXcm>,
	AllowSubscriptionsFrom<ParentOrSiblings>,
	AllowTopLevelPaidExecutionFrom<Everything>,
	TakeWeightCredit,
	WithComputedOrigin<
+		AllowTopLevelPaidExecutionFrom<Everything>,
		UniversalLocation,
		ConstU32<8>,
	>,
);

But if you want to restrict this barrier to only match Saturn Multisigs, simply change the Everything like so:

pub type Barrier = (
	AllowKnownQueryResponses<PolkadotXcm>,
	AllowSubscriptionsFrom<ParentOrSiblings>,
	AllowTopLevelPaidExecutionFrom<Everything>,
	TakeWeightCredit,
	WithComputedOrigin<
-		AllowTopLevelPaidExecutionFrom<Everything>,
+		AllowTopLevelPaidExecutionFrom<orml_xcm_builder_kusama::TinkernetMultisigMultiLocation>,
		UniversalLocation,
		ConstU32<8>,
	>,
);

And that's everything you need to set up in your XCM configs, your parachain should now be able to receive and interpret Saturn Multisig calls through XCM!