System Calls
Starknet smart contracts are written in Cairo. However, Cairo is a general purpose language that you can use for much more than just contract language. For details, see Cairo – a Turing-complete STARK-friendly CPU architecture.
So writing smart contracts requires some operations, such as calling another contract or accessing the contract’s storage, that standalone programs do not require.
The Starknet contract language supports these operations by using system calls. System calls enable a contract to require services from the Starknet OS. You can use system calls in a function to get information that depends on the broader state of Starknet, which would otherwise be inaccessible, rather than local variables that appear in the function’s scope.
getters
In Cairo 1.0, all block/transaction/execution context getters are batched into a single system call: get_execution_info
.
get_execution_info
extern fn get_execution_info_syscall() -> SyscallResult<Box<starknet::info::ExecutionInfo>> implicits(
GasBuiltin, System
) nopanic;
Gets information about the original transaction.
None.
ExecutionInfo
|
A struct containing the execution info |
call_contract
Calls a given contract. This system call expects the address of the called contract, a selector for a function within that contract, and call arguments.
extern fn call_contract_syscall(
address: ContractAddress, entry_point_selector: felt252, calldata: Span<felt252>
) -> SyscallResult<Span<felt252>> implicits(GasBuiltin, System) nopanic;
address
|
The address of the contract you want to call. |
entry_point_selector
|
A selector for a function within that contract. |
calldata
|
The calldata array |
-
the call response, of type
SyscallResult<Span<felt252>>
This is considered a lower level syntax for calling contracts. If the interface of the called contract is available, then you can use a more straightforward syntax. |
deploy
extern fn deploy_syscall(
class_hash: ClassHash,
contract_address_salt: felt252,
calldata: Span<felt252>,
deploy_from_zero: bool,
) -> SyscallResult<(ContractAddress, Span::<felt252>)> implicits(GasBuiltin, System) nopanic;
Deploys a new instance of a previously declared class.
class_hash
|
The class hash of the contract to be deployed |
contract_address_salt
|
The salt, an arbitrary value provided by the sender, used in the computation of the contract’s address. |
calldata
|
The constructor’s calldata. An array of felts. |
deploy_from_zero
|
A flag used for the contract address computation. If not set, the caller address will be used as the new contract’s deployer address, otherwise 0 is used. |
-
A tuple wrapped with
SyscallResult
where:-
The first element is the address of the deployed contract (of type
ContractAddress
) -
The second element is the response array from the contract’s constructor (of type
Span::<felt252>
)
-
emit_event
extern fn emit_event_syscall(
keys: Span<felt252>, data: Span<felt252>
) -> SyscallResult<()> implicits(GasBuiltin, System) nopanic;
Emits an event with a given set of keys and data.
For more information, and for a higher level syntax for emitting events, see Starknet events.
keys
|
The event’s keys. These are analogous to Ethereum’s event topics, you can use the starknet_getEvents method to filter by these keys. |
data
|
The event’s data |
None.
The following example emits an event with two keys, the strings status
and deposit
and three data elements: 1
, 2
, and 3
.
let keys = ArrayTrait::new();
keys.append('key');
keys.append('deposit');
let values = ArrayTrait::new();
values.append(1);
values.append(2);
values.append(3);
emit_event_syscall(keys, values).unwrap_syscall();
library_call
extern fn library_call_syscall(
class_hash: ClassHash, function_selector: felt252, calldata: Span<felt252>
) -> SyscallResult<Span<felt252>> implicits(GasBuiltin, System) nopanic;
Calls the requested function in any previously declared class.
This system call replaces the known delegate call functionality from Ethereum, with the important difference that there is only one contract involved.
The class is only used for its logic.
class_hash
|
The hash of the class you want to use. |
function_selector
|
A selector for a function within that class. |
calldata
|
The calldata. |
-
The call response, of type
SyscallResult<Span<felt252>>
.
send_message_to_L1
extern fn send_message_to_l1_syscall(
to_address: felt252, payload: Span<felt252>
) -> SyscallResult<()> implicits(GasBuiltin, System) nopanic;
Sends a message to L1.
This system call includes the message parameters as part of the proof’s output, and exposes these parameters to the Starknet Core contract on L1 once the state update, including the transaction, is received.
For more information, see Starknet’s messaging mechanism.
to_address
|
The recipient’s L1 address. |
payload
|
The array containing the message payload |
None.
The following example sends a message whose content is (1,2)
to the L1 contract whose address is 3423542542364363
.
let payload = ArrayTrait::new();
payload.append(1);
payload.append(2);
send_message_to_l1_syscall(payload).unwrap_syscall();
replace_class
extern fn replace_class_syscall(
class_hash: ClassHash
) -> SyscallResult<()> implicits(GasBuiltin, System) nopanic;
Once replace_class
is called, the class of the calling contract (i.e. the contract whose
address is returned by get_contract_address
at the time the syscall is called) will be replaced
by the class whose hash is given by the class_hash argument .
After calling The new class will be used from the next transaction onwards or if the contract is called via the call_contract syscall in the same transaction (after the replacement). |
class_hash
|
The hash of the class you want to use as a replacement. |
None
storage_read
extern fn storage_read_syscall(
address_domain: u32, address: StorageAddress,
) -> SyscallResult<felt252> implicits(GasBuiltin, System) nopanic;
Gets the value of a key in the storage of the calling contract.
This system call provides direct access to any possible key in storage, in contrast with balance.read()
, which enables you to read storage variables that are defined explicitly in the contract.
For information on accessing storage by using the storage variables, see storage variables.
address_domain
|
The domain of the key, used to separate between different DA modes. Currently only |
address
|
The requested storage address |
Address domains One can think about the state of Starknet as a collection of address→value mappings.
Each mapping is independent of the rest, and is considered a different address domain.
This separation is used in Starknet to offer different data availability modes.
In the on-chain mode (indicated by domain |
-
The value of the key, of type
SyscallResult<felt252>
use starknet::storage_access::storage_base_address_from_felt252;
...
let storage_address = storage_base_address_from_felt252(3534535754756246375475423547453)
storage_read_syscall(0, storage_address).unwrap_syscall()
storage_write
Sets the value of a key in the storage of the calling contract.
extern fn storage_write_syscall(
address_domain: u32, address: StorageAddress, value: felt252
) -> SyscallResult<()> implicits(GasBuiltin, System) nopanic;
Sets the value of a key in the storage of the calling contract.
This system call provides direct access to any possible key in storage, in contrast with balance.write()
, which enables you to write to storage variables that are defined explicitly in the contract.
For information on accessing storage by using the storage variables, see storage variables.
address_domain
|
The domain of the key, used to separate between different DA modes. Currently only |
.value
|
The value to write to the key. |
None.