Skip to content
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: 2 additions & 2 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -792,5 +792,5 @@ seismic-alloy-provider = { git = "https://github.com/SeismicSystems/seismic-allo
seismic-alloy-genesis = { git = "https://github.com/SeismicSystems/seismic-alloy.git", rev = "c1ce53389ad2bf9bd04c15f4924abe77677395b6" }

# evm
alloy-evm = { git = "https://github.com/SeismicSystems/seismic-evm.git", rev = "c33f3076495d153eefbde07dd81c3a575f3d19b8" }
alloy-seismic-evm = { git = "https://github.com/SeismicSystems/seismic-evm.git", rev = "c33f3076495d153eefbde07dd81c3a575f3d19b8" }
alloy-evm = { git = "https://github.com/SeismicSystems/seismic-evm.git", rev = "0a751067fa55afc762e64c919c4443eea72546ca" }
alloy-seismic-evm = { git = "https://github.com/SeismicSystems/seismic-evm.git", rev = "0a751067fa55afc762e64c919c4443eea72546ca" }
7 changes: 7 additions & 0 deletions crates/rpc/rpc-eth-types/src/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ pub enum EthApiError {
/// Code overrides are not permitted (Seismic privacy)
#[error("code overrides are not permitted on Seismic (account: {0:?})")]
CodeOverrideNotPermitted(Address),
/// Storage overrides are not permitted (Seismic privacy)
#[error("storage overrides are not permitted on Seismic (account: {0:?})")]
StorageOverrideNotPermitted(Address),
/// Other internal error
#[error(transparent)]
Internal(RethError),
Expand Down Expand Up @@ -258,6 +261,7 @@ impl From<EthApiError> for jsonrpsee_types::error::ErrorObject<'static> {
EthApiError::Signing(_) |
EthApiError::BothStateAndStateDiffInOverride(_) |
EthApiError::CodeOverrideNotPermitted(_) |
EthApiError::StorageOverrideNotPermitted(_) |
EthApiError::InvalidTracerConfig |
EthApiError::TransactionConversionError |
EthApiError::InvalidRewardPercentiles |
Expand Down Expand Up @@ -356,6 +360,9 @@ where
StateOverrideError::CodeOverrideNotPermitted(address) => {
Self::CodeOverrideNotPermitted(address)
}
StateOverrideError::StorageOverrideNotPermitted(address) => {
Self::StorageOverrideNotPermitted(address)
}
StateOverrideError::Database(err) => err.into(),
}
}
Expand Down
146 changes: 146 additions & 0 deletions crates/seismic/node/tests/e2e/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1390,3 +1390,149 @@ async fn test_usdc_only_susdc_transfer_e2e() -> eyre::Result<()> {
assert!(receipt.status());
Ok(())
}

#[tokio::test(flavor = "multi_thread")]
async fn test_eth_call_rejects_storage_override() -> eyre::Result<()> {
let (_node, client, chain_id, wallet, _tasks) = setup_test_node().await?;

let victim_addr = Address::from_hex("0x0000000000000000000000000000000000001234").unwrap();

let storage: alloy_primitives::map::B256HashMap<B256> =
[(B256::ZERO, B256::from(U256::from(1)))].into_iter().collect();

let mut state_overrides = StateOverride::default();
state_overrides
.insert(victim_addr, AccountOverride { state_diff: Some(storage), ..Default::default() });

let result = EthApiOverrideClient::<Block>::call(
&client,
SeismicTransactionRequest {
inner: TransactionRequest {
from: Some(wallet.inner.address()),
to: Some(TxKind::Call(victim_addr)),
gas: Some(1_000_000),
chain_id: Some(chain_id),
..Default::default()
},
seismic_elements: None,
}
.into(),
None,
Some(state_overrides),
None,
)
.await;

match &result {
Ok(output) => panic!(
"eth_call with storage override should be rejected, but got Ok: 0x{}",
hex::encode(output)
),
Err(e) => {
let err_msg = e.to_string();
assert!(
err_msg.to_lowercase().contains("storage overrides are not permitted"),
"Expected storage override rejection error, got: {}",
err_msg
);
}
}
Ok(())
}

#[tokio::test(flavor = "multi_thread")]
async fn test_eth_estimate_gas_rejects_storage_override() -> eyre::Result<()> {
let (_node, client, chain_id, wallet, _tasks) = setup_test_node().await?;

let victim_addr = Address::from_hex("0x0000000000000000000000000000000000001234").unwrap();

let storage: alloy_primitives::map::B256HashMap<B256> =
[(B256::ZERO, B256::from(U256::from(1)))].into_iter().collect();

let mut state_overrides = StateOverride::default();
state_overrides
.insert(victim_addr, AccountOverride { state_diff: Some(storage), ..Default::default() });

let result = EthApiOverrideClient::<Block>::estimate_gas(
&client,
SeismicCallRequest::TransactionRequest(SeismicTransactionRequest {
inner: TransactionRequest {
from: Some(wallet.inner.address()),
to: Some(TxKind::Call(victim_addr)),
gas: Some(1_000_000),
chain_id: Some(chain_id),
..Default::default()
},
seismic_elements: None,
}),
None,
Some(state_overrides),
)
.await;

match &result {
Ok(gas) => {
panic!("eth_estimateGas with storage override should be rejected, but got Ok: {}", gas)
}
Err(e) => {
let err_msg = e.to_string();
assert!(
err_msg.to_lowercase().contains("storage overrides are not permitted"),
"Expected storage override rejection error, got: {}",
err_msg
);
}
}
Ok(())
}

#[tokio::test(flavor = "multi_thread")]
async fn test_eth_simulate_v1_rejects_storage_override() -> eyre::Result<()> {
let (_node, client, chain_id, wallet, _tasks) = setup_test_node().await?;

let victim_addr = Address::from_hex("0x0000000000000000000000000000000000001234").unwrap();

let storage: alloy_primitives::map::B256HashMap<B256> =
[(B256::ZERO, B256::from(U256::from(1)))].into_iter().collect();

let mut state_overrides = StateOverride::default();
state_overrides
.insert(victim_addr, AccountOverride { state_diff: Some(storage), ..Default::default() });

let nonce = get_nonce(&client, wallet.inner.address()).await;
let tx_bytes = get_signed_deploy_tx_bytes(
wallet.inner.clone(),
nonce,
chain_id,
ContractTestContext::get_deploy_input_plaintext(),
)
.await;

let block_with_storage_override = SimBlock {
block_overrides: None,
state_overrides: Some(state_overrides),
calls: vec![SeismicCallRequest::Bytes(tx_bytes)],
};

let simulate_payload = SimulatePayload::<SeismicCallRequest> {
block_state_calls: vec![block_with_storage_override],
trace_transfers: false,
validation: false,
return_full_transactions: false,
};

let result = EthApiOverrideClient::<Block>::simulate_v1(&client, simulate_payload, None).await;

match &result {
Ok(_) => panic!("eth_simulateV1 with storage override should be rejected"),
Err(e) => {
let err_msg = e.to_string();
assert!(
err_msg.to_lowercase().contains("storage overrides are not permitted"),
"Expected storage override rejection error, got: {}",
err_msg
);
}
}
Ok(())
}
Loading