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 skeleton code for its token deployment #88

Merged
merged 8 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions contracts/interchain-token-service/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
alloy-primitives = { workspace = true }
alloy-sol-types = { workspace = true }
axelar-gas-service = { workspace = true, features = ["library"] }
axelar-gateway = { workspace = true, features = ["library"] }
axelar-soroban-std = { workspace = true }
soroban-sdk = { workspace = true, features = ["alloc"] }

[dev-dependencies]
axelar-gas-service = { workspace = true, features = ["testutils"] }
axelar-gateway = { workspace = true, features = ["testutils"] }
axelar-soroban-std = { workspace = true, features = ["testutils"] }
goldie = { version = "0.5" }
hex = "0.4"
Expand Down
167 changes: 165 additions & 2 deletions contracts/interchain-token-service/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,55 @@
use axelar_soroban_std::ensure;
use soroban_sdk::{contract, contractimpl, Address, Env, String};
use axelar_soroban_std::types::Token;
use soroban_sdk::{bytes, contract, contractimpl, Address, Bytes, Env, String};

use crate::error::ContractError;
use crate::event;
use crate::storage_types::DataKey;
use crate::types::MessageType;

use axelar_gas_service::AxelarGasServiceClient;
use axelar_gateway::AxelarGatewayMessagingClient;

use axelar_gateway::executable::AxelarExecutableInterface;

#[contract]
pub struct InterchainTokenService;

#[contractimpl]
impl AxelarExecutableInterface for InterchainTokenService {
fn gateway(env: &Env) -> Address {
env.storage().instance().get(&DataKey::Gateway).unwrap()
}

fn execute(
env: Env,
source_chain: String,
message_id: String,
source_address: String,
payload: Bytes,
) {
let _ = Self::validate_message(&env, &source_chain, &message_id, &source_address, &payload);

let _ = Self::execute_message(
&env,
source_chain.clone(),
message_id.clone(),
source_address.clone(),
payload.clone(),
);

event::executed(&env, source_chain, message_id, source_address, payload);
}
}

#[contractimpl]
impl InterchainTokenService {
pub fn __constructor(env: Env, owner: Address) {
pub fn __constructor(env: Env, owner: Address, gateway: Address, gas_service: Address) {
env.storage().instance().set(&DataKey::Owner, &owner);
env.storage().instance().set(&DataKey::Gateway, &gateway);
env.storage()
.instance()
.set(&DataKey::GasService, &gas_service);
}

pub fn owner(env: &Env) -> Address {
Expand Down Expand Up @@ -72,4 +110,129 @@ impl InterchainTokenService {

Ok(())
}

pub fn gas_service(env: &Env) -> Address {
env.storage().instance().get(&DataKey::GasService).unwrap()
}

pub fn execute_message(
_env: &Env,
_source_chain: String,
_message_id: String,
_source_address: String,
_payload: Bytes,
) -> Result<(), ContractError> {
// TODO: get_execute_params
ahramy marked this conversation as resolved.
Show resolved Hide resolved

let message_type = MessageType::DeployInterchainToken;

match message_type {
MessageType::InterchainTransfer => {
// TODO
Ok(())
ahramy marked this conversation as resolved.
Show resolved Hide resolved
}
MessageType::DeployInterchainToken => {
// TODO
Ok(())
}
MessageType::DeployTokenManager => {
// Note: this case is not supported by the ITS hub
Ok(())
}
_ => Err(ContractError::InvalidMessageType),
}
}

#[allow(clippy::too_many_arguments)]
pub fn deploy_interchain_token(
_env: Env,
_caller: Address,
_destination_chain: String,
_name: String,
_symbol: String,
_decimals: i128,
_minter: Bytes,
_gas_token: Token,
) {
// TODO: deploy interchain token
}

pub fn deploy_remote_interchain_token(
env: Env,
caller: Address,
destination_chain: String,
_token_id: String,
gas_token: Token,
_metadata: Bytes,
) {
let destination_address = String::from_str(&env, "destination_address");
ahramy marked this conversation as resolved.
Show resolved Hide resolved

// TODO: abi encode with MessageType.DeployInterchainToken
let payload = bytes!(&env, 0x1234);

Self::pay_gas_and_call_contract(
env,
caller,
destination_chain,
destination_address,
payload,
gas_token,
);
}

#[allow(clippy::too_many_arguments)]
pub fn interchain_token_transfer(
env: Env,
caller: Address,
_token_id: String,
destination_chain: String,
destination_address: String,
_amount: i128,
_metadata: Bytes,
gas_token: Token,
) {
// TODO: _takeToken, decode metadata, and abi encode with MessageType.InterchainTransfer
let payload = bytes!(&env, 0x1234);
ahramy marked this conversation as resolved.
Show resolved Hide resolved

Self::pay_gas_and_call_contract(
env,
caller,
destination_chain,
destination_address,
payload,
gas_token,
);
}

fn pay_gas_and_call_contract(
env: Env,
caller: Address,
destination_chain: String,
destination_address: String,
payload: Bytes,
gas_token: Token,
) {
let gateway = AxelarGatewayMessagingClient::new(&env, &Self::gateway(&env));
let gas_service = AxelarGasServiceClient::new(&env, &Self::gas_service(&env));

caller.require_auth();

// get_call_aprams from payload

gas_service.pay_gas_for_contract_call(
&caller,
&destination_chain,
&destination_address,
&payload,
&caller,
&gas_token,
);

gateway.call_contract(
&env.current_contract_address(),
&destination_chain,
&destination_address,
&payload,
);
}
}
1 change: 1 addition & 0 deletions contracts/interchain-token-service/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ pub enum ContractError {
NotOwner = 1,
TrustedAddressAlreadySet = 2,
NoTrustedAddressSet = 3,
InvalidMessageType = 4,
}
18 changes: 17 additions & 1 deletion contracts/interchain-token-service/src/event.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use soroban_sdk::{Address, Env, String, Symbol};
use soroban_sdk::{Address, Bytes, Env, String, Symbol};

pub fn set_trusted_address(env: &Env, chain: String, trusted_address: String) {
let topics = (
Expand Down Expand Up @@ -26,3 +26,19 @@ pub fn transfer_ownership(env: &Env, previous_owner: Address, new_owner: Address
);
env.events().publish(topics, ());
}

pub fn executed(
env: &Env,
source_chain: String,
message_id: String,
source_address: String,
payload: Bytes,
) {
let topics = (
Symbol::new(env, "executed"),
source_chain,
message_id,
source_address,
);
env.events().publish(topics, (payload,));
}
2 changes: 2 additions & 0 deletions contracts/interchain-token-service/src/storage_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ use soroban_sdk::{contracttype, String};
pub enum DataKey {
Owner,
TrustedAddress(String),
Gateway,
GasService,
}
30 changes: 28 additions & 2 deletions contracts/interchain-token-service/tests/test.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use axelar_gas_service::{AxelarGasService, AxelarGasServiceClient};
use axelar_gateway::testutils;
use axelar_gateway::AxelarGatewayClient;
use interchain_token_service::contract::{InterchainTokenService, InterchainTokenServiceClient};
use interchain_token_service::error::ContractError;

Expand All @@ -6,10 +9,28 @@ use soroban_sdk::testutils::{MockAuth, MockAuthInvoke};

use soroban_sdk::{testutils::Address as _, Address, Env, String, Symbol};

fn setup_gateway<'a>(env: &Env) -> AxelarGatewayClient<'a> {
let (_, client) = testutils::setup_gateway(env, 0, 5);
client
}

fn setup_gas_service<'a>(env: &Env) -> AxelarGasServiceClient<'a> {
let gas_collector: Address = Address::generate(&env);
let gas_service_id = env.register(AxelarGasService, (&gas_collector,));
let gas_service_client = AxelarGasServiceClient::new(env, &gas_service_id);

gas_service_client
}

fn setup_env<'a>() -> (Env, InterchainTokenServiceClient<'a>) {
let env = Env::default();
let owner = Address::generate(&env);
let contract_id = env.register(InterchainTokenService, (&owner,));
let gateway_client = setup_gateway(&env);
let gas_service_client = setup_gas_service(&env);
let contract_id = env.register(
InterchainTokenService,
(&owner, gateway_client.address, gas_service_client.address),
);
let client = InterchainTokenServiceClient::new(&env, &contract_id);

(env, client)
Expand All @@ -19,7 +40,12 @@ fn setup_env<'a>() -> (Env, InterchainTokenServiceClient<'a>) {
fn register_interchain_token_service() {
let env = Env::default();
let owner = Address::generate(&env);
let contract_id = env.register(InterchainTokenService, (&owner,));
let gateway_client = setup_gateway(&env);
let gas_service_client = setup_gas_service(&env);
let contract_id = env.register(
InterchainTokenService,
(&owner, gateway_client.address, gas_service_client.address),
);
let client = InterchainTokenServiceClient::new(&env, &contract_id);

assert_eq!(client.owner(), owner);
Expand Down
Loading