Skip to content

Commit 54697dc

Browse files
authored
feat: account signer utilities (#218)
1 parent 5bfe2a1 commit 54697dc

File tree

11 files changed

+1043
-49
lines changed

11 files changed

+1043
-49
lines changed

packages/sdk-platforms/rust/zksync-sso-erc4337/crates/zksync-sso-erc4337-core/src/erc4337/account/modular_smart_account.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pub mod nonce;
44
pub mod send;
55
pub mod session;
66
pub mod signers;
7+
pub mod utils;
78

89
#[cfg(test)]
910
pub mod test_utilities;

packages/sdk-platforms/rust/zksync-sso-erc4337/crates/zksync-sso-erc4337-core/src/erc4337/account/modular_smart_account/session/active.rs

Lines changed: 31 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
use crate::{
22
config::contracts::Contracts,
3-
erc4337::account::modular_smart_account::session::{
4-
SessionKeyValidator, session_lib::session_spec::SessionSpec,
3+
erc4337::account::modular_smart_account::{
4+
session::{
5+
SessionKeyValidator, session_lib::session_spec::SessionSpec,
6+
},
7+
utils::{
8+
calculate_from_block, create_logs_filter_with_range,
9+
parse_add_remove_events,
10+
},
511
},
612
};
713
use alloy::{
814
primitives::{Address, FixedBytes},
915
providers::Provider,
10-
rpc::types::{BlockNumberOrTag, Filter, FilterSet, Log},
16+
rpc::types::{Filter, Log},
1117
sol_types::SolEvent,
1218
};
1319
use serde::{Deserialize, Serialize};
@@ -19,8 +25,6 @@ pub struct ActiveSession {
1925
pub session_spec: SessionSpec,
2026
}
2127

22-
const MAX_BLOCK_RANGE: u64 = 100_000;
23-
2428
pub async fn get_active_sessions<P>(
2529
account_address: Address,
2630
provider: P,
@@ -52,27 +56,11 @@ where
5256
Ok(active_sessions)
5357
}
5458

55-
fn calculate_from_block(current_block: u64) -> u64 {
56-
current_block.saturating_sub(MAX_BLOCK_RANGE)
57-
}
58-
5959
fn create_session_logs_filter_with_range(
6060
session_key_validator_address: Address,
6161
from_block: u64,
6262
) -> Filter {
63-
Filter {
64-
address: session_key_validator_address.into(),
65-
topics: [
66-
FilterSet::default(),
67-
FilterSet::default(),
68-
FilterSet::default(),
69-
FilterSet::default(),
70-
],
71-
block_option: alloy::rpc::types::FilterBlockOption::Range {
72-
from_block: Some(BlockNumberOrTag::Number(from_block)),
73-
to_block: None,
74-
},
75-
}
63+
create_logs_filter_with_range(session_key_validator_address, from_block)
7664
}
7765

7866
fn parse_session_events(
@@ -84,33 +72,27 @@ fn parse_session_events(
8472
let session_revoked_topic =
8573
SessionKeyValidator::SessionRevoked::SIGNATURE_HASH;
8674

87-
let mut created_sessions: Vec<(FixedBytes<32>, SessionSpec)> = Vec::new();
88-
let mut revoked_hashes: HashSet<FixedBytes<32>> = HashSet::new();
89-
90-
for log in logs {
91-
if let Some(topic0) = log.inner.topics().first() {
92-
if *topic0 == session_created_topic
93-
&& let Ok(decoded) =
94-
log.log_decode::<SessionKeyValidator::SessionCreated>()
95-
{
96-
let event = decoded.inner.data;
97-
if event.account == account_address {
98-
let session_spec: SessionSpec = event.sessionSpec.into();
99-
created_sessions.push((event.sessionHash, session_spec));
100-
}
101-
} else if *topic0 == session_revoked_topic
102-
&& let Ok(decoded) =
103-
log.log_decode::<SessionKeyValidator::SessionRevoked>()
104-
{
105-
let event = decoded.inner.data;
106-
if event.account == account_address {
107-
revoked_hashes.insert(event.sessionHash);
108-
}
75+
parse_add_remove_events(
76+
logs,
77+
account_address,
78+
session_created_topic,
79+
session_revoked_topic,
80+
|event: SessionKeyValidator::SessionCreated, account_address| {
81+
if event.account == account_address {
82+
let session_spec: SessionSpec = event.sessionSpec.into();
83+
Some((event.sessionHash, session_spec))
84+
} else {
85+
None
10986
}
110-
}
111-
}
112-
113-
(created_sessions, revoked_hashes)
87+
},
88+
|event: SessionKeyValidator::SessionRevoked, account_address| {
89+
if event.account == account_address {
90+
Some(event.sessionHash)
91+
} else {
92+
None
93+
}
94+
},
95+
)
11496
}
11597

11698
pub fn filter_active_sessions(
@@ -162,7 +144,7 @@ mod tests {
162144
};
163145
use alloy::{
164146
primitives::{FixedBytes, U256, Uint, address},
165-
rpc::types::FilterBlockOption,
147+
rpc::types::{BlockNumberOrTag, FilterBlockOption, FilterSet},
166148
};
167149
use std::{collections::HashSet, sync::Arc};
168150

packages/sdk-platforms/rust/zksync-sso-erc4337/crates/zksync-sso-erc4337-core/src/erc4337/account/modular_smart_account/signers/eoa.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
1+
pub mod active;
2+
pub mod add;
3+
pub mod remove;
4+
15
use crate::erc4337::account::modular_smart_account::signers::STUB_PRIVATE_KEY;
26
use alloy::{
37
primitives::{Address, Bytes, FixedBytes},
48
signers::{SignerSync, local::PrivateKeySigner},
9+
sol,
510
};
611
use std::str::FromStr;
712

13+
sol!(
14+
#[sol(rpc)]
15+
#[derive(Debug, Default)]
16+
#[allow(missing_docs)]
17+
EOAKeyValidator,
18+
"../../../../../../packages/erc4337-contracts/out/EOAKeyValidator.sol/EOAKeyValidator.json"
19+
);
20+
821
pub fn stub_signature_eoa(eoa_validator: Address) -> eyre::Result<Bytes> {
922
let hash = FixedBytes::default();
1023
let private_key_hex = STUB_PRIVATE_KEY;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
use crate::{
2+
config::contracts::Contracts,
3+
erc4337::account::modular_smart_account::{
4+
signers::eoa::EOAKeyValidator,
5+
utils::{
6+
calculate_from_block, create_logs_filter_with_range,
7+
parse_add_remove_events,
8+
},
9+
},
10+
};
11+
use alloy::{
12+
primitives::Address, providers::Provider, rpc::types::Log,
13+
sol_types::SolEvent,
14+
};
15+
use std::collections::HashSet;
16+
17+
pub async fn get_active_owners<P>(
18+
account_address: Address,
19+
provider: P,
20+
contracts: Contracts,
21+
) -> eyre::Result<Vec<Address>>
22+
where
23+
P: Provider + Send + Sync + Clone,
24+
{
25+
let eoa_validator_address = contracts.eoa_validator;
26+
27+
let from_block = {
28+
let current_block = provider.get_block_number().await?;
29+
calculate_from_block(current_block)
30+
};
31+
32+
let filter =
33+
create_logs_filter_with_range(eoa_validator_address, from_block);
34+
35+
let all_logs = provider.get_logs(&filter).await?;
36+
37+
let (added_signers, removed_signers) =
38+
parse_eoa_events(all_logs, account_address);
39+
40+
let active_signers = filter_active_signers(added_signers, removed_signers);
41+
42+
Ok(active_signers)
43+
}
44+
45+
fn parse_eoa_events(
46+
logs: Vec<Log>,
47+
account_address: Address,
48+
) -> (Vec<Address>, HashSet<Address>) {
49+
let owner_added_topic = EOAKeyValidator::OwnerAdded::SIGNATURE_HASH;
50+
let owner_removed_topic = EOAKeyValidator::OwnerRemoved::SIGNATURE_HASH;
51+
52+
parse_add_remove_events(
53+
logs,
54+
account_address,
55+
owner_added_topic,
56+
owner_removed_topic,
57+
|event: EOAKeyValidator::OwnerAdded, account_address| {
58+
if event.smartAccount == account_address {
59+
Some(event.owner)
60+
} else {
61+
None
62+
}
63+
},
64+
|event: EOAKeyValidator::OwnerRemoved, account_address| {
65+
if event.smartAccount == account_address {
66+
Some(event.owner)
67+
} else {
68+
None
69+
}
70+
},
71+
)
72+
}
73+
74+
fn filter_active_signers(
75+
added_signers: Vec<Address>,
76+
removed_signers: HashSet<Address>,
77+
) -> Vec<Address> {
78+
added_signers
79+
.into_iter()
80+
.filter(|signer| !removed_signers.contains(signer))
81+
.collect()
82+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
use crate::erc4337::{
2+
account::{
3+
erc7579::{Execution, calls::encode_calls},
4+
modular_smart_account::{
5+
send::{SendParams, send_transaction},
6+
signers::eoa::EOAKeyValidator,
7+
},
8+
},
9+
bundler::pimlico::client::BundlerClient,
10+
signer::Signer,
11+
};
12+
use alloy::{
13+
primitives::{Address, Bytes, U256},
14+
providers::Provider,
15+
sol_types::SolCall,
16+
};
17+
18+
pub async fn add_owner<P>(
19+
account_address: Address,
20+
new_owner: Address,
21+
entry_point_address: Address,
22+
eoa_validator_address: Address,
23+
bundler_client: BundlerClient,
24+
provider: P,
25+
signer: Signer,
26+
) -> eyre::Result<()>
27+
where
28+
P: Provider + Send + Sync + Clone,
29+
{
30+
let call_data = add_owner_call_data(new_owner, eoa_validator_address);
31+
32+
send_transaction(SendParams {
33+
account: account_address,
34+
entry_point: entry_point_address,
35+
factory_payload: None,
36+
call_data,
37+
nonce_key: None,
38+
paymaster: None,
39+
bundler_client,
40+
provider,
41+
signer,
42+
})
43+
.await?;
44+
45+
Ok(())
46+
}
47+
48+
fn add_owner_call_data(
49+
new_owner: Address,
50+
eoa_validator_address: Address,
51+
) -> Bytes {
52+
let add_owner_calldata =
53+
EOAKeyValidator::addOwnerCall { owner: new_owner }.abi_encode().into();
54+
55+
let call = {
56+
let target = eoa_validator_address;
57+
let value = U256::from(0);
58+
let data = add_owner_calldata;
59+
Execution { target, value, data }
60+
};
61+
62+
let calls = vec![call];
63+
encode_calls(calls).into()
64+
}

0 commit comments

Comments
 (0)