Skip to content

Commit e575087

Browse files
committed
fix(rpc): account for nested multisig state reads
1 parent 62d65fe commit e575087

1 file changed

Lines changed: 43 additions & 4 deletions

File tree

crates/node/src/rpc/mod.rs

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ use tempo_primitives::{
7676
TEMPO_GAS_PRICE_SCALING_FACTOR, TempoHeader, TempoPrimitives, TempoReceipt, TempoTxEnvelope,
7777
subblock::PartialValidatorKey,
7878
};
79-
use tempo_revm::TempoTxEnv;
79+
use tempo_revm::{NATIVE_MULTISIG_NESTED_ACCOUNT_GAS, TempoTxEnv};
8080
use tokio::sync::{Mutex, broadcast};
8181

8282
/// Placeholder constant for `eth_getBalance` calls because the native token balance is N/A on
@@ -450,7 +450,9 @@ fn load_native_multisig_simulation_hint(
450450
NativeMultisig::account_threshold_storage_slot(account);
451451
let (owner_count_slot, owner_count_offset) =
452452
NativeMultisig::account_owners_len_storage_slot(account);
453+
let (version_slot, version_offset) = NativeMultisig::account_version_storage_slot(account);
453454
debug_assert_eq!(threshold_slot, owner_count_slot);
455+
debug_assert_eq!(threshold_slot, version_slot);
454456
let header = db
455457
.storage(NATIVE_MULTISIG_ADDRESS, threshold_slot)
456458
.map_err(Into::into)?;
@@ -459,10 +461,12 @@ fn load_native_multisig_simulation_hint(
459461
.map_err(|err| EthApiError::InvalidParams(err.to_string()))?;
460462
let owner_count = extract_from_word::<u8>(header, owner_count_offset.unwrap_or_default(), 1)
461463
.map_err(|err| EthApiError::InvalidParams(err.to_string()))? as usize;
462-
if threshold == 0 && owner_count == 0 {
464+
let version = extract_from_word::<u64>(header, version_offset.unwrap_or_default(), 8)
465+
.map_err(|err| EthApiError::InvalidParams(err.to_string()))?;
466+
if threshold == 0 && owner_count == 0 && version == 0 {
463467
return Ok(None);
464468
}
465-
if threshold == 0 || owner_count == 0 || owner_count > MAX_MULTISIG_OWNERS {
469+
if threshold == 0 || owner_count == 0 || version == 0 || owner_count > MAX_MULTISIG_OWNERS {
466470
return Err(EthApiError::InvalidParams(
467471
"native multisig config has an invalid header".to_string(),
468472
));
@@ -609,7 +613,8 @@ fn native_multisig_simulation_approval_gas(approval: &MultisigSimulationApproval
609613
SignatureType::WebAuthn => MAX_WEBAUTHN_GAS,
610614
},
611615
MultisigSimulationApproval::UnknownPrimitive => MAX_WEBAUTHN_GAS,
612-
MultisigSimulationApproval::Multisig(hint) => NODE_HEADER_GAS
616+
MultisigSimulationApproval::Multisig(hint) => NATIVE_MULTISIG_NESTED_ACCOUNT_GAS
617+
.saturating_add(NODE_HEADER_GAS)
613618
.saturating_add(CONFIG_OWNER_GAS.saturating_mul(hint.owner_count as u64))
614619
.saturating_add(
615620
hint.approvals
@@ -981,6 +986,10 @@ mod tests {
981986
NativeMultisig::account_owners_len_storage_slot(account),
982987
owners.len() as u8,
983988
);
989+
let (version_slot, version_offset) =
990+
NativeMultisig::account_version_storage_slot(account);
991+
*self.0.entry(version_slot).or_default() |=
992+
U256::from(1) << (version_offset.unwrap_or_default() * 8);
984993
for (index, &(owner, weight)) in owners.iter().enumerate() {
985994
self.insert_address(
986995
NativeMultisig::config_owner_address_storage_slot(account, index),
@@ -1254,6 +1263,36 @@ mod tests {
12541263
assert_eq!(nested.approvals.len(), 8);
12551264
}
12561265

1266+
#[test]
1267+
fn nested_simulation_approval_includes_account_access_gas() {
1268+
let approval = MultisigSimulationApproval::Multisig(Box::new(MultisigSimulationHint {
1269+
account: Address::from([0x22; 20]),
1270+
owner_count: 1,
1271+
approvals: vec![MultisigSimulationApproval::Primitive {
1272+
key_type: SignatureType::Secp256k1,
1273+
key_data: None,
1274+
}],
1275+
}));
1276+
1277+
assert_eq!(
1278+
native_multisig_simulation_approval_gas(&approval),
1279+
2_100 + NATIVE_MULTISIG_NESTED_ACCOUNT_GAS + 2_100 + 4_200 + 2_100 + 3_000
1280+
);
1281+
}
1282+
1283+
#[test]
1284+
fn simulation_hints_reject_zero_config_version() {
1285+
let account = Address::from([0xaa; 20]);
1286+
let mut db = SlotDb::default();
1287+
db.insert_u8(NativeMultisig::account_threshold_storage_slot(account), 1);
1288+
db.insert_u8(NativeMultisig::account_owners_len_storage_slot(account), 1);
1289+
1290+
assert!(matches!(
1291+
load_native_multisig_simulation_hints(account, None, &mut db),
1292+
Err(EthApiError::InvalidParams(reason)) if reason.contains("invalid header")
1293+
));
1294+
}
1295+
12571296
#[test]
12581297
fn simulation_hints_reject_nonzero_reserved_storage_bits() {
12591298
let account = Address::from([0xaa; 20]);

0 commit comments

Comments
 (0)