Forráskód Böngészése

Merge branch 'minting_monorepo_migration' into monorepo_external_modules
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.

Shamil Gadelshin 5 éve
szülő
commit
26483a27ca

+ 50 - 0
runtime-modules/token-mint/Cargo.toml

@@ -0,0 +1,50 @@
+[package]
+name = 'substrate-token-mint-module'
+version = '1.0.1'
+authors = ['Mokhtar Naamani <mokhtar.naamani@gmail.com>']
+edition = '2018'
+
+[dependencies]
+hex-literal = '0.1.0'
+serde = { version = '1.0.101', optional = true}
+serde_derive = { version = '1.0.101', optional = true }
+rstd = { package = 'sr-std', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'}
+runtime-primitives = { package = 'sr-primitives', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'}
+srml-support = { package = 'srml-support', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'}
+srml-support-procedural = { package = 'srml-support-procedural', git = 'https://github.com/paritytech/substrate.git', rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'}
+system = { package = 'srml-system', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'}
+balances = { package = 'srml-balances', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'}
+codec = { package = 'parity-scale-codec', version = '1.0.0', default-features = false, features = ['derive'] }
+# https://users.rust-lang.org/t/failure-derive-compilation-error/39062
+quote = '<=1.0.2'
+
+[dependencies.timestamp]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'srml-timestamp'
+rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+
+[dependencies.runtime-io]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'sr-io'
+rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+
+[dev-dependencies]
+runtime-io = { package = 'sr-io', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'}
+primitives = { package = 'substrate-primitives', git = 'https://github.com/paritytech/substrate.git', rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'}
+
+[features]
+default = ['std']
+std = [
+	'serde',
+	'serde_derive',
+	'codec/std',
+	'rstd/std',
+	'runtime-io/std',
+	'runtime-primitives/std',
+	'srml-support/std',
+	'system/std',
+  	'balances/std',
+	'timestamp/std',
+]

+ 260 - 0
runtime-modules/token-mint/src/lib.rs

@@ -0,0 +1,260 @@
+// Ensure we're `no_std` when compiling for Wasm.
+#![cfg_attr(not(feature = "std"), no_std)]
+
+#[cfg(feature = "std")]
+use rstd::prelude::*;
+
+use codec::{Codec, Decode, Encode};
+use runtime_primitives::traits::{MaybeSerialize, Member, One, SimpleArithmetic, Zero};
+use srml_support::traits::Currency;
+use srml_support::{decl_module, decl_storage, ensure, Parameter};
+
+mod mint;
+mod mock;
+mod tests;
+
+pub use mint::*;
+
+use system;
+
+pub trait Trait: system::Trait {
+    /// The currency to mint.
+    type Currency: Currency<Self::AccountId>;
+
+    /// The type used as a mint identifier.
+    type MintId: Parameter
+        + Member
+        + SimpleArithmetic
+        + Codec
+        + Default
+        + Copy
+        + MaybeSerialize
+        + PartialEq;
+}
+
+pub type BalanceOf<T> =
+    <<T as Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::Balance;
+
+#[derive(PartialEq, Eq, Debug)]
+pub enum GeneralError {
+    MintNotFound,
+    NextAdjustmentInPast,
+}
+
+/// Errors that can arise from attempt to mint and transfer tokens from a mint to
+/// an account.
+#[derive(PartialEq, Eq, Debug)]
+pub enum TransferError {
+    MintNotFound,
+    NotEnoughCapacity,
+}
+
+/// Errors that can arise from attempt to transfer capacity between mints.
+#[derive(PartialEq, Eq, Debug)]
+pub enum CapacityTransferError {
+    SourceMintNotFound,
+    DestinationMintNotFound,
+    NotEnoughCapacity,
+}
+
+impl From<MintingError> for CapacityTransferError {
+    fn from(err: MintingError) -> CapacityTransferError {
+        match err {
+            MintingError::NotEnoughCapacity => CapacityTransferError::NotEnoughCapacity,
+        }
+    }
+}
+
+impl From<MintingError> for TransferError {
+    fn from(err: MintingError) -> TransferError {
+        match err {
+            MintingError::NotEnoughCapacity => TransferError::NotEnoughCapacity,
+        }
+    }
+}
+
+#[derive(Encode, Decode, Copy, Clone, Debug, Eq, PartialEq)]
+pub enum Adjustment<Balance: Zero, BlockNumber> {
+    // First adjustment will be after AdjustOnInterval.block_interval
+    Interval(AdjustOnInterval<Balance, BlockNumber>),
+    // First Adjustment will be at absolute blocknumber
+    IntervalAfterFirstAdjustmentAbsolute(AdjustOnInterval<Balance, BlockNumber>, BlockNumber),
+    // First Adjustment will be after a specified number of blocks
+    IntervalAfterFirstAdjustmentRelative(AdjustOnInterval<Balance, BlockNumber>, BlockNumber),
+}
+
+decl_storage! {
+    trait Store for Module<T: Trait> as TokenMint {
+        /// Mints
+        pub Mints get(mints) : linked_map T::MintId => Mint<BalanceOf<T>, T::BlockNumber>;
+
+        /// The number of mints created.
+        pub MintsCreated get(mints_created): T::MintId;
+    }
+}
+
+decl_module! {
+    pub struct Module<T: Trait> for enum Call where origin: T::Origin {
+        fn on_finalize(now: T::BlockNumber) {
+            Self::update_mints(now);
+        }
+    }
+}
+
+impl<T: Trait> Module<T> {
+    fn update_mints(now: T::BlockNumber) {
+        // Are we reading value from storage twice?
+        for (mint_id, ref mut mint) in <Mints<T>>::enumerate() {
+            if mint.maybe_do_capacity_adjustment(now) {
+                <Mints<T>>::insert(&mint_id, mint);
+            }
+        }
+    }
+
+    /// Adds a new mint with given settings to mints, and returns new MintId.
+    pub fn add_mint(
+        initial_capacity: BalanceOf<T>,
+        adjustment: Option<Adjustment<BalanceOf<T>, T::BlockNumber>>,
+    ) -> Result<T::MintId, GeneralError> {
+        let now = <system::Module<T>>::block_number();
+
+        // Ensure the next adjustment if set, is in the future
+        if let Some(adjustment) = adjustment {
+            match adjustment {
+                Adjustment::IntervalAfterFirstAdjustmentAbsolute(_, first_adjustment_in) => {
+                    ensure!(
+                        first_adjustment_in > now,
+                        GeneralError::NextAdjustmentInPast
+                    );
+                }
+                _ => (),
+            }
+        }
+
+        // Determine next adjutment
+        let next_adjustment = adjustment.map(|adjustment| match adjustment {
+            Adjustment::Interval(adjust_on_interval) => NextAdjustment {
+                at_block: now + adjust_on_interval.block_interval,
+                adjustment: adjust_on_interval,
+            },
+            Adjustment::IntervalAfterFirstAdjustmentAbsolute(
+                adjust_on_interval,
+                first_adjustment_at,
+            ) => NextAdjustment {
+                adjustment: adjust_on_interval,
+                at_block: first_adjustment_at,
+            },
+            Adjustment::IntervalAfterFirstAdjustmentRelative(
+                adjust_on_interval,
+                first_adjustment_after,
+            ) => NextAdjustment {
+                adjustment: adjust_on_interval,
+                at_block: now + first_adjustment_after,
+            },
+        });
+
+        // get next mint_id and increment total number of mints created
+        let mint_id = Self::mints_created();
+        <MintsCreated<T>>::put(mint_id + One::one());
+
+        <Mints<T>>::insert(mint_id, Mint::new(initial_capacity, next_adjustment, now));
+
+        Ok(mint_id)
+    }
+
+    /// Removes a mint. Passing a non existent mint has no side effects.
+    pub fn remove_mint(mint_id: T::MintId) {
+        <Mints<T>>::remove(&mint_id);
+    }
+
+    /// Tries to transfer exact requested amount from mint to a recipient account id.
+    /// Returns error if amount exceeds mint capacity or the specified mint doesn't exist.
+    /// Transfering amount of zero has no side effects. Return nothing on success.
+    pub fn transfer_tokens(
+        mint_id: T::MintId,
+        requested_amount: BalanceOf<T>,
+        recipient: &T::AccountId,
+    ) -> Result<(), TransferError> {
+        if requested_amount == Zero::zero() {
+            return Ok(());
+        }
+
+        ensure!(<Mints<T>>::exists(&mint_id), TransferError::MintNotFound);
+
+        let mut mint = Self::mints(&mint_id);
+
+        // Try minting
+        mint.mint_tokens(requested_amount)?;
+
+        <Mints<T>>::insert(&mint_id, mint);
+
+        // Deposit into recipient account
+        T::Currency::deposit_creating(recipient, requested_amount);
+
+        Ok(())
+    }
+
+    /// Provided mint exists, sets its capacity to specied value, return error otherwise.
+    pub fn set_mint_capacity(
+        mint_id: T::MintId,
+        capacity: BalanceOf<T>,
+    ) -> Result<(), GeneralError> {
+        ensure!(<Mints<T>>::exists(&mint_id), GeneralError::MintNotFound);
+
+        <Mints<T>>::mutate(&mint_id, |mint| {
+            mint.set_capacity(capacity);
+        });
+
+        Ok(())
+    }
+
+    /// Provided source and destination mints exist, will attempt to transfer capacity from the source mint
+    /// to the destination mint. Will return errors on non-existence of
+    /// mints or capacity_to_transfer exceeds the source mint's capacity.
+    pub fn transfer_capacity(
+        source: T::MintId,
+        destination: T::MintId,
+        capacity_to_transfer: BalanceOf<T>,
+    ) -> Result<(), CapacityTransferError> {
+        ensure!(
+            <Mints<T>>::exists(&source),
+            CapacityTransferError::SourceMintNotFound
+        );
+        ensure!(
+            <Mints<T>>::exists(&destination),
+            CapacityTransferError::DestinationMintNotFound
+        );
+
+        <Mints<T>>::mutate(&source, |source_mint| {
+            <Mints<T>>::mutate(&destination, |destination_mint| {
+                source_mint.transfer_capacity_to(destination_mint, capacity_to_transfer)
+            })
+        })?;
+
+        Ok(())
+    }
+
+    /// Returns a mint's capacity if it exists, error otherwise.
+    pub fn get_mint_capacity(mint_id: T::MintId) -> Result<BalanceOf<T>, GeneralError> {
+        ensure!(<Mints<T>>::exists(&mint_id), GeneralError::MintNotFound);
+        let mint = Self::mints(&mint_id);
+
+        Ok(mint.capacity())
+    }
+
+    /// Returns a mint's adjustment policy if it exists, error otherwise.
+    pub fn get_mint_next_adjustment(
+        mint_id: T::MintId,
+    ) -> Result<Option<NextAdjustment<BalanceOf<T>, T::BlockNumber>>, GeneralError> {
+        ensure!(<Mints<T>>::exists(&mint_id), GeneralError::MintNotFound);
+
+        let mint = Self::mints(&mint_id);
+
+        Ok(mint.next_adjustment())
+    }
+
+    /// Returns true if a mint exists.
+    pub fn mint_exists(mint_id: T::MintId) -> bool {
+        <Mints<T>>::exists(&mint_id)
+    }
+}

+ 153 - 0
runtime-modules/token-mint/src/mint.rs

@@ -0,0 +1,153 @@
+use codec::{Decode, Encode};
+use runtime_primitives::traits::{SimpleArithmetic, Zero};
+use srml_support::ensure;
+
+#[derive(Encode, Decode, Copy, Clone, Debug, Eq, PartialEq)]
+pub enum AdjustCapacityBy<Balance: Zero> {
+    /// Set capacity of mint to specific value
+    Setting(Balance),
+    /// Add to the capacity of the mint
+    Adding(Balance),
+    /// Reduce capacity of the mint
+    Reducing(Balance),
+}
+
+#[derive(Encode, Decode, Copy, Clone, Debug, Eq, PartialEq)]
+pub struct AdjustOnInterval<Balance: Zero, BlockNumber> {
+    pub block_interval: BlockNumber,
+    pub adjustment_type: AdjustCapacityBy<Balance>,
+}
+
+#[derive(Encode, Decode, Copy, Clone, Debug, Eq, PartialEq)]
+pub struct NextAdjustment<Balance: Zero, BlockNumber> {
+    pub adjustment: AdjustOnInterval<Balance, BlockNumber>,
+    pub at_block: BlockNumber,
+}
+
+#[derive(Encode, Decode, Default, Copy, Clone)]
+// Note we don't use TokenMint<T: Trait> it breaks the Default derivation macro with error T doesn't impl Default
+// Which requires manually implementing Default trait.
+// We want Default trait on TokenMint so we can use it as value in StorageMap without needing to wrap it in an Option
+pub struct Mint<Balance, BlockNumber>
+where
+    Balance: Copy + SimpleArithmetic + Zero,
+    BlockNumber: Copy + SimpleArithmetic,
+{
+    capacity: Balance,
+
+    // Whether there is an upcoming block where an adjustment to the mint will be made
+    // When this is not set, the mint is effectively paused.
+    next_adjustment: Option<NextAdjustment<Balance, BlockNumber>>,
+
+    created_at: BlockNumber,
+
+    total_minted: Balance,
+}
+
+#[derive(PartialEq, Eq, Debug)]
+pub enum MintingError {
+    NotEnoughCapacity,
+}
+
+impl<Balance, BlockNumber> Mint<Balance, BlockNumber>
+where
+    Balance: Copy + SimpleArithmetic + Zero,
+    BlockNumber: Copy + SimpleArithmetic,
+{
+    pub fn new(
+        initial_capacity: Balance,
+        next_adjustment: Option<NextAdjustment<Balance, BlockNumber>>,
+        now: BlockNumber,
+    ) -> Self {
+        Mint {
+            capacity: initial_capacity,
+            created_at: now,
+            total_minted: Zero::zero(),
+            next_adjustment: next_adjustment,
+        }
+    }
+
+    pub fn mint_tokens(&mut self, requested_amount: Balance) -> Result<(), MintingError> {
+        ensure!(
+            self.capacity >= requested_amount,
+            MintingError::NotEnoughCapacity
+        );
+        self.capacity -= requested_amount;
+        self.total_minted += requested_amount;
+        Ok(())
+    }
+
+    pub fn set_capacity(&mut self, new_capacity: Balance) {
+        self.capacity = new_capacity;
+    }
+
+    pub fn capacity(&self) -> Balance {
+        self.capacity
+    }
+
+    pub fn can_mint(&self, amount: Balance) -> bool {
+        self.capacity >= amount
+    }
+
+    pub fn created_at(&self) -> BlockNumber {
+        self.created_at
+    }
+
+    pub fn total_minted(&self) -> Balance {
+        self.total_minted
+    }
+
+    pub fn transfer_capacity_to(
+        &mut self,
+        destination: &mut Self,
+        capacity_to_transfer: Balance,
+    ) -> Result<(), MintingError> {
+        ensure!(
+            self.capacity >= capacity_to_transfer,
+            MintingError::NotEnoughCapacity
+        );
+        self.capacity -= capacity_to_transfer;
+        destination.capacity += capacity_to_transfer;
+        Ok(())
+    }
+
+    pub fn next_adjustment(&self) -> Option<NextAdjustment<Balance, BlockNumber>> {
+        self.next_adjustment
+    }
+
+    pub fn maybe_do_capacity_adjustment(&mut self, now: BlockNumber) -> bool {
+        self.next_adjustment.map_or(false, |next_adjustment| {
+            if now != next_adjustment.at_block {
+                false
+            } else {
+                // update mint capacity
+                self.capacity = Self::adjusted_capacity(
+                    self.capacity,
+                    next_adjustment.adjustment.adjustment_type,
+                );
+
+                // set next adjustment
+                self.next_adjustment = Some(NextAdjustment {
+                    adjustment: next_adjustment.adjustment,
+                    at_block: now + next_adjustment.adjustment.block_interval,
+                });
+
+                true
+            }
+        })
+    }
+
+    fn adjusted_capacity(capacity: Balance, adjustment_type: AdjustCapacityBy<Balance>) -> Balance {
+        match adjustment_type {
+            AdjustCapacityBy::Adding(amount) => capacity + amount,
+            AdjustCapacityBy::Setting(amount) => amount,
+            AdjustCapacityBy::Reducing(amount) => {
+                if amount > capacity {
+                    Zero::zero()
+                } else {
+                    capacity - amount
+                }
+            }
+        }
+    }
+}

+ 90 - 0
runtime-modules/token-mint/src/mock.rs

@@ -0,0 +1,90 @@
+#![cfg(test)]
+
+use crate::*;
+
+use primitives::H256;
+
+use crate::{Module, Trait};
+use balances;
+use runtime_primitives::{
+    testing::Header,
+    traits::{BlakeTwo256, IdentityLookup},
+    Perbill,
+};
+use srml_support::{impl_outer_origin, parameter_types};
+
+impl_outer_origin! {
+    pub enum Origin for Test {}
+}
+
+// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct Test;
+parameter_types! {
+    pub const BlockHashCount: u64 = 250;
+    pub const MaximumBlockWeight: u32 = 1024;
+    pub const MaximumBlockLength: u32 = 2 * 1024;
+    pub const AvailableBlockRatio: Perbill = Perbill::one();
+    pub const MinimumPeriod: u64 = 5;
+}
+
+impl system::Trait for Test {
+    type Origin = Origin;
+    type Index = u64;
+    type BlockNumber = u64;
+    type Call = ();
+    type Hash = H256;
+    type Hashing = BlakeTwo256;
+    type AccountId = u64;
+    type Lookup = IdentityLookup<Self::AccountId>;
+    type Header = Header;
+    type Event = ();
+    type BlockHashCount = BlockHashCount;
+    type MaximumBlockWeight = MaximumBlockWeight;
+    type MaximumBlockLength = MaximumBlockLength;
+    type AvailableBlockRatio = AvailableBlockRatio;
+    type Version = ();
+}
+
+parameter_types! {
+    pub const ExistentialDeposit: u32 = 0;
+    pub const TransferFee: u32 = 0;
+    pub const CreationFee: u32 = 0;
+    pub const TransactionBaseFee: u32 = 1;
+    pub const TransactionByteFee: u32 = 0;
+    pub const InitialMembersBalance: u64 = 2000;
+}
+
+impl balances::Trait for Test {
+    /// The type for recording an account's balance.
+    type Balance = u64;
+    /// What to do if an account's free balance gets zeroed.
+    type OnFreeBalanceZero = ();
+    /// What to do if a new account is created.
+    type OnNewAccount = ();
+    /// The ubiquitous event type.
+    type Event = ();
+
+    type DustRemoval = ();
+    type TransferPayment = ();
+    type ExistentialDeposit = ExistentialDeposit;
+    type TransferFee = TransferFee;
+    type CreationFee = CreationFee;
+}
+
+impl Trait for Test {
+    type Currency = Balances;
+    type MintId = u64;
+}
+
+pub fn build_test_externalities() -> runtime_io::TestExternalities {
+    let t = system::GenesisConfig::default()
+        .build_storage::<Test>()
+        .unwrap();
+
+    t.into()
+}
+
+pub type System = system::Module<Test>;
+pub type Balances = balances::Module<Test>;
+pub type Minting = Module<Test>;

+ 202 - 0
runtime-modules/token-mint/src/tests.rs

@@ -0,0 +1,202 @@
+#![cfg(test)]
+
+use super::*;
+use crate::mock::*;
+
+#[test]
+fn adding_and_removing_mints() {
+    build_test_externalities().execute_with(|| {
+        System::set_block_number(1);
+        let capacity: u64 = 5000;
+        let adjustment_amount: u64 = 500;
+
+        let adjustment = AdjustOnInterval {
+            adjustment_type: AdjustCapacityBy::Adding(adjustment_amount),
+            block_interval: 100,
+        };
+
+        let mint_id = Minting::add_mint(capacity, Some(Adjustment::Interval(adjustment)))
+            .ok()
+            .unwrap();
+        assert!(Minting::mint_exists(mint_id));
+
+        assert_eq!(Minting::get_mint_capacity(mint_id).ok().unwrap(), capacity);
+
+        assert_eq!(
+            Minting::get_mint_next_adjustment(mint_id),
+            Ok(Some(NextAdjustment {
+                adjustment,
+                at_block: 1 + 100,
+            }))
+        );
+
+        Minting::remove_mint(mint_id);
+        assert!(!Minting::mint_exists(mint_id));
+    });
+}
+
+#[test]
+fn minting() {
+    build_test_externalities().execute_with(|| {
+        let capacity: u64 = 5000;
+
+        let mint_id = Minting::add_mint(capacity, None).ok().unwrap();
+
+        assert!(Minting::transfer_tokens(mint_id, 1000, &1).is_ok());
+
+        assert_eq!(Balances::free_balance(&1), 1000);
+
+        assert_eq!(Minting::get_mint_capacity(mint_id).ok().unwrap(), 4000);
+    });
+}
+
+#[test]
+fn minting_exact() {
+    build_test_externalities().execute_with(|| {
+        let capacity: u64 = 1000;
+
+        let mint_id = Minting::add_mint(capacity, None).ok().unwrap();
+
+        assert_eq!(
+            Minting::transfer_tokens(mint_id, 2000, &1),
+            Err(TransferError::NotEnoughCapacity)
+        );
+    });
+}
+
+#[test]
+fn adjustment_adding() {
+    build_test_externalities().execute_with(|| {
+        System::set_block_number(0);
+        let capacity: u64 = 5000;
+        let adjustment_amount: u64 = 500;
+
+        let adjustment = AdjustOnInterval {
+            adjustment_type: AdjustCapacityBy::Adding(adjustment_amount),
+            block_interval: 100,
+        };
+
+        let mint_id = Minting::add_mint(capacity, Some(Adjustment::Interval(adjustment)))
+            .ok()
+            .unwrap();
+
+        Minting::update_mints(100);
+        assert_eq!(
+            Minting::get_mint_capacity(mint_id).ok().unwrap(),
+            capacity + (adjustment_amount * 1)
+        );
+
+        // no adjustments should happen
+        Minting::update_mints(100);
+        Minting::update_mints(140);
+        Minting::update_mints(199);
+
+        Minting::update_mints(200);
+        assert_eq!(
+            Minting::get_mint_capacity(mint_id).ok().unwrap(),
+            capacity + (adjustment_amount * 2)
+        );
+    });
+}
+
+#[test]
+fn adjustment_reducing() {
+    build_test_externalities().execute_with(|| {
+        System::set_block_number(0);
+        let capacity: u64 = 5000;
+        let adjustment_amount: u64 = 500;
+
+        let adjustment = AdjustOnInterval {
+            adjustment_type: AdjustCapacityBy::Reducing(adjustment_amount),
+            block_interval: 100,
+        };
+
+        let mint_id = Minting::add_mint(capacity, Some(Adjustment::Interval(adjustment)))
+            .ok()
+            .unwrap();
+
+        Minting::update_mints(100);
+        assert_eq!(
+            Minting::get_mint_capacity(mint_id).ok().unwrap(),
+            capacity - adjustment_amount
+        );
+
+        assert_eq!(
+            Minting::get_mint_capacity(mint_id).ok().unwrap(),
+            capacity - (adjustment_amount * 1)
+        );
+
+        // no adjustments should happen
+        Minting::update_mints(100);
+        Minting::update_mints(140);
+        Minting::update_mints(199);
+
+        Minting::update_mints(200);
+        assert_eq!(
+            Minting::get_mint_capacity(mint_id).ok().unwrap(),
+            capacity - (adjustment_amount * 2)
+        );
+    });
+}
+
+#[test]
+fn adjustment_setting() {
+    build_test_externalities().execute_with(|| {
+        System::set_block_number(0);
+        let capacity: u64 = 2000;
+        let setting_amount: u64 = 5000;
+
+        let adjustment = AdjustOnInterval {
+            adjustment_type: AdjustCapacityBy::Setting(setting_amount),
+            block_interval: 100,
+        };
+
+        let mint_id = Minting::add_mint(capacity, Some(Adjustment::Interval(adjustment)))
+            .ok()
+            .unwrap();
+
+        Minting::update_mints(100);
+        assert_eq!(
+            Minting::get_mint_capacity(mint_id).ok().unwrap(),
+            setting_amount
+        );
+    });
+}
+
+#[test]
+fn adjustment_first_interval() {
+    build_test_externalities().execute_with(|| {
+        System::set_block_number(0);
+        let capacity: u64 = 2000;
+        let amount: u64 = 500;
+
+        let adjustment = AdjustOnInterval {
+            adjustment_type: AdjustCapacityBy::Adding(amount),
+            block_interval: 100,
+        };
+
+        let mint_id = Minting::add_mint(
+            capacity,
+            Some(Adjustment::IntervalAfterFirstAdjustmentAbsolute(
+                adjustment, 1000,
+            )),
+        )
+        .ok()
+        .unwrap();
+
+        Minting::update_mints(100);
+        assert_eq!(Minting::get_mint_capacity(mint_id).ok().unwrap(), capacity);
+
+        Minting::update_mints(1000);
+        assert_eq!(
+            Minting::get_mint_capacity(mint_id).ok().unwrap(),
+            capacity + amount
+        );
+
+        Minting::update_mints(1100);
+        assert_eq!(
+            Minting::get_mint_capacity(mint_id).ok().unwrap(),
+            capacity + 2 * amount
+        );
+    });
+}