Skip to content

Commit

Permalink
feat(provider): add an entry point v0.7 provider
Browse files Browse the repository at this point in the history
  • Loading branch information
dancoombs committed Mar 25, 2024
1 parent b623c94 commit e85626f
Show file tree
Hide file tree
Showing 21 changed files with 863 additions and 109 deletions.
5 changes: 2 additions & 3 deletions crates/pool/src/mempool/paymaster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,9 +523,8 @@ impl PaymasterBalance {
#[cfg(test)]
mod tests {
use ethers::types::{Address, H256, U256};
use rundler_provider::MockEntryPointV0_6;
use rundler_provider::{DepositInfo, MockEntryPointV0_6};
use rundler_types::{
contracts::v0_6::verifying_paymaster::DepositInfo,
pool::{PaymasterMetadata, PoolOperation},
v0_6::UserOperation,
EntityInfos, UserOperation as UserOperationTrait, UserOperationId, ValidTimeRange,
Expand Down Expand Up @@ -971,7 +970,7 @@ mod tests {

entrypoint.expect_get_deposit_info().returning(|_| {
Ok(DepositInfo {
deposit: 1000,
deposit: 1000.into(),
staked: true,
stake: 10000,
unstake_delay_sec: 100,
Expand Down
5 changes: 2 additions & 3 deletions crates/pool/src/mempool/uo_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -681,13 +681,12 @@ mod tests {
use std::collections::HashMap;

use ethers::types::{Bytes, H160};
use rundler_provider::MockEntryPointV0_6;
use rundler_provider::{DepositInfo, MockEntryPointV0_6};
use rundler_sim::{
MockPrechecker, MockSimulator, PrecheckError, PrecheckSettings, SimulationError,
SimulationResult, SimulationSettings, ViolationError,
};
use rundler_types::{
contracts::v0_6::verifying_paymaster::DepositInfo,
pool::{PrecheckViolation, SimulationViolation},
v0_6::UserOperation,
EntityInfo, EntityInfos, EntityType, EntryPointVersion, GasFees,
Expand Down Expand Up @@ -1428,7 +1427,7 @@ mod tests {
let mut entrypoint = MockEntryPointV0_6::new();
entrypoint.expect_get_deposit_info().returning(|_| {
Ok(DepositInfo {
deposit: 1000,
deposit: 1000.into(),
staked: true,
stake: 10000,
unstake_delay_sec: 100,
Expand Down
44 changes: 44 additions & 0 deletions crates/provider/src/ethers/entry_point/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,48 @@
// You should have received a copy of the GNU General Public License along with Rundler.
// If not, see https://www.gnu.org/licenses/.

use ethers::{
providers::Middleware,
types::{Address, Bytes, Eip1559TransactionRequest, U256, U64},
};
use rundler_types::contracts::{
arbitrum::node_interface::NodeInterface, optimism::gas_price_oracle::GasPriceOracle,
};

pub(crate) mod v0_6;
pub(crate) mod v0_7;

async fn estimate_arbitrum_l1_gas<P: Middleware + 'static>(
arb_node: &NodeInterface<P>,
address: Address,
data: Bytes,
) -> anyhow::Result<U256> {
let gas = arb_node
.gas_estimate_l1_component(address, false, data)
.call()
.await?;
Ok(U256::from(gas.0))
}

async fn estimate_optimism_l1_gas<P: Middleware + 'static>(
opt_oracle: &GasPriceOracle<P>,
address: Address,
data: Bytes,
gas_price: U256,
) -> anyhow::Result<U256> {
// construct an unsigned transaction with default values just for L1 gas estimation
let tx = Eip1559TransactionRequest::new()
.from(Address::random())
.to(address)
.gas(U256::from(1_000_000))
.max_priority_fee_per_gas(U256::from(100_000_000))
.max_fee_per_gas(U256::from(100_000_000))
.value(U256::from(0))
.data(data)
.nonce(U256::from(100_000))
.chain_id(U64::from(100_000))
.rlp();

let l1_fee = opt_oracle.get_l1_fee(tx).call().await?;
Ok(l1_fee.checked_div(gas_price).unwrap_or(U256::MAX))
}
82 changes: 47 additions & 35 deletions crates/provider/src/ethers/entry_point/v0_6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use ethers::{
providers::{spoof, Middleware, RawCall},
types::{
transaction::eip2718::TypedTransaction, Address, BlockId, Bytes, Eip1559TransactionRequest,
H160, H256, U256, U64,
H160, H256, U256,
},
utils::hex,
};
Expand All @@ -31,18 +31,22 @@ use rundler_types::{
v0_6::{
get_balances::{GetBalancesResult, GETBALANCES_BYTECODE},
i_aggregator::IAggregator,
i_entry_point::{ExecutionResult, FailedOp, IEntryPoint, SignatureValidationFailed},
i_entry_point::{
DepositInfo as DepositInfoV0_6, ExecutionResult as ExecutionResultV0_6, FailedOp,
IEntryPoint, SignatureValidationFailed,
},
shared_types::UserOpsPerAggregator as UserOpsPerAggregatorV0_6,
},
},
v0_6::UserOperation,
DepositInfoV0_6, GasFees, UserOpsPerAggregator, ValidationOutput,
GasFees, UserOpsPerAggregator, ValidationOutput,
};
use rundler_utils::eth::{self, ContractRevertError};

use crate::{
traits::HandleOpsOut, AggregatorOut, AggregatorSimOut, BundleHandler, EntryPointProvider,
L1GasProvider, Provider, SignatureAggregator, SimulationProvider,
traits::HandleOpsOut, AggregatorOut, AggregatorSimOut, BundleHandler, DepositInfo,
EntryPointProvider, ExecutionResult, L1GasProvider, Provider, SignatureAggregator,
SimulationProvider,
};

const ARBITRUM_NITRO_NODE_INTERFACE_ADDRESS: Address = H160([
Expand Down Expand Up @@ -119,12 +123,13 @@ where
.context("entry point should return balance")
}

async fn get_deposit_info(&self, address: Address) -> anyhow::Result<DepositInfoV0_6> {
async fn get_deposit_info(&self, address: Address) -> anyhow::Result<DepositInfo> {
Ok(self
.i_entry_point
.get_deposit_info(address)
.await
.context("should get deposit info")?)
.context("should get deposit info")?
.into())
}

async fn get_balances(&self, addresses: Vec<Address>) -> anyhow::Result<Vec<U256>> {
Expand Down Expand Up @@ -265,12 +270,7 @@ where
.calldata()
.context("should get calldata for entry point handle ops")?;

let gas = self
.arb_node
.gas_estimate_l1_component(entry_point_address, false, data)
.call()
.await?;
Ok(U256::from(gas.0))
super::estimate_arbitrum_l1_gas(&self.arb_node, entry_point_address, data).await
}

async fn calc_optimism_l1_gas(
Expand All @@ -285,21 +285,8 @@ where
.calldata()
.context("should get calldata for entry point handle ops")?;

// construct an unsigned transaction with default values just for L1 gas estimation
let tx = Eip1559TransactionRequest::new()
.from(Address::random())
.to(entry_point_address)
.gas(U256::from(1_000_000))
.max_priority_fee_per_gas(U256::from(100_000_000))
.max_fee_per_gas(U256::from(100_000_000))
.value(U256::from(0))
.data(data)
.nonce(U256::from(100_000))
.chain_id(U64::from(100_000))
.rlp();

let l1_fee = self.opt_gas_oracle.get_l1_fee(tx).call().await?;
Ok(l1_fee.checked_div(gas_price).unwrap_or(U256::MAX))
super::estimate_optimism_l1_gas(&self.opt_gas_oracle, entry_point_address, data, gas_price)
.await
}
}

Expand All @@ -310,18 +297,18 @@ where
{
type UO = UserOperation;

async fn get_simulate_validation_call(
fn get_tracer_simulate_validation_call(
&self,
user_op: UserOperation,
max_validation_gas: u64,
) -> anyhow::Result<TypedTransaction> {
) -> (TypedTransaction, spoof::State) {
let pvg = user_op.pre_verification_gas;
let tx = self
let call = self
.i_entry_point
.simulate_validation(user_op)
.gas(U256::from(max_validation_gas) + pvg)
.tx;
Ok(tx)
(call, spoof::State::default())
}

async fn call_simulate_validation(
Expand All @@ -338,7 +325,7 @@ where
.await
{
Ok(()) => anyhow::bail!("simulateValidation should always revert"),
Err(ContractError::Revert(revert_data)) => ValidationOutput::decode(revert_data)
Err(ContractError::Revert(revert_data)) => ValidationOutput::decode_v0_6(revert_data)
.context("entry point should return validation output"),
Err(error) => Err(error).context("call simulation RPC failed")?,
}
Expand All @@ -348,8 +335,8 @@ where
&self,
revert_data: Bytes,
) -> Result<ExecutionResult, String> {
if let Ok(result) = ExecutionResult::decode(&revert_data) {
Ok(result)
if let Ok(result) = ExecutionResultV0_6::decode(&revert_data) {
Ok(result.into())
} else if let Ok(failed_op) = FailedOp::decode(&revert_data) {
Err(failed_op.reason)
} else if let Ok(err) = ContractRevertError::decode(&revert_data) {
Expand Down Expand Up @@ -411,3 +398,28 @@ fn get_handle_ops_call<M: Middleware>(
};
call.gas(gas)
}

impl From<ExecutionResultV0_6> for ExecutionResult {
fn from(result: ExecutionResultV0_6) -> Self {
ExecutionResult {
pre_op_gas: result.pre_op_gas,
paid: result.paid,
valid_after: result.valid_after.into(),
valid_until: result.valid_until.into(),
target_success: result.target_success,
target_result: result.target_result,
}
}
}

impl From<DepositInfoV0_6> for DepositInfo {
fn from(info: DepositInfoV0_6) -> Self {
DepositInfo {
deposit: info.deposit.into(),
staked: info.staked,
stake: info.stake,
unstake_delay_sec: info.unstake_delay_sec,
withdraw_time: info.withdraw_time,
}
}
}
Loading

0 comments on commit e85626f

Please sign in to comment.