axelar-cgp-sui

Module 0x0::balance_manager

The BalanceManager is a shared object that holds all of the balances for different assets. A combination of BalanceManager and TradeProof are passed into a pool to perform trades. A TradeProof can be generated in two ways: by the owner directly, or by any TradeCap owner. The owner can generate a TradeProof without the risk of equivocation. The TradeCap owner, due to it being an owned object, risks equivocation when generating a TradeProof. Generally, a high frequency trading engine will trade as the default owner.

use 0x1::type_name;
use 0x2::bag;
use 0x2::balance;
use 0x2::coin;
use 0x2::event;
use 0x2::object;
use 0x2::tx_context;
use 0x2::vec_set;

Resource BalanceManager

A shared object that is passed into pools for placing orders.

struct BalanceManager has store, key
Fields
id: object::UID
owner: address
balances: bag::Bag
allow_listed: vec_set::VecSet<object::ID>

Struct BalanceEvent

Event emitted when a deposit or withdrawal occurs.

struct BalanceEvent has copy, drop
Fields
balance_manager_id: object::ID
asset: type_name::TypeName
amount: u64
deposit: bool

Struct BalanceKey

Balance identifier.

struct BalanceKey<T> has copy, drop, store
Fields
dummy_field: bool

Resource TradeCap

Owners of a TradeCap need to get a TradeProof to trade across pools in a single PTB (drops after).

struct TradeCap has store, key
Fields
id: object::UID
balance_manager_id: object::ID

Struct TradeProof

BalanceManager owner and TradeCap owners can generate a TradeProof. TradeProof is used to validate the balance_manager when trading on DeepBook.

struct TradeProof has drop
Fields
balance_manager_id: object::ID
trader: address

Constants

const EBalanceManagerBalanceTooLow: u64 = 3;

const EInvalidOwner: u64 = 0;

const EInvalidProof: u64 = 2;

const EInvalidTrader: u64 = 1;

const EMaxTradeCapsReached: u64 = 4;

const ETradeCapNotInList: u64 = 5;

const MAX_TRADE_CAPS: u64 = 1000;

Function new

public fun new(ctx: &mut tx_context::TxContext): balance_manager::BalanceManager
Implementation
public fun new(ctx: &mut TxContext): BalanceManager {
    BalanceManager {
        id: object::new(ctx),
        owner: ctx.sender(),
        balances: bag::new(ctx),
        allow_listed: vec_set::empty(),
    }
}

Function balance

Returns the balance of a Coin in a balance_manager.

public fun balance<T>(balance_manager: &balance_manager::BalanceManager): u64
Implementation
public fun balance<T>(balance_manager: &BalanceManager): u64 {
    let key = BalanceKey<T> {};
    if (!balance_manager.balances.contains(key)) {
        0
    } else {
        let acc_balance: &Balance<T> = &balance_manager.balances[key];
        acc_balance.value()
    }
}

Function mint_trade_cap

Mint a TradeCap, only owner can mint a TradeCap.

public fun mint_trade_cap(balance_manager: &mut balance_manager::BalanceManager, ctx: &mut tx_context::TxContext): balance_manager::TradeCap
Implementation
public fun mint_trade_cap(
    balance_manager: &mut BalanceManager,
    ctx: &mut TxContext,
): TradeCap {
    balance_manager.validate_owner(ctx);
    assert!(
        balance_manager.allow_listed.size() < MAX_TRADE_CAPS,
        EMaxTradeCapsReached,
    );

    let id = object::new(ctx);
    balance_manager.allow_listed.insert(id.to_inner());

    TradeCap {
        id,
        balance_manager_id: object::id(balance_manager),
    }
}

Function revoke_trade_cap

Revoke a TradeCap. Only the owner can revoke a TradeCap.

public fun revoke_trade_cap(balance_manager: &mut balance_manager::BalanceManager, trade_cap_id: &object::ID, ctx: &tx_context::TxContext)
Implementation
public fun revoke_trade_cap(
    balance_manager: &mut BalanceManager,
    trade_cap_id: &ID,
    ctx: &TxContext,
) {
    balance_manager.validate_owner(ctx);

    assert!(
        balance_manager.allow_listed.contains(trade_cap_id),
        ETradeCapNotInList,
    );
    balance_manager.allow_listed.remove(trade_cap_id);
}

Function generate_proof_as_owner

Generate a TradeProof by the owner. The owner does not require a capability and can generate TradeProofs without the risk of equivocation.

public fun generate_proof_as_owner(balance_manager: &mut balance_manager::BalanceManager, ctx: &tx_context::TxContext): balance_manager::TradeProof
Implementation
public fun generate_proof_as_owner(
    balance_manager: &mut BalanceManager,
    ctx: &TxContext,
): TradeProof {
    balance_manager.validate_owner(ctx);

    TradeProof {
        balance_manager_id: object::id(balance_manager),
        trader: ctx.sender(),
    }
}

Function generate_proof_as_trader

Generate a TradeProof with a TradeCap. Risk of equivocation since TradeCap is an owned object.

public fun generate_proof_as_trader(balance_manager: &mut balance_manager::BalanceManager, trade_cap: &balance_manager::TradeCap, ctx: &tx_context::TxContext): balance_manager::TradeProof
Implementation
public fun generate_proof_as_trader(
    balance_manager: &mut BalanceManager,
    trade_cap: &TradeCap,
    ctx: &TxContext,
): TradeProof {
    balance_manager.validate_trader(trade_cap);

    TradeProof {
        balance_manager_id: object::id(balance_manager),
        trader: ctx.sender(),
    }
}

Function deposit

Deposit funds to a balance_manager. Only owner can call this directly.

public fun deposit<T>(balance_manager: &mut balance_manager::BalanceManager, coin: coin::Coin<T>, ctx: &mut tx_context::TxContext)
Implementation
public fun deposit<T>(
    balance_manager: &mut BalanceManager,
    coin: Coin<T>,
    ctx: &mut TxContext,
) {
    event::emit(BalanceEvent {
        balance_manager_id: object::id(balance_manager),
        asset: type_name::get<T>(),
        amount: coin.value(),
        deposit: true,
    });

    let proof = generate_proof_as_owner(balance_manager, ctx);
    balance_manager.deposit_with_proof(&proof, coin.into_balance());
}

Function withdraw

Withdraw funds from a balance_manager. Only owner can call this directly. If withdraw_all is true, amount is ignored and full balance withdrawn. If withdraw_all is false, withdraw_amount will be withdrawn.

public fun withdraw<T>(balance_manager: &mut balance_manager::BalanceManager, withdraw_amount: u64, ctx: &mut tx_context::TxContext): coin::Coin<T>
Implementation
public fun withdraw<T>(
    balance_manager: &mut BalanceManager,
    withdraw_amount: u64,
    ctx: &mut TxContext,
): Coin<T> {
    let proof = generate_proof_as_owner(balance_manager, ctx);
    let coin = balance_manager
        .withdraw_with_proof(&proof, withdraw_amount, false)
        .into_coin(ctx);
    event::emit(BalanceEvent {
        balance_manager_id: object::id(balance_manager),
        asset: type_name::get<T>(),
        amount: coin.value(),
        deposit: false,
    });

    coin
}

Function withdraw_all

public fun withdraw_all<T>(balance_manager: &mut balance_manager::BalanceManager, ctx: &mut tx_context::TxContext): coin::Coin<T>
Implementation
public fun withdraw_all<T>(
    balance_manager: &mut BalanceManager,
    ctx: &mut TxContext,
): Coin<T> {
    let proof = generate_proof_as_owner(balance_manager, ctx);
    let coin = balance_manager
        .withdraw_with_proof(&proof, 0, true)
        .into_coin(ctx);
    event::emit(BalanceEvent {
        balance_manager_id: object::id(balance_manager),
        asset: type_name::get<T>(),
        amount: coin.value(),
        deposit: false,
    });

    coin
}

Function validate_proof

public fun validate_proof(balance_manager: &balance_manager::BalanceManager, proof: &balance_manager::TradeProof)
Implementation
public fun validate_proof(
    balance_manager: &BalanceManager,
    proof: &TradeProof,
) {
    assert!(
        object::id(balance_manager) == proof.balance_manager_id,
        EInvalidProof,
    );
}

Function owner

Returns the owner of the balance_manager.

public fun owner(balance_manager: &balance_manager::BalanceManager): address
Implementation
public fun owner(balance_manager: &BalanceManager): address {
    balance_manager.owner
}

Function id

Returns the owner of the balance_manager.

public fun id(balance_manager: &balance_manager::BalanceManager): object::ID
Implementation
public fun id(balance_manager: &BalanceManager): ID {
    balance_manager.id.to_inner()
}

Function deposit_with_proof

Deposit funds to a balance_manager. Pool will call this to deposit funds.

public(friend) fun deposit_with_proof<T>(balance_manager: &mut balance_manager::BalanceManager, proof: &balance_manager::TradeProof, to_deposit: balance::Balance<T>)
Implementation
public(package) fun deposit_with_proof<T>(
    balance_manager: &mut BalanceManager,
    proof: &TradeProof,
    to_deposit: Balance<T>,
) {
    balance_manager.validate_proof(proof);

    let key = BalanceKey<T> {};

    if (balance_manager.balances.contains(key)) {
        let balance: &mut Balance<T> = &mut balance_manager.balances[key];
        balance.join(to_deposit);
    } else {
        balance_manager.balances.add(key, to_deposit);
    }
}

Function withdraw_with_proof

Withdraw funds from a balance_manager. Pool will call this to withdraw funds.

public(friend) fun withdraw_with_proof<T>(balance_manager: &mut balance_manager::BalanceManager, proof: &balance_manager::TradeProof, withdraw_amount: u64, withdraw_all: bool): balance::Balance<T>
Implementation
public(package) fun withdraw_with_proof<T>(
    balance_manager: &mut BalanceManager,
    proof: &TradeProof,
    withdraw_amount: u64,
    withdraw_all: bool,
): Balance<T> {
    balance_manager.validate_proof(proof);

    let key = BalanceKey<T> {};
    let key_exists = balance_manager.balances.contains(key);
    if (withdraw_all) {
        if (key_exists) {
            balance_manager.balances.remove(key)
        } else {
            balance::zero()
        }
    } else {
        assert!(key_exists, EBalanceManagerBalanceTooLow);
        let acc_balance: &mut Balance<T> = &mut balance_manager.balances[key];
        let acc_value = acc_balance.value();
        assert!(acc_value >= withdraw_amount, EBalanceManagerBalanceTooLow);
        if (withdraw_amount == acc_value) {
            balance_manager.balances.remove(key)
        } else {
            acc_balance.split(withdraw_amount)
        }
    }
}

Function delete

Deletes a balance_manager. This is used for deleting temporary balance_managers for direct swap with pool.

public(friend) fun delete(balance_manager: balance_manager::BalanceManager)
Implementation
public(package) fun delete(balance_manager: BalanceManager) {
    let BalanceManager {
        id,
        owner: _,
        balances,
        allow_listed: _,
    } = balance_manager;

    id.delete();
    balances.destroy_empty();
}

Function trader

public(friend) fun trader(trade_proof: &balance_manager::TradeProof): address
Implementation
public(package) fun trader(trade_proof: &TradeProof): address {
    trade_proof.trader
}

Function validate_owner

fun validate_owner(balance_manager: &balance_manager::BalanceManager, ctx: &tx_context::TxContext)
Implementation
fun validate_owner(balance_manager: &BalanceManager, ctx: &TxContext) {
    assert!(ctx.sender() == balance_manager.owner(), EInvalidOwner);
}

Function validate_trader

fun validate_trader(balance_manager: &balance_manager::BalanceManager, trade_cap: &balance_manager::TradeCap)
Implementation
fun validate_trader(balance_manager: &BalanceManager, trade_cap: &TradeCap) {
    assert!(
        balance_manager.allow_listed.contains(object::borrow_id(trade_cap)),
        EInvalidTrader,
    );
}