Skip to content

Commit

Permalink
tests: set up local component testing infrastructure and add initial …
Browse files Browse the repository at this point in the history
…unit tests (#81)

* imp: initialize a temp ChannelEnd

* imp: better org around client-relevant validations under recv_validate

* tests: add some local components tests
  • Loading branch information
Farhad-Shabani authored Sep 17, 2024
1 parent 540f292 commit 661b02b
Show file tree
Hide file tree
Showing 43 changed files with 646 additions and 251 deletions.
1 change: 1 addition & 0 deletions cairo-contracts/Scarb.lock
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ dependencies = [
name = "starknet_ibc_core"
version = "0.1.0"
dependencies = [
"openzeppelin_testing",
"snforge_std",
"starknet_ibc_utils",
]
Expand Down
37 changes: 35 additions & 2 deletions cairo-contracts/packages/apps/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
pub mod transfer {
pub mod components;
mod erc20_call;
mod errors;
pub mod interfaces;
pub mod types;

pub use components::transfer::TokenTransferComponent;
pub use components::transferrable::TransferrableComponent;
pub use erc20_call::{ERC20Contract, ERC20ContractTrait};
pub use errors::TransferErrors;
pub use interfaces::transfer::{
ISendTransfer, ISendTransferDispatcher, ISendTransferDispatcherTrait, ITokenAddress,
ITokenAddressDispatcher, ITokenAddressDispatcherTrait,
};
pub use interfaces::transferrable::{
ITransferrable, ITransferrableDispatcher, ITransferrableDispatcherTrait
};
pub mod components {
pub mod transfer;
pub mod transferrable;
}
pub mod interfaces {
pub mod transfer;
pub mod transferrable;
}

/// The poseidon hash of the transfer port id.
pub const TRANSFER_PORT_ID_HASH: felt252 =
Expand All @@ -16,3 +31,21 @@ pub mod transfer {
"transfer"
}
}
pub mod tests {
mod config;
mod dummy;
mod extend_spy;
#[cfg(test)]
mod test_transfer;
pub use config::{TransferAppConfig, TransferAppConfigImpl, TransferAppConfigTrait};
pub use dummy::{
NAME, SYMBOL, PUBKEY, AMOUNT, SUPPLY, OWNER, STARKNET, COSMOS, SALT, DECIMALS, CLASS_HASH,
EMPTY_MEMO
};

pub use extend_spy::{TransferEventSpyExtImpl, TransferEventSpyExt};
pub(crate) use mocks::mock_transfer::MockTransferApp;
mod mocks {
pub(crate) mod mock_transfer;
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
use starknet::ContractAddress;
use starknet_ibc_apps::tests::{PUBKEY, NAME, AMOUNT, SUPPLY, EMPTY_MEMO};
use starknet_ibc_apps::transfer::TRANSFER_PORT_ID;
use starknet_ibc_apps::transfer::types::PrefixedDenomTrait;
use starknet_ibc_apps::transfer::types::{
MsgTransfer, PacketData, PrefixedDenom, Denom, Memo, TracePrefixTrait, Participant
};
use starknet_ibc_contracts::tests::constants::{PUBKEY, NAME, AMOUNT, SUPPLY};
use starknet_ibc_core::channel::Packet;
use starknet_ibc_core::client::{Height, Timestamp};
use starknet_ibc_core::host::{PortId, ChannelId, Sequence};
use starknet_ibc_core::tests::{PORT_ID, CHANNEL_ID};

#[derive(Clone, Debug, Drop, Serde)]
pub struct TransferAppConfig {
pub native_denom: PrefixedDenom,
pub hosted_denom: PrefixedDenom,
pub chan_id_on_a: ByteArray,
pub chan_id_on_b: ByteArray,
pub chan_id_on_a: ChannelId,
pub chan_id_on_b: ChannelId,
pub amount: u256,
}

Expand All @@ -30,8 +31,8 @@ pub impl TransferAppConfigImpl of TransferAppConfigTrait {
TransferAppConfig {
native_denom,
hosted_denom,
chan_id_on_a: "channel-0",
chan_id_on_b: "channel-1",
chan_id_on_a: CHANNEL_ID(0),
chan_id_on_b: CHANNEL_ID(1),
amount: AMOUNT,
}
}
Expand All @@ -47,10 +48,7 @@ pub impl TransferAppConfigImpl of TransferAppConfigTrait {


fn prefix_native_denom(self: @TransferAppConfig) -> PrefixedDenom {
let trace_prefix = TracePrefixTrait::new(
PortId { port_id: TRANSFER_PORT_ID() },
ChannelId { channel_id: self.chan_id_on_a.clone() }
);
let trace_prefix = TracePrefixTrait::new(PORT_ID(), self.chan_id_on_a.clone());
let mut native_denom = self.native_denom.clone();

native_denom.add_prefix(trace_prefix);
Expand All @@ -59,10 +57,7 @@ pub impl TransferAppConfigImpl of TransferAppConfigTrait {
}

fn prefix_hosted_denom(self: @TransferAppConfig) -> PrefixedDenom {
let trace_prefix = TracePrefixTrait::new(
PortId { port_id: TRANSFER_PORT_ID() },
ChannelId { channel_id: self.chan_id_on_b.clone() }
);
let trace_prefix = TracePrefixTrait::new(PORT_ID(), self.chan_id_on_b.clone());

let mut hosted_denom = self.hosted_denom.clone();

Expand All @@ -75,8 +70,8 @@ pub impl TransferAppConfigImpl of TransferAppConfigTrait {
self: @TransferAppConfig, denom: PrefixedDenom, sender: Participant, receiver: Participant
) -> MsgTransfer {
MsgTransfer {
port_id_on_a: PortId { port_id: TRANSFER_PORT_ID() },
chan_id_on_a: ChannelId { channel_id: self.chan_id_on_a.clone() },
port_id_on_a: PORT_ID(),
chan_id_on_a: self.chan_id_on_a.clone(),
packet_data: self.dummy_packet_data(denom, sender, receiver),
timeout_height_on_b: Height { revision_number: 0, revision_height: 1000 },
timeout_timestamp_on_b: Timestamp { timestamp: 1000 }
Expand All @@ -91,10 +86,10 @@ pub impl TransferAppConfigImpl of TransferAppConfigTrait {

Packet {
seq_on_a: Sequence { sequence: 0 },
port_id_on_a: PortId { port_id: TRANSFER_PORT_ID() },
chan_id_on_a: ChannelId { channel_id: self.chan_id_on_a.clone() },
port_id_on_b: PortId { port_id: TRANSFER_PORT_ID() },
chan_id_on_b: ChannelId { channel_id: self.chan_id_on_b.clone() },
port_id_on_a: PORT_ID(),
chan_id_on_a: self.chan_id_on_a.clone(),
port_id_on_b: PORT_ID(),
chan_id_on_b: self.chan_id_on_b.clone(),
data: serialized_data,
timeout_height_on_b: Height { revision_number: 0, revision_height: 1000 },
timeout_timestamp_on_b: Timestamp { timestamp: 1000 }
Expand All @@ -104,6 +99,6 @@ pub impl TransferAppConfigImpl of TransferAppConfigTrait {
fn dummy_packet_data(
self: @TransferAppConfig, denom: PrefixedDenom, sender: Participant, receiver: Participant
) -> PacketData {
PacketData { denom, amount: *self.amount, sender, receiver, memo: Memo { memo: "" }, }
PacketData { denom, amount: *self.amount, sender, receiver, memo: EMPTY_MEMO() }
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use core::serde::Serde;
use starknet::ContractAddress;
use starknet::class_hash::class_hash_const;
use starknet::contract_address_const;
use starknet_ibc_apps::transfer::types::Participant;
use starknet::{ContractAddress, ClassHash};
use starknet_ibc_apps::transfer::types::{Participant, Memo};

pub const SUPPLY: u256 = 2000;
pub const DECIMALS: u8 = 18_u8;
Expand All @@ -24,6 +25,10 @@ pub fn OWNER() -> ContractAddress {
contract_address_const::<'OWNER'>()
}

pub fn CLASS_HASH() -> ClassHash {
class_hash_const::<'ERC20Mintable'>()
}

pub fn STARKNET() -> Participant {
OWNER().into()
}
Expand All @@ -35,3 +40,7 @@ pub fn COSMOS() -> Participant {
serialized_address.into()
}

pub fn EMPTY_MEMO() -> Memo {
Memo { memo: "" }
}

54 changes: 54 additions & 0 deletions cairo-contracts/packages/apps/src/tests/extend_spy.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use openzeppelin_testing::events::{EventSpyExt, EventSpyExtImpl};
use snforge_std::EventSpy;
use starknet::ContractAddress;
use starknet_ibc_apps::tests::EMPTY_MEMO;
use starknet_ibc_apps::transfer::TokenTransferComponent::{
Event, SendEvent, RecvEvent, CreateTokenEvent
};
use starknet_ibc_apps::transfer::types::{Participant, PrefixedDenom, Memo};

#[generate_trait]
pub impl TransferEventSpyExtImpl of TransferEventSpyExt {
fn assert_send_event(
ref self: EventSpy,
contract_address: ContractAddress,
sender: Participant,
receiver: Participant,
denom: PrefixedDenom,
amount: u256
) {
let expected = Event::SendEvent(
SendEvent { sender, receiver, denom, amount, memo: EMPTY_MEMO(), }
);
self.assert_emitted_single(contract_address, expected);
}

fn assert_recv_event(
ref self: EventSpy,
contract_address: ContractAddress,
sender: Participant,
receiver: Participant,
denom: PrefixedDenom,
amount: u256,
success: bool
) {
let expected = Event::RecvEvent(
RecvEvent { sender, receiver, denom, amount, memo: EMPTY_MEMO(), success, }
);
self.assert_emitted_single(contract_address, expected);
}

fn assert_create_token_event(
ref self: EventSpy,
contract_address: ContractAddress,
name: ByteArray,
symbol: ByteArray,
address: ContractAddress,
initial_supply: u256
) {
let expected = Event::CreateTokenEvent(
CreateTokenEvent { name, symbol, address, initial_supply }
);
self.assert_emitted_single(contract_address, expected);
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
// This mock contract extends the preset ICS-20 token transfer component,
// granting external access to all internal validation and execution functions
// for testing purposes.
#[starknet::contract]
pub(crate) mod MockTransferApp {
use openzeppelin_access::ownable::OwnableComponent;
use starknet::ClassHash;
use starknet::ContractAddress;
use starknet_ibc_apps::transfer::components::{TokenTransferComponent, TransferrableComponent};
use starknet_ibc_apps::transfer::types::{
PrefixedDenom, Denom, DenomTrait, PacketData, TracePrefix, Memo, TracePrefixTrait,
PrefixedDenomTrait
};
use starknet_ibc_apps::transfer::{ERC20Contract, ERC20ContractTrait};
use starknet_ibc_apps::transfer::{TokenTransferComponent, TransferrableComponent};
use starknet_ibc_core::host::{PortId, ChannelId, ChannelIdTrait};

component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
Expand Down Expand Up @@ -115,7 +112,6 @@ pub(crate) mod MockTransferApp {
self.transfer.burn_validate(account, denom, amount, memo);
}


#[external(v0)]
fn escrow_execute(
ref self: ContractState,
Expand Down
24 changes: 24 additions & 0 deletions cairo-contracts/packages/apps/src/tests/test_transfer.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use starknet_ibc_apps::tests::{MockTransferApp, CLASS_HASH};
use starknet_ibc_apps::transfer::TokenTransferComponent::{
TransferInitializerImpl, TransferReaderImpl
};
use starknet_ibc_apps::transfer::TokenTransferComponent;

type ComponentState = TokenTransferComponent::ComponentState<MockTransferApp::ContractState>;

fn COMPONENT_STATE() -> ComponentState {
TokenTransferComponent::component_state_for_testing()
}

fn setup() -> ComponentState {
let mut state = COMPONENT_STATE();
state.initializer(CLASS_HASH());
state
}

#[test]
fn test_init_state() {
let state = setup();
let class_hash = state.read_erc20_class_hash();
assert_eq!(class_hash, CLASS_HASH());
}
5 changes: 0 additions & 5 deletions cairo-contracts/packages/apps/src/transfer/components.cairo

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ pub mod TokenTransferComponent {
use starknet::ContractAddress;
use starknet::storage::Map;
use starknet::{get_contract_address, get_caller_address};
use starknet_ibc_apps::transfer::interfaces::{ITransferrable, ISendTransfer, ITokenAddress};
use starknet_ibc_apps::transfer::types::{
MsgTransfer, PrefixedDenom, Denom, DenomTrait, PacketData, TracePrefix, Memo,
TracePrefixTrait, PrefixedDenomTrait, Participant
};
use starknet_ibc_apps::transfer::{ERC20Contract, ERC20ContractTrait, TransferErrors};
use starknet_ibc_apps::transfer::{ITransferrable, ISendTransfer, ITokenAddress};
use starknet_ibc_core::channel::{Packet, Acknowledgement, IAppCallback};
use starknet_ibc_core::host::{PortId, ChannelId, ChannelIdTrait};
use starknet_ibc_utils::{ComputeKeyTrait, ValidateBasicTrait};
Expand Down Expand Up @@ -100,7 +100,7 @@ pub mod TokenTransferComponent {
}

#[generate_trait]
impl SendTransferInternalImpl<
pub(crate) impl SendTransferInternalImpl<
TContractState,
+HasComponent<TContractState>,
+ITransferrable<TContractState>,
Expand Down Expand Up @@ -199,7 +199,7 @@ pub mod TokenTransferComponent {
}

#[generate_trait]
impl RecvPacketInternalImpl<
pub(crate) impl RecvPacketInternalImpl<
TContractState,
+HasComponent<TContractState>,
+ITransferrable<TContractState>,
Expand Down Expand Up @@ -417,7 +417,7 @@ pub mod TokenTransferComponent {
}

#[generate_trait]
impl OwnerAssertionImpl<
pub(crate) impl OwnerAssertionImpl<
TContractState,
+HasComponent<TContractState>,
+Drop<TContractState>,
Expand All @@ -430,7 +430,7 @@ pub mod TokenTransferComponent {
}

#[generate_trait]
impl TransferInternalImpl<
pub(crate) impl TransferInternalImpl<
TContractState, +HasComponent<TContractState>, +Drop<TContractState>
> of TransferInternalTrait<TContractState> {
fn get_token(self: @ComponentState<TContractState>, token_key: felt252) -> ERC20Contract {
Expand Down Expand Up @@ -502,7 +502,7 @@ pub mod TokenTransferComponent {
}

#[generate_trait]
impl TransferReaderImpl<
pub(crate) impl TransferReaderImpl<
TContractState, +HasComponent<TContractState>, +Drop<TContractState>
> of TransferReaderTrait<TContractState> {
fn read_erc20_class_hash(self: @ComponentState<TContractState>) -> ClassHash {
Expand All @@ -527,7 +527,7 @@ pub mod TokenTransferComponent {
}

#[generate_trait]
impl TransferWriterImpl<
pub(crate) impl TransferWriterImpl<
TContractState, +HasComponent<TContractState>, +Drop<TContractState>
> of TransferWriterTrait<TContractState> {
fn write_erc20_class_hash(
Expand Down Expand Up @@ -558,7 +558,7 @@ pub mod TokenTransferComponent {
}

#[generate_trait]
impl TransferEventImpl<
pub(crate) impl TransferEventImpl<
TContractState, +HasComponent<TContractState>, +Drop<TContractState>
> of TransferEventTrait<TContractState> {
fn emit_send_event(ref self: ComponentState<TContractState>, packet_data: PacketData) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#[starknet::component]
pub mod TransferrableComponent {
use starknet_ibc_apps::transfer::TransferErrors;
use starknet_ibc_apps::transfer::interfaces::ITransferrable;
use starknet_ibc_apps::transfer::{TransferErrors, ITransferrable};

#[storage]
struct Storage {
Expand Down
7 changes: 0 additions & 7 deletions cairo-contracts/packages/apps/src/transfer/interfaces.cairo

This file was deleted.

Loading

0 comments on commit 661b02b

Please sign in to comment.