-
Notifications
You must be signed in to change notification settings - Fork 179
/
balance.go
67 lines (56 loc) · 2.45 KB
/
balance.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package types
import (
"encoding/binary"
"math/big"
"github.com/onflow/cadence"
)
var (
SmallestAcceptableBalanceValueInAttoFlow = new(big.Int).SetInt64(1e10)
OneFlowInAttoFlow = new(big.Int).SetInt64(1e18)
)
// Balance represents the balance of an address
// in the evm environment, balances are kept in attoflow (1e10^-18 flow),
// the smallest denomination of FLOW token (similar to how Wei is used to store Eth)
// But on the FLOW Vaults, we use Cadence.UFix64 to store values in Flow.
// this could result in accidental conversion mistakes, the balance object here would
// do the conversions and does appropriate checks.
//
// For example the smallest unit of Flow token that a FlowVault could store is 1e10^-8,
// so transfering smaller values (or values with smalls fractions) could result in loss in
// conversion. The balance object checks it to prevent invalid balance.
// This means that values smaller than 1e10^-8 flow could not be bridged between FVM and Flow EVM.
type Balance cadence.UFix64
// ToAttoFlow converts the balance into AttoFlow
func (b Balance) ToAttoFlow() *big.Int {
return new(big.Int).Mul(new(big.Int).SetUint64(uint64(b)), SmallestAcceptableBalanceValueInAttoFlow)
}
// Sub subtract the other balance from this balance
func (b Balance) Sub(other Balance) Balance {
// no need to check for underflow, as go does it
return Balance(uint64(b) - uint64(other))
}
// Add adds the other balance from this balance
func (b Balance) Add(other Balance) Balance {
// no need to check for overflow, as go does it
return Balance(uint64(b) + uint64(other))
}
// Encode encodes the balance into byte slice
func (b Balance) Encode() []byte {
encoded := make([]byte, 8)
binary.BigEndian.PutUint64(encoded, b.ToAttoFlow().Uint64())
return encoded
}
// DecodeBalance decodes a balance from an encoded byte slice
func DecodeBalance(encoded []byte) (Balance, error) {
balance := new(big.Int)
return NewBalanceFromAttoFlow(balance.SetUint64(binary.BigEndian.Uint64(encoded)))
}
// NewBalanceFromAttoFlow constructs a new balance from atto flow value
func NewBalanceFromAttoFlow(inp *big.Int) (Balance, error) {
if new(big.Int).Mod(inp, SmallestAcceptableBalanceValueInAttoFlow).Cmp(big.NewInt(0)) != 0 {
return 0, ErrBalanceConversion
}
// we only need to divide by 10 given we already have 8 as factor
converted := new(big.Int).Div(inp, SmallestAcceptableBalanceValueInAttoFlow)
return Balance(cadence.UFix64(converted.Uint64())), nil
}