Skip to content

Commit

Permalink
Merge branch 'main' into feature/existential_deposit_is_0
Browse files Browse the repository at this point in the history
  • Loading branch information
asiniscalchi committed Nov 14, 2023
2 parents 67cd3c0 + 05610c2 commit 3e64cc7
Show file tree
Hide file tree
Showing 34 changed files with 444 additions and 2,107 deletions.
66 changes: 1 addition & 65 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ pallet-authorship = { git = "https://github.com/paritytech/substrate", branch =
pallet-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0", default-features = false, features = ["historical"] }
pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0", default-features = false }
pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0", default-features = false }
pallet-multisig = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0", default-features = false }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0", default-features = false }
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0", default-features = false }
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0", default-features = false }
Expand Down Expand Up @@ -220,9 +221,7 @@ polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "relea
polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "release-v1.0.0" }

# LAOS pallets
pallet-living-assets-ownership = { path = "./ownership-chain/pallets/living-assets-ownership", default-features = false }
pallet-laos-evolution = { path = "./ownership-chain/pallets/laos-evolution", default-features = false }
pallet-evm-living-assets-ownership = { path = "./ownership-chain/precompile/living-assets", default-features = false }
pallet-evm-laos-evolution = { path = "./ownership-chain/precompile/laos-evolution", default-features = false }
pallet-evm-erc721 = { path = "./ownership-chain/precompile/erc721", default-features = false }

Expand Down
82 changes: 82 additions & 0 deletions docs/multisig.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# How to use multisig accounts

This guide explains how to use multisig accounts in Caladan.

## What is a multisig account?

A multisig account is an account that requires multiple signatures to approve a transaction. This is useful for security reasons, as it means that no single person can approve a transaction on their own. It is also useful for organizational reasons, as it means that multiple people can be involved in the approval process.

More about multisig accounts in Polkadot can be found [here](https://wiki.polkadot.network/docs/learn-account-multisig#introduction-to-multisig-accounts).
And more detailed version of this guide can be found [here](https://support.polkadot.network/support/solutions/articles/65000181826-how-to-create-and-use-a-multisig-account)

## Pre-requisites

We will be using a local Zombienet network to demonstrate:

1. Create a multisig account
2. Change sudo key to a multisig account
3. Approve a transaction with a multisig account

## Launch a local Zombienet network

Follow the instructions [here](../ownership-chain/zombienet/README.md) to launch a local Zombienet network.

## Create a multisig account

In `Accounts` tab, click on `+ Multisig`:

![+Multisig](https://github.com/freeverseio/laos/assets/137785454/0e7b3bea-255d-4940-9cdc-28b948406fca)

In the new window, select signatories for the multisig and give a name to the multisig:

![Select signatories](https://github.com/freeverseio/laos/assets/137785454/579f41df-7c40-4119-950d-8028b3198966)

You can see the new account in the `multisig` section (in our example, it's called `Sudoers`):

![Sudoers](https://github.com/freeverseio/laos/assets/137785454/5ab13574-edcc-402e-8bdd-2a6b49c92a5c)

And more info when you click on it:

![More info](https://github.com/freeverseio/laos/assets/137785454/d1f136ed-b5cf-4760-876a-dba578f01586)

**NOTE** Next steps will require you to sign transactions and send funds from the multisig account, so make sure to deposit some funds to it.

## Change sudo to new multisig

Go to `Extrinsics` tab and select `Sudo->setKey()` extrinsic, and select newly created multisig account as `new`:

![Change sudo](https://github.com/freeverseio/laos/assets/137785454/6c71335b-4841-452c-972e-328686b40790)

**NOTE**: This should not be wrapped to `sudo` extrinsic and should be signed by the current sudo account (f.e, it's `Alith` in this example)

## Use multisig to transfer funds

Now we want use new multisig account to transfer funds. For this, simply click on the `Transfer` tab and select multisig account as a `sender`. Select `to` and `amount` and click on `Make Transfer`:

![Transfer](https://github.com/freeverseio/laos/assets/137785454/32b0fc93-2fc5-43f5-8bbc-503bb35a442a)

In the next window, you will see this:

![Authorize tx](https://github.com/freeverseio/laos/assets/137785454/df0593fd-6663-411a-821b-e7e0c4becb6c)

**NOTE**: Make sure to copy `multisig call data` field and share it with other multisig signatories.

It's important to note that this call will signed and submitted first with one of the signatories of the multisig, meaning it already has 1 approval. Then the `multisig call data` is shared with other signers. Now, click on `Sign and Submit`

## Approve multisig call

If you are one of the signers, when you go to `Accounts` tab and `multisig` section, you will see a notification that says `Multisig approvals pending`:

![Approvals pending](https://github.com/freeverseio/laos/assets/137785454/93c8750d-b714-4e3f-8638-818a74eb365c)

Click on it and you will go to a window like this:

![Pending call hashes](https://github.com/freeverseio/laos/assets/137785454/25b939e5-7327-4006-aaf1-3c583049ac81)

Here you have to now paste `multisig call data` from the previous step, select the signer and `Approve` the call.

## Multisig executed

Once the second signer approved the call, multisig will be executed and funds are transferred:

![Multisig Executed](https://github.com/freeverseio/laos/assets/137785454/6ce884e9-17ee-4a9d-b1d2-6c06b04e71ca)
14 changes: 7 additions & 7 deletions ownership-chain/e2e-tests/tests/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ export const GENESIS_ACCOUNT = "0xC0F0f4ab324C46e55D02D0033343B4Be8A55532d";
export const GENESIS_ACCOUNT_PRIVATE_KEY = "0xb9d2ea9a615f3165812e8d44de0d24da9bbd164b65c4f0573e1ce2c8dbd9c8df";
export const GENESIS_ACCOUNT_BALANCE = "77559934324363988853790420524572160";
export const GAS_PRICE = "0x3B9ACA00";
export const GAS = "0x10000";
export const ETH_BLOCK_GAS_LIMIT = 15000000; // The same configuration as runtime
export const GAS_LIMIT = ETH_BLOCK_GAS_LIMIT - 10000000;
export const GAS = "0x10000";

// LAOS Evolution Contract
export const LAOS_EVOLUTION_ABI = LaosEvolution.abi as AbiItem[];
export const CONTRACT_ADDRESS = "0x0000000000000000000000000000000000000403";
export const SELECTOR_LOG_NEW_COLLECTION = "0x6eb24fd767a7bcfa417f3fe25a2cb245d2ae52293d3c4a8f8c6450a09795d289";
export const SELECTOR_LOG_MINTED_WITH_EXTERNAL_TOKEN_URI =
"0x4b3b5da28a351f8bb73b960d7c80b2cef3e3570cb03448234dee173942c74786";
export const SELECTOR_LOG_EVOLVED_WITH_EXTERNAL_TOKEN_URI =
"0x95c167d04a267f10e6b3f373c7a336dc65cf459caf048854dc32a2d37ab1607c";
export const SELECTOR_LOG_NEW_COLLECTION = "0x5b84d9550adb7000df7bee717735ecd3af48ea3f66c6886d52e8227548fb228c";
export const SELECTOR_LOG_MINTED_WITH_EXTERNAL_TOKEN_URI = "0x4b3b5da28a351f8bb73b960d7c80b2cef3e3570cb03448234dee173942c74786";
export const SELECTOR_LOG_EVOLVED_WITH_EXTERNAL_TOKEN_URI = "0x95c167d04a267f10e6b3f373c7a336dc65cf459caf048854dc32a2d37ab1607c";

export const MAX_U96 = new BN("79228162514264337593543950336"); // 2^96 - 1
export const MAX_U96 = new BN('79228162514264337593543950336'); // 2^96 - 1
38 changes: 28 additions & 10 deletions ownership-chain/e2e-tests/tests/test-create-collection.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { describeWithExistingNode } from "./util";
import { step } from "mocha-steps";
import { CONTRACT_ADDRESS, GAS, GAS_PRICE, GENESIS_ACCOUNT, GENESIS_ACCOUNT_PRIVATE_KEY, LAOS_EVOLUTION_ABI, SELECTOR_LOG_NEW_COLLECTION } from "./config";
import { CONTRACT_ADDRESS, GAS_LIMIT, GAS_PRICE, GENESIS_ACCOUNT, GENESIS_ACCOUNT_PRIVATE_KEY, LAOS_EVOLUTION_ABI, SELECTOR_LOG_NEW_COLLECTION } from "./config";
import { expect } from "chai";
import Contract from "web3-eth-contract";
import { step } from "mocha-steps";


describeWithExistingNode("Frontier RPC (Create Collection)", (context) => {
Expand All @@ -13,6 +13,7 @@ describeWithExistingNode("Frontier RPC (Create Collection)", (context) => {
contract = new context.web3.eth.Contract(LAOS_EVOLUTION_ABI, CONTRACT_ADDRESS, {
from: GENESIS_ACCOUNT,
gasPrice: GAS_PRICE,
gas: GAS_LIMIT,
});

nonce = await context.web3.eth.getTransactionCount(GENESIS_ACCOUNT);
Expand All @@ -21,7 +22,7 @@ describeWithExistingNode("Frontier RPC (Create Collection)", (context) => {

step("when collection does not exist owner of call should fail", async function () {
try {
await contract.methods.ownerOfCollection("1111").call();
await contract.methods.owner().call();
expect.fail("Expected error was not thrown"); // Ensure an error is thrown
} catch (error) {
expect(error.message).to.be.eq(
Expand All @@ -33,30 +34,47 @@ describeWithExistingNode("Frontier RPC (Create Collection)", (context) => {
step("when collection is created, it should return owner", async function () {
this.timeout(70000);

const result = await contract.methods.createCollection(GENESIS_ACCOUNT).send({ from: GENESIS_ACCOUNT, gas: GAS, nonce: nonce++ });
const result = await contract.methods.createCollection(GENESIS_ACCOUNT).send({
from: GENESIS_ACCOUNT,
gas: GAS_LIMIT,
gasPrice: GAS_PRICE,
nonce: nonce++,
});
expect(result.status).to.be.eq(true);

const owner = await contract.methods.ownerOfCollection(result.events.NewCollection.returnValues.collectionId).call();
expect(context.web3.utils.isAddress(result.events.NewCollection.returnValues._collectionAddress)).to.be.eq(true);

let collectionContract = new context.web3.eth.Contract(LAOS_EVOLUTION_ABI, result.events.NewCollection.returnValues._collectionAddress, {
from: GENESIS_ACCOUNT,
gas: GAS_LIMIT,
gasPrice: GAS_PRICE,
});

const owner = await collectionContract.methods.owner().call();
expect(owner).to.be.eq(GENESIS_ACCOUNT);
});

step("when collection is created event is emitted", async function () {
this.timeout(70000);

const result = await contract.methods.createCollection(GENESIS_ACCOUNT).send({ from: GENESIS_ACCOUNT, gas: GAS, nonce: nonce++ });
const result = await contract.methods.createCollection(GENESIS_ACCOUNT).send({
from: GENESIS_ACCOUNT,
gas: GAS_LIMIT,
gasPrice: GAS_PRICE,
nonce: nonce++,
});
expect(result.status).to.be.eq(true);

expect(Object.keys(result.events).length).to.be.eq(1);
expect(result.events.NewCollection.returnValues.collectionId).not.to.be.NaN;
expect(result.events.NewCollection.returnValues.owner).to.be.eq(GENESIS_ACCOUNT);
expect(context.web3.utils.isAddress(result.events.NewCollection.returnValues._collectionAddress)).to.be.eq(true);
expect(result.events.NewCollection.returnValues._owner).to.be.eq(GENESIS_ACCOUNT);

// event topics
expect(result.events.NewCollection.raw.topics.length).to.be.eq(2);
expect(result.events.NewCollection.raw.topics[0]).to.be.eq(SELECTOR_LOG_NEW_COLLECTION);
expect(result.events.NewCollection.raw.topics[1]).to.be.eq(context.web3.utils.padLeft(GENESIS_ACCOUNT.toLowerCase(), 64));

// event data
expect(result.events.NewCollection.raw.data).to.be.eq("0x" + context.web3.utils.padLeft(result.events.NewCollection.returnValues.collectionId, 64));
expect(result.events.NewCollection.raw.data).to.be.eq(context.web3.utils.padLeft(result.events.NewCollection.returnValues._collectionAddress, 64));
});

});
Loading

0 comments on commit 3e64cc7

Please sign in to comment.