Skip to content

Commit

Permalink
feat: 7702 safe (#18)
Browse files Browse the repository at this point in the history
* feat: 7702 safe

* chore: rebase

* chore: more effort

* chore: fix submodule URL

* fix: remove platform

* feat: test Safe on Sepolia & Pimlico (#20)

* feat: test Safe against Sepolia and Sepolia

* chore: comment

* chore: prefer assert

* chore: add missing deps

* chore: Safe Swift refactor (#21)
  • Loading branch information
chris13524 committed Sep 12, 2024
1 parent 08362a7 commit dfe0f88
Show file tree
Hide file tree
Showing 22 changed files with 867 additions and 381 deletions.
3 changes: 2 additions & 1 deletion .env.template
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ BUNDLER_API_KEY=""
BUNDLER_BASE_URL=""
RPC_API_KEY=""
RPC_BASE_URL=""
FAUCET_MNEMONIC=""
PIMLICO_API_KEY=""
PIMLICO_BUNDLER_URL=""
PIMLICO_RPC_URL=""
PIMLICO_RPC_URL=""
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ jobs:
- run: while ! curl localhost:8545/health; do sleep 1; done
- run: while ! curl localhost:4337/health; do sleep 1; done
- run: while ! curl localhost:3000/ping; do sleep 1; done
- run: cargo build --workspace --all-features --all-targets
- run: cargo test --all-features --lib --bins
# - run: cargo clippy --workspace --all-features --all-targets -- -D warnings
- run: cargo build --workspace --features=full --all-targets
- run: cargo test --features=full --lib --bins
# - run: cargo clippy --workspace --features=full --all-targets -- -D warnings
- run: cargo +nightly fmt --all -- --check

udeps:
Expand Down Expand Up @@ -65,7 +65,7 @@ jobs:
# - run: rustup target add wasm32-unknown-unknown
# - run: git submodule update --init --recursive
# - run: make setup-thirdparty
# - run: cargo build --workspace --all-features --lib --bins --target wasm32-unknown-unknown --exclude=ffi
# - run: cargo build --workspace --features=full --lib --bins --target wasm32-unknown-unknown --exclude=ffi

build_swift_and_test:
name: Swift Package - latest
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@
[submodule "crates/yttrium/safe7579"]
path = crates/yttrium/safe7579
url = https://github.com/rhinestonewtf/safe7579
[submodule "test/scripts/forked_state/mock-aa-environment"]
path = test/scripts/forked_state/mock-aa-environment
url = https://github.com/WalletConnect/mock-aa-environment.git
38 changes: 37 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ To contribute to this project, ensure you have the following dependencies instal
- `rustc`
- `swiftc` and Xcode
- `foundry`
- `make`
- `just`
- `npm`
- `pnpm`
- `yarn`

### Setup

Expand All @@ -87,4 +92,35 @@ After installing the dependencies, clone the repository and run the following co
make setup
```

This will fetch the third party dependencies and build the project, including the Swift bindings.
This will fetch the third party dependencies and build the project, including the Swift bindings.

### Devloop

During normal development you can use the `just devloop` command to test your code both during development and before comitting/pushing. This is handy as it runs as many checks as possible and fixes any issues (such as formatting) automatically.

This command does not require any configuration.

```bash
just devloop
```

TODO: make this setup anvil automatically

### Specific tests

Some tests require some configuration (such as funds on Sepolia). For these, supply `FAUCET_MNEMONIC` and add some funds on the account.

#### Pimlico/Sepolia

```bash
just test-pimlico-api
```

Required environment variables:

```text
FAUCET_MNEMONIC
PIMLICO_API_KEY
PIMLICO_BUNDLER_URL
PIMLICO_RPC_URL
```
1 change: 1 addition & 0 deletions crates/ffi/src/account_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ impl FFIAccountClient {
config.chain_id.clone(),
config.config.into(),
service,
config.safe,
);
account_client
}
Expand Down
1 change: 1 addition & 0 deletions crates/ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ mod ffi {
pub chain_id: u64,
pub config: FFIConfig,
pub signer_type: String,
pub safe: bool,
}

enum FFIStringResult {
Expand Down
4 changes: 4 additions & 0 deletions crates/yttrium/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ version.workspace = true
edition.workspace = true
rust-version.workspace = true

[features]
full = []
test_pimlico_api = []

[dependencies]
# Ethereum
alloy = { git = "https://github.com/alloy-rs/alloy", version = "0.3.2", features = [
Expand Down
2 changes: 1 addition & 1 deletion crates/yttrium/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use {
};

fn main() {
build_contracts();
// build_contracts();
}

const CONTRACTS_DIR: &str = "crates/yttrium/safe-smart-account/contracts";
Expand Down
21 changes: 19 additions & 2 deletions crates/yttrium/src/account_client.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::config::Config;
use crate::private_key_service::PrivateKeyService;
use crate::sign_service::SignService;
use crate::transaction::send::safe_test;
use crate::transaction::{send::send_transaction, Transaction};
use alloy::primitives::Address;
use alloy::signers::local::PrivateKeySigner;
Expand Down Expand Up @@ -47,6 +48,7 @@ pub struct AccountClient {
chain_id: u64,
config: Config,
signer: Signer,
safe: bool,
}

impl AccountClient {
Expand All @@ -61,6 +63,7 @@ impl AccountClient {
chain_id,
config: config.clone(),
signer: Signer::Native(Arc::new(Mutex::new(sign_service))),
safe: false,
}
}

Expand All @@ -69,6 +72,7 @@ impl AccountClient {
chain_id: u64,
config: Config,
private_key_service: PrivateKeyService,
safe: bool,
) -> Self {
Self {
owner,
Expand All @@ -77,6 +81,7 @@ impl AccountClient {
signer: Signer::PrivateKey(Arc::new(Mutex::new(
private_key_service,
))),
safe,
}
}

Expand All @@ -98,6 +103,7 @@ impl AccountClient {
signer: Signer::PrivateKey(Arc::new(Mutex::new(
private_key_service,
))),
safe: false,
}
}

Expand All @@ -111,6 +117,7 @@ impl AccountClient {
self.chain_id.clone(),
self.config.clone(),
self.signer.clone(),
self.safe,
)
.await
}
Expand All @@ -136,6 +143,7 @@ impl AccountClient {
self.chain_id.clone(),
self.config.clone(),
self.signer.clone(),
self.safe,
)
.await
}
Expand All @@ -162,6 +170,7 @@ impl AccountClient {
chain_id: 0,
config: Config::local(),
signer: Signer::Native(Arc::new(Mutex::new(SignService::mock()))),
safe: false,
}
}
}
Expand All @@ -171,6 +180,7 @@ pub async fn get_address_with_signer(
chain_id: u64,
config: Config,
signer: Signer,
safe: bool,
) -> eyre::Result<String> {
match signer {
Signer::PrivateKey(private_key_service) => {
Expand All @@ -185,6 +195,7 @@ pub async fn get_address_with_signer(
chain_id,
config,
private_key_signer,
safe,
)
.await
}
Expand All @@ -199,11 +210,15 @@ pub async fn get_address_with_private_key_signer(
chain_id: u64,
config: Config,
signer: PrivateKeySigner,
safe: bool,
) -> eyre::Result<String> {
use crate::smart_accounts::simple_account::sender_address::get_sender_address_with_signer;

let sender_address =
get_sender_address_with_signer(config, chain_id, signer).await?;
let sender_address = if safe {
safe_test::get_address(signer, config).await?
} else {
get_sender_address_with_signer(config, chain_id, signer).await?
};

Ok(sender_address.to_string())
}
Expand Down Expand Up @@ -239,6 +254,7 @@ mod tests {
chain_id,
config,
private_key_service,
false,
);

let transaction = Transaction::new_from_strings(
Expand Down Expand Up @@ -278,6 +294,7 @@ mod tests {
chain_id,
config,
private_key_service,
false,
);

let sender_address = account_client.get_address().await?;
Expand Down
1 change: 1 addition & 0 deletions crates/yttrium/src/bundler/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ mod tests {
max_priority_fee_per_gas: max_priority_fee_per_gas.into(),
paymaster: paymaster,
paymaster_data: paymaster_data,
// authorization_list: None,
signature: signature,
}
};
Expand Down
5 changes: 4 additions & 1 deletion crates/yttrium/src/bundler/pimlico/paymaster/models.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::user_operation::UserOperationV07;
use crate::user_operation::{Authorization, UserOperationV07};
use alloy::primitives::{Address, Bytes, U256};
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -31,6 +31,8 @@ pub struct UserOperationPreSponsorshipV07 {
pub paymaster_verification_gas_limit: Option<U256>,
pub paymaster_post_op_gas_limit: Option<U256>,
pub paymaster_data: Option<Bytes>,
// #[serde(skip_serializing_if = "Option::is_none")]
// pub authorization_list: Option<Vec<Authorization>>,
pub signature: Bytes,
}

Expand All @@ -52,6 +54,7 @@ impl From<UserOperationV07> for UserOperationPreSponsorshipV07 {
.paymaster_verification_gas_limit,
paymaster_post_op_gas_limit: user_op.paymaster_post_op_gas_limit,
paymaster_data: user_op.paymaster_data,
// authorization_list: user_op.authorization_list,
signature: user_op.signature,
}
}
Expand Down
25 changes: 22 additions & 3 deletions crates/yttrium/src/transaction/send.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::smart_accounts::safe::Execution;
use crate::transaction::send::simple_account_test::send_transaction_with_signer;
use crate::{
config::Config, transaction::Transaction, user_operation::UserOperationV07,
};
use alloy::signers::local::PrivateKeySigner;
use core::fmt;

mod safe_test;
pub mod safe_test;
pub mod send_tests;
pub mod simple_account_test;

Expand Down Expand Up @@ -50,6 +51,7 @@ pub async fn send_transaction(
chain_id: u64,
config: Config,
signer: Signer,
safe: bool,
) -> eyre::Result<String> {
match signer {
Signer::PrivateKey(private_key_service) => {
Expand All @@ -65,6 +67,7 @@ pub async fn send_transaction(
chain_id,
config,
private_key_signer,
safe,
)
.await
}
Expand All @@ -80,12 +83,27 @@ pub async fn send_transaction_with_private_key_signer(
chain_id: u64,
config: Config,
private_key_signer: PrivateKeySigner,
safe: bool,
) -> eyre::Result<String> {
let signer = private_key_signer;

let user_operation_hash =
let user_operation_hash = if safe {
safe_test::send_transaction(
vec![Execution {
target: transaction.to,
value: transaction.value,
callData: transaction.data,
}],
signer,
None,
None,
config,
)
.await?
} else {
send_transaction_with_signer(transaction, config, chain_id, signer)
.await?;
.await?
};

println!("user_operation_hash: {:?}", user_operation_hash);

Expand Down Expand Up @@ -271,6 +289,7 @@ mod tests {
paymaster_verification_gas_limit: None,
paymaster_post_op_gas_limit: None,
paymaster_data: None,
// authorization_list: None,
signature: Bytes::from_str(
crate::smart_accounts::simple_account::DUMMY_SIGNATURE_HEX
.strip_prefix("0x")
Expand Down
Loading

0 comments on commit dfe0f88

Please sign in to comment.