Skip to content

Commit 977dd0b

Browse files
authored
fix: system contract no class hash (#387)
1 parent 8f86123 commit 977dd0b

2 files changed

Lines changed: 54 additions & 6 deletions

File tree

crates/rpc/rpc-server/src/starknet/mod.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -369,9 +369,12 @@ where
369369
contract_address: ContractAddress,
370370
) -> StarknetApiResult<ClassHash> {
371371
self.on_io_blocking_task(move |this| {
372-
// Contract address 0x1 is special system contract and does not
373-
// have a class. See https://docs.starknet.io/architecture-and-concepts/network-architecture/starknet-state/#address_0x1.
374-
if contract_address.0 == Felt::ONE {
372+
// Contract address 0x1 and 0x2 are special system contracts and does not
373+
// have a class.
374+
//
375+
// See https://docs.starknet.io/architecture-and-concepts/network-architecture/starknet-state/#address_0x1.
376+
if contract_address == ContractAddress::ONE || contract_address == ContractAddress::TWO
377+
{
375378
return Ok(ClassHash::ZERO);
376379
}
377380

@@ -422,9 +425,12 @@ where
422425
let state = self.state(&block_id)?;
423426

424427
// Check that contract exist by checking the class hash of the contract,
425-
// unless its address 0x1 which is special system contract and does not
426-
// have a class. See https://docs.starknet.io/architecture-and-concepts/network-architecture/starknet-state/#address_0x1.
427-
if contract_address.0 != Felt::ONE
428+
// unless its address 0x1 or 0x2 which are special system contracts and does not
429+
// have a class.
430+
//
431+
// See https://docs.starknet.io/architecture-and-concepts/network-architecture/starknet-state/#address_0x1.
432+
if contract_address != ContractAddress::ONE
433+
&& contract_address != ContractAddress::TWO
428434
&& state.class_hash_of_contract(contract_address)?.is_none()
429435
{
430436
return Err(StarknetApiError::ContractNotFound);

crates/rpc/rpc-server/tests/starknet.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,3 +1340,45 @@ async fn simulate_should_skip_strict_nonce_check(#[case] nonce: Felt, #[case] sh
13401340
let res = contract.transfer(&recipient, &amount).nonce(nonce).simulate(false, false).await;
13411341
assert_eq!(res.is_ok(), should_ok)
13421342
}
1343+
1344+
/// Test that special system contract addresses (0x1 and 0x2) return ClassHash::ZERO
1345+
/// for `get_class_hash_at` calls, as they don't have an associated class.
1346+
///
1347+
/// See https://docs.starknet.io/architecture-and-concepts/network-architecture/starknet-state/#address_0x1
1348+
#[tokio::test]
1349+
async fn special_system_contract_class_hash() {
1350+
let sequencer = TestNode::new().await;
1351+
let provider = sequencer.starknet_rpc_client();
1352+
1353+
// Address 0x1 should return ClassHash::ZERO
1354+
let class_hash =
1355+
provider.get_class_hash_at(BlockIdOrTag::PreConfirmed, felt!("0x1").into()).await.unwrap();
1356+
assert_eq!(class_hash, Felt::ZERO, "Address 0x1 should return ClassHash::ZERO");
1357+
1358+
// Address 0x2 should return ClassHash::ZERO
1359+
let class_hash =
1360+
provider.get_class_hash_at(BlockIdOrTag::PreConfirmed, felt!("0x2").into()).await.unwrap();
1361+
assert_eq!(class_hash, Felt::ZERO, "Address 0x2 should return ClassHash::ZERO");
1362+
}
1363+
1364+
/// Test that `get_storage_at` works for special system contract addresses (0x1 and 0x2)
1365+
/// without returning ContractNotFound error.
1366+
///
1367+
/// See https://docs.starknet.io/architecture-and-concepts/network-architecture/starknet-state/#address_0x1
1368+
#[tokio::test]
1369+
async fn special_system_contract_storage() {
1370+
let sequencer = TestNode::new().await;
1371+
let provider = sequencer.starknet_rpc_client();
1372+
1373+
let storage_key = felt!("0x0");
1374+
1375+
// Address 0x1 should not return ContractNotFound
1376+
let result =
1377+
provider.get_storage_at(felt!("0x1").into(), storage_key, BlockIdOrTag::PreConfirmed).await;
1378+
assert!(result.is_ok(), "get_storage_at for address 0x1 should not fail");
1379+
1380+
// Address 0x2 should not return ContractNotFound
1381+
let result =
1382+
provider.get_storage_at(felt!("0x2").into(), storage_key, BlockIdOrTag::PreConfirmed).await;
1383+
assert!(result.is_ok(), "get_storage_at for address 0x2 should not fail");
1384+
}

0 commit comments

Comments
 (0)