diff --git a/apps/blockchain/starknet/src/bridge.cairo b/apps/blockchain/starknet/src/bridge.cairo index 23cbf8af..0b734875 100644 --- a/apps/blockchain/starknet/src/bridge.cairo +++ b/apps/blockchain/starknet/src/bridge.cairo @@ -24,12 +24,9 @@ mod bridge { IStarklaneCollectionAdmin}; // events use starklane::interfaces::{ - DepositRequestInitiated, - WithdrawRequestCompleted, - CollectionDeployedFromL1, - ReplacedClassHash, - BridgeEnabled, - CollectionWhiteListUpdated, + DepositRequestInitiated, WithdrawRequestCompleted, CollectionDeployedFromL1, + ReplacedClassHash, BridgeEnabled, CollectionWhiteListUpdated, WhiteListEnabled, + BridgeL1AddressUpdated, ERC721ClassHashUpdated, L1L2CollectionMappingUpdated }; use starklane::request::{ @@ -110,6 +107,10 @@ mod bridge { ReplacedClassHash: ReplacedClassHash, BridgeEnabled: BridgeEnabled, CollectionWhiteListUpdated: CollectionWhiteListUpdated, + WhiteListEnabled: WhiteListEnabled, + BridgeL1AddressUpdated: BridgeL1AddressUpdated, + ERC721ClassHashUpdated: ERC721ClassHashUpdated, + L1L2CollectionMappingUpdated: L1L2CollectionMappingUpdated, #[flat] OwnableEvent: OwnableComponent::Event, } @@ -211,6 +212,7 @@ mod bridge { fn set_bridge_l1_addr(ref self: ContractState, address: EthAddress) { ensure_is_admin(@self); self.bridge_l1_address.write(address); + self.emit(BridgeL1AddressUpdated { address }); } fn get_bridge_l1_addr(self: @ContractState) -> EthAddress { @@ -220,6 +222,7 @@ mod bridge { fn set_erc721_class_hash(ref self: ContractState, class_hash: ClassHash) { ensure_is_admin(@self); self.erc721_bridgeable_class.write(class_hash); + self.emit(ERC721ClassHashUpdated { class_hash }); } fn get_erc721_class_hash(self: @ContractState) -> ClassHash { @@ -308,6 +311,7 @@ mod bridge { fn enable_white_list(ref self: ContractState, enable: bool) { ensure_is_admin(@self); self.white_list_enabled.write(enable); + self.emit(WhiteListEnabled { enabled: enable }); } fn is_white_list_enabled(self: @ContractState) -> bool { @@ -361,6 +365,7 @@ mod bridge { ensure_is_admin(@self); self.l1_to_l2_addresses.write(collection_l1, collection_l2); self.l2_to_l1_addresses.write(collection_l2, collection_l1); + self.emit(L1L2CollectionMappingUpdated { collection_l1, collection_l2 }); } } diff --git a/apps/blockchain/starknet/src/interfaces.cairo b/apps/blockchain/starknet/src/interfaces.cairo index 33264712..0302a9ab 100644 --- a/apps/blockchain/starknet/src/interfaces.cairo +++ b/apps/blockchain/starknet/src/interfaces.cairo @@ -106,4 +106,21 @@ struct CollectionWhiteListUpdated { #[key] collection: ContractAddress, enabled: bool, -} \ No newline at end of file +} + +#[derive(Drop, starknet::Event)] +struct WhiteListEnabled { + enabled: bool, +} + +#[derive(Drop, starknet::Event)] +struct BridgeL1AddressUpdated { + #[key] + address: EthAddress, +} + +#[derive(Drop, starknet::Event)] +struct ERC721ClassHashUpdated { + #[key] + class_hash: ClassHash, +} diff --git a/apps/blockchain/starknet/src/tests/bridge_t.cairo b/apps/blockchain/starknet/src/tests/bridge_t.cairo index c7d1043b..cafde030 100644 --- a/apps/blockchain/starknet/src/tests/bridge_t.cairo +++ b/apps/blockchain/starknet/src/tests/bridge_t.cairo @@ -21,7 +21,7 @@ mod tests { IOwnableTwoStepDispatcher, IOwnableTwoStepDispatcherTrait }; - use starknet::{ContractAddress, ClassHash, EthAddress}; + use starknet::{ContractAddress, ClassHash, EthAddress, class_hash_const}; use starklane::{ request::{Request, compute_request_hash}, interfaces::{IStarklaneDispatcher, IStarklaneDispatcherTrait, @@ -783,7 +783,7 @@ mod tests { let collection1 = starknet::contract_address_const::<'collection1'>(); let collection2 = starknet::contract_address_const::<'collection2'>(); - let collection3 = starknet::contract_address_const::<'collection3'>(); + let _collection3 = starknet::contract_address_const::<'collection3'>(); start_prank(CheatTarget::One(bridge_address), BRIDGE_ADMIN); bridge.enable_white_list(true); stop_prank(CheatTarget::One(bridge_address)); @@ -1080,4 +1080,138 @@ mod tests { stop_prank(CheatTarget::One(bridge_address)); } + #[test] + fn enable_white_list() { + let erc721b_contract_class = declare("erc721_bridgeable"); + + let BRIDGE_ADMIN = starknet::contract_address_const::<'starklane'>(); + let BRIDGE_L1 = EthAddress { address: 'starklane_l1' }; + + let bridge_address = deploy_starklane(BRIDGE_ADMIN, BRIDGE_L1, erc721b_contract_class.class_hash); + let bridge = IStarklaneDispatcher { contract_address: bridge_address }; + + assert_eq!(bridge.is_white_list_enabled(), false); + + let mut spy = spy_events(SpyOn::One(bridge_address)); + start_prank(CheatTarget::One(bridge_address), BRIDGE_ADMIN); + bridge.enable_white_list(true); + stop_prank(CheatTarget::One(bridge_address)); + spy.assert_emitted(@array![ + ( + bridge_address, + bridge::Event::WhiteListEnabled( + bridge::WhiteListEnabled { + enabled: true, + } + ) + ) + ]); + + assert_eq!(bridge.is_white_list_enabled(), true); + } + + #[test] + fn set_bridge_l1_addr() { + let erc721b_contract_class = declare("erc721_bridgeable"); + + let BRIDGE_ADMIN = starknet::contract_address_const::<'starklane'>(); + let BRIDGE_L1 = EthAddress { address: 'starklane_l1' }; + let NEW_BRIDGE_L1 = EthAddress { address: 'new_starklane_l1' }; + + let bridge_address = deploy_starklane(BRIDGE_ADMIN, BRIDGE_L1, erc721b_contract_class.class_hash); + let bridge = IStarklaneDispatcher { contract_address: bridge_address }; + + assert_eq!(bridge.get_bridge_l1_addr(), BRIDGE_L1); + + let mut spy = spy_events(SpyOn::One(bridge_address)); + start_prank(CheatTarget::One(bridge_address), BRIDGE_ADMIN); + bridge.set_bridge_l1_addr(NEW_BRIDGE_L1); + stop_prank(CheatTarget::One(bridge_address)); + spy.assert_emitted(@array![ + ( + bridge_address, + bridge::Event::BridgeL1AddressUpdated( + bridge::BridgeL1AddressUpdated { + address: NEW_BRIDGE_L1, + } + ) + ) + ]); + + assert_eq!(bridge.get_bridge_l1_addr(), NEW_BRIDGE_L1); + } + + #[test] + fn set_erc721_class_hash() { + let erc721b_contract_class = declare("erc721_bridgeable"); + + let BRIDGE_ADMIN = starknet::contract_address_const::<'starklane'>(); + let BRIDGE_L1 = EthAddress { address: 'starklane_l1' }; + let ERC721_CLASS_HASH = class_hash_const::<'ERC721_CLASS_HASH'>(); + + let bridge_address = deploy_starklane(BRIDGE_ADMIN, BRIDGE_L1, erc721b_contract_class.class_hash); + let bridge = IStarklaneDispatcher { contract_address: bridge_address }; + + assert_eq!(bridge.get_erc721_class_hash(), erc721b_contract_class.class_hash); + + let mut spy = spy_events(SpyOn::One(bridge_address)); + start_prank(CheatTarget::One(bridge_address), BRIDGE_ADMIN); + bridge.set_erc721_class_hash(ERC721_CLASS_HASH); + stop_prank(CheatTarget::One(bridge_address)); + spy.assert_emitted(@array![ + ( + bridge_address, + bridge::Event::ERC721ClassHashUpdated( + bridge::ERC721ClassHashUpdated { + class_hash: ERC721_CLASS_HASH, + } + ) + ) + ]); + + assert_eq!(bridge.get_erc721_class_hash(), ERC721_CLASS_HASH); + } + + #[test] + fn set_l1_l2_collection_mapping() { + let erc721b_contract_class = declare("erc721_bridgeable"); + + let BRIDGE_ADMIN = starknet::contract_address_const::<'starklane'>(); + let BRIDGE_L1 = EthAddress { address: 'starklane_l1' }; + let COLLECTION_OWNER = starknet::contract_address_const::<'collection owner'>(); + + let bridge_address = deploy_starklane(BRIDGE_ADMIN, BRIDGE_L1, erc721b_contract_class.class_hash); + let bridge = IStarklaneDispatcher { contract_address: bridge_address }; + + let collection_l1 = EthAddress { address: 0x4269}; + + let erc721b_address = deploy_erc721b( + erc721b_contract_class, + "everai", + "DUO", + bridge_address, + COLLECTION_OWNER + ); + + assert_eq!(bridge.get_erc721_class_hash(), erc721b_contract_class.class_hash); + + let mut spy = spy_events(SpyOn::One(bridge_address)); + start_prank(CheatTarget::One(bridge_address), BRIDGE_ADMIN); + bridge.set_l1_l2_collection_mapping(collection_l1, erc721b_address); + stop_prank(CheatTarget::One(bridge_address)); + spy.assert_emitted(@array![ + ( + bridge_address, + bridge::Event::L1L2CollectionMappingUpdated( + bridge::L1L2CollectionMappingUpdated { + collection_l1, + collection_l2: erc721b_address + } + ) + ) + ]); + + assert_eq!(bridge.get_l1_collection_address(erc721b_address), collection_l1); + assert_eq!(bridge.get_l2_collection_address(collection_l1), erc721b_address); + } }