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  }