diff --git a/crates/chainspec/src/hardfork.rs b/crates/chainspec/src/hardfork.rs index 798e0fd196..3c64e6f1b1 100644 --- a/crates/chainspec/src/hardfork.rs +++ b/crates/chainspec/src/hardfork.rs @@ -37,6 +37,7 @@ hardfork!( impl TempoHardfork { /// Returns `true` if this hardfork is Moderato or later. + #[inline] pub fn is_moderato(self) -> bool { self >= Self::Moderato } @@ -144,7 +145,6 @@ mod tests { #[test] fn test_is_moderato() { assert!(!TempoHardfork::Adagio.is_moderato()); - assert!(TempoHardfork::Moderato.is_moderato()); } diff --git a/crates/precompiles/src/lib.rs b/crates/precompiles/src/lib.rs index 678a95f006..2ceee9af38 100644 --- a/crates/precompiles/src/lib.rs +++ b/crates/precompiles/src/lib.rs @@ -26,7 +26,7 @@ use crate::{ nonce::NonceManager, path_usd::PathUSD, stablecoin_exchange::StablecoinExchange, - storage::evm::EvmPrecompileStorageProvider, + storage::{PrecompileStorageProvider, evm::EvmPrecompileStorageProvider}, tip_account_registrar::TipAccountRegistrar, tip_fee_manager::TipFeeManager, tip20::{TIP20Token, address_to_token_id_unchecked, is_tip20}, @@ -277,6 +277,20 @@ fn mutate_void( f(sender, call).into_precompile_result(0, |()| Bytes::new()) } +#[inline] +fn fill_precompile_output( + mut output: PrecompileOutput, + storage: &mut impl PrecompileStorageProvider, +) -> PrecompileOutput { + output.gas_used = storage.gas_used(); + + // add refund only if it is not reverted + if !output.reverted && storage.spec().is_allegretto() { + output.gas_refunded = storage.gas_refunded(); + } + output +} + /// Helper function to return an unknown function selector error /// /// Before Moderato: Returns a generic PrecompileError::Other diff --git a/crates/precompiles/src/nonce/dispatch.rs b/crates/precompiles/src/nonce/dispatch.rs index 283cfaa2e4..649a74383c 100644 --- a/crates/precompiles/src/nonce/dispatch.rs +++ b/crates/precompiles/src/nonce/dispatch.rs @@ -1,6 +1,6 @@ use crate::{ - Precompile, input_cost, nonce::NonceManager, storage::PrecompileStorageProvider, - unknown_selector, view, + Precompile, fill_precompile_output, input_cost, nonce::NonceManager, + storage::PrecompileStorageProvider, unknown_selector, view, }; use alloy::{primitives::Address, sol_types::SolCall}; use revm::precompile::{PrecompileError, PrecompileResult}; @@ -33,10 +33,7 @@ impl Precompile for NonceManager<'_, S> { _ => unknown_selector(selector, self.storage.gas_used(), self.storage.spec()), }; - result.map(|mut res| { - res.gas_used = self.storage.gas_used(); - res - }) + result.map(|res| fill_precompile_output(res, self.storage)) } } diff --git a/crates/precompiles/src/path_usd/dispatch.rs b/crates/precompiles/src/path_usd/dispatch.rs index dd97534a7d..678e00d362 100644 --- a/crates/precompiles/src/path_usd/dispatch.rs +++ b/crates/precompiles/src/path_usd/dispatch.rs @@ -1,5 +1,5 @@ use crate::{ - Precompile, input_cost, metadata, mutate, mutate_void, + Precompile, fill_precompile_output, input_cost, metadata, mutate, mutate_void, path_usd::PathUSD, storage::{ContractStorage, PrecompileStorageProvider}, tip20::{IRolesAuth, ITIP20}, @@ -218,10 +218,7 @@ impl Precompile for PathUSD<'_, S> { _ => Err(PrecompileError::Other("Unknown selector".into())), }; - result.map(|mut res| { - res.gas_used = self.token.storage().gas_used(); - res - }) + result.map(|res| fill_precompile_output(res, self.token.storage())) } } diff --git a/crates/precompiles/src/stablecoin_exchange/dispatch.rs b/crates/precompiles/src/stablecoin_exchange/dispatch.rs index da5f176d39..de11d023bf 100644 --- a/crates/precompiles/src/stablecoin_exchange/dispatch.rs +++ b/crates/precompiles/src/stablecoin_exchange/dispatch.rs @@ -5,7 +5,7 @@ use alloy::{primitives::Address, sol_types::SolCall}; use revm::precompile::{PrecompileError, PrecompileResult}; use crate::{ - Precompile, input_cost, mutate, mutate_void, + Precompile, fill_precompile_output, input_cost, mutate, mutate_void, stablecoin_exchange::{IStablecoinExchange, StablecoinExchange}, storage::PrecompileStorageProvider, unknown_selector, view, @@ -183,10 +183,7 @@ impl<'a, S: PrecompileStorageProvider> Precompile for StablecoinExchange<'a, S> _ => unknown_selector(selector, self.storage.gas_used(), self.storage.spec()), }; - result.map(|mut res| { - res.gas_used = self.storage.gas_used(); - res - }) + result.map(|res| fill_precompile_output(res, self.storage)) } } diff --git a/crates/precompiles/src/storage/evm.rs b/crates/precompiles/src/storage/evm.rs index 113f4687ee..e3bb7a460d 100644 --- a/crates/precompiles/src/storage/evm.rs +++ b/crates/precompiles/src/storage/evm.rs @@ -13,6 +13,7 @@ pub struct EvmPrecompileStorageProvider<'a> { internals: EvmInternals<'a>, chain_id: u64, gas_remaining: u64, + gas_refunded: i64, gas_limit: u64, spec: TempoHardfork, } @@ -29,6 +30,7 @@ impl<'a> EvmPrecompileStorageProvider<'a> { internals, chain_id, gas_remaining: gas_limit, + gas_refunded: 0, gas_limit, spec, } @@ -103,6 +105,12 @@ impl<'a> PrecompileStorageProvider for EvmPrecompileStorageProvider<'a> { result.is_cold, ))?; + // refund gas. + self.refund_gas(revm::interpreter::gas::sstore_refund( + SpecId::AMSTERDAM, + &result.data, + )); + Ok(()) } @@ -165,11 +173,21 @@ impl<'a> PrecompileStorageProvider for EvmPrecompileStorageProvider<'a> { Ok(()) } + #[inline] + fn refund_gas(&mut self, gas: i64) { + self.gas_refunded = self.gas_refunded.saturating_add(gas); + } + #[inline] fn gas_used(&self) -> u64 { self.gas_limit - self.gas_remaining } + #[inline] + fn gas_refunded(&self) -> i64 { + self.gas_refunded + } + #[inline] fn spec(&self) -> TempoHardfork { self.spec diff --git a/crates/precompiles/src/storage/hashmap.rs b/crates/precompiles/src/storage/hashmap.rs index 50b7ff6e80..3067c2ca38 100644 --- a/crates/precompiles/src/storage/hashmap.rs +++ b/crates/precompiles/src/storage/hashmap.rs @@ -135,10 +135,18 @@ impl PrecompileStorageProvider for HashMapStorageProvider { Ok(()) } + fn refund_gas(&mut self, _gas: i64) { + // No-op + } + fn gas_used(&self) -> u64 { 0 } + fn gas_refunded(&self) -> i64 { + 0 + } + fn spec(&self) -> TempoHardfork { self.spec } diff --git a/crates/precompiles/src/storage/mod.rs b/crates/precompiles/src/storage/mod.rs index e9653de12c..f171636f56 100644 --- a/crates/precompiles/src/storage/mod.rs +++ b/crates/precompiles/src/storage/mod.rs @@ -47,9 +47,15 @@ pub trait PrecompileStorageProvider { /// Deducts gas from the remaining gas and return an error if the gas is insufficient. fn deduct_gas(&mut self, gas: u64) -> Result<(), TempoPrecompileError>; + /// Add refund to the refund gas counter. + fn refund_gas(&mut self, gas: i64); + /// Returns the gas used so far. fn gas_used(&self) -> u64; + /// Returns the gas refunded so far. + fn gas_refunded(&self) -> i64; + /// Currently active hardfork. fn spec(&self) -> TempoHardfork; } diff --git a/crates/precompiles/src/tip20/dispatch.rs b/crates/precompiles/src/tip20/dispatch.rs index 6af9f817a2..a264d7f675 100644 --- a/crates/precompiles/src/tip20/dispatch.rs +++ b/crates/precompiles/src/tip20/dispatch.rs @@ -1,6 +1,6 @@ use super::ITIP20; use crate::{ - Precompile, input_cost, metadata, mutate, mutate_void, + Precompile, fill_precompile_output, input_cost, metadata, mutate, mutate_void, storage::PrecompileStorageProvider, tip20::{IRolesAuth, TIP20Token}, unknown_selector, view, @@ -251,10 +251,7 @@ impl<'a, S: PrecompileStorageProvider> Precompile for TIP20Token<'a, S> { _ => unknown_selector(selector, self.storage.gas_used(), self.storage.spec()), }; - result.map(|mut res| { - res.gas_used = self.storage.gas_used(); - res - }) + result.map(|res| fill_precompile_output(res, self.storage)) } } diff --git a/crates/precompiles/src/tip20_factory/dispatch.rs b/crates/precompiles/src/tip20_factory/dispatch.rs index d0fc8d895b..63f1842548 100644 --- a/crates/precompiles/src/tip20_factory/dispatch.rs +++ b/crates/precompiles/src/tip20_factory/dispatch.rs @@ -1,4 +1,6 @@ -use crate::{Precompile, input_cost, mutate, tip20::is_tip20, unknown_selector, view}; +use crate::{ + Precompile, fill_precompile_output, input_cost, mutate, tip20::is_tip20, unknown_selector, view, +}; use alloy::{primitives::Address, sol_types::SolCall}; use revm::precompile::{PrecompileError, PrecompileResult}; @@ -36,10 +38,7 @@ impl<'a, S: PrecompileStorageProvider> Precompile for TIP20Factory<'a, S> { _ => unknown_selector(selector, self.storage.gas_used(), self.storage.spec()), }; - result.map(|mut res| { - res.gas_used = self.storage.gas_used(); - res - }) + result.map(|res| fill_precompile_output(res, self.storage)) } } diff --git a/crates/precompiles/src/tip20_rewards_registry/dispatch.rs b/crates/precompiles/src/tip20_rewards_registry/dispatch.rs index b6470ffb1b..c839908737 100644 --- a/crates/precompiles/src/tip20_rewards_registry/dispatch.rs +++ b/crates/precompiles/src/tip20_rewards_registry/dispatch.rs @@ -1,4 +1,4 @@ -use crate::{Precompile, input_cost, mutate_void, unknown_selector}; +use crate::{Precompile, fill_precompile_output, input_cost, mutate_void, unknown_selector}; use alloy::{primitives::Address, sol_types::SolCall}; use revm::precompile::{PrecompileError, PrecompileResult}; use tempo_contracts::precompiles::ITIP20RewardsRegistry; @@ -30,10 +30,7 @@ impl<'a, S: PrecompileStorageProvider> Precompile for TIP20RewardsRegistry<'a, S _ => unknown_selector(selector, self.storage.gas_used(), self.storage.spec()), }; - result.map(|mut res| { - res.gas_used = self.storage.gas_used(); - res - }) + result.map(|res| fill_precompile_output(res, self.storage)) } } diff --git a/crates/precompiles/src/tip403_registry/dispatch.rs b/crates/precompiles/src/tip403_registry/dispatch.rs index 12a7ce70ca..50e99299ef 100644 --- a/crates/precompiles/src/tip403_registry/dispatch.rs +++ b/crates/precompiles/src/tip403_registry/dispatch.rs @@ -1,4 +1,6 @@ -use crate::{Precompile, input_cost, mutate, mutate_void, unknown_selector, view}; +use crate::{ + Precompile, fill_precompile_output, input_cost, mutate, mutate_void, unknown_selector, view, +}; use alloy::{primitives::Address, sol_types::SolCall}; use revm::precompile::{PrecompileError, PrecompileResult}; @@ -69,10 +71,7 @@ impl<'a, S: PrecompileStorageProvider> Precompile for TIP403Registry<'a, S> { _ => unknown_selector(selector, self.storage.gas_used(), self.storage.spec()), }; - result.map(|mut res| { - res.gas_used = self.storage.gas_used(); - res - }) + result.map(|res| fill_precompile_output(res, self.storage)) } } diff --git a/crates/precompiles/src/tip_account_registrar/dispatch.rs b/crates/precompiles/src/tip_account_registrar/dispatch.rs index 10edcaf4c0..9f096938eb 100644 --- a/crates/precompiles/src/tip_account_registrar/dispatch.rs +++ b/crates/precompiles/src/tip_account_registrar/dispatch.rs @@ -1,4 +1,7 @@ -use crate::{Precompile, input_cost, mutate, storage::PrecompileStorageProvider, unknown_selector}; +use crate::{ + Precompile, fill_precompile_output, input_cost, mutate, storage::PrecompileStorageProvider, + unknown_selector, +}; use alloy::{primitives::Address, sol_types::SolCall}; use revm::precompile::{PrecompileError, PrecompileResult}; @@ -46,10 +49,7 @@ impl<'a, S: PrecompileStorageProvider> Precompile for TipAccountRegistrar<'a, S> _ => unknown_selector(selector, self.storage.gas_used(), self.storage.spec()), }; - result.map(|mut res| { - res.gas_used = self.storage.gas_used(); - res - }) + result.map(|res| fill_precompile_output(res, self.storage)) } } diff --git a/crates/precompiles/src/tip_fee_manager/dispatch.rs b/crates/precompiles/src/tip_fee_manager/dispatch.rs index 225a29b712..7c48e0705e 100644 --- a/crates/precompiles/src/tip_fee_manager/dispatch.rs +++ b/crates/precompiles/src/tip_fee_manager/dispatch.rs @@ -1,7 +1,7 @@ use crate::{ Precompile, error::TempoPrecompileError, - input_cost, mutate, mutate_void, + fill_precompile_output, input_cost, mutate, mutate_void, storage::PrecompileStorageProvider, tip_fee_manager::{IFeeManager, ITIPFeeAMM, TipFeeManager, amm::MIN_LIQUIDITY}, unknown_selector, view, @@ -153,10 +153,7 @@ impl<'a, S: PrecompileStorageProvider> Precompile for TipFeeManager<'a, S> { _ => unknown_selector(selector, self.storage.gas_used(), self.storage.spec()), }; - result.map(|mut res| { - res.gas_used = self.storage.gas_used(); - res - }) + result.map(|res| fill_precompile_output(res, self.storage)) } } diff --git a/crates/precompiles/src/validator_config/dispatch.rs b/crates/precompiles/src/validator_config/dispatch.rs index ef61e0e3cd..60cc128fae 100644 --- a/crates/precompiles/src/validator_config/dispatch.rs +++ b/crates/precompiles/src/validator_config/dispatch.rs @@ -1,6 +1,7 @@ use super::{IValidatorConfig, ValidatorConfig}; use crate::{ - Precompile, input_cost, mutate_void, storage::PrecompileStorageProvider, unknown_selector, view, + Precompile, fill_precompile_output, input_cost, mutate_void, + storage::PrecompileStorageProvider, unknown_selector, view, }; use alloy::{primitives::Address, sol_types::SolCall}; use revm::precompile::{PrecompileError, PrecompileResult}; @@ -61,10 +62,7 @@ impl<'a, S: PrecompileStorageProvider> Precompile for ValidatorConfig<'a, S> { _ => unknown_selector(selector, self.storage.gas_used(), self.storage.spec()), }; - result.map(|mut res| { - res.gas_used = self.storage.gas_used(); - res - }) + result.map(|res| fill_precompile_output(res, self.storage)) } }