Skip to content

Commit

Permalink
charge all stf fees properly, with respect to decimals
Browse files Browse the repository at this point in the history
  • Loading branch information
brenzi committed Oct 25, 2024
1 parent 884659e commit 1004fb1
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 72 deletions.
52 changes: 25 additions & 27 deletions app-libs/stf/src/guess_the_number.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,37 @@
use crate::helpers::{enclave_signer_account, shielding_target, shielding_target_genesis_hash};
/*
Copyright 2021 Integritee AG and Supercomputing Systems AG
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// TrustedCalls and Getters for the Guess-The-Number game

use crate::helpers::shielding_target_genesis_hash;
#[cfg(not(feature = "std"))]
use alloc::format;
use codec::{Decode, Encode};
use frame_support::dispatch::UnfilteredDispatchable;
use ita_parentchain_specs::MinimalChainSpec;
use ita_sgx_runtime::{
GuessTheNumber, GuessType, ParentchainIntegritee, ParentchainTargetA, ParentchainTargetB,
Runtime, System,
};
use ita_sgx_runtime::{GuessTheNumber, GuessType, Runtime, System};
use itp_node_api::metadata::provider::AccessNodeMetadata;
use itp_node_api_metadata::NodeMetadataTrait;
use itp_sgx_runtime_primitives::types::{Balance, Moment};
use itp_stf_interface::{ExecuteCall, ExecuteGetter};
use itp_stf_primitives::error::StfError;
use itp_types::{
parentchain::{ParentchainCall, ParentchainId},
AccountId,
};
use itp_types::{parentchain::ParentchainCall, AccountId};
use itp_utils::stringify::account_id_to_string;
use log::{debug, info, trace};
use sp_runtime::MultiAddress;
use log::*;
use sp_std::{sync::Arc, vec::Vec};

/// General public information about the status of the guess-the-number game
Expand Down Expand Up @@ -73,7 +85,6 @@ where
_calls: &mut Vec<ParentchainCall>,
_node_metadata_repo: Arc<NodeMetadataRepository>,
) -> Result<(), Self::Error> {
let fee = get_fee_for(&self);
match self {
Self::set_winnings(sender, winnings) => {
// authorization happens in pallet itself, we just pass authentication
Expand Down Expand Up @@ -106,19 +117,6 @@ where
Self::guess(sender, guess) => {
let origin = ita_sgx_runtime::RuntimeOrigin::signed(sender);
std::println!("⣿STF⣿ guess-the-number: someone is attempting a guess");
// endow fee to enclave (self)
let fee_recipient: itp_stf_primitives::types::AccountId = enclave_signer_account();
// fixme: apply fees through standard frame process and tune it
info!("guess fee {}", fee);
ita_sgx_runtime::BalancesCall::<Runtime>::transfer {
dest: MultiAddress::Id(fee_recipient),
value: fee,
}
.dispatch_bypass_filter(origin.clone())
.map_err(|e| {
Self::Error::Dispatch(format!("GuessTheNumber fee error: {:?}", e.error))
})?;

ita_sgx_runtime::GuessTheNumberCall::<Runtime>::guess { guess }
.dispatch_bypass_filter(origin)
.map_err(|e| {
Expand All @@ -136,10 +134,10 @@ where
}
}

fn get_fee_for(tc: &GuessTheNumberTrustedCall) -> Balance {
pub fn get_fee_for(tc: &GuessTheNumberTrustedCall) -> Balance {
let one = MinimalChainSpec::one_unit(shielding_target_genesis_hash().unwrap_or_default());
match tc {
GuessTheNumberTrustedCall::guess(..) => one / crate::STF_GUESS_FEE_DIVIDER,
GuessTheNumberTrustedCall::guess(..) => one / crate::STF_GUESS_FEE_UNIT_DIVIDER,
_ => Balance::from(0u32),
}
}
Expand Down
8 changes: 3 additions & 5 deletions app-libs/stf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ pub mod test_genesis;
pub mod trusted_call;

pub(crate) const ENCLAVE_ACCOUNT_KEY: &str = "Enclave_Account_Key";

// fixme: this if a temporary hack only. double-check decimals for target chain
// as long as it is hard-coded, needs to be reasonable for 10 (Paseo) and 12 decimals
pub const STF_TX_FEE: Balance = 100_000_000;
pub const STF_GUESS_FEE_DIVIDER: Balance = 10;
pub const STF_SHIELDING_FEE_AMOUNT_DIVIDER: Balance = 571; // approx 0.175%
pub const STF_TX_FEE_UNIT_DIVIDER: Balance = 100; // 0.01 tokens
pub const STF_GUESS_FEE_UNIT_DIVIDER: Balance = 10; // 0.1 tokens
70 changes: 34 additions & 36 deletions app-libs/stf/src/trusted_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@ use std::vec::Vec;
use crate::evm_helpers::{create_code_hash, evm_create2_address, evm_create_address};
use crate::{
guess_the_number::GuessTheNumberTrustedCall,
helpers::{enclave_signer_account, ensure_enclave_signer_account, shard_vault, wrap_bytes},
Getter,
helpers::{
enclave_signer_account, ensure_enclave_signer_account, shard_vault,
shielding_target_genesis_hash, wrap_bytes,
},
Getter, STF_SHIELDING_FEE_AMOUNT_DIVIDER,
};
use codec::{Compact, Decode, Encode};
use frame_support::{ensure, traits::UnfilteredDispatchable};
use ita_parentchain_specs::MinimalChainSpec;
#[cfg(feature = "evm")]
use ita_sgx_runtime::{AddressMapping, HashedAddressMapping};
pub use ita_sgx_runtime::{Balance, Index};
Expand Down Expand Up @@ -244,6 +248,10 @@ where
let system_nonce = System::account_nonce(&sender);
ensure!(self.nonce == system_nonce, Self::Error::InvalidNonce(self.nonce, system_nonce));

// try to charge fee first and fail early
let fee = get_fee_for(&self);
charge_fee(fee, &sender)?;

// increment the nonce, no matter if the call succeeds or fails.
// The call must have entered the transaction pool already,
// so it should be considered as valid
Expand Down Expand Up @@ -283,25 +291,6 @@ where
TrustedCall::balance_transfer(from, to, value) => {
let origin = ita_sgx_runtime::RuntimeOrigin::signed(from.clone());
std::println!("⣿STF⣿ 🔄 balance_transfer from ⣿⣿⣿ to ⣿⣿⣿ amount ⣿⣿⣿");
// endow fee to enclave (self)
let fee_recipient: AccountId = enclave_signer_account();
// fixme: apply fees through standard frame process and tune it
let fee = crate::STF_TX_FEE;
info!(
"from {}, to {}, amount {}, fee {}",
account_id_to_string(&from),
account_id_to_string(&to),
value,
fee
);
ita_sgx_runtime::BalancesCall::<Runtime>::transfer {
dest: MultiAddress::Id(fee_recipient),
value: fee,
}
.dispatch_bypass_filter(origin.clone())
.map_err(|e| {
Self::Error::Dispatch(format!("Balance Transfer error: {:?}", e.error))
})?;
ita_sgx_runtime::BalancesCall::<Runtime>::transfer {
dest: MultiAddress::Id(to),
value,
Expand All @@ -318,11 +307,6 @@ where
account_id_to_string(&beneficiary),
value
);
// endow fee to enclave (self)
let fee_recipient: AccountId = enclave_signer_account();
// fixme: apply fees through standard frame process and tune it. has to be at least two L1 transfer's fees
let fee = crate::STF_TX_FEE * 3;

info!(
"balance_unshield(from (L2): {}, to (L1): {}, amount {} (+fee: {}), shard {})",
account_id_to_string(&account_incognito),
Expand All @@ -332,15 +316,6 @@ where
shard
);

let origin = ita_sgx_runtime::RuntimeOrigin::signed(account_incognito.clone());
ita_sgx_runtime::BalancesCall::<Runtime>::transfer {
dest: MultiAddress::Id(fee_recipient),
value: fee,
}
.dispatch_bypass_filter(origin)
.map_err(|e| {
Self::Error::Dispatch(format!("Balance Unshielding error: {:?}", e.error))
})?;
burn_funds(account_incognito, value)?;

let (vault, parentchain_id) = shard_vault().ok_or_else(|| {
Expand Down Expand Up @@ -593,6 +568,29 @@ where
}
}

fn get_fee_for(tc: &TrustedCallSigned) -> Balance {
let one = MinimalChainSpec::one_unit(shielding_target_genesis_hash().unwrap_or_default());
match &tc.call {
TrustedCall::balance_transfer(..) => one / crate::STF_TX_FEE_UNIT_DIVIDER,
TrustedCall::balance_unshield(..) => one / crate::STF_TX_FEE_UNIT_DIVIDER * 3,
TrustedCall::guess_the_number(call) => crate::guess_the_number::get_fee_for(&call),
_ => Balance::from(0u32),
}
}

fn charge_fee(fee: Balance, payer: &AccountId) -> Result<(), StfError> {
debug!("attempting to charge fee for TrustedCall");
let fee_recipient: AccountId = enclave_signer_account();
let origin = ita_sgx_runtime::RuntimeOrigin::signed(payer.clone());
ita_sgx_runtime::BalancesCall::<Runtime>::transfer {
dest: MultiAddress::Id(fee_recipient),
value: fee,
}
.dispatch_bypass_filter(origin)
.map_err(|e| StfError::Dispatch(format!("Fee Payment Error: {:?}", e.error)))?;
Ok(())
}

fn burn_funds(account: AccountId, amount: u128) -> Result<(), StfError> {
let account_info = System::account(&account);
if account_info.data.free < amount {
Expand All @@ -610,7 +608,7 @@ fn burn_funds(account: AccountId, amount: u128) -> Result<(), StfError> {

fn shield_funds(account: AccountId, amount: u128) -> Result<(), StfError> {
//fixme: make fee configurable and send fee to vault account on L2
let fee = amount / 571; // approx 0.175%
let fee = amount / STF_SHIELDING_FEE_AMOUNT_DIVIDER;

// endow fee to enclave (self)
let fee_recipient: AccountId = enclave_signer_account();
Expand Down
9 changes: 6 additions & 3 deletions cli/src/benchmark/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ use crate::{
};
use codec::Decode;
use hdrhistogram::Histogram;
use ita_stf::{Getter, Index, TrustedCall, TrustedCallSigned, TrustedGetter, STF_TX_FEE};
use ita_stf::{
Getter, Index, TrustedCall, TrustedCallSigned, TrustedGetter, STF_TX_FEE_UNIT_DIVIDER,
};
use itc_rpc_client::direct_client::{DirectApi, DirectClient};
use itp_stf_primitives::{
traits::TrustedCallSigning,
Expand Down Expand Up @@ -136,7 +138,8 @@ impl BenchmarkCommand {
println!("Nonce for account {}: {}", self.funding_account, nonce_start);

let mut accounts = Vec::new();
let initial_balance = (self.number_iterations + 1) * (STF_TX_FEE + EXISTENTIAL_DEPOSIT);
let initial_balance = (self.number_iterations + 1)
* (1_000_000_000_000 / STF_TX_FEE_UNIT_DIVIDER + EXISTENTIAL_DEPOSIT);
// Setup new accounts and initialize them with money from Alice.
for i in 0..self.number_clients {
let nonce = i + nonce_start;
Expand Down Expand Up @@ -230,7 +233,7 @@ impl BenchmarkCommand {
output.push(result);

// FIXME: We probably should re-fund the account in this case.
if client.current_balance <= EXISTENTIAL_DEPOSIT + STF_TX_FEE {
if client.current_balance <= 1_000_000_000_000 / STF_TX_FEE_UNIT_DIVIDER + EXISTENTIAL_DEPOSIT {
error!("Account {:?} does not have enough balance anymore. Finishing benchmark early", client.account.public());
break;
}
Expand Down
4 changes: 3 additions & 1 deletion enclave-runtime/src/test/tests_main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,9 @@ fn test_create_state_diff() {
assert_eq!(receiver_acc_info.data.free, TX_AMOUNT);
assert_eq!(
sender_acc_info.data.free,
ita_stf::test_genesis::ENDOWED_ACC_FUNDS - TX_AMOUNT - ita_stf::STF_TX_FEE
ita_stf::test_genesis::ENDOWED_ACC_FUNDS
- TX_AMOUNT
- 1_000_000_000_000 / ita_stf::STF_TX_FEE_UNIT_DIVIDER
);
}

Expand Down

0 comments on commit 1004fb1

Please sign in to comment.