diff --git a/src/precompiles/blake2.rs b/src/precompiles/blake2.rs index 3541fe82b..bf5e7acb9 100644 --- a/src/precompiles/blake2.rs +++ b/src/precompiles/blake2.rs @@ -204,7 +204,8 @@ mod tests { 0300000000000000\ 0000000000000000\ 00", - ).unwrap(); + ) + .unwrap(); blake2f(&input, Some(12)).unwrap().1 } @@ -259,7 +260,9 @@ mod tests { let expected = hex::decode( "75ab69d3190a562c51aef8d88f1c2775876944407270c42c9844252c26d28752\ - 98743e7f6d5ea2f2d3e8d226039cd31b4e426ac4f2d3d666a610c2116fde4735").unwrap(); + 98743e7f6d5ea2f2d3e8d226039cd31b4e426ac4f2d3d666a610c2116fde4735", + ) + .unwrap(); assert_eq!(test_blake2f_final_block_false(), expected); } } diff --git a/src/precompiles/bn128.rs b/src/precompiles/bn128.rs index 6beb68f5e..7c6ed07a7 100644 --- a/src/precompiles/bn128.rs +++ b/src/precompiles/bn128.rs @@ -1,7 +1,7 @@ +use crate::precompiles::util::check_gas; use crate::precompiles::PrecompileResult; use crate::prelude::*; use evm::{ExitError, ExitSucceed}; -use crate::precompiles::util::check_gas; /// bn128 costs. mod costs { @@ -105,7 +105,10 @@ pub(crate) fn alt_bn128_mul(input: &[u8], target_gas: Option) -> Precompile pub(crate) fn alt_bn128_pair(input: &[u8], target_gas: Option) -> PrecompileResult { use bn::{arith::U256, AffineG1, AffineG2, Fq, Fq2, Group, Gt, G1, G2}; - check_gas(target_gas, costs::PAIR_PER_POINT * input.len() as u64 / 192u64 + costs::PAIR)?; + check_gas( + target_gas, + costs::PAIR_PER_POINT * input.len() as u64 / 192u64 + costs::PAIR, + )?; if input.len() % 192 != 0 { return Err(ExitError::Other(Borrowed( diff --git a/src/precompiles/mod.rs b/src/precompiles/mod.rs index e3369ab0e..57703e013 100644 --- a/src/precompiles/mod.rs +++ b/src/precompiles/mod.rs @@ -44,7 +44,7 @@ pub fn istanbul_precompiles( hash::ripemd160(input).as_bytes().to_vec(), 0, ))), - 4 => Some(Ok((ExitSucceed::Returned, identity(input).to_vec(), 0))), + 4 => Some(identity(input, target_gas)), 5 => match modexp::modexp(input, target_gas) { Ok(r) => Some(Ok((ExitSucceed::Returned, r, 0))), Err(e) => Some(Err(e)), @@ -58,10 +58,21 @@ pub fn istanbul_precompiles( } } +mod costs { + pub(super) const IDENTITY_BASE: u64 = 15; + + pub(super) const IDENTITY_PER_WORD: u64 = 3; +} + +/// Takes the input bytes, copies them, and returns it as the output. +/// /// See: https://ethereum.github.io/yellowpaper/paper.pdf /// See: https://etherscan.io/address/0000000000000000000000000000000000000004 -fn identity(input: &[u8]) -> &[u8] { - input +fn identity(input: &[u8], target_gas: Option) -> PrecompileResult { + let cost = (input.len() + 31) as u64 / 32 * costs::IDENTITY_PER_WORD + costs::IDENTITY_BASE; + util::check_gas(target_gas, cost)?; + + Ok((ExitSucceed::Returned, input.to_vec(), 0)) } #[cfg(test)] @@ -70,6 +81,22 @@ mod tests { #[test] fn test_identity() { - assert_eq!(identity(b""), b"") + let input = [0u8, 1, 2, 3]; + + let expected = input[0..2].to_vec(); + let res = identity(&input[0..2], Some(18)).unwrap().1; + assert_eq!(res, expected); + + let expected = input.to_vec(); + let res = identity(&input, Some(18)).unwrap().1; + + // gas fail + let res = identity(&input[0..2], Some(17)); + assert!(matches!(res, Err(ExitError::OutOfGas))); + + // larger input + let input = [0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; + let res = identity(&input, Some(21)).unwrap().1; + assert_eq!(res, input.to_vec()); } }