Testing
This crate provides various helper functions for declaring, deploying,
and testing smart contracts using the snforge
toolchain from Starknet Foundry.
use openzeppelin_testing;
The module isn’t part of the openzeppelin
package and to be accessible has to
be added as a separate dependency in Scarb.toml
:
[dev-dependencies]
openzeppelin_testing = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.17.0" }
Test Utilities
common
A module providing common test helpers.
use openzeppelin_testing::common;
panic_data_to_byte_array(panic_data: Array<felt252>) → ByteArray
function
Converts panic data into a string (ByteArray
).
panic_data
is expected to be a valid serialized ByteArray
with an extra felt252
at the beginning, which is the BYTE_ARRAY_MAGIC.
to_base_16_string(value: felt252) → ByteArray
function
Converts a felt252
to a base16
string padded to 66 characters (including the 0x
prefix).
to_base_16_string_no_padding(value: felt252) → ByteArray
function
Converts a felt252
to a base16
(hexadecimal) string without padding, but including the 0x
prefix.
assert_entrypoint_not_found_error<T, +Drop<T>>(result: SyscallResult<T>, selector: felt252, contract_address: ContractAddress)
function
Asserts that the syscall result of a call failed with an "Entrypoint not found" error, following the Starknet Foundry emitted error format.
IntoBase16StringTrait
trait
A helper trait that enables a value to be represented as a base16
(hexadecimal) string padded to 66 characters
(including the 0x
prefix). The type of the value must implement Into<T, felt252>
to be
convertible to felt252
.
Usage example:
use openzeppelin_testing::common::IntoBase16String;
let expected_panic_message = format!(
"Entry point selector {} not found in contract {}",
selector.into_base_16_string(),
contract_address.into_base_16_string()
);
The no-padding version can be used in the same way by calling selector.into_base_16_string_no_padding() .
|
deployment
use openzeppelin_testing::deployment;
A module containing utilities that simplify declaring and deploying contracts using the snforge
toolchain.
declare_class(contract_name: ByteArray) → ContractClass
function
Declares a contract with a snforge_std::declare
call and unwraps the result. This function will skip declaration and just return the ContractClass
if the contract is already declared (the result of snforge_std::declare
call is of type DeclareResult::AlreadyDeclared
).
deploy(contract_class: ContractClass, calldata: Array<felt252>) → ContractAddress
function
Deploys an instance of a contract and unwraps the result.
deploy_at(contract_class: ContractClass, target_address: ContractAddress, calldata: Array<felt252>)
function
Deploys an instance of a contract at a given address.
deploy_another_at(existing: ContractAddress, target_address: ContractAddress, calldata: Array<felt252>)
function
Deploys a contract using the class hash from another already-deployed contract.
Note that currently, snforge
does not support redeclaring a contract class. Consequently,
there is no direct method to deploy a second instance of a contract if neither its ContractClass
nor its class_hash
is available in the context. This helper function provides a solution by retrieving
the class hash from an existing contract and using it to facilitate the deployment.
use openzeppelin_testing::deploy_another_at;
let alice_address = setup_account(array!['ALICE_PUBKEY']);
let bob_address = contract_address_const::<'BOB'>();
deploy_another_at(alice_address, bob_address, array!['BOB_PUBKEY']);
declare_and_deploy(contract_name: ByteArray, calldata: Array<felt252>) → ContractAddress
function
Combines the declaration of a class and the deployment of a contract into one function call. This function will skip declaration if the contract is already declared (the result of snforge_std::declare
call is of type DeclareResult::AlreadyDeclared
).
declare_and_deploy_at(contract_name: ByteArray, target_address: ContractAddress, calldata: Array<felt252>)
function
Combines the declaration of a class and the deployment of a contract at the given address into one function call. This function will skip declaration if the contract is already declared (the result of snforge_std::declare
call is of type DeclareResult::AlreadyDeclared
).
events
use openzeppelin_testing::events;
use openzeppelin_testing::events::EventSpyExt;
A module offering an extended set of functions for handling emitted events, enhancing the default
event utilities provided by snforge
. These functions are accessible via the EventSpyExt
trait implemented on the EventSpy
struct.
assert_only_event<T, +starknet::Event<T>, +Drop<T>>(ref self: EventSpy, from_address: ContractAddress, expected_event: T)
function
Ensures that from_address
has emitted only the expected_event
and no additional events.
assert_emitted_single<T, +starknet::Event<T>, +Drop<T>>(ref self: EventSpy, from_address: ContractAddress, expected_event: T)
function
Ensures that from_address
has emitted the expected_event
.
drop_event(ref self: EventSpy)
function
Removes a single event from the queue. If the queue is empty, the function will panic.
drop_n_events(ref self: EventSpy, number_to_drop: u32)
function
Removes number_to_drop
events from the queue. If the queue is empty, the function will panic.
drop_all_events(ref self: EventSpy)
function
Removes all events remaining on the queue. If the queue is empty already, the function will do nothing.
assert_no_events_left(ref self: EventSpy)
function
Ensures that there are no events remaining on the queue.
signing
use openzeppelin_testing::signing;
A module offering utility functions for easier management of key pairs and signatures.
get_stark_keys_from(private_key: felt252) → StarkKeyPair
function
Builds a Stark key pair from a private key represented by a felt252
value.
get_secp256k1_keys_from(private_key: u256) → Secp256k1KeyPair
function
Builds a Secp256k1 key pair from a private key represented by a u256
value.
SerializedSigning
trait
A helper trait that facilitates signing and converting the result signature into a serialized format.
Usage example:
use openzeppelin_testing::signing::{
StarkKeyPair, get_stark_keys_from, StarkSerializedSigning
};
let key_pair = get_stark_keys_from('SECRET_KEY');
let serialized_signature = key_pair.serialized_sign('TX_HASH');