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 2 commits
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
185 changes: 174 additions & 11 deletions contracts/interchain-token-service/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,78 @@
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::interface::InterchainTokenServiceInterface;
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 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);
}

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

pub fn owner(env: &Env) -> Address {
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
ahramy marked this conversation as resolved.
Show resolved Hide resolved

gas_service.pay_gas_for_contract_call(
&caller,
ahramy marked this conversation as resolved.
Show resolved Hide resolved
&destination_chain,
&destination_address,
&payload,
&caller,
&gas_token,
);

gateway.call_contract(
&env.current_contract_address(),
&destination_chain,
&destination_address,
&payload,
);
}
}

#[contractimpl]
impl InterchainTokenServiceInterface for InterchainTokenService {
fn owner(env: &Env) -> Address {
env.storage()
.instance()
.get(&DataKey::Owner)
.expect("owner not found")
}

pub fn transfer_ownership(env: Env, new_owner: Address) {
fn transfer_ownership(env: Env, new_owner: Address) {
let owner = Self::owner(&env);
owner.require_auth();

Expand All @@ -30,17 +81,13 @@ impl InterchainTokenService {
event::transfer_ownership(&env, owner, new_owner);
}

pub fn trusted_address(env: &Env, chain: String) -> Option<String> {
fn trusted_address(env: &Env, chain: String) -> Option<String> {
env.storage()
.persistent()
.get(&DataKey::TrustedAddress(chain))
}

pub fn set_trusted_address(
env: Env,
chain: String,
address: String,
) -> Result<(), ContractError> {
fn set_trusted_address(env: Env, chain: String, address: String) -> Result<(), ContractError> {
Self::owner(&env).require_auth();

let key = DataKey::TrustedAddress(chain.clone());
Expand All @@ -57,7 +104,7 @@ impl InterchainTokenService {
Ok(())
}

pub fn remove_trusted_address(env: Env, chain: String) -> Result<(), ContractError> {
fn remove_trusted_address(env: Env, chain: String) -> Result<(), ContractError> {
Self::owner(&env).require_auth();

let Some(trusted_address) = Self::trusted_address(&env, chain.clone()) else {
Expand All @@ -72,4 +119,120 @@ impl InterchainTokenService {

Ok(())
}

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)]
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
}

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)]
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,
);
}
}

#[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);
}
}
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,));
}
58 changes: 58 additions & 0 deletions contracts/interchain-token-service/src/interface.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use axelar_soroban_std::types::Token;
use soroban_sdk::{contractclient, Address, Bytes, Env, String};

use crate::error::ContractError;

#[contractclient(name = "InterchainTokenServiceClient")]
pub trait InterchainTokenServiceInterface {
ahramy marked this conversation as resolved.
Show resolved Hide resolved
fn owner(env: &Env) -> Address;

fn transfer_ownership(env: Env, new_owner: Address);

fn trusted_address(env: &Env, chain: String) -> Option<String>;

fn set_trusted_address(env: Env, chain: String, address: String) -> Result<(), ContractError>;
ahramy marked this conversation as resolved.
Show resolved Hide resolved

fn remove_trusted_address(env: Env, chain: String) -> Result<(), ContractError>;

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

#[allow(clippy::too_many_arguments)]
fn deploy_interchain_token(
_env: Env,
_caller: Address,
_destination_chain: String,
_name: String,
_symbol: String,
_decimals: i128,
ahramy marked this conversation as resolved.
Show resolved Hide resolved
_minter: Bytes,
_gas_token: Token,
);

fn deploy_remote_interchain_token(
env: Env,
caller: Address,
destination_chain: String,
_token_id: String,
gas_token: Token,
_metadata: Bytes,
ahramy marked this conversation as resolved.
Show resolved Hide resolved
);

#[allow(clippy::too_many_arguments)]
fn interchain_token_transfer(
ahramy marked this conversation as resolved.
Show resolved Hide resolved
env: Env,
caller: Address,
_token_id: String,
destination_chain: String,
destination_address: String,
ahramy marked this conversation as resolved.
Show resolved Hide resolved
_amount: i128,
_metadata: Bytes,
gas_token: Token,
);
}
1 change: 1 addition & 0 deletions contracts/interchain-token-service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
mod abi;
pub mod error;
mod event;
mod interface;
mod storage_types;
mod types;

Expand Down
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,
}
Loading
Loading