Skip to content

Commit

Permalink
Withdrawal tests (#11)
Browse files Browse the repository at this point in the history
* feat: initiliased testcases

* admin function tests

* fix: max total balance check

* feat: block token test

* disable limit test

* feat: add failing tc for withdraw limit

* fixed testcases after rebase

* chore: added messaging mock

* Update src/bridge/token_bridge.cairo

Co-authored-by: Apoorv Sadana <[email protected]>

* resolve comments

* add reactivate and unblock

* add reactivate and unblock

* unblock tests

* reactivate and unblock tests

* resolved merge conflicts

* restructure testcases

* fix: visibility modifier

* deposit tests

* make them unit

* make them unit

* deposit flow tests

* change to mock usdc address

* improve: not needed to deploy usdc in while mock testing

* unit testcases

* add token actions restructure

* migrate to latest foundry

* restructure

* deposit failing tc

* test: happy withdraw test

* chore: ran formatter

* fix settlement of message

* change deposit tests to use message_payloads

* add assert

* failing withdraw tc

* cancel request

* deposit with message cancels

* Update tests/deposit_test.cairo

Co-authored-by: Apoorv Sadana <[email protected]>

* resolved comments

* fix consume message

* reclaim testcases

* fix consume message check

* consume message

* add balance check

* add events in actions

* deactivate tc

* send messages tc

* change name

* withdrawal limit tests initialised

* fix build failure

* remaining quota

* withdrawal tests

* Update src/withdrawal_limit/mock.cairo

Co-authored-by: Apoorv Sadana <[email protected]>

* Update src/withdrawal_limit/tests/withdrawal_limit_test.cairo

Co-authored-by: Apoorv Sadana <[email protected]>

* Update src/withdrawal_limit/tests/withdrawal_limit_test.cairo

Co-authored-by: Apoorv Sadana <[email protected]>

* Update src/withdrawal_limit/tests/withdrawal_limit_test.cairo

Co-authored-by: Apoorv Sadana <[email protected]>

* should fail if message not registered (#12)

* resolve commits

* Update src/withdrawal_limit/tests/withdrawal_limit_test.cairo

Co-authored-by: Apoorv Sadana <[email protected]>

* Update src/withdrawal_limit/tests/withdrawal_limit_test.cairo

Co-authored-by: Apoorv Sadana <[email protected]>

* move file to mocks

* code repetition reduced

* failing tests fixed

---------

Co-authored-by: Apoorv Sadana <[email protected]>
  • Loading branch information
byteZorvin and apoorvsadana authored Aug 20, 2024
1 parent 4f7a8ec commit b753a64
Show file tree
Hide file tree
Showing 16 changed files with 437 additions and 52 deletions.
22 changes: 1 addition & 21 deletions src/bridge/tests/messaging_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -25,32 +25,12 @@ use openzeppelin::{
interface::{IOwnableTwoStepDispatcher, IOwnableTwoStepDispatcherTrait}
}
};
use starknet_bridge::bridge::tests::utils::setup::{deploy_erc20, mock_state_testing};
use starknet_bridge::bridge::tests::utils::message_payloads;
use starknet::contract_address::{contract_address_const};
use starknet_bridge::constants;


/// Returns the state of a contract for testing. This must be used
/// to test internal functions or directly access the storage.
/// You can't spy event with this. Use deploy instead.
pub fn mock_state_testing() -> TokenBridge::ContractState {
TokenBridge::contract_state_for_testing()
}

fn deploy_erc20(name: ByteArray, symbol: ByteArray) -> ContractAddress {
let erc20_class_hash = snf::declare("ERC20").unwrap();
let mut constructor_args = ArrayTrait::new();
name.serialize(ref constructor_args);
symbol.serialize(ref constructor_args);
let fixed_supply: u256 = 1000000000;
fixed_supply.serialize(ref constructor_args);
OWNER().serialize(ref constructor_args);

let (usdc, _) = erc20_class_hash.deploy(@constructor_args).unwrap();
return usdc;
}


#[test]
fn deploy_message_payload_ok() {
let usdc_address = deploy_erc20("USDC", "USDC");
Expand Down
22 changes: 1 addition & 21 deletions src/bridge/tests/token_actions_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,12 @@ use starknet_bridge::bridge::tests::utils::message_payloads;
use starknet_bridge::mocks::hash;
use starknet::contract_address::{contract_address_const};
use starknet_bridge::constants;
use starknet_bridge::bridge::tests::utils::setup::{deploy_erc20, mock_state_testing};

use starknet_bridge::bridge::tests::constants::{
OWNER, L3_BRIDGE_ADDRESS, USDC_MOCK_ADDRESS, DELAY_TIME
};


/// Returns the state of a contract for testing. This must be used
/// to test internal functions or directly access the storage.
/// You can't spy event with this. Use deploy instead.
pub fn mock_state_testing() -> TokenBridge::ContractState {
TokenBridge::contract_state_for_testing()
}

fn deploy_erc20(name: ByteArray, symbol: ByteArray) -> ContractAddress {
let erc20_class_hash = snf::declare("ERC20").unwrap();
let mut constructor_args = ArrayTrait::new();
name.serialize(ref constructor_args);
symbol.serialize(ref constructor_args);
let fixed_supply: u256 = 1000000000;
fixed_supply.serialize(ref constructor_args);
OWNER().serialize(ref constructor_args);

let (usdc, _) = erc20_class_hash.deploy(@constructor_args).unwrap();
return usdc;
}

#[test]
fn deactivate_token_ok() {
let mut mock = mock_state_testing();
Expand Down
4 changes: 3 additions & 1 deletion tests/setup.cairo → src/bridge/tests/utils/setup.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ use openzeppelin::access::ownable::{
};
use openzeppelin::token::erc20::interface::{IERC20, IERC20Dispatcher, IERC20DispatcherTrait};
use starknet::contract_address::{contract_address_const};
use super::constants::{OWNER, L3_BRIDGE_ADDRESS, DELAY_TIME};
use starknet_bridge::bridge::tests::constants::{
OWNER, USDC_MOCK_ADDRESS, L3_BRIDGE_ADDRESS, DELAY_TIME
};
use starknet_bridge::constants;
use starknet_bridge::bridge::tests::utils::message_payloads;

Expand Down
1 change: 1 addition & 0 deletions src/bridge/token_bridge.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ pub mod TokenBridge {
self
.messaging_contract
.write(IMessagingDispatcher { contract_address: messaging_contract });
self.withdrawal.initialize(5);
self.ownable.initializer(owner);
}

Expand Down
8 changes: 8 additions & 0 deletions src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub mod bridge {
mod messaging_test;
pub mod utils {
pub mod message_payloads;
pub mod setup;
}
}

Expand All @@ -25,13 +26,20 @@ pub mod bridge {
pub mod withdrawal_limit {
pub mod component;
pub mod interface;

#[cfg(test)]
mod tests {
mod withdrawal_limit_test;
}
}

pub mod constants;

pub mod mocks {
pub mod erc20;
pub mod messaging;
pub mod messaging_malicious;
pub mod withdrawal_limit_mock;
pub mod hash;
}

56 changes: 56 additions & 0 deletions src/mocks/messaging_malicious.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#[starknet::contract]
mod messaging_malicious {
use piltover::messaging::interface::IMessaging;
use starknet::ContractAddress;


#[storage]
struct Storage {}


#[abi(embed_v0)]
impl MessagingImpl of IMessaging<ContractState> {
fn send_message_to_appchain(
ref self: ContractState,
to_address: ContractAddress,
selector: felt252,
payload: Span<felt252>
) -> (felt252, felt252) {
(0, 0)
}

fn consume_message_from_appchain(
ref self: ContractState, from_address: ContractAddress, payload: Span<felt252>
) -> felt252 {
0
}

fn sn_to_appchain_messages(self: @ContractState, message_hash: felt252) -> felt252 {
0
}

fn appchain_to_sn_messages(self: @ContractState, message_hash: felt252) -> felt252 {
0
}

fn start_message_cancellation(
ref self: ContractState,
to_address: ContractAddress,
selector: felt252,
payload: Span<felt252>,
nonce: felt252,
) -> felt252 {
0
}

fn cancel_message(
ref self: ContractState,
to_address: ContractAddress,
selector: felt252,
payload: Span<felt252>,
nonce: felt252,
) -> felt252 {
0
}
}
}
80 changes: 80 additions & 0 deletions src/mocks/withdrawal_limit_mock.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use starknet::ContractAddress;

#[starknet::interface]
pub trait IMockWithdrawalLimit<TState> {
fn toggle_withdrawal_limit_for_token(
ref self: TState, token: ContractAddress, is_applied: bool
);
fn consume_quota(ref self: TState, token: ContractAddress, amount: u256);
fn write_daily_withdrawal_limit_pct(ref self: TState, limit_percent: u8);
fn get_daily_withdrawal_limit_pct(self: @TState) -> u8;
}

#[starknet::contract]
pub mod withdrawal_limit_mock {
use starknet_bridge::withdrawal_limit::component::WithdrawalLimitComponent::InternalTrait;
use starknet_bridge::withdrawal_limit::{
component::WithdrawalLimitComponent,
interface::{IWithdrawalLimitDispatcher, IWithdrawalLimitDispatcherTrait, IWithdrawalLimit}
};
use starknet_bridge::bridge::interface::IWithdrawalLimitStatus;
use starknet::ContractAddress;


component!(path: WithdrawalLimitComponent, storage: withdrawal, event: WithdrawalEvent);

// WithdrawalLimit
#[abi(embed_v0)]
impl WithdrawalLimitImpl =
WithdrawalLimitComponent::WithdrawalLimitImpl<ContractState>;
impl WithdrawalLimitInternal = WithdrawalLimitComponent::InternalImpl<ContractState>;


#[storage]
struct Storage {
limits: LegacyMap<ContractAddress, bool>,
#[substorage(v0)]
withdrawal: WithdrawalLimitComponent::Storage,
}

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

#[constructor]
pub fn constructor(ref self: ContractState) {
self.withdrawal.initialize(5);
}


#[abi(embed_v0)]
impl MockWithdrawalLimitImpl of super::IMockWithdrawalLimit<ContractState> {
fn toggle_withdrawal_limit_for_token(
ref self: ContractState, token: ContractAddress, is_applied: bool
) {
self.limits.write(token, is_applied);
}

fn consume_quota(ref self: ContractState, token: ContractAddress, amount: u256) {
self.withdrawal.consume_withdrawal_quota(token, amount);
}

fn write_daily_withdrawal_limit_pct(ref self: ContractState, limit_percent: u8) {
self.withdrawal.write_daily_withdrawal_limit_pct(limit_percent);
}

fn get_daily_withdrawal_limit_pct(self: @ContractState) -> u8 {
self.withdrawal.daily_withdrawal_limit_pct.read()
}
}

#[abi(embed_v0)]
impl WithdrawalLimitStatusImpl of IWithdrawalLimitStatus<ContractState> {
fn is_withdrawal_limit_applied(self: @ContractState, token: ContractAddress) -> bool {
self.limits.read(token)
}
}
}
25 changes: 23 additions & 2 deletions src/withdrawal_limit/component.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,21 @@ pub mod WithdrawalLimitComponent {
#[event]
#[derive(Drop, starknet::Event)]
pub enum Event {
RemainingQuotaUpdated: RemainingQuotaUpdated
RemainingQuotaUpdated: RemainingQuotaUpdated,
DailyWithdrawalPercentageUpdated: DailyWithdrawalPercentageUpdated
}

#[derive(Drop, starknet::Event)]
pub struct RemainingQuotaUpdated {
new_quota: u256
pub token: ContractAddress,
pub day: u64,
pub new_quota: u256
}

#[derive(Drop, starknet::Event)]
pub struct DailyWithdrawalPercentageUpdated {
pub new_percentage: u8
}

#[embeddable_as(WithdrawalLimitImpl)]
pub impl WithdrawalLimit<
Expand All @@ -45,6 +52,8 @@ pub mod WithdrawalLimitComponent {
return BoundedInt::max();
}
let remaining_quota = self.read_withdrawal_quota_slot(:token);

// if remaining_quota is 0 then quota is not initialised
if remaining_quota == 0 {
return self.get_daily_withdrawal_limit(:token);
}
Expand All @@ -56,6 +65,11 @@ pub mod WithdrawalLimitComponent {
pub impl InternalImpl<
TContractState, +HasComponent<TContractState>, +IWithdrawalLimitStatus<TContractState>
> of InternalTrait<TContractState> {
// This initializes the withdrawal_limit component
fn initialize(ref self: ComponentState<TContractState>, daily_withdrawal_limit_pct: u8) {
self.daily_withdrawal_limit_pct.write(daily_withdrawal_limit_pct);
}

// Sets the remaining withdrawal quota for today.
fn set_remaining_withdrawal_quota(
ref self: ComponentState<TContractState>, token: ContractAddress, amount: u256
Expand All @@ -65,6 +79,8 @@ pub mod WithdrawalLimitComponent {
self
.remaining_intraday_withdraw_quota
.write((token, day), amount + constants::REMAINING_QUOTA_OFFSET);

self.emit(RemainingQuotaUpdated { token: token, day: day, new_quota: amount });
}

// Returns the remaining withdrawal quota for today.
Expand Down Expand Up @@ -118,6 +134,11 @@ pub mod WithdrawalLimitComponent {
) {
assert(daily_withdrawal_limit_pct <= 100, 'LIMIT_PCT_TOO_HIGH');
self.daily_withdrawal_limit_pct.write(daily_withdrawal_limit_pct);

self
.emit(
DailyWithdrawalPercentageUpdated { new_percentage: daily_withdrawal_limit_pct }
);
}
}
}
Loading

0 comments on commit b753a64

Please sign in to comment.