Skip to content

Commit

Permalink
feat(interchain-token-service): encode source/recipient addresses as …
Browse files Browse the repository at this point in the history
…strings instead of XDR (#147)

Co-authored-by: Milap Sheth <[email protected]>
  • Loading branch information
TanvirDeol and milapsheth authored Jan 20, 2025
1 parent 1a5876d commit 2b3ca63
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 31 deletions.
12 changes: 4 additions & 8 deletions contracts/interchain-token-service/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use soroban_sdk::token::StellarAssetClient;
use soroban_sdk::xdr::{FromXdr, ToXdr};
use soroban_sdk::xdr::ToXdr;
use soroban_sdk::{contract, contractimpl, Address, Bytes, BytesN, Env, String};
use soroban_token_sdk::metadata::TokenMetadata;
use stellar_axelar_gas_service::AxelarGasServiceClient;
Expand Down Expand Up @@ -377,7 +377,7 @@ impl InterchainTokenServiceInterface for InterchainTokenService {

let message = Message::InterchainTransfer(InterchainTransfer {
token_id,
source_address: caller.clone().to_xdr(env),
source_address: caller.to_string_bytes(),
destination_address,
amount,
data,
Expand Down Expand Up @@ -674,8 +674,7 @@ impl InterchainTokenService {
data,
}: InterchainTransfer,
) -> Result<(), ContractError> {
let destination_address = Address::from_xdr(env, &destination_address)
.map_err(|_| ContractError::InvalidDestinationAddress)?;
let destination_address = Address::from_string_bytes(&destination_address);

let token_config_value = Self::token_id_config_with_extended_ttl(env, token_id.clone())?;

Expand Down Expand Up @@ -734,10 +733,7 @@ impl InterchainTokenService {
let token_metadata = TokenMetadata::new(name, symbol, decimals as u32)?;

// Note: attempt to convert a byte string which doesn't represent a valid Soroban address fails at the Host level
let minter = minter
.map(|m| Address::from_xdr(env, &m))
.transpose()
.map_err(|_| ContractError::InvalidMinter)?;
let minter = minter.map(|m| Address::from_string_bytes(&m));

let deployed_address =
Self::deploy_interchain_token_contract(env, minter, token_id.clone(), token_metadata);
Expand Down
9 changes: 5 additions & 4 deletions contracts/interchain-token-service/tests/executable.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
mod utils;

use soroban_sdk::testutils::Address as _;
use soroban_sdk::xdr::ToXdr;
use soroban_sdk::{token, vec, Address, Bytes, BytesN, String};
use stellar_axelar_gateway::testutils::{generate_proof, get_approve_hash};
use stellar_axelar_gateway::types::Message as GatewayMessage;
use stellar_axelar_std::address::AddressExt;
use stellar_axelar_std::traits::BytesExt;
use stellar_axelar_std::{assert_auth_err, events};
use stellar_interchain_token_service::types::{HubMessage, InterchainTransfer, Message};
Expand Down Expand Up @@ -124,14 +124,15 @@ fn interchain_transfer_execute_succeeds() {

let executable_id = env.register(test::ExecutableContract, (client.address.clone(),));

let sender = Address::generate(&env).to_xdr(&env);
let sender = Address::generate(&env).to_string_bytes();
let source_chain = client.its_hub_chain_name();
let source_address: String = client.its_hub_address();

let amount = 1000;
let deployer = Address::generate(&env);
let token_id = setup_its_token(&env, &client, &deployer, amount);
let data = Bytes::from_hex(&env, "dead");
let destination_address = executable_id.to_string_bytes();
let original_source_chain = String::from_str(&env, "ethereum");
client
.mock_all_auths()
Expand All @@ -142,7 +143,7 @@ fn interchain_transfer_execute_succeeds() {
message: Message::InterchainTransfer(InterchainTransfer {
token_id: token_id.clone(),
source_address: sender,
destination_address: executable_id.clone().to_xdr(&env),
destination_address,
amount,
data: Some(data.clone()),
}),
Expand Down Expand Up @@ -186,7 +187,7 @@ fn executable_fails_if_not_executed_from_its() {
let executable_client = test::ExecutableContractClient::new(&env, &executable_id);

let source_chain = client.its_hub_chain_name();
let source_address = Address::generate(&env).to_xdr(&env);
let source_address = Address::generate(&env).to_string_bytes();
let amount = 1000;
let token_id = BytesN::<32>::from_array(&env, &[1; 32]);
let token_address = Address::generate(&env);
Expand Down
15 changes: 7 additions & 8 deletions contracts/interchain-token-service/tests/execute.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
mod utils;

use soroban_sdk::testutils::Address as _;
use soroban_sdk::xdr::ToXdr;
use soroban_sdk::{vec, Address, Bytes, BytesN, Env, String};
use soroban_token_sdk::metadata::TokenMetadata;
use stellar_axelar_gateway::types::Message as GatewayMessage;
use stellar_axelar_std::address::AddressExt;
use stellar_axelar_std::{assert_contract_err, events};
use stellar_interchain_token::InterchainTokenClient;
use stellar_interchain_token_service::error::ContractError;
Expand Down Expand Up @@ -124,8 +124,8 @@ fn execute_fails_with_invalid_source_address() {
fn interchain_transfer_message_execute_succeeds() {
let (env, client, gateway_client, _, signers) = setup_env();

let sender = Address::generate(&env).to_xdr(&env);
let recipient = Address::generate(&env).to_xdr(&env);
let sender = Address::generate(&env).to_string_bytes();
let recipient = Address::generate(&env).to_string_bytes();
let source_chain = client.its_hub_chain_name();
let source_address = client.its_hub_address();
let original_source_chain = String::from_str(&env, "ethereum");
Expand Down Expand Up @@ -176,8 +176,7 @@ fn deploy_interchain_token_message_execute_succeeds() {
let (env, client, gateway_client, _, signers) = setup_env();
register_chains(&env, &client);

let sender = Address::generate(&env);
let sender_bytes = sender.clone().to_xdr(&env);
let sender = Address::generate(&env).to_string_bytes();
let source_chain = client.its_hub_chain_name();
let source_address = client.its_hub_address();

Expand All @@ -199,7 +198,7 @@ fn deploy_interchain_token_message_execute_succeeds() {
name: token_metadata.name.clone(),
symbol: token_metadata.symbol.clone(),
decimals: token_metadata.decimal as u8,
minter: Some(sender_bytes),
minter: Some(sender.clone()),
}),
};
let payload = msg.abi_encode(&env).unwrap();
Expand All @@ -226,7 +225,7 @@ fn deploy_interchain_token_message_execute_succeeds() {

let token = InterchainTokenClient::new(&env, &client.token_address(&token_id));

assert!(token.is_minter(&sender));
assert!(token.is_minter(&Address::from_string_bytes(&sender)));
assert_eq!(token.name(), token_metadata.name);
assert_eq!(token.symbol(), token_metadata.symbol);
assert_eq!(token.decimals(), token_metadata.decimal);
Expand Down Expand Up @@ -374,7 +373,7 @@ fn deploy_interchain_token_message_execute_fails_token_already_deployed() {
let (env, client, gateway_client, _, signers) = setup_env();
register_chains(&env, &client);

let sender = Address::generate(&env).to_xdr(&env);
let sender = Address::generate(&env).to_string_bytes();
let source_chain = client.its_hub_chain_name();
let source_address = client.its_hub_address();

Expand Down
6 changes: 3 additions & 3 deletions contracts/interchain-token-service/tests/flow_limit.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
mod utils;

use soroban_sdk::testutils::{Address as _, Ledger as _};
use soroban_sdk::xdr::ToXdr;
use soroban_sdk::{vec, Address, Bytes, BytesN, Env, String};
use stellar_axelar_gateway::testutils::TestSignerSet;
use stellar_axelar_gateway::types::Message as GatewayMessage;
use stellar_axelar_gateway::AxelarGatewayClient;
use stellar_axelar_std::address::AddressExt;
use stellar_axelar_std::traits::BytesExt;
use stellar_axelar_std::{assert_auth, assert_contract_err, events};
use stellar_interchain_token_service::error::ContractError;
Expand Down Expand Up @@ -86,8 +86,8 @@ fn approve_its_transfer(
token_id: &BytesN<32>,
amount: i128,
) -> ApprovedMessage {
let sender = Address::generate(env).to_xdr(env);
let recipient = Address::generate(env).to_xdr(env);
let sender = Address::generate(env).to_string_bytes();
let recipient = Address::generate(env).to_string_bytes();
let source_chain = client.its_hub_chain_name();
let source_address = client.its_hub_address();

Expand Down
4 changes: 2 additions & 2 deletions contracts/interchain-token-service/tests/message_routing.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
mod utils;
use soroban_sdk::testutils::Address as _;
use soroban_sdk::xdr::ToXdr;
use soroban_sdk::{Address, Bytes, String};
use stellar_axelar_std::address::AddressExt;
use stellar_axelar_std::assert_contract_err;
use stellar_axelar_std::traits::BytesExt;
use stellar_interchain_token_service::error::ContractError;
Expand Down Expand Up @@ -45,7 +45,7 @@ fn send_to_untrusted_chain_fails() {
&sender,
&token_id,
&String::from_str(&env, "untrusted_chain"),
&Address::generate(&env).to_xdr(&env),
&Address::generate(&env).to_string_bytes(),
&amount,
&None,
&gas_token,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
contract: Contract(CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXI7N)
topics: (Symbol(executed), String(ethereum), String(test), Bytes(0, 0, 0, 18, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12), BytesN<32>(19, 164, 112, 128, 76, 247, 2, 236, 196, 20, 87, 206, 58, 2, 208, 102, 225, 238, 175, 151, 45, 250, 47, 204, 76, 253, 158, 193, 68, 73, 208, 149), Contract(CBQXZFUKGANX4DCFGMAEZNEIZ6KEN5RRIUPP25SRMZ6WGLVGFAFT5XSD), 1000)
topics: (Symbol(executed), String(ethereum), String(test), Bytes(67, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 89, 82, 69, 53), BytesN<32>(19, 164, 112, 128, 76, 247, 2, 236, 196, 20, 87, 206, 58, 2, 208, 102, 225, 238, 175, 151, 45, 250, 47, 204, 76, 253, 158, 193, 68, 73, 208, 149), Contract(CBQXZFUKGANX4DCFGMAEZNEIZ6KEN5RRIUPP25SRMZ6WGLVGFAFT5XSD), 1000)
data: (Bytes(222, 173))
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
contract: Contract(CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVAX5)
topics: (Symbol(interchain_transfer_received), String(ethereum), BytesN<32>(19, 164, 112, 128, 76, 247, 2, 236, 196, 20, 87, 206, 58, 2, 208, 102, 225, 238, 175, 151, 45, 250, 47, 204, 76, 253, 158, 193, 68, 73, 208, 149), Bytes(0, 0, 0, 18, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11), Contract(CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYRE5), 1000)
topics: (Symbol(interchain_transfer_received), String(ethereum), BytesN<32>(19, 164, 112, 128, 76, 247, 2, 236, 196, 20, 87, 206, 58, 2, 208, 102, 225, 238, 175, 151, 45, 250, 47, 204, 76, 253, 158, 193, 68, 73, 208, 149), Bytes(67, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 88, 73, 55, 78), Contract(CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYRE5), 1000)
data: (None)
86 changes: 82 additions & 4 deletions packages/axelar-std/src/address.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,94 @@
use soroban_sdk::{Address, Env, String};
use soroban_sdk::{Address, Bytes, Env, String};

const ZERO_ADDRESS: &str = "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF";
const STELLAR_ADDRESS_LEN: usize = ZERO_ADDRESS.len();

pub trait AddressExt {
fn zero(env: &Env) -> Address;

fn to_string_bytes(&self) -> Bytes;
}

impl AddressExt for Address {
/// Returns Stellar's "dead" address, represented by the constant `ZERO_ADDRESS`.
/// # Reference
/// - Stellar [GitHub](https://github.com/stellar/js-stellar-base/blob/master/test/unit/address_test.js)
/// Returns Stellar's ["dead"](https://github.com/stellar/js-stellar-base/blob/master/test/unit/address_test.js) address, represented by the constant `ZERO_ADDRESS`.
fn zero(env: &Env) -> Address {
Self::from_string(&String::from_str(env, ZERO_ADDRESS))
}

/// Converts Stellar address to a string represented as bytes
fn to_string_bytes(&self) -> Bytes {
let mut address_string_bytes = [0u8; STELLAR_ADDRESS_LEN];
self.to_string().copy_into_slice(&mut address_string_bytes);
Bytes::from_slice(self.env(), &address_string_bytes)
}
}

#[cfg(test)]
mod tests {
use soroban_sdk::testutils::Address as _;
use soroban_sdk::{Address, Bytes, Env, String};

use super::{AddressExt, ZERO_ADDRESS};

#[test]
fn zero_address_to_string() {
let env = &Env::default();
assert_eq!(
Address::zero(env).to_string(),
String::from_str(env, ZERO_ADDRESS)
);
}

#[test]
fn string_to_address_to_string() {
let env = &Env::default();
let cases = [
ZERO_ADDRESS,
"GC7OHFPWPSWXL4HMN6TXAG54MTZSMJIASWHO6KVRQNHNCXEAHWDSGGC3",
"CB6743BTQ2TZHTUCRSUFAH2X5ICOZGI6I3UCQBY3VFSSJ7IERGXUM7TX",
]
.into_iter()
.map(|s| Bytes::from_slice(env, s.as_bytes()));

for address_bytes in cases {
let address = Address::from_string_bytes(&address_bytes);
assert_eq!(address.to_string_bytes(), address_bytes);
}
}

#[test]
fn address_to_string_to_address() {
let env = &Env::default();

let cases = [
Address::zero(env),
Address::generate(env),
env.register_stellar_asset_contract_v2(Address::generate(env))
.address(),
];

for address in cases {
let address_bytes = address.to_string_bytes();
assert_eq!(Address::from_string_bytes(&address_bytes), address);
}
}

#[test]
#[should_panic(expected = "HostError: Error(Value, InvalidInput)")]
fn unsupported_muxed_address_format_fails_on_conversion() {
let env = &Env::default();

let unsupported_address =
"MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUAAAAAAAAAAAACJUQ";
Address::from_string(&String::from_str(env, unsupported_address));
}

#[test]
#[should_panic(expected = "HostError: Error(Value, InvalidInput)")]
fn unsupported_signed_payload_address_format_fails_on_conversion() {
let env = &Env::default();

let unsupported_address = "PA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUAAAAAOQCAQDAQCQMBYIBEFAWDANBYHRAEISCMKBKFQXDAMRUGY4DUAAAAFGBU";
Address::from_string(&String::from_str(env, unsupported_address));
}
}

0 comments on commit 2b3ca63

Please sign in to comment.