fix: allow from in eth_call and eth_estimateGas (#4)
* fix gas esimtation in uniswap frontend * calculate empty account
This commit is contained in:
parent
b1d33bb9af
commit
dc0e31cedd
|
@ -8,7 +8,7 @@ use config::Config;
|
|||
use consensus::types::{ExecutionPayload, Header};
|
||||
use consensus::ConsensusClient;
|
||||
use execution::evm::Evm;
|
||||
use execution::types::ExecutionBlock;
|
||||
use execution::types::{CallOpts, ExecutionBlock};
|
||||
use execution::ExecutionClient;
|
||||
|
||||
pub struct Client {
|
||||
|
@ -68,22 +68,16 @@ impl Client {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn call(
|
||||
&self,
|
||||
to: &Address,
|
||||
calldata: &Vec<u8>,
|
||||
value: U256,
|
||||
block: &Option<u64>,
|
||||
) -> Result<Vec<u8>> {
|
||||
pub fn call(&self, opts: &CallOpts, block: &Option<u64>) -> Result<Vec<u8>> {
|
||||
let payload = self.get_payload(block)?;
|
||||
let mut evm = Evm::new(self.execution.clone(), payload);
|
||||
evm.call(to, calldata, value)
|
||||
evm.call(opts)
|
||||
}
|
||||
|
||||
pub fn estimate_gas(&self, to: &Address, calldata: &Vec<u8>, value: U256) -> Result<u64> {
|
||||
pub fn estimate_gas(&self, opts: &CallOpts) -> Result<u64> {
|
||||
let payload = self.get_payload(&None)?;
|
||||
let mut evm = Evm::new(self.execution.clone(), payload);
|
||||
evm.estimate_gas(to, calldata, value)
|
||||
evm.estimate_gas(opts)
|
||||
}
|
||||
|
||||
pub async fn get_balance(&self, address: &Address, block: &Option<u64>) -> Result<U256> {
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
use ethers::{
|
||||
abi::AbiEncode,
|
||||
types::{Address, U256},
|
||||
};
|
||||
use ethers::{abi::AbiEncode, types::Address};
|
||||
use eyre::Result;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{fmt::Display, net::SocketAddr, str::FromStr, sync::Arc};
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
|
@ -14,8 +10,8 @@ use jsonrpsee::{
|
|||
};
|
||||
|
||||
use super::Client;
|
||||
use common::utils::{hex_str_to_bytes, u64_to_hex_string};
|
||||
use execution::types::ExecutionBlock;
|
||||
use common::utils::u64_to_hex_string;
|
||||
use execution::types::{CallOpts, ExecutionBlock};
|
||||
|
||||
pub struct Rpc {
|
||||
client: Arc<Mutex<Client>>,
|
||||
|
@ -110,29 +106,16 @@ impl EthRpcServer for RpcInner {
|
|||
|
||||
async fn call(&self, opts: CallOpts, block: &str) -> Result<String, Error> {
|
||||
let block = convert_err(decode_block(block))?;
|
||||
let to = convert_err(Address::from_str(&opts.to))?;
|
||||
let data = convert_err(hex_str_to_bytes(&opts.data.unwrap_or("0x".to_string())))?;
|
||||
let value = convert_err(U256::from_str_radix(
|
||||
&opts.value.unwrap_or("0x0".to_string()),
|
||||
16,
|
||||
))?;
|
||||
|
||||
let client = self.client.lock().await;
|
||||
let res = convert_err(client.call(&to, &data, value, &block))?;
|
||||
let res = convert_err(client.call(&opts, &block))?;
|
||||
|
||||
Ok(hex::encode(res))
|
||||
Ok(format!("0x{}", hex::encode(res)))
|
||||
}
|
||||
|
||||
async fn estimate_gas(&self, opts: CallOpts) -> Result<String, Error> {
|
||||
let to = convert_err(Address::from_str(&opts.to))?;
|
||||
let data = convert_err(hex_str_to_bytes(&opts.data.unwrap_or("0x".to_string())))?;
|
||||
let value = convert_err(U256::from_str_radix(
|
||||
&opts.value.unwrap_or("0x0".to_string()),
|
||||
16,
|
||||
))?;
|
||||
|
||||
let client = self.client.lock().await;
|
||||
let gas = convert_err(client.estimate_gas(&to, &data, value))?;
|
||||
let gas = convert_err(client.estimate_gas(&opts))?;
|
||||
|
||||
Ok(u64_to_hex_string(gas))
|
||||
}
|
||||
|
||||
|
@ -221,12 +204,3 @@ fn decode_block(block: &str) -> Result<Option<u64>> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct CallOpts {
|
||||
from: Option<String>,
|
||||
to: String,
|
||||
gas: Option<String>,
|
||||
value: Option<String>,
|
||||
data: Option<String>,
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ use tokio::runtime::Runtime;
|
|||
|
||||
use consensus::types::ExecutionPayload;
|
||||
|
||||
use crate::types::CallOpts;
|
||||
|
||||
use super::ExecutionClient;
|
||||
|
||||
pub struct Evm {
|
||||
|
@ -23,13 +25,12 @@ impl Evm {
|
|||
Evm { evm }
|
||||
}
|
||||
|
||||
pub fn call(&mut self, to: &Address, calldata: &Vec<u8>, value: U256) -> Result<Vec<u8>> {
|
||||
pub fn call(&mut self, opts: &CallOpts) -> Result<Vec<u8>> {
|
||||
let mut env = Env::default();
|
||||
let mut tx = revm::TxEnv::default();
|
||||
tx.transact_to = TransactTo::Call(*to);
|
||||
tx.data = Bytes::from(calldata.clone());
|
||||
tx.value = value;
|
||||
env.tx = tx;
|
||||
env.tx.transact_to = TransactTo::Call(opts.to);
|
||||
env.tx.caller = opts.from.unwrap_or(Address::zero());
|
||||
env.tx.value = opts.value.unwrap_or(U256::from(0));
|
||||
env.tx.data = Bytes::from(opts.data.clone().unwrap_or(vec![]));
|
||||
|
||||
self.evm.env = env;
|
||||
|
||||
|
@ -46,13 +47,12 @@ impl Evm {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn estimate_gas(&mut self, to: &Address, calldata: &Vec<u8>, value: U256) -> Result<u64> {
|
||||
pub fn estimate_gas(&mut self, opts: &CallOpts) -> Result<u64> {
|
||||
let mut env = Env::default();
|
||||
let mut tx = revm::TxEnv::default();
|
||||
tx.transact_to = TransactTo::Call(*to);
|
||||
tx.data = Bytes::from(calldata.clone());
|
||||
tx.value = value;
|
||||
env.tx = tx;
|
||||
env.tx.transact_to = TransactTo::Call(opts.to);
|
||||
env.tx.caller = opts.from.unwrap_or(Address::zero());
|
||||
env.tx.value = opts.value.unwrap_or(U256::from(0));
|
||||
env.tx.data = Bytes::from(opts.data.clone().unwrap_or(vec![]));
|
||||
|
||||
self.evm.env = env;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ pub fn verify_proof(proof: &Vec<Vec<u8>>, root: &Vec<u8>, path: &Vec<u8>, value:
|
|||
let nibble = get_nibble(&path, path_offset);
|
||||
let node = &node_list[nibble as usize];
|
||||
|
||||
if node.len() == 0 && value[0] == 0x80 {
|
||||
if node.len() == 0 && is_empty_value(value) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
@ -34,7 +34,7 @@ pub fn verify_proof(proof: &Vec<Vec<u8>>, root: &Vec<u8>, path: &Vec<u8>, value:
|
|||
if i == proof.len() - 1 {
|
||||
// exclusion proof
|
||||
if &node_list[0][skip_length(&node_list[0])..] != &path[path_offset..]
|
||||
&& value[0] == 0x80
|
||||
&& is_empty_value(value)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -57,6 +57,22 @@ pub fn verify_proof(proof: &Vec<Vec<u8>>, root: &Vec<u8>, path: &Vec<u8>, value:
|
|||
false
|
||||
}
|
||||
|
||||
fn is_empty_value(value: &Vec<u8>) -> bool {
|
||||
let mut stream = RlpStream::new();
|
||||
stream.begin_list(4);
|
||||
stream.append_empty_data();
|
||||
stream.append_empty_data();
|
||||
let empty_storage_hash = "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421";
|
||||
stream.append(&hex::decode(empty_storage_hash).unwrap());
|
||||
let empty_code_hash = "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470";
|
||||
stream.append(&hex::decode(empty_code_hash).unwrap());
|
||||
let empty_account = stream.out();
|
||||
|
||||
let is_empty_slot = value.len() == 1 && value[0] == 0x80;
|
||||
let is_empty_account = value == &empty_account;
|
||||
is_empty_slot || is_empty_account
|
||||
}
|
||||
|
||||
fn shared_prefix_length(path: &Vec<u8>, path_offset: usize, node_path: &Vec<u8>) -> usize {
|
||||
let skip_length = skip_length(node_path);
|
||||
let mut node_decoded = vec![];
|
||||
|
|
|
@ -72,6 +72,30 @@ pub struct ExecutionBlock {
|
|||
pub uncles: Vec<H256>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct CallOpts {
|
||||
pub from: Option<Address>,
|
||||
pub to: Address,
|
||||
pub gas: Option<U256>,
|
||||
pub value: Option<U256>,
|
||||
#[serde(default, deserialize_with = "bytes_deserialize")]
|
||||
pub data: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
fn bytes_deserialize<'de, D>(deserializer: D) -> Result<Option<Vec<u8>>, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let bytes: Option<String> = serde::Deserialize::deserialize(deserializer)?;
|
||||
match bytes {
|
||||
Some(bytes) => {
|
||||
let bytes = hex::decode(bytes.strip_prefix("0x").unwrap()).unwrap();
|
||||
Ok(Some(bytes.to_vec()))
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_bytes<S>(bytes: &Vec<u8>, s: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
|
|
Loading…
Reference in New Issue