Skip to content

Commit

Permalink
fix XCM transfers for Peaq EVM on Alphanet (#254)
Browse files Browse the repository at this point in the history
* add isEvmSigner to EvmParachain to handle peaq in the dapp

* get balances and decimals without signer

* remove evm signer from getSourceData

* add changeset

* --wip-- [skip ci]

* try to fix

* --wip-- [skip ci]

* --wip-- [skip ci]

* fix fee getters for Peaq EVM

* remove console.log

* --wip-- [skip ci]

* fix multilocation for peaq

* --wip-- [skip ci]

* uncomment DEV from Peaq EVM to Moonbase alpha

* fix peaq evm to moonbase aplha DEV transfer

* generate new changeset

* changes after the review

* remove optional
  • Loading branch information
Rihyx authored Jun 4, 2024
1 parent 12cd202 commit 6282815
Show file tree
Hide file tree
Showing 15 changed files with 347 additions and 159 deletions.
8 changes: 8 additions & 0 deletions .changeset/clever-grapes-tap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@moonbeam-network/xcm-builder': minor
'@moonbeam-network/xcm-config': minor
'@moonbeam-network/xcm-types': minor
'@moonbeam-network/xcm-sdk': minor
---

make Precompile XCM flow work for Peaq
6 changes: 4 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"cSpell.words": [
"Acala",
"aSEED",
"Astar",
"AUSD",
"aSEED",
"Darwinia",
"Derivated",
"Heiko",
Expand All @@ -19,6 +19,7 @@
"Litentry",
"mangata",
"mnemonic",
"multilocation",
"nodle",
"parachain",
"parachains",
Expand All @@ -29,7 +30,8 @@
"Robonomics",
"Shiden",
"Suri",
"TEER"
"TEER",
"Viem"
],
"editor.defaultFormatter": "rvest.vs-code-prettier-eslint",
"editor.formatOnPaste": false,
Expand Down
21 changes: 21 additions & 0 deletions packages/builder/src/balance/BalanceBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
PalletBalancesAccountData,
} from '@polkadot/types/lookup';
import { isString } from '@polkadot/util';
import { evmToAddress } from '@polkadot/util-crypto';
import { ContractConfig } from '../contract';
import { SubstrateQueryConfig } from '../types/substrate/SubstrateQueryConfig';
import {
Expand Down Expand Up @@ -128,6 +129,26 @@ function system() {
},
}),
}),
accountEvmTo32: (): BalanceConfigBuilder => ({
build: ({ address }) => {
const substrateAddress = evmToAddress(address);

return new SubstrateQueryConfig({
module: 'system',
func: 'account',
args: [substrateAddress],
transform: async (
response: FrameSystemAccountInfo,
): Promise<bigint> => {
const balance = response.data as PalletBalancesAccountData &
PalletBalancesAccountDataOld;
const frozen = balance.miscFrozen ?? balance.frozen;

return BigInt(balance.free.sub(frozen).toString());
},
});
},
}),
};
}

Expand Down
47 changes: 46 additions & 1 deletion packages/builder/src/contract/contracts/Xtokens/Xtokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { AnyChain } from '@moonbeam-network/xcm-types';
import { formatAssetIdToERC20 } from '@moonbeam-network/xcm-utils';
import { isString, u8aToHex } from '@polkadot/util';
import { decodeAddress } from '@polkadot/util-crypto';
import { decodeAddress, evmToAddress } from '@polkadot/util-crypto';
import { ContractConfigBuilder } from '../../ContractBuilder.interfaces';
import { ContractConfig } from '../../ContractConfig';

Expand Down Expand Up @@ -42,6 +42,26 @@ export function Xtokens() {
module: 'Xtokens',
}),
}),
transferWithEvmTo32: (weight = U_64_MAX): ContractConfigBuilder => ({
build: ({ address, amount, asset, destination }) => {
const multilocation =
getDestinationMultilocationForPrecompileDestination(
address,
destination,
);

return new ContractConfig({
args: [
isString(asset) ? formatAssetIdToERC20(asset) : asset,
amount,
multilocation,
weight,
],
func: 'transfer',
module: 'Xtokens',
});
},
}),
};
}

Expand Down Expand Up @@ -78,6 +98,31 @@ type DestinationMultilocation = [
),
];

function getDestinationMultilocationForPrecompileDestination(
address: string,
destination: AnyChain,
): DestinationMultilocation {
/*
01: AccountId32
03: AccountKey20
https://docs.moonbeam.network/builders/interoperability/xcm/xc20/xtokens/#building-the-precompile-multilocation
*/
const accountType = '01';
const substrateAddress = evmToAddress(address);
const acc = `0x${accountType}${u8aToHex(
decodeAddress(substrateAddress),
-1,
false,
)}00`;

return [
1,
destination.parachainId
? [`0x0000000${destination.parachainId.toString(16)}`, acc]
: [acc],
];
}

function getDestinationMultilocation(
address: string,
destination: AnyChain,
Expand Down
11 changes: 11 additions & 0 deletions packages/config/src/chains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,7 @@ export const moonbaseAlpha = new EvmParachain({
genesisHash:
'0x91bc6e169807aaa54802737e1c504b2577d4fafedd5a02c10293b1cd60e39527',
id: 1287,
isEvmSigner: true,
isTestChain: true,
key: 'moonbase-alpha',
name: 'Moonbase Alpha',
Expand Down Expand Up @@ -1002,6 +1003,7 @@ export const moonbeam = new EvmParachain({
genesisHash:
'0xfe58ea77779b7abda7da4ec526d14db9b1e9cd40a217c34892af80a9b332b76d',
id: 1284,
isEvmSigner: true,
key: 'moonbeam',
name: 'Moonbeam',
nativeCurrency: {
Expand Down Expand Up @@ -1122,6 +1124,7 @@ export const moonriver = new EvmParachain({
genesisHash:
'0x401a1f9dca3da46f5c4091016c8a2f26dcea05865116b286f60f668207d1474b',
id: 1285,
isEvmSigner: true,
key: 'moonriver',
name: 'Moonriver',
nativeCurrency: {
Expand Down Expand Up @@ -1263,6 +1266,10 @@ export const peaqAlphanet = new Parachain({

export const peaqEvmAlphanet = new EvmParachain({
assetsData: [
{
asset: agng,
decimals: 18,
},
{
asset: dev,
decimals: 18,
Expand All @@ -1276,10 +1283,14 @@ export const peaqEvmAlphanet = new EvmParachain({
metadataId: 0,
},
],
contracts: {
Xtokens: '0x0000000000000000000000000000000000000803',
},
ecosystem: Ecosystem.AlphanetRelay,
genesisHash:
'0x2dfcd5c560f6db1667cbc2bc3791dfd337f88f400af6de39b1b8638ee7af6ed4',
id: 9990,
isEvmSigner: true,
isTestChain: true,
key: 'peaq-evm-Alphanet',
name: 'Peaq EVM Alphanet',
Expand Down
4 changes: 2 additions & 2 deletions packages/config/src/configs/moonbaseAlpha.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ export const moonbaseAlphaConfig = new ChainConfig({
new AssetConfig({
asset: dev,
balance: BalanceBuilder().substrate().system().account(),
contract: ContractBuilder().Xtokens().transfer(),
contract: ContractBuilder().Xtokens().transferWithEvmTo32(),
destination: peaqEvmAlphanet,
destinationFee: {
amount: 0.00000001,
Expand All @@ -321,7 +321,7 @@ export const moonbaseAlphaConfig = new ChainConfig({
new AssetConfig({
asset: ftmwh,
balance: BalanceBuilder().evm().erc20(),
contract: ContractBuilder().Xtokens().transfer(),
contract: ContractBuilder().Xtokens().transferWithEvmTo32(),
destination: peaqEvmAlphanet,
destinationFee: {
amount: 0.01,
Expand Down
44 changes: 30 additions & 14 deletions packages/config/src/configs/peaqEvmAlphanet.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BalanceBuilder } from '@moonbeam-network/xcm-builder';
import { dev, ftmwh } from '../assets';
import { BalanceBuilder, ContractBuilder } from '@moonbeam-network/xcm-builder';
import { agng, dev, ftmwh } from '../assets';
import { moonbaseAlpha, peaqEvmAlphanet } from '../chains';
import { AssetConfig } from '../types/AssetConfig';
import { ChainConfig } from '../types/ChainConfig';
Expand All @@ -9,33 +9,49 @@ export const peaqEvmAlphanetConfig = new ChainConfig({
new AssetConfig({
asset: ftmwh,
balance: BalanceBuilder().evm().erc20(),
// contract: ContractBuilder().Xtokens().transfer(),
contract: ContractBuilder().Xtokens().transferMultiCurrencies(),
destination: moonbaseAlpha,
destinationFee: {
amount: 0.01,
asset: ftmwh,
asset: dev,
balance: BalanceBuilder().evm().erc20(),
},
// fee: {
// asset: dev,
// balance: BalanceBuilder().substrate().system().account(),
// },
fee: {
asset: agng,
balance: BalanceBuilder().substrate().system().accountEvmTo32(),
},
}),
new AssetConfig({
asset: dev,
balance: BalanceBuilder().evm().erc20(),
// contract: ContractBuilder().Xtokens().transfer(),
contract: ContractBuilder().Xtokens().transfer(),
destination: moonbaseAlpha,
destinationFee: {
amount: 0.01,
asset: ftmwh,
asset: dev,
balance: BalanceBuilder().evm().erc20(),
},
// fee: {
// asset: dev,
// balance: BalanceBuilder().substrate().system().account(),
// },
fee: {
asset: agng,
balance: BalanceBuilder().substrate().system().accountEvmTo32(),
},
}),

// new AssetConfig({
// asset: agng,
// balance: BalanceBuilder().substrate().system().accountEvmTo32(),
// contract: ContractBuilder().Xtokens().transferMultiCurrencies(),
// destination: moonbaseAlpha,
// destinationFee: {
// amount: 0.01,
// asset: dev,
// balance: BalanceBuilder().evm().erc20(),
// },
// fee: {
// asset: agng,
// balance: BalanceBuilder().substrate().system().account(),
// },
// }),
],
chain: peaqEvmAlphanet,
});
11 changes: 9 additions & 2 deletions packages/sdk/src/contract/contract.factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,19 @@ import { Erc20Public } from './contracts/Erc20/Erc20Public';
export function createContractWithSigner(
config: ContractConfig,
signer: EvmSigner,
chain?: AnyChain,
): TransferContractInterface | BalanceContractInterface {
if (config.module === 'Erc20') {
return new Erc20(config, signer);
}

if (config.module === 'Xtokens') {
if (chain && 'contracts' in chain) {
const address = chain?.contracts?.Xtokens;

return new Xtokens(config, signer, address);
}

return new Xtokens(config, signer);
}

Expand All @@ -37,9 +44,9 @@ export function createContractWithoutSigner(
export function createContract(
config: ContractConfig,
signer: EvmSigner | undefined,
chain?: AnyChain,
chain: AnyChain,
): TransferContractInterface | BalanceContractInterface {
return signer
? createContractWithSigner(config, signer)
? createContractWithSigner(config, signer, chain)
: createContractWithoutSigner(config, chain as EvmParachain);
}
11 changes: 8 additions & 3 deletions packages/sdk/src/contract/contracts/Xtokens/Xtokens.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ContractConfig } from '@moonbeam-network/xcm-builder';
import { Contract, TransactionResponse } from 'ethers';
import {
Address,
GetContractReturnType,
PublicClient,
WriteContractReturnType,
Expand All @@ -16,19 +17,24 @@ import abi from './XtokensABI.json';
type XtokensContract = GetContractReturnType<typeof abi, PublicClient>;

export class Xtokens implements TransferContractInterface {
readonly address = '0x0000000000000000000000000000000000000804';
readonly defaultMoonChainAddress =
'0x0000000000000000000000000000000000000804';

readonly address: Address;

readonly #config: ContractConfig;

readonly #contract: Contract | XtokensContract;

readonly #signer: EvmSigner;

constructor(config: ContractConfig, signer: EvmSigner) {
constructor(config: ContractConfig, signer: EvmSigner, address?: Address) {
this.#config = config;

this.#signer = signer;

this.address = address ?? this.defaultMoonChainAddress;

this.#contract = isEthersSigner(signer)
? new Contract(this.address, abi, signer)
: getContract({
Expand Down Expand Up @@ -84,7 +90,6 @@ export class Xtokens implements TransferContractInterface {
} catch (error) {
// eslint-disable-next-line no-console
console.error(error);

throw new Error(
"Can't get a fee. Make sure that you have enough balance!",
);
Expand Down
Loading

0 comments on commit 6282815

Please sign in to comment.