Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(its)!: add missing its events #176

Merged
merged 14 commits into from
Oct 11, 2024
5 changes: 5 additions & 0 deletions .changeset/chatty-mails-smell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@axelar-network/axelar-cgp-sui': minor
---

Add missing its events
108 changes: 107 additions & 1 deletion move/its/sources/events.move
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -10,6 +15,39 @@ public struct CoinRegistered<phantom T> has copy, drop {
token_id: TokenId,
}

public struct InterchainTransfer<phantom T> has copy, drop {
token_id: TokenId,
source_address: address,
destination_chain: String,
destination_address: vector<u8>,
amount: u256,
data_hash: Bytes32,
}

public struct InterchainTokenDeploymentStarted<phantom T> has copy, drop {
token_id: TokenId,
name: string::String,
symbol: String,
decimals: u8,
destination_chain: String,
}

public struct InterchainTransferReceived<phantom T> has copy, drop {
message_id: String,
token_id: TokenId,
source_chain: String,
source_address: vector<u8>,
destination_address: address,
amount: u256,
data_hash: Bytes32,
}

public struct UnregisteredCoinReceived<phantom T> has copy, drop {
token_id: UnregisteredTokenId,
symbol: String,
decimals: u8,
}

// -----------------
// Package Functions
// -----------------
Expand All @@ -18,3 +56,71 @@ public(package) fun coin_registered<T>(token_id: TokenId) {
token_id,
});
}

public(package) fun interchain_transfer<T>(
token_id: TokenId,
source_address: address,
destination_chain: String,
destination_address: vector<u8>,
amount: u256,
data: &vector<u8>,
) {
let data_hash = bytes32::new(address::from_bytes(keccak256(data)));
event::emit(InterchainTransfer<T> {
token_id,
source_address,
destination_chain,
destination_address,
amount,
data_hash,
});
}

public(package) fun interchain_token_deployment_started<T>(
token_id: TokenId,
name: string::String,
symbol: String,
decimals: u8,
destination_chain: String,
) {
event::emit(InterchainTokenDeploymentStarted<T> {
token_id,
name,
symbol,
decimals,
destination_chain,
});
}

public(package) fun interchain_transfer_received<T>(
message_id: String,
token_id: TokenId,
source_chain: String,
source_address: vector<u8>,
destination_address: address,
amount: u256,
data: &vector<u8>,
) {
let data_hash = bytes32::new(address::from_bytes(keccak256(data)));
event::emit(InterchainTransferReceived<T> {
message_id,
token_id,
source_chain,
source_address,
destination_address,
amount,
data_hash,
});
}

public(package) fun unregistered_coin_received<T>(
token_id: UnregisteredTokenId,
symbol: String,
decimals: u8,
) {
event::emit(UnregisteredCoinReceived<T> {
token_id,
symbol,
decimals,
});
}
6 changes: 3 additions & 3 deletions move/its/sources/types/address_tracker.move
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ use sui::table::{Self, Table};
// Errors
// ------
#[error]
const ENoAddress: vector<u8> = b"attempt to borrow a trusted address but it's not registered.";
const ENoAddress: vector<u8> = b"attempt to borrow a trusted address but it's not registered";
#[error]
const EEmptyChainName: vector<u8> = b"empty trusted chain name is unsupported.";
const EEmptyChainName: vector<u8> = b"empty trusted chain name is unsupported";
#[error]
const EEmptyTrustedAddress: vector<u8> = b"empty trusted address is unsupported.";
const EEmptyTrustedAddress: vector<u8> = b"empty trusted address is unsupported";

/// The interchain address tracker stores the trusted addresses for each chain.
public struct InterchainAddressTracker has store {
Expand Down
9 changes: 5 additions & 4 deletions move/its/sources/types/trusted_addresses.move
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ public struct TrustedAddresses has copy, drop {
trusted_addresses: vector<String>,
}

public fun new(trusted_chains: vector<String>, trusted_addresses: vector<String>): TrustedAddresses {
public fun new(
trusted_chains: vector<String>,
trusted_addresses: vector<String>,
): TrustedAddresses {
let length = trusted_chains.length();

assert!(length == trusted_addresses.length(), EMalformedTrustedAddresses);
Expand All @@ -20,9 +23,7 @@ public fun new(trusted_chains: vector<String>, trusted_addresses: vector<String>
}
}

public fun destroy(
self: TrustedAddresses,
): (vector<String>, vector<String>) {
public fun destroy(self: TrustedAddresses): (vector<String>, vector<String>) {
let TrustedAddresses { trusted_chains, trusted_addresses } = self;
(trusted_chains, trusted_addresses)
}
92 changes: 67 additions & 25 deletions move/its/sources/versioned/its_v0.move
Original file line number Diff line number Diff line change
Expand Up @@ -30,37 +30,37 @@ use version_control::version_control::VersionControl;
// ------
#[error]
const EUnregisteredCoin: vector<u8> =
b"Trying to find a coin that doesn't exist.";
b"trying to find a coin that doesn't exist";
#[error]
const EUntrustedAddress: vector<u8> =
b"the sender that sent this message is not trusted.";
b"the sender that sent this message is not trusted";
#[error]
const EInvalidMessageType: vector<u8> =
b"the message type received is not supported.";
b"the message type received is not supported";
#[error]
const EWrongDestination: vector<u8> =
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<u8> =
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<u8> =
b"interchain transfer trying to be proccessed as an interchain transfer";
#[error]
const EModuleNameDoesNotMatchSymbol: vector<u8> =
b"the module name does not match the symbol.";
b"the module name does not match the symbol";
#[error]
const ENotDistributor: vector<u8> = b"only the distributor can mint.";
const ENotDistributor: vector<u8> = b"only the distributor can mint";
#[error]
const ENonZeroTotalSupply: vector<u8> =
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<u8> =
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<u8> = b"the chain is not trusted.";
const EUntrustedChain: vector<u8> = b"the chain is not trusted";
#[error]
const ENewerTicket: vector<u8> = b"cannot proccess newer tickets.";
const ENewerTicket: vector<u8> = b"cannot proccess newer tickets";

// === MESSAGE TYPES ===
const MESSAGE_TYPE_INTERCHAIN_TRANSFER: u256 = 0;
Expand All @@ -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<u8> = b"Axelarnet";
const ITS_HUB_CHAIN_NAME: vector<u8> = 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<u8> = b"hub";
Expand Down Expand Up @@ -247,6 +247,14 @@ public(package) fun deploy_remote_interchain_token<T>(
.write_u256((decimals as u256))
.write_bytes(vector::empty());

events::interchain_token_deployment_started<T>(
token_id,
name,
symbol,
decimals,
destination_chain,
);

prepare_message(self, destination_chain, writer.into_bytes())
}

Expand Down Expand Up @@ -281,6 +289,15 @@ public(package) fun send_interchain_transfer<T>(
.write_u256(amount)
.write_bytes(data);

events::interchain_transfer<T>(
token_id,
source_address,
destination_chain,
destination_address,
amount,
&data,
);

self.prepare_message(destination_chain, writer.into_bytes())
}

Expand All @@ -290,15 +307,17 @@ public(package) fun receive_interchain_transfer<T>(
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,
EInvalidMessageType,
);

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();
Expand All @@ -309,7 +328,17 @@ public(package) fun receive_interchain_transfer<T>(
.coin_management_mut(token_id)
.give_coin<T>(amount, clock, ctx);

transfer::public_transfer(coin, destination_address)
transfer::public_transfer(coin, destination_address);

events::interchain_transfer_received<T>(
message_id,
token_id,
source_chain,
source_address,
destination_address,
amount,
&b"",
);
}

public(package) fun receive_interchain_transfer_with_data<T>(
Expand All @@ -319,7 +348,7 @@ public(package) fun receive_interchain_transfer_with_data<T>(
clock: &Clock,
ctx: &mut TxContext,
): (String, vector<u8>, vector<u8>, Coin<T>) {
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);
Expand All @@ -331,26 +360,33 @@ public(package) fun receive_interchain_transfer_with_data<T>(
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<T>(
message_id,
token_id,
source_chain,
source_address,
destination_address,
amount,
&data,
);

(source_chain, source_address, data, coin)
}

public(package) fun receive_deploy_interchain_token<T>(
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,
Expand Down Expand Up @@ -406,6 +442,12 @@ public(package) fun give_unregistered_coin<T>(
let token_id = token_id::unregistered_token_id(&symbol, decimals);

self.add_unregistered_coin<T>(token_id, treasury_cap, coin_metadata);

events::unregistered_coin_received<T>(
token_id,
symbol,
decimals,
);
}

public(package) fun mint_as_distributor<T>(
Expand Down Expand Up @@ -605,8 +647,8 @@ fun prepare_message(
fun decode_approved_message(
self: &ITS_v0,
approved_message: ApprovedMessage,
): (String, vector<u8>) {
let (mut source_chain, _, source_address, mut payload) = self
): (String, vector<u8>, String) {
let (mut source_chain, message_id, source_address, mut payload) = self
.channel
.consume_approved_message(approved_message);

Expand Down Expand Up @@ -636,7 +678,7 @@ fun decode_approved_message(
);
};

(source_chain, payload)
(source_chain, payload, message_id)
}
// ---------
// Test Only
Expand Down