diff --git a/src/tests/account/test_account.cairo b/src/tests/account/test_account.cairo index 2ca9550a8..cef5a31e3 100644 --- a/src/tests/account/test_account.cairo +++ b/src/tests/account/test_account.cairo @@ -101,7 +101,7 @@ fn test_constructor() { let mut state = STATE(); Account::constructor(ref state, PUBLIC_KEY); - let event = testing::pop_log::(ZERO()).unwrap(); + let event = utils::pop_log::(ZERO()).unwrap(); assert(event.new_owner_guid == PUBLIC_KEY, 'Invalid owner key'); utils::assert_no_events_left(ZERO()); @@ -447,10 +447,10 @@ fn test_public_key_setter_and_getter() { // Set key PublicKeyImpl::set_public_key(ref state, NEW_PUBKEY); - let event = testing::pop_log::(ACCOUNT_ADDRESS()).unwrap(); + let event = utils::pop_log::(ACCOUNT_ADDRESS()).unwrap(); assert(event.removed_owner_guid == 0, 'Invalid old owner key'); - let event = testing::pop_log::(ACCOUNT_ADDRESS()).unwrap(); + let event = utils::pop_log::(ACCOUNT_ADDRESS()).unwrap(); assert(event.new_owner_guid == NEW_PUBKEY, 'Invalid new owner key'); utils::assert_no_events_left(ACCOUNT_ADDRESS()); @@ -488,10 +488,10 @@ fn test_public_key_setter_and_getter_camel() { // Set key PublicKeyCamelImpl::setPublicKey(ref state, NEW_PUBKEY); - let event = testing::pop_log::(ACCOUNT_ADDRESS()).unwrap(); + let event = utils::pop_log::(ACCOUNT_ADDRESS()).unwrap(); assert(event.removed_owner_guid == 0, 'Invalid old owner key'); - let event = testing::pop_log::(ACCOUNT_ADDRESS()).unwrap(); + let event = utils::pop_log::(ACCOUNT_ADDRESS()).unwrap(); assert(event.new_owner_guid == NEW_PUBKEY, 'Invalid new owner key'); utils::assert_no_events_left(ACCOUNT_ADDRESS()); @@ -521,7 +521,7 @@ fn test_initializer() { let mut state = STATE(); Account::InternalImpl::initializer(ref state, PUBLIC_KEY); - let event = testing::pop_log::(ZERO()).unwrap(); + let event = utils::pop_log::(ZERO()).unwrap(); assert(event.new_owner_guid == PUBLIC_KEY, 'Invalid owner key'); utils::assert_no_events_left(ZERO()); @@ -577,7 +577,7 @@ fn test__set_public_key() { let mut state = STATE(); Account::InternalImpl::_set_public_key(ref state, PUBLIC_KEY); - let event = testing::pop_log::(ZERO()).unwrap(); + let event = utils::pop_log::(ZERO()).unwrap(); assert(event.new_owner_guid == PUBLIC_KEY, 'Invalid owner key'); utils::assert_no_events_left(ZERO()); diff --git a/src/tests/token/test_erc20.cairo b/src/tests/token/test_erc20.cairo index 6ff440859..73f4034a3 100644 --- a/src/tests/token/test_erc20.cairo +++ b/src/tests/token/test_erc20.cairo @@ -9,6 +9,7 @@ use openzeppelin::token::erc20::ERC20::ERC20Impl; use openzeppelin::token::erc20::ERC20::InternalImpl; use openzeppelin::token::erc20::ERC20::Transfer; use openzeppelin::token::erc20::ERC20; +use openzeppelin::utils::serde::SerializedAppend; use starknet::ContractAddress; use starknet::contract_address_const; use starknet::testing; @@ -597,6 +598,12 @@ fn assert_event_approval(owner: ContractAddress, spender: ContractAddress, value assert(event.owner == owner, 'Invalid `owner`'); assert(event.spender == spender, 'Invalid `spender`'); assert(event.value == value, 'Invalid `value`'); + + // Check indexed keys + let mut indexed_keys = array![]; + indexed_keys.append_serde(owner); + indexed_keys.append_serde(spender); + utils::assert_indexed_keys(event, indexed_keys.span()) } fn assert_only_event_approval(owner: ContractAddress, spender: ContractAddress, value: u256) { @@ -609,6 +616,12 @@ fn assert_event_transfer(from: ContractAddress, to: ContractAddress, value: u256 assert(event.from == from, 'Invalid `from`'); assert(event.to == to, 'Invalid `to`'); assert(event.value == value, 'Invalid `value`'); + + // Check indexed keys + let mut indexed_keys = array![]; + indexed_keys.append_serde(from); + indexed_keys.append_serde(to); + utils::assert_indexed_keys(event, indexed_keys.span()); } fn assert_only_event_transfer(from: ContractAddress, to: ContractAddress, value: u256) { diff --git a/src/tests/token/test_erc721.cairo b/src/tests/token/test_erc721.cairo index 4299928f9..c0eb59bea 100644 --- a/src/tests/token/test_erc721.cairo +++ b/src/tests/token/test_erc721.cairo @@ -20,6 +20,7 @@ use openzeppelin::token::erc721::ERC721::{ }; use openzeppelin::token::erc721::ERC721; use openzeppelin::token::erc721; +use openzeppelin::utils::serde::SerializedAppend; use starknet::contract_address_const; use starknet::ContractAddress; use starknet::testing; @@ -1389,6 +1390,12 @@ fn assert_event_approval_for_all( assert(event.operator == operator, 'Invalid `operator`'); assert(event.approved == approved, 'Invalid `approved`'); utils::assert_no_events_left(ZERO()); + + // Check indexed keys + let mut indexed_keys = array![]; + indexed_keys.append_serde(owner); + indexed_keys.append_serde(operator); + utils::assert_indexed_keys(event, indexed_keys.span()); } fn assert_event_approval(owner: ContractAddress, approved: ContractAddress, token_id: u256) { @@ -1397,6 +1404,13 @@ fn assert_event_approval(owner: ContractAddress, approved: ContractAddress, toke assert(event.approved == approved, 'Invalid `approved`'); assert(event.token_id == token_id, 'Invalid `token_id`'); utils::assert_no_events_left(ZERO()); + + // Check indexed keys + let mut indexed_keys = array![]; + indexed_keys.append_serde(owner); + indexed_keys.append_serde(approved); + indexed_keys.append_serde(token_id); + utils::assert_indexed_keys(event, indexed_keys.span()); } fn assert_event_transfer(from: ContractAddress, to: ContractAddress, token_id: u256) { @@ -1405,4 +1419,11 @@ fn assert_event_transfer(from: ContractAddress, to: ContractAddress, token_id: u assert(event.to == to, 'Invalid `to`'); assert(event.token_id == token_id, 'Invalid `token_id`'); utils::assert_no_events_left(ZERO()); + + // Check indexed keys + let mut indexed_keys = array![]; + indexed_keys.append_serde(from); + indexed_keys.append_serde(to); + indexed_keys.append_serde(token_id); + utils::assert_indexed_keys(event, indexed_keys.span()); } diff --git a/src/tests/upgrades/test_upgradeable.cairo b/src/tests/upgrades/test_upgradeable.cairo index c43f8518f..fff1d8ed6 100644 --- a/src/tests/upgrades/test_upgradeable.cairo +++ b/src/tests/upgrades/test_upgradeable.cairo @@ -10,7 +10,6 @@ use openzeppelin::upgrades::upgradeable::Upgradeable::Upgraded; use starknet::ClassHash; use starknet::ContractAddress; use starknet::Felt252TryIntoClassHash; -use starknet::testing; const VALUE: felt252 = 123; @@ -46,7 +45,7 @@ fn test_upgraded_event() { let v1 = deploy_v1(); v1.upgrade(V2_CLASS_HASH()); - let event = testing::pop_log::(v1.contract_address).unwrap(); + let event = utils::pop_log::(v1.contract_address).unwrap(); assert(event.class_hash == V2_CLASS_HASH(), 'Invalid class hash'); } diff --git a/src/tests/utils.cairo b/src/tests/utils.cairo index e0ebeacb3..74ce5893a 100644 --- a/src/tests/utils.cairo +++ b/src/tests/utils.cairo @@ -18,16 +18,35 @@ fn deploy(contract_class_hash: felt252, calldata: Array) -> ContractAdd /// Pop the earliest unpopped logged event for the contract as the requested type /// and checks there's no more data left on the event, preventing unaccounted params. -/// Indexed event members are currently not supported, so they are ignored. +/// This function also removes the first key from the event. This is because indexed +/// params are set as event keys, but the first event key is always set as the +/// event ID. fn pop_log, impl TEvent: starknet::Event>( address: ContractAddress ) -> Option { let (mut keys, mut data) = testing::pop_log_raw(address)?; + + // Remove the event ID from the keys + keys.pop_front(); + let ret = starknet::Event::deserialize(ref keys, ref data); assert(data.is_empty(), 'Event has extra data'); ret } +/// Asserts that `expected_keys` exactly matches the indexed keys from `event`. +/// `expected_keys` must include all indexed event keys for `event` in the order +/// that they're defined. +fn assert_indexed_keys, impl TEvent: starknet::Event>( + event: T, expected_keys: Span +) { + let mut keys = array![]; + let mut data = array![]; + + event.append_keys_and_data(ref keys, ref data); + assert(expected_keys == keys.span(), 'Invalid keys'); +} + fn assert_no_events_left(address: ContractAddress) { assert(testing::pop_log_raw(address).is_none(), 'Events remaining on queue'); } diff --git a/src/token/erc20/erc20.cairo b/src/token/erc20/erc20.cairo index c62cd3803..ee1204d36 100644 --- a/src/token/erc20/erc20.cairo +++ b/src/token/erc20/erc20.cairo @@ -27,14 +27,18 @@ mod ERC20 { #[derive(Drop, starknet::Event)] struct Transfer { + #[key] from: ContractAddress, + #[key] to: ContractAddress, value: u256 } #[derive(Drop, starknet::Event)] struct Approval { + #[key] owner: ContractAddress, + #[key] spender: ContractAddress, value: u256 } diff --git a/src/token/erc721/erc721.cairo b/src/token/erc721/erc721.cairo index d67952f2d..8572f50c8 100644 --- a/src/token/erc721/erc721.cairo +++ b/src/token/erc721/erc721.cairo @@ -37,21 +37,29 @@ mod ERC721 { #[derive(Drop, starknet::Event)] struct Transfer { + #[key] from: ContractAddress, + #[key] to: ContractAddress, + #[key] token_id: u256 } #[derive(Drop, starknet::Event)] struct Approval { + #[key] owner: ContractAddress, + #[key] approved: ContractAddress, + #[key] token_id: u256 } #[derive(Drop, starknet::Event)] struct ApprovalForAll { + #[key] owner: ContractAddress, + #[key] operator: ContractAddress, approved: bool }