Skip to content

Commit

Permalink
add more tests and check arcade account impl validity
Browse files Browse the repository at this point in the history
  • Loading branch information
0xChqrles authored and fracek committed Dec 6, 2023
1 parent 467639d commit 4f5ecdc
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 1 deletion.
2 changes: 2 additions & 0 deletions demos/arcade-factory/src/account/interface.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const ARCADE_ACCOUNT_ID: felt252 = 22227699753170493970302265346292000442692;

#[starknet::interface]
trait ArcadeAccountABI<TState> {
fn set_master_account(ref self: TState, master_account: starknet::ContractAddress);
Expand Down
18 changes: 17 additions & 1 deletion demos/arcade-factory/src/factory/factory.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@ mod FactoryComponent {
// locals
use arcade_factory::factory::interface;

use arcade_factory::account::interface::{ ArcadeAccountABIDispatcher, ArcadeAccountABIDispatcherTrait };
use arcade_factory::account::interface::{
ARCADE_ACCOUNT_ID,
ArcadeAccountABIDispatcher,
ArcadeAccountABIDispatcherTrait,
};

const CONTRACT_ADDRESS_PREFIX: felt252 = 'STARKNET_CONTRACT_ADDRESS';

const SUPPORTS_INTERFACE_SELECTOR: felt252 = 0xfe80f537b66d12a00b6d3c072b44afbb716e78dde5c3f0ef116ee93d3e3283;

//
// Storage
//
Expand Down Expand Up @@ -105,6 +111,16 @@ mod FactoryComponent {
ref self: ComponentState<TContractState>,
arcade_account_implementation: starknet::ClassHash
) {
// check that the new implementation is a valid arcade account
let ret_data = starknet::library_call_syscall(
class_hash: arcade_account_implementation,
function_selector: SUPPORTS_INTERFACE_SELECTOR,
calldata: array![ARCADE_ACCOUNT_ID].span()
).unwrap_syscall();

assert((ret_data.len() == 1) & (*ret_data.at(0) == true.into()), 'Invalid arcade account impl');

// update implementation
self._arcade_account_implementation.write(arcade_account_implementation);
}
}
Expand Down
51 changes: 51 additions & 0 deletions demos/arcade-factory/src/tests/mocks/arcade_account_mock.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ mod ArcadeAccountMock {
// locals
use super::ArcadeAccountMockABI;

use arcade_factory::account::interface;

//
// Storage
//
Expand Down Expand Up @@ -49,4 +51,53 @@ mod ArcadeAccountMock {
self._master_account.write(master_account);
}
}

#[external(v0)]
fn supports_interface(self: @ContractState, interface_id: felt252) -> bool {
return interface_id == interface::ARCADE_ACCOUNT_ID;
}
}

#[starknet::contract]
mod ValidArcadeAccountMock {
// locals
use arcade_factory::account::interface;

//
// Storage
//

#[storage]
struct Storage { }

//
// ArcadeAccountMockABI
//

#[external(v0)]
fn supports_interface(self: @ContractState, interface_id: felt252) -> bool {
return interface_id == interface::ARCADE_ACCOUNT_ID;
}
}

#[starknet::contract]
mod InvalidArcadeAccountMock {
// locals
use arcade_factory::account::interface;

//
// Storage
//

#[storage]
struct Storage { }

//
// ArcadeAccountMockABI
//

#[external(v0)]
fn supports_interface(self: @ContractState, interface_id: felt252) -> bool {
return interface_id != interface::ARCADE_ACCOUNT_ID;
}
}
70 changes: 70 additions & 0 deletions demos/arcade-factory/src/tests/test_factory.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use arcade_factory::factory::contract::ArcadeFactory;
use arcade_factory::factory::interface::{ ArcadeFactoryABIDispatcher, ArcadeFactoryABIDispatcherTrait };

use super::mocks::arcade_account_mock::{
ValidArcadeAccountMock,
InvalidArcadeAccountMock,
ArcadeAccountMock,
ArcadeAccountMockABIDispatcher,
ArcadeAccountMockABIDispatcherTrait,
Expand Down Expand Up @@ -38,6 +40,22 @@ fn setup() -> ArcadeFactoryABIDispatcher {

// Cannot test address computation with current cairo version

// Constructor

#[test]
#[available_gas(20000000)]
#[should_panic(expected: ('Result::unwrap failed.',))] // cannot have another error message from constructor
fn test_constructor_invalid_arcade_account_implementation() {
let owner = constants::OWNER();

utils::deploy(
contract_class_hash: ArcadeFactory::TEST_CLASS_HASH,
calldata: array![owner.into(), InvalidArcadeAccountMock::TEST_CLASS_HASH]
);
}

// Arcade account implementation

#[test]
#[available_gas(20000000)]
fn test_arcade_account_implementation() {
Expand All @@ -49,6 +67,8 @@ fn test_arcade_account_implementation() {
);
}

// Deploy

#[test]
#[available_gas(20000000)]
fn test_deploy() {
Expand Down Expand Up @@ -88,3 +108,53 @@ fn test_upgrade_from_zero() {
testing::set_contract_address(constants::ZERO());
factory.upgrade(new_class_hash: 'new class hash'.try_into().unwrap());
}

// Set arcade account implementation

#[test]
#[available_gas(20000000)]
fn test_set_arcade_account_implementation() {
let factory = setup();

testing::set_contract_address(constants::OWNER());
factory.set_arcade_account_implementation(
arcade_account_implementation: ValidArcadeAccountMock::TEST_CLASS_HASH.try_into().unwrap()
);

assert(
factory.arcade_account_implementation() == ValidArcadeAccountMock::TEST_CLASS_HASH.try_into().unwrap(),
'Invalid arcade account impl'
);
}

#[test]
#[available_gas(20000000)]
#[should_panic(expected: ('Invalid arcade account impl', 'ENTRYPOINT_FAILED',))]
fn test_set_arcade_account_implementation_invalid() {
let factory = setup();

testing::set_contract_address(constants::OWNER());
factory.set_arcade_account_implementation(
arcade_account_implementation: InvalidArcadeAccountMock::TEST_CLASS_HASH.try_into().unwrap()
);
}

#[test]
#[available_gas(20000000)]
#[should_panic(expected: ('Caller is not the owner', 'ENTRYPOINT_FAILED',))]
fn test_set_arcade_account_implementation_unauthorized() {
let factory = setup();

testing::set_contract_address(constants::OTHER());
factory.set_arcade_account_implementation(arcade_account_implementation: 'new class hash'.try_into().unwrap());
}

#[test]
#[available_gas(20000000)]
#[should_panic(expected: ('Caller is the zero address', 'ENTRYPOINT_FAILED',))]
fn test_set_arcade_account_implementation_from_zero() {
let factory = setup();

testing::set_contract_address(constants::ZERO());
factory.set_arcade_account_implementation(arcade_account_implementation: 'new class hash'.try_into().unwrap());
}

0 comments on commit 4f5ecdc

Please sign in to comment.