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

(All Runtimes) Parametrize the deposit for pallet_randomness #2941

Merged
merged 22 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
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
1 change: 1 addition & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions runtime/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ xcm-fee-payment-runtime-api = { workspace = true }

# Parity
parity-scale-codec = { workspace = true }
scale-info = { workspace = true }

account = { workspace = true }

Expand Down Expand Up @@ -118,6 +119,7 @@ std = [
"pallet-xcm-weight-trader/std",
"pallet-message-queue/std",
"parity-scale-codec/std",
"scale-info/std",
"precompile-utils/std",
"sp-consensus-slots/std",
"sp-core/std",
Expand Down
1 change: 1 addition & 0 deletions runtime/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ mod impl_self_contained_call;
mod impl_xcm_evm_runner;
pub mod migrations;
pub mod timestamp;
pub mod types;
pub mod weights;

#[cfg(feature = "runtime-benchmarks")]
Expand Down
131 changes: 131 additions & 0 deletions runtime/common/src/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// Copyright 2024 Moonbeam Foundation.
// This file is part of Moonbeam.

// Moonbeam 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.

// Moonbeam 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 Moonbeam. If not, see <http://www.gnu.org/licenses/>.
use parity_scale_codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
use scale_info::TypeInfo;
use sp_std::prelude::*;

#[derive(Debug, PartialEq, Eq, Clone, Copy, Encode, TypeInfo, MaxEncodedLen)]
#[scale_info(skip_type_params(LOWER, UPPER))]
pub struct BoundedU128<const LOWER: u128, const UPPER: u128>(u128);

impl<const L: u128, const U: u128> BoundedU128<L, U> {
pub fn new(value: u128) -> Result<Self, &'static str> {
if value < L || value > U {
return Err("Value out of bounds");
}
Ok(Self(value))
}

pub fn safe_new<const VAL: u128>() -> Self {
TarekkMA marked this conversation as resolved.
Show resolved Hide resolved
if VAL < L {
Self(L)
} else if VAL > U {
Self(U)
} else {
Self(VAL)
}
}

pub fn value(&self) -> u128 {
self.0
}
}

impl<const L: u128, const U: u128> Decode for BoundedU128<L, U> {
fn decode<I: parity_scale_codec::Input>(
input: &mut I,
) -> Result<Self, parity_scale_codec::Error> {
let value = u128::decode(input)?;
if value < L || value > U {
return Err("Value out of bounds".into());
}
Ok(Self(value))
}
}

impl<const L: u128, const U: u128> EncodeLike<u128> for BoundedU128<L, U> {}

#[macro_export]
macro_rules! expose_u128_get {
($name:ident,$bounded_get:ty) => {
pub struct $name;

impl sp_core::Get<u128> for $name {
fn get() -> u128 {
<$bounded_get>::get().value()
}
}
};
}

#[cfg(test)]
mod tests {
use frame_support::parameter_types;
use sp_core::Get;

use super::*;

#[test]
fn test_bounded_u128() {
let bounded = BoundedU128::<1, 10>::new(5).unwrap();
assert_eq!(bounded.value(), 5);

let bounded = BoundedU128::<1, 10>::new(0);
assert_eq!(bounded, Err("Value out of bounds"));

let bounded = BoundedU128::<1, 10>::new(11);
assert_eq!(bounded, Err("Value out of bounds"));

let bounded = BoundedU128::<1, 10>::safe_new::<0>();
assert_eq!(bounded.value(), 1);

let bounded = BoundedU128::<1, 10>::safe_new::<5>();
assert_eq!(bounded.value(), 5);

let bounded = BoundedU128::<1, 10>::safe_new::<11>();
assert_eq!(bounded.value(), 10);
}

#[test]
fn test_expose_u128_get() {
parameter_types! {
pub Bounded: BoundedU128::<1, 10> = BoundedU128::<1, 10>::new(4).unwrap();
}
expose_u128_get!(Exposed, Bounded);
assert_eq!(Bounded::get().value(), Exposed::get());
}

#[test]
fn test_encode_decode() {
let bounded = BoundedU128::<1, 10>::new(5).unwrap();
let encoded = bounded.encode();
let decoded = BoundedU128::<1, 10>::decode(&mut &encoded[..]).unwrap();
assert_eq!(bounded, decoded);
}

#[test]
fn test_encode_invalid() {
let bounded = BoundedU128::<1, 10>::new(9);
let encoded = bounded.encode();
let decoded = BoundedU128::<1, 3>::decode(&mut &encoded[..]);
assert_eq!(decoded, Err("Value out of bounds".into()));

let bounded = BoundedU128::<1, 10>::new(9);
let encoded = bounded.encode();
let decoded = BoundedU128::<100, 500>::decode(&mut &encoded[..]);
assert_eq!(decoded, Err("Value out of bounds".into()));
}
}
2 changes: 1 addition & 1 deletion runtime/moonbase/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1355,7 +1355,7 @@ impl pallet_randomness::Config for Runtime {
type Currency = Balances;
type BabeDataGetter = BabeDataGetter<Runtime>;
type VrfKeyLookup = AuthorMapping;
type Deposit = ConstU128<{ 1 * currency::UNIT * currency::SUPPLY_FACTOR }>;
type Deposit = runtime_params::PalletRandomnessDepositU128;
type MaxRandomWords = ConstU8<100>;
type MinBlockDelay = ConstU32<2>;
type MaxBlockDelay = ConstU32<2_000>;
Expand Down
19 changes: 18 additions & 1 deletion runtime/moonbase/src/runtime_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
// along with Moonbeam. If not, see <http://www.gnu.org/licenses/>.

//! Dynamic runtime parametes.
use crate::Runtime;
use crate::{currency, Runtime};
use frame_support::dynamic_params::{dynamic_pallet_params, dynamic_params};
use moonbeam_runtime_common::expose_u128_get;
use moonbeam_runtime_common::types::BoundedU128;
use sp_runtime::Perbill;

#[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::<Runtime>)]
Expand All @@ -29,8 +31,23 @@ pub mod dynamic_params {
#[codec(index = 0)]
pub static FeesTreasuryProportion: Perbill = Perbill::from_percent(20);
}

#[dynamic_pallet_params]
#[codec(index = 1)]
pub mod pallet_randomness {
#[codec(index = 0)]
pub static Deposit: BoundedU128<
{ 1 * currency::UNIT * currency::SUPPLY_FACTOR },
{ 1_000 * currency::UNIT * currency::SUPPLY_FACTOR },
> = BoundedU128::safe_new::<{ 1 * currency::UNIT * currency::SUPPLY_FACTOR }>();
}
}

expose_u128_get!(
PalletRandomnessDepositU128,
dynamic_params::pallet_randomness::Deposit
);

#[cfg(feature = "runtime-benchmarks")]
impl Default for RuntimeParameters {
fn default() -> Self {
Expand Down
56 changes: 55 additions & 1 deletion test/suites/dev/moonbase/test-parameters/test-parameters.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { describeSuite, DevModeContext, expect } from "@moonwall/cli";
import "@moonbeam-network/api-augment";
import { alith } from "@moonwall/util";

import { fail } from "assert";
const UNIT = 1_000_000_000_000_000_000n;

const RUNTIME = "MoonbaseRuntime";
Expand Down Expand Up @@ -83,5 +83,59 @@ describeSuite({
}

testParam("RuntimeConfig", "FeesTreasuryProportion", ["Perbill", 200_000_000]);
testParam("PalletRandomness", "Deposit", ["u128", UNIT * 100n]);

it({
id: `T${testCounter++} - PalletRandomness - Deposit - CustomTests`,
title: "Deposit parameter should only be accepted in bounds",
test: async () => {
const MIN = 1n * UNIT;
const MAX = 1000n * UNIT;

// used as an acceptable value
const AVG = (MIN + MAX) / 2n;

const param1 = parameterType(context, "PalletRandomness", "Deposit", MIN - 1n);
try {
await context.createBlock(
context
.polkadotJs()
.tx.sudo.sudo(context.polkadotJs().tx.parameters.setParameter(param1.toU8a()))
.signAsync(alith),
{ allowFailures: false }
);
fail("An extrinsic should not be created, since the parameter is invalid");
} catch (error) {
expect(error.toString().toLowerCase()).to.contain("value out of bounds");
}

const param2 = parameterType(context, "PalletRandomness", "Deposit", MAX + 1n);
try {
await context.createBlock(
context
.polkadotJs()
.tx.sudo.sudo(context.polkadotJs().tx.parameters.setParameter(param2.toU8a()))
.signAsync(alith),
{ allowFailures: false }
);
fail("An extrinsic should not be created, since the parameter is invalid");
} catch (error) {
expect(error.toString().toLowerCase()).to.contain("value out of bounds");
}

const param3 = parameterType(context, "PalletRandomness", "Deposit", AVG);
const res3 = await context.createBlock(
context
.polkadotJs()
.tx.sudo.sudo(context.polkadotJs().tx.parameters.setParameter(param3.toU8a()))
.signAsync(alith),
{ allowFailures: false }
);
expect(
res3.result?.successful,
"An extrinsic should be created, since the parameter is valid"
).to.be.true;
},
});
},
});
Loading