Foundation

The first page one sees is the foundation.rs at the very top of the list of Rust files on GitHub. This contract is targeted towards NEAR Foundation accounts, "foundation" here doesn't mean it's the foundation of the smart contract (meaning it's most important functions), but NEAR Foundation's "foundation". So let's take a look at it.

use near_sdk::{near_bindgen, Promise, require, AccountId};
// use near_account_id::AccountId;
use std::cmp;

use crate::*;

#[near_bindgen]
impl LockupContract{
    /// FOUNDATION'S METHOD
    /// 
    /// Requires 25 TGas (1 * BASE_GAS)
    /// 
    /// Terminates vesting schedule and locks the remaining
    /// unvested amount. If the lockup contract was initialized
    /// with the private vesting schedule, then this method 
    /// expects to receive a `VestingScheduleWithSalt` to
    /// reveal the vesting schedule; otherwise expects `None`. 
    pub fn terminate_vesting(
      &mut self,
      vesting_schedule_with_salt: Option<VestingScheduleWithSalt>,
    ) {
      self.assert_called_by_foundation();

      let vesting_schedule = self.assert_vesting(vesting_schedule_with_salt);
      let unvested_amount = self.get_unvested_amount(vesting_schedule);
      require!(
        unvested_amount.0 > 0,
        "The account is fully vested"
      );

      env::log_str(
        format!(
          "Terminating vesting. The remaining unvested balance is {}",
          unvested_amount.0
        ).as_str()
      );

      let deficit = unvested_amount
          .0
          .saturating_sub(self.get_account_balance().0);

      // If there's deficit in liquid balance and a staking pool is selected,
      // then the contract will try to withdraw everything from this staking
      // pool to cover deficit. 
      let status = if deficit > 0 && self.staking_information.is_some() {
        TerminationStatus::VestingTerminatedWithDeficit
      } else {
        TerminationStatus::ReadyToWithdraw
      };

      self.vesting_information = VestingInformation::Terminating(
        TerminationInformation {
          unvested_amount, 
          status,
        }
      );
    }

    /// FOUNDATION'S METHOD
    /// 
    /// Requires 175 TGas (7 * BASE_GAS)
    /// 
    /// When vesting is terminated and there are deficit of the 
    /// tokens on the account, the deficit amount of tokens has to
    /// be unstaked and withdrawn from the staking pool. 
    /// This includes unstaking everything + waiting for 4 epochs
    /// to prepare for withdrawal. 
    pub fn termination_prepare_to_withdraw(&mut self) -> Promise {
      self.assert_called_by_foundation();
      self.assert_staking_pool_is_idle();

      let status = self.get_termination_status();

      match status {
        None => {
          env::panic_str("There is no termination in progress.");
        }

        Some(TerminationStatus::UnstakingInProgress)
        | Some(TerminationStatus::WithdrawingFromStakingPoolInProgress)
        | Some(TerminationStatus::WithdrawingFromAccountInProgress) => {
          env::panic_str("Another transaction already in progress.");
        }

        Some(TerminationStatus::ReadyToWithdraw) => {
          env::panic_str("The account is ready to withdraw unvested balance.")
        }

        Some(TerminationStatus::VestingTerminatedWithDeficit) => {
          // Need to unstake
          self.set_termination_status(TerminationStatus::UnstakingInProgress);
          self.set_staking_pool_status(TransactionStatus::Busy);
          env::log_str("Termination Step: Unstaking everything from staking pool.");

          ext_staking_pool::get_account_staked_balance(
            env::current_account_id(),
            self
                .staking_information
                .as_ref()
                .unwrap()
                .staking_pool_account_id
                .clone(),
            NO_DEPOSIT,
            gas::staking_pool::GET_ACCOUNT_STAKED_BALANCE,
          )
          .then(
            ext_self_foundation::on_get_account_staked_balance_to_unstake(
              env::current_account_id(),
              NO_DEPOSIT,
              gas::foundation_callbacks::ON_GET_ACCOUNT_STAKED_BALANCE_TO_UNSTAKE,
            ),
          )
        }

        Some(TerminationStatus::EverythingUnstaked) => {
          // Need to withdraw everything

          self.set_termination_status(
            TerminationStatus::WithdrawingFromStakingPoolInProgress,
          );
          self.set_staking_pool_status(TransactionStatus::Busy);
          
          env::log_str("Termination Step: Withdraw everything from staking pool.");

          ext_staking_pool::get_account_unstaked_balance(
            env::current_account_id(),
            self.staking_information
                .as_ref()
                .unwrap()
                .staking_pool_account_id
                .clone(),
            NO_DEPOSIT,
            gas::staking_pool::GET_ACCOUNT_UNSTAKED_BALANCE,
          )
          .then(
            ext_self_foundation::on_get_account_unstaked_balance_to_withdraw(
              env::current_account_id(),
              NO_DEPOSIT,
              gas::foundation_callbacks::ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW,
            ),
          )
        }
      }
    }

    /// FOUNDATION'S METHOD
    /// 
    /// Requires 75 TGas
    /// 
    /// Withdraws the unvested amount from the early termination of the 
    /// vesting schedule.
    pub fn termination_withdraw(&mut self, receiver_id: AccountId) -> Promise {
      self.assert_called_by_foundation();

      require!(
        env::is_valid_account_id(receiver_id.as_bytes()),
        "The receiver account ID is invalid."
      );

      require!(
        self.get_termination_status() == Some(TerminationStatus::ReadyToWithdraw),
        "Termination status (Funds) is not ready to withdraw"
      );

      let amount = cmp::min(
        self.get_terminated_unvested_balance().0,
        self.get_account_balance().0
      );

      require!(
        amount > 0,
        "Insufficient liquid balance (amount) to withdraw."
      );

      env::log_str(
        format!(
          "Termination Step: Withdrawing {} of terminated unvested balance to @{}",
          amount, receiver_id
        )
        .as_str(),
      );

      self.set_termination_status(TerminationStatus::WithdrawingFromAccountInProgress);

      Promise::new(receiver_id.clone()).transfer(amount).then(
        ext_self_foundation::on_withdraw_unvested_amount(
          amount.into(),
          receiver_id,
          env::current_account_id(),
          NO_DEPOSIT,
          gas::foundation_callbacks::ON_WITHDRAW_UNVESTED_AMOUNT,
        ),
      )
    }
}



The first assertion checks whether the account is fully vested or not. Based on this definition of "fully vested", we can understand that the "vested amount" are the ones ready to withdraw. So the first assertion unvested_amount.0 > 0 tells you that, "hey, there are still some tokens in lockup (vesting), so you can terminate the lockup (vesting) process to withdraw them. In contrast, the error message "The account is fully vested" actually means "Hey, you have nothing locked up, so you have nothing to terminate".

Note that saturating_sub isn't part of near-sdk-rs but standard function inside Rust.

There are some functions that makes sense, but we'll see them later like self.assert_called_by_foundation(). Now, one wants to talk about one of the internal functions, called self.get_account_balance().

use near_sdk::require;
use crate::*;

/*********************
 * Internal Methods
 *********************/

impl LockupContract {
    /// Balance excluding storage staking balance. 
    /// Storage staking balance can't be transferred out
    /// without deleting this contract.
    pub(crate) fn get_account_balance(&self) -> WrappedBalance {
      env::account_balance()
          .saturating_sub(MIN_BALANCE_FOR_STORAGE)
          .into()
    }

    pub(crate) fn set_staking_pool_status(
      &mut self,
      status: TransactionStatus
    ) {
      self.staking_information
          .as_mut()
          .expect("Staking pool should be selected.")
          .status = status;
    }

    pub(crate) fn set_termination_status(
      &mut self,
      status: TerminationStatus
    ) {
      if let VestingInformation::Terminating(termination_information) = 
          &mut self.vesting_information 
      {
        termination_information.status = status;
      } else {
        unreachable!("Vesting information not at terminating stage. ");
      }
    }

    pub(crate) fn assert_vesting(
      &self,
      vesting_schedule_with_salt: Option<VestingScheduleWithSalt>,
    ) -> VestingSchedule {
      match &self.vesting_information {

        VestingInformation::VestingHash(hash) => {
          if let Some(vesting_schedule_with_salt) = vesting_schedule_with_salt {
            require!(
              &vesting_schedule_with_salt.hash() == &hash.0,
              "Presented vesting schedule and salt don't match the hash."
            );
            vesting_schedule_with_salt.vesting_schedule
          } else {
            env::panic_str("Expected vesting schedule and salt, but not provided.")
          }
        }

        VestingInformation::VestingSchedule(vesting_schedule) => {
          require!(
            vesting_schedule_with_salt.is_none(),
            "Explicit vesting schedule already exists."
          );
          vesting_schedule.clone()
        }

        VestingInformation::Terminating(_) => env::panic_str("Vesting was terminated."),

        VestingInformation::None => env::panic_str("Vesting is None."),
      }
    }

    pub(crate) fn assert_staking_pool_is_idle(&self) {
      require!(
        self.staking_information.is_some(),
        "Staking pool is not selected."
      );

      match self.staking_information.as_ref().unwrap().status {
        
        TransactionStatus::Idle => (),

        TransactionStatus::Busy => {
          env::panic_str("Contract currently busy with another operation. ")
        }
      };
    }

    pub(crate) fn assert_staking_pool_is_not_selected(&self) {
      require!(
        self.staking_information.is_none(),
        "Staking pool is already selected"
      );
    }

    pub(crate) fn assert_no_termination(&self) {
      if let VestingInformation::Terminating(_) = &self.vesting_information {
        env::panic_str(
          "All operations are blocked until vesting termination is completed." 
        );
      }
    }



    pub(crate) fn assert_called_by_foundation(&self) {
      if let Some(foundation_account_id) = &self.foundation_account_id {
        require!(
          &env::predecessor_account_id() == foundation_account_id,
          "Can only be called by NEAR Foundation"
        )
      } else {
        env::panic_str("No NEAR Foundation account specified in the contract.");
      }
    }


    pub(crate) fn assert_owner(&self) {
      require!(
        &env::predecessor_account_id() == &self.owner_account_id,
        "This method can only be called by the owner. "
      )
    }

    pub(crate) fn assert_transfers_enabled(&self) {
      require!(
        self.are_transfers_enabled(),
        "Transfers are disabled."
      );
    }

    pub(crate) fn assert_transfers_disabled(&self) {
      require!(
        !self.are_transfers_enabled(),
        "Transfers are already enabled."
      );
    }


    pub(crate) fn assert_no_staking_or_idle(&self) {
      if let Some(staking_information) = &self.staking_information {
        match staking_information.status {
          TransactionStatus::Idle => (),
          TransactionStatus::Busy => {
            env::panic_str("Contract is currently busy with another operation.")
          }
        };
      }
    }


    pub(crate) fn staking_pool_account_id_clone(&self) -> AccountId {
      self.staking_information
          .as_ref()
          .unwrap()
          .staking_pool_account_id
          .clone()
    }
}

As stated in the explanation, this function will return the account balance excluding those that are reserved. The reserved funds are for storage and transactions, and they could be seen in your NEAR Wallet as well if you navigate to the "Account" page.

Account Page of NEAR Wallet. See there are "Reserved for Storage" and "Reserved for transactions".

Another popular one is the assert_called_by_foundation. This checks whether the predecessor (which account is evoking the method directly) is actually the foundation's account.

These are the most important, the rest of the hidden ones, we'll take a look as we get there, but they should be easy to understand based on their names.

Next, let's take a look at termination_prepare_to_withdraw.

use near_sdk::{near_bindgen, Promise, require, AccountId};
// use near_account_id::AccountId;
use std::cmp;

use crate::*;

#[near_bindgen]
impl LockupContract{
    /// FOUNDATION'S METHOD
    /// 
    /// Requires 25 TGas (1 * BASE_GAS)
    /// 
    /// Terminates vesting schedule and locks the remaining
    /// unvested amount. If the lockup contract was initialized
    /// with the private vesting schedule, then this method 
    /// expects to receive a `VestingScheduleWithSalt` to
    /// reveal the vesting schedule; otherwise expects `None`. 
    pub fn terminate_vesting(
      &mut self,
      vesting_schedule_with_salt: Option<VestingScheduleWithSalt>,
    ) {
      self.assert_called_by_foundation();

      let vesting_schedule = self.assert_vesting(vesting_schedule_with_salt);
      let unvested_amount = self.get_unvested_amount(vesting_schedule);
      require!(
        unvested_amount.0 > 0,
        "The account is fully vested"
      );

      env::log_str(
        format!(
          "Terminating vesting. The remaining unvested balance is {}",
          unvested_amount.0
        ).as_str()
      );

      let deficit = unvested_amount
          .0
          .saturating_sub(self.get_account_balance().0);

      // If there's deficit in liquid balance and a staking pool is selected,
      // then the contract will try to withdraw everything from this staking
      // pool to cover deficit. 
      let status = if deficit > 0 && self.staking_information.is_some() {
        TerminationStatus::VestingTerminatedWithDeficit
      } else {
        TerminationStatus::ReadyToWithdraw
      };

      self.vesting_information = VestingInformation::Terminating(
        TerminationInformation {
          unvested_amount, 
          status,
        }
      );
    }

    /// FOUNDATION'S METHOD
    /// 
    /// Requires 175 TGas (7 * BASE_GAS)
    /// 
    /// When vesting is terminated and there are deficit of the 
    /// tokens on the account, the deficit amount of tokens has to
    /// be unstaked and withdrawn from the staking pool. 
    /// This includes unstaking everything + waiting for 4 epochs
    /// to prepare for withdrawal. 
    pub fn termination_prepare_to_withdraw(&mut self) -> Promise {
      self.assert_called_by_foundation();
      self.assert_staking_pool_is_idle();

      let status = self.get_termination_status();

      match status {
        None => {
          env::panic_str("There is no termination in progress.");
        }

        Some(TerminationStatus::UnstakingInProgress)
        | Some(TerminationStatus::WithdrawingFromStakingPoolInProgress)
        | Some(TerminationStatus::WithdrawingFromAccountInProgress) => {
          env::panic_str("Another transaction already in progress.");
        }

        Some(TerminationStatus::ReadyToWithdraw) => {
          env::panic_str("The account is ready to withdraw unvested balance.")
        }

        Some(TerminationStatus::VestingTerminatedWithDeficit) => {
          // Need to unstake
          self.set_termination_status(TerminationStatus::UnstakingInProgress);
          self.set_staking_pool_status(TransactionStatus::Busy);
          env::log_str("Termination Step: Unstaking everything from staking pool.");

          ext_staking_pool::get_account_staked_balance(
            env::current_account_id(),
            self
                .staking_information
                .as_ref()
                .unwrap()
                .staking_pool_account_id
                .clone(),
            NO_DEPOSIT,
            gas::staking_pool::GET_ACCOUNT_STAKED_BALANCE,
          )
          .then(
            ext_self_foundation::on_get_account_staked_balance_to_unstake(
              env::current_account_id(),
              NO_DEPOSIT,
              gas::foundation_callbacks::ON_GET_ACCOUNT_STAKED_BALANCE_TO_UNSTAKE,
            ),
          )
        }

        Some(TerminationStatus::EverythingUnstaked) => {
          // Need to withdraw everything

          self.set_termination_status(
            TerminationStatus::WithdrawingFromStakingPoolInProgress,
          );
          self.set_staking_pool_status(TransactionStatus::Busy);
          
          env::log_str("Termination Step: Withdraw everything from staking pool.");

          ext_staking_pool::get_account_unstaked_balance(
            env::current_account_id(),
            self.staking_information
                .as_ref()
                .unwrap()
                .staking_pool_account_id
                .clone(),
            NO_DEPOSIT,
            gas::staking_pool::GET_ACCOUNT_UNSTAKED_BALANCE,
          )
          .then(
            ext_self_foundation::on_get_account_unstaked_balance_to_withdraw(
              env::current_account_id(),
              NO_DEPOSIT,
              gas::foundation_callbacks::ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW,
            ),
          )
        }
      }
    }

    /// FOUNDATION'S METHOD
    /// 
    /// Requires 75 TGas
    /// 
    /// Withdraws the unvested amount from the early termination of the 
    /// vesting schedule.
    pub fn termination_withdraw(&mut self, receiver_id: AccountId) -> Promise {
      self.assert_called_by_foundation();

      require!(
        env::is_valid_account_id(receiver_id.as_bytes()),
        "The receiver account ID is invalid."
      );

      require!(
        self.get_termination_status() == Some(TerminationStatus::ReadyToWithdraw),
        "Termination status (Funds) is not ready to withdraw"
      );

      let amount = cmp::min(
        self.get_terminated_unvested_balance().0,
        self.get_account_balance().0
      );

      require!(
        amount > 0,
        "Insufficient liquid balance (amount) to withdraw."
      );

      env::log_str(
        format!(
          "Termination Step: Withdrawing {} of terminated unvested balance to @{}",
          amount, receiver_id
        )
        .as_str(),
      );

      self.set_termination_status(TerminationStatus::WithdrawingFromAccountInProgress);

      Promise::new(receiver_id.clone()).transfer(amount).then(
        ext_self_foundation::on_withdraw_unvested_amount(
          amount.into(),
          receiver_id,
          env::current_account_id(),
          NO_DEPOSIT,
          gas::foundation_callbacks::ON_WITHDRAW_UNVESTED_AMOUNT,
        ),
      )
    }
}



As usual, we'll leave some of the setters and getters method to later on, since the name explains what they're trying to do, hence we don't need to specially explain them here.

When we write the status, we want to fail hard, and fail early. Fail early, so we can save gas, and knows where our error are, so we always have the results leading to panicking at the top before solving for success results after all panic has confirmed false.

We shall take a look at the cross-contract calls, starting name with ext_, that are available in lib.rs. These are cross-contract calls, meaning sending the call requires some time, so it'll happen in the future; and future means we need to use Promise.

There are some functions called gas::, these are in the gas.rs, where it contains a list of constants for the gas fee to pay. We won't specifically look at it, we'll look at it when we need it. Here, we have two different gas required. Let's take a look at them.

The first is gas::staking_pool::GET_ACCOUNT_STAKED_BALANCE:

use near_sdk::Gas;

/// For local processing and local updates. 
const BASE_GAS: Gas = Gas(25_000_000_000_000);


pub mod whitelist {
    use near_sdk::Gas;

    /// Gas attached to the promise checking whether the given
    /// staking pool account ID is whitelisted. 
    pub const IS_WHITELISTED: Gas = super::BASE_GAS;
}


pub mod staking_pool {
    use near_sdk::Gas;

    /// Gas attached to deposit call on staking pool contract.
    /// Local updates + restaking (potentially)
    pub const DEPOSIT: Gas = Gas(super::BASE_GAS.0 * 2);

    /// Gas attached to deposit call on staking pool contract.
    /// local updates + staking call (2x Base).
    pub const DEPOSIT_AND_STAKE: Gas = Gas(super::BASE_GAS.0 * 3);

    /// Gas attached to withdraw call on staking pool contract. 
    /// BASE for execution + 2 * BASE for transferring amount and 
    /// potentially restaking. 
    pub const WITHDRAW: Gas = Gas(super::BASE_GAS.0 * 3);


    /// Gas attached to unstake call on staking pool contract. 
    /// BASE for execution + 2 * BASE for staking call. 
    pub const UNSTAKE: Gas = Gas(super::BASE_GAS.0 * 3);

    /// Gas to unstake all call on staking pool contract.
    /// BASE for execution + 2 * BASE for staking call.
    pub const UNSTAKE_ALL: Gas = Gas(super::BASE_GAS.0 * 3);


    /// The amount of Gas required to get the current staked balance
    /// of this account from staking pool. 
    /// Requires BASE for local processing. 
    pub const GET_ACCOUNT_STAKED_BALANCE: Gas = super::BASE_GAS;

    /// The amount of Gas required to get current unstaked balance of 
    /// this account from the staking pool. 
    /// Requires BASE for local processing. 
    pub const GET_ACCOUNT_UNSTAKED_BALANCE: Gas = super::BASE_GAS;

    /// The amount of gas required to get the current total balance
    /// of this account from the staking pool.
    pub const GET_ACCOUNT_TOTAL_BALANCE: Gas = super::BASE_GAS;

    /// Gas attached to stake call on staking pool contract.
    /// Execution + staking call (2x)
    pub const STAKE: Gas = Gas(super::BASE_GAS.0 * 3);
}


pub mod owner_callbacks {
    use near_sdk::Gas;

    /// Gas attached to inner callback for processing whitelist
    /// check results. 
    pub const ON_WHITELIST_IS_WHITELISTED: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of 
    /// deposit call to staking pool. 
    pub const ON_STAKING_POOL_DEPOSIT: Gas = super::BASE_GAS;

    /// Gas attached to inner callbacks for processing result of 
    /// the deposit and stake call to the staking pool. 
    pub const ON_STAKING_POOL_DEPOSIT_AND_STAKE: Gas = super::BASE_GAS;

    /// Gas attached to the inner callback for processing result of
    /// the call to get the current total balance from the staking
    /// pool. 
    pub const ON_GET_ACCOUNT_TOTAL_BALANCE: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the 
    /// withdraw call to the staking pool. 
    pub const ON_STAKING_POOL_WITHDRAW: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the
    /// call to get the current unstaked balance from staking pool.
    /// Callback might proceed with withdrawing this amount. 
    /// local updates + withdrawal + another callback
    pub const ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW_BY_OWNER: Gas = 
      Gas(
        super::BASE_GAS.0
        + super::staking_pool::WITHDRAW.0
        + ON_STAKING_POOL_WITHDRAW.0
      );

    /// Gas attached to the inner callback for processing result
    /// of the stake call to the staking pool. 
    pub const ON_STAKING_POOL_STAKE: Gas = super::BASE_GAS;

    /// Gas attached to the inner callback for processing result 
    /// of the unstake call to the staking pool.
    pub const ON_STAKING_POOL_UNSTAKE: Gas = super::BASE_GAS;

    /// Gas to unstake all call to staking pool.
    pub const ON_STAKING_POOL_UNSTAKE_ALL: Gas = super::BASE_GAS;

    /// Gas attached to the inner callbacks for checking result for
    /// transfer voting call to voting contract.
    pub const ON_VOTING_GET_RESULT: Gas = super::BASE_GAS;
}


pub mod foundation_callbacks {
    use near_sdk::Gas;


    /// Gas attached to inner callback for processing result of the call to get
    /// the current staked balance from staking pool. 
    /// The callback might proceed without unstaking. 
    pub const ON_GET_ACCOUNT_STAKED_BALANCE_TO_UNSTAKE: Gas = Gas(
      super::BASE_GAS.0
      + super::staking_pool::UNSTAKE.0 
      + ON_STAKING_POOL_UNSTAKE_FOR_TERMINATION.0);


    /// Gas attached to inner callback for processing result of unstake call to
    /// staking pool. 
    pub const ON_STAKING_POOL_UNSTAKE_FOR_TERMINATION: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the call to get
    /// the current unstaked balance from staking pool. 
    /// The callback might proceed with withdrawing this amount. 
    pub const ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW: Gas = Gas(
      super::BASE_GAS.0
      + super::staking_pool::WITHDRAW.0
      + ON_STAKING_POOL_WITHDRAW_FOR_TERMINATION.0);

    // Gas attached to inner callback for processing result of withdraw call.
    pub const ON_STAKING_POOL_WITHDRAW_FOR_TERMINATION: Gas = super::BASE_GAS;
    

    /// Gas attached to inner callback for processing result of withdrawal
    /// of terminated unvested balance. 
    pub const ON_WITHDRAW_UNVESTED_AMOUNT: Gas = super::BASE_GAS;
}


pub mod transfer_poll {
    use near_sdk::Gas;

    /// Gas attached to check whether transfers were enabled on transfer poll
    /// contract. 
    pub const GET_RESULT: Gas = super::BASE_GAS;
}

So we see, we just need the BASE amount of GAS for local processing in this case.

The second is gas::foundation_callbacks::ON_GET_ACCOUNT_STAKED_BALANCE_TO_UNSTAKE:

use near_sdk::Gas;

/// For local processing and local updates. 
const BASE_GAS: Gas = Gas(25_000_000_000_000);


pub mod whitelist {
    use near_sdk::Gas;

    /// Gas attached to the promise checking whether the given
    /// staking pool account ID is whitelisted. 
    pub const IS_WHITELISTED: Gas = super::BASE_GAS;
}


pub mod staking_pool {
    use near_sdk::Gas;

    /// Gas attached to deposit call on staking pool contract.
    /// Local updates + restaking (potentially)
    pub const DEPOSIT: Gas = Gas(super::BASE_GAS.0 * 2);

    /// Gas attached to deposit call on staking pool contract.
    /// local updates + staking call (2x Base).
    pub const DEPOSIT_AND_STAKE: Gas = Gas(super::BASE_GAS.0 * 3);

    /// Gas attached to withdraw call on staking pool contract. 
    /// BASE for execution + 2 * BASE for transferring amount and 
    /// potentially restaking. 
    pub const WITHDRAW: Gas = Gas(super::BASE_GAS.0 * 3);


    /// Gas attached to unstake call on staking pool contract. 
    /// BASE for execution + 2 * BASE for staking call. 
    pub const UNSTAKE: Gas = Gas(super::BASE_GAS.0 * 3);

    /// Gas to unstake all call on staking pool contract.
    /// BASE for execution + 2 * BASE for staking call.
    pub const UNSTAKE_ALL: Gas = Gas(super::BASE_GAS.0 * 3);


    /// The amount of Gas required to get the current staked balance
    /// of this account from staking pool. 
    /// Requires BASE for local processing. 
    pub const GET_ACCOUNT_STAKED_BALANCE: Gas = super::BASE_GAS;

    /// The amount of Gas required to get current unstaked balance of 
    /// this account from the staking pool. 
    /// Requires BASE for local processing. 
    pub const GET_ACCOUNT_UNSTAKED_BALANCE: Gas = super::BASE_GAS;

    /// The amount of gas required to get the current total balance
    /// of this account from the staking pool.
    pub const GET_ACCOUNT_TOTAL_BALANCE: Gas = super::BASE_GAS;

    /// Gas attached to stake call on staking pool contract.
    /// Execution + staking call (2x)
    pub const STAKE: Gas = Gas(super::BASE_GAS.0 * 3);
}


pub mod owner_callbacks {
    use near_sdk::Gas;

    /// Gas attached to inner callback for processing whitelist
    /// check results. 
    pub const ON_WHITELIST_IS_WHITELISTED: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of 
    /// deposit call to staking pool. 
    pub const ON_STAKING_POOL_DEPOSIT: Gas = super::BASE_GAS;

    /// Gas attached to inner callbacks for processing result of 
    /// the deposit and stake call to the staking pool. 
    pub const ON_STAKING_POOL_DEPOSIT_AND_STAKE: Gas = super::BASE_GAS;

    /// Gas attached to the inner callback for processing result of
    /// the call to get the current total balance from the staking
    /// pool. 
    pub const ON_GET_ACCOUNT_TOTAL_BALANCE: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the 
    /// withdraw call to the staking pool. 
    pub const ON_STAKING_POOL_WITHDRAW: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the
    /// call to get the current unstaked balance from staking pool.
    /// Callback might proceed with withdrawing this amount. 
    /// local updates + withdrawal + another callback
    pub const ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW_BY_OWNER: Gas = 
      Gas(
        super::BASE_GAS.0
        + super::staking_pool::WITHDRAW.0
        + ON_STAKING_POOL_WITHDRAW.0
      );

    /// Gas attached to the inner callback for processing result
    /// of the stake call to the staking pool. 
    pub const ON_STAKING_POOL_STAKE: Gas = super::BASE_GAS;

    /// Gas attached to the inner callback for processing result 
    /// of the unstake call to the staking pool.
    pub const ON_STAKING_POOL_UNSTAKE: Gas = super::BASE_GAS;

    /// Gas to unstake all call to staking pool.
    pub const ON_STAKING_POOL_UNSTAKE_ALL: Gas = super::BASE_GAS;

    /// Gas attached to the inner callbacks for checking result for
    /// transfer voting call to voting contract.
    pub const ON_VOTING_GET_RESULT: Gas = super::BASE_GAS;
}


pub mod foundation_callbacks {
    use near_sdk::Gas;


    /// Gas attached to inner callback for processing result of the call to get
    /// the current staked balance from staking pool. 
    /// The callback might proceed without unstaking. 
    pub const ON_GET_ACCOUNT_STAKED_BALANCE_TO_UNSTAKE: Gas = Gas(
      super::BASE_GAS.0
      + super::staking_pool::UNSTAKE.0 
      + ON_STAKING_POOL_UNSTAKE_FOR_TERMINATION.0);


    /// Gas attached to inner callback for processing result of unstake call to
    /// staking pool. 
    pub const ON_STAKING_POOL_UNSTAKE_FOR_TERMINATION: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the call to get
    /// the current unstaked balance from staking pool. 
    /// The callback might proceed with withdrawing this amount. 
    pub const ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW: Gas = Gas(
      super::BASE_GAS.0
      + super::staking_pool::WITHDRAW.0
      + ON_STAKING_POOL_WITHDRAW_FOR_TERMINATION.0);

    // Gas attached to inner callback for processing result of withdraw call.
    pub const ON_STAKING_POOL_WITHDRAW_FOR_TERMINATION: Gas = super::BASE_GAS;
    

    /// Gas attached to inner callback for processing result of withdrawal
    /// of terminated unvested balance. 
    pub const ON_WITHDRAW_UNVESTED_AMOUNT: Gas = super::BASE_GAS;
}


pub mod transfer_poll {
    use near_sdk::Gas;

    /// Gas attached to check whether transfers were enabled on transfer poll
    /// contract. 
    pub const GET_RESULT: Gas = super::BASE_GAS;
}
use near_sdk::Gas;

/// For local processing and local updates. 
const BASE_GAS: Gas = Gas(25_000_000_000_000);


pub mod whitelist {
    use near_sdk::Gas;

    /// Gas attached to the promise checking whether the given
    /// staking pool account ID is whitelisted. 
    pub const IS_WHITELISTED: Gas = super::BASE_GAS;
}


pub mod staking_pool {
    use near_sdk::Gas;

    /// Gas attached to deposit call on staking pool contract.
    /// Local updates + restaking (potentially)
    pub const DEPOSIT: Gas = Gas(super::BASE_GAS.0 * 2);

    /// Gas attached to deposit call on staking pool contract.
    /// local updates + staking call (2x Base).
    pub const DEPOSIT_AND_STAKE: Gas = Gas(super::BASE_GAS.0 * 3);

    /// Gas attached to withdraw call on staking pool contract. 
    /// BASE for execution + 2 * BASE for transferring amount and 
    /// potentially restaking. 
    pub const WITHDRAW: Gas = Gas(super::BASE_GAS.0 * 3);


    /// Gas attached to unstake call on staking pool contract. 
    /// BASE for execution + 2 * BASE for staking call. 
    pub const UNSTAKE: Gas = Gas(super::BASE_GAS.0 * 3);

    /// Gas to unstake all call on staking pool contract.
    /// BASE for execution + 2 * BASE for staking call.
    pub const UNSTAKE_ALL: Gas = Gas(super::BASE_GAS.0 * 3);


    /// The amount of Gas required to get the current staked balance
    /// of this account from staking pool. 
    /// Requires BASE for local processing. 
    pub const GET_ACCOUNT_STAKED_BALANCE: Gas = super::BASE_GAS;

    /// The amount of Gas required to get current unstaked balance of 
    /// this account from the staking pool. 
    /// Requires BASE for local processing. 
    pub const GET_ACCOUNT_UNSTAKED_BALANCE: Gas = super::BASE_GAS;

    /// The amount of gas required to get the current total balance
    /// of this account from the staking pool.
    pub const GET_ACCOUNT_TOTAL_BALANCE: Gas = super::BASE_GAS;

    /// Gas attached to stake call on staking pool contract.
    /// Execution + staking call (2x)
    pub const STAKE: Gas = Gas(super::BASE_GAS.0 * 3);
}


pub mod owner_callbacks {
    use near_sdk::Gas;

    /// Gas attached to inner callback for processing whitelist
    /// check results. 
    pub const ON_WHITELIST_IS_WHITELISTED: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of 
    /// deposit call to staking pool. 
    pub const ON_STAKING_POOL_DEPOSIT: Gas = super::BASE_GAS;

    /// Gas attached to inner callbacks for processing result of 
    /// the deposit and stake call to the staking pool. 
    pub const ON_STAKING_POOL_DEPOSIT_AND_STAKE: Gas = super::BASE_GAS;

    /// Gas attached to the inner callback for processing result of
    /// the call to get the current total balance from the staking
    /// pool. 
    pub const ON_GET_ACCOUNT_TOTAL_BALANCE: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the 
    /// withdraw call to the staking pool. 
    pub const ON_STAKING_POOL_WITHDRAW: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the
    /// call to get the current unstaked balance from staking pool.
    /// Callback might proceed with withdrawing this amount. 
    /// local updates + withdrawal + another callback
    pub const ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW_BY_OWNER: Gas = 
      Gas(
        super::BASE_GAS.0
        + super::staking_pool::WITHDRAW.0
        + ON_STAKING_POOL_WITHDRAW.0
      );

    /// Gas attached to the inner callback for processing result
    /// of the stake call to the staking pool. 
    pub const ON_STAKING_POOL_STAKE: Gas = super::BASE_GAS;

    /// Gas attached to the inner callback for processing result 
    /// of the unstake call to the staking pool.
    pub const ON_STAKING_POOL_UNSTAKE: Gas = super::BASE_GAS;

    /// Gas to unstake all call to staking pool.
    pub const ON_STAKING_POOL_UNSTAKE_ALL: Gas = super::BASE_GAS;

    /// Gas attached to the inner callbacks for checking result for
    /// transfer voting call to voting contract.
    pub const ON_VOTING_GET_RESULT: Gas = super::BASE_GAS;
}


pub mod foundation_callbacks {
    use near_sdk::Gas;


    /// Gas attached to inner callback for processing result of the call to get
    /// the current staked balance from staking pool. 
    /// The callback might proceed without unstaking. 
    pub const ON_GET_ACCOUNT_STAKED_BALANCE_TO_UNSTAKE: Gas = Gas(
      super::BASE_GAS.0
      + super::staking_pool::UNSTAKE.0 
      + ON_STAKING_POOL_UNSTAKE_FOR_TERMINATION.0);


    /// Gas attached to inner callback for processing result of unstake call to
    /// staking pool. 
    pub const ON_STAKING_POOL_UNSTAKE_FOR_TERMINATION: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the call to get
    /// the current unstaked balance from staking pool. 
    /// The callback might proceed with withdrawing this amount. 
    pub const ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW: Gas = Gas(
      super::BASE_GAS.0
      + super::staking_pool::WITHDRAW.0
      + ON_STAKING_POOL_WITHDRAW_FOR_TERMINATION.0);

    // Gas attached to inner callback for processing result of withdraw call.
    pub const ON_STAKING_POOL_WITHDRAW_FOR_TERMINATION: Gas = super::BASE_GAS;
    

    /// Gas attached to inner callback for processing result of withdrawal
    /// of terminated unvested balance. 
    pub const ON_WITHDRAW_UNVESTED_AMOUNT: Gas = super::BASE_GAS;
}


pub mod transfer_poll {
    use near_sdk::Gas;

    /// Gas attached to check whether transfers were enabled on transfer poll
    /// contract. 
    pub const GET_RESULT: Gas = super::BASE_GAS;
}

The Base, as previously mentioned, are for local processing (here called local updates, which means the same).

The unstaking part is also similar:

use near_sdk::Gas;

/// For local processing and local updates. 
const BASE_GAS: Gas = Gas(25_000_000_000_000);


pub mod whitelist {
    use near_sdk::Gas;

    /// Gas attached to the promise checking whether the given
    /// staking pool account ID is whitelisted. 
    pub const IS_WHITELISTED: Gas = super::BASE_GAS;
}


pub mod staking_pool {
    use near_sdk::Gas;

    /// Gas attached to deposit call on staking pool contract.
    /// Local updates + restaking (potentially)
    pub const DEPOSIT: Gas = Gas(super::BASE_GAS.0 * 2);

    /// Gas attached to deposit call on staking pool contract.
    /// local updates + staking call (2x Base).
    pub const DEPOSIT_AND_STAKE: Gas = Gas(super::BASE_GAS.0 * 3);

    /// Gas attached to withdraw call on staking pool contract. 
    /// BASE for execution + 2 * BASE for transferring amount and 
    /// potentially restaking. 
    pub const WITHDRAW: Gas = Gas(super::BASE_GAS.0 * 3);


    /// Gas attached to unstake call on staking pool contract. 
    /// BASE for execution + 2 * BASE for staking call. 
    pub const UNSTAKE: Gas = Gas(super::BASE_GAS.0 * 3);

    /// Gas to unstake all call on staking pool contract.
    /// BASE for execution + 2 * BASE for staking call.
    pub const UNSTAKE_ALL: Gas = Gas(super::BASE_GAS.0 * 3);


    /// The amount of Gas required to get the current staked balance
    /// of this account from staking pool. 
    /// Requires BASE for local processing. 
    pub const GET_ACCOUNT_STAKED_BALANCE: Gas = super::BASE_GAS;

    /// The amount of Gas required to get current unstaked balance of 
    /// this account from the staking pool. 
    /// Requires BASE for local processing. 
    pub const GET_ACCOUNT_UNSTAKED_BALANCE: Gas = super::BASE_GAS;

    /// The amount of gas required to get the current total balance
    /// of this account from the staking pool.
    pub const GET_ACCOUNT_TOTAL_BALANCE: Gas = super::BASE_GAS;

    /// Gas attached to stake call on staking pool contract.
    /// Execution + staking call (2x)
    pub const STAKE: Gas = Gas(super::BASE_GAS.0 * 3);
}


pub mod owner_callbacks {
    use near_sdk::Gas;

    /// Gas attached to inner callback for processing whitelist
    /// check results. 
    pub const ON_WHITELIST_IS_WHITELISTED: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of 
    /// deposit call to staking pool. 
    pub const ON_STAKING_POOL_DEPOSIT: Gas = super::BASE_GAS;

    /// Gas attached to inner callbacks for processing result of 
    /// the deposit and stake call to the staking pool. 
    pub const ON_STAKING_POOL_DEPOSIT_AND_STAKE: Gas = super::BASE_GAS;

    /// Gas attached to the inner callback for processing result of
    /// the call to get the current total balance from the staking
    /// pool. 
    pub const ON_GET_ACCOUNT_TOTAL_BALANCE: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the 
    /// withdraw call to the staking pool. 
    pub const ON_STAKING_POOL_WITHDRAW: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the
    /// call to get the current unstaked balance from staking pool.
    /// Callback might proceed with withdrawing this amount. 
    /// local updates + withdrawal + another callback
    pub const ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW_BY_OWNER: Gas = 
      Gas(
        super::BASE_GAS.0
        + super::staking_pool::WITHDRAW.0
        + ON_STAKING_POOL_WITHDRAW.0
      );

    /// Gas attached to the inner callback for processing result
    /// of the stake call to the staking pool. 
    pub const ON_STAKING_POOL_STAKE: Gas = super::BASE_GAS;

    /// Gas attached to the inner callback for processing result 
    /// of the unstake call to the staking pool.
    pub const ON_STAKING_POOL_UNSTAKE: Gas = super::BASE_GAS;

    /// Gas to unstake all call to staking pool.
    pub const ON_STAKING_POOL_UNSTAKE_ALL: Gas = super::BASE_GAS;

    /// Gas attached to the inner callbacks for checking result for
    /// transfer voting call to voting contract.
    pub const ON_VOTING_GET_RESULT: Gas = super::BASE_GAS;
}


pub mod foundation_callbacks {
    use near_sdk::Gas;


    /// Gas attached to inner callback for processing result of the call to get
    /// the current staked balance from staking pool. 
    /// The callback might proceed without unstaking. 
    pub const ON_GET_ACCOUNT_STAKED_BALANCE_TO_UNSTAKE: Gas = Gas(
      super::BASE_GAS.0
      + super::staking_pool::UNSTAKE.0 
      + ON_STAKING_POOL_UNSTAKE_FOR_TERMINATION.0);


    /// Gas attached to inner callback for processing result of unstake call to
    /// staking pool. 
    pub const ON_STAKING_POOL_UNSTAKE_FOR_TERMINATION: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the call to get
    /// the current unstaked balance from staking pool. 
    /// The callback might proceed with withdrawing this amount. 
    pub const ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW: Gas = Gas(
      super::BASE_GAS.0
      + super::staking_pool::WITHDRAW.0
      + ON_STAKING_POOL_WITHDRAW_FOR_TERMINATION.0);

    // Gas attached to inner callback for processing result of withdraw call.
    pub const ON_STAKING_POOL_WITHDRAW_FOR_TERMINATION: Gas = super::BASE_GAS;
    

    /// Gas attached to inner callback for processing result of withdrawal
    /// of terminated unvested balance. 
    pub const ON_WITHDRAW_UNVESTED_AMOUNT: Gas = super::BASE_GAS;
}


pub mod transfer_poll {
    use near_sdk::Gas;

    /// Gas attached to check whether transfers were enabled on transfer poll
    /// contract. 
    pub const GET_RESULT: Gas = super::BASE_GAS;
}
use near_sdk::Gas;

/// For local processing and local updates. 
const BASE_GAS: Gas = Gas(25_000_000_000_000);


pub mod whitelist {
    use near_sdk::Gas;

    /// Gas attached to the promise checking whether the given
    /// staking pool account ID is whitelisted. 
    pub const IS_WHITELISTED: Gas = super::BASE_GAS;
}


pub mod staking_pool {
    use near_sdk::Gas;

    /// Gas attached to deposit call on staking pool contract.
    /// Local updates + restaking (potentially)
    pub const DEPOSIT: Gas = Gas(super::BASE_GAS.0 * 2);

    /// Gas attached to deposit call on staking pool contract.
    /// local updates + staking call (2x Base).
    pub const DEPOSIT_AND_STAKE: Gas = Gas(super::BASE_GAS.0 * 3);

    /// Gas attached to withdraw call on staking pool contract. 
    /// BASE for execution + 2 * BASE for transferring amount and 
    /// potentially restaking. 
    pub const WITHDRAW: Gas = Gas(super::BASE_GAS.0 * 3);


    /// Gas attached to unstake call on staking pool contract. 
    /// BASE for execution + 2 * BASE for staking call. 
    pub const UNSTAKE: Gas = Gas(super::BASE_GAS.0 * 3);

    /// Gas to unstake all call on staking pool contract.
    /// BASE for execution + 2 * BASE for staking call.
    pub const UNSTAKE_ALL: Gas = Gas(super::BASE_GAS.0 * 3);


    /// The amount of Gas required to get the current staked balance
    /// of this account from staking pool. 
    /// Requires BASE for local processing. 
    pub const GET_ACCOUNT_STAKED_BALANCE: Gas = super::BASE_GAS;

    /// The amount of Gas required to get current unstaked balance of 
    /// this account from the staking pool. 
    /// Requires BASE for local processing. 
    pub const GET_ACCOUNT_UNSTAKED_BALANCE: Gas = super::BASE_GAS;

    /// The amount of gas required to get the current total balance
    /// of this account from the staking pool.
    pub const GET_ACCOUNT_TOTAL_BALANCE: Gas = super::BASE_GAS;

    /// Gas attached to stake call on staking pool contract.
    /// Execution + staking call (2x)
    pub const STAKE: Gas = Gas(super::BASE_GAS.0 * 3);
}


pub mod owner_callbacks {
    use near_sdk::Gas;

    /// Gas attached to inner callback for processing whitelist
    /// check results. 
    pub const ON_WHITELIST_IS_WHITELISTED: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of 
    /// deposit call to staking pool. 
    pub const ON_STAKING_POOL_DEPOSIT: Gas = super::BASE_GAS;

    /// Gas attached to inner callbacks for processing result of 
    /// the deposit and stake call to the staking pool. 
    pub const ON_STAKING_POOL_DEPOSIT_AND_STAKE: Gas = super::BASE_GAS;

    /// Gas attached to the inner callback for processing result of
    /// the call to get the current total balance from the staking
    /// pool. 
    pub const ON_GET_ACCOUNT_TOTAL_BALANCE: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the 
    /// withdraw call to the staking pool. 
    pub const ON_STAKING_POOL_WITHDRAW: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the
    /// call to get the current unstaked balance from staking pool.
    /// Callback might proceed with withdrawing this amount. 
    /// local updates + withdrawal + another callback
    pub const ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW_BY_OWNER: Gas = 
      Gas(
        super::BASE_GAS.0
        + super::staking_pool::WITHDRAW.0
        + ON_STAKING_POOL_WITHDRAW.0
      );

    /// Gas attached to the inner callback for processing result
    /// of the stake call to the staking pool. 
    pub const ON_STAKING_POOL_STAKE: Gas = super::BASE_GAS;

    /// Gas attached to the inner callback for processing result 
    /// of the unstake call to the staking pool.
    pub const ON_STAKING_POOL_UNSTAKE: Gas = super::BASE_GAS;

    /// Gas to unstake all call to staking pool.
    pub const ON_STAKING_POOL_UNSTAKE_ALL: Gas = super::BASE_GAS;

    /// Gas attached to the inner callbacks for checking result for
    /// transfer voting call to voting contract.
    pub const ON_VOTING_GET_RESULT: Gas = super::BASE_GAS;
}


pub mod foundation_callbacks {
    use near_sdk::Gas;


    /// Gas attached to inner callback for processing result of the call to get
    /// the current staked balance from staking pool. 
    /// The callback might proceed without unstaking. 
    pub const ON_GET_ACCOUNT_STAKED_BALANCE_TO_UNSTAKE: Gas = Gas(
      super::BASE_GAS.0
      + super::staking_pool::UNSTAKE.0 
      + ON_STAKING_POOL_UNSTAKE_FOR_TERMINATION.0);


    /// Gas attached to inner callback for processing result of unstake call to
    /// staking pool. 
    pub const ON_STAKING_POOL_UNSTAKE_FOR_TERMINATION: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the call to get
    /// the current unstaked balance from staking pool. 
    /// The callback might proceed with withdrawing this amount. 
    pub const ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW: Gas = Gas(
      super::BASE_GAS.0
      + super::staking_pool::WITHDRAW.0
      + ON_STAKING_POOL_WITHDRAW_FOR_TERMINATION.0);

    // Gas attached to inner callback for processing result of withdraw call.
    pub const ON_STAKING_POOL_WITHDRAW_FOR_TERMINATION: Gas = super::BASE_GAS;
    

    /// Gas attached to inner callback for processing result of withdrawal
    /// of terminated unvested balance. 
    pub const ON_WITHDRAW_UNVESTED_AMOUNT: Gas = super::BASE_GAS;
}


pub mod transfer_poll {
    use near_sdk::Gas;

    /// Gas attached to check whether transfers were enabled on transfer poll
    /// contract. 
    pub const GET_RESULT: Gas = super::BASE_GAS;
}
use near_sdk::Gas;

/// For local processing and local updates. 
const BASE_GAS: Gas = Gas(25_000_000_000_000);


pub mod whitelist {
    use near_sdk::Gas;

    /// Gas attached to the promise checking whether the given
    /// staking pool account ID is whitelisted. 
    pub const IS_WHITELISTED: Gas = super::BASE_GAS;
}


pub mod staking_pool {
    use near_sdk::Gas;

    /// Gas attached to deposit call on staking pool contract.
    /// Local updates + restaking (potentially)
    pub const DEPOSIT: Gas = Gas(super::BASE_GAS.0 * 2);

    /// Gas attached to deposit call on staking pool contract.
    /// local updates + staking call (2x Base).
    pub const DEPOSIT_AND_STAKE: Gas = Gas(super::BASE_GAS.0 * 3);

    /// Gas attached to withdraw call on staking pool contract. 
    /// BASE for execution + 2 * BASE for transferring amount and 
    /// potentially restaking. 
    pub const WITHDRAW: Gas = Gas(super::BASE_GAS.0 * 3);


    /// Gas attached to unstake call on staking pool contract. 
    /// BASE for execution + 2 * BASE for staking call. 
    pub const UNSTAKE: Gas = Gas(super::BASE_GAS.0 * 3);

    /// Gas to unstake all call on staking pool contract.
    /// BASE for execution + 2 * BASE for staking call.
    pub const UNSTAKE_ALL: Gas = Gas(super::BASE_GAS.0 * 3);


    /// The amount of Gas required to get the current staked balance
    /// of this account from staking pool. 
    /// Requires BASE for local processing. 
    pub const GET_ACCOUNT_STAKED_BALANCE: Gas = super::BASE_GAS;

    /// The amount of Gas required to get current unstaked balance of 
    /// this account from the staking pool. 
    /// Requires BASE for local processing. 
    pub const GET_ACCOUNT_UNSTAKED_BALANCE: Gas = super::BASE_GAS;

    /// The amount of gas required to get the current total balance
    /// of this account from the staking pool.
    pub const GET_ACCOUNT_TOTAL_BALANCE: Gas = super::BASE_GAS;

    /// Gas attached to stake call on staking pool contract.
    /// Execution + staking call (2x)
    pub const STAKE: Gas = Gas(super::BASE_GAS.0 * 3);
}


pub mod owner_callbacks {
    use near_sdk::Gas;

    /// Gas attached to inner callback for processing whitelist
    /// check results. 
    pub const ON_WHITELIST_IS_WHITELISTED: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of 
    /// deposit call to staking pool. 
    pub const ON_STAKING_POOL_DEPOSIT: Gas = super::BASE_GAS;

    /// Gas attached to inner callbacks for processing result of 
    /// the deposit and stake call to the staking pool. 
    pub const ON_STAKING_POOL_DEPOSIT_AND_STAKE: Gas = super::BASE_GAS;

    /// Gas attached to the inner callback for processing result of
    /// the call to get the current total balance from the staking
    /// pool. 
    pub const ON_GET_ACCOUNT_TOTAL_BALANCE: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the 
    /// withdraw call to the staking pool. 
    pub const ON_STAKING_POOL_WITHDRAW: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the
    /// call to get the current unstaked balance from staking pool.
    /// Callback might proceed with withdrawing this amount. 
    /// local updates + withdrawal + another callback
    pub const ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW_BY_OWNER: Gas = 
      Gas(
        super::BASE_GAS.0
        + super::staking_pool::WITHDRAW.0
        + ON_STAKING_POOL_WITHDRAW.0
      );

    /// Gas attached to the inner callback for processing result
    /// of the stake call to the staking pool. 
    pub const ON_STAKING_POOL_STAKE: Gas = super::BASE_GAS;

    /// Gas attached to the inner callback for processing result 
    /// of the unstake call to the staking pool.
    pub const ON_STAKING_POOL_UNSTAKE: Gas = super::BASE_GAS;

    /// Gas to unstake all call to staking pool.
    pub const ON_STAKING_POOL_UNSTAKE_ALL: Gas = super::BASE_GAS;

    /// Gas attached to the inner callbacks for checking result for
    /// transfer voting call to voting contract.
    pub const ON_VOTING_GET_RESULT: Gas = super::BASE_GAS;
}


pub mod foundation_callbacks {
    use near_sdk::Gas;


    /// Gas attached to inner callback for processing result of the call to get
    /// the current staked balance from staking pool. 
    /// The callback might proceed without unstaking. 
    pub const ON_GET_ACCOUNT_STAKED_BALANCE_TO_UNSTAKE: Gas = Gas(
      super::BASE_GAS.0
      + super::staking_pool::UNSTAKE.0 
      + ON_STAKING_POOL_UNSTAKE_FOR_TERMINATION.0);


    /// Gas attached to inner callback for processing result of unstake call to
    /// staking pool. 
    pub const ON_STAKING_POOL_UNSTAKE_FOR_TERMINATION: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the call to get
    /// the current unstaked balance from staking pool. 
    /// The callback might proceed with withdrawing this amount. 
    pub const ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW: Gas = Gas(
      super::BASE_GAS.0
      + super::staking_pool::WITHDRAW.0
      + ON_STAKING_POOL_WITHDRAW_FOR_TERMINATION.0);

    // Gas attached to inner callback for processing result of withdraw call.
    pub const ON_STAKING_POOL_WITHDRAW_FOR_TERMINATION: Gas = super::BASE_GAS;
    

    /// Gas attached to inner callback for processing result of withdrawal
    /// of terminated unvested balance. 
    pub const ON_WITHDRAW_UNVESTED_AMOUNT: Gas = super::BASE_GAS;
}


pub mod transfer_poll {
    use near_sdk::Gas;

    /// Gas attached to check whether transfers were enabled on transfer poll
    /// contract. 
    pub const GET_RESULT: Gas = super::BASE_GAS;
}

Finally is the termination_withdraw method.

use near_sdk::{near_bindgen, Promise, require, AccountId};
// use near_account_id::AccountId;
use std::cmp;

use crate::*;

#[near_bindgen]
impl LockupContract{
    /// FOUNDATION'S METHOD
    /// 
    /// Requires 25 TGas (1 * BASE_GAS)
    /// 
    /// Terminates vesting schedule and locks the remaining
    /// unvested amount. If the lockup contract was initialized
    /// with the private vesting schedule, then this method 
    /// expects to receive a `VestingScheduleWithSalt` to
    /// reveal the vesting schedule; otherwise expects `None`. 
    pub fn terminate_vesting(
      &mut self,
      vesting_schedule_with_salt: Option<VestingScheduleWithSalt>,
    ) {
      self.assert_called_by_foundation();

      let vesting_schedule = self.assert_vesting(vesting_schedule_with_salt);
      let unvested_amount = self.get_unvested_amount(vesting_schedule);
      require!(
        unvested_amount.0 > 0,
        "The account is fully vested"
      );

      env::log_str(
        format!(
          "Terminating vesting. The remaining unvested balance is {}",
          unvested_amount.0
        ).as_str()
      );

      let deficit = unvested_amount
          .0
          .saturating_sub(self.get_account_balance().0);

      // If there's deficit in liquid balance and a staking pool is selected,
      // then the contract will try to withdraw everything from this staking
      // pool to cover deficit. 
      let status = if deficit > 0 && self.staking_information.is_some() {
        TerminationStatus::VestingTerminatedWithDeficit
      } else {
        TerminationStatus::ReadyToWithdraw
      };

      self.vesting_information = VestingInformation::Terminating(
        TerminationInformation {
          unvested_amount, 
          status,
        }
      );
    }

    /// FOUNDATION'S METHOD
    /// 
    /// Requires 175 TGas (7 * BASE_GAS)
    /// 
    /// When vesting is terminated and there are deficit of the 
    /// tokens on the account, the deficit amount of tokens has to
    /// be unstaked and withdrawn from the staking pool. 
    /// This includes unstaking everything + waiting for 4 epochs
    /// to prepare for withdrawal. 
    pub fn termination_prepare_to_withdraw(&mut self) -> Promise {
      self.assert_called_by_foundation();
      self.assert_staking_pool_is_idle();

      let status = self.get_termination_status();

      match status {
        None => {
          env::panic_str("There is no termination in progress.");
        }

        Some(TerminationStatus::UnstakingInProgress)
        | Some(TerminationStatus::WithdrawingFromStakingPoolInProgress)
        | Some(TerminationStatus::WithdrawingFromAccountInProgress) => {
          env::panic_str("Another transaction already in progress.");
        }

        Some(TerminationStatus::ReadyToWithdraw) => {
          env::panic_str("The account is ready to withdraw unvested balance.")
        }

        Some(TerminationStatus::VestingTerminatedWithDeficit) => {
          // Need to unstake
          self.set_termination_status(TerminationStatus::UnstakingInProgress);
          self.set_staking_pool_status(TransactionStatus::Busy);
          env::log_str("Termination Step: Unstaking everything from staking pool.");

          ext_staking_pool::get_account_staked_balance(
            env::current_account_id(),
            self
                .staking_information
                .as_ref()
                .unwrap()
                .staking_pool_account_id
                .clone(),
            NO_DEPOSIT,
            gas::staking_pool::GET_ACCOUNT_STAKED_BALANCE,
          )
          .then(
            ext_self_foundation::on_get_account_staked_balance_to_unstake(
              env::current_account_id(),
              NO_DEPOSIT,
              gas::foundation_callbacks::ON_GET_ACCOUNT_STAKED_BALANCE_TO_UNSTAKE,
            ),
          )
        }

        Some(TerminationStatus::EverythingUnstaked) => {
          // Need to withdraw everything

          self.set_termination_status(
            TerminationStatus::WithdrawingFromStakingPoolInProgress,
          );
          self.set_staking_pool_status(TransactionStatus::Busy);
          
          env::log_str("Termination Step: Withdraw everything from staking pool.");

          ext_staking_pool::get_account_unstaked_balance(
            env::current_account_id(),
            self.staking_information
                .as_ref()
                .unwrap()
                .staking_pool_account_id
                .clone(),
            NO_DEPOSIT,
            gas::staking_pool::GET_ACCOUNT_UNSTAKED_BALANCE,
          )
          .then(
            ext_self_foundation::on_get_account_unstaked_balance_to_withdraw(
              env::current_account_id(),
              NO_DEPOSIT,
              gas::foundation_callbacks::ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW,
            ),
          )
        }
      }
    }

    /// FOUNDATION'S METHOD
    /// 
    /// Requires 75 TGas
    /// 
    /// Withdraws the unvested amount from the early termination of the 
    /// vesting schedule.
    pub fn termination_withdraw(&mut self, receiver_id: AccountId) -> Promise {
      self.assert_called_by_foundation();

      require!(
        env::is_valid_account_id(receiver_id.as_bytes()),
        "The receiver account ID is invalid."
      );

      require!(
        self.get_termination_status() == Some(TerminationStatus::ReadyToWithdraw),
        "Termination status (Funds) is not ready to withdraw"
      );

      let amount = cmp::min(
        self.get_terminated_unvested_balance().0,
        self.get_account_balance().0
      );

      require!(
        amount > 0,
        "Insufficient liquid balance (amount) to withdraw."
      );

      env::log_str(
        format!(
          "Termination Step: Withdrawing {} of terminated unvested balance to @{}",
          amount, receiver_id
        )
        .as_str(),
      );

      self.set_termination_status(TerminationStatus::WithdrawingFromAccountInProgress);

      Promise::new(receiver_id.clone()).transfer(amount).then(
        ext_self_foundation::on_withdraw_unvested_amount(
          amount.into(),
          receiver_id,
          env::current_account_id(),
          NO_DEPOSIT,
          gas::foundation_callbacks::ON_WITHDRAW_UNVESTED_AMOUNT,
        ),
      )
    }
}



To terminate and wtihdraw, we need to check for several things. Example staking: we need to pass the number of epoch before the funds are ready to withdraw, hence the termination status needs to be checked against, and receiver needs to be the correct person (same ID whom put the fund in in the first place).

We also want to check for something to withdraw before withdrawing.

Here is the gas callback again:

use near_sdk::Gas;

/// For local processing and local updates. 
const BASE_GAS: Gas = Gas(25_000_000_000_000);


pub mod whitelist {
    use near_sdk::Gas;

    /// Gas attached to the promise checking whether the given
    /// staking pool account ID is whitelisted. 
    pub const IS_WHITELISTED: Gas = super::BASE_GAS;
}


pub mod staking_pool {
    use near_sdk::Gas;

    /// Gas attached to deposit call on staking pool contract.
    /// Local updates + restaking (potentially)
    pub const DEPOSIT: Gas = Gas(super::BASE_GAS.0 * 2);

    /// Gas attached to deposit call on staking pool contract.
    /// local updates + staking call (2x Base).
    pub const DEPOSIT_AND_STAKE: Gas = Gas(super::BASE_GAS.0 * 3);

    /// Gas attached to withdraw call on staking pool contract. 
    /// BASE for execution + 2 * BASE for transferring amount and 
    /// potentially restaking. 
    pub const WITHDRAW: Gas = Gas(super::BASE_GAS.0 * 3);


    /// Gas attached to unstake call on staking pool contract. 
    /// BASE for execution + 2 * BASE for staking call. 
    pub const UNSTAKE: Gas = Gas(super::BASE_GAS.0 * 3);

    /// Gas to unstake all call on staking pool contract.
    /// BASE for execution + 2 * BASE for staking call.
    pub const UNSTAKE_ALL: Gas = Gas(super::BASE_GAS.0 * 3);


    /// The amount of Gas required to get the current staked balance
    /// of this account from staking pool. 
    /// Requires BASE for local processing. 
    pub const GET_ACCOUNT_STAKED_BALANCE: Gas = super::BASE_GAS;

    /// The amount of Gas required to get current unstaked balance of 
    /// this account from the staking pool. 
    /// Requires BASE for local processing. 
    pub const GET_ACCOUNT_UNSTAKED_BALANCE: Gas = super::BASE_GAS;

    /// The amount of gas required to get the current total balance
    /// of this account from the staking pool.
    pub const GET_ACCOUNT_TOTAL_BALANCE: Gas = super::BASE_GAS;

    /// Gas attached to stake call on staking pool contract.
    /// Execution + staking call (2x)
    pub const STAKE: Gas = Gas(super::BASE_GAS.0 * 3);
}


pub mod owner_callbacks {
    use near_sdk::Gas;

    /// Gas attached to inner callback for processing whitelist
    /// check results. 
    pub const ON_WHITELIST_IS_WHITELISTED: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of 
    /// deposit call to staking pool. 
    pub const ON_STAKING_POOL_DEPOSIT: Gas = super::BASE_GAS;

    /// Gas attached to inner callbacks for processing result of 
    /// the deposit and stake call to the staking pool. 
    pub const ON_STAKING_POOL_DEPOSIT_AND_STAKE: Gas = super::BASE_GAS;

    /// Gas attached to the inner callback for processing result of
    /// the call to get the current total balance from the staking
    /// pool. 
    pub const ON_GET_ACCOUNT_TOTAL_BALANCE: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the 
    /// withdraw call to the staking pool. 
    pub const ON_STAKING_POOL_WITHDRAW: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the
    /// call to get the current unstaked balance from staking pool.
    /// Callback might proceed with withdrawing this amount. 
    /// local updates + withdrawal + another callback
    pub const ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW_BY_OWNER: Gas = 
      Gas(
        super::BASE_GAS.0
        + super::staking_pool::WITHDRAW.0
        + ON_STAKING_POOL_WITHDRAW.0
      );

    /// Gas attached to the inner callback for processing result
    /// of the stake call to the staking pool. 
    pub const ON_STAKING_POOL_STAKE: Gas = super::BASE_GAS;

    /// Gas attached to the inner callback for processing result 
    /// of the unstake call to the staking pool.
    pub const ON_STAKING_POOL_UNSTAKE: Gas = super::BASE_GAS;

    /// Gas to unstake all call to staking pool.
    pub const ON_STAKING_POOL_UNSTAKE_ALL: Gas = super::BASE_GAS;

    /// Gas attached to the inner callbacks for checking result for
    /// transfer voting call to voting contract.
    pub const ON_VOTING_GET_RESULT: Gas = super::BASE_GAS;
}


pub mod foundation_callbacks {
    use near_sdk::Gas;


    /// Gas attached to inner callback for processing result of the call to get
    /// the current staked balance from staking pool. 
    /// The callback might proceed without unstaking. 
    pub const ON_GET_ACCOUNT_STAKED_BALANCE_TO_UNSTAKE: Gas = Gas(
      super::BASE_GAS.0
      + super::staking_pool::UNSTAKE.0 
      + ON_STAKING_POOL_UNSTAKE_FOR_TERMINATION.0);


    /// Gas attached to inner callback for processing result of unstake call to
    /// staking pool. 
    pub const ON_STAKING_POOL_UNSTAKE_FOR_TERMINATION: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the call to get
    /// the current unstaked balance from staking pool. 
    /// The callback might proceed with withdrawing this amount. 
    pub const ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW: Gas = Gas(
      super::BASE_GAS.0
      + super::staking_pool::WITHDRAW.0
      + ON_STAKING_POOL_WITHDRAW_FOR_TERMINATION.0);

    // Gas attached to inner callback for processing result of withdraw call.
    pub const ON_STAKING_POOL_WITHDRAW_FOR_TERMINATION: Gas = super::BASE_GAS;
    

    /// Gas attached to inner callback for processing result of withdrawal
    /// of terminated unvested balance. 
    pub const ON_WITHDRAW_UNVESTED_AMOUNT: Gas = super::BASE_GAS;
}


pub mod transfer_poll {
    use near_sdk::Gas;

    /// Gas attached to check whether transfers were enabled on transfer poll
    /// contract. 
    pub const GET_RESULT: Gas = super::BASE_GAS;
}

Now if you ask me, how did we manage to know what to write if we're given a blank .rs file? No we don't actually know the code, so we'll do try and see, just like how you write program usually. This section doesn't do that, it directly tells you what is being done. (In a later section we might deal with something from a blank slate and try and see).

Some changes to near-sdk 4.0 pre-release

Previously for cross-contract calls, we are passing in a reference (with &, example &env::something), now it changes to use env::something. But this also means for the &self.staking_information.as_ref().unwrap().staking_pool_account_id in the original code won't work, as after removing & we want them to implement the Copy trait, which is not available. Hence, we can only do .clone() at the end as a temporary workaround to this issue. Keep in mind we might want a different method of dealing with this as .clone() is said to be (one of?) the most inefficient manner to deal with objects. That will have to wait for the super developers to determine how to deal with them when near-sdk 4.0 becomes stable.

Gas

Another thing is Gas. There are some errors that looks like this:

error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
  --> src/gas.rs:20:30
   |
20 |     pub const UNSTAKE: Gas = super::BASE_GAS * 3;
   |                              ^^^^^^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0015`.

which means we can't create a constant directly like this (which results in the error above):

pub const SOME_CONST: Gas = super::BASE_GAS * 3;

As a current workaround, it's something more complicated, we have to force it be constant ourselves until this is fixed. To force it:

use near_sdk::Gas;

/// For local processing and local updates. 
const BASE_GAS: Gas = Gas(25_000_000_000_000);


pub mod whitelist {
    use near_sdk::Gas;

    /// Gas attached to the promise checking whether the given
    /// staking pool account ID is whitelisted. 
    pub const IS_WHITELISTED: Gas = super::BASE_GAS;
}


pub mod staking_pool {
    use near_sdk::Gas;

    /// Gas attached to deposit call on staking pool contract.
    /// Local updates + restaking (potentially)
    pub const DEPOSIT: Gas = Gas(super::BASE_GAS.0 * 2);

    /// Gas attached to deposit call on staking pool contract.
    /// local updates + staking call (2x Base).
    pub const DEPOSIT_AND_STAKE: Gas = Gas(super::BASE_GAS.0 * 3);

    /// Gas attached to withdraw call on staking pool contract. 
    /// BASE for execution + 2 * BASE for transferring amount and 
    /// potentially restaking. 
    pub const WITHDRAW: Gas = Gas(super::BASE_GAS.0 * 3);


    /// Gas attached to unstake call on staking pool contract. 
    /// BASE for execution + 2 * BASE for staking call. 
    pub const UNSTAKE: Gas = Gas(super::BASE_GAS.0 * 3);

    /// Gas to unstake all call on staking pool contract.
    /// BASE for execution + 2 * BASE for staking call.
    pub const UNSTAKE_ALL: Gas = Gas(super::BASE_GAS.0 * 3);


    /// The amount of Gas required to get the current staked balance
    /// of this account from staking pool. 
    /// Requires BASE for local processing. 
    pub const GET_ACCOUNT_STAKED_BALANCE: Gas = super::BASE_GAS;

    /// The amount of Gas required to get current unstaked balance of 
    /// this account from the staking pool. 
    /// Requires BASE for local processing. 
    pub const GET_ACCOUNT_UNSTAKED_BALANCE: Gas = super::BASE_GAS;

    /// The amount of gas required to get the current total balance
    /// of this account from the staking pool.
    pub const GET_ACCOUNT_TOTAL_BALANCE: Gas = super::BASE_GAS;

    /// Gas attached to stake call on staking pool contract.
    /// Execution + staking call (2x)
    pub const STAKE: Gas = Gas(super::BASE_GAS.0 * 3);
}


pub mod owner_callbacks {
    use near_sdk::Gas;

    /// Gas attached to inner callback for processing whitelist
    /// check results. 
    pub const ON_WHITELIST_IS_WHITELISTED: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of 
    /// deposit call to staking pool. 
    pub const ON_STAKING_POOL_DEPOSIT: Gas = super::BASE_GAS;

    /// Gas attached to inner callbacks for processing result of 
    /// the deposit and stake call to the staking pool. 
    pub const ON_STAKING_POOL_DEPOSIT_AND_STAKE: Gas = super::BASE_GAS;

    /// Gas attached to the inner callback for processing result of
    /// the call to get the current total balance from the staking
    /// pool. 
    pub const ON_GET_ACCOUNT_TOTAL_BALANCE: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the 
    /// withdraw call to the staking pool. 
    pub const ON_STAKING_POOL_WITHDRAW: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the
    /// call to get the current unstaked balance from staking pool.
    /// Callback might proceed with withdrawing this amount. 
    /// local updates + withdrawal + another callback
    pub const ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW_BY_OWNER: Gas = 
      Gas(
        super::BASE_GAS.0
        + super::staking_pool::WITHDRAW.0
        + ON_STAKING_POOL_WITHDRAW.0
      );

    /// Gas attached to the inner callback for processing result
    /// of the stake call to the staking pool. 
    pub const ON_STAKING_POOL_STAKE: Gas = super::BASE_GAS;

    /// Gas attached to the inner callback for processing result 
    /// of the unstake call to the staking pool.
    pub const ON_STAKING_POOL_UNSTAKE: Gas = super::BASE_GAS;

    /// Gas to unstake all call to staking pool.
    pub const ON_STAKING_POOL_UNSTAKE_ALL: Gas = super::BASE_GAS;

    /// Gas attached to the inner callbacks for checking result for
    /// transfer voting call to voting contract.
    pub const ON_VOTING_GET_RESULT: Gas = super::BASE_GAS;
}


pub mod foundation_callbacks {
    use near_sdk::Gas;


    /// Gas attached to inner callback for processing result of the call to get
    /// the current staked balance from staking pool. 
    /// The callback might proceed without unstaking. 
    pub const ON_GET_ACCOUNT_STAKED_BALANCE_TO_UNSTAKE: Gas = Gas(
      super::BASE_GAS.0
      + super::staking_pool::UNSTAKE.0 
      + ON_STAKING_POOL_UNSTAKE_FOR_TERMINATION.0);


    /// Gas attached to inner callback for processing result of unstake call to
    /// staking pool. 
    pub const ON_STAKING_POOL_UNSTAKE_FOR_TERMINATION: Gas = super::BASE_GAS;

    /// Gas attached to inner callback for processing result of the call to get
    /// the current unstaked balance from staking pool. 
    /// The callback might proceed with withdrawing this amount. 
    pub const ON_GET_ACCOUNT_UNSTAKED_BALANCE_TO_WITHDRAW: Gas = Gas(
      super::BASE_GAS.0
      + super::staking_pool::WITHDRAW.0
      + ON_STAKING_POOL_WITHDRAW_FOR_TERMINATION.0);

    // Gas attached to inner callback for processing result of withdraw call.
    pub const ON_STAKING_POOL_WITHDRAW_FOR_TERMINATION: Gas = super::BASE_GAS;
    

    /// Gas attached to inner callback for processing result of withdrawal
    /// of terminated unvested balance. 
    pub const ON_WITHDRAW_UNVESTED_AMOUNT: Gas = super::BASE_GAS;
}


pub mod transfer_poll {
    use near_sdk::Gas;

    /// Gas attached to check whether transfers were enabled on transfer poll
    /// contract. 
    pub const GET_RESULT: Gas = super::BASE_GAS;
}

This does not work either, resulting in same error:

pub const SOME_CONST: Gas = Gas(
  (super::BASE_GAS * 3).0
) 

Next, let's take a look at the lib.rs file for the external cross-contract calls ext_ that we skipped earlier.

#TODO: (test might be included later)

Later noted

There's a termination_prepare_to_withdraw where the ext_staking_pool::get_account_staked_balance we have the env::current_account_id() as second argument instead of first. Same for ext_staking_pool::get_account_unstaked_balance. We got it wrong; it should be first argument. If you don't make it first, if you did the integration tests yourself, you'll get this error:

---- test_termination_with_staking_hashed::termination_with_staking_hashed stdout ----
thread 'test_termination_with_staking_hashed::termination_with_staking_hashed' panicked at 'Outcome ExecutionOutcome {
    logs: [],
    receipt_ids: [
        `CzcTYusrPhZMzY4idvaxnDdeqD27q2tFCVC49RVBems2`,
    ],
    burnt_gas: 2513996987497,
    tokens_burnt: 251399698749700000000,
    status: Failure(Action #0: Smart contract panicked: Callback computation 0 was not successful),
} was a failure', /home/azureuser/.cargo/registry/src/github.com-1ecc6299db9ec823/near-sdk-sim-4.0.0-pre.4/src/outcome.rs:90:9
stack backtrace:
   0: rust_begin_unwind
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/std/src/panicking.rs:498:5
   1: core::panicking::panic_fmt
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/panicking.rs:107:14
   2: near_sdk_sim::outcome::ExecutionResult::assert_success
             at /home/azureuser/.cargo/registry/src/github.com-1ecc6299db9ec823/near-sdk-sim-4.0.0-pre.4/src/outcome.rs:90:9
   3: sim::test_termination_with_staking_hashed::termination_with_staking_hashed
             at ./tests/sim/test_termination_with_staking_hashed.rs:213:5
   4: sim::test_termination_with_staking_hashed::termination_with_staking_hashed::{{closure}}
             at ./tests/sim/test_termination_with_staking_hashed.rs:5:1
   5: core::ops::function::FnOnce::call_once
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/ops/function.rs:227:5
   6: core::ops::function::FnOnce::call_once
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/ops/function.rs:227:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

with a backtrace. Because it's a compiled wasm, Smart contract panicked: Callback computation 0 was not successful is just not very helpful.

References