Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate tests #26

Merged
merged 9 commits into from
Jan 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ jobs:
- name: Setup third party dependencies
run: |
make fetch-thirdparty
- name: Install Foundry
zsluedem marked this conversation as resolved.
Show resolved Hide resolved
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly
- name: Install solc
run: |
sudo add-apt-repository ppa:ethereum/ethereum
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "thirdparty/account-abstraction"]
path = thirdparty/account-abstraction
url = https://github.com/eth-infinitism/account-abstraction.git
[submodule "thirdparty/bundler"]
path = thirdparty/bundler
url = https://github.com/eth-infinitism/bundler.git
22 changes: 11 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ authors = ["Vid Kersic <[email protected]>"]
edition = "2021"
description = "AA - Bundler implementation"
default-run = "bundler"
rust-version = "1.66.1"

[dependencies]
anyhow = "1"
Expand All @@ -13,7 +14,7 @@ clap = { version = "4", features = ["derive"] }
dirs = "4.0"
educe = { version = "0.4", features = ["Debug", "Default"] }
ethereum-interfaces = { git = "https://github.com/ledgerwatch/interfaces" }
ethers = { git = "https://github.com/gakonst/ethers-rs", rev = "b27c7b0", features = ["ethers-solc"] }
ethers = { git = "https://github.com/gakonst/ethers-rs.git", rev = "3ed83d5dd38e7819605511631aaddcc3e472427e", features = ["ethers-solc"] }
expanded-pathbuf = "0.1"
hex = { version = "0.4.3", default-features = false, features = ["std"] }
jsonrpsee = { version = "0.16", features = ["server", "macros"] }
Expand All @@ -34,7 +35,7 @@ tracing-subscriber = "0.3"

[build-dependencies]
anyhow = "1"
ethers = { git = "https://github.com/gakonst/ethers-rs", rev = "b27c7b0", features = ["ethers-solc"] }
ethers = { git = "https://github.com/gakonst/ethers-rs.git", rev = "3ed83d5dd38e7819605511631aaddcc3e472427e", features = ["ethers-solc"] }
protobuf-src = "1.1.0"
prost-build = "0.11"
tonic-build = "0.8"
Expand Down
15 changes: 12 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
build:
make fetch-thirdparty
cd thirdparty/account-abstraction && yarn install && yarn compile && cd ../..
cargo build

run-bundler:
Expand All @@ -14,14 +16,21 @@ run-create-wallet:
cargo run --bin create-wallet -- --output-path ${HOME}/.aa-bundler

fetch-thirdparty:
git submodule update --init
git submodule update --init

test:
test:
cd thirdparty/bundler && yarn install && yarn preprocess && cd ../..
cargo test

format:
cargo fmt --all

lint:
cd thirdparty/bundler && yarn install && yarn preprocess && cd ../..
cargo fmt --all -- --check
cargo clippy -- -D warnings -A clippy::derive_partial_eq_without_eq
cargo clippy --tests -- -D warnings -A clippy::derive_partial_eq_without_eq

clean:
cd thirdparty/account-abstraction && yarn clean && cd ../..
cd thirdparty/bundler && yarn clear && cd ../..
cargo clean
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ For more information: https://hackmd.io/@Vid201/aa-bundler-rust

## Prerequisites

1. Ethereum JSON-RPC API with enabled [`debug_traceCall`](https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-debug#debug_tracecall) (currently implemented only in [Geth](https://github.com/ethereum/go-ethereum) and [Erigon](https://github.com/ledgerwatch/erigon)). For testing purposes, you can setup [private Geth node](https://github.com/krzkaczor/geth-private-node).
1. [solc](https://docs.soliditylang.org/en/v0.8.17/installing-solidity.html) >=0.8.12
1. Ethereum execution client JSON-RPC API with enabled [`debug_traceCall`](https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-debug#debug_tracecall). For production, you can use [Geth](https://github.com/ethereum/go-ethereum) or [Erigon](https://github.com/ledgerwatch/erigon). For testing purposes, you can use [Anvil](https://github.com/foundry-rs/foundry/tree/master/anvil#anvil), which provides enough functionalities of execution clients like Geth. To install Anvil, use [foundryup](https://getfoundry.sh/)
2. [solc](https://docs.soliditylang.org/en/v0.8.17/installing-solidity.html) >=0.8.12

## How to run?

Expand Down
6 changes: 3 additions & 3 deletions src/types/user_operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ mod tests {
call_gas_limit: U256::from(200000),
verification_gas_limit: U256::from(100000),
pre_verification_gas: U256::from(21000),
max_fee_per_gas: U256::from(3000000000 as u64),
max_fee_per_gas: U256::from(3000000000_u64),
max_priority_fee_per_gas: U256::from(1000000000),
paymaster_and_data: Bytes::default(),
signature: Bytes::from_str("0x7cb39607585dee8e297d0d7a669ad8c5e43975220b6773c10a138deadbc8ec864981de4b9b3c735288a217115fb33f8326a61ddabc60a534e3b5536515c70f931c").unwrap(),
Expand Down Expand Up @@ -169,7 +169,7 @@ mod tests {
call_gas_limit: U256::from(200000),
verification_gas_limit: U256::from(100000),
pre_verification_gas: U256::from(21000),
max_fee_per_gas: U256::from(3000000000 as u64),
max_fee_per_gas: U256::from(3000000000_u64),
max_priority_fee_per_gas: U256::from(1000000000),
paymaster_and_data: Bytes::default(),
signature: Bytes::from_str("0x7cb39607585dee8e297d0d7a669ad8c5e43975220b6773c10a138deadbc8ec864981de4b9b3c735288a217115fb33f8326a61ddabc60a534e3b5536515c70f931c").unwrap(),
Expand Down Expand Up @@ -203,7 +203,7 @@ mod tests {
call_gas_limit: U256::from(200000),
verification_gas_limit: U256::from(100000),
pre_verification_gas: U256::from(21000),
max_fee_per_gas: U256::from(3000000000 as u64),
max_fee_per_gas: U256::from(3000000000_u64),
max_priority_fee_per_gas: U256::from(1000000000),
paymaster_and_data: Bytes::default(),
signature: Bytes::from_str("0x7cb39607585dee8e297d0d7a669ad8c5e43975220b6773c10a138deadbc8ec864981de4b9b3c735288a217115fb33f8326a61ddabc60a534e3b5536515c70f931c").unwrap(),
Expand Down
1 change: 1 addition & 0 deletions src/uopool/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ mod tests {
use super::*;
use ethers::types::{H256, U256};

#[allow(clippy::unit_cmp)]
#[tokio::test]
async fn memory_mempool() {
let entry_point = Address::random();
Expand Down
40 changes: 40 additions & 0 deletions tests/common/gen.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use ethers::prelude::abigen;

abigen!(SimpleAccountFactory,
"$CARGO_MANIFEST_DIR/thirdparty/account-abstraction/artifacts/contracts/samples/SimpleAccountFactory.sol/SimpleAccountFactory.json");

abigen!(SimpleAccount,
"$CARGO_MANIFEST_DIR/thirdparty/account-abstraction/artifacts/contracts/samples/SimpleAccount.sol/SimpleAccount.json");

abigen!(
EntryPointContract,
"$CARGO_MANIFEST_DIR/thirdparty/account-abstraction/artifacts/contracts/core/EntryPoint.sol/EntryPoint.json"
);
abigen!(
TestOpcodesAccountFactory,
"$CARGO_MANIFEST_DIR/thirdparty/bundler/packages/bundler/artifacts/contracts/tests/TestOpcodesAccount.sol/TestOpcodesAccountFactory.json"
);
abigen!(
TestOpcodesAccount,
"$CARGO_MANIFEST_DIR/thirdparty/bundler/packages/bundler/artifacts/contracts/tests/TestOpcodesAccount.sol/TestOpcodesAccount.json"
);
abigen!(
TestStorageAccount,
"$CARGO_MANIFEST_DIR/thirdparty/bundler/packages/bundler/artifacts/contracts/tests/TestStorageAccount.sol/TestStorageAccount.json"
);
abigen!(
TestRecursionAccount,
"$CARGO_MANIFEST_DIR/thirdparty/bundler/packages/bundler/artifacts/contracts/tests/TestRecursionAccount.sol/TestRecursionAccount.json"
);
abigen!(
TestStorageAccountFactory,
"$CARGO_MANIFEST_DIR/thirdparty/bundler/packages/bundler/artifacts/contracts/tests/TestStorageAccount.sol/TestStorageAccountFactory.json"
);
abigen!(
TestRulesAccount,
"$CARGO_MANIFEST_DIR/thirdparty/bundler/packages/bundler/artifacts/contracts/tests/TestRulesAccount.sol/TestRulesAccount.json"
);
abigen!(
TestRulesAccountFactory,
"$CARGO_MANIFEST_DIR/thirdparty/bundler/packages/bundler/artifacts/contracts/tests/TestRulesAccount.sol/TestRulesAccountFactory.json"
);
115 changes: 115 additions & 0 deletions tests/common/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
use std::sync::Arc;

use aa_bundler::types::user_operation::UserOperation;
use ethers::{
prelude::k256::ecdsa::SigningKey,
providers::Middleware,
signers::{Signer, Wallet},
types::{Address, Bytes, U256},
};

use self::gen::{
EntryPointContract, TestOpcodesAccount, TestOpcodesAccountFactory, TestRecursionAccount,
TestRulesAccountFactory, TestStorageAccount, TestStorageAccountFactory,
};
pub mod gen;

pub const ANVIL_TEST_KEY_PHRASE: &str =
"test test test test test test test test test test test junk";

pub struct DeployedContract<C> {
contract: C,
pub address: Address,
}
impl<C> DeployedContract<C> {
pub fn new(contract: C, address: Address) -> Self {
Self { contract, address }
}

pub fn contract(&self) -> &C {
&self.contract
}
}

pub async fn deploy_entry_point<M: Middleware + 'static>(
client: Arc<M>,
) -> anyhow::Result<DeployedContract<EntryPointContract<M>>> {
let (entry_point, receipt) = EntryPointContract::deploy(client, ())?
.send_with_receipt()
.await?;
let address = receipt.contract_address.unwrap();
Ok(DeployedContract::new(entry_point, address))
}

pub async fn deploy_test_opcode_account<M: Middleware + 'static>(
client: Arc<M>,
) -> anyhow::Result<DeployedContract<TestOpcodesAccount<M>>> {
let (account, receipt) = TestOpcodesAccount::deploy(client, ())?
.send_with_receipt()
.await?;
let address = receipt.contract_address.unwrap();
Ok(DeployedContract::new(account, address))
}

pub async fn deploy_test_opcode_account_factory<M: Middleware + 'static>(
client: Arc<M>,
) -> anyhow::Result<DeployedContract<TestOpcodesAccountFactory<M>>> {
let (factory, receipt) = TestOpcodesAccountFactory::deploy(client, ())?
.send_with_receipt()
.await?;
let address = receipt.contract_address.unwrap();
Ok(DeployedContract::new(factory, address))
}

pub async fn deploy_test_storage_account_factory<M: Middleware + 'static>(
client: Arc<M>,
) -> anyhow::Result<DeployedContract<TestStorageAccountFactory<M>>> {
let (factory, receipt) = TestStorageAccountFactory::deploy(client, ())?
.send_with_receipt()
.await?;
let address = receipt.contract_address.unwrap();
Ok(DeployedContract::new(factory, address))
}

pub async fn deploy_test_storage_account<M: Middleware + 'static>(
client: Arc<M>,
) -> anyhow::Result<DeployedContract<TestStorageAccount<M>>> {
let (account, receipt) = TestStorageAccount::deploy(client, ())?
.send_with_receipt()
.await?;
let address = receipt.contract_address.unwrap();
Ok(DeployedContract::new(account, address))
}

pub async fn deploy_test_recursion_account<M: Middleware + 'static>(
client: Arc<M>,
entry_point_address: Address,
) -> anyhow::Result<DeployedContract<TestRecursionAccount<M>>> {
let (account, receipt) = TestRecursionAccount::deploy(client, entry_point_address)?
.send_with_receipt()
.await?;
let address = receipt.contract_address.unwrap();
Ok(DeployedContract::new(account, address))
}

pub async fn deploy_test_rules_account_factory<M: Middleware + 'static>(
client: Arc<M>,
) -> anyhow::Result<DeployedContract<TestRulesAccountFactory<M>>> {
let (factory, receipt) = TestRulesAccountFactory::deploy(client, ())?
.send_with_receipt()
.await?;
let address = receipt.contract_address.unwrap();
Ok(DeployedContract::new(factory, address))
}

pub async fn sign(
user_op: &mut UserOperation,
entry_point_address: Address,
chain_id: U256,
key: Wallet<SigningKey>,
) -> anyhow::Result<()> {
let user_op_hash = user_op.hash(entry_point_address, chain_id);
let signature = key.sign_message(user_op_hash.as_bytes()).await?;
user_op.signature = Bytes::from(signature.to_vec());
Ok(())
}
Loading