From 0ae209ba817612fd99efdca61a4f0d743ffbf63f Mon Sep 17 00:00:00 2001 From: Milap Sheth Date: Sat, 11 May 2024 04:56:58 -0400 Subject: [PATCH 1/4] fix: lint issues --- move/axelar/sources/utils.move | 6 ++-- move/squid/sources/squid/deepbook_v2.move | 40 ++++++++--------------- move/squid/sources/squid/discovery.move | 6 ++-- move/squid/sources/squid/squid.move | 4 +-- 4 files changed, 20 insertions(+), 36 deletions(-) diff --git a/move/axelar/sources/utils.move b/move/axelar/sources/utils.move index 596a24b9..588a2363 100644 --- a/move/axelar/sources/utils.move +++ b/move/axelar/sources/utils.move @@ -55,7 +55,7 @@ module axelar::utils { public fun compare_address_vectors(v1: &vector, v2: &vector): bool { let length = vector::length(v1); - assert!(length == vector::length(v2), EVectorLengthMismatch); + assert!(length == vector::length(v2), EVectorLengthMismatch); let mut i = 0; while(i < length) { let b1 = *vector::borrow(v1, i); @@ -76,7 +76,7 @@ module axelar::utils { let prefix = x"5f7809eb09754577387a816582ece609511d0262b2c52aa15306083ca3c85962066d6f64756c650866756e6374696f6e02021234025678020574797065310574"; let mut signature = x"5f7809eb09754577387a816582ece609511d0262b2c52aa15306083ca3c85962066d6f64756c650866756e6374696f6e02021234025678020574797065310574"; let inputs = vector[0, 1, 10, 11, 27, 28, 30, 38, 39]; - let outputs = vector[0, 1, 10, 11, 0, 1, 30, 1, 0]; + let outputs = vector[0, 1, 10, 11, 0, 1, 30, 1, 0]; let length = vector::length(&inputs); let mut i = 0; @@ -104,7 +104,7 @@ module axelar::utils { let weights = vector[1, 3, 6]; let threshold = 4; let output = x"dd5d3f9c1017e8356ea1858db7b89800b6cd43775c5c1b7c633f6ef933583cfd"; - + assert!(operators_hash(&operators, &weights, threshold) == output, 0); } diff --git a/move/squid/sources/squid/deepbook_v2.move b/move/squid/sources/squid/deepbook_v2.move index cf1065ee..a81e650f 100644 --- a/move/squid/sources/squid/deepbook_v2.move +++ b/move/squid/sources/squid/deepbook_v2.move @@ -18,7 +18,7 @@ module squid::deepbook_v2 { const FLOAT_SCALING: u64 = 1_000_000_000; const SWAP_TYPE: u8 = 1; - + const EWrongSwapType: u64 = 0; const EWrongPool: u64 = 1; const EWrongCoinType: u64 = 2; @@ -156,9 +156,9 @@ module squid::deepbook_v2 { while(i > 0) { i = i - 1; let (used, max_out) = get_max_quote_from_base( - pool, - *vector::borrow(&prices, i), - *vector::borrow(&depths, i), + pool, + *vector::borrow(&prices, i), + *vector::borrow(&depths, i), amount_left ); amount_left = amount_left - used; @@ -166,7 +166,7 @@ module squid::deepbook_v2 { if(amount_left < lot_size) break; }; (amount_left, output) - + } public fun predict_quote_for_base(pool: &Pool, amount: u64, lot_size: u64, clock: &Clock): (u64, u64) { @@ -177,23 +177,23 @@ module squid::deepbook_v2 { let mut output = 0; let mut i = 0; let length = vector::length(&prices); - while(i < length) { - let price = *vector::borrow(&prices, i); + while(i < length) { + let price = *vector::borrow(&prices, i); let (used, max_out) = get_max_base_from_quote( - pool, - price, - *vector::borrow(&depths, i), - amount_left, + pool, + price, + *vector::borrow(&depths, i), + amount_left, lot_size ); - + amount_left = amount_left - used; output = output + max_out; let (_, left_base) = unsafe_div_round(amount_left, price); if (left_base < lot_size) break; i = i + 1; }; - + (amount_left, output) } @@ -336,16 +336,4 @@ module squid::deepbook_v2 { vector[type_base, type_quote] , ) } - - - #[test] - fun test() { - let ctx = &mut tx_context.dummy(); - clob::create_pool( - 100, - 100, - coin, - ctx, - ); - } -} \ No newline at end of file +} diff --git a/move/squid/sources/squid/discovery.move b/move/squid/sources/squid/discovery.move index d000509c..dc478b2f 100644 --- a/move/squid/sources/squid/discovery.move +++ b/move/squid/sources/squid/discovery.move @@ -3,8 +3,6 @@ module squid::discovery { use sui::bcs; - use abi::abi; - use axelar::discovery::{Self, RelayerDiscovery, MoveCall, Transaction}; use its::its::ITS; @@ -53,7 +51,7 @@ module squid::discovery { let (_, _, _, data) = its::discovery::get_interchain_transfer_info(payload); let package_id = discovery::package_id(); let (swap_data, type_in, _amount_in, _destination_in, type_out, _min_out, _destination_out) = swap_info::decode_swap_info_data(data); - + let mut squid_arg = vector[0]; vector::append(&mut squid_arg, object::id(squid).id_to_bytes()); @@ -154,4 +152,4 @@ module squid::discovery { vector[type_in, type_out], ) } -} \ No newline at end of file +} diff --git a/move/squid/sources/squid/squid.move b/move/squid/sources/squid/squid.move index 65f38cb1..c3ce5f6e 100644 --- a/move/squid/sources/squid/squid.move +++ b/move/squid/sources/squid/squid.move @@ -1,6 +1,4 @@ module squid::squid { - use abi::abi; - use axelar::channel::{Self, Channel, ApprovedCall}; use its::service; @@ -44,4 +42,4 @@ module squid::squid { public(package) fun coin_bag(self: &mut Squid): &mut CoinBag{ &mut self.coin_bag } -} \ No newline at end of file +} From 4ad549556c32e65f61d69a94a0cc037941d489bb Mon Sep 17 00:00:00 2001 From: Milap Sheth Date: Sat, 11 May 2024 04:58:18 -0400 Subject: [PATCH 2/4] docs: update README --- README.md | 69 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index f69882f8..06626bef 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,46 @@ # Axelar CGP Sui -An implementation of the Axelar gateway for the Sui blockchain. +An implementation of the Axelar cross-chain contracts in Move for the Sui blockchain. ## Installation -Install Sui and run a local Sui network: https://docs.sui.io/build/sui-local-network. -The copy `.env.exaple` to `.env` and add a valid private key for sui. If you want to deploy to testnet you shoukd have its address be funded. +Install Sui as shown [here](https://docs.sui.io/guides/developer/getting-started/sui-install) -## Deployment +Install node.js 18+ + +Build all Move packages + +```sh +npm ci -To deploy to testnet run `node scripts/publish-package axelar testnet` +npm run build +``` ## Testing -run `npm run test` to run move tests on all the move packages. +Run tests for all Move packages + +```sh +npm run test +``` + +### Development + +If using VS Code, install `move-analyzer` via `cargo`, + +```sh +cargo install --git https://github.com/move-language/move move-analyzer --features "address20" +``` + +Next, install the `move-analyzer` extension in VS Code. + +## Deployment + +Copy `.env.example` to `.env` and add a valid private key for sui. If you want to deploy to testnet the corresponding address should be funded. + +Run a [local](https://docs.sui.io/build/sui-local-network) Sui network for local testing, or use testnet. + +To deploy to testnet run `node scripts/publish-package axelar testnet` ## Scripts @@ -23,10 +50,37 @@ First run `node scripts/publish-package` and then any of `node scripts/`. +- The module that defined the shared object type has to implement a function called `get_call_info`, which has no types, and takes the incoming call `payload` as the first argument, followed by a number of shared objects whose ids are specified by the `get_call_info_object_ids` mentioned above. This function has to return a `std::ascii::String` which is the JSON encoded call data to fullfill the contract call. +- This calldata has the following 3 fields: + - `target`: the target method, in the form of `packag_iId::module_name::function_name`. + - `arguments`: an array of arguments that can be: + - `contractCall`: the `ApprovedCall` object (see below). + - `pure:${info}`: a pure argument specified by `$info`. + - `obj:${objectId}`: a shared object with the specified `id`. + - `typeArguments`: a list of types to be passed to the function called + ## ITS spec The ITS on sui is supposed to be able to receive 3 messages: -- Register Coin: The payload will be abi encoded data that looks like this: + +- Register Coin: The payload will be abi encoded data that looks like this: `4`: `uint256`, fixed, `tokenId`: `bytes32`, fixed, `name`: `string`, variable, @@ -62,6 +116,7 @@ ITS also needs to be able to send 2 calls, the call to receive coin and the call This module and the object it creates (`CoinManagement`) will tell if a coin is registered as a mint/burn or lock unlock token. To create a `CoinManagement` object one has to call + - `mint_burn`, passing in a `TreasuryCap`. - `lock_unlock`. - `lock_unlock_funded` passing in some initial `Coin` to lock. From d04fcdd42ef08e2ec6ad6aaf2932c682dbcd929e Mon Sep 17 00:00:00 2001 From: Milap Sheth Date: Tue, 14 May 2024 03:33:02 -0400 Subject: [PATCH 3/4] feat(gas-service): add method to collect gas (#26) --- .../sources/gas_service/gas_service.move | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/move/gas_service/sources/gas_service/gas_service.move b/move/gas_service/sources/gas_service/gas_service.move index 9d744e8e..bb8e4266 100644 --- a/move/gas_service/sources/gas_service/gas_service.move +++ b/move/gas_service/sources/gas_service/gas_service.move @@ -14,23 +14,23 @@ module gas_service::gas_service { balance: Balance, } - public struct RefunderCap has key, store { + public struct GasCollectorCap has key, store { id: UID, } public struct NativeGasPaidForContractCall has copy, drop { - sender: address, - destination_chain: String, - destination_address: String, - payload_hash: address, + sender: address, + destination_chain: String, + destination_address: String, + payload_hash: address, value: u64, refund_address: address, } public struct NativeGasAdded has copy, drop { - tx_hash: address, + tx_hash: address, log_index: u64, - value: u64, + value: u64, refund_address: address, } @@ -40,7 +40,7 @@ module gas_service::gas_service { balance: balance::zero(), }); - transfer::public_transfer(RefunderCap { + transfer::public_transfer(GasCollectorCap { id: object::new(ctx), }, ctx.sender()); } @@ -85,10 +85,10 @@ module gas_service::gas_service { }); } - public fun refund(self: &mut GasService, _: &RefunderCap, receiver: address, amount: u64, ctx: &mut TxContext) { + public fun refund(self: &mut GasService, _: &GasCollectorCap, receiver: address, amount: u64, ctx: &mut TxContext) { transfer::public_transfer( coin::take(&mut self.balance, amount, ctx), receiver, ) } -} \ No newline at end of file +} From d073303300f569df829d13d85594f48928066da8 Mon Sep 17 00:00:00 2001 From: Milap Sheth Date: Tue, 14 May 2024 05:06:43 -0400 Subject: [PATCH 4/4] feat(gas-service): collect gas --- README.md | 11 ++---- .../sources/gas_service/gas_service.move | 38 +++++++++++++++++-- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 06626bef..43c90b69 100644 --- a/README.md +++ b/README.md @@ -26,17 +26,14 @@ npm run test ### Development -If using VS Code, install `move-analyzer` via `cargo`, +Install the `Move` extension in VS Code. It should come pre-installed with `move-analyzer`. -```sh -cargo install --git https://github.com/move-language/move move-analyzer --features "address20" -``` - -Next, install the `move-analyzer` extension in VS Code. +Move Book: https://move-book.com +Move Examples: https://examples.sui.io ## Deployment -Copy `.env.example` to `.env` and add a valid private key for sui. If you want to deploy to testnet the corresponding address should be funded. +Copy `.env.example` to `.env` and add a valid private key for Sui. If you want to deploy to testnet the corresponding address should be funded. Run a [local](https://docs.sui.io/build/sui-local-network) Sui network for local testing, or use testnet. diff --git a/move/gas_service/sources/gas_service/gas_service.move b/move/gas_service/sources/gas_service/gas_service.move index bb8e4266..887eb7b6 100644 --- a/move/gas_service/sources/gas_service/gas_service.move +++ b/move/gas_service/sources/gas_service/gas_service.move @@ -8,8 +8,7 @@ module gas_service::gas_service { use sui::hash::keccak256; use sui::event; - public struct GasService - has key, store { + public struct GasService has key, store { id: UID, balance: Balance, } @@ -34,6 +33,18 @@ module gas_service::gas_service { refund_address: address, } + public struct Refunded has copy, drop { + tx_hash: address, + log_index: u64, + value: u64, + refund_address: address, + } + + public struct GasCollected has copy, drop { + receiver: address, + value: u64, + } + fun init(ctx: &mut TxContext) { transfer::share_object(GasService { id: object::new(ctx), @@ -85,10 +96,29 @@ module gas_service::gas_service { }); } - public fun refund(self: &mut GasService, _: &GasCollectorCap, receiver: address, amount: u64, ctx: &mut TxContext) { + public fun collect_gas(self: &mut GasService, _: &GasCollectorCap, receiver: address, amount: u64, ctx: &mut TxContext) { transfer::public_transfer( coin::take(&mut self.balance, amount, ctx), receiver, - ) + ); + + event::emit(GasCollected { + receiver, + value: amount, + }); + } + + public fun refund(self: &mut GasService, _: &GasCollectorCap, tx_hash: address, log_index: u64, receiver: address, amount: u64, ctx: &mut TxContext) { + transfer::public_transfer( + coin::take(&mut self.balance, amount, ctx), + receiver, + ); + + event::emit(Refunded { + tx_hash, + log_index, + value: amount, + refund_address: receiver, + }); } }