Skip to main content

Custom Modifier

In the Factory contract, prior to the setFeeTo and setFeeToSetter entries, there is a check that occurs, and the caller is feeToSetter. Let's create a custom modifier for it.

only_fee_setter

In the .logics/impls/factory/factory.rs file, import modifier_definition and modifiers:

use openbrush::{
modifier_definition,
modifiers,
traits::{
AccountId,
Storage,
ZERO_ADDRESS,
},
};

Let's define the generic modifier below the impl block. Some rules for the generic type parameters:

  • If it should use Storage structs - it should accept a type parameter.
  • It should have the same return type - Result<R, E> where E is wrapped in From Trait.

In the body of the modifier we will ensure that the caller address is equal to fee_to_setter, otherwise return an Error:

#[modifier_definition]
pub fn only_fee_setter<T, F, R, E>(instance: &mut T, body: F) -> Result<R, E>
where
T: Storage<data::Data>,
F: FnOnce(&mut T) -> Result<R, E>,
E: From<FactoryError>,
{
if instance.data().fee_to_setter != T::env().caller() {
return Err(From::from(FactoryError::CallerIsNotFeeSetter))
}
body(instance)
}

Prepend the modifier to the top of the set_fee_to and set_fee_to_setter functions:

#[modifiers(only_fee_setter)]
fn set_fee_to(&mut self, fee_to: AccountId) -> Result<(), FactoryError> {
self.data::<data::Data>().fee_to = fee_to;
Ok(())
}

#[modifiers(only_fee_setter)]
fn set_fee_to_setter(&mut self, fee_to_setter: AccountId) -> Result<(), FactoryError> {
self.data::<data::Data>().fee_to_setter = fee_to_setter;
Ok(())
}

Add CallerIsNotFeeSetter variant to FactoryError:

#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub enum FactoryError {
PairError(PairError),
CallerIsNotFeeSetter,
ZeroAddress,
IdenticalAddresses,
PairInstantiationFailed,
}

And that's it! Check your Factory contract with (run in the contract folder):

cargo contract build

It should now look like this branch.