github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/builtin/market/market_balances.go (about)

     1  package market
     2  
     3  import (
     4  	addr "github.com/filecoin-project/go-address"
     5  	"github.com/filecoin-project/go-state-types/abi"
     6  	"github.com/filecoin-project/go-state-types/big"
     7  	"github.com/filecoin-project/go-state-types/exitcode"
     8  	"golang.org/x/xerrors"
     9  )
    10  
    11  func (m *marketStateMutation) lockClientAndProviderBalances(proposal *DealProposal) error {
    12  	if err := m.maybeLockBalance(proposal.Client, proposal.ClientBalanceRequirement()); err != nil {
    13  		return xerrors.Errorf("failed to lock client funds: %w", err)
    14  	}
    15  	if err := m.maybeLockBalance(proposal.Provider, proposal.ProviderCollateral); err != nil {
    16  		return xerrors.Errorf("failed to lock provider funds: %w", err)
    17  	}
    18  
    19  	m.totalClientLockedCollateral = big.Add(m.totalClientLockedCollateral, proposal.ClientCollateral)
    20  	m.totalClientStorageFee = big.Add(m.totalClientStorageFee, proposal.TotalStorageFee())
    21  	m.totalProviderLockedCollateral = big.Add(m.totalProviderLockedCollateral, proposal.ProviderCollateral)
    22  	return nil
    23  }
    24  
    25  func (m *marketStateMutation) unlockBalance(addr addr.Address, amount abi.TokenAmount, lockReason BalanceLockingReason) error {
    26  	if amount.LessThan(big.Zero()) {
    27  		return xerrors.Errorf("unlock negative amount %v", amount)
    28  	}
    29  
    30  	err := m.lockedTable.MustSubtract(addr, amount)
    31  	if err != nil {
    32  		return xerrors.Errorf("subtracting from locked balance: %w", err)
    33  	}
    34  
    35  	switch lockReason {
    36  	case ClientCollateral:
    37  		m.totalClientLockedCollateral = big.Sub(m.totalClientLockedCollateral, amount)
    38  	case ClientStorageFee:
    39  		m.totalClientStorageFee = big.Sub(m.totalClientStorageFee, amount)
    40  	case ProviderCollateral:
    41  		m.totalProviderLockedCollateral = big.Sub(m.totalProviderLockedCollateral, amount)
    42  	}
    43  
    44  	return nil
    45  }
    46  
    47  // move funds from locked in client to available in provider
    48  func (m *marketStateMutation) transferBalance(fromAddr addr.Address, toAddr addr.Address, amount abi.TokenAmount) error {
    49  	if amount.LessThan(big.Zero()) {
    50  		return xerrors.Errorf("transfer negative amount %v", amount)
    51  	}
    52  	if err := m.escrowTable.MustSubtract(fromAddr, amount); err != nil {
    53  		return xerrors.Errorf("subtract from escrow: %w", err)
    54  	}
    55  	if err := m.unlockBalance(fromAddr, amount, ClientStorageFee); err != nil {
    56  		return xerrors.Errorf("subtract from locked: %w", err)
    57  	}
    58  	if err := m.escrowTable.Add(toAddr, amount); err != nil {
    59  		return xerrors.Errorf("add to escrow: %w", err)
    60  	}
    61  	return nil
    62  }
    63  
    64  func (m *marketStateMutation) slashBalance(addr addr.Address, amount abi.TokenAmount, reason BalanceLockingReason) error {
    65  	if amount.LessThan(big.Zero()) {
    66  		return xerrors.Errorf("negative amount to slash: %v", amount)
    67  	}
    68  
    69  	if err := m.escrowTable.MustSubtract(addr, amount); err != nil {
    70  		return xerrors.Errorf("subtract from escrow: %v", err)
    71  	}
    72  
    73  	return m.unlockBalance(addr, amount, reason)
    74  }
    75  
    76  func (m *marketStateMutation) maybeLockBalance(addr addr.Address, amount abi.TokenAmount) error {
    77  	if amount.LessThan(big.Zero()) {
    78  		return xerrors.Errorf("cannot lock negative amount %v", amount)
    79  	}
    80  
    81  	prevLocked, err := m.lockedTable.Get(addr)
    82  	if err != nil {
    83  		return xerrors.Errorf("failed to get locked balance: %w", err)
    84  	}
    85  
    86  	escrowBalance, err := m.escrowTable.Get(addr)
    87  	if err != nil {
    88  		return xerrors.Errorf("failed to get escrow balance: %w", err)
    89  	}
    90  
    91  	if big.Add(prevLocked, amount).GreaterThan(escrowBalance) {
    92  		return exitcode.ErrInsufficientFunds.Wrapf("insufficient balance for addr %s: escrow balance %s < locked %s + required %s",
    93  			addr, escrowBalance, prevLocked, amount)
    94  	}
    95  
    96  	if err := m.lockedTable.Add(addr, amount); err != nil {
    97  		return xerrors.Errorf("failed to add locked balance: %w", err)
    98  	}
    99  	return nil
   100  }