Skip to content

Commit

Permalink
refactor(axelar-gas-service)!: switch gas_collector to operator (#209)
Browse files Browse the repository at this point in the history
  • Loading branch information
milapsheth authored Jan 24, 2025
1 parent ca3b486 commit 2553182
Show file tree
Hide file tree
Showing 18 changed files with 47 additions and 86 deletions.
11 changes: 11 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,14 @@ jobs:
run: RUSTFLAGS="-D warnings" cargo test --locked
env:
RUST_BACKTRACE: 1

- name: Remove all golden files
run: find . -name "*.golden" -exec rm -rf {} \;

- name: Regenerate golden files
run: RUSTFLAGS="-D warnings" cargo test --locked
env:
GOLDIE_UPDATE: 1

- name: Check for stale golden files
run: git diff --exit-code
23 changes: 6 additions & 17 deletions contracts/stellar-axelar-gas-service/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,22 @@ use soroban_sdk::{contract, contractimpl, token, Address, Bytes, Env, String};
use stellar_axelar_std::events::Event;
use stellar_axelar_std::ttl::extend_instance_ttl;
use stellar_axelar_std::types::Token;
use stellar_axelar_std::{ensure, interfaces, Ownable, Upgradable};
use stellar_axelar_std::{ensure, interfaces, Operatable, Ownable, Upgradable};

use crate::error::ContractError;
use crate::event::{GasAddedEvent, GasCollectedEvent, GasPaidEvent, GasRefundedEvent};
use crate::interface::AxelarGasServiceInterface;
use crate::storage_types::DataKey;

#[contract]
#[derive(Ownable, Upgradable)]
#[derive(Operatable, Ownable, Upgradable)]
pub struct AxelarGasService;

#[contractimpl]
impl AxelarGasService {
/// Initialize the gas service contract with a gas_collector address.
pub fn __constructor(env: Env, owner: Address, gas_collector: Address) {
pub fn __constructor(env: Env, owner: Address, operator: Address) {
interfaces::set_operator(&env, &operator);
interfaces::set_owner(&env, &owner);
env.storage()
.instance()
.set(&DataKey::GasCollector, &gas_collector);
}
}

Expand Down Expand Up @@ -94,8 +91,7 @@ impl AxelarGasServiceInterface for AxelarGasService {
}

fn collect_fees(env: Env, receiver: Address, token: Token) -> Result<(), ContractError> {
let gas_collector = Self::gas_collector(&env);
gas_collector.require_auth();
Self::operator(&env).require_auth();

ensure!(token.amount > 0, ContractError::InvalidAmount);

Expand All @@ -117,7 +113,7 @@ impl AxelarGasServiceInterface for AxelarGasService {
}

fn refund(env: Env, message_id: String, receiver: Address, token: Token) {
Self::gas_collector(&env).require_auth();
Self::operator(&env).require_auth();

token::Client::new(&env, &token.address).transfer(
&env.current_contract_address(),
Expand All @@ -132,11 +128,4 @@ impl AxelarGasServiceInterface for AxelarGasService {
}
.emit(&env);
}

fn gas_collector(env: &Env) -> Address {
env.storage()
.instance()
.get(&DataKey::GasCollector)
.expect("gas collector not found")
}
}
10 changes: 4 additions & 6 deletions contracts/stellar-axelar-gas-service/src/interface.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use soroban_sdk::{contractclient, Address, Bytes, Env, String};
use stellar_axelar_std::interfaces::OperatableInterface;
use stellar_axelar_std::types::Token;

use crate::error::ContractError;

#[contractclient(name = "AxelarGasServiceClient")]
pub trait AxelarGasServiceInterface {
pub trait AxelarGasServiceInterface: OperatableInterface {
/// Pay for gas using a token for sending a message on a destination chain.
///
/// This function is called on the source chain before calling the gateway to send a message.
Expand Down Expand Up @@ -38,14 +39,11 @@ pub trait AxelarGasServiceInterface {

/// Allows the `gas_collector` to collect accumulated fees from the contract.
///
/// Only callable by the `gas_collector`.
/// Only callable by the `operator`.
fn collect_fees(env: Env, receiver: Address, token: Token) -> Result<(), ContractError>;

/// Refunds gas payment to the receiver in relation to a specific cross-chain message.
///
/// Only callable by the `gas_collector`.
/// Only callable by the `operator`.
fn refund(env: Env, message_id: String, receiver: Address, token: Token);

/// Returns the address of the `gas_collector`.
fn gas_collector(env: &Env) -> Address;
}
1 change: 0 additions & 1 deletion contracts/stellar-axelar-gas-service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ cfg_if::cfg_if! {
pub use interface::{AxelarGasServiceClient, AxelarGasServiceInterface};
} else {
pub mod event;
mod storage_types;
mod contract;

pub use contract::{AxelarGasService, AxelarGasServiceClient};
Expand Down
7 changes: 0 additions & 7 deletions contracts/stellar-axelar-gas-service/src/storage_types.rs

This file was deleted.

52 changes: 24 additions & 28 deletions contracts/stellar-axelar-gas-service/src/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ fn setup_env<'a>() -> (Env, Address, Address, AxelarGasServiceClient<'a>) {
let env = Env::default();

let owner: Address = Address::generate(&env);
let gas_collector: Address = Address::generate(&env);
let contract_id = env.register(AxelarGasService, (&owner, &gas_collector));
let operator: Address = Address::generate(&env);
let contract_id = env.register(AxelarGasService, (&owner, &operator));
let client = AxelarGasServiceClient::new(&env, &contract_id);

(env, contract_id, gas_collector, client)
(env, contract_id, operator, client)
}

fn setup_token(env: &Env, recipient: &Address, amount: i128) -> Token {
Expand Down Expand Up @@ -60,11 +60,11 @@ fn register_gas_service() {
let env = Env::default();

let owner: Address = Address::generate(&env);
let gas_collector = Address::generate(&env);
let contract_id = env.register(AxelarGasService, (&owner, &gas_collector));
let operator = Address::generate(&env);
let contract_id = env.register(AxelarGasService, (&owner, &operator));
let client = AxelarGasServiceClient::new(&env, &contract_id);

assert_eq!(client.gas_collector(), gas_collector);
assert_eq!(client.operator(), operator);
}

#[test]
Expand Down Expand Up @@ -258,7 +258,7 @@ fn add_gas() {

#[test]
fn collect_fees_fails_with_zero_amount() {
let (env, _, gas_collector, client) = setup_env();
let (env, _, operator, client) = setup_env();
let spender: Address = Address::generate(&env);
let refund_amount = 0;
let supply: i128 = 1000;
Expand All @@ -270,16 +270,14 @@ fn collect_fees_fails_with_zero_amount() {
};

assert_contract_err!(
client
.mock_all_auths()
.try_collect_fees(&gas_collector, &token),
client.mock_all_auths().try_collect_fees(&operator, &token),
ContractError::InvalidAmount
);
}

#[test]
fn collect_fees_fails_with_insufficient_balance() {
let (env, contract_id, gas_collector, client) = setup_env();
let (env, contract_id, operator, client) = setup_env();

let supply: i128 = 5;
let asset = &env.register_stellar_asset_contract_v2(Address::generate(&env));
Expand All @@ -294,9 +292,7 @@ fn collect_fees_fails_with_insufficient_balance() {
};

assert_contract_err!(
client
.mock_all_auths()
.try_collect_fees(&gas_collector, &token),
client.mock_all_auths().try_collect_fees(&operator, &token),
ContractError::InsufficientBalance
);
}
Expand All @@ -323,8 +319,8 @@ fn collect_fees_fails_without_authorization() {
}

#[test]
fn collect_fees() {
let (env, contract_id, gas_collector, client) = setup_env();
fn collect_fees_succeeds() {
let (env, contract_id, operator, client) = setup_env();

let supply: i128 = 1000;
let asset = &env.register_stellar_asset_contract_v2(Address::generate(&env));
Expand All @@ -342,24 +338,24 @@ fn collect_fees() {

let transfer_token_auth = mock_auth!(
env,
gas_collector,
token.transfer(gas_collector, client.address, token.amount)
operator,
token.transfer(operator, client.address, token.amount)
);

let collect_fees_auth = mock_auth!(
env,
gas_collector,
client.collect_fees(&gas_collector, &token),
operator,
client.collect_fees(&operator, &token),
&[(transfer_token_auth.invoke).clone()]
);

client
.mock_auths(&[collect_fees_auth])
.collect_fees(&gas_collector, &token);
.collect_fees(&operator, &token);

goldie::assert!(fmt_last_emitted_event::<GasCollectedEvent>(&env));

assert_eq!(refund_amount, token_client.balance(&gas_collector));
assert_eq!(refund_amount, token_client.balance(&operator));
assert_eq!(supply - refund_amount, token_client.balance(&contract_id));
}

Expand Down Expand Up @@ -388,7 +384,7 @@ fn refund_fails_without_authorization() {
#[test]
#[should_panic(expected = "HostError: Error(Contract, #10)")] // "balance is not sufficient to spend"
fn refund_fails_with_insufficient_balance() {
let (env, contract_id, gas_collector, client) = setup_env();
let (env, contract_id, operator, client) = setup_env();

let supply: i128 = 1;
let asset = &env.register_stellar_asset_contract_v2(Address::generate(&env));
Expand All @@ -407,13 +403,13 @@ fn refund_fails_with_insufficient_balance() {

let transfer_token_auth = mock_auth!(
env,
gas_collector,
token.transfer(gas_collector, client.address, token.amount)
operator,
token.transfer(operator, client.address, token.amount)
);

let refund_auth = mock_auth!(
env,
gas_collector,
operator,
client.refund(&message_id, &receiver, &token),
&[(transfer_token_auth.invoke).clone()]
);
Expand All @@ -424,7 +420,7 @@ fn refund_fails_with_insufficient_balance() {
}

#[test]
fn refund() {
fn refund_succeeds() {
let (env, contract_id, _, client) = setup_env();

let supply: i128 = 1000;
Expand All @@ -445,7 +441,7 @@ fn refund() {
let message_id = message_id(&env);

assert_auth!(
&client.gas_collector(),
client.operator(),
client.refund(&message_id, &receiver, &token)
);

Expand Down
4 changes: 2 additions & 2 deletions contracts/stellar-axelar-gas-service/src/testutils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use crate::{AxelarGasService, AxelarGasServiceClient};

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

gas_service_client
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

0 comments on commit 2553182

Please sign in to comment.