Skip to content

Commit

Permalink
test for lockable components
Browse files Browse the repository at this point in the history
  • Loading branch information
mubarak23 committed Aug 19, 2024
1 parent 2c18f12 commit dfe8bfb
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 14 deletions.
18 changes: 7 additions & 11 deletions src/components/lockable/lockable.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ pub mod LockableComponent {
};

#[storage]
struct Storage {
pub struct Storage {
lock_until: u64
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
pub enum Event {
AccountLocked: AccountLocked
}

Expand Down Expand Up @@ -69,28 +69,24 @@ pub mod LockableComponent {

let account_comp = get_dep_component!(@self, Account);

// get the token
// let (token_contract, token_id, chain_id) = account_comp.token();

// get the token owner
let owner = account_comp.owner();

// assert(account_comp.is_non_zero(), Errors::UNAUTHORIZED);
assert(get_caller_address() != owner, Errors::NOT_OWNER);
assert(get_caller_address() == owner, Errors::NOT_OWNER);

assert(lock_until <= current_timestamp + 356, Errors::EXCEEDS_MAX_LOCK_TIME);

// _beforeLock may be call before upating the lock period
let lock_status = self.is_lock(); //.is_locked();
assert(!lock_status, Errors::LOCKED_ACCOUNT);
let lock_status = self.is_lock();

assert(lock_status != true, Errors::LOCKED_ACCOUNT);
// set the lock_util which set the period the account is lock
self.lock_until.write(lock_until);
// emit event
self
.emit(
AccountLocked {
account: get_caller_address(),
locked_at: current_timestamp,
locked_at: get_block_timestamp(),
lock_until: lock_until
}
);
Expand Down
28 changes: 25 additions & 3 deletions src/components/presets/account_preset.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,22 @@ pub mod AccountPreset {
use starknet::{ContractAddress, get_caller_address, ClassHash, account::Call};
use token_bound_accounts::components::account::account::AccountComponent;
use token_bound_accounts::components::upgradeable::upgradeable::UpgradeableComponent;
use token_bound_accounts::interfaces::{IUpgradeable::IUpgradeable, IExecutable::IExecutable,};
use token_bound_accounts::components::lockable::lockable::LockableComponent;
use token_bound_accounts::interfaces::{
IUpgradeable::IUpgradeable, IExecutable::IExecutable, ILockable::ILockable
};

component!(path: AccountComponent, storage: account, event: AccountEvent);
component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);
component!(path: LockableComponent, storage: lockable, event: LockableEvent);

// Account
#[abi(embed_v0)]
impl AccountImpl = AccountComponent::AccountImpl<ContractState>;

impl AccountInternalImpl = AccountComponent::InternalImpl<ContractState>;
impl UpgradeableInternalImpl = UpgradeableComponent::Private<ContractState>;
impl LockableImpl = LockableComponent::LockableImpl<ContractState>;

// *************************************************************************
// STORAGE
Expand All @@ -26,7 +31,9 @@ pub mod AccountPreset {
#[substorage(v0)]
account: AccountComponent::Storage,
#[substorage(v0)]
upgradeable: UpgradeableComponent::Storage
upgradeable: UpgradeableComponent::Storage,
#[substorage(v0)]
lockable: LockableComponent::Storage,
}

// *************************************************************************
Expand All @@ -38,7 +45,9 @@ pub mod AccountPreset {
#[flat]
AccountEvent: AccountComponent::Event,
#[flat]
UpgradeableEvent: UpgradeableComponent::Event
UpgradeableEvent: UpgradeableComponent::Event,
#[flat]
LockableEvent: LockableComponent::Event
}

// *************************************************************************
Expand Down Expand Up @@ -68,4 +77,17 @@ pub mod AccountPreset {
self.upgradeable._upgrade(new_class_hash);
}
}

// *************************************************************************
// LOCKABLE IMPL
// *************************************************************************
#[abi(embed_v0)]
impl Lockable of ILockable<ContractState> {
fn lock(ref self: ContractState, lock_until: u64) {
self.lockable.lock(lock_until);
}
fn is_lock(self: @ContractState) -> bool {
self.lockable.is_lock()
}
}
}
152 changes: 152 additions & 0 deletions tests/test_lockable_component.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
// *************************************************************************
// LOCKABLE COMPONENT TEST
// *************************************************************************
use starknet::{ContractAddress, account::Call, get_block_timestamp};
use snforge_std::{
declare, start_cheat_caller_address, stop_cheat_caller_address, start_cheat_transaction_hash,
start_cheat_nonce, spy_events, EventSpyAssertionsTrait, ContractClassTrait, ContractClass
};
use core::hash::HashStateTrait;
use core::pedersen::PedersenTrait;

use token_bound_accounts::interfaces::IAccount::{
IAccountDispatcher, IAccountDispatcherTrait, IAccountSafeDispatcher, IAccountSafeDispatcherTrait
};
use token_bound_accounts::interfaces::ILockable::{ILockableDispatcher, ILockableDispatcherTrait};

use token_bound_accounts::interfaces::IExecutable::{
IExecutableDispatcher, IExecutableDispatcherTrait
};
use token_bound_accounts::components::presets::account_preset::AccountPreset;
use token_bound_accounts::components::account::account::AccountComponent;
use token_bound_accounts::components::lockable::lockable::LockableComponent;

use token_bound_accounts::test_helper::{
hello_starknet::{IHelloStarknetDispatcher, IHelloStarknetDispatcherTrait, HelloStarknet},
erc721_helper::{IERC721Dispatcher, IERC721DispatcherTrait, ERC721},
simple_account::{ISimpleAccountDispatcher, ISimpleAccountDispatcherTrait, SimpleAccount}
};


const ACCOUNT: felt252 = 1234;
const ACCOUNT2: felt252 = 5729;
const SALT: felt252 = 123;

#[derive(Drop)]
struct SignedTransactionData {
private_key: felt252,
public_key: felt252,
transaction_hash: felt252,
r: felt252,
s: felt252
}

fn SIGNED_TX_DATA() -> SignedTransactionData {
SignedTransactionData {
private_key: 1234,
public_key: 883045738439352841478194533192765345509759306772397516907181243450667673002,
transaction_hash: 2717105892474786771566982177444710571376803476229898722748888396642649184538,
r: 3068558690657879390136740086327753007413919701043650133111397282816679110801,
s: 3355728545224320878895493649495491771252432631648740019139167265522817576501
}
}

// *************************************************************************
// SETUP
// *************************************************************************
fn __setup__() -> (ContractAddress, ContractAddress) {
// deploy erc721 helper contract
let erc721_contract = declare("ERC721").unwrap();
let mut erc721_constructor_calldata = array!['tokenbound', 'TBA'];
let (erc721_contract_address, _) = erc721_contract
.deploy(@erc721_constructor_calldata)
.unwrap();

// deploy recipient contract
let account_contract = declare("SimpleAccount").unwrap();
let (recipient, _) = account_contract
.deploy(
@array![883045738439352841478194533192765345509759306772397516907181243450667673002]
)
.unwrap();

// mint a new token
let dispatcher = IERC721Dispatcher { contract_address: erc721_contract_address };
dispatcher.mint(recipient, 1.try_into().unwrap());

// deploy account contract
let account_contract = declare("AccountPreset").unwrap();
let mut acct_constructor_calldata = array![erc721_contract_address.try_into().unwrap(), 1, 0];
let (account_contract_address, _) = account_contract
.deploy(@acct_constructor_calldata)
.unwrap();

(account_contract_address, erc721_contract_address)
}


#[test]
fn test_lockable_owner() {
let (contract_address, erc721_contract_address) = __setup__();
let acct_dispatcher = IAccountDispatcher { contract_address: contract_address };

let token_dispatcher = IERC721Dispatcher { contract_address: erc721_contract_address };
let owner = acct_dispatcher.owner();
let token_owner = token_dispatcher.ownerOf(1.try_into().unwrap());

start_cheat_caller_address(contract_address, token_owner);

assert(owner == token_owner, 'invalid owner');
stop_cheat_caller_address(contract_address);
}
#[test]
fn test_lockable() {
let (contract_address, _) = __setup__();
let acct_dispatcher = IAccountDispatcher { contract_address: contract_address };

let owner = acct_dispatcher.owner();

start_cheat_caller_address(contract_address, owner);

let lockable_dispatcher = ILockableDispatcher { contract_address };

lockable_dispatcher.lock(40);
let check_lock = lockable_dispatcher.is_lock();

assert(check_lock == true, 'Account Not Lock');
stop_cheat_caller_address(contract_address);
}
#[test]
fn test_lockable_emits_event() {
let (contract_address, _) = __setup__();

let acct_dispatcher = IAccountDispatcher { contract_address: contract_address };

let owner = acct_dispatcher.owner();

// spy on emitted events
let mut spy = spy_events();

start_cheat_caller_address(contract_address, owner);

// call the lock function
let lockable_dispatcher = ILockableDispatcher { contract_address: contract_address };

lockable_dispatcher.lock(40);

// check events are emitted
spy
.assert_emitted(
@array![
(
contract_address,
LockableComponent::Event::AccountLocked(
LockableComponent::AccountLocked {
account: owner, locked_at: get_block_timestamp(), lock_until: 40
}
)
)
]
);
}

0 comments on commit dfe8bfb

Please sign in to comment.