Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add page on sending ERC-20s via XCM #582

Merged
merged 38 commits into from
Apr 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
b577be3
add send erc20 docs
eshaben Mar 10, 2023
b23186e
compress images
eshaben Mar 10, 2023
fc92484
minor update
eshaben Mar 10, 2023
8927990
move checking prereqs
eshaben Mar 10, 2023
d03c438
minor fix for consistency
eshaben Mar 10, 2023
761d019
update meta description
eshaben Mar 13, 2023
cb6f2e6
add section on registering an erc20 on another chain
eshaben Apr 20, 2023
3a95902
Merge remote-tracking branch 'origin' into eshaben/rt2200-xcm
eshaben Apr 20, 2023
0203d16
use polkadot.js api and update to xcm v3
eshaben Apr 20, 2023
ba4adf4
fix amount
eshaben Apr 20, 2023
8c6c3c6
remove unused image
eshaben Apr 20, 2023
8601c09
account for optional network parameter
eshaben Apr 20, 2023
0d212ae
some refactoring
albertov19 Apr 21, 2023
1fbc8e2
clean up a bit
eshaben Apr 22, 2023
8a1431e
Merge branch 'eshaben/rt2200-xcm' of github.com:PureStake/moonbeam-do…
eshaben Apr 22, 2023
2206907
rename images
eshaben Apr 22, 2023
0b4370f
stick to one name
eshaben Apr 22, 2023
bfb2a8a
Merge remote-tracking branch 'origin' into eshaben/rt2200-xcm
eshaben Apr 22, 2023
24edaa3
update related xcm docs for local xc-20s
eshaben Apr 22, 2023
93bd912
add links
eshaben Apr 22, 2023
1218a80
minor changes
albertov19 Apr 24, 2023
77586cc
remove tables from polkadot.js api section
eshaben Apr 24, 2023
0934087
remove extra pages and condense content into oveview and send xc-20s …
eshaben Apr 25, 2023
51d227a
Merge branch 'eshaben/rt2200-xcm' of github.com:PureStake/moonbeam-do…
eshaben Apr 25, 2023
605a3b5
minor fixes
eshaben Apr 25, 2023
54aae91
use numbered steps
eshaben Apr 25, 2023
c492b50
minor fix
eshaben Apr 25, 2023
0d23e26
minor fixes and remove unused snippets
eshaben Apr 26, 2023
22d68bc
remove unused snippet
eshaben Apr 26, 2023
6b8519b
add snippets and update existing snippets
eshaben Apr 26, 2023
30f51a1
add snippet for retrieving xc20s
eshaben Apr 26, 2023
60bb2e5
disconnect api
eshaben Apr 26, 2023
4650a48
last changes
albertov19 Apr 27, 2023
28de5cb
coments and merge
albertov19 Apr 27, 2023
4990b68
Apply suggestions from code review
eshaben Apr 27, 2023
98d7bce
update snippet paths
eshaben Apr 27, 2023
50b2918
Revert "update snippet paths"
eshaben Apr 27, 2023
1941adf
minor changes
eshaben Apr 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .snippets/code/xc20/retrieve-xc20s.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { ApiPromise, WsProvider } from '@polkadot/api'; // Version 9.13.6

const getXc20s = async () => {
// 1. Create API provider
const substrateProvider = new WsProvider(
'wss://wss.api.moonbase.moonbeam.network'
);
const api = await ApiPromise.create({ provider: substrateProvider });

// 2. Query the assets pallet for all assets
const assets = await api.query.assets.asset.entries();

// 3. Get metadata for each asset using the ID
assets.forEach(
async ([
{
args: [id],
},
]) => {
const metadata = await api.query.assets.metadata(id);
console.log(`Asset ID: ${id}`);
console.log(`Metadata: ${metadata}`);
console.log('-----');
}
);

api.disconnect();
};

getXc20s();
73 changes: 73 additions & 0 deletions .snippets/code/xtokens/ethers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import abi from './xtokensABI.js'; // Import the x-tokens ABI
import { ethers } from 'ethers'; // Import Ethers library
const PRIVATE_KEY = 'YOUR_PRIVATE_KEY_HERE';

// Create Ethers wallet & contract instance
const provider = new ethers.providers.JsonRpcProvider(
'https://rpc.api.moonbase.moonbeam.network'
);
const signer = new ethers.Wallet(PRIVATE_KEY, provider);
const xTokens = new ethers.Contract(
'0x0000000000000000000000000000000000000804',
abi,
signer
);

// xcUNIT address in Moonbase Alpha
const xcUNIT_ADDRESS = '0xFfFFfFff1FcaCBd218EDc0EbA20Fc2308C778080';

// Multilocation targeting Alice's account on the relay chain from Moonbase Alpha
const ALICE_RELAY_ACC = [
1,
['0x01c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300'],
];

// Sends 1 xcUNIT to the relay chain using the transfer function
async function transferToAlice() {
// Creates, signs, and sends the transfer transaction
const transaction = await xTokens.transfer(
xcUNIT_ADDRESS, // Asset
'1000000000000', // Amount
ALICE_RELAY_ACC, // Destination
'1000000000' // Weight
);

// Waits for the transaction to be included in a block
await transaction.wait();
console.log(transaction);
}

// Multilocation targeting the relay chain or its asset from a parachain
const RELAY_CHAIN_ASSET = [1, []];

// Sends 1 xcUNIT to the relay chain using the transferMultiasset function
async function transferMultiassetToAlice() {
const transaction = await xTokens.transferMultiasset(
RELAY_CHAIN_ASSET, // Asset
'1000000000000', // Amount
ALICE_RELAY_ACC, // Destination
'1000000000' // Weight
);
await transaction.wait();
console.log(transaction);
}

transferToAlice();
transferMultiassetToAlice();

// Here are some additional multilocations for the Asset multilocation:
const LOCAL_ASSET = [0, ['0x0424', '0x05FD9D0BF45A2947A519A741C4B9E99EB6']]; // Note that 0x0424 indicates the x-tokens pallet
const DEV_FROM_OTHER_PARACHAIN = [1, ['0x00000003E8', '0x0403']]; // Use if you were targeting DEV from a non-Moonbeam network

// Here are some additional multilocations for the Destination multilocation:
const ADDRESS32_OF_PARACHAIN = [
1,
[
'0x00000007EF',
'0x01c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300',
],
];
const ADDRESS20_FROM_PARACHAIN_TO_MOONBASE = [
1,
['0x00000003E8', '0x03f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac00'],
];
60 changes: 0 additions & 60 deletions .snippets/code/xtokens/ethersjs.md

This file was deleted.

40 changes: 40 additions & 0 deletions .snippets/code/xtokens/transfer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ApiPromise, WsProvider, Keyring } from '@polkadot/api'; // Version 9.13.6

// 1. Provide input data
const providerWsURL = 'wss://wss.api.moonbase.moonbeam.network';
const RELAY_ACC_ADDRESS =
'0xc4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a063'; // Alice's relay account address
const currencyId = {
ForeignAsset: {
ForeignAsset: 42259045809535163221576417993425387648n
}
};
const amount = 1000000000000n;
const dest = {
V3: {
parents: 1,
interior: { X1: { AccountId32: { id: RELAY_ACC_ADDRESS } } },
},
};
const destWeightLimit = { Unlimited: null };

// 2. Create Keyring instance
const keyring = new Keyring({ type: 'ethereum' });
const alice = keyring.addFromUri(PRIVATE_KEY);

const sendXc20 = async () => {
// 3. Create Substrate API provider
const substrateProvider = new WsProvider(providerWsURL);
const api = await ApiPromise.create({ provider: substrateProvider });

// 4. Craft the extrinsic
const tx = api.tx.xTokens.transfer(currencyId, amount, dest, destWeightLimit);

// 5. Send the transaction
const txHash = await tx.signAndSend(alice);
console.log(`Submitted with hash ${txHash}`);

api.disconnect();
};

sendXc20();
47 changes: 47 additions & 0 deletions .snippets/code/xtokens/transferMultiAsset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { ApiPromise, WsProvider, Keyring } from '@polkadot/api'; // Version 9.13.6

// 1. Provide input data
const providerWsURL = 'wss://wss.api.moonbase.moonbeam.network';
const RELAY_ACC_ADDRESS =
'0xc4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a063'; // Alice's relay account address
const asset = {
V3: {
id: {
Concrete: {
parents: 1,
interior: null,
},
},
fun: {
Fungible: { Fungible: 1000000000000n },
},
},
};
const dest = {
V3: {
parents: 1,
interior: { X1: { AccountId32: { id: RELAY_ACC_ADDRESS } } },
},
};
const destWeightLimit = { Unlimited: null };

// 2. Create Keyring instance
const keyring = new Keyring({ type: 'ethereum' });
const alice = keyring.addFromUri(PRIVATE_KEY);

const sendXc20 = async () => {
// 3. Create Substrate API provider
const substrateProvider = new WsProvider(providerWsURL);
const api = await ApiPromise.create({ provider: substrateProvider });

// 4. Craft the extrinsic
const tx = api.tx.xTokens.transferMultiasset(asset, dest, destWeightLimit);

// 5. Send the transaction
const txHash = await tx.signAndSend(alice);
console.log(`Submitted with hash ${txHash}`);

api.disconnect();
};

sendXc20();
44 changes: 27 additions & 17 deletions .snippets/code/xtokens/web3js.md → .snippets/code/xtokens/web3.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
```javascript
import abi from './xtokensABI.js'; // Import the x-tokens ABI
import Web3 from 'web3'; // Import Web3 library
const PRIVATE_KEY = 'YOUR_PRIVATE_KEY_HERE';
Expand All @@ -15,24 +14,27 @@ const xTokens = new web3.eth.Contract(
const xcUNIT_ADDRESS = '0xFfFFfFff1FcaCBd218EDc0EbA20Fc2308C778080';

// Multilocation targeting Alice's account on the relay chain from Moonbase Alpha
const ALICE_RELAY_ACC = [1, ['0x01c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300']];
const ALICE_RELAY_ACC = [
1,
['0x01c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300'],
];

// Sends 1 xcUNIT to the relay chain using the transfer function
async function transferToAlice() {
// Create transaction
const transferTx = xTokens.methods.transfer(
xcUNIT_ADDRESS, // Asset
'1000000000000', // Amount
ALICE_RELAY_ACC, // Destination
'1000000000' // Weight
xcUNIT_ADDRESS, // Asset
'1000000000000', // Amount
ALICE_RELAY_ACC, // Destination
'1000000000' // Weight
);

// Sign transaction
const signedTx = await web3.eth.accounts.signTransaction(
{
to: '0x0000000000000000000000000000000000000804',
data: transferTx.encodeABI(),
gas: await transferTx.estimateGas()
gas: await transferTx.estimateGas(),
},
PRIVATE_KEY
);
Expand All @@ -48,16 +50,16 @@ const RELAY_CHAIN_ASSET = [1, []];
// Sends 1 xcUNIT to the relay chain using the transferMultiasset function
async function transferMultiassetToAlice() {
const transferTx = xTokens.methods.transferMultiasset(
RELAY_CHAIN_ASSET, // Asset
'1000000000000', // Amount
ALICE_RELAY_ACC, // Destination
'1000000000' // Weight
RELAY_CHAIN_ASSET, // Asset
'1000000000000', // Amount
ALICE_RELAY_ACC, // Destination
'1000000000' // Weight
);
const signedTx = await web3.eth.accounts.signTransaction(
{
to: '0x0000000000000000000000000000000000000804',
data: transferTx.encodeABI(),
gas: await transferTx.estimateGas()
gas: await transferTx.estimateGas(),
},
PRIVATE_KEY
);
Expand All @@ -69,10 +71,18 @@ transferToAlice();
transferMultiassetToAlice();

// Here are some additional multilocations for the Asset multilocation:
const LOCAL_ASSET = [0, ["0x0424", "0x05FD9D0BF45A2947A519A741C4B9E99EB6"]]; // Note that 0x0424 indicates the x-tokens pallet
const DEV_FROM_OTHER_PARACHAIN = [1, ["0x00000003E8", "0x0403"]]; // Use if you were targeting DEV from a non-Moonbeam network
const LOCAL_ASSET = [0, ['0x0424', '0x05FD9D0BF45A2947A519A741C4B9E99EB6']]; // Note that 0x0424 indicates the x-tokens pallet
const DEV_FROM_OTHER_PARACHAIN = [1, ['0x00000003E8', '0x0403']]; // Use if you were targeting DEV from a non-Moonbeam network

// Here are some additional multilocations for the Destination multilocation:
const ADDRESS32_OF_PARACHAIN = [1, ["0x00000007EF", "0x01c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300"]];
const ADDRESS20_FROM_PARACHAIN_TO_MOONBASE = [1, ["0x00000003E8", "0x03f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac00"]];
```
const ADDRESS32_OF_PARACHAIN = [
1,
[
'0x00000007EF',
'0x01c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300',
],
];
const ADDRESS20_FROM_PARACHAIN_TO_MOONBASE = [
1,
['0x00000003E8', '0x03f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac00'],
];
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
```python
from web3 import Web3

abi = 'XTOKENS_ABI_HERE' # Paste or import the x-tokens ABI
Expand Down Expand Up @@ -36,7 +35,7 @@ def transferToAlice():
# Sign transaction
signedTx = web3.eth.account.sign_transaction(transferTx, privateKey)

# 7. Send tx and wait for receipt
# Send tx and wait for receipt
hash = web3.eth.send_raw_transaction(signedTx.rawTransaction)
receipt = web3.eth.wait_for_transaction_receipt(hash)
print(f'Tx successful with hash: { receipt.transactionHash.hex() }')
Expand Down Expand Up @@ -72,4 +71,3 @@ def transferMultiassetToAlice():
# Here are some additional multilocations for the Destination multilocation:
ADDRESS32_OF_PARACHAIN = [1, ["0x00000007EF", "0x01c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300"]]
ADDRESS20_FROM_PARACHAIN_TO_MOONBASE = [1, ["0x00000003E8", "0x03f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac00"]]
```
10 changes: 5 additions & 5 deletions .snippets/text/erc20-interface/erc20-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ The interface includes the following functions:
- **decimals()** — read-only function that returns the decimals of the token
- **totalSupply()** — read-only function that returns the total number of tokens in existence
- **balanceOf**(*address* who) — read-only function that returns the balance of the specified address
- **allowance**(*address* owner, *address* spender) — read-only function that checks and returns the amount of tokens that an owner is allowed to a spender
- **transfer**(*address* to, *uint256* value) — transfers a given amount of tokens to a specified address and returns true if the transfer was successful
- **approve**(*address* spender, *uint256* value) — approves the provided address to spend a specified amount of tokens on behalf of `msg.sender`. Returns true if successful
- **transferFrom**(*address* from, *address* to, *uint256* value) — transfers tokens from one given address to another given address and returns true if successful
- **allowance**(*address* owner, *address* spender) — read-only function that checks and returns the amount of tokens that a spender is allowed to spend on behalf of the owner
- **transfer**(*address* to, *uint256* value) — transfers a given amount of tokens to a specified address and returns `true` if the transfer was successful
- **approve**(*address* spender, *uint256* value) — approves the provided address to spend a specified amount of tokens on behalf of `msg.sender`. Returns `true` if successful
- **transferFrom**(*address* from, *address* to, *uint256* value) — transfers tokens from one given address to another given address and returns `true` if successful

!!! note
The ERC-20 standard does not specify the implications of multiple calls to `approve`. Changing an allowance with this function numerous times enables a possible attack vector. To avoid incorrect or unintended transaction ordering, you can first reduce the `spender` allowance to `0` and then set the desired allowance afterward. For more details on the attack vector, you can check out the [ERC-20 API: An Attack Vector on Approve/TransferFrom Methods](https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/edit#){target=_blank} overview
The ERC-20 standard does not specify the implications of multiple calls to `approve`. Changing an allowance with this function numerous times enables a possible attack vector. To avoid incorrect or unintended transaction ordering, you can first reduce the `spender` allowance to `0` and then set the desired allowance afterward. For more details on the attack vector, you can check out the [ERC-20 API: An Attack Vector on Approve/TransferFrom Methods](https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/edit#){target=_blank} overview.

The interface also includes the following required events:

Expand Down
3 changes: 0 additions & 3 deletions .snippets/text/xc-20/list-of-assets.md

This file was deleted.

4 changes: 0 additions & 4 deletions .snippets/text/xc-20/retrieve-metadata.md

This file was deleted.

Loading