git.delta.rocks / unique-network / refs/commits / 17e188aac633

difftreelog

Merge pull request #577 from UniqueNetwork/fix/fee-multiplier-update

Yaroslav Bolyukin2022-12-19parents: #49182bd #bea7716.patch.diff
in: master

16 files changed

modifiedpallets/configuration/src/lib.rsdiffbeforeafterboth
--- a/pallets/configuration/src/lib.rs
+++ b/pallets/configuration/src/lib.rs
@@ -25,12 +25,14 @@
 };
 use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
 use scale_info::TypeInfo;
-use sp_arithmetic::traits::{BaseArithmetic, Unsigned};
+use sp_arithmetic::{
+	per_things::{Perbill, PerThing},
+	traits::{BaseArithmetic, Unsigned},
+};
 use smallvec::smallvec;
 
 pub use pallet::*;
 use sp_core::U256;
-use sp_runtime::Perbill;
 
 #[pallet]
 mod pallet {
@@ -46,8 +48,7 @@
 	#[pallet::config]
 	pub trait Config: frame_system::Config {
 		#[pallet::constant]
-		type DefaultWeightToFeeCoefficient: Get<u32>;
-
+		type DefaultWeightToFeeCoefficient: Get<u64>;
 		#[pallet::constant]
 		type DefaultMinGasPrice: Get<u64>;
 
@@ -66,7 +67,7 @@
 
 	#[pallet::storage]
 	pub type WeightToFeeCoefficientOverride<T: Config> = StorageValue<
-		Value = u32,
+		Value = u64,
 		QueryKind = ValueQuery,
 		OnEmpty = T::DefaultWeightToFeeCoefficient,
 	>;
@@ -90,7 +91,7 @@
 		#[pallet::weight(T::DbWeight::get().writes(1))]
 		pub fn set_weight_to_fee_coefficient_override(
 			origin: OriginFor<T>,
-			coeff: Option<u32>,
+			coeff: Option<u64>,
 		) -> DispatchResult {
 			ensure_root(origin)?;
 			if let Some(coeff) = coeff {
@@ -156,14 +157,17 @@
 impl<T, B> WeightToFeePolynomial for WeightToFee<T, B>
 where
 	T: Config,
-	B: BaseArithmetic + From<u32> + Copy + Unsigned,
+	B: BaseArithmetic + From<u32> + From<u64> + Copy + Unsigned,
 {
 	type Balance = B;
 
 	fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
 		smallvec!(WeightToFeeCoefficient {
-			coeff_integer: <WeightToFeeCoefficientOverride<T>>::get().into(),
-			coeff_frac: Perbill::zero(),
+			coeff_integer: (<WeightToFeeCoefficientOverride<T>>::get() / Perbill::ACCURACY as u64)
+				.into(),
+			coeff_frac: Perbill::from_parts(
+				(<WeightToFeeCoefficientOverride<T>>::get() % Perbill::ACCURACY as u64) as u32
+			),
 			negative: false,
 			degree: 1,
 		})
modifiedprimitives/common/src/constants.rsdiffbeforeafterboth
--- a/primitives/common/src/constants.rs
+++ b/primitives/common/src/constants.rs
@@ -43,10 +43,10 @@
 pub const UNIQUE: Balance = 100 * CENTIUNIQUE;
 
 // Targeting 0.1 UNQ per transfer
-pub const WEIGHT_TO_FEE_COEFF: u32 = /*<weight2fee>*/175_199_920/*</weight2fee>*/;
+pub const WEIGHT_TO_FEE_COEFF: u64 = /*<weight2fee>*/77_083_524_944_487_510/*</weight2fee>*/;
 
 // Targeting 0.15 UNQ per transfer via ETH
-pub const MIN_GAS_PRICE: u64 = /*<mingasprice>*/1_014_919_410_810/*</mingasprice>*/;
+pub const MIN_GAS_PRICE: u64 = /*<mingasprice>*/1_014_919_313_914/*</mingasprice>*/;
 
 /// We assume that ~10% of the block weight is consumed by `on_initalize` handlers.
 /// This is used to limit the maximal weight of a single extrinsic.
@@ -60,5 +60,5 @@
 	.set_proof_size(MAX_POV_SIZE as u64);
 
 parameter_types! {
-	pub const TransactionByteFee: Balance = 501 * MICROUNIQUE;
+	pub const TransactionByteFee: Balance = 501 * MICROUNIQUE / 2;
 }
modifiedruntime/common/config/pallets/mod.rsdiffbeforeafterboth
--- a/runtime/common/config/pallets/mod.rs
+++ b/runtime/common/config/pallets/mod.rs
@@ -104,7 +104,7 @@
 	pub const DayRelayBlocks: BlockNumber = RELAY_DAYS;
 }
 impl pallet_configuration::Config for Runtime {
-	type DefaultWeightToFeeCoefficient = ConstU32<{ up_common::constants::WEIGHT_TO_FEE_COEFF }>;
+	type DefaultWeightToFeeCoefficient = ConstU64<{ up_common::constants::WEIGHT_TO_FEE_COEFF }>;
 	type DefaultMinGasPrice = ConstU64<{ up_common::constants::MIN_GAS_PRICE }>;
 	type MaxXcmAllowedLocations = ConstU32<16>;
 	type AppPromotionDailyRate = AppPromotionDailyRate;
modifiedruntime/common/config/substrate.rsdiffbeforeafterboth
--- a/runtime/common/config/substrate.rs
+++ b/runtime/common/config/substrate.rs
@@ -28,10 +28,12 @@
 	traits::{BlakeTwo256, AccountIdLookup},
 	Perbill, Permill, Percent,
 };
+use sp_arithmetic::traits::One;
 use frame_system::{
 	limits::{BlockLength, BlockWeights},
 	EnsureRoot,
 };
+use pallet_transaction_payment::{Multiplier, ConstFeeMultiplier};
 use crate::{
 	runtime_common::DealWithFees, Runtime, RuntimeEvent, RuntimeCall, RuntimeOrigin, PalletInfo,
 	System, Balances, Treasury, SS58Prefix, Version,
@@ -152,6 +154,8 @@
 	/// This value increases the priority of `Operational` transactions by adding
 	/// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.
 	pub const OperationalFeeMultiplier: u8 = 5;
+
+	pub FeeMultiplier: Multiplier = Multiplier::one();
 }
 
 impl pallet_transaction_payment::Config for Runtime {
@@ -160,7 +164,7 @@
 	type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
 	type OperationalFeeMultiplier = OperationalFeeMultiplier;
 	type WeightToFee = pallet_configuration::WeightToFee<Self, Balance>;
-	type FeeMultiplierUpdate = ();
+	type FeeMultiplierUpdate = ConstFeeMultiplier<FeeMultiplier>;
 }
 
 parameter_types! {
modifiedtests/src/calibrate.tsdiffbeforeafterboth
1import {IKeyringPair} from '@polkadot/types/types';1import {IKeyringPair} from '@polkadot/types/types';
2
3import {usingEthPlaygrounds, EthUniqueHelper} from './eth/util';2import {usingEthPlaygrounds, EthUniqueHelper} from './eth/util';
43
4class Fract {
5 static ZERO = new Fract(0n);
6 constructor(public readonly a: bigint, public readonly b: bigint = 1n) {
7 if (b === 0n) throw new Error('division by zero');
8 if (b < 0n) throw new Error('missing normalization');
9 }
510
6function linearRegression(points: { x: bigint, y: bigint }[]) {11 mul(other: Fract) {
7 let sumxy = 0n;12 return new Fract(this.a * other.a, this.b * other.b).optimize();
8 let sumx = 0n;
9 let sumy = 0n;
10 let sumx2 = 0n;
11 const n = points.length;
12 for (let i = 0; i < n; i++) {
13 const p = points[i];
14 sumxy += p.x * p.y;
15 sumx += p.x;
16 sumy += p.y;
17 sumx2 += p.x * p.x;
18 }13 }
1914
20 const nb = BigInt(n);15 div(other: Fract) {
16 return this.mul(other.inv());
17 }
2118
22 const a = (nb * sumxy - sumx * sumy) / (nb * sumx2 - sumx * sumx);19 plus(other: Fract) {
20 if (this.b === other.b) {
21 return new Fract(this.a + other.a, this.b);
23 const b = (sumy - a * sumx) / nb;22 }
23 return new Fract(this.a * other.b + other.a * this.b, this.b * other.b).optimize();
24 }
2425
25 return {a, b};26 minus(other: Fract) {
27 return this.plus(other.neg());
26}28 }
2729
28// JS has no builtin function to calculate sqrt of bigint30 neg() {
29// https://stackoverflow.com/a/53684036/6190169
30function sqrt(value: bigint) {
31 if (value < 0n) {31 return new Fract(-this.a, this.b);
32 throw 'square root of negative numbers is not supported';
33 }32 }
33 inv() {
34 if (this.a < 0) {
35 return new Fract(-this.b, -this.a);
36 } else {
37 return new Fract(this.b, this.a);
38 }
39 }
3440
35 if (value < 2n) {41 optimize() {
42 function gcd(x: bigint, y: bigint) {
43 if (x < 0n)
44 x = -x;
45 if (y < 0n)
46 y = -y;
47 while(y) {
36 return value;48 const t = y;
49 y = x % y;
50 x = t;
51 }
52 return x;
53 }
54 const v = gcd(this.a, this.b);
55 return new Fract(this.a / v, this.b / v);
37 }56 }
3857
39 function newtonIteration(n: bigint, x0: bigint): bigint {58 toBigInt() {
59 return this.a / this.b;
60 }
61 toNumber() {
40 const x1 = ((n / x0) + x0) >> 1n;62 const v = this.optimize();
63 return Number(v.a) / Number(v.b);
64 }
65 toString() {
66 const v = this.optimize();
41 if (x0 === x1 || x0 === (x1 - 1n)) {67 return `${v.a} / ${v.b}`;
68 }
69
70 lt(other: Fract) {
71 return this.a * other.b < other.a * this.b;
72 }
73 eq(other: Fract) {
74 return this.a * other.b === other.a * this.b;
75 }
76
77 sqrt() {
78 if (this.a < 0n) {
42 return x0;79 throw 'square root of negative numbers is not supported';
43 }80 }
81
44 return newtonIteration(n, x1);82 if (this.lt(new Fract(2n))) {
83 return this;
84 }
85
86 function newtonIteration(n: Fract, x0: Fract): Fract {
87 const x1 = rpn(n, x0, '/', x0, '+', new Fract(2n), '/');
88 if (x0.eq(x1) || x0.eq(x1.minus(new Fract(1n)))) {
89 return x0;
90 }
91 return newtonIteration(n, x1);
92 }
93
94 return newtonIteration(this, new Fract(1n));
45 }95 }
96}
4697
47 return newtonIteration(value, 1n);98type Op = Fract | '+' | '-' | '*' | '/' | 'dup' | Op[];
99function rpn(...ops: (Op)[]) {
100 const stack: Fract[] = [];
101 for (const op of ops) {
102 if (op instanceof Fract) {
103 stack.push(op);
104 } else if (op === '+') {
105 if (stack.length < 2)
106 throw new Error('stack underflow');
107 const b = stack.pop()!;
108 const a = stack.pop()!;
109 stack.push(a.plus(b));
110 } else if (op === '*') {
111 if (stack.length < 2)
112 throw new Error('stack underflow');
113 const b = stack.pop()!;
114 const a = stack.pop()!;
115 stack.push(a.mul(b));
116 } else if (op === '-') {
117 if (stack.length < 2)
118 throw new Error('stack underflow');
119 const b = stack.pop()!;
120 const a = stack.pop()!;
121 stack.push(a.minus(b));
122 } else if (op === '/') {
123 if (stack.length < 2)
124 throw new Error('stack underflow');
125 const b = stack.pop()!;
126 const a = stack.pop()!;
127 stack.push(a.div(b));
128 } else if (op === 'dup') {
129 if (stack.length < 1)
130 throw new Error('stack underflow');
131 const a = stack.pop()!;
132 stack.push(a);
133 stack.push(a);
134 } else if (Array.isArray(op)) {
135 stack.push(rpn(...op));
136 } else {
137 throw new Error(`unknown operand: ${op}`);
138 }
139 }
140 if (stack.length != 1)
141 throw new Error('one element should be left on stack');
142 return stack[0]!;
48}143}
49144
50function _error(points: { x: bigint, y: bigint }[], hypothesis: (a: bigint) => bigint) {145function linearRegression(points: { x: Fract, y: Fract }[]) {
146 let sumxy = Fract.ZERO;
147 let sumx = Fract.ZERO;
148 let sumy = Fract.ZERO;
149 let sumx2 = Fract.ZERO;
150 const n = points.length;
151 for (let i = 0; i < n; i++) {
152 const p = points[i];
153 sumxy = rpn(p.x, p.y, '*', sumxy, '+');
154 sumx = sumx.plus(p.x);
155 sumy = sumy.plus(p.y);
156 sumx2 = rpn(p.x, p.x, '*', sumx2, '+');
157 }
158
159 const nb = new Fract(BigInt(n));
160
161 const a = rpn(
162 [nb, sumxy, '*', sumx, sumy, '*', '-'],
163 [nb, sumx2, '*', sumx, sumx, '*', '-'],
164 '/',
165 );
166 const b = rpn(
167 [sumy, a, sumx, '*', '-'],
168 nb,
169 '/',
170 );
171
172 return {a, b};
173}
174
175const hypothesisLinear = (a: Fract, b: Fract) => (x: Fract) => rpn(x, a, '*', b, '+');
176
177function _error(points: { x: Fract, y: Fract }[], hypothesis: (a: Fract) => Fract) {
51 return sqrt(points.map(p => {178 return points.map(p => {
52 const v = hypothesis(p.x);179 const v = hypothesis(p.x);
53 const vv = p.y;180 const vv = p.y;
54181
55 return (v - vv) ** 2n;182 return rpn(v, vv, '-', 'dup', '*');
56 }).reduce((a, b) => a + b, 0n) / BigInt(points.length));183 }).reduce((a, b) => a.plus(b), Fract.ZERO).sqrt().div(new Fract(BigInt(points.length)));
57}184}
58185
59async function calibrateWeightToFee(helper: EthUniqueHelper, privateKey: (account: string) => Promise<IKeyringPair>) {186async function calibrateWeightToFee(helper: EthUniqueHelper, privateKey: (account: string) => Promise<IKeyringPair>) {
68 await token.transfer(alice, {Substrate: bob.address});195 await token.transfer(alice, {Substrate: bob.address});
69 const aliceBalanceAfter = await helper.balance.getSubstrate(alice.address);196 const aliceBalanceAfter = await helper.balance.getSubstrate(alice.address);
70197
71 console.log(`Original price: ${Number(aliceBalanceBefore - aliceBalanceAfter) / Number(helper.balance.getOneTokenNominal())} UNQ`);198 console.log(`\t[NFT transfer] Original price: ${Number(aliceBalanceBefore - aliceBalanceAfter) / Number(helper.balance.getOneTokenNominal())} UNQ`);
72 }199 }
73200
74 const api = helper.getApi();201 const api = helper.getApi();
75 const defaultCoeff = (api.consts.configuration.defaultWeightToFeeCoefficient as any).toBigInt();202 const base = (await api.query.configuration.weightToFeeCoefficientOverride() as any).toBigInt();
76 for (let i = -5; i < 5; i++) {203 for (let i = -5; i < 5; i++) {
77 await helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.configuration.setWeightToFeeCoefficientOverride(defaultCoeff + defaultCoeff / 1000n * BigInt(i))));204 await helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.configuration.setWeightToFeeCoefficientOverride(base + base / 1000n * BigInt(i))));
78205
79 const coefficient = (await api.query.configuration.weightToFeeCoefficientOverride() as any).toBigInt();206 const coefficient = new Fract((await api.query.configuration.weightToFeeCoefficientOverride() as any).toBigInt());
80 const collection = await helper.nft.mintCollection(alice, {name: 'New', description: 'New collection', tokenPrefix: 'NEW'});207 const collection = await helper.nft.mintCollection(alice, {name: 'New', description: 'New collection', tokenPrefix: 'NEW'});
81 const token = await collection.mintToken(alice, {Substrate: alice.address});208 const token = await collection.mintToken(alice, {Substrate: alice.address});
82209
83 const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address);210 const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address);
84 await token.transfer(alice, {Substrate: bob.address});211 await token.transfer(alice, {Substrate: bob.address});
85 const aliceBalanceAfter = await helper.balance.getSubstrate(alice.address);212 const aliceBalanceAfter = await helper.balance.getSubstrate(alice.address);
86213
87 const transferPrice = aliceBalanceBefore - aliceBalanceAfter;214 const transferPrice = new Fract(aliceBalanceBefore - aliceBalanceAfter);
88215
89 dataPoints.push({x: transferPrice, y: coefficient});216 dataPoints.push({x: transferPrice, y: coefficient});
90 }217 }
91 const {a, b} = linearRegression(dataPoints);218 const {a, b} = linearRegression(dataPoints);
92219
93 // console.log(`Error: ${error(dataPoints, x => a*x+b)}`);220 const hyp = hypothesisLinear(a, b);
221 // console.log(`\t[NFT transfer] Error: ${_error(dataPoints, hyp).toNumber()}`);
94222
95 const perfectValue = a * helper.balance.getOneTokenNominal() / 10n + b;223 // 0.1 UNQ
224 const perfectValue = hyp(rpn(new Fract(helper.balance.getOneTokenNominal()), new Fract(1n, 10n), '*'));
96 await helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.configuration.setWeightToFeeCoefficientOverride(perfectValue.toString())));225 await helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.configuration.setWeightToFeeCoefficientOverride(perfectValue.toBigInt())));
97226
98 {227 {
99 const collection = await helper.nft.mintCollection(alice, {name: 'New', description: 'New collection', tokenPrefix: 'NEW'});228 const collection = await helper.nft.mintCollection(alice, {name: 'New', description: 'New collection', tokenPrefix: 'NEW'});
102 await token.transfer(alice, {Substrate: bob.address});231 await token.transfer(alice, {Substrate: bob.address});
103 const aliceBalanceAfter = await helper.balance.getSubstrate(alice.address);232 const aliceBalanceAfter = await helper.balance.getSubstrate(alice.address);
104233
105 console.log(`Calibrated price: ${Number(aliceBalanceBefore - aliceBalanceAfter) / Number(helper.balance.getOneTokenNominal())} UNQ`);234 console.log(`\t[NFT transfer] Calibrated price: ${Number(aliceBalanceBefore - aliceBalanceAfter) / Number(helper.balance.getOneTokenNominal())} UNQ`);
106 }235 }
107}236}
108237
121250
122 const cost = await helper.eth.calculateFee({Ethereum: caller}, () => contract.methods.transfer(receiver, token.tokenId).send({from: caller, gas: helper.eth.DEFAULT_GAS}));251 const cost = await helper.eth.calculateFee({Ethereum: caller}, () => contract.methods.transfer(receiver, token.tokenId).send({from: caller, gas: helper.eth.DEFAULT_GAS}));
123252
124 console.log(`Original price: ${Number(cost) / Number(helper.balance.getOneTokenNominal())} UNQ`);253 console.log(`\t[ETH NFT transfer] Original price: ${Number(cost) / Number(helper.balance.getOneTokenNominal())} UNQ`);
125 }254 }
126255
127 const api = helper.getApi();256 const api = helper.getApi();
128 const defaultCoeff = (api.consts.configuration.defaultMinGasPrice as any).toBigInt();257 // const defaultCoeff = (api.consts.configuration.defaultMinGasPrice as any).toBigInt();
258 const base = (await api.query.configuration.minGasPriceOverride() as any).toBigInt();
129 for (let i = -8; i < 8; i++) {259 for (let i = -8; i < 8; i++) {
130 const gasPrice = defaultCoeff + defaultCoeff / 100000n * BigInt(i);260 const gasPrice = base + base / 100000n * BigInt(i);
131 const gasPriceStr = '0x' + gasPrice.toString(16);261 const gasPriceStr = '0x' + gasPrice.toString(16);
132 await helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.configuration.setMinGasPriceOverride(gasPrice)));262 await helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.configuration.setMinGasPriceOverride(gasPrice)));
133263
134 const coefficient = (await api.query.configuration.minGasPriceOverride() as any).toBigInt();264 const coefficient = new Fract((await api.query.configuration.minGasPriceOverride() as any).toBigInt());
135 const collection = await helper.nft.mintCollection(alice, {name: 'New', description: 'New collection', tokenPrefix: 'NEW'});265 const collection = await helper.nft.mintCollection(alice, {name: 'New', description: 'New collection', tokenPrefix: 'NEW'});
136 const token = await collection.mintToken(alice, {Ethereum: caller});266 const token = await collection.mintToken(alice, {Ethereum: caller});
137267
138 const address = helper.ethAddress.fromCollectionId(collection.collectionId);268 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
139 const contract = helper.ethNativeContract.collection(address, 'nft', caller);269 const contract = helper.ethNativeContract.collection(address, 'nft', caller);
140270
141 const transferPrice = await helper.eth.calculateFee({Ethereum: caller}, () => contract.methods.transfer(receiver, token.tokenId).send({from: caller, gasPrice: gasPriceStr, gas: helper.eth.DEFAULT_GAS}));271 const transferPrice = new Fract(await helper.eth.calculateFee({Ethereum: caller}, () => contract.methods.transfer(receiver, token.tokenId).send({from: caller, gasPrice: gasPriceStr, gas: helper.eth.DEFAULT_GAS})));
142272
143 dataPoints.push({x: transferPrice, y: coefficient});273 dataPoints.push({x: transferPrice, y: coefficient});
144 }274 }
145275
146 const {a, b} = linearRegression(dataPoints);276 const {a, b} = linearRegression(dataPoints);
147277
148 // console.log(`Error: ${error(dataPoints, x => a*x+b)}`);278 const hyp = hypothesisLinear(a, b);
279 // console.log(`\t[ETH NFT transfer] Error: ${_error(dataPoints, hyp).toNumber()}`);
149280
150 // * 0.15 = * 10000 / 66666281 // 0.15 UNQ
151 const perfectValue = a * helper.balance.getOneTokenNominal() * 1000000n / 6666666n + b;282 const perfectValue = hyp(rpn(new Fract(helper.balance.getOneTokenNominal()), new Fract(15n, 100n), '*'));
152 await helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.configuration.setMinGasPriceOverride(perfectValue.toString())));283 await helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.configuration.setMinGasPriceOverride(perfectValue.toBigInt())));
153284
154 {285 {
155 const collection = await helper.nft.mintCollection(alice, {name: 'New', description: 'New collection', tokenPrefix: 'NEW'});286 const collection = await helper.nft.mintCollection(alice, {name: 'New', description: 'New collection', tokenPrefix: 'NEW'});
160291
161 const cost = await helper.eth.calculateFee({Ethereum: caller}, () => contract.methods.transfer(receiver, token.tokenId).send({from: caller, gas: helper.eth.DEFAULT_GAS}));292 const cost = await helper.eth.calculateFee({Ethereum: caller}, () => contract.methods.transfer(receiver, token.tokenId).send({from: caller, gas: helper.eth.DEFAULT_GAS}));
162293
163 console.log(`Calibrated price: ${Number(cost) / Number(helper.balance.getOneTokenNominal())} UNQ`);294 console.log(`\t[ETH NFT transfer] Calibrated price: ${Number(cost) / Number(helper.balance.getOneTokenNominal())} UNQ`);
164 }295 }
165}296}
166297
167(async () => {298(async () => {
168 await usingEthPlaygrounds(async (helper: EthUniqueHelper, privateKey) => {299 await usingEthPlaygrounds(async (helper: EthUniqueHelper, privateKey) => {
169 // Second run slightly reduces error sometimes, as price line is not actually straight, this is a curve300 // Subsequent runs reduce error, as price line is not actually straight, this is a curve
170301
171 await calibrateWeightToFee(helper, privateKey);302 const iterations = 3;
172 await calibrateWeightToFee(helper, privateKey);
173303
174 await calibrateMinGasPrice(helper, privateKey);304 console.log('[Calibrate WeightToFee]');
305 for (let i = 0; i < iterations; i++) {
306 await calibrateWeightToFee(helper, privateKey);
175 await calibrateMinGasPrice(helper, privateKey);307 }
308
309 console.log();
310
311 console.log('[Calibrate MinGasPrice]');
312 for (let i = 0; i < iterations; i++) {
313 await calibrateMinGasPrice(helper, privateKey);
314 }
176 });315 });
177})();316})();
178317
addedtests/src/eth/ethFeesAreCorrect.test.tsdiffbeforeafterboth
--- /dev/null
+++ b/tests/src/eth/ethFeesAreCorrect.test.ts
@@ -0,0 +1,66 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://witww.gnu.org/licenses/>.
+
+import {IKeyringPair} from '@polkadot/types/types';
+import {itEth, usingEthPlaygrounds, expect} from './util';
+
+describe('Eth fees are correct', () => {
+  let donor: IKeyringPair;
+  let minter: IKeyringPair;
+  let alice: IKeyringPair;
+
+  before(async () => {
+    await usingEthPlaygrounds(async (helper, privateKey) => {
+      donor = await privateKey({filename: __filename});
+      [minter, alice] = await helper.arrange.createAccounts([100n, 200n], donor);
+    });
+  });
+
+
+  itEth('web3 fees are the same as evm.call fees', async ({helper}) => {
+    const collection = await helper.nft.mintCollection(minter, {});
+    
+    const owner = await helper.eth.createAccountWithBalance(donor);
+    const receiver = await helper.eth.createAccountWithBalance(donor);
+    const aliceEth = helper.address.substrateToEth(alice.address);
+
+    const {tokenId: tokenA} = await collection.mintToken(minter, {Ethereum: owner});
+    const {tokenId: tokenB} = await collection.mintToken(minter, {Ethereum: aliceEth});
+
+    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+
+    const balanceBeforeWeb3Transfer = await helper.balance.getEthereum(owner);
+    await contract.methods.transfer(receiver, tokenA).send({from: owner});
+    const balanceAfterWeb3Transfer = await helper.balance.getEthereum(owner);
+    const web3Diff = balanceBeforeWeb3Transfer - balanceAfterWeb3Transfer;
+
+    const encodedCall = contract.methods.transfer(receiver, tokenB)
+      .encodeABI();
+    
+    const balanceBeforeEvmCall = await helper.balance.getSubstrate(alice.address);
+    await helper.eth.sendEVM(
+      alice,
+      collectionAddress,
+      encodedCall,
+      '0',
+    );
+    const balanceAfterEvmCall = await helper.balance.getSubstrate(alice.address);
+    const evmCallDiff = balanceBeforeEvmCall - balanceAfterEvmCall;
+
+    expect(web3Diff).to.be.equal(evmCallDiff);
+  });
+});
modifiedtests/src/interfaces/augment-api-consts.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-consts.ts
+++ b/tests/src/interfaces/augment-api-consts.ts
@@ -82,7 +82,7 @@
       appPromotionDailyRate: Perbill & AugmentedConst<ApiType>;
       dayRelayBlocks: u32 & AugmentedConst<ApiType>;
       defaultMinGasPrice: u64 & AugmentedConst<ApiType>;
-      defaultWeightToFeeCoefficient: u32 & AugmentedConst<ApiType>;
+      defaultWeightToFeeCoefficient: u64 & AugmentedConst<ApiType>;
       maxXcmAllowedLocations: u32 & AugmentedConst<ApiType>;
       /**
        * Generic const
modifiedtests/src/interfaces/augment-api-query.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-query.ts
+++ b/tests/src/interfaces/augment-api-query.ts
@@ -162,7 +162,7 @@
     configuration: {
       appPromomotionConfigurationOverride: AugmentedQuery<ApiType, () => Observable<PalletConfigurationAppPromotionConfiguration>, []> & QueryableStorageEntry<ApiType, []>;
       minGasPriceOverride: AugmentedQuery<ApiType, () => Observable<u64>, []> & QueryableStorageEntry<ApiType, []>;
-      weightToFeeCoefficientOverride: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;
+      weightToFeeCoefficientOverride: AugmentedQuery<ApiType, () => Observable<u64>, []> & QueryableStorageEntry<ApiType, []>;
       xcmAllowedLocationsOverride: AugmentedQuery<ApiType, () => Observable<Option<Vec<XcmV1MultiLocation>>>, []> & QueryableStorageEntry<ApiType, []>;
       /**
        * Generic query
modifiedtests/src/interfaces/augment-api-rpc.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-rpc.ts
+++ b/tests/src/interfaces/augment-api-rpc.ts
@@ -16,7 +16,7 @@
 import type { BlockHash } from '@polkadot/types/interfaces/chain';
 import type { PrefixedStorageKey } from '@polkadot/types/interfaces/childstate';
 import type { AuthorityId } from '@polkadot/types/interfaces/consensus';
-import type { CodeUploadRequest, CodeUploadResult, ContractCallRequest, ContractExecResult, ContractInstantiateResult, InstantiateRequest } from '@polkadot/types/interfaces/contracts';
+import type { CodeUploadRequest, CodeUploadResult, ContractCallRequest, ContractExecResult, ContractInstantiateResult, InstantiateRequestV1 } from '@polkadot/types/interfaces/contracts';
 import type { BlockStats } from '@polkadot/types/interfaces/dev';
 import type { CreatedBlock } from '@polkadot/types/interfaces/engine';
 import type { EthAccount, EthCallRequest, EthFeeHistory, EthFilter, EthFilterChanges, EthLog, EthReceipt, EthRichBlock, EthSubKind, EthSubParams, EthSyncStatus, EthTransaction, EthTransactionRequest, EthWork } from '@polkadot/types/interfaces/eth';
@@ -24,7 +24,7 @@
 import type { EncodedFinalityProofs, JustificationNotification, ReportedRoundStates } from '@polkadot/types/interfaces/grandpa';
 import type { MmrLeafBatchProof, MmrLeafProof } from '@polkadot/types/interfaces/mmr';
 import type { StorageKind } from '@polkadot/types/interfaces/offchain';
-import type { FeeDetails, RuntimeDispatchInfo } from '@polkadot/types/interfaces/payment';
+import type { FeeDetails, RuntimeDispatchInfoV1 } from '@polkadot/types/interfaces/payment';
 import type { RpcMethods } from '@polkadot/types/interfaces/rpc';
 import type { AccountId, AccountId32, BlockNumber, H160, H256, H64, Hash, Header, Index, Justification, KeyValue, SignedBlock, StorageData } from '@polkadot/types/interfaces/runtime';
 import type { MigrationStatusResult, ReadProof, RuntimeVersion, TraceBlockResponse } from '@polkadot/types/interfaces/state';
@@ -174,7 +174,7 @@
        * @deprecated Use the runtime interface `api.call.contractsApi.instantiate` instead
        * Instantiate a new contract
        **/
-      instantiate: AugmentedRpc<(request: InstantiateRequest | { origin?: any; value?: any; gasLimit?: any; storageDepositLimit?: any; code?: any; data?: any; salt?: any } | string | Uint8Array, at?: BlockHash | string | Uint8Array) => Observable<ContractInstantiateResult>>;
+      instantiate: AugmentedRpc<(request: InstantiateRequestV1 | { origin?: any; value?: any; gasLimit?: any; code?: any; data?: any; salt?: any } | string | Uint8Array, at?: BlockHash | string | Uint8Array) => Observable<ContractInstantiateResult>>;
       /**
        * @deprecated Not available in newer versions of the contracts interfaces
        * Returns the projected time a given contract will be able to sustain paying its rent
@@ -426,13 +426,15 @@
     };
     payment: {
       /**
+       * @deprecated Use `api.call.transactionPaymentApi.queryFeeDetails` instead
        * Query the detailed fee of a given encoded extrinsic
        **/
       queryFeeDetails: AugmentedRpc<(extrinsic: Bytes | string | Uint8Array, at?: BlockHash | string | Uint8Array) => Observable<FeeDetails>>;
       /**
+       * @deprecated Use `api.call.transactionPaymentApi.queryInfo` instead
        * Retrieves the fee information for an encoded extrinsic
        **/
-      queryInfo: AugmentedRpc<(extrinsic: Bytes | string | Uint8Array, at?: BlockHash | string | Uint8Array) => Observable<RuntimeDispatchInfo>>;
+      queryInfo: AugmentedRpc<(extrinsic: Bytes | string | Uint8Array, at?: BlockHash | string | Uint8Array) => Observable<RuntimeDispatchInfoV1>>;
     };
     rmrk: {
       /**
modifiedtests/src/interfaces/augment-api-runtime.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-runtime.ts
+++ b/tests/src/interfaces/augment-api-runtime.ts
@@ -6,7 +6,7 @@
 import '@polkadot/api-base/types/calls';
 
 import type { ApiTypes, AugmentedCall, DecoratedCallBase } from '@polkadot/api-base/types';
-import type { Bytes, Null, Option, Result, U256, Vec, bool, u256, u64 } from '@polkadot/types-codec';
+import type { Bytes, Null, Option, Result, U256, Vec, bool, u256, u32, u64 } from '@polkadot/types-codec';
 import type { AnyNumber, ITuple } from '@polkadot/types-codec/types';
 import type { CheckInherentsResult, InherentData } from '@polkadot/types/interfaces/blockbuilder';
 import type { BlockHash } from '@polkadot/types/interfaces/chain';
@@ -16,6 +16,7 @@
 import type { EvmAccount, EvmCallInfo, EvmCreateInfo } from '@polkadot/types/interfaces/evm';
 import type { Extrinsic } from '@polkadot/types/interfaces/extrinsics';
 import type { OpaqueMetadata } from '@polkadot/types/interfaces/metadata';
+import type { FeeDetails, RuntimeDispatchInfo } from '@polkadot/types/interfaces/payment';
 import type { AccountId, Block, H160, H256, Header, Index, KeyTypeId, Permill, SlotDuration } from '@polkadot/types/interfaces/runtime';
 import type { RuntimeVersion } from '@polkadot/types/interfaces/state';
 import type { ApplyExtrinsicResult, DispatchError } from '@polkadot/types/interfaces/system';
@@ -228,5 +229,20 @@
        **/
       [key: string]: DecoratedCallBase<ApiType>;
     };
+    /** 0x37c8bb1350a9a2a8/2 */
+    transactionPaymentApi: {
+      /**
+       * The transaction fee details
+       **/
+      queryFeeDetails: AugmentedCall<ApiType, (uxt: Extrinsic | IExtrinsic | string | Uint8Array, len: u32 | AnyNumber | Uint8Array) => Observable<FeeDetails>>;
+      /**
+       * The transaction info
+       **/
+      queryInfo: AugmentedCall<ApiType, (uxt: Extrinsic | IExtrinsic | string | Uint8Array, len: u32 | AnyNumber | Uint8Array) => Observable<RuntimeDispatchInfo>>;
+      /**
+       * Generic call
+       **/
+      [key: string]: DecoratedCallBase<ApiType>;
+    };
   } // AugmentedCalls
 } // declare module
modifiedtests/src/interfaces/augment-api-tx.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-tx.ts
+++ b/tests/src/interfaces/augment-api-tx.ts
@@ -217,7 +217,7 @@
     configuration: {
       setAppPromotionConfigurationOverride: AugmentedSubmittable<(configuration: PalletConfigurationAppPromotionConfiguration | { recalculationInterval?: any; pendingInterval?: any; intervalIncome?: any; maxStakersPerCalculation?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletConfigurationAppPromotionConfiguration]>;
       setMinGasPriceOverride: AugmentedSubmittable<(coeff: Option<u64> | null | Uint8Array | u64 | AnyNumber) => SubmittableExtrinsic<ApiType>, [Option<u64>]>;
-      setWeightToFeeCoefficientOverride: AugmentedSubmittable<(coeff: Option<u32> | null | Uint8Array | u32 | AnyNumber) => SubmittableExtrinsic<ApiType>, [Option<u32>]>;
+      setWeightToFeeCoefficientOverride: AugmentedSubmittable<(coeff: Option<u64> | null | Uint8Array | u64 | AnyNumber) => SubmittableExtrinsic<ApiType>, [Option<u64>]>;
       setXcmAllowedLocations: AugmentedSubmittable<(locations: Option<Vec<XcmV1MultiLocation>> | null | Uint8Array | Vec<XcmV1MultiLocation> | (XcmV1MultiLocation | { parents?: any; interior?: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [Option<Vec<XcmV1MultiLocation>>]>;
       /**
        * Generic tx
@@ -1432,6 +1432,23 @@
        **/
       destroyCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
       /**
+       * Repairs a collection if the data was somehow corrupted.
+       * 
+       * # Arguments
+       * 
+       * * `collection_id`: ID of the collection to repair.
+       **/
+      forceRepairCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;
+      /**
+       * Repairs a token if the data was somehow corrupted.
+       * 
+       * # Arguments
+       * 
+       * * `collection_id`: ID of the collection the item belongs to.
+       * * `item_id`: ID of the item.
+       **/
+      forceRepairItem: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32]>;
+      /**
        * Remove admin of a collection.
        * 
        * An admin address can remove itself. List of admins may become empty,
@@ -1474,15 +1491,6 @@
        * * `address`: ID of the address to be removed from the allowlist.
        **/
       removeFromAllowList: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, address: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;
-      /**
-       * Repairs a broken item
-       * 
-       * # Arguments
-       * 
-       * * `collection_id`: ID of the collection the item belongs to.
-       * * `item_id`: ID of the item.
-       **/
-      repairItem: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32]>;
       /**
        * Re-partition a refungible token, while owning all of its parts/pieces.
        * 
modifiedtests/src/interfaces/augment-types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-types.ts
+++ b/tests/src/interfaces/augment-types.ts
@@ -24,7 +24,7 @@
 import type { StatementKind } from '@polkadot/types/interfaces/claims';
 import type { CollectiveOrigin, MemberCount, ProposalIndex, Votes, VotesTo230 } from '@polkadot/types/interfaces/collective';
 import type { AuthorityId, RawVRFOutput } from '@polkadot/types/interfaces/consensus';
-import type { AliveContractInfo, CodeHash, CodeSource, CodeUploadRequest, CodeUploadResult, CodeUploadResultValue, ContractCallFlags, ContractCallRequest, ContractExecResult, ContractExecResultOk, ContractExecResultResult, ContractExecResultSuccessTo255, ContractExecResultSuccessTo260, ContractExecResultTo255, ContractExecResultTo260, ContractExecResultTo267, ContractInfo, ContractInstantiateResult, ContractInstantiateResultTo267, ContractInstantiateResultTo299, ContractReturnFlags, ContractStorageKey, DeletedContract, ExecReturnValue, Gas, HostFnWeights, HostFnWeightsTo264, InstantiateRequest, InstantiateRequestV1, InstantiateRequestV2, InstantiateReturnValue, InstantiateReturnValueOk, InstantiateReturnValueTo267, InstructionWeights, Limits, LimitsTo264, PrefabWasmModule, RentProjection, Schedule, ScheduleTo212, ScheduleTo258, ScheduleTo264, SeedOf, StorageDeposit, TombstoneContractInfo, TrieId } from '@polkadot/types/interfaces/contracts';
+import type { AliveContractInfo, CodeHash, CodeSource, CodeUploadRequest, CodeUploadResult, CodeUploadResultValue, ContractCallFlags, ContractCallRequest, ContractExecResult, ContractExecResultOk, ContractExecResultResult, ContractExecResultSuccessTo255, ContractExecResultSuccessTo260, ContractExecResultTo255, ContractExecResultTo260, ContractExecResultTo267, ContractExecResultU64, ContractInfo, ContractInstantiateResult, ContractInstantiateResultTo267, ContractInstantiateResultTo299, ContractInstantiateResultU64, ContractReturnFlags, ContractStorageKey, DeletedContract, ExecReturnValue, Gas, HostFnWeights, HostFnWeightsTo264, InstantiateRequest, InstantiateRequestV1, InstantiateRequestV2, InstantiateReturnValue, InstantiateReturnValueOk, InstantiateReturnValueTo267, InstructionWeights, Limits, LimitsTo264, PrefabWasmModule, RentProjection, Schedule, ScheduleTo212, ScheduleTo258, ScheduleTo264, SeedOf, StorageDeposit, TombstoneContractInfo, TrieId } from '@polkadot/types/interfaces/contracts';
 import type { ContractConstructorSpecLatest, ContractConstructorSpecV0, ContractConstructorSpecV1, ContractConstructorSpecV2, ContractConstructorSpecV3, ContractContractSpecV0, ContractContractSpecV1, ContractContractSpecV2, ContractContractSpecV3, ContractContractSpecV4, ContractCryptoHasher, ContractDiscriminant, ContractDisplayName, ContractEventParamSpecLatest, ContractEventParamSpecV0, ContractEventParamSpecV2, ContractEventSpecLatest, ContractEventSpecV0, ContractEventSpecV1, ContractEventSpecV2, ContractLayoutArray, ContractLayoutCell, ContractLayoutEnum, ContractLayoutHash, ContractLayoutHashingStrategy, ContractLayoutKey, ContractLayoutStruct, ContractLayoutStructField, ContractMessageParamSpecLatest, ContractMessageParamSpecV0, ContractMessageParamSpecV2, ContractMessageSpecLatest, ContractMessageSpecV0, ContractMessageSpecV1, ContractMessageSpecV2, ContractMetadata, ContractMetadataLatest, ContractMetadataV0, ContractMetadataV1, ContractMetadataV2, ContractMetadataV3, ContractMetadataV4, ContractProject, ContractProjectContract, ContractProjectInfo, ContractProjectSource, ContractProjectV0, ContractSelector, ContractStorageLayout, ContractTypeSpec } from '@polkadot/types/interfaces/contractsAbi';
 import type { FundIndex, FundInfo, LastContribution, TrieIndex } from '@polkadot/types/interfaces/crowdloan';
 import type { CollationInfo, CollationInfoV1, ConfigData, MessageId, OverweightIndex, PageCounter, PageIndexData } from '@polkadot/types/interfaces/cumulus';
@@ -47,7 +47,7 @@
 import type { StorageKind } from '@polkadot/types/interfaces/offchain';
 import type { DeferredOffenceOf, Kind, OffenceDetails, Offender, OpaqueTimeSlot, ReportIdOf, Reporter } from '@polkadot/types/interfaces/offences';
 import type { AbridgedCandidateReceipt, AbridgedHostConfiguration, AbridgedHrmpChannel, AssignmentId, AssignmentKind, AttestedCandidate, AuctionIndex, AuthorityDiscoveryId, AvailabilityBitfield, AvailabilityBitfieldRecord, BackedCandidate, Bidder, BufferedSessionChange, CandidateCommitments, CandidateDescriptor, CandidateEvent, CandidateHash, CandidateInfo, CandidatePendingAvailability, CandidateReceipt, CollatorId, CollatorSignature, CommittedCandidateReceipt, CoreAssignment, CoreIndex, CoreOccupied, CoreState, DisputeLocation, DisputeResult, DisputeState, DisputeStatement, DisputeStatementSet, DoubleVoteReport, DownwardMessage, ExplicitDisputeStatement, GlobalValidationData, GlobalValidationSchedule, GroupIndex, GroupRotationInfo, HeadData, HostConfiguration, HrmpChannel, HrmpChannelId, HrmpOpenChannelRequest, InboundDownwardMessage, InboundHrmpMessage, InboundHrmpMessages, IncomingParachain, IncomingParachainDeploy, IncomingParachainFixed, InvalidDisputeStatementKind, LeasePeriod, LeasePeriodOf, LocalValidationData, MessageIngestionType, MessageQueueChain, MessagingStateSnapshot, MessagingStateSnapshotEgressEntry, MultiDisputeStatementSet, NewBidder, OccupiedCore, OccupiedCoreAssumption, OldV1SessionInfo, OutboundHrmpMessage, ParaGenesisArgs, ParaId, ParaInfo, ParaLifecycle, ParaPastCodeMeta, ParaScheduling, ParaValidatorIndex, ParachainDispatchOrigin, ParachainInherentData, ParachainProposal, ParachainsInherentData, ParathreadClaim, ParathreadClaimQueue, ParathreadEntry, PersistedValidationData, PvfCheckStatement, QueuedParathread, RegisteredParachainInfo, RelayBlockNumber, RelayChainBlockNumber, RelayChainHash, RelayHash, Remark, ReplacementTimes, Retriable, ScheduledCore, Scheduling, ScrapedOnChainVotes, ServiceQuality, SessionInfo, SessionInfoValidatorGroup, SignedAvailabilityBitfield, SignedAvailabilityBitfields, SigningContext, SlotRange, SlotRange10, Statement, SubId, SystemInherentData, TransientValidationData, UpgradeGoAhead, UpgradeRestriction, UpwardMessage, ValidDisputeStatementKind, ValidationCode, ValidationCodeHash, ValidationData, ValidationDataType, ValidationFunctionParams, ValidatorSignature, ValidityAttestation, VecInboundHrmpMessage, WinnersData, WinnersData10, WinnersDataTuple, WinnersDataTuple10, WinningData, WinningData10, WinningDataEntry } from '@polkadot/types/interfaces/parachains';
-import type { FeeDetails, InclusionFee, RuntimeDispatchInfo } from '@polkadot/types/interfaces/payment';
+import type { FeeDetails, InclusionFee, RuntimeDispatchInfo, RuntimeDispatchInfoV1, RuntimeDispatchInfoV2 } from '@polkadot/types/interfaces/payment';
 import type { Approvals } from '@polkadot/types/interfaces/poll';
 import type { ProxyAnnouncement, ProxyDefinition, ProxyType } from '@polkadot/types/interfaces/proxy';
 import type { AccountStatus, AccountValidity } from '@polkadot/types/interfaces/purchase';
@@ -273,10 +273,12 @@
     ContractExecResultTo255: ContractExecResultTo255;
     ContractExecResultTo260: ContractExecResultTo260;
     ContractExecResultTo267: ContractExecResultTo267;
+    ContractExecResultU64: ContractExecResultU64;
     ContractInfo: ContractInfo;
     ContractInstantiateResult: ContractInstantiateResult;
     ContractInstantiateResultTo267: ContractInstantiateResultTo267;
     ContractInstantiateResultTo299: ContractInstantiateResultTo299;
+    ContractInstantiateResultU64: ContractInstantiateResultU64;
     ContractLayoutArray: ContractLayoutArray;
     ContractLayoutCell: ContractLayoutCell;
     ContractLayoutEnum: ContractLayoutEnum;
@@ -1057,6 +1059,8 @@
     RpcMethods: RpcMethods;
     RuntimeDbWeight: RuntimeDbWeight;
     RuntimeDispatchInfo: RuntimeDispatchInfo;
+    RuntimeDispatchInfoV1: RuntimeDispatchInfoV1;
+    RuntimeDispatchInfoV2: RuntimeDispatchInfoV2;
     RuntimeVersion: RuntimeVersion;
     RuntimeVersionApi: RuntimeVersionApi;
     RuntimeVersionPartial: RuntimeVersionPartial;
modifiedtests/src/interfaces/default/types.tsdiffbeforeafterboth
--- a/tests/src/interfaces/default/types.ts
+++ b/tests/src/interfaces/default/types.ts
@@ -1303,7 +1303,7 @@
 export interface PalletConfigurationCall extends Enum {
   readonly isSetWeightToFeeCoefficientOverride: boolean;
   readonly asSetWeightToFeeCoefficientOverride: {
-    readonly coeff: Option<u32>;
+    readonly coeff: Option<u64>;
   } & Struct;
   readonly isSetMinGasPriceOverride: boolean;
   readonly asSetMinGasPriceOverride: {
@@ -2319,12 +2319,16 @@
     readonly operator: PalletEvmAccountBasicCrossAccountIdRepr;
     readonly approve: bool;
   } & Struct;
-  readonly isRepairItem: boolean;
-  readonly asRepairItem: {
+  readonly isForceRepairCollection: boolean;
+  readonly asForceRepairCollection: {
+    readonly collectionId: u32;
+  } & Struct;
+  readonly isForceRepairItem: boolean;
+  readonly asForceRepairItem: {
     readonly collectionId: u32;
     readonly itemId: u32;
   } & Struct;
-  readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition' | 'SetAllowanceForAll' | 'RepairItem';
+  readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition' | 'SetAllowanceForAll' | 'ForceRepairCollection' | 'ForceRepairItem';
 }
 
 /** @name PalletUniqueError */
modifiedtests/src/interfaces/lookup.tsdiffbeforeafterboth
--- a/tests/src/interfaces/lookup.ts
+++ b/tests/src/interfaces/lookup.ts
@@ -2282,8 +2282,11 @@
         operator: 'PalletEvmAccountBasicCrossAccountIdRepr',
         approve: 'bool',
       },
-      repair_item: {
+      force_repair_collection: {
         collectionId: 'u32',
+      },
+      force_repair_item: {
+        collectionId: 'u32',
         itemId: 'u32'
       }
     }
@@ -2452,7 +2455,7 @@
   PalletConfigurationCall: {
     _enum: {
       set_weight_to_fee_coefficient_override: {
-        coeff: 'Option<u32>',
+        coeff: 'Option<u64>',
       },
       set_min_gas_price_override: {
         coeff: 'Option<u64>',
modifiedtests/src/interfaces/types-lookup.tsdiffbeforeafterboth
--- a/tests/src/interfaces/types-lookup.ts
+++ b/tests/src/interfaces/types-lookup.ts
@@ -2517,12 +2517,16 @@
       readonly operator: PalletEvmAccountBasicCrossAccountIdRepr;
       readonly approve: bool;
     } & Struct;
-    readonly isRepairItem: boolean;
-    readonly asRepairItem: {
+    readonly isForceRepairCollection: boolean;
+    readonly asForceRepairCollection: {
+      readonly collectionId: u32;
+    } & Struct;
+    readonly isForceRepairItem: boolean;
+    readonly asForceRepairItem: {
       readonly collectionId: u32;
       readonly itemId: u32;
     } & Struct;
-    readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition' | 'SetAllowanceForAll' | 'RepairItem';
+    readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition' | 'SetAllowanceForAll' | 'ForceRepairCollection' | 'ForceRepairItem';
   }
 
   /** @name UpDataStructsCollectionMode (237) */
@@ -2675,7 +2679,7 @@
   interface PalletConfigurationCall extends Enum {
     readonly isSetWeightToFeeCoefficientOverride: boolean;
     readonly asSetWeightToFeeCoefficientOverride: {
-      readonly coeff: Option<u32>;
+      readonly coeff: Option<u64>;
     } & Struct;
     readonly isSetMinGasPriceOverride: boolean;
     readonly asSetMinGasPriceOverride: {
modifiedtests/src/nesting/collectionProperties.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/collectionProperties.test.ts
+++ b/tests/src/nesting/collectionProperties.test.ts
@@ -209,7 +209,7 @@
   before(async () => {
     await usingPlaygrounds(async (helper, privateKey) => {
       const donor = await privateKey({filename: __filename});
-      [alice, bob] = await helper.arrange.createAccounts([100n, 10n], donor);
+      [alice, bob] = await helper.arrange.createAccounts([1000n, 100n], donor);
     });
   });