diff --git a/substrate/frame/revive/src/vm/evm/instructions/arithmetic.rs b/substrate/frame/revive/src/vm/evm/instructions/arithmetic.rs index 67910ad1d3581..c1acf2c10f8e3 100644 --- a/substrate/frame/revive/src/vm/evm/instructions/arithmetic.rs +++ b/substrate/frame/revive/src/vm/evm/instructions/arithmetic.rs @@ -37,21 +37,21 @@ pub fn add<'ext, E: Ext>(context: Context<'_, 'ext, E>) { /// Implements the MUL instruction - multiplies two values from stack. pub fn mul<'ext, E: Ext>(context: Context<'_, 'ext, E>) { - gas_legacy!(context.interpreter, revm_gas::LOW); + gas!(context.interpreter, RuntimeCosts::EVMGas(5)); popn_top!([op1], op2, context.interpreter); *op2 = op1.wrapping_mul(*op2); } /// Implements the SUB instruction - subtracts two values from stack. pub fn sub<'ext, E: Ext>(context: Context<'_, 'ext, E>) { - gas_legacy!(context.interpreter, revm_gas::VERYLOW); + gas!(context.interpreter, RuntimeCosts::EVMGas(3)); popn_top!([op1], op2, context.interpreter); *op2 = op1.wrapping_sub(*op2); } /// Implements the DIV instruction - divides two values from stack. pub fn div<'ext, E: Ext>(context: Context<'_, 'ext, E>) { - gas_legacy!(context.interpreter, revm_gas::LOW); + gas!(context.interpreter, RuntimeCosts::EVMGas(5)); popn_top!([op1], op2, context.interpreter); if !op2.is_zero() { *op2 = op1.wrapping_div(*op2); @@ -62,7 +62,7 @@ pub fn div<'ext, E: Ext>(context: Context<'_, 'ext, E>) { /// /// Performs signed division of two values from stack. pub fn sdiv<'ext, E: Ext>(context: Context<'_, 'ext, E>) { - gas_legacy!(context.interpreter, revm_gas::LOW); + gas!(context.interpreter, RuntimeCosts::EVMGas(5)); popn_top!([op1], op2, context.interpreter); *op2 = i256_div(op1, *op2); } @@ -71,7 +71,7 @@ pub fn sdiv<'ext, E: Ext>(context: Context<'_, 'ext, E>) { /// /// Pops two values from stack and pushes the remainder of their division. pub fn rem<'ext, E: Ext>(context: Context<'_, 'ext, E>) { - gas_legacy!(context.interpreter, revm_gas::LOW); + gas!(context.interpreter, RuntimeCosts::EVMGas(5)); popn_top!([op1], op2, context.interpreter); if !op2.is_zero() { *op2 = op1.wrapping_rem(*op2); @@ -82,7 +82,7 @@ pub fn rem<'ext, E: Ext>(context: Context<'_, 'ext, E>) { /// /// Performs signed modulo of two values from stack. pub fn smod<'ext, E: Ext>(context: Context<'_, 'ext, E>) { - gas_legacy!(context.interpreter, revm_gas::LOW); + gas!(context.interpreter, RuntimeCosts::EVMGas(5)); popn_top!([op1], op2, context.interpreter); *op2 = i256_mod(op1, *op2) } @@ -91,7 +91,7 @@ pub fn smod<'ext, E: Ext>(context: Context<'_, 'ext, E>) { /// /// Pops three values from stack and pushes (a + b) % n. pub fn addmod<'ext, E: Ext>(context: Context<'_, 'ext, E>) { - gas_legacy!(context.interpreter, revm_gas::MID); + gas!(context.interpreter, RuntimeCosts::EVMGas(8)); popn_top!([op1, op2], op3, context.interpreter); *op3 = op1.add_mod(op2, *op3) } @@ -100,16 +100,26 @@ pub fn addmod<'ext, E: Ext>(context: Context<'_, 'ext, E>) { /// /// Pops three values from stack and pushes (a * b) % n. pub fn mulmod<'ext, E: Ext>(context: Context<'_, 'ext, E>) { - gas_legacy!(context.interpreter, revm_gas::MID); + gas!(context.interpreter, RuntimeCosts::EVMGas(8)); popn_top!([op1, op2], op3, context.interpreter); *op3 = op1.mul_mod(op2, *op3) } /// Implements the EXP instruction - exponentiates two values from stack. pub fn exp<'ext, E: Ext>(context: Context<'_, 'ext, E>) { - let spec_id = context.interpreter.runtime_flag.spec_id(); popn_top!([op1], op2, context.interpreter); - gas_or_fail!(context.interpreter, revm_gas::exp_cost(spec_id, *op2)); + + // Calculate gas cost for EXP: 10 (base) + 50 * byte_length_of_exponent + // For zero exponent, byte length is 1. For non-zero, calculate based on significant bits. + let exp_byte_len = if op2.is_zero() { + 1u64 + } else { + let significant_bits = 256 - op2.leading_zeros() as u64; + (significant_bits + 7) / 8 // Round up to nearest byte + }; + let gas_cost = 10u64.saturating_add(50u64.saturating_mul(exp_byte_len)); + gas!(context.interpreter, RuntimeCosts::EVMGas(gas_cost)); + *op2 = op1.pow(*op2); } @@ -143,7 +153,7 @@ pub fn exp<'ext, E: Ext>(context: Context<'_, 'ext, E>) { /// Similarly, if `b == 0` then the yellow paper says the output should start with all zeros, /// then end with bits from `b`; this is equal to `y & mask` where `&` is bitwise `AND`. pub fn signextend<'ext, E: Ext>(context: Context<'_, 'ext, E>) { - gas_legacy!(context.interpreter, revm_gas::LOW); + gas!(context.interpreter, RuntimeCosts::EVMGas(5)); popn_top!([ext], x, context.interpreter); // For 31 we also don't need to do anything. if ext < U256::from(31) {