Skip to content

Commit

Permalink
refactor(gas-service)!: support generic pay_gas method
Browse files Browse the repository at this point in the history
  • Loading branch information
milapsheth committed May 27, 2024
1 parent 4a4c832 commit ed76ea2
Showing 1 changed file with 181 additions and 23 deletions.
204 changes: 181 additions & 23 deletions move/gas_service/sources/gas_service/gas_service.move
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ module gas_service::gas_service {
use sui::hash::keccak256;
use sui::event;

// -----
// Types
// -----

public struct GasService has key, store {
id: UID,
balance: Balance<SUI>,
Expand All @@ -17,34 +21,42 @@ module gas_service::gas_service {
id: UID,
}

public struct NativeGasPaidForContractCall has copy, drop {
// ------
// Events
// ------

public struct GasPaid<phantom T> has copy, drop {
sender: address,
destination_chain: String,
destination_address: String,
payload_hash: address,
value: u64,
refund_address: address,
params: vector<u8>,
}

public struct NativeGasAdded has copy, drop {
tx_hash: address,
log_index: u64,
public struct GasAdded<phantom T> has copy, drop {
message_id: String,
value: u64,
refund_address: address,
params: vector<u8>,
}

public struct Refunded has copy, drop {
tx_hash: address,
log_index: u64,
public struct Refunded<phantom T> has copy, drop {
message_id: String,
value: u64,
refund_address: address,
}

public struct GasCollected has copy, drop {
public struct GasCollected<phantom T> has copy, drop {
receiver: address,
value: u64,
}

// -----
// Setup
// -----

fun init(ctx: &mut TxContext) {
transfer::share_object(GasService {
id: object::new(ctx),
Expand All @@ -56,43 +68,55 @@ module gas_service::gas_service {
}, ctx.sender());
}

// This can only be called once since it needs its own upgrade cap which it deletes.
public fun pay_native_gas_for_contract_call(
// ----------------
// Public Functions
// ----------------

/// Pay gas for a contract call.
/// This function is called by the channel that wants to pay gas for a contract call.
/// It can also be called by the user to pay gas for a contract call, while setting the sender as the channel ID.
public fun pay_gas(
self: &mut GasService,
coin: Coin<SUI>,
sender: address,
destination_chain: String,
destination_address: String,
payload: vector<u8>,
refund_address: address,
params: vector<u8>,
) {
let value = coin.value();
coin::put(&mut self.balance, coin);
let payload_hash = address::from_bytes(keccak256(&payload));
event::emit( NativeGasPaidForContractCall {

event::emit(GasPaid<SUI> {
sender,
destination_chain,
destination_address,
payload_hash,
value,
refund_address,
params,
})
}

public fun add_native_gas(
/// Add gas for an existing cross-chain contract call.
/// This function can be called by a user who wants to add gas for a contract call with insufficient gas.
public fun add_gas(
self: &mut GasService,
coin: Coin<SUI>,
tx_hash: address,
log_index: u64,
refund_address: address
message_id: String,
refund_address: address,
params: vector<u8>,
) {
let value = coin.value();
coin::put(&mut self.balance, coin);
event::emit( NativeGasAdded {
tx_hash,
log_index,

event::emit(GasAdded<SUI> {
message_id,
value,
refund_address,
params,
});
}

Expand All @@ -102,23 +126,157 @@ module gas_service::gas_service {
receiver,
);

event::emit(GasCollected {
event::emit(GasCollected<SUI> {
receiver,
value: amount,
});
}

public fun refund(self: &mut GasService, _: &GasCollectorCap, tx_hash: address, log_index: u64, receiver: address, amount: u64, ctx: &mut TxContext) {
public fun refund(self: &mut GasService, _: &GasCollectorCap, message_id: String, receiver: address, amount: u64, ctx: &mut TxContext) {
transfer::public_transfer(
coin::take(&mut self.balance, amount, ctx),
receiver,
);

event::emit(Refunded {
tx_hash,
log_index,
event::emit(Refunded<SUI> {
message_id,
value: amount,
refund_address: receiver,
});
}

// -----
// Tests
// -----

#[test_only]
fun new(ctx: &mut TxContext): (GasService, GasCollectorCap) {
let service = GasService {
id: object::new(ctx),
balance: balance::zero<SUI>(),
};

let cap = GasCollectorCap {
id: object::new(ctx),
};

(service, cap)
}

#[test_only]
fun destroy(self: GasService) {
let GasService { id, balance } = self;
id.delete();
balance.destroy_for_testing();
}

#[test_only]
fun destroy_cap(self: GasCollectorCap) {
let GasCollectorCap { id } = self;
id.delete();
}

#[test]
fun test_init() {
let ctx = &mut sui::tx_context::dummy();
init(ctx);
}

#[test]
fun test_pay_gas() {
let ctx = &mut sui::tx_context::dummy();
let (mut service, cap) = new(ctx);
let value = 10;
let c: Coin<SUI> = coin::mint_for_testing(value, ctx);

service.pay_gas(
c,
ctx.sender(),
std::ascii::string(b"destination chain"),
std::ascii::string(b"destination address"),
vector[],
ctx.sender(),
vector[],
);

assert!(service.balance.value() == value, 0);

cap.destroy_cap();
service.destroy();
}

#[test]
fun test_add_gas() {
let ctx = &mut sui::tx_context::dummy();
let (mut service, cap) = new(ctx);
let value = 10;
let c: Coin<SUI> = coin::mint_for_testing(value, ctx);

service.add_gas(
c,
std::ascii::string(b"message id"),
@0x0,
vector[],
);

assert!(service.balance.value() == value, 0);

cap.destroy_cap();
service.destroy();
}

#[test]
fun test_collect_gas() {
let ctx = &mut sui::tx_context::dummy();
let (mut service, cap) = new(ctx);
let value = 10;
let c: Coin<SUI> = coin::mint_for_testing(value, ctx);

service.add_gas(
c,
std::ascii::string(b"message id"),
@0x0,
vector[],
);

service.collect_gas(
&cap,
ctx.sender(),
value,
ctx,
);

assert!(service.balance.value() == 0, 0);

cap.destroy_cap();
service.destroy();
}

#[test]
fun test_refund() {
let ctx = &mut sui::tx_context::dummy();
let (mut service, cap) = new(ctx);
let value = 10;
let c: Coin<SUI> = coin::mint_for_testing(value, ctx);

service.add_gas(
c,
std::ascii::string(b"message id"),
@0x0,
vector[],
);

service.refund(
&cap,
std::ascii::string(b"message id"),
ctx.sender(),
value,
ctx,
);

assert!(service.balance.value() == 0, 0);

cap.destroy_cap();
service.destroy();
}
}

0 comments on commit ed76ea2

Please sign in to comment.