diff --git a/e2e-tests/tests/config.ts b/e2e-tests/tests/config.ts index 3714ee2cf..3e2aa1742 100644 --- a/e2e-tests/tests/config.ts +++ b/e2e-tests/tests/config.ts @@ -15,8 +15,6 @@ export const LOCAL_NODE_URL = "http://127.0.0.1:9999"; // Chain config export const CHAIN_ID = 667; export const GAS_PRICE = "0x3B9ACA00"; -export const ETH_BLOCK_GAS_LIMIT = 15000000; // The same configuration as runtime -export const GAS_LIMIT = ETH_BLOCK_GAS_LIMIT - 10000000; // TODO remove subtraction // Accounts export const FAITH = "0xC0F0f4ab324C46e55D02D0033343B4Be8A55532d"; diff --git a/e2e-tests/tests/test-create-collection.ts b/e2e-tests/tests/test-create-collection.ts index 1c3f71685..2dac893af 100644 --- a/e2e-tests/tests/test-create-collection.ts +++ b/e2e-tests/tests/test-create-collection.ts @@ -4,7 +4,6 @@ import Contract from "web3-eth-contract"; import { EVOLUTION_COLLECTION_FACTORY_CONTRACT_ADDRESS, EVOLUTION_COLLECTION_FACTORY_ABI, - GAS_LIMIT, GAS_PRICE, FAITH, FAITH_PRIVATE_KEY, @@ -27,7 +26,6 @@ describeWithExistingNode("Frontier RPC (Create Collection)", (context) => { { from: FAITH, gasPrice: GAS_PRICE, - gas: GAS_LIMIT, } ); context.web3.eth.accounts.wallet.add(FAITH_PRIVATE_KEY); @@ -42,9 +40,10 @@ describeWithExistingNode("Frontier RPC (Create Collection)", (context) => { }); step("when collection is created event is emitted", async function () { + const estimatedGas = await contract.methods.createCollection(FAITH).estimateGas(); const result = await contract.methods.createCollection(FAITH).send({ from: FAITH, - gas: GAS_LIMIT, + gas: estimatedGas, gasPrice: GAS_PRICE, }); expect(result.status).to.be.eq(true); diff --git a/e2e-tests/tests/test-evolution.ts b/e2e-tests/tests/test-evolution.ts index 2807f8bbb..c55f98406 100644 --- a/e2e-tests/tests/test-evolution.ts +++ b/e2e-tests/tests/test-evolution.ts @@ -1,20 +1,9 @@ +import { createCollection, describeWithExistingNode, slotAndOwnerToTokenId } from "./util"; import { - addressToCollectionId, - createCollection, - describeWithExistingNode, - extractRevertReason, - slotAndOwnerToTokenId, -} from "./util"; -import { - GAS_LIMIT, FAITH, SELECTOR_LOG_EVOLVED_WITH_EXTERNAL_TOKEN_URI, SELECTOR_LOG_MINTED_WITH_EXTERNAL_TOKEN_URI, SELECTOR_LOG_OWNERSHIP_TRANSFERRED, - SELECTOR_LOG_PUBLIC_MINTING_ENABLED, - SELECTOR_LOG_PUBLIC_MINTING_DISABLED, - ALITH, - ALITH_PRIVATE_KEY, } from "./config"; import { expect } from "chai"; import Contract from "web3-eth-contract"; @@ -47,9 +36,10 @@ describeWithExistingNode("Frontier RPC (Mint and Evolve Assets)", (context) => { const tokenURI = "https://example.com"; let nonce = await context.web3.eth.getTransactionCount(FAITH); + const estimatedGas = await collectionContract.methods.mintWithExternalURI(to, slot, tokenURI).estimateGas(); const result = await collectionContract.methods .mintWithExternalURI(to, slot, tokenURI) - .send({ from: FAITH, gas: GAS_LIMIT, nonce: nonce++ }); + .send({ from: FAITH, gas: estimatedGas, nonce: nonce++ }); expect(result.status).to.be.eq(true); const tokenId = result.events.MintedWithExternalURI.returnValues._tokenId; @@ -72,9 +62,10 @@ describeWithExistingNode("Frontier RPC (Mint and Evolve Assets)", (context) => { const to = FAITH; const tokenURI = "https://example.com"; + const estimatedGas = await collectionContract.methods.mintWithExternalURI(to, slot, tokenURI).estimateGas(); const result = await collectionContract.methods .mintWithExternalURI(to, slot, tokenURI) - .send({ from: FAITH, gas: GAS_LIMIT }); + .send({ from: FAITH, gas: estimatedGas }); expect(result.status).to.be.eq(true); expect(Object.keys(result.events).length).to.be.eq(1); @@ -108,14 +99,18 @@ describeWithExistingNode("Frontier RPC (Mint and Evolve Assets)", (context) => { const tokenId = slotAndOwnerToTokenId(slot, to); const tokenIdDecimal = new BN(tokenId, 16, "be").toString(10); + var estimatedGas = await collectionContract.methods.mintWithExternalURI(to, slot, tokenURI).estimateGas(); const mintingResult = await collectionContract.methods .mintWithExternalURI(to, slot, tokenURI) - .send({ from: FAITH, gas: GAS_LIMIT }); + .send({ from: FAITH, gas: estimatedGas }); expect(mintingResult.status).to.be.eq(true); + estimatedGas = await collectionContract.methods + .evolveWithExternalURI(tokenIdDecimal, newTokenURI) + .estimateGas(); const evolvingResult = await collectionContract.methods .evolveWithExternalURI(tokenIdDecimal, newTokenURI) - .send({ from: FAITH, gas: GAS_LIMIT }); + .send({ from: FAITH, gas: estimatedGas }); expect(evolvingResult.status).to.be.eq(true); const got = await collectionContract.methods.tokenURI(tokenIdDecimal).call(); @@ -130,14 +125,18 @@ describeWithExistingNode("Frontier RPC (Mint and Evolve Assets)", (context) => { const tokenId = slotAndOwnerToTokenId(slot, to); const tokenIdDecimal = new BN(tokenId, 16, "be").toString(10); + var estimatedGas = await collectionContract.methods.mintWithExternalURI(to, slot, tokenURI).estimateGas(); const mintingResult = await collectionContract.methods .mintWithExternalURI(to, slot, tokenURI) - .send({ from: FAITH, gas: GAS_LIMIT }); + .send({ from: FAITH, gas: estimatedGas }); expect(mintingResult.status).to.be.eq(true); + estimatedGas = await collectionContract.methods + .evolveWithExternalURI(tokenIdDecimal, newTokenURI) + .estimateGas(); const evolvingResult = await collectionContract.methods .evolveWithExternalURI(tokenIdDecimal, newTokenURI) - .send({ from: FAITH, gas: GAS_LIMIT }); + .send({ from: FAITH, gas: estimatedGas }); expect(evolvingResult.status).to.be.eq(true); expect(Object.keys(evolvingResult.events).length).to.be.eq(1); @@ -171,9 +170,10 @@ describeWithExistingNode("Frontier RPC (Transfer Ownership)", (context) => { const newOwner = "0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"; expect(await collectionContract.methods.owner().call()).to.be.eq(FAITH); + const estimatedGas = await collectionContract.methods.transferOwnership(newOwner).estimateGas(); const tranferringResult = await collectionContract.methods .transferOwnership(newOwner) - .send({ from: FAITH, gas: GAS_LIMIT }); + .send({ from: FAITH, gas: estimatedGas }); expect(tranferringResult.status).to.be.eq(true); expect(await collectionContract.methods.owner().call()).to.be.eq(newOwner); @@ -198,10 +198,13 @@ describeWithExistingNode("Frontier RPC (Transfer Ownership)", (context) => { expect(tranferringResult.events.OwnershipTransferred.raw.data).to.be.eq("0x"); try { - await collectionContract.methods.transferOwnership(FAITH).send({ from: FAITH, gas: GAS_LIMIT }); + const estimatedGas = await collectionContract.methods.transferOwnership(FAITH).estimateGas(); + await collectionContract.methods.transferOwnership(FAITH).send({ from: FAITH, gas: estimatedGas }); expect.fail("Expected error was not thrown"); // Ensure an error is thrown } catch (error) { - expect(await extractRevertReason(context, error.receipt.transactionHash)).to.eq("NoPermission"); + expect(error.message).to.eq( + "Returned error: VM Exception while processing transaction: revert NoPermission" + ); } }); }); diff --git a/e2e-tests/tests/test-staking.ts b/e2e-tests/tests/test-staking.ts index 339a63857..efacbe128 100644 --- a/e2e-tests/tests/test-staking.ts +++ b/e2e-tests/tests/test-staking.ts @@ -1,10 +1,8 @@ import { describeWithExistingNode } from "./util"; import { - GAS_LIMIT, ALITH, STAKING_ABI, STAKING_CONTRACT_ADDRESS, - GAS_PRICE, UNIT, FAITH_PRIVATE_KEY, FAITH, diff --git a/e2e-tests/tests/test-update-extended-token-uri.ts b/e2e-tests/tests/test-update-extended-token-uri.ts index 24baa26da..29c89f4f8 100644 --- a/e2e-tests/tests/test-update-extended-token-uri.ts +++ b/e2e-tests/tests/test-update-extended-token-uri.ts @@ -4,7 +4,6 @@ import Contract from "web3-eth-contract"; import { ASSET_METADATA_EXTENDER_ADDRESS, ASSET_METADATA_EXTENDER_ABI, - GAS_LIMIT, GAS_PRICE, FAITH, FAITH_PRIVATE_KEY, @@ -20,7 +19,6 @@ describeWithExistingNode("Frontier RPC (Extend Token URI)", (context) => { contract = new context.web3.eth.Contract(ASSET_METADATA_EXTENDER_ABI, ASSET_METADATA_EXTENDER_ADDRESS, { from: FAITH, gasPrice: GAS_PRICE, - gas: GAS_LIMIT, }); context.web3.eth.accounts.wallet.add(FAITH_PRIVATE_KEY); }); @@ -36,9 +34,10 @@ describeWithExistingNode("Frontier RPC (Extend Token URI)", (context) => { step("extend should return ok", async function () { let nonce = await context.web3.eth.getTransactionCount(FAITH); + const estimatedGas = await contract.methods.extendULWithExternalURI(uloc, tokenURI).estimateGas(); extendResult = await contract.methods.extendULWithExternalURI(uloc, tokenURI).send({ from: FAITH, - gas: GAS_LIMIT, + gas: estimatedGas, gasPrice: GAS_PRICE, nonce: nonce++, }); @@ -94,15 +93,15 @@ describeWithExistingNode("Frontier RPC (Update Extended Token URI)", async (cont contract = new context.web3.eth.Contract(ASSET_METADATA_EXTENDER_ABI, ASSET_METADATA_EXTENDER_ADDRESS, { from: FAITH, gasPrice: GAS_PRICE, - gas: GAS_LIMIT, }); context.web3.eth.accounts.wallet.add(FAITH_PRIVATE_KEY); // we first create an extension to be updated later let nonce = await context.web3.eth.getTransactionCount(FAITH); + const estimatedGas = await contract.methods.extendULWithExternalURI(uloc, tokenURI).estimateGas(); const createResult = await contract.methods.extendULWithExternalURI(uloc, tokenURI).send({ from: FAITH, - gas: GAS_LIMIT, + gas: estimatedGas, gasPrice: GAS_PRICE, nonce: nonce++, }); @@ -119,9 +118,10 @@ describeWithExistingNode("Frontier RPC (Update Extended Token URI)", async (cont step("update extension should return ok", async function () { let nonce = await context.web3.eth.getTransactionCount(FAITH); + const estimatedGas = await contract.methods.updateExtendedULWithExternalURI(uloc, newTokenURI).estimateGas(); updateExtensionResult = await contract.methods.updateExtendedULWithExternalURI(uloc, newTokenURI).send({ from: FAITH, - gas: GAS_LIMIT, + gas: estimatedGas, gasPrice: GAS_PRICE, nonce: nonce++, }); diff --git a/e2e-tests/tests/test-vesting.ts b/e2e-tests/tests/test-vesting.ts index 7818f9b5c..241cb437f 100644 --- a/e2e-tests/tests/test-vesting.ts +++ b/e2e-tests/tests/test-vesting.ts @@ -4,24 +4,20 @@ import Contract from "web3-eth-contract"; import { VESTING_CONTRACT_ADDRESS, VESTING_ABI, - GAS_LIMIT, GAS_PRICE, FAITH, FAITH_PRIVATE_KEY, ALITH, ALITH_PRIVATE_KEY, } from "./config"; -import { describeWithExistingNode, extractRevertReason } from "./util"; -import Web3 from "web3"; +import { describeWithExistingNode } from "./util"; describeWithExistingNode("Frontier RPC (Vesting)", (context) => { let contract: Contract; before(async function () { contract = new context.web3.eth.Contract(VESTING_ABI, VESTING_CONTRACT_ADDRESS, { - from: FAITH, gasPrice: GAS_PRICE, - gas: GAS_LIMIT, }); context.web3.eth.accounts.wallet.add(FAITH_PRIVATE_KEY); context.web3.eth.accounts.wallet.add(ALITH_PRIVATE_KEY); @@ -34,10 +30,12 @@ describeWithExistingNode("Frontier RPC (Vesting)", (context) => { it("when there is no vesting do vest reverts", async function () { try { let nonce = await context.web3.eth.getTransactionCount(FAITH); - await contract.methods.vest().send({ from: FAITH, gas: GAS_LIMIT, nonce: nonce++ }); + const estimatedGas = await contract.methods.vest().estimateGas(); + contract.options.from = FAITH; + await contract.methods.vest().send({ from: FAITH, gas: estimatedGas, nonce: nonce++ }); expect.fail("Expected error was not thrown"); // Ensure an error is thrown } catch (error) { - expect(await extractRevertReason(context, error.receipt.transactionHash)).to.eq("NotVesting"); + expect(error.message).to.eq("Returned error: VM Exception while processing transaction: revert NotVesting"); } }); it("when vesting exists it returns the list", async function () { @@ -50,12 +48,15 @@ describeWithExistingNode("Frontier RPC (Vesting)", (context) => { step("when vesting exists do vest returns ok", async function () { let nonce = await context.web3.eth.getTransactionCount(ALITH); contract.options.from = ALITH; - let result = await contract.methods.vest().send({ from: ALITH, gas: GAS_LIMIT, nonce: nonce++ }); + const estimatedGas = await contract.methods.vest().estimateGas(); + let result = await contract.methods.vest().send({ from: ALITH, gas: estimatedGas, nonce: nonce++ }); expect(result.status).to.be.eq(true); }); step("when vesting exists do vestOther returns ok", async function () { let nonce = await context.web3.eth.getTransactionCount(FAITH); - let result = await contract.methods.vestOther(ALITH).send({ from: FAITH, gas: GAS_LIMIT, nonce: nonce++ }); + contract.options.from = FAITH; + const estimatedGas = await contract.methods.vestOther(ALITH).estimateGas(); + let result = await contract.methods.vestOther(ALITH).send({ from: FAITH, gas: estimatedGas, nonce: nonce++ }); expect(result.status).to.be.eq(true); }); }); diff --git a/e2e-tests/tests/util.ts b/e2e-tests/tests/util.ts index b43ed6297..701d6482f 100644 --- a/e2e-tests/tests/util.ts +++ b/e2e-tests/tests/util.ts @@ -4,7 +4,6 @@ import Web3 from "web3"; import { JsonRpcResponse } from "web3-core-helpers"; import { EVOLUTION_COLLECTION_FACTORY_CONTRACT_ADDRESS, - GAS_LIMIT, GAS_PRICE, FAITH, FAITH_PRIVATE_KEY, @@ -87,9 +86,10 @@ export async function createCollection(context: { web3: Web3 }): Promise = <::Currency as Curr ::AccountId, >>::Balance; -/* - * Allow directive added because when the macro expands, `T` has constraints in - * multiple locations. This is what the expanded code looks like: - * ``` - * fn _precompile_vest(verify: bool) - * where - * T: Config + pallet_vesting: Config, - * ``` - */ #[benchmarks( where T: Config + pallet_vesting::Config, diff --git a/runtime/laos/src/apis.rs b/runtime/laos/src/apis.rs index 0e3277946..1eda85224 100644 --- a/runtime/laos/src/apis.rs +++ b/runtime/laos/src/apis.rs @@ -23,6 +23,7 @@ use frame_support::{ use pallet_aura::Authorities; use pallet_ethereum::{Call::transact, Transaction as EthereumTransaction}; use pallet_evm::{Account as EVMAccount, FeeCalculator, Runner}; +use parity_scale_codec::Encode; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H160, H256, U256}; use sp_runtime::{ @@ -175,6 +176,8 @@ impl_runtime_apis! { estimate: bool, access_list: Option)>>, ) -> Result { + use pallet_evm::GasWeightMapping as _; + let config = if estimate { let mut config = ::config().clone(); config.estimate = true; @@ -183,9 +186,46 @@ impl_runtime_apis! { None }; - let is_transactional = false; - let validate = true; - let evm_config = config.as_ref().unwrap_or(::config()); + // Estimated encoded transaction size must be based on the heaviest transaction + // type (EIP1559Transaction) to be compatible with all transaction types. + let mut estimated_transaction_len = data.len() + + // pallet ethereum index: 1 + // transact call index: 1 + // Transaction enum variant: 1 + // chain_id 8 bytes + // nonce: 32 + // max_priority_fee_per_gas: 32 + // max_fee_per_gas: 32 + // gas_limit: 32 + // action: 21 (enum varianrt + call address) + // value: 32 + // access_list: 1 (empty vec size) + // 65 bytes signature + 258; + + if access_list.is_some() { + estimated_transaction_len += access_list.encoded_size(); + } + + + let gas_limit = if gas_limit > U256::from(u64::MAX) { + u64::MAX + } else { + gas_limit.low_u64() + }; + let without_base_extrinsic_weight = true; + + let (weight_limit, proof_size_base_cost) = + match ::GasWeightMapping::gas_to_weight( + gas_limit, + without_base_extrinsic_weight + ) { + weight_limit if weight_limit.proof_size() > 0 => { + (Some(weight_limit), Some(estimated_transaction_len as u64)) + } + _ => (None, None), + }; + ::Runner::call( from, to, @@ -196,11 +236,11 @@ impl_runtime_apis! { max_priority_fee_per_gas, nonce, access_list.unwrap_or_default(), - is_transactional, - validate, - None, - None, - evm_config, + false, + true, + weight_limit, + proof_size_base_cost, + config.as_ref().unwrap_or(::config()), ).map_err(|err| err.error.into()) } diff --git a/runtime/laos/src/configs/collective.rs b/runtime/laos/src/configs/collective.rs index 173d3a3d0..fe3a5817b 100644 --- a/runtime/laos/src/configs/collective.rs +++ b/runtime/laos/src/configs/collective.rs @@ -13,6 +13,8 @@ parameter_types! { pub MaxProposalWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block; } +pub type HalfOfCouncil = + pallet_collective::EnsureProportionAtLeast; pub type CouncilMajority = pallet_collective::EnsureProportionMoreThan; pub type AllOfCouncil = diff --git a/runtime/laos/src/configs/democracy.rs b/runtime/laos/src/configs/democracy.rs index 45b91c30a..bd23214dd 100644 --- a/runtime/laos/src/configs/democracy.rs +++ b/runtime/laos/src/configs/democracy.rs @@ -1,5 +1,5 @@ use super::collective::{ - AllOfCouncil, AllOfTechnicalCommittee, CouncilMajority, TechnicalCommittee, + AllOfCouncil, AllOfTechnicalCommittee, CouncilMajority, HalfOfCouncil, TechnicalCommittee, TechnicalCommitteeMajority, TwoThirdOfCouncil, }; use crate::{ @@ -48,7 +48,7 @@ impl pallet_democracy::Config for Runtime { type ExternalDefaultOrigin = AllOfCouncil; /// A simple-majority can have the next scheduled referendum be a straight /// majority-carries vote. - type ExternalMajorityOrigin = CouncilMajority; + type ExternalMajorityOrigin = HalfOfCouncil; /// A straight majority of the council can decide what their next motion is. type ExternalOrigin = CouncilMajority; /// Majority of technical committee can have an ExternalMajority/ExternalDefault vote