diff --git a/.changeset/chatty-mails-smell.md b/.changeset/chatty-mails-smell.md new file mode 100644 index 00000000..0f30e949 --- /dev/null +++ b/.changeset/chatty-mails-smell.md @@ -0,0 +1,5 @@ +--- +'@axelar-network/axelar-cgp-sui': minor +--- + +Add missing its events diff --git a/move/its/sources/events.move b/move/its/sources/events.move index 3f44911f..9a348669 100644 --- a/move/its/sources/events.move +++ b/move/its/sources/events.move @@ -1,7 +1,12 @@ module its::events; -use its::token_id::TokenId; +use axelar_gateway::bytes32::{Self, Bytes32}; +use its::token_id::{TokenId, UnregisteredTokenId}; +use std::ascii::String; +use std::string; +use sui::address; use sui::event; +use sui::hash::keccak256; // ----- // Types @@ -10,6 +15,39 @@ public struct CoinRegistered has copy, drop { token_id: TokenId, } +public struct InterchainTransfer has copy, drop { + token_id: TokenId, + source_address: address, + destination_chain: String, + destination_address: vector, + amount: u256, + data_hash: Bytes32, +} + +public struct InterchainTokenDeploymentStarted has copy, drop { + token_id: TokenId, + name: string::String, + symbol: String, + decimals: u8, + destination_chain: String, +} + +public struct InterchainTransferReceived has copy, drop { + message_id: String, + token_id: TokenId, + source_chain: String, + source_address: vector, + destination_address: address, + amount: u256, + data_hash: Bytes32, +} + +public struct UnregisteredCoinReceived has copy, drop { + token_id: UnregisteredTokenId, + symbol: String, + decimals: u8, +} + // ----------------- // Package Functions // ----------------- @@ -18,3 +56,71 @@ public(package) fun coin_registered(token_id: TokenId) { token_id, }); } + +public(package) fun interchain_transfer( + token_id: TokenId, + source_address: address, + destination_chain: String, + destination_address: vector, + amount: u256, + data: &vector, +) { + let data_hash = bytes32::new(address::from_bytes(keccak256(data))); + event::emit(InterchainTransfer { + token_id, + source_address, + destination_chain, + destination_address, + amount, + data_hash, + }); +} + +public(package) fun interchain_token_deployment_started( + token_id: TokenId, + name: string::String, + symbol: String, + decimals: u8, + destination_chain: String, +) { + event::emit(InterchainTokenDeploymentStarted { + token_id, + name, + symbol, + decimals, + destination_chain, + }); +} + +public(package) fun interchain_transfer_received( + message_id: String, + token_id: TokenId, + source_chain: String, + source_address: vector, + destination_address: address, + amount: u256, + data: &vector, +) { + let data_hash = bytes32::new(address::from_bytes(keccak256(data))); + event::emit(InterchainTransferReceived { + message_id, + token_id, + source_chain, + source_address, + destination_address, + amount, + data_hash, + }); +} + +public(package) fun unregistered_coin_received( + token_id: UnregisteredTokenId, + symbol: String, + decimals: u8, +) { + event::emit(UnregisteredCoinReceived { + token_id, + symbol, + decimals, + }); +} diff --git a/move/its/sources/types/address_tracker.move b/move/its/sources/types/address_tracker.move index 22473d59..78021402 100644 --- a/move/its/sources/types/address_tracker.move +++ b/move/its/sources/types/address_tracker.move @@ -9,11 +9,11 @@ use sui::table::{Self, Table}; // Errors // ------ #[error] -const ENoAddress: vector = b"attempt to borrow a trusted address but it's not registered."; +const ENoAddress: vector = b"attempt to borrow a trusted address but it's not registered"; #[error] -const EEmptyChainName: vector = b"empty trusted chain name is unsupported."; +const EEmptyChainName: vector = b"empty trusted chain name is unsupported"; #[error] -const EEmptyTrustedAddress: vector = b"empty trusted address is unsupported."; +const EEmptyTrustedAddress: vector = b"empty trusted address is unsupported"; /// The interchain address tracker stores the trusted addresses for each chain. public struct InterchainAddressTracker has store { diff --git a/move/its/sources/types/trusted_addresses.move b/move/its/sources/types/trusted_addresses.move index 40773a63..a1ab3581 100644 --- a/move/its/sources/types/trusted_addresses.move +++ b/move/its/sources/types/trusted_addresses.move @@ -9,7 +9,10 @@ public struct TrustedAddresses has copy, drop { trusted_addresses: vector, } -public fun new(trusted_chains: vector, trusted_addresses: vector): TrustedAddresses { +public fun new( + trusted_chains: vector, + trusted_addresses: vector, +): TrustedAddresses { let length = trusted_chains.length(); assert!(length == trusted_addresses.length(), EMalformedTrustedAddresses); @@ -20,9 +23,7 @@ public fun new(trusted_chains: vector, trusted_addresses: vector } } -public fun destroy( - self: TrustedAddresses, -): (vector, vector) { +public fun destroy(self: TrustedAddresses): (vector, vector) { let TrustedAddresses { trusted_chains, trusted_addresses } = self; (trusted_chains, trusted_addresses) } diff --git a/move/its/sources/versioned/its_v0.move b/move/its/sources/versioned/its_v0.move index 785ecbd8..f4580a71 100644 --- a/move/its/sources/versioned/its_v0.move +++ b/move/its/sources/versioned/its_v0.move @@ -30,37 +30,37 @@ use version_control::version_control::VersionControl; // ------ #[error] const EUnregisteredCoin: vector = - b"Trying to find a coin that doesn't exist."; + b"trying to find a coin that doesn't exist"; #[error] const EUntrustedAddress: vector = - b"the sender that sent this message is not trusted."; + b"the sender that sent this message is not trusted"; #[error] const EInvalidMessageType: vector = - b"the message type received is not supported."; + b"the message type received is not supported"; #[error] const EWrongDestination: vector = - b"the channel trying to receive this call is not the destination."; + b"the channel trying to receive this call is not the destination"; #[error] const EInterchainTransferHasData: vector = - b"interchain transfer with data trying to be processed as an interchain transfer."; + b"interchain transfer with data trying to be processed as an interchain transfer"; #[error] const EInterchainTransferHasNoData: vector = b"interchain transfer trying to be proccessed as an interchain transfer"; #[error] const EModuleNameDoesNotMatchSymbol: vector = - b"the module name does not match the symbol."; + b"the module name does not match the symbol"; #[error] -const ENotDistributor: vector = b"only the distributor can mint."; +const ENotDistributor: vector = b"only the distributor can mint"; #[error] const ENonZeroTotalSupply: vector = - b"trying to give a token that has had some supply already minted."; + b"trying to give a token that has had some supply already minted"; #[error] const EUnregisteredCoinHasUrl: vector = - b"the interchain token that is being registered has a URL."; + b"the interchain token that is being registered has a URL"; #[error] -const EUntrustedChain: vector = b"the chain is not trusted."; +const EUntrustedChain: vector = b"the chain is not trusted"; #[error] -const ENewerTicket: vector = b"cannot proccess newer tickets."; +const ENewerTicket: vector = b"cannot proccess newer tickets"; // === MESSAGE TYPES === const MESSAGE_TYPE_INTERCHAIN_TRANSFER: u256 = 0; @@ -72,7 +72,7 @@ const MESSAGE_TYPE_RECEIVE_FROM_HUB: u256 = 4; // === HUB CONSTANTS === // Chain name for Axelar. This is used for routing ITS calls via ITS hub on // Axelar. -const ITS_HUB_CHAIN_NAME: vector = b"Axelarnet"; +const ITS_HUB_CHAIN_NAME: vector = b"axelarnet"; // Identifier to be used as destination address for chains that route to hub. // For Sui this will probably be every supported chain. const ITS_HUB_ROUTING_IDENTIFIER: vector = b"hub"; @@ -247,6 +247,14 @@ public(package) fun deploy_remote_interchain_token( .write_u256((decimals as u256)) .write_bytes(vector::empty()); + events::interchain_token_deployment_started( + token_id, + name, + symbol, + decimals, + destination_chain, + ); + prepare_message(self, destination_chain, writer.into_bytes()) } @@ -281,6 +289,15 @@ public(package) fun send_interchain_transfer( .write_u256(amount) .write_bytes(data); + events::interchain_transfer( + token_id, + source_address, + destination_chain, + destination_address, + amount, + &data, + ); + self.prepare_message(destination_chain, writer.into_bytes()) } @@ -290,7 +307,9 @@ public(package) fun receive_interchain_transfer( clock: &Clock, ctx: &mut TxContext, ) { - let (_, payload) = self.decode_approved_message(approved_message); + let (source_chain, payload, message_id) = self.decode_approved_message( + approved_message, + ); let mut reader = abi::new_reader(payload); assert!( reader.read_u256() == MESSAGE_TYPE_INTERCHAIN_TRANSFER, @@ -298,7 +317,7 @@ public(package) fun receive_interchain_transfer( ); let token_id = token_id::from_u256(reader.read_u256()); - reader.skip_slot(); // skip source_address + let source_address = reader.read_bytes(); let destination_address = address::from_bytes(reader.read_bytes()); let amount = reader.read_u256(); let data = reader.read_bytes(); @@ -309,7 +328,17 @@ public(package) fun receive_interchain_transfer( .coin_management_mut(token_id) .give_coin(amount, clock, ctx); - transfer::public_transfer(coin, destination_address) + transfer::public_transfer(coin, destination_address); + + events::interchain_transfer_received( + message_id, + token_id, + source_chain, + source_address, + destination_address, + amount, + &b"", + ); } public(package) fun receive_interchain_transfer_with_data( @@ -319,7 +348,7 @@ public(package) fun receive_interchain_transfer_with_data( clock: &Clock, ctx: &mut TxContext, ): (String, vector, vector, Coin) { - let (source_chain, payload) = self.decode_approved_message( + let (source_chain, payload, message_id) = self.decode_approved_message( approved_message, ); let mut reader = abi::new_reader(payload); @@ -331,18 +360,25 @@ public(package) fun receive_interchain_transfer_with_data( let token_id = token_id::from_u256(reader.read_u256()); let source_address = reader.read_bytes(); - let destination_address = reader.read_bytes(); + let destination_address = address::from_bytes(reader.read_bytes()); let amount = reader.read_u256(); let data = reader.read_bytes(); - assert!( - address::from_bytes(destination_address) == channel.to_address(), - EWrongDestination, - ); + assert!(destination_address == channel.to_address(), EWrongDestination); assert!(!data.is_empty(), EInterchainTransferHasNoData); let coin = self.coin_management_mut(token_id).give_coin(amount, clock, ctx); + events::interchain_transfer_received( + message_id, + token_id, + source_chain, + source_address, + destination_address, + amount, + &data, + ); + (source_chain, source_address, data, coin) } @@ -350,7 +386,7 @@ public(package) fun receive_deploy_interchain_token( self: &mut ITS_v0, approved_message: ApprovedMessage, ) { - let (_, payload) = self.decode_approved_message(approved_message); + let (_, payload, _) = self.decode_approved_message(approved_message); let mut reader = abi::new_reader(payload); assert!( reader.read_u256() == MESSAGE_TYPE_DEPLOY_INTERCHAIN_TOKEN, @@ -406,6 +442,12 @@ public(package) fun give_unregistered_coin( let token_id = token_id::unregistered_token_id(&symbol, decimals); self.add_unregistered_coin(token_id, treasury_cap, coin_metadata); + + events::unregistered_coin_received( + token_id, + symbol, + decimals, + ); } public(package) fun mint_as_distributor( @@ -605,8 +647,8 @@ fun prepare_message( fun decode_approved_message( self: &ITS_v0, approved_message: ApprovedMessage, -): (String, vector) { - let (mut source_chain, _, source_address, mut payload) = self +): (String, vector, String) { + let (mut source_chain, message_id, source_address, mut payload) = self .channel .consume_approved_message(approved_message); @@ -636,7 +678,7 @@ fun decode_approved_message( ); }; - (source_chain, payload) + (source_chain, payload, message_id) } // --------- // Test Only