Skip to content

Instantly share code, notes, and snippets.

@MOZGIII
Created October 2, 2024 23:31
Show Gist options
  • Save MOZGIII/1fe5618aaea930bfa00fff06e24fa153 to your computer and use it in GitHub Desktop.
Save MOZGIII/1fe5618aaea930bfa00fff06e24fa153 to your computer and use it in GitHub Desktop.
// A helper script to verify runtime upgrade execution related to polkadot-v0.9.42.
//
// - download forked-chain-local by the following url
// `https://drive.google.com/drive/folders/1_xzDs9PUSWzMj0K-GpGrTKapq7Z4a76Y?usp=share_link`
//
// - run the peer
// `./target/release/humanode-peer --chain forked-chain-local.json --alice --tmp`
//
// - run the script passing wasm code path containing updated runtime spec version
import { ApiPromise, WsProvider } from "@polkadot/api";
import { Keyring } from "@polkadot/keyring";
import { readFile } from "fs/promises";
import { PrivateKeyAccount, privateKeyToAccount } from "viem/accounts";
import { arg } from "./lib/args.js";
import assert from "node:assert/strict";
import sendAndWait from "./lib/sendAndWait.js";
const prepareClaimMessageSignature = (
ethAccount: PrivateKeyAccount,
substrateAddress: Uint8Array,
) => {
const message =
"I hereby sign that I claim HMND to 0x" +
Buffer.from(substrateAddress).toString("hex") +
" on network with genesis " +
api.genesisHash.toHex() +
".";
return ethAccount.signMessage({ message });
};
const compressedWasmPath = arg(2);
const TOKEN_UNIT = 10n ** 18n;
const wsProvider = new WsProvider("ws://localhost:9944");
const api = await ApiPromise.create({ provider: wsProvider });
const code = await readFile(compressedWasmPath);
const keyring = new Keyring({ type: "sr25519", ss58Format: 5234 });
const alice = keyring.addFromUri("//Alice");
const bob = keyring.addFromUri("//Bob");
const charlie = keyring.addFromUri("//Charlie");
// 0x81Bc98c2148aC7478dDC19f250Fa08CeC0e746f3
const bobEthereum = privateKeyToAccount(
"0x563e8651c5515c78c16d5689282465d23e949d9e331f6f2d1c737f2018e420ee",
);
// 0x0F7a27bAE67919705A83830df3A7A16d7c485958
const charlieEthereum = privateKeyToAccount(
"0x858a03a3c0812675b64fb9d222cbe23fdf94b3e01254f3a4b71bd75c078e89b2",
);
// Alice -> Bob: 10 HMND.
console.log("Sending 10 HMND from Alice to Bob");
await sendAndWait(api.tx.balances.transfer(bob.address, 10n * TOKEN_UNIT), {
signWith: alice,
});
// Add bobEthereum token claims.
console.log("Adding bobEthereum token claims");
await sendAndWait(
api.tx.sudo.sudo(
api.tx.tokenClaims.addClaim(
bobEthereum.address,
{
balance: 1000n * TOKEN_UNIT,
vesting: [
{
balance: 1000n * TOKEN_UNIT,
cliff: 0,
vesting: 604_800_000,
},
],
},
alice.address,
),
),
{ signWith: alice },
);
// Bob claims tokens.
console.log("Bob is claiming tokens related to BobEthereum");
await sendAndWait(
api.tx.tokenClaims.claim(
bobEthereum.address,
await prepareClaimMessageSignature(bobEthereum, bob.publicKey),
),
{ signWith: bob },
);
// Add charlieEthereum token claims.
console.log("Adding CharlieEthereum token claims");
await sendAndWait(
api.tx.sudo.sudo(
api.tx.tokenClaims.addClaim(
charlieEthereum.address,
{
balance: 1000n * TOKEN_UNIT,
vesting: [
{
balance: 1000n * TOKEN_UNIT,
cliff: 0,
vesting: 604_800_000,
},
],
},
alice.address,
),
),
{ signWith: alice },
);
// Runtime upgrade.
console.log("Running runtime upgrade");
await sendAndWait(
api.tx.sudo.sudoUncheckedWeight(
api.tx.system.setCode(`0x${code.toString("hex")}`),
{
refTime: 0,
proofSize: 0,
},
),
{ signWith: alice },
);
console.log("\nRuntime upgrade checks");
// Alice -> Bob: 10 HMND.
console.log("Sending 10 HMND from Alice to Bob");
await sendAndWait(api.tx.balances.transfer(bob.address, 10n * TOKEN_UNIT), {
signWith: alice,
});
// Assert that alice is upgraded account.
const aliceAccountSystem = await api.query.system.account(alice.address);
assert(aliceAccountSystem.data.flags.toBigInt() != 0n);
// Assert that bob is upgraded account.
const bobAccountSystem = await api.query.system.account(bob.address);
assert(bobAccountSystem.data.flags.toBigInt() != 0n);
// Bob executes unlock.
const bobAccountSystemBeforeUnlock = await api.query.system.account(
bob.address,
);
console.log("Bob is unlocking tokens");
await sendAndWait(api.tx.vesting.unlock(), { signWith: bob });
const bobAccountSystemAfterUnlock = await api.query.system.account(bob.address);
assert(
bobAccountSystemBeforeUnlock.data.free !=
bobAccountSystemAfterUnlock.data.free,
);
// Alice -> Charlie: 10 HMND.
console.log("Sending 10 HMND from Alice to Charlie");
await sendAndWait(api.tx.balances.transfer(charlie.address, 10n * TOKEN_UNIT), {
signWith: alice,
});
// Charlie claims tokens.
console.log("Charlie is claiming tokens related to CharlieEthereum");
await sendAndWait(
api.tx.tokenClaims.claim(
charlieEthereum.address,
await prepareClaimMessageSignature(charlieEthereum, charlie.publicKey),
),
{ signWith: charlie },
);
// Charlie executes unlock.
const charlieAccountSystemBeforeUnlock = await api.query.system.account(
charlie.address,
);
console.log("Charlie is unlocking tokens");
await sendAndWait(api.tx.vesting.unlock(), { signWith: charlie });
const charlieAccountSystemAfterUnlock = await api.query.system.account(
charlie.address,
);
assert(
charlieAccountSystemBeforeUnlock.data.free !=
charlieAccountSystemAfterUnlock.data.free,
);
process.exit(0);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment