Skip to content

Commit

Permalink
Merge branch 'main' into pallet-pass
Browse files Browse the repository at this point in the history
  • Loading branch information
pandres95 authored Oct 7, 2024
2 parents 6341c26 + dae50bf commit 1b1d41d
Show file tree
Hide file tree
Showing 6 changed files with 402 additions and 1 deletion.
18 changes: 18 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"rust-analyzer.lens.references.trait.enable": true,
"rust-analyzer.checkOnSave": true,
"rust-analyzer.cargo.features": [
"runtime-benchmarks",
],
"rust-analyzer.showUnlinkedFileNotification": false,
"rust-analyzer.rustfmt.extraArgs": [
"+stable"
],
"[rust]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "rust-lang.rust-analyzer"
},
"[toml]": {
"editor.formatOnSave": false
}
}
7 changes: 7 additions & 0 deletions Cargo.lock

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

18 changes: 17 additions & 1 deletion traits/gas-tank/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,26 @@ repository.workspace = true
version = "0.1.0"

[dependencies]
frame-support = {workspace = true}
codec.workspace = true
frame-support.workspace = true
frame-system.workspace = true
sp-runtime.workspace = true

[dev-dependencies]
pallet-balances.workspace = true
pallet-nfts.workspace = true
scale-info.workspace = true
sp-io.workspace = true

[features]
default = ["std"]
std = [
"codec/std",
"pallet-balances/std",
"pallet-nfts/std",
"frame-support/std",
"frame-system/std",
"scale-info/std",
"sp-io/std",
"sp-runtime/std",
]
109 changes: 109 additions & 0 deletions traits/gas-tank/src/impl_nonfungibles.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use core::marker::PhantomData;

use frame_support::{
pallet_prelude::{Decode, Encode},
traits::nonfungibles_v2,
weights::Weight,
};
use frame_system::pallet_prelude::BlockNumberFor;
use sp_runtime::traits::{Bounded, CheckedAdd, CheckedSub};

use crate::*;

pub const ATTR_MEMBERSHIP_GAS: &[u8] = b"membership_gas";
pub const ATTR_GAS_TX_PAY_WITH_MEMBERSHIP: &[u8] = b"mbmshp_pays_gas";

#[derive(Encode, Decode, Debug)]
pub struct MembershipWeightTank<T: frame_system::Config> {
pub since: BlockNumberFor<T>,
pub used: Weight,
pub period: Option<BlockNumberFor<T>>,
pub max_per_period: Option<Weight>,
}

impl<T> Default for MembershipWeightTank<T>
where
T: frame_system::Config,
BlockNumberFor<T>: Default,
{
fn default() -> Self {
Self {
since: Default::default(),
used: Default::default(),
period: Default::default(),
max_per_period: Default::default(),
}
}
}

pub struct NonFungibleGasBurner<T, F, I>(PhantomData<(T, F, I)>);

impl<T, F, ItemConfig> GasBurner for NonFungibleGasBurner<T, F, ItemConfig>
where
T: frame_system::Config,
BlockNumberFor<T>: Bounded,
F: nonfungibles_v2::Inspect<T::AccountId>
+ nonfungibles_v2::InspectEnumerable<T::AccountId>
+ nonfungibles_v2::Mutate<T::AccountId, ItemConfig>,
ItemConfig: Default,
{
type AccountId = T::AccountId;
type Gas = Weight;

fn check_available_gas(who: &Self::AccountId, estimated: &Self::Gas) -> Option<Self::Gas> {
F::owned(who).find_map(|(collection, item)| {
let mut gas_tank: MembershipWeightTank<T> =
F::typed_system_attribute(&collection, Some(&item), &ATTR_MEMBERSHIP_GAS)?;

let block_number = frame_system::Pallet::<T>::block_number();
let period = gas_tank.period.unwrap_or(BlockNumberFor::<T>::max_value());

let Some(max_weight) = gas_tank.max_per_period else {
return Some(Weight::MAX);
};

if block_number.checked_sub(&gas_tank.since)? > period {
gas_tank.since = block_number.checked_add(&period)?;
gas_tank.used = Weight::zero();

F::set_typed_attribute(&collection, &item, &ATTR_MEMBERSHIP_GAS, &gas_tank).ok()?;
};

let remaining = max_weight.checked_sub(&gas_tank.used.checked_add(estimated)?)?;
F::set_typed_attribute(
&collection,
&item,
&ATTR_GAS_TX_PAY_WITH_MEMBERSHIP,
&remaining,
)
.ok()?;

Some(remaining)
})
}

fn burn_gas(who: &Self::AccountId, expected: &Self::Gas, used: &Self::Gas) -> Self::Gas {
F::owned(who)
.find_map(|(collection, item)| {
if !expected.eq(&F::typed_system_attribute(
&collection,
Some(&item),
&ATTR_GAS_TX_PAY_WITH_MEMBERSHIP,
)?) {
return None;
}
F::clear_typed_attribute(&collection, &item, &ATTR_GAS_TX_PAY_WITH_MEMBERSHIP)
.ok()?;

let mut gas_tank: MembershipWeightTank<T> =
F::typed_system_attribute(&collection, Some(&item), &ATTR_MEMBERSHIP_GAS)?;

gas_tank.used = gas_tank.used.checked_add(used)?;

F::set_typed_attribute(&collection, &item, &ATTR_MEMBERSHIP_GAS, &gas_tank).ok()?;
let max_weight = gas_tank.max_per_period?;
Some(max_weight.saturating_sub(gas_tank.used))
})
.unwrap_or_default()
}
}
7 changes: 7 additions & 0 deletions traits/gas-tank/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
#![cfg_attr(not(feature = "std"), no_std)]

use frame_support::Parameter;

#[cfg(test)]
mod tests;

mod impl_nonfungibles;

pub trait GasTank: GasBurner + GasFueler {}

/// Handles burning _"gas"_ from a tank to be spendable in transactions
Expand Down
Loading

0 comments on commit 1b1d41d

Please sign in to comment.