-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: add back contract_id as output to the setup_emv test chore: update tests to pass in correct token address into refund chore: WIP - adding auth for refund methods and tests for emitted events chore: unwrapping index value
- Loading branch information
Showing
8 changed files
with
260 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,50 +1,122 @@ | ||
use soroban_sdk::token::TokenClient; | ||
use soroban_sdk::{contract, contractimpl, Address, Bytes, BytesN, Env, String, U256}; | ||
use soroban_sdk::{contract, contractimpl, token, Address, Bytes, BytesN, Env, String, Vec, U256}; | ||
|
||
use crate::interface::AxelarGasServiceInterface; | ||
use crate::event; | ||
use crate::storage_types::DataKey; | ||
use crate::{error::Error, event}; | ||
|
||
#[contract] | ||
pub struct AxelarGasService; | ||
|
||
#[contractimpl] | ||
impl AxelarGasService { | ||
|
||
pub fn initialize(env: Env) { | ||
if env.storage().instance().get(&DataKey::Initialized).unwrap_or(false) { | ||
pub fn initialize(env: Env, gas_collector: Address) { | ||
if env | ||
.storage() | ||
.instance() | ||
.get(&DataKey::Initialized) | ||
.unwrap_or(false) | ||
{ | ||
panic!("Already initialized"); | ||
} | ||
|
||
env.storage().instance().set(&DataKey::Initialized, &true); | ||
|
||
env.storage() | ||
.instance() | ||
.set(&DataKey::GasCollector, &gas_collector); | ||
} | ||
} | ||
|
||
#[contractimpl] | ||
impl AxelarGasServiceInterface for AxelarGasService { | ||
|
||
fn pay_native_gas_for_contract_call(env: Env, sender: Address, destination_chain: String, destination_address: String, payload: Bytes, refund_address: Address) { | ||
event::native_gas_paid_for_contract_call(&env, sender, destination_chain, destination_address, payload, refund_address) | ||
} | ||
|
||
fn collect_fees() { | ||
fn pay_native_gas_for_contract_call( | ||
env: Env, | ||
sender: Address, | ||
destination_chain: String, | ||
destination_address: String, | ||
payload: Bytes, | ||
refund_address: Address, | ||
) { | ||
event::native_gas_paid_for_contract_call( | ||
&env, | ||
sender, | ||
destination_chain, | ||
destination_address, | ||
payload, | ||
refund_address, | ||
) | ||
} | ||
|
||
|
||
fn refund(env: Env, tx_hash: BytesN<32>, log_index: U256, receiver: Address, token_addr: Address, amount: i128) { | ||
|
||
//TODOs | ||
// 1. need modifier function to ensure only callable by collector | ||
// 2. confirm whether we want to generalize for non-native tokens | ||
|
||
event::refunded(&env, tx_hash, log_index, receiver, token_addr, amount); | ||
|
||
let token = TokenClient::new(&env, &token_addr); | ||
|
||
// 3. send tokens to receiver. test this | ||
token.transfer(&env.current_contract_address(), &receiver, &amount) | ||
|
||
fn collect_fees( | ||
env: Env, | ||
receiver: Address, | ||
token_addresses: Vec<Address>, | ||
amounts: Vec<i128>, | ||
) -> Result<(), Error> { | ||
//TODO confirm this is analogous to onlyGasCollector in Solidity | ||
let gas_collector: Address = env | ||
.storage() | ||
.instance() | ||
.get(&DataKey::GasCollector) | ||
.unwrap(); | ||
|
||
gas_collector.require_auth(); | ||
|
||
//TODO: sanity check address zero | ||
|
||
let token_addr_length = token_addresses.len(); | ||
|
||
if token_addr_length != amounts.len() { | ||
return Err(Error::InvalidAmounts); | ||
} | ||
|
||
for i in 0..token_addr_length { | ||
let amount = amounts.get(i).unwrap(); | ||
|
||
let token_addr = token_addresses | ||
.get(i).unwrap(); | ||
|
||
if amount == 0 { | ||
return Err(Error::InvalidAmounts); | ||
} | ||
|
||
let token_client = token::Client::new(&env, &token_addr); | ||
|
||
let contract_token_balance = token_client.balance(&env.current_contract_address()); | ||
|
||
if contract_token_balance >= amount { | ||
token_client.transfer(&env.current_contract_address(), &receiver, &amount) | ||
} else { | ||
return Err(Error::InsufficientBalance); | ||
} | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
|
||
} | ||
fn refund( | ||
env: Env, | ||
tx_hash: BytesN<32>, | ||
log_index: U256, | ||
receiver: Address, | ||
token_addr: Address, | ||
amount: i128, | ||
) { | ||
//TODO confirm this is analogous to onlyGasCollector in Solidity | ||
let gas_collector: Address = env | ||
.storage() | ||
.instance() | ||
.get(&DataKey::GasCollector) | ||
.unwrap(); | ||
|
||
gas_collector.require_auth(); | ||
|
||
event::refunded(&env, tx_hash, log_index, &receiver, &token_addr, amount); | ||
|
||
token::Client::new(&env, &token_addr).transfer( | ||
&env.current_contract_address(), | ||
&receiver, | ||
&amount, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
use soroban_sdk::contracterror; | ||
|
||
#[contracterror] | ||
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] | ||
#[repr(u32)] | ||
pub enum Error { | ||
InvalidAddress = 1, | ||
InvalidAmounts = 2, | ||
InsufficientBalance = 3, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,34 @@ | ||
use soroban_sdk::{symbol_short, Address, Bytes, BytesN, Env, String, U256}; | ||
|
||
pub(crate) fn refunded(env: &Env, tx_hash: BytesN<32>, log_index: U256, receiver: Address, token: Address, amount: i128) { | ||
pub(crate) fn refunded( | ||
env: &Env, | ||
tx_hash: BytesN<32>, | ||
log_index: U256, | ||
receiver: &Address, | ||
token: &Address, | ||
amount: i128, | ||
) { | ||
let topics = (symbol_short!("refunded"), tx_hash, log_index); | ||
env.events().publish(topics, (receiver, token, amount)); | ||
} | ||
|
||
pub(crate) fn native_gas_paid_for_contract_call(env: &Env, sender: Address, destination_chain: String, destination_address: String, payload: Bytes, refund_address: Address) { | ||
pub(crate) fn native_gas_paid_for_contract_call( | ||
env: &Env, | ||
sender: Address, | ||
destination_chain: String, | ||
destination_address: String, | ||
payload: Bytes, | ||
refund_address: Address, | ||
) { | ||
let topics = (symbol_short!("cc_g_paid"),); | ||
env.events().publish(topics, (sender, destination_chain, destination_address, env.crypto().keccak256(&payload), refund_address)); | ||
} | ||
env.events().publish( | ||
topics, | ||
( | ||
sender, | ||
destination_chain, | ||
destination_address, | ||
env.crypto().keccak256(&payload), | ||
refund_address, | ||
), | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,33 @@ | ||
use soroban_sdk::{Address, Bytes, BytesN, Env, String, U256}; | ||
use crate::error::Error; | ||
use soroban_sdk::{Address, Bytes, BytesN, Env, String, Vec, U256}; | ||
/// Interface for the Axelar Gas Service. | ||
// #[contractclient(crate_path = "crate", name = "AxelarGasService")] | ||
pub trait AxelarGasServiceInterface { | ||
|
||
/// Pay for gas using native currency for a contract call on a destination chain. This function is called on the source chain before calling the gateway to execute a remote contract. | ||
fn pay_native_gas_for_contract_call( env: Env, sender: Address, destination_chain: String, destination_address: String, payload: Bytes, refund_address: Address); | ||
|
||
fn pay_native_gas_for_contract_call( | ||
env: Env, | ||
sender: Address, | ||
destination_chain: String, | ||
destination_address: String, | ||
payload: Bytes, | ||
refund_address: Address, | ||
); | ||
|
||
/// Allows the gasCollector to collect accumulated fees from the contract. | ||
fn collect_fees(); | ||
|
||
/// Refunds gas payment to the receiver in relation to a specific cross-chain transaction. Only callable by the gasCollector. | ||
fn refund( env: Env, tx_hash: BytesN<32>, log_index: U256, receiver: Address, token: Address, amount: i128); | ||
fn collect_fees( | ||
env: Env, | ||
receiver: Address, | ||
token_addr: Vec<Address>, | ||
amounts: Vec<i128>, | ||
) -> Result<(), Error>; | ||
|
||
} | ||
/// Refunds gas payment to the receiver in relation to a specific cross-chain transaction. Only callable by the gasCollector. | ||
fn refund( | ||
env: Env, | ||
tx_hash: BytesN<32>, | ||
log_index: U256, | ||
receiver: Address, | ||
token: Address, | ||
amount: i128, | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,5 @@ use soroban_sdk::contracttype; | |
#[derive(Clone, Debug)] | ||
pub enum DataKey { | ||
Initialized, | ||
GasCollector, | ||
} |
Oops, something went wrong.