Skip to content

Commit

Permalink
Get sovereign account balance in destination and KSM in Kusama Asset …
Browse files Browse the repository at this point in the history
…Hub (#339)

* -wip- initial commit get sovereign account balances and validate transfer amount

* add variable names to alert message

* consider if destination is relay or not to use corresponding sovereign account address

* add destinationFee in source config return to use it in sovereign balance validation

* do validation only for asset hub and remove logs

* remove comment

* add isRelay flag

* Update packages/sdk/src/getTransferData/getTransferData.utils.ts

Co-authored-by: elmar <[email protected]>

* add flag for checking sovereign account balances

* update snapshots

* add changeset

* change back DED fee token

* add KSM to AssetHub configuration

* update changeset

* update snaps

---------

Co-authored-by: elmar <[email protected]>
  • Loading branch information
mmaurello and ekenigs authored Oct 9, 2024
1 parent 046e9a6 commit 6e543ce
Show file tree
Hide file tree
Showing 14 changed files with 331 additions and 116 deletions.
8 changes: 8 additions & 0 deletions .changeset/smooth-ghosts-judge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@moonbeam-network/xcm-config': minor
'@moonbeam-network/xcm-types': minor
'@moonbeam-network/xcm-sdk': minor
'@moonbeam-network/xcm-builder': patch
---

Add sovereign account balance checking
31 changes: 31 additions & 0 deletions packages/builder/src/extrinsic/pallets/polkadotXcm/polkadotXcm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,5 +182,36 @@ export function polkadotXcm() {
}),
};
},
trasferAssets: () => {
const func = 'transferAssets';

return {
here: (): ExtrinsicConfigBuilder => ({
build: (params) =>
new ExtrinsicConfig({
module: pallet,
func,
getArgs: (extrinsicFunction) =>
getPolkadotXcmExtrinsicArgs({
...params,
func: extrinsicFunction,
asset: [
{
id: {
Concrete: {
parents: 1,
interior: 'Here',
},
},
fun: {
Fungible: params.amount,
},
},
],
}),
}),
}),
};
},
};
}
5 changes: 5 additions & 0 deletions packages/config/src/chains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ export const alphanetRelay = new Parachain({
ecosystem: Ecosystem.AlphanetRelay,
genesisHash:
'0xe1ea3ab1d46ba8f4898b6b4b9c54ffc05282d299f89e84bd0fd08067758c9443',
isRelay: true,
isTestChain: true,
key: 'alphanet-relay',
name: 'Alphanet Relay',
Expand Down Expand Up @@ -640,6 +641,7 @@ export const kusama = new Parachain({
ecosystem: Ecosystem.Kusama,
genesisHash:
'0xb0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe',
isRelay: true,
key: 'kusama',
name: 'Kusama',
parachainId: 0,
Expand Down Expand Up @@ -669,6 +671,7 @@ export const kusamaAssetHub = new Parachain({
metadataId: 9999999,
},
],
checkSovereignAccountBalances: true,
ecosystem: Ecosystem.Kusama,
genesisHash:
'0x48239ef607d7928874027a43a67689209727dfb3d3dc5e5b03a39bdc2eda771a',
Expand Down Expand Up @@ -1690,6 +1693,7 @@ export const polkadot = new Parachain({
ecosystem: Ecosystem.Polkadot,
genesisHash:
'0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3',
isRelay: true,
key: 'polkadot',
name: 'Polkadot',
parachainId: 0,
Expand Down Expand Up @@ -1744,6 +1748,7 @@ export const polkadotAssetHub = new Parachain({
palletInstance: 50,
},
],
checkSovereignAccountBalances: true,
ecosystem: Ecosystem.Polkadot,
genesisHash:
'0x68d56f15f85d3136970ec16946040bc1752654e906147f7e43e9d539d7c3de2f',
Expand Down
18 changes: 18 additions & 0 deletions packages/config/src/configs/kusamaAssetHub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,24 @@ export const kusamaAssetHubConfig = new ChainConfig({
},
min: AssetMinBuilder().assets().asset(),
}),
new AssetConfig({
asset: ksm,
balance: BalanceBuilder().substrate().system().account(),
destination: moonriver,
destinationFee: {
amount: FeeBuilder().xcmPaymentApi().xcmPaymentFee({
isAssetReserveChain: false,
}),
asset: ksm,
balance: BalanceBuilder().substrate().system().account(),
},
extrinsic: ExtrinsicBuilder().polkadotXcm().trasferAssets().here(),
fee: {
asset: ksm,
balance: BalanceBuilder().substrate().system().account(),
xcmDeliveryFeeAmount,
},
}),
],
chain: kusamaAssetHub,
});
1 change: 1 addition & 0 deletions packages/config/src/configs/moonbeam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,7 @@ export const moonbeamConfig = new ChainConfig({
amount: 0.2,
asset: usdt,
balance: BalanceBuilder().substrate().assets().account(),
destinationBalance: BalanceBuilder().substrate().system().account(),
},
fee: {
asset: glmr,
Expand Down
15 changes: 15 additions & 0 deletions packages/config/src/configs/moonriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,21 @@ export const moonriverConfig = new ChainConfig({
balance: BalanceBuilder().substrate().system().account(),
},
}),
new AssetConfig({
asset: ksm,
balance: BalanceBuilder().substrate().assets().account(),
contract: ContractBuilder().Xtokens().transfer(),
destination: kusamaAssetHub,
destinationFee: {
amount: 0.0003,
asset: ksm,
balance: BalanceBuilder().substrate().assets().account(),
},
fee: {
asset: movr,
balance: BalanceBuilder().substrate().system().account(),
},
}),
new AssetConfig({
asset: mgx,
balance: BalanceBuilder().substrate().assets().account(),
Expand Down
1 change: 1 addition & 0 deletions packages/config/src/types/AssetConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface AssetConfigConstructorParams {

export interface DestinationFeeConfig extends FeeAssetConfig {
amount: number | FeeConfigBuilder;
destinationBalance?: BalanceConfigBuilder;
}

export interface FeeAssetConfig {
Expand Down
68 changes: 66 additions & 2 deletions packages/sdk/src/getTransferData/getDestinationData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
import { FeeConfigBuilder } from '@moonbeam-network/xcm-builder';
import { TransferConfig } from '@moonbeam-network/xcm-config';
import { AssetAmount } from '@moonbeam-network/xcm-types';
import { toBigInt } from '@moonbeam-network/xcm-utils';
import {
getSovereignAccountAddresses,
toBigInt,
} from '@moonbeam-network/xcm-utils';
import { PolkadotService } from '../polkadot';
import { DestinationChainTransferData } from '../sdk.interfaces';
import { getBalance, getDecimals, getMin } from './getTransferData.utils';
Expand Down Expand Up @@ -35,11 +38,13 @@ export async function getDestinationData({

const balance = await getBalance({
address: destinationAddress,
asset: config.asset,
balanceBuilder: config.balance,
chain,
config,
decimals: zeroAmount.decimals,
polkadot,
});

const min = await getMin(config, polkadot);

const balanceAmount = zeroAmount.copyWith({ amount: balance });
Expand All @@ -51,12 +56,20 @@ export async function getDestinationData({
polkadot,
});
const minAmount = zeroAmount.copyWith({ amount: min });

return {
balance: balanceAmount,
chain,
existentialDeposit,
fee: feeAmount,
min: minAmount,
sovereignAccountBalances: chain.checkSovereignAccountBalances
? await getSovereignAccountBalances({
decimals: zeroAmount.decimals,
polkadot,
transferConfig,
})
: undefined,
};
}

Expand Down Expand Up @@ -97,3 +110,54 @@ export async function getFee({
amount: await cfg.call(),
});
}

interface GetSovereignAccountBalancesProps {
transferConfig: TransferConfig;
decimals: number;
polkadot: PolkadotService;
}

async function getSovereignAccountBalances({
transferConfig,
decimals,
polkadot,
}: GetSovereignAccountBalancesProps) {
const {
destination: { chain, config },
source: { config: sourceConfig },
} = transferConfig;
const sovereignAccountAddresses = getSovereignAccountAddresses(
transferConfig.source.chain.parachainId,
);

const destinationFeeAssetBalance =
sourceConfig.destinationFee?.destinationBalance;

const sovereignAccountAddress = chain.isRelay
? sovereignAccountAddresses.relay
: sovereignAccountAddresses.generic;

const sovereignAccountBalance = await getBalance({
address: sovereignAccountAddress,
asset: config.asset,
balanceBuilder: config.balance,
chain,
decimals,
polkadot,
});

const sovereignAccountFeeAssetBalance = destinationFeeAssetBalance
? await getBalance({
address: sovereignAccountAddress,
asset: sourceConfig.destinationFee.asset,
balanceBuilder: destinationFeeAssetBalance,
chain,
decimals, // TODO this is not correct but will only affect us if a chain has both checkSovereignAccountBalances and usesChainDecimals flags
polkadot,
})
: undefined;
return {
feeAssetBalance: sovereignAccountFeeAssetBalance,
transferAssetBalance: sovereignAccountBalance,
};
}
13 changes: 8 additions & 5 deletions packages/sdk/src/getTransferData/getSourceData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {
import { PolkadotService } from '../polkadot';
import { EvmSigner, SourceChainTransferData } from '../sdk.interfaces';
import {
GetBalancesParams,
BaseParams,
getBalance,
getDecimals,
getMin,
Expand Down Expand Up @@ -112,8 +112,9 @@ export async function getSourceData({

const balance = await getBalance({
address: sourceAddress,
asset: config.asset,
balanceBuilder: config.balance,
chain,
config,
decimals: zeroAmount.decimals,
polkadot,
});
Expand Down Expand Up @@ -197,6 +198,7 @@ export async function getSourceData({
return {
balance: balanceAmount,
chain,
destinationFee,
destinationFeeBalance: destinationFeeBalanceAmount,
existentialDeposit,
fee: feeAmount,
Expand All @@ -206,10 +208,10 @@ export async function getSourceData({
};
}

export interface GetFeeBalanceParams
extends Omit<GetBalancesParams, 'config' | 'evmSigner'> {
export interface GetFeeBalanceParams extends BaseParams {
balance: bigint;
feeConfig: FeeAssetConfig | undefined;
decimals: number;
}

export async function getFeeBalance({
Expand Down Expand Up @@ -456,8 +458,9 @@ export async function getAssetsBalances({
// eslint-disable-next-line no-await-in-loop
const balance = await getBalance({
address,
asset: asset.asset,
balanceBuilder: asset.balance,
chain,
config: asset,
decimals,
polkadot,
});
Expand Down
8 changes: 8 additions & 0 deletions packages/sdk/src/getTransferData/getTransferData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from '../sdk.interfaces';
import { getDestinationData } from './getDestinationData';
import { getSourceData } from './getSourceData';
import { validateSovereignAccountBalances } from './getTransferData.utils';

export interface GetTransferDataParams extends Partial<Signers> {
configService: IConfigService;
Expand Down Expand Up @@ -60,6 +61,7 @@ export async function getTransferData({
const bigAmount = Big(
toBigInt(amount, source.balance.decimals).toString(),
);

const result = bigAmount.minus(
source.balance.isSame(destinationFee) ? destinationFee.toBig() : Big(0),
);
Expand Down Expand Up @@ -93,6 +95,12 @@ export async function getTransferData({
},
async transfer(amount): Promise<string> {
const bigintAmount = toBigInt(amount, source.balance.decimals);
validateSovereignAccountBalances({
amount: bigintAmount,
destination,
source,
});

const {
asset,
source: { chain, config },
Expand Down
Loading

0 comments on commit 6e543ce

Please sign in to comment.