channel_balance.gno
2.62 Kb · 65 lines
1package ucs03_zkgm
2
3import (
4 "encoding/hex"
5
6 types "gno.land/p/onbloc/ibc/union/types"
7
8 u256 "gno.land/p/onbloc/math/uint256"
9)
10
11// Precision invariant: channel balances are denominated in LOCAL VAULT precision —
12// the actual escrowed amount held on this chain (the grc20 ledger for vouchers,
13// the banker for native), 1:1 with custody — NOT the wire/counterparty precision.
14
15// ChannelBalanceKeyV2 returns the storage key for a v2 channel balance entry.
16func ChannelBalanceKeyV2(channelId types.ChannelId, path *u256.Uint, baseToken, quoteToken []byte) string {
17 return channelId.String() + "/" + path.ToString() + "/" + hex.EncodeToString(baseToken) + "/" + hex.EncodeToString(quoteToken)
18}
19
20// increaseChannelBalanceV2 adds amount to the (channel, path, base, quote) escrow balance.
21// reference: https://github.com/unionlabs/union/blob/d91c5e94354e15801bd5f82dc658eae3b79f2dad/cosmwasm/app/ucs03-zkgm/src/contract.rs#L3272-L3299
22func (v *ucs03ZkgmV1) increaseChannelBalanceV2(_ int, rlm realm, channelId types.ChannelId, path *u256.Uint, baseToken, quoteToken []byte, amount int64) error {
23 key := ChannelBalanceKeyV2(channelId, path, baseToken, quoteToken)
24
25 curAmount, ok := v.store.GetChannelBalanceV2(key)
26 if !ok || curAmount == nil {
27 curAmount = u256.Zero()
28 }
29
30 amountUint256 := u256.NewUint(uint64(amount))
31
32 // silently storing a smaller balance. This entrypoint returns no error,
33 // so an overflow aborts the tx via panic.
34 calculatedAmount, overflow := u256.Zero().AddOverflow(curAmount, amountUint256)
35 if overflow {
36 return makeError(errChannelBalanceOverflow)
37 }
38
39 v.store.SetChannelBalanceV2(0, rlm, key, calculatedAmount)
40
41 return nil
42}
43
44// decreaseChannelBalanceV2 subtracts from the escrow balance, erroring on underflow and preserving a zero entry.
45// reference: https://github.com/unionlabs/union/blob/d91c5e94354e15801bd5f82dc658eae3b79f2dad/cosmwasm/app/ucs03-zkgm/src/contract.rs#L3241-L3268
46func (v *ucs03ZkgmV1) decreaseChannelBalanceV2(_ int, rlm realm, channelId types.ChannelId, path *u256.Uint, baseToken, quoteToken []byte, amount int64) error {
47 key := ChannelBalanceKeyV2(channelId, path, baseToken, quoteToken)
48
49 amountUint256 := u256.NewUint(uint64(amount))
50
51 curAmount, ok := v.store.GetChannelBalanceV2(key)
52 if !ok || curAmount == nil || curAmount.Cmp(amountUint256) < 0 {
53 return makeError(errChannelBalanceUnderflow)
54 }
55
56 // This entrypoint returns an error, so an underflow aborts the tx via return.
57 calculatedAmount, underflow := u256.Zero().SubOverflow(curAmount, amountUint256)
58 if underflow {
59 return makeError(errChannelBalanceUnderflow)
60 }
61
62 v.store.SetChannelBalanceV2(0, rlm, key, calculatedAmount)
63
64 return nil
65}