Skip to content

Commit

Permalink
feat(runtime-eden): add bridge_all_vesting_schedules (#872)
Browse files Browse the repository at this point in the history
  • Loading branch information
aliXsed authored Jul 18, 2024
1 parent f1b9390 commit 9d95038
Show file tree
Hide file tree
Showing 9 changed files with 635 additions and 19 deletions.
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.

22 changes: 13 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ members = ["node", "pallets/*", "primitives", "runtimes/*", "support"]
resolver = "1"

[workspace.package]
version= "2.5.3"
version = "2.5.3"
authors = ["Nodle Developers <[email protected]>"]
edition = "2021"

Expand All @@ -28,7 +28,7 @@ cumulus-primitives-core = { version = "0.7.0", default-features = false }
cumulus-primitives-parachain-inherent = { version = "0.7.0", default-features = false }
cumulus-primitives-timestamp = { version = "0.7.0", default-features = false }
cumulus-primitives-utility = { version = "0.7.0", default-features = false }
cumulus-client-consensus-proposer = { version = "0.7.0", default-features = false}
cumulus-client-consensus-proposer = { version = "0.7.0", default-features = false }
cumulus-relay-chain-inprocess-interface = { version = "0.7.0", default-features = false }
cumulus-relay-chain-interface = { version = "0.7.0", default-features = false }
cumulus-relay-chain-rpc-interface = { version = "0.7.0", default-features = false }
Expand Down Expand Up @@ -103,7 +103,7 @@ sp-core = { version = "28.0.0", default-features = false }
sp-inherents = { version = "26.0.0", default-features = false }
sp-io = { version = "30.0.0", default-features = false }
sp-keystore = { version = "0.34.0", default-features = false }
sp-genesis-builder = { version = "0.7.0", default-features = false}
sp-genesis-builder = { version = "0.7.0", default-features = false }
sp-npos-elections = { version = "26.0.0", default-features = false }
sp-offchain = { version = "26.0.0", default-features = false }
sp-runtime = { version = "31.0.0", default-features = false }
Expand All @@ -119,25 +119,29 @@ sp-version = { version = "29.0.0", default-features = false }
substrate-build-script-utils = { version = "11.0.0", default-features = false }
substrate-prometheus-endpoint = { version = "0.17.0", default-features = false }
substrate-wasm-builder = { version = "17.0.0", default-features = false }
xcm-builder = { package="staging-xcm-builder", version = "7.0.0", default-features = false }
xcm-executor = { package="staging-xcm-executor", version = "7.0.0", default-features = false }
xcm = { package = "staging-xcm", version = "7.0.0", default-features = false}
xcm-builder = { package = "staging-xcm-builder", version = "7.0.0", default-features = false }
xcm-executor = { package = "staging-xcm-executor", version = "7.0.0", default-features = false }
xcm = { package = "staging-xcm", version = "7.0.0", default-features = false }

#ORML
orml-xtokens = { version = "0.7.0", default-features = false }
orml-traits = { version = "0.7.0", default-features = false }

#Crates
clap = { version = "4.1.8", features = ["derive"] }
codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false}
codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false }
derive_more = "0.99.2"
getrandom = { version = "0.2", features = ["js"] }
hex-literal = { version = "0.4.1" }
jsonrpsee = { version = "0.16.2", features = ["server"] }
lazy_static = {version = "1.4.0", default-features = false, features = ["spin_no_std"] }
lazy_static = { version = "1.4.0", default-features = false, features = [
"spin_no_std",
] }
log = { version = "0.4.17", default-features = false }
safe-mix = { version = "1.0.1", default-features = false }
scale-info = { version = "2.5.0", default-features = false, features = ["derive"] }
scale-info = { version = "2.5.0", default-features = false, features = [
"derive",
] }
serde = { version = "1.0.152", default-features = false }
serde_json = { version = "1.0.104", default-features = false }
static_assertions = "1.1.0"
Expand Down
9 changes: 4 additions & 5 deletions node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ runtime-benchmarks = [
[dependencies]
clap = { workspace = true, features = ["derive"] }
derive_more.workspace = true
log = { workspace = true, default-features = true}
log = { workspace = true, default-features = true }
codec.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
Expand Down Expand Up @@ -99,7 +99,6 @@ polkadot-cli.workspace = true
polkadot-parachain-primitives.workspace = true
polkadot-primitives.workspace = true
polkadot-service.workspace = true
xcm = { workspace = true, default-features = false}
hex-literal = "0.4.1"
[dev-dependencies]
hex-literal = {workspace = true }
xcm = { workspace = true, default-features = false }

hex-literal = { workspace = true }
9 changes: 7 additions & 2 deletions pallets/grants/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ std = [
"codec/std",
"serde",
"frame-support/std",
"frame-benchmarking/std",

"frame-system/std",
"pallet-balances/std",
"sp-runtime/std",
Expand All @@ -25,6 +27,7 @@ std = [
runtime-benchmarks = [
"frame-benchmarking",
"frame-system/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"frame-support/runtime-benchmarks",
]
try-runtime = ["frame-support/try-runtime"]
Expand All @@ -33,16 +36,18 @@ try-runtime = ["frame-support/try-runtime"]
log = { workspace = true, default-features = false }
codec = { workspace = true, default-features = false, features = ["derive"] }
serde = { workspace = true, optional = true }
scale-info = { workspace = true, default-features = false, features = ["derive"] }
scale-info = { workspace = true, default-features = false, features = [
"derive",
] }
frame-benchmarking = { workspace = true, default-features = false, optional = true }
frame-support = { workspace = true, default-features = false }
frame-system = { workspace = true, default-features = false }
pallet-balances = { workspace = true, default-features = false }
sp-io = { workspace = true, default-features = false }
sp-runtime = { workspace = true, default-features = false }
sp-std = { workspace = true, default-features = false }
hex-literal = { workspace = true }

[dev-dependencies]
sp-core = { workspace = true, default-features = false }
sp-tracing = { workspace = true, default-features = false }

29 changes: 28 additions & 1 deletion pallets/grants/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use crate::Pallet as Grants;
use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, BenchmarkError};
use frame_support::traits::{EnsureOrigin, Get, UnfilteredDispatchable};
use frame_system::RawOrigin;
use hex_literal::hex;
use sp_runtime::traits::Bounded;
use sp_std::prelude::*;

Expand Down Expand Up @@ -98,7 +99,33 @@ benchmarks! {
let origin = T::CancelOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
}: { call.dispatch_bypass_filter(origin)? }

renounce {
bridge_all_vesting_schedules {
let config = create_shared_config::<T>(1);
let bridge_name = b"zklocal";
let bridge_id = 1;
let remote_chain_id = 9924;
Pallet::<T>::set_bridge(RawOrigin::Root.into(), bridge_id, bridge_name.to_vec(), remote_chain_id)?;

for _x in 1 .. T::MaxSchedule::get() {
Pallet::<T>::do_add_vesting_schedule(&config.granter, &config.grantee, config.schedule.clone())?;
}

}: _(RawOrigin::Signed(config.grantee.clone()), hex!("2E7F3926Ae74FDCDcAde2c2AB50990C5daFD42bD"), bridge_id)

set_bridge {
let bridge_name = b"bridge_between_eden_zks_main_era";
let bridge_id = 1;
let remote_chain_id = 300;
}: _(RawOrigin::Root, bridge_id, bridge_name.to_vec(), remote_chain_id)

remove_bridge {
let bridge_name = b"bridge_between_eden_zks_main_era";
let bridge_id = 1;
let remote_chain_id = 300;
Pallet::<T>::set_bridge(RawOrigin::Root.into(), bridge_id, bridge_name.to_vec(), remote_chain_id)?;
}: _(RawOrigin::Root, bridge_id)

renounce {
let config = create_shared_config::<T>(1);
let call = Call::<T>::renounce{
who: config.grantee_lookup,
Expand Down
120 changes: 118 additions & 2 deletions pallets/grants/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use frame_support::{
BoundedVec,
};
use sp_runtime::{
traits::{AtLeast32Bit, BlockNumberProvider, CheckedAdd, Saturating, StaticLookup, Zero},
traits::{AtLeast32Bit, BlockNumberProvider, CheckedAdd, ConstU32, Saturating, StaticLookup, Zero},
DispatchResult, RuntimeDebug,
};
use sp_std::{
Expand Down Expand Up @@ -77,6 +77,19 @@ pub struct VestingSchedule<BlockNumber, Balance> {
pub per_period: Balance,
}

const BRIDGE_NAME_MAX_LENGTH: u32 = 32;

// A unique identifier for a bridge between parachain and a remote ethereum based chain/rollup.
#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, scale_info::TypeInfo)]
pub struct BridgeId(u32);

// Details of a bridge between parachain and a remote ethereum based chain/rollup.
#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, scale_info::TypeInfo)]
pub struct BridgeDetails {
chain_id: u64,
name: BoundedVec<u8, ConstU32<BRIDGE_NAME_MAX_LENGTH>>,
}

impl<BlockNumber: AtLeast32Bit + Copy, Balance: AtLeast32Bit + Copy> VestingSchedule<BlockNumber, Balance> {
/// Returns the end of all periods, `None` if calculation overflows.
pub fn end(&self) -> Option<BlockNumber> {
Expand Down Expand Up @@ -109,7 +122,7 @@ impl<BlockNumber: AtLeast32Bit + Copy, Balance: AtLeast32Bit + Copy> VestingSche
#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_support::pallet_prelude::{DispatchResultWithPostInfo, *};
use frame_support::pallet_prelude::{DispatchResultWithPostInfo, OptionQuery, *};
use frame_system::pallet_prelude::*;

#[pallet::config]
Expand Down Expand Up @@ -214,6 +227,90 @@ pub mod pallet {

Ok(().into())
}

/// Initiate a bridge transfer of all vested funds to the given `eth_address` on the given `chain_id`.
/// This process will need to be completed by the bridge oracles.
#[pallet::call_index(4)]
#[pallet::weight(T::WeightInfo::bridge_all_vesting_schedules())]
pub fn bridge_all_vesting_schedules(
origin: OriginFor<T>,
eth_address: [u8; 20],
bridge_id: u32,
) -> DispatchResultWithPostInfo {
let from = ensure_signed(origin)?;
ensure!(
Bridges::<T>::contains_key(&BridgeId(bridge_id)),

Check warning on line 242 in pallets/grants/src/lib.rs

View workflow job for this annotation

GitHub Actions / lints

the borrowed expression implements the required traits

warning: the borrowed expression implements the required traits --> pallets/grants/src/lib.rs:242:32 | 242 | Bridges::<T>::contains_key(&BridgeId(bridge_id)), | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `BridgeId(bridge_id)` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrows_for_generic_args = note: `#[warn(clippy::needless_borrows_for_generic_args)]` on by default
Error::<T>::BridgeNotFound
);

let locked_amount_left = Self::do_claim(&from);
if locked_amount_left.is_zero() {
<VestingSchedules<T>>::remove(from);
Self::deposit_event(Event::NoVestedFundsToBridgeAfterClaim);
return Ok(().into());
}

let free_balance = T::Currency::free_balance(&from);
let bridgeable_funds = locked_amount_left.min(free_balance);

T::Currency::remove_lock(VESTING_LOCK_ID, &from);
T::Currency::settle(
&from,
T::Currency::burn(bridgeable_funds),
WithdrawReasons::RESERVE,
ExistenceRequirement::AllowDeath,
)
.map_err(|_| Error::<T>::FailedToSettleBridge)?;

let grants = <VestingSchedules<T>>::take(&from);

Self::deposit_event(Event::BridgeInitiated {
to: eth_address,
bridge_id,
amount: bridgeable_funds,
grants,
});

Ok(().into())
}

/// Allow governance to indicate a bridge is setup between the parachain and a remote chain.
#[pallet::call_index(5)]
#[pallet::weight(T::WeightInfo::set_bridge())]
pub fn set_bridge(
origin: OriginFor<T>,
bridge_id: u32,
bridge_name: Vec<u8>,
remote_chain_id: u64,
) -> DispatchResultWithPostInfo {
ensure_root(origin)?;

let id = BridgeId(bridge_id);
ensure!(!Bridges::<T>::contains_key(&id), Error::<T>::BridgeAlreadyExists);

let details = BridgeDetails {
chain_id: remote_chain_id,
name: bridge_name.try_into().map_err(|_| Error::<T>::BridgeNameTooLong)?,
};

Bridges::<T>::insert(id, details);

Ok(().into())
}

/// Remove a bridge from the list of active bridges.
#[pallet::call_index(6)]
#[pallet::weight(T::WeightInfo::remove_bridge())]
pub fn remove_bridge(origin: OriginFor<T>, bridge_id: u32) -> DispatchResultWithPostInfo {
ensure_root(origin)?;

let id = BridgeId(bridge_id);
ensure!(Bridges::<T>::contains_key(&id), Error::<T>::BridgeNotFound);

Bridges::<T>::remove(&id);

Ok(().into())
}
}

#[pallet::event]
Expand All @@ -227,6 +324,17 @@ pub mod pallet {
VestingSchedulesCanceled(T::AccountId),
/// Renounced rights to cancel grant for the given account id \[who\]
Renounced(T::AccountId),
/// Initiated a bridge transfer of all vested funds \[to, chain_id, amount, grants\]
/// The field amount is crucial for the bridge because it shows the total entitlement of the user on the other side of the bridge.
BridgeInitiated {
to: [u8; 20],
bridge_id: u32,
amount: BalanceOf<T>,
grants: BoundedVec<VestingScheduleOf<T>, T::MaxSchedule>,
},
/// Bridge was initiated and successfully completed one sidedly because
/// there were no vested funds to bridge after claiming free tokens for the user.
NoVestedFundsToBridgeAfterClaim,
}

#[pallet::error]
Expand All @@ -239,6 +347,10 @@ pub mod pallet {
VestingToSelf,
MaxScheduleOverflow,
Renounced,
FailedToSettleBridge,
BridgeAlreadyExists,
BridgeNotFound,
BridgeNameTooLong,
}

#[pallet::storage]
Expand All @@ -255,6 +367,10 @@ pub mod pallet {
#[pallet::getter(fn renounced)]
pub type Renounced<T: Config> = StorageMap<_, Blake2_128Concat, T::AccountId, bool, ValueQuery>;

#[pallet::storage]
#[pallet::getter(fn bridges)]
pub type Bridges<T: Config> = StorageMap<_, Blake2_128Concat, BridgeId, BridgeDetails, OptionQuery>;

#[pallet::storage]
pub(crate) type StorageVersion<T: Config> = StorageValue<_, Releases, ValueQuery>;

Expand Down
Loading

0 comments on commit 9d95038

Please sign in to comment.