Syscalls
At the protocol level, the Starknet Operating System (OS) is the program that manages the whole Starknet network.
Some of the OS functionalities are exposed to smart contracts through the use of syscalls (system calls). Syscalls can be used to get information about the state of the Starknet network, to interact with/deploy contracts, emit events, send messages, and perform other low-level operations.
Syscalls return a SyscallResult
which is either Success
of Failure
, allowing the contract to handle errors.
Here's the available syscalls:
- get_block_hash
- get_execution_info
- call_contract
- deploy
- emit_event
- library_call
- send_message_to_L1
- replace_class
- storage_read
- storage_write
get_block_hash
fn get_block_hash_syscall(block_number: u64) -> SyscallResult<felt252>
Get the hash of the block number block_number
.
Only within the range [first_v0_12_0_block, current_block - 10]
.
get_execution_info
fn get_execution_info_syscall() -> SyscallResult<Box<starknet::info::ExecutionInfo>>
Get information about the current execution context.
The returned ExecutionInfo
is defined as :
#[derive(Copy, Drop, Debug)]
pub struct ExecutionInfo {
pub block_info: Box<BlockInfo>,
pub tx_info: Box<TxInfo>,
pub caller_address: ContractAddress,
pub contract_address: ContractAddress,
pub entry_point_selector: felt252,
}
#[derive(Copy, Drop, Debug, Serde)]
pub struct BlockInfo {
pub block_number: u64,
pub block_timestamp: u64,
pub sequencer_address: ContractAddress,
}
#[derive(Copy, Drop, Debug, Serde)]
pub struct TxInfo {
// The version of the transaction. Always fixed (1)
pub version: felt252,
// The account contract from which this transaction originates.
pub account_contract_address: ContractAddress,
// The max_fee field of the transaction.
pub max_fee: u128,
// The signature of the transaction.
pub signature: Span<felt252>,
// The hash of the transaction.
pub transaction_hash: felt252,
// The identifier of the chain.
// This field can be used to prevent replay of testnet transactions on mainnet.
pub chain_id: felt252,
// The transaction's nonce.
pub nonce: felt252,
// A span of ResourceBounds structs.
pub resource_bounds: Span<ResourceBounds>,
// The tip.
pub tip: u128,
// If specified, the paymaster should pay for the execution of the tx.
// The data includes the address of the paymaster sponsoring the transaction, followed by
// extra data to send to the paymaster.
pub paymaster_data: Span<felt252>,
// The data availability mode for the nonce.
pub nonce_data_availability_mode: u32,
// The data availability mode for the account balance from which fee will be taken.
pub fee_data_availability_mode: u32,
// If nonempty, will contain the required data for deploying and initializing an account
// contract: its class hash, address salt and constructor calldata.
pub account_deployment_data: Span<felt252>,
}
starknet::info
provides helper functions to access the ExecutionInfo
fields in a more convenient way:
get_execution_info() -> Box<ExecutionInfo>
get_caller_address() -> ContractAddress
get_contract_address() -> ContractAddress
get_block_info() -> Box<BlockInfo>
get_tx_info() -> Box<TxInfo>
get_block_timestamp() -> u64
get_block_number() -> u64
call_contract
fn call_contract_syscall(
address: ContractAddress, entry_point_selector: felt252, calldata: Span<felt252>
) -> SyscallResult<Span<felt252>>
Call a contract at address
with the given entry_point_selector
and calldata
.
Failure can't be caught for this syscall, and if the call fails, the whole transaction will revert.
This is not the recommended way to call a contract. Instead, use the dispatcher generated from the contract interface as shown in the Calling other contracts chapter.
deploy
fn deploy_syscall(
class_hash: ClassHash,
contract_address_salt: felt252,
calldata: Span<felt252>,
deploy_from_zero: bool,
) -> SyscallResult<(ContractAddress, Span::<felt252>)>
Deploy a new contract of the predeclared class class_hash
with calldata
.
The success result is a tuple containing the deployed contract address and the return value of the constructor.
contract_address_salt
and deploy_from_zero
are used to compute the contract address.
Example of the usage of the deploy
syscall from the Factory pattern:
fn create_counter_at(ref self: ContractState, init_value: u128) -> ContractAddress {
// Constructor arguments
let mut constructor_calldata: Array::<felt252> = array![init_value.into()];
// Contract deployment
let (deployed_address, _) = deploy_syscall(
self.counter_class_hash.read(), 0, constructor_calldata.span(), false
)
.unwrap_syscall();
deployed_address
}
emit_event
fn emit_event_syscall(
keys: Span<felt252>, data: Span<felt252>
) -> SyscallResult<()>
Emit an event with the given keys
and data
.
Example of the usage of the emit_event
syscall from the Events chapter:
self.emit(Event::CounterIncreased(CounterIncreased { amount }));
self
.emit(
Event::UserIncreaseCounter(
UserIncreaseCounter {
user: get_caller_address(), new_value: self.counter.read()
}
)
);
library_call
fn library_call_syscall(
class_hash: ClassHash, function_selector: felt252, calldata: Span<felt252>
) -> SyscallResult<Span<felt252>>
Call the function function_selector
of the class class_hash
with calldata
.
This is analogous to a delegate call in Ethereum, but only a single class is called.
send_message_to_L1
fn send_message_to_l1_syscall(
to_address: felt252, payload: Span<felt252>
) -> SyscallResult<()>
Send a message to the L1 contract at to_address
with the given payload
.
replace_class
fn replace_class_syscall(
class_hash: ClassHash
) -> SyscallResult<()>
Replace the class of the calling contract with the class class_hash
.
This is used for contract upgrades. Here's an example from the Upgradeable Contract:
fn upgrade(ref self: ContractState, impl_hash: ClassHash) {
assert(impl_hash.is_non_zero(), 'Class hash cannot be zero');
starknet::syscalls::replace_class_syscall(impl_hash).unwrap_syscall();
self.emit(Event::Upgraded(Upgraded { implementation: impl_hash }))
}
The new class code will only be used for future calls to the contract.
The current transaction containing the replace_class
syscall will continue to use the old class code. Note that you can explicitly use the new class code in the same transaction by calling call_contract
after the replace_class
syscall.
storage_read
fn storage_read_syscall(
address_domain: u32, address: StorageAddress,
) -> SyscallResult<felt252>
This low-level syscall is used to get the value in the storage of a specific key at address
in the address_domain
.
address_domain
is used to distinguish between data availability modes.
Currently, only mode ONCHAIN
(0
) is supported.
storage_write
fn storage_write_syscall(
address_domain: u32, address: StorageAddress, value: felt252
) -> SyscallResult<()>
Similar to storage_read
, this low-level syscall is used to write the value value
in the storage of a specific key at address
in the address_domain
.
Documentation
Syscalls are defined in starknet::syscall
.
You can also read the official documentation page for more details.