0x0::state
State module represents the current state of the pool. It maintains all the accounts, history, and governance information. It also processes all the transactions and updates the state accordingly.
State
StakeEvent
ProposalEvent
VoteEvent
RebateEvent
empty
process_create
withdraw_settled_amounts
process_cancel
process_modify
process_stake
process_unstake
process_proposal
process_vote
process_claim_rebates
governance
governance_mut
account_exists
account
history_mut
history
process_fills
update_account
use 0x0::account;
use 0x0::balances;
use 0x0::constants;
use 0x0::deep_price;
use 0x0::fill;
use 0x0::governance;
use 0x0::history;
use 0x0::math;
use 0x0::order;
use 0x0::order_info;
use 0x0::trade_params;
use 0x1::option;
use 0x2::event;
use 0x2::object;
use 0x2::table;
use 0x2::tx_context;
use 0x2::vec_set;
State
struct State has store
StakeEvent
struct StakeEvent has copy, drop
pool_id: object::ID
balance_manager_id: object::ID
epoch: u64
amount: u64
stake: bool
ProposalEvent
struct ProposalEvent has copy, drop
pool_id: object::ID
balance_manager_id: object::ID
epoch: u64
taker_fee: u64
maker_fee: u64
stake_required: u64
VoteEvent
struct VoteEvent has copy, drop
pool_id: object::ID
balance_manager_id: object::ID
epoch: u64
from_proposal_id: option::Option<object::ID>
to_proposal_id: object::ID
stake: u64
RebateEvent
struct RebateEvent has copy, drop
pool_id: object::ID
balance_manager_id: object::ID
epoch: u64
claim_amount: u64
const EAlreadyProposed: u64 = 3;
const EMaxOpenOrders: u64 = 2;
const ENoStake: u64 = 1;
empty
public(friend) fun empty(stable_pool: bool, ctx: &mut tx_context::TxContext): state::State
public(package) fun empty(stable_pool: bool, ctx: &mut TxContext): State {
let governance = governance::empty(
stable_pool,
ctx,
);
let trade_params = governance.trade_params();
let history = history::empty(trade_params, ctx.epoch(), ctx);
State { history, governance, accounts: table::new(ctx) }
}
process_create
Up until this point, an OrderInfo object has been created and potentially filled. The OrderInfo object contains all of the necessary information to update the state of the pool. This includes the volumes for the taker and potentially multiple makers. First, fills are iterated and processed, updating the appropriate user’s volumes. Funds are settled for those makers. Then, the taker’s trading fee is calculated and the taker’s volumes are updated. Finally, the taker’s balances are settled.
public(friend) fun process_create(self: &mut state::State, order_info: &mut order_info::OrderInfo, ctx: &tx_context::TxContext): (balances::Balances, balances::Balances)
public(package) fun process_create(
self: &mut State,
order_info: &mut OrderInfo,
ctx: &TxContext,
): (Balances, Balances) {
self.governance.update(ctx);
self.history.update(self.governance.trade_params(), ctx);
let fills = order_info.fills_ref();
self.process_fills(fills, ctx);
self.update_account(order_info.balance_manager_id(), ctx);
let account = &mut self.accounts[order_info.balance_manager_id()];
let account_volume = account.total_volume();
let account_stake = account.active_stake();
// avg exucuted price for taker
let avg_executed_price = if (order_info.executed_quantity() > 0) {
math::div(
order_info.cumulative_quote_quantity(),
order_info.executed_quantity(),
)
} else {
0
};
let account_volume_in_deep = order_info
.order_deep_price()
.deep_quantity_u128(
account_volume,
math::mul_u128(account_volume, avg_executed_price as u128),
);
// taker fee will almost be calculated as 0 for whitelisted pools by default, as account_volume_in_deep is 0
let taker_fee = self
.governance
.trade_params()
.taker_fee_for_user(account_stake, account_volume_in_deep);
let maker_fee = self.governance.trade_params().maker_fee();
if (order_info.order_inserted()) {
assert!(
account.open_orders().size() < constants::max_open_orders(),
EMaxOpenOrders,
);
account.add_order(order_info.order_id());
};
account.add_taker_volume(order_info.executed_quantity());
let (mut settled, mut owed) = order_info.calculate_partial_fill_balances(
taker_fee,
maker_fee,
);
let (old_settled, old_owed) = account.settle();
self
.history
.add_total_fees_collected(balances::new(0, 0, order_info.paid_fees()));
settled.add_balances(old_settled);
owed.add_balances(old_owed);
(settled, owed)
}
withdraw_settled_amounts
public(friend) fun withdraw_settled_amounts(self: &mut state::State, balance_manager_id: object::ID): (balances::Balances, balances::Balances)
public(package) fun withdraw_settled_amounts(
self: &mut State,
balance_manager_id: ID,
): (Balances, Balances) {
let account = &mut self.accounts[balance_manager_id];
account.settle()
}
process_cancel
Update account settled balances and volumes. Remove order from account orders.
public(friend) fun process_cancel(self: &mut state::State, order: &mut order::Order, balance_manager_id: object::ID, ctx: &tx_context::TxContext): (balances::Balances, balances::Balances)
public(package) fun process_cancel(
self: &mut State,
order: &mut Order,
balance_manager_id: ID,
ctx: &TxContext,
): (Balances, Balances) {
self.governance.update(ctx);
self.history.update(self.governance.trade_params(), ctx);
self.update_account(balance_manager_id, ctx);
order.set_canceled();
let epoch = order.epoch();
let maker_fee = self.history.historic_maker_fee(epoch);
let balances = order.calculate_cancel_refund(maker_fee, option::none());
let account = &mut self.accounts[balance_manager_id];
account.remove_order(order.order_id());
account.add_settled_balances(balances);
account.settle()
}
process_modify
Given the modified quantity, update account settled balances and volumes.
public(friend) fun process_modify(self: &mut state::State, balance_manager_id: object::ID, cancel_quantity: u64, order: &order::Order, ctx: &tx_context::TxContext): (balances::Balances, balances::Balances)
public(package) fun process_modify(
self: &mut State,
balance_manager_id: ID,
cancel_quantity: u64,
order: &Order,
ctx: &TxContext,
): (Balances, Balances) {
self.governance.update(ctx);
self.history.update(self.governance.trade_params(), ctx);
self.update_account(balance_manager_id, ctx);
let epoch = order.epoch();
let maker_fee = self.history.historic_maker_fee(epoch);
let balances = order.calculate_cancel_refund(
maker_fee,
option::some(cancel_quantity),
);
self.accounts[balance_manager_id].add_settled_balances(balances);
self.accounts[balance_manager_id].settle()
}
process_stake
Process stake transaction. Add stake to account and update governance.
public(friend) fun process_stake(self: &mut state::State, pool_id: object::ID, balance_manager_id: object::ID, new_stake: u64, ctx: &tx_context::TxContext): (balances::Balances, balances::Balances)
public(package) fun process_stake(
self: &mut State,
pool_id: ID,
balance_manager_id: ID,
new_stake: u64,
ctx: &TxContext,
): (Balances, Balances) {
self.governance.update(ctx);
self.history.update(self.governance.trade_params(), ctx);
self.update_account(balance_manager_id, ctx);
let (stake_before, stake_after) = self
.accounts[balance_manager_id]
.add_stake(new_stake);
self.governance.adjust_voting_power(stake_before, stake_after);
event::emit(StakeEvent {
pool_id,
balance_manager_id,
epoch: ctx.epoch(),
amount: new_stake,
stake: true,
});
self.accounts[balance_manager_id].settle()
}
process_unstake
Process unstake transaction. Remove stake from account and update governance.
public(friend) fun process_unstake(self: &mut state::State, pool_id: object::ID, balance_manager_id: object::ID, ctx: &tx_context::TxContext): (balances::Balances, balances::Balances)
public(package) fun process_unstake(
self: &mut State,
pool_id: ID,
balance_manager_id: ID,
ctx: &TxContext,
): (Balances, Balances) {
self.governance.update(ctx);
self.history.update(self.governance.trade_params(), ctx);
self.update_account(balance_manager_id, ctx);
let account = &mut self.accounts[balance_manager_id];
let active_stake = account.active_stake();
let inactive_stake = account.inactive_stake();
let voted_proposal = account.voted_proposal();
account.remove_stake();
self.governance.adjust_voting_power(active_stake + inactive_stake, 0);
self.governance.adjust_vote(voted_proposal, option::none(), active_stake);
event::emit(StakeEvent {
pool_id,
balance_manager_id,
epoch: ctx.epoch(),
amount: active_stake + inactive_stake,
stake: false,
});
account.settle()
}
process_proposal
Process proposal transaction. Add proposal to governance and update account.
public(friend) fun process_proposal(self: &mut state::State, pool_id: object::ID, balance_manager_id: object::ID, taker_fee: u64, maker_fee: u64, stake_required: u64, ctx: &tx_context::TxContext)
public(package) fun process_proposal(
self: &mut State,
pool_id: ID,
balance_manager_id: ID,
taker_fee: u64,
maker_fee: u64,
stake_required: u64,
ctx: &TxContext,
) {
self.governance.update(ctx);
self.history.update(self.governance.trade_params(), ctx);
self.update_account(balance_manager_id, ctx);
let account = &mut self.accounts[balance_manager_id];
let stake = account.active_stake();
let proposal_created = account.created_proposal();
assert!(stake > 0, ENoStake);
assert!(!proposal_created, EAlreadyProposed);
account.set_created_proposal(true);
self
.governance
.add_proposal(
taker_fee,
maker_fee,
stake_required,
stake,
balance_manager_id,
);
self.process_vote(pool_id, balance_manager_id, balance_manager_id, ctx);
event::emit(ProposalEvent {
pool_id,
balance_manager_id,
epoch: ctx.epoch(),
taker_fee,
maker_fee,
stake_required,
});
}
process_vote
Process vote transaction. Update account voted proposal and governance.
public(friend) fun process_vote(self: &mut state::State, pool_id: object::ID, balance_manager_id: object::ID, proposal_id: object::ID, ctx: &tx_context::TxContext)
public(package) fun process_vote(
self: &mut State,
pool_id: ID,
balance_manager_id: ID,
proposal_id: ID,
ctx: &TxContext,
) {
self.governance.update(ctx);
self.history.update(self.governance.trade_params(), ctx);
self.update_account(balance_manager_id, ctx);
let account = &mut self.accounts[balance_manager_id];
assert!(account.active_stake() > 0, ENoStake);
let prev_proposal = account.set_voted_proposal(option::some(proposal_id));
self
.governance
.adjust_vote(
prev_proposal,
option::some(proposal_id),
account.active_stake(),
);
event::emit(VoteEvent {
pool_id,
balance_manager_id,
epoch: ctx.epoch(),
from_proposal_id: prev_proposal,
to_proposal_id: proposal_id,
stake: account.active_stake(),
});
}
process_claim_rebates
Process claim rebates transaction. Update account rebates and settle balances.
public(friend) fun process_claim_rebates(self: &mut state::State, pool_id: object::ID, balance_manager_id: object::ID, ctx: &tx_context::TxContext): (balances::Balances, balances::Balances)
public(package) fun process_claim_rebates(
self: &mut State,
pool_id: ID,
balance_manager_id: ID,
ctx: &TxContext,
): (Balances, Balances) {
self.governance.update(ctx);
self.history.update(self.governance.trade_params(), ctx);
self.update_account(balance_manager_id, ctx);
let account = &mut self.accounts[balance_manager_id];
let claim_amount = account.claim_rebates();
event::emit(RebateEvent {
pool_id,
balance_manager_id,
epoch: ctx.epoch(),
claim_amount,
});
account.settle()
}
governance
public(friend) fun governance(self: &state::State): &governance::Governance
public(package) fun governance(self: &State): &Governance {
&self.governance
}
governance_mut
public(friend) fun governance_mut(self: &mut state::State, ctx: &tx_context::TxContext): &mut governance::Governance
public(package) fun governance_mut(
self: &mut State,
ctx: &TxContext,
): &mut Governance {
self.governance.update(ctx);
&mut self.governance
}
account_exists
public(friend) fun account_exists(self: &state::State, balance_manager_id: object::ID): bool
public(package) fun account_exists(self: &State, balance_manager_id: ID): bool {
self.accounts.contains(balance_manager_id)
}
account
public(friend) fun account(self: &state::State, balance_manager_id: object::ID): &account::Account
public(package) fun account(self: &State, balance_manager_id: ID): &Account {
&self.accounts[balance_manager_id]
}
history_mut
public(friend) fun history_mut(self: &mut state::State): &mut history::History
public(package) fun history_mut(self: &mut State): &mut History {
&mut self.history
}
history
public(friend) fun history(self: &state::State): &history::History
process_fills
Process fills for all makers. Update maker accounts and history.
fun process_fills(self: &mut state::State, fills: &mut vector<fill::Fill>, ctx: &tx_context::TxContext)
fun process_fills(self: &mut State, fills: &mut vector<Fill>, ctx: &TxContext) {
let whitelisted = self.governance.whitelisted();
let mut i = 0;
while (i < fills.length()) {
let fill = &mut fills[i];
let maker = fill.balance_manager_id();
self.update_account(maker, ctx);
let account = &mut self.accounts[maker];
account.process_maker_fill(fill);
let base_volume = fill.base_quantity();
let quote_volume = fill.quote_quantity();
let historic_maker_fee = self
.history
.historic_maker_fee(fill.maker_epoch());
let fee_volume = fill
.maker_deep_price()
.deep_quantity(base_volume, quote_volume);
let order_maker_fee = if (whitelisted) {
0
} else {
math::mul(fee_volume, historic_maker_fee)
};
if (!fill.expired()) {
if (order_maker_fee > 0) {
fill.set_fill_maker_fee(order_maker_fee);
};
self.history.add_volume(base_volume, account.active_stake());
self
.history
.add_total_fees_collected(balances::new(0, 0, order_maker_fee));
} else {
account.add_settled_balances(balances::new(0, 0, order_maker_fee));
};
i = i + 1;
};
}
update_account
If account doesn’t exist, create it. Update account volumes and rebates.
fun update_account(self: &mut state::State, balance_manager_id: object::ID, ctx: &tx_context::TxContext)
fun update_account(self: &mut State, balance_manager_id: ID, ctx: &TxContext) {
if (!self.accounts.contains(balance_manager_id)) {
self.accounts.add(balance_manager_id, account::empty(ctx));
};
let account = &mut self.accounts[balance_manager_id];
let (prev_epoch, maker_volume, active_stake) = account.update(ctx);
if (prev_epoch > 0 && maker_volume > 0 && active_stake > 0) {
let rebates = self
.history
.calculate_rebate_amount(prev_epoch, maker_volume, active_stake);
account.add_rebates(rebates);
}
}