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