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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ trait IOrchestrator<TContractState> {
fn pop_front(ref self: TContractState) -> felt252;
fn get_index(ref self: TContractState) -> felt252;
fn set_index(ref self: TContractState, index: felt252);
fn should_fail_invalid_scenario_panic_message(ref self: TContractState) -> felt252;
fn should_fail_undeployed_panic_message(ref self: TContractState) -> felt252;
fn should_fail_call_no_entrypoint_panic_message(ref self: TContractState) -> felt252;
fn should_fail_libcall_no_entrypoint_panic_message(ref self: TContractState) -> felt252;
Expand All @@ -20,25 +21,51 @@ mod FuzzRevertContract {
use starknet::info::SyscallResultTrait;

// Scenarios.
// The RETURN scenario *must* be zero, as the zero value also indicates end of scenario stream
// (when cairo0 fuzz contracts get the None value from the orchestrator).
// TODO(Dori): Convert to enum.
const SCENARIO_RETURN: felt252 = 0;
const SCENARIO_CALL: felt252 = 1;
const SCENARIO_LIBRARY_CALL: felt252 = 2;
const SCENARIO_WRITE: felt252 = 3;
const SCENARIO_REPLACE_CLASS: felt252 = 4;
const SCENARIO_DEPLOY: felt252 = 5;
const SCENARIO_PANIC: felt252 = 6;
const SCENARIO_INCREMENT_COUNTER: felt252 = 7;
const SCENARIO_SEND_MESSAGE: felt252 = 8;
const SCENARIO_DEPLOY_NON_EXISTING: felt252 = 9;
const SCENARIO_LIBRARY_CALL_NON_EXISTING: felt252 = 10;
const SCENARIO_SHA256: felt252 = 11;
const SCENARIO_KECCAK: felt252 = 12;
const SCENARIO_CALL_UNDEPLOYED: felt252 = 13;
const SCENARIO_CALL_NON_EXISTING_ENTRY_POINT: felt252 = 14;
const SCENARIO_LIBRARY_CALL_NON_EXISTING_ENTRY_POINT: felt252 = 15;
enum Scenario {
Return,
Call,
LibraryCall,
Write,
ReplaceClass,
Deploy,
Panic,
IncrementCounter,
SendMessage,
DeployNonExisting,
LibraryCallNonExisting,
Sha256,
Keccak,
CallUndeployed,
CallNonExistingEntryPoint,
LibraryCallNonExistingEntryPoint,
}

impl FeltTryIntoScenario of TryInto<felt252, Scenario> {
fn try_into(self: felt252) -> Option<Scenario> {
match self {
// The RETURN scenario *must* be zero, as the zero value also indicates end of
// scenario stream (when cairo0 fuzz contracts get the None value from the
// orchestrator).
0 => Some(Scenario::Return),
1 => Some(Scenario::Call),
2 => Some(Scenario::LibraryCall),
3 => Some(Scenario::Write),
4 => Some(Scenario::ReplaceClass),
5 => Some(Scenario::Deploy),
6 => Some(Scenario::Panic),
7 => Some(Scenario::IncrementCounter),
8 => Some(Scenario::SendMessage),
9 => Some(Scenario::DeployNonExisting),
10 => Some(Scenario::LibraryCallNonExisting),
11 => Some(Scenario::Sha256),
12 => Some(Scenario::Keccak),
13 => Some(Scenario::CallUndeployed),
14 => Some(Scenario::CallNonExistingEntryPoint),
15 => Some(Scenario::LibraryCallNonExistingEntryPoint),
_ => None,
}
}
}

#[storage]
struct Storage {
Expand Down Expand Up @@ -122,128 +149,116 @@ mod FuzzRevertContract {
let orchestrator = self.orchestrator();

// Get next scenario; None means done.
let scenario = orchestrator.pop_front();

if scenario == SCENARIO_RETURN {
return;
}

if scenario == SCENARIO_CALL {
let address: ContractAddress = orchestrator.pop_front().try_into().unwrap();
let selector = orchestrator.pop_front();
let should_unwrap: bool = orchestrator.pop_front() != 0;
let result = syscalls::call_contract_syscall(address, selector, array![].span());
self.handle_error_catch(result, should_unwrap);
}

if scenario == SCENARIO_LIBRARY_CALL {
let class_hash: ClassHash = orchestrator.pop_front().try_into().unwrap();
let selector = orchestrator.pop_front();
let should_unwrap: bool = orchestrator.pop_front() != 0;
let result = syscalls::library_call_syscall(class_hash, selector, array![].span());
self.handle_error_catch(result, should_unwrap);
}

if scenario == SCENARIO_WRITE {
let key: StorageAddress = orchestrator.pop_front().try_into().unwrap();
let value = orchestrator.pop_front();
let address_domain = 0;
syscalls::storage_write_syscall(address_domain, key, value).unwrap_syscall();
}

if scenario == SCENARIO_REPLACE_CLASS {
let class_hash: ClassHash = orchestrator.pop_front().try_into().unwrap();
syscalls::replace_class_syscall(class_hash).unwrap_syscall();
}

if scenario == SCENARIO_DEPLOY {
// The class hash is assumed to be a fuzz test class hash.
// Deploy it with a non-trivial orchestrator address.
let class_hash: ClassHash = orchestrator.pop_front().try_into().unwrap();
let salt = orchestrator.pop_front();
let deploy_from_zero: bool = true;
let ctor_calldata = array![self.orchestrator_address.read().into()];
// Deploy errors cannot be caught. Just unwrap the syscall.
syscalls::deploy_syscall(class_hash, salt, ctor_calldata.span(), deploy_from_zero)
.unwrap_syscall();
}

if scenario == SCENARIO_PANIC {
// Panic message is part of the scenario data.
let message = orchestrator.pop_front();
panic(array![orchestrator.get_index(), message]);
}

if scenario == SCENARIO_INCREMENT_COUNTER {
let value = self.counter.read();
self.counter.write(value + 1);
}

if scenario == SCENARIO_SEND_MESSAGE {
let payload = array![orchestrator.pop_front()];
syscalls::send_message_to_l1_syscall(0xadd1, payload.span()).unwrap_syscall();
}

if scenario == SCENARIO_DEPLOY_NON_EXISTING {
let class_hash: ClassHash = 0xde6107000c1.try_into().unwrap();
let salt = 0;
let deploy_from_zero: bool = true;
// Unrecoverable error (we do not prove class hashes do not exist), no option to catch
// error.
syscalls::deploy_syscall(class_hash, salt, array![].span(), deploy_from_zero)
.unwrap_syscall();
}

if scenario == SCENARIO_LIBRARY_CALL_NON_EXISTING {
let class_hash: ClassHash = 0x11bca11000c1.try_into().unwrap();
// Unrecoverable error (we do not prove class hashes do not exist), no option to catch
// error.
syscalls::library_call_syscall(class_hash, 0, array![].span()).unwrap_syscall();
}

if scenario == SCENARIO_SHA256 {
let preimage: u32 = orchestrator.pop_front().try_into().unwrap();
compute_sha256_u32_array(array![preimage], 0, 0);
}

if scenario == SCENARIO_KECCAK {
let preimage: u128 = orchestrator.pop_front().try_into().unwrap();
let mut input: Array::<u256> = Default::default();
input.append(u256 { low: preimage, high: preimage });
keccak::keccak_u256s_le_inputs(input.span());
}

if scenario == SCENARIO_CALL_UNDEPLOYED {
let address: ContractAddress = orchestrator.pop_front().try_into().unwrap();
let selector = orchestrator.pop_front();
let _should_unwrap = orchestrator.pop_front();
// Calling an undeployed contract should be an uncatchable fail.
syscalls::call_contract_syscall(address, selector, array![].span()).unwrap_err();
panic_with_felt252(orchestrator.should_fail_undeployed_panic_message());
}

if scenario == SCENARIO_CALL_NON_EXISTING_ENTRY_POINT {
let address: ContractAddress = orchestrator.pop_front().try_into().unwrap();
let selector = orchestrator.pop_front();
let should_unwrap: bool = orchestrator.pop_front() != 0;
self
.handle_syscall_immediate_failure(
syscalls::call_contract_syscall(address, selector, array![].span()),
orchestrator.should_fail_call_no_entrypoint_panic_message(),
should_unwrap
);
}
let scenario: Scenario = match orchestrator.pop_front().try_into() {
Some(scenario) => scenario,
None => panic_with_felt252(orchestrator.should_fail_invalid_scenario_panic_message()),
};

if scenario == SCENARIO_LIBRARY_CALL_NON_EXISTING_ENTRY_POINT {
let class_hash: ClassHash = orchestrator.pop_front().try_into().unwrap();
let selector = orchestrator.pop_front();
let should_unwrap: bool = orchestrator.pop_front() != 0;
self
.handle_syscall_immediate_failure(
syscalls::library_call_syscall(class_hash, selector, array![].span()),
orchestrator.should_fail_libcall_no_entrypoint_panic_message(),
should_unwrap
);
match scenario {
Scenario::Return => { return; },
Scenario::Call => {
let address: ContractAddress = orchestrator.pop_front().try_into().unwrap();
let selector = orchestrator.pop_front();
let should_unwrap: bool = orchestrator.pop_front() != 0;
let result = syscalls::call_contract_syscall(address, selector, array![].span());
self.handle_error_catch(result, should_unwrap);
},
Scenario::LibraryCall => {
let class_hash: ClassHash = orchestrator.pop_front().try_into().unwrap();
let selector = orchestrator.pop_front();
let should_unwrap: bool = orchestrator.pop_front() != 0;
let result = syscalls::library_call_syscall(class_hash, selector, array![].span());
self.handle_error_catch(result, should_unwrap);
},
Scenario::Write => {
let key: StorageAddress = orchestrator.pop_front().try_into().unwrap();
let value = orchestrator.pop_front();
let address_domain = 0;
syscalls::storage_write_syscall(address_domain, key, value).unwrap_syscall();
},
Scenario::ReplaceClass => {
let class_hash: ClassHash = orchestrator.pop_front().try_into().unwrap();
syscalls::replace_class_syscall(class_hash).unwrap_syscall();
},
Scenario::Deploy => {
// The class hash is assumed to be a fuzz test class hash.
// Deploy it with a non-trivial orchestrator address.
let class_hash: ClassHash = orchestrator.pop_front().try_into().unwrap();
let salt = orchestrator.pop_front();
let deploy_from_zero: bool = true;
let ctor_calldata = array![self.orchestrator_address.read().into()];
// Deploy errors cannot be caught. Just unwrap the syscall.
syscalls::deploy_syscall(class_hash, salt, ctor_calldata.span(), deploy_from_zero)
.unwrap_syscall();
},
Scenario::Panic => {
// Panic message is part of the scenario data.
let message = orchestrator.pop_front();
panic(array![orchestrator.get_index(), message]);
},
Scenario::IncrementCounter => {
let value = self.counter.read();
self.counter.write(value + 1);
},
Scenario::SendMessage => {
let payload = array![orchestrator.pop_front()];
syscalls::send_message_to_l1_syscall(0xadd1, payload.span()).unwrap_syscall();
},
Scenario::DeployNonExisting => {
let class_hash: ClassHash = 0xde6107000c1.try_into().unwrap();
let salt = 0;
let deploy_from_zero: bool = true;
// Unrecoverable error (we do not prove class hashes do not exist), no option to
// catch error.
syscalls::deploy_syscall(class_hash, salt, array![].span(), deploy_from_zero)
.unwrap_syscall();
},
Scenario::LibraryCallNonExisting => {
let class_hash: ClassHash = 0x11bca11000c1.try_into().unwrap();
// Unrecoverable error (we do not prove class hashes do not exist), no option to
// catch error.
syscalls::library_call_syscall(class_hash, 0, array![].span()).unwrap_syscall();
},
Scenario::Sha256 => {
let preimage: u32 = orchestrator.pop_front().try_into().unwrap();
compute_sha256_u32_array(array![preimage], 0, 0);
},
Scenario::Keccak => {
let preimage: u128 = orchestrator.pop_front().try_into().unwrap();
let mut input: Array::<u256> = Default::default();
input.append(u256 { low: preimage, high: preimage });
keccak::keccak_u256s_le_inputs(input.span());
},
Scenario::CallUndeployed => {
let address: ContractAddress = orchestrator.pop_front().try_into().unwrap();
let selector = orchestrator.pop_front();
let _should_unwrap = orchestrator.pop_front();
// Calling an undeployed contract should be an uncatchable fail.
syscalls::call_contract_syscall(address, selector, array![].span()).unwrap_err();
panic_with_felt252(orchestrator.should_fail_undeployed_panic_message());
},
Scenario::CallNonExistingEntryPoint => {
let address: ContractAddress = orchestrator.pop_front().try_into().unwrap();
let selector = orchestrator.pop_front();
let should_unwrap: bool = orchestrator.pop_front() != 0;
self
.handle_syscall_immediate_failure(
syscalls::call_contract_syscall(address, selector, array![].span()),
orchestrator.should_fail_call_no_entrypoint_panic_message(),
should_unwrap
);
},
Scenario::LibraryCallNonExistingEntryPoint => {
let class_hash: ClassHash = orchestrator.pop_front().try_into().unwrap();
let selector = orchestrator.pop_front();
let should_unwrap: bool = orchestrator.pop_front() != 0;
self
.handle_syscall_immediate_failure(
syscalls::library_call_syscall(class_hash, selector, array![].span()),
orchestrator.should_fail_libcall_no_entrypoint_panic_message(),
should_unwrap
);
},
}

// Unless explicitly stated otherwise, the next operation should be in the current call
Expand Down
Loading
Loading