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

     1  package market_test
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"errors"
     7  	"strings"
     8  	"testing"
     9  
    10  	address "github.com/filecoin-project/go-address"
    11  	"github.com/filecoin-project/go-state-types/abi"
    12  	"github.com/filecoin-project/go-state-types/big"
    13  	"github.com/filecoin-project/go-state-types/cbor"
    14  	"github.com/filecoin-project/go-state-types/crypto"
    15  	"github.com/filecoin-project/go-state-types/exitcode"
    16  	cid "github.com/ipfs/go-cid"
    17  	cbg "github.com/whyrusleeping/cbor-gen"
    18  
    19  	"github.com/filecoin-project/specs-actors/v4/actors/builtin"
    20  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/market"
    21  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/miner"
    22  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/power"
    23  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/reward"
    24  	"github.com/filecoin-project/specs-actors/v4/actors/builtin/verifreg"
    25  	"github.com/filecoin-project/specs-actors/v4/actors/util/adt"
    26  	"github.com/filecoin-project/specs-actors/v4/support/mock"
    27  	tutil "github.com/filecoin-project/specs-actors/v4/support/testing"
    28  
    29  	"github.com/stretchr/testify/assert"
    30  	"github.com/stretchr/testify/require"
    31  )
    32  
    33  func mustCbor(o cbor.Marshaler) []byte {
    34  	buf := new(bytes.Buffer)
    35  	if err := o.MarshalCBOR(buf); err != nil {
    36  		panic(err)
    37  	}
    38  
    39  	return buf.Bytes()
    40  }
    41  
    42  func TestExports(t *testing.T) {
    43  	mock.CheckActorExports(t, market.Actor{})
    44  }
    45  
    46  func TestRemoveAllError(t *testing.T) {
    47  	marketActor := tutil.NewIDAddr(t, 100)
    48  	builder := mock.NewBuilder(marketActor)
    49  	rt := builder.Build(t)
    50  	store := adt.AsStore(rt)
    51  
    52  	smm, err := market.MakeEmptySetMultimap(store, builtin.DefaultHamtBitwidth)
    53  	require.NoError(t, err)
    54  
    55  	if err := smm.RemoveAll(42); err != nil {
    56  		t.Fatalf("expected no error, got: %s", err)
    57  	}
    58  }
    59  
    60  func TestMarketActor(t *testing.T) {
    61  	owner := tutil.NewIDAddr(t, 101)
    62  	provider := tutil.NewIDAddr(t, 102)
    63  	worker := tutil.NewIDAddr(t, 103)
    64  	client := tutil.NewIDAddr(t, 104)
    65  	minerAddrs := &minerAddrs{owner, worker, provider, nil}
    66  
    67  	var st market.State
    68  
    69  	t.Run("simple construction", func(t *testing.T) {
    70  		actor := market.Actor{}
    71  		receiver := tutil.NewIDAddr(t, 100)
    72  		builder := mock.NewBuilder(receiver).
    73  			WithCaller(builtin.SystemActorAddr, builtin.InitActorCodeID)
    74  
    75  		rt := builder.Build(t)
    76  
    77  		rt.ExpectValidateCallerAddr(builtin.SystemActorAddr)
    78  
    79  		ret := rt.Call(actor.Constructor, nil).(*abi.EmptyValue)
    80  		assert.Nil(t, ret)
    81  		rt.Verify()
    82  
    83  		store := adt.AsStore(rt)
    84  
    85  		emptyBalanceTable, err := adt.StoreEmptyMap(store, adt.BalanceTableBitwidth)
    86  		assert.NoError(t, err)
    87  
    88  		emptyMap, err := adt.StoreEmptyMap(store, builtin.DefaultHamtBitwidth)
    89  		assert.NoError(t, err)
    90  
    91  		emptyProposalsArrayCid, err := adt.StoreEmptyArray(store, market.ProposalsAmtBitwidth)
    92  		assert.NoError(t, err)
    93  
    94  		emptyStatesArrayCid, err := adt.StoreEmptyArray(store, market.StatesAmtBitwidth)
    95  		assert.NoError(t, err)
    96  
    97  		emptyMultiMap, err := market.StoreEmptySetMultimap(store, builtin.DefaultHamtBitwidth)
    98  		assert.NoError(t, err)
    99  
   100  		var state market.State
   101  		rt.GetState(&state)
   102  
   103  		assert.Equal(t, emptyProposalsArrayCid, state.Proposals)
   104  		assert.Equal(t, emptyStatesArrayCid, state.States)
   105  		assert.Equal(t, emptyMap, state.PendingProposals)
   106  		assert.Equal(t, emptyBalanceTable, state.EscrowTable)
   107  		assert.Equal(t, emptyBalanceTable, state.LockedTable)
   108  		assert.Equal(t, abi.DealID(0), state.NextID)
   109  		assert.Equal(t, emptyMultiMap, state.DealOpsByEpoch)
   110  		assert.Equal(t, abi.ChainEpoch(-1), state.LastCron)
   111  	})
   112  
   113  	t.Run("AddBalance", func(t *testing.T) {
   114  		t.Run("adds to provider escrow funds", func(t *testing.T) {
   115  			testCases := []struct {
   116  				delta int64
   117  				total int64
   118  			}{
   119  				{10, 10},
   120  				{20, 30},
   121  				{40, 70},
   122  			}
   123  
   124  			// Test adding provider funds from both worker and owner address
   125  			for _, callerAddr := range []address.Address{owner, worker} {
   126  				rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   127  
   128  				for _, tc := range testCases {
   129  					rt.SetCaller(callerAddr, builtin.AccountActorCodeID)
   130  					rt.SetReceived(abi.NewTokenAmount(tc.delta))
   131  					rt.ExpectValidateCallerType(builtin.CallerTypesSignable...)
   132  					expectGetControlAddresses(rt, provider, owner, worker)
   133  
   134  					rt.Call(actor.AddBalance, &provider)
   135  
   136  					rt.Verify()
   137  
   138  					rt.GetState(&st)
   139  					assert.Equal(t, abi.NewTokenAmount(tc.total), actor.getEscrowBalance(rt, provider))
   140  
   141  					actor.checkState(rt)
   142  				}
   143  			}
   144  		})
   145  
   146  		t.Run("fails unless called by an account actor", func(t *testing.T) {
   147  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   148  
   149  			rt.SetReceived(abi.NewTokenAmount(10))
   150  			rt.ExpectValidateCallerType(builtin.CallerTypesSignable...)
   151  
   152  			rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
   153  			rt.ExpectAbort(exitcode.SysErrForbidden, func() {
   154  				rt.Call(actor.AddBalance, &provider)
   155  			})
   156  
   157  			rt.Verify()
   158  
   159  			actor.checkState(rt)
   160  		})
   161  
   162  		t.Run("adds to non-provider escrow funds", func(t *testing.T) {
   163  			testCases := []struct {
   164  				delta int64
   165  				total int64
   166  			}{
   167  				{10, 10},
   168  				{20, 30},
   169  				{40, 70},
   170  			}
   171  
   172  			// Test adding non-provider funds from both worker and client addresses
   173  			for _, callerAddr := range []address.Address{client, worker} {
   174  				rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   175  
   176  				for _, tc := range testCases {
   177  					rt.SetCaller(callerAddr, builtin.AccountActorCodeID)
   178  					rt.SetReceived(abi.NewTokenAmount(tc.delta))
   179  					rt.ExpectValidateCallerType(builtin.CallerTypesSignable...)
   180  
   181  					rt.Call(actor.AddBalance, &callerAddr)
   182  
   183  					rt.Verify()
   184  
   185  					rt.GetState(&st)
   186  					assert.Equal(t, abi.NewTokenAmount(tc.total), actor.getEscrowBalance(rt, callerAddr))
   187  
   188  					actor.checkState(rt)
   189  				}
   190  			}
   191  		})
   192  
   193  		t.Run("fail when balance is zero", func(t *testing.T) {
   194  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   195  
   196  			rt.SetCaller(tutil.NewIDAddr(t, 101), builtin.AccountActorCodeID)
   197  			rt.SetReceived(big.Zero())
   198  
   199  			rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
   200  				rt.Call(actor.AddBalance, &provider)
   201  			})
   202  			rt.Verify()
   203  
   204  			actor.checkState(rt)
   205  		})
   206  	})
   207  
   208  	t.Run("WithdrawBalance", func(t *testing.T) {
   209  		startEpoch := abi.ChainEpoch(10)
   210  		endEpoch := startEpoch + 200*builtin.EpochsInDay
   211  		publishEpoch := abi.ChainEpoch(5)
   212  
   213  		t.Run("fails with a negative withdraw amount", func(t *testing.T) {
   214  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   215  
   216  			params := market.WithdrawBalanceParams{
   217  				ProviderOrClientAddress: provider,
   218  				Amount:                  abi.NewTokenAmount(-1),
   219  			}
   220  
   221  			rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
   222  				rt.Call(actor.WithdrawBalance, &params)
   223  			})
   224  
   225  			rt.Verify()
   226  			actor.checkState(rt)
   227  		})
   228  
   229  		t.Run("fails if withdraw from non provider funds is not initiated by the recipient", func(t *testing.T) {
   230  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   231  			actor.addParticipantFunds(rt, client, abi.NewTokenAmount(20))
   232  
   233  			rt.GetState(&st)
   234  			assert.Equal(t, abi.NewTokenAmount(20), actor.getEscrowBalance(rt, client))
   235  
   236  			rt.ExpectValidateCallerAddr(client)
   237  			params := market.WithdrawBalanceParams{
   238  				ProviderOrClientAddress: client,
   239  				Amount:                  abi.NewTokenAmount(1),
   240  			}
   241  
   242  			// caller is not the recipient
   243  			rt.SetCaller(tutil.NewIDAddr(t, 909), builtin.AccountActorCodeID)
   244  			rt.ExpectAbort(exitcode.SysErrForbidden, func() {
   245  				rt.Call(actor.WithdrawBalance, &params)
   246  			})
   247  			rt.Verify()
   248  
   249  			// verify there was no withdrawal
   250  			rt.GetState(&st)
   251  			assert.Equal(t, abi.NewTokenAmount(20), actor.getEscrowBalance(rt, client))
   252  
   253  			actor.checkState(rt)
   254  		})
   255  
   256  		t.Run("fails if withdraw from provider funds is not initiated by the owner or worker", func(t *testing.T) {
   257  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   258  			actor.addProviderFunds(rt, abi.NewTokenAmount(20), minerAddrs)
   259  
   260  			rt.GetState(&st)
   261  			assert.Equal(t, abi.NewTokenAmount(20), actor.getEscrowBalance(rt, provider))
   262  
   263  			// only signing parties can add balance for client AND provider.
   264  			rt.ExpectValidateCallerAddr(owner, worker)
   265  			params := market.WithdrawBalanceParams{
   266  				ProviderOrClientAddress: provider,
   267  				Amount:                  abi.NewTokenAmount(1),
   268  			}
   269  
   270  			// caller is not owner or worker
   271  			rt.SetCaller(tutil.NewIDAddr(t, 909), builtin.AccountActorCodeID)
   272  			expectGetControlAddresses(rt, provider, owner, worker)
   273  
   274  			rt.ExpectAbort(exitcode.SysErrForbidden, func() {
   275  				rt.Call(actor.WithdrawBalance, &params)
   276  			})
   277  			rt.Verify()
   278  
   279  			// verify there was no withdrawal
   280  			rt.GetState(&st)
   281  			assert.Equal(t, abi.NewTokenAmount(20), actor.getEscrowBalance(rt, provider))
   282  
   283  			actor.checkState(rt)
   284  		})
   285  
   286  		t.Run("withdraws from provider escrow funds and sends to owner", func(t *testing.T) {
   287  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   288  
   289  			actor.addProviderFunds(rt, abi.NewTokenAmount(20), minerAddrs)
   290  
   291  			rt.GetState(&st)
   292  			assert.Equal(t, abi.NewTokenAmount(20), actor.getEscrowBalance(rt, provider))
   293  
   294  			// worker calls WithdrawBalance, balance is transferred to owner
   295  			withdrawAmount := abi.NewTokenAmount(1)
   296  			actor.withdrawProviderBalance(rt, withdrawAmount, withdrawAmount, minerAddrs)
   297  
   298  			rt.GetState(&st)
   299  			assert.Equal(t, abi.NewTokenAmount(19), actor.getEscrowBalance(rt, provider))
   300  
   301  			actor.checkState(rt)
   302  		})
   303  
   304  		t.Run("withdraws from non-provider escrow funds", func(t *testing.T) {
   305  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   306  			actor.addParticipantFunds(rt, client, abi.NewTokenAmount(20))
   307  
   308  			rt.GetState(&st)
   309  			assert.Equal(t, abi.NewTokenAmount(20), actor.getEscrowBalance(rt, client))
   310  
   311  			withdrawAmount := abi.NewTokenAmount(1)
   312  			actor.withdrawClientBalance(rt, client, withdrawAmount, withdrawAmount)
   313  
   314  			rt.GetState(&st)
   315  			assert.Equal(t, abi.NewTokenAmount(19), actor.getEscrowBalance(rt, client))
   316  
   317  			actor.checkState(rt)
   318  		})
   319  
   320  		t.Run("client withdrawing more than escrow balance limits to available funds", func(t *testing.T) {
   321  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   322  			actor.addParticipantFunds(rt, client, abi.NewTokenAmount(20))
   323  
   324  			// withdraw amount greater than escrow balance
   325  			withdrawAmount := abi.NewTokenAmount(25)
   326  			expectedAmount := abi.NewTokenAmount(20)
   327  			actor.withdrawClientBalance(rt, client, withdrawAmount, expectedAmount)
   328  
   329  			actor.assertAccountZero(rt, client)
   330  
   331  			actor.checkState(rt)
   332  		})
   333  
   334  		t.Run("worker withdrawing more than escrow balance limits to available funds", func(t *testing.T) {
   335  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   336  			actor.addProviderFunds(rt, abi.NewTokenAmount(20), minerAddrs)
   337  
   338  			rt.GetState(&st)
   339  			assert.Equal(t, abi.NewTokenAmount(20), actor.getEscrowBalance(rt, provider))
   340  
   341  			// withdraw amount greater than escrow balance
   342  			withdrawAmount := abi.NewTokenAmount(25)
   343  			actualWithdrawn := abi.NewTokenAmount(20)
   344  			actor.withdrawProviderBalance(rt, withdrawAmount, actualWithdrawn, minerAddrs)
   345  
   346  			actor.assertAccountZero(rt, provider)
   347  
   348  			actor.checkState(rt)
   349  		})
   350  
   351  		t.Run("balance after withdrawal must ALWAYS be greater than or equal to locked amount", func(t *testing.T) {
   352  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   353  
   354  			// publish the deal so that client AND provider collateral is locked
   355  			rt.SetEpoch(publishEpoch)
   356  			dealId := actor.generateAndPublishDeal(rt, client, minerAddrs, startEpoch, endEpoch, startEpoch)
   357  			deal := actor.getDealProposal(rt, dealId)
   358  			rt.GetState(&st)
   359  			require.Equal(t, deal.ProviderCollateral, actor.getEscrowBalance(rt, provider))
   360  			require.Equal(t, deal.ClientBalanceRequirement(), actor.getEscrowBalance(rt, client))
   361  
   362  			withDrawAmt := abi.NewTokenAmount(1)
   363  			withDrawableAmt := abi.NewTokenAmount(0)
   364  			// client cannot withdraw any funds since all it's balance is locked
   365  			actor.withdrawClientBalance(rt, client, withDrawAmt, withDrawableAmt)
   366  			//  provider cannot withdraw any funds since all it's balance is locked
   367  			actor.withdrawProviderBalance(rt, withDrawAmt, withDrawableAmt, minerAddrs)
   368  
   369  			// add some more funds to the provider & ensure withdrawal is limited by the locked funds
   370  			withDrawAmt = abi.NewTokenAmount(30)
   371  			withDrawableAmt = abi.NewTokenAmount(25)
   372  			actor.addProviderFunds(rt, withDrawableAmt, minerAddrs)
   373  			actor.withdrawProviderBalance(rt, withDrawAmt, withDrawableAmt, minerAddrs)
   374  
   375  			// add some more funds to the client & ensure withdrawal is limited by the locked funds
   376  			actor.addParticipantFunds(rt, client, withDrawableAmt)
   377  			actor.withdrawClientBalance(rt, client, withDrawAmt, withDrawableAmt)
   378  
   379  			actor.checkState(rt)
   380  		})
   381  
   382  		t.Run("worker balance after withdrawal must account for slashed funds", func(t *testing.T) {
   383  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   384  
   385  			// publish deal
   386  			rt.SetEpoch(publishEpoch)
   387  			dealID := actor.generateAndPublishDeal(rt, client, minerAddrs, startEpoch, endEpoch, startEpoch)
   388  
   389  			// activate the deal
   390  			actor.activateDeals(rt, endEpoch+1, provider, publishEpoch, dealID)
   391  			st := actor.getDealState(rt, dealID)
   392  			require.EqualValues(t, publishEpoch, st.SectorStartEpoch)
   393  
   394  			// slash the deal
   395  			newEpoch := publishEpoch + 1
   396  			rt.SetEpoch(newEpoch)
   397  			actor.terminateDeals(rt, provider, dealID)
   398  			st = actor.getDealState(rt, dealID)
   399  			require.EqualValues(t, publishEpoch+1, st.SlashEpoch)
   400  
   401  			// provider cannot withdraw any funds since all it's balance is locked
   402  			withDrawAmt := abi.NewTokenAmount(1)
   403  			actualWithdrawn := abi.NewTokenAmount(0)
   404  			actor.withdrawProviderBalance(rt, withDrawAmt, actualWithdrawn, minerAddrs)
   405  
   406  			// add some more funds to the provider & ensure withdrawal is limited by the locked funds
   407  			actor.addProviderFunds(rt, abi.NewTokenAmount(25), minerAddrs)
   408  			withDrawAmt = abi.NewTokenAmount(30)
   409  			actualWithdrawn = abi.NewTokenAmount(25)
   410  
   411  			actor.withdrawProviderBalance(rt, withDrawAmt, actualWithdrawn, minerAddrs)
   412  
   413  			actor.checkState(rt)
   414  		})
   415  	})
   416  }
   417  
   418  func TestPublishStorageDeals(t *testing.T) {
   419  	owner := tutil.NewIDAddr(t, 101)
   420  	provider := tutil.NewIDAddr(t, 102)
   421  	worker := tutil.NewIDAddr(t, 103)
   422  	client := tutil.NewIDAddr(t, 104)
   423  	control := tutil.NewIDAddr(t, 200)
   424  	startEpoch := abi.ChainEpoch(42)
   425  	endEpoch := startEpoch + 200*builtin.EpochsInDay
   426  	mAddr := &minerAddrs{owner, worker, provider, []address.Address{control}}
   427  	var st market.State
   428  
   429  	t.Run("simple deal", func(t *testing.T) {
   430  		startEpoch := abi.ChainEpoch(1000)
   431  		endEpoch := startEpoch + 200*builtin.EpochsInDay
   432  		publishEpoch := abi.ChainEpoch(1)
   433  
   434  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   435  		rt.SetEpoch(publishEpoch)
   436  
   437  		// Publish from miner worker.
   438  		deal1 := actor.generateDealAndAddFunds(rt, client, mAddr, startEpoch, endEpoch)
   439  		rt.SetCaller(worker, builtin.AccountActorCodeID)
   440  		_ = actor.publishDeals(rt, mAddr, publishDealReq{deal: deal1})
   441  
   442  		// Publish from miner control address.
   443  		deal2 := actor.generateDealAndAddFunds(rt, client, mAddr, startEpoch+1, endEpoch+1)
   444  		rt.SetCaller(control, builtin.AccountActorCodeID)
   445  		_ = actor.publishDeals(rt, mAddr, publishDealReq{deal: deal2})
   446  
   447  		actor.checkState(rt)
   448  	})
   449  
   450  	t.Run("provider and client addresses are resolved before persisting state and sent to VerigReg actor for a verified deal", func(t *testing.T) {
   451  		// provider addresses
   452  		providerBls := tutil.NewBLSAddr(t, 101)
   453  		providerResolved := tutil.NewIDAddr(t, 102)
   454  		// client addresses
   455  		clientBls := tutil.NewBLSAddr(t, 900)
   456  		clientResolved := tutil.NewIDAddr(t, 333)
   457  		mAddr := &minerAddrs{owner, worker, providerBls, nil}
   458  
   459  		rt, actor := basicMarketSetup(t, owner, providerResolved, worker, clientResolved)
   460  		// mappings for resolving address
   461  		rt.AddIDAddress(providerBls, providerResolved)
   462  		rt.AddIDAddress(clientBls, clientResolved)
   463  
   464  		// generate deal and add required funds for deal
   465  		startEpoch := abi.ChainEpoch(42)
   466  		endEpoch := startEpoch + 200*builtin.EpochsInDay
   467  		deal := generateDealProposal(clientBls, mAddr.provider, startEpoch, endEpoch)
   468  		deal.VerifiedDeal = true
   469  
   470  		// add funds for cient using it's BLS address -> will be resolved and persisted
   471  		actor.addParticipantFunds(rt, clientBls, deal.ClientBalanceRequirement())
   472  		require.EqualValues(t, deal.ClientBalanceRequirement(), actor.getEscrowBalance(rt, clientResolved))
   473  
   474  		// add funds for provider using it's BLS address -> will be resolved and persisted
   475  		rt.SetReceived(deal.ProviderCollateral)
   476  		rt.SetCaller(mAddr.owner, builtin.AccountActorCodeID)
   477  		rt.ExpectValidateCallerType(builtin.CallerTypesSignable...)
   478  		expectGetControlAddresses(rt, providerResolved, mAddr.owner, mAddr.worker)
   479  		rt.Call(actor.AddBalance, &mAddr.provider)
   480  		rt.Verify()
   481  		rt.SetBalance(big.Add(rt.Balance(), deal.ProviderCollateral))
   482  		require.EqualValues(t, deal.ProviderCollateral, actor.getEscrowBalance(rt, providerResolved))
   483  
   484  		// publish deal using the BLS addresses
   485  		rt.SetCaller(mAddr.worker, builtin.AccountActorCodeID)
   486  		rt.ExpectValidateCallerType(builtin.CallerTypesSignable...)
   487  		expectGetControlAddresses(rt, providerResolved, mAddr.owner, mAddr.worker)
   488  		expectQueryNetworkInfo(rt, actor)
   489  		//  create a client proposal with a valid signature
   490  		var params market.PublishStorageDealsParams
   491  		buf := bytes.Buffer{}
   492  		require.NoError(t, deal.MarshalCBOR(&buf), "failed to marshal deal proposal")
   493  		sig := crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("does not matter")}
   494  		clientProposal := market.ClientDealProposal{Proposal: deal, ClientSignature: sig}
   495  		params.Deals = append(params.Deals, clientProposal)
   496  		// expect a call to verify the above signature
   497  		rt.ExpectVerifySignature(sig, deal.Client, buf.Bytes(), nil)
   498  
   499  		// request is sent to the VerigReg actor using the resolved address
   500  		param := &verifreg.UseBytesParams{
   501  			Address:  clientResolved,
   502  			DealSize: big.NewIntUnsigned(uint64(deal.PieceSize)),
   503  		}
   504  		rt.ExpectSend(builtin.VerifiedRegistryActorAddr, builtin.MethodsVerifiedRegistry.UseBytes, param, abi.NewTokenAmount(0), nil, exitcode.Ok)
   505  
   506  		deal2 := deal
   507  		deal2.Client = clientResolved
   508  		deal2.Provider = providerResolved
   509  		actor.expectGetRandom(rt, &deal2, abi.ChainEpoch(100))
   510  
   511  		ret := rt.Call(actor.PublishStorageDeals, &params)
   512  		rt.Verify()
   513  		resp, ok := ret.(*market.PublishStorageDealsReturn)
   514  		require.True(t, ok)
   515  		dealId := resp.IDs[0]
   516  
   517  		// assert that deal is persisted with the resolved addresses
   518  		prop := actor.getDealProposal(rt, dealId)
   519  		require.EqualValues(t, clientResolved, prop.Client)
   520  		require.EqualValues(t, providerResolved, prop.Provider)
   521  
   522  		actor.checkState(rt)
   523  	})
   524  
   525  	t.Run("publish a deal after activating a previous deal which has a start epoch far in the future", func(t *testing.T) {
   526  		startEpoch := abi.ChainEpoch(1000)
   527  		endEpoch := startEpoch + 200*builtin.EpochsInDay
   528  		publishEpoch := abi.ChainEpoch(1)
   529  
   530  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   531  
   532  		// publish the deal and activate it
   533  		rt.SetEpoch(publishEpoch)
   534  		deal1ID := actor.generateAndPublishDeal(rt, client, mAddr, startEpoch, endEpoch, startEpoch)
   535  		actor.activateDeals(rt, endEpoch, provider, publishEpoch, deal1ID)
   536  		st := actor.getDealState(rt, deal1ID)
   537  		require.EqualValues(t, publishEpoch, st.SectorStartEpoch)
   538  
   539  		// now publish a second deal and activate it
   540  		newEpoch := publishEpoch + 1
   541  		rt.SetEpoch(newEpoch)
   542  		deal2ID := actor.generateAndPublishDeal(rt, client, mAddr, startEpoch+1, endEpoch+1, startEpoch+1)
   543  		actor.activateDeals(rt, endEpoch+1, provider, newEpoch, deal2ID)
   544  
   545  		actor.checkState(rt)
   546  	})
   547  
   548  	t.Run("publish a deal with enough collateral when circulating supply > 0", func(t *testing.T) {
   549  		startEpoch := abi.ChainEpoch(1000)
   550  		endEpoch := startEpoch + 200*builtin.EpochsInDay
   551  		publishEpoch := abi.ChainEpoch(1)
   552  
   553  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   554  
   555  		clientCollateral := abi.NewTokenAmount(10) // min is zero so this is placeholder
   556  
   557  		// given power and circ supply cancel this should be 1*dealqapower / 100
   558  		dealSize := abi.PaddedPieceSize(2048) // generateDealProposal's deal size
   559  		providerCollateral := big.Div(
   560  			big.Mul(big.NewInt(int64(dealSize)), market.ProviderCollateralSupplyTarget.Numerator),
   561  			market.ProviderCollateralSupplyTarget.Denominator,
   562  		)
   563  		deal := actor.generateDealWithCollateralAndAddFunds(rt, client, mAddr, providerCollateral, clientCollateral, startEpoch, endEpoch)
   564  		rt.SetCirculatingSupply(actor.networkQAPower) // convenient for these two numbers to cancel out
   565  
   566  		// publish the deal successfully
   567  		rt.SetEpoch(publishEpoch)
   568  		rt.SetCaller(worker, builtin.AccountActorCodeID)
   569  		actor.publishDeals(rt, mAddr, publishDealReq{deal: deal})
   570  
   571  		actor.checkState(rt)
   572  	})
   573  
   574  	t.Run("publish multiple deals for different clients and ensure balances are correct", func(t *testing.T) {
   575  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   576  		client1 := tutil.NewIDAddr(t, 900)
   577  		client2 := tutil.NewIDAddr(t, 901)
   578  		client3 := tutil.NewIDAddr(t, 902)
   579  
   580  		// generate first deal for
   581  		deal1 := actor.generateDealAndAddFunds(rt, client1, mAddr, startEpoch, endEpoch)
   582  
   583  		// generate second deal
   584  		deal2 := actor.generateDealAndAddFunds(rt, client2, mAddr, startEpoch, endEpoch)
   585  
   586  		// generate third deal
   587  		deal3 := actor.generateDealAndAddFunds(rt, client3, mAddr, startEpoch, endEpoch)
   588  
   589  		rt.SetCaller(worker, builtin.AccountActorCodeID)
   590  		actor.publishDeals(rt, mAddr, publishDealReq{deal: deal1}, publishDealReq{deal: deal2},
   591  			publishDealReq{deal: deal3})
   592  
   593  		// assert locked balance for all clients and provider
   594  		providerLocked := big.Sum(deal1.ProviderCollateral, deal2.ProviderCollateral, deal3.ProviderCollateral)
   595  		client1Locked := actor.getLockedBalance(rt, client1)
   596  		client2Locked := actor.getLockedBalance(rt, client2)
   597  		client3Locked := actor.getLockedBalance(rt, client3)
   598  		require.EqualValues(t, deal1.ClientBalanceRequirement(), client1Locked)
   599  		require.EqualValues(t, deal2.ClientBalanceRequirement(), client2Locked)
   600  		require.EqualValues(t, deal3.ClientBalanceRequirement(), client3Locked)
   601  		require.EqualValues(t, providerLocked, actor.getLockedBalance(rt, provider))
   602  
   603  		// assert locked funds dealStates
   604  		rt.GetState(&st)
   605  		totalClientCollateralLocked := big.Sum(deal3.ClientCollateral, deal1.ClientCollateral, deal2.ClientCollateral)
   606  		require.EqualValues(t, totalClientCollateralLocked, st.TotalClientLockedCollateral)
   607  		require.EqualValues(t, providerLocked, st.TotalProviderLockedCollateral)
   608  		totalStorageFee := big.Sum(deal1.TotalStorageFee(), deal2.TotalStorageFee(), deal3.TotalStorageFee())
   609  		require.EqualValues(t, totalStorageFee, st.TotalClientStorageFee)
   610  
   611  		// publish two more deals for same clients with same provider
   612  		deal4 := actor.generateDealAndAddFunds(rt, client3, mAddr, abi.ChainEpoch(1000), abi.ChainEpoch(1000+200*builtin.EpochsInDay))
   613  		deal5 := actor.generateDealAndAddFunds(rt, client3, mAddr, abi.ChainEpoch(100), abi.ChainEpoch(100+200*builtin.EpochsInDay))
   614  		rt.SetCaller(worker, builtin.AccountActorCodeID)
   615  		actor.publishDeals(rt, mAddr, publishDealReq{deal: deal4}, publishDealReq{deal: deal5})
   616  
   617  		// assert locked balances for clients and provider
   618  		rt.GetState(&st)
   619  		providerLocked = big.Sum(providerLocked, deal4.ProviderCollateral, deal5.ProviderCollateral)
   620  		require.EqualValues(t, providerLocked, actor.getLockedBalance(rt, provider))
   621  
   622  		client3LockedUpdated := actor.getLockedBalance(rt, client3)
   623  		require.EqualValues(t, big.Sum(client3Locked, deal4.ClientBalanceRequirement(), deal5.ClientBalanceRequirement()), client3LockedUpdated)
   624  
   625  		client1Locked = actor.getLockedBalance(rt, client1)
   626  		client2Locked = actor.getLockedBalance(rt, client2)
   627  		require.EqualValues(t, deal1.ClientBalanceRequirement(), client1Locked)
   628  		require.EqualValues(t, deal2.ClientBalanceRequirement(), client2Locked)
   629  
   630  		// assert locked funds dealStates
   631  		totalClientCollateralLocked = big.Sum(totalClientCollateralLocked, deal4.ClientCollateral, deal5.ClientCollateral)
   632  		require.EqualValues(t, totalClientCollateralLocked, st.TotalClientLockedCollateral)
   633  		require.EqualValues(t, providerLocked, st.TotalProviderLockedCollateral)
   634  
   635  		totalStorageFee = big.Sum(totalStorageFee, deal4.TotalStorageFee(), deal5.TotalStorageFee())
   636  		require.EqualValues(t, totalStorageFee, st.TotalClientStorageFee)
   637  
   638  		// PUBLISH DEALS with a different provider
   639  		provider2 := tutil.NewIDAddr(t, 109)
   640  		miner := &minerAddrs{owner, worker, provider2, nil}
   641  
   642  		// generate first deal for second provider
   643  		deal6 := actor.generateDealAndAddFunds(rt, client1, miner, abi.ChainEpoch(20), abi.ChainEpoch(20+200*builtin.EpochsInDay))
   644  
   645  		// generate second deal for second provider
   646  		deal7 := actor.generateDealAndAddFunds(rt, client1, miner, abi.ChainEpoch(25), abi.ChainEpoch(60+200*builtin.EpochsInDay))
   647  
   648  		// publish both the deals for the second provider
   649  		rt.SetCaller(worker, builtin.AccountActorCodeID)
   650  		actor.publishDeals(rt, miner, publishDealReq{deal: deal6}, publishDealReq{deal: deal7})
   651  
   652  		// assertions
   653  		rt.GetState(&st)
   654  		provider2Locked := big.Add(deal6.ProviderCollateral, deal7.ProviderCollateral)
   655  		require.EqualValues(t, provider2Locked, actor.getLockedBalance(rt, provider2))
   656  		client1LockedUpdated := actor.getLockedBalance(rt, client1)
   657  		require.EqualValues(t, big.Add(deal7.ClientBalanceRequirement(), big.Add(client1Locked, deal6.ClientBalanceRequirement())), client1LockedUpdated)
   658  
   659  		// assert first provider's balance as well
   660  		require.EqualValues(t, providerLocked, actor.getLockedBalance(rt, provider))
   661  
   662  		totalClientCollateralLocked = big.Add(totalClientCollateralLocked, big.Add(deal6.ClientCollateral, deal7.ClientCollateral))
   663  		require.EqualValues(t, totalClientCollateralLocked, st.TotalClientLockedCollateral)
   664  		require.EqualValues(t, big.Add(providerLocked, provider2Locked), st.TotalProviderLockedCollateral)
   665  		totalStorageFee = big.Add(totalStorageFee, big.Add(deal6.TotalStorageFee(), deal7.TotalStorageFee()))
   666  		require.EqualValues(t, totalStorageFee, st.TotalClientStorageFee)
   667  
   668  		actor.checkState(rt)
   669  	})
   670  }
   671  
   672  func TestPublishStorageDealsFailures(t *testing.T) {
   673  	owner := tutil.NewIDAddr(t, 101)
   674  	provider := tutil.NewIDAddr(t, 102)
   675  	worker := tutil.NewIDAddr(t, 103)
   676  	client := tutil.NewIDAddr(t, 104)
   677  	mAddrs := &minerAddrs{owner, worker, provider, nil}
   678  
   679  	currentEpoch := abi.ChainEpoch(5)
   680  	startEpoch := abi.ChainEpoch(10)
   681  	endEpoch := startEpoch + 200*builtin.EpochsInDay
   682  
   683  	// simple failures because of invalid deal params
   684  	{
   685  		tcs := map[string]struct {
   686  			setup                      func(*mock.Runtime, *marketActorTestHarness, *market.DealProposal)
   687  			exitCode                   exitcode.ExitCode
   688  			signatureVerificationError error
   689  		}{
   690  			"deal end after deal start": {
   691  				setup: func(_ *mock.Runtime, _ *marketActorTestHarness, d *market.DealProposal) {
   692  					d.StartEpoch = 10
   693  					d.EndEpoch = 9
   694  				},
   695  				exitCode: exitcode.ErrIllegalArgument,
   696  			},
   697  			"current epoch greater than start epoch": {
   698  				setup: func(_ *mock.Runtime, _ *marketActorTestHarness, d *market.DealProposal) {
   699  					d.StartEpoch = currentEpoch - 1
   700  				},
   701  				exitCode: exitcode.ErrIllegalArgument,
   702  			},
   703  			"deal duration greater than max deal duration": {
   704  				setup: func(_ *mock.Runtime, _ *marketActorTestHarness, d *market.DealProposal) {
   705  					d.StartEpoch = abi.ChainEpoch(10)
   706  					d.EndEpoch = d.StartEpoch + (540 * builtin.EpochsInDay) + 1
   707  				},
   708  				exitCode: exitcode.ErrIllegalArgument,
   709  			},
   710  			"negative price per epoch": {
   711  				setup: func(_ *mock.Runtime, _ *marketActorTestHarness, d *market.DealProposal) {
   712  					d.StoragePricePerEpoch = abi.NewTokenAmount(-1)
   713  				},
   714  				exitCode: exitcode.ErrIllegalArgument,
   715  			},
   716  			"price per epoch greater than total filecoin": {
   717  				setup: func(_ *mock.Runtime, _ *marketActorTestHarness, d *market.DealProposal) {
   718  					d.StoragePricePerEpoch = big.Add(builtin.TotalFilecoin, big.NewInt(1))
   719  				},
   720  				exitCode: exitcode.ErrIllegalArgument,
   721  			},
   722  			"negative provider collateral": {
   723  				setup: func(_ *mock.Runtime, _ *marketActorTestHarness, d *market.DealProposal) {
   724  					d.ProviderCollateral = big.NewInt(-1)
   725  				},
   726  				exitCode: exitcode.ErrIllegalArgument,
   727  			},
   728  			"provider collateral greater than max collateral": {
   729  				setup: func(_ *mock.Runtime, _ *marketActorTestHarness, d *market.DealProposal) {
   730  					d.ProviderCollateral = big.Add(builtin.TotalFilecoin, big.NewInt(1))
   731  				},
   732  				exitCode: exitcode.ErrIllegalArgument,
   733  			},
   734  			"provider collateral less than bound": {
   735  				setup: func(rt *mock.Runtime, h *marketActorTestHarness, d *market.DealProposal) {
   736  					// with these two equal provider collatreal min is 5/100 * deal size
   737  					rt.SetCirculatingSupply(h.networkQAPower)
   738  					dealSize := big.NewInt(2048) // default deal size used
   739  					providerMin := big.Div(
   740  						big.Mul(dealSize, market.ProviderCollateralSupplyTarget.Numerator),
   741  						market.ProviderCollateralSupplyTarget.Denominator,
   742  					)
   743  					d.ProviderCollateral = big.Sub(providerMin, big.NewInt(1))
   744  				},
   745  				exitCode: exitcode.ErrIllegalArgument,
   746  			},
   747  			"negative client collateral": {
   748  				setup: func(_ *mock.Runtime, _ *marketActorTestHarness, d *market.DealProposal) {
   749  					d.ClientCollateral = big.NewInt(-1)
   750  				},
   751  				exitCode: exitcode.ErrIllegalArgument,
   752  			},
   753  			"client collateral greater than max collateral": {
   754  				setup: func(_ *mock.Runtime, _ *marketActorTestHarness, d *market.DealProposal) {
   755  					d.ClientCollateral = big.Add(builtin.TotalFilecoin, big.NewInt(1))
   756  				},
   757  				exitCode: exitcode.ErrIllegalArgument,
   758  			},
   759  			"client does not have enough balance for collateral": {
   760  				setup: func(rt *mock.Runtime, a *marketActorTestHarness, d *market.DealProposal) {
   761  					a.addParticipantFunds(rt, client, big.Sub(d.ClientBalanceRequirement(), big.NewInt(1)))
   762  					a.addProviderFunds(rt, d.ProviderCollateral, mAddrs)
   763  				},
   764  				exitCode: exitcode.ErrInsufficientFunds,
   765  			},
   766  			"provider does not have enough balance for collateral": {
   767  				setup: func(rt *mock.Runtime, a *marketActorTestHarness, d *market.DealProposal) {
   768  					a.addParticipantFunds(rt, client, d.ClientBalanceRequirement())
   769  					a.addProviderFunds(rt, big.Sub(d.ProviderCollateral, big.NewInt(1)), mAddrs)
   770  				},
   771  				exitCode: exitcode.ErrInsufficientFunds,
   772  			},
   773  			"unable to resolve client address": {
   774  				setup: func(_ *mock.Runtime, a *marketActorTestHarness, d *market.DealProposal) {
   775  					d.Client = tutil.NewBLSAddr(t, 1)
   776  				},
   777  				exitCode: exitcode.ErrNotFound,
   778  			},
   779  			"signature is invalid": {
   780  				setup: func(_ *mock.Runtime, a *marketActorTestHarness, d *market.DealProposal) {
   781  
   782  				},
   783  				exitCode:                   exitcode.ErrIllegalArgument,
   784  				signatureVerificationError: errors.New("error"),
   785  			},
   786  			"no entry for client in locked  balance table": {
   787  				setup: func(rt *mock.Runtime, a *marketActorTestHarness, d *market.DealProposal) {
   788  					a.addProviderFunds(rt, d.ProviderCollateral, mAddrs)
   789  				},
   790  				exitCode: exitcode.ErrInsufficientFunds,
   791  			},
   792  			"no entry for provider in locked  balance table": {
   793  				setup: func(rt *mock.Runtime, a *marketActorTestHarness, d *market.DealProposal) {
   794  					a.addParticipantFunds(rt, client, d.ClientBalanceRequirement())
   795  				},
   796  				exitCode: exitcode.ErrInsufficientFunds,
   797  			},
   798  			"bad piece CID": {
   799  				setup: func(_ *mock.Runtime, _ *marketActorTestHarness, d *market.DealProposal) {
   800  					d.PieceCID = tutil.MakeCID("random cid", nil)
   801  				},
   802  				exitCode: exitcode.ErrIllegalArgument,
   803  			},
   804  			"zero piece size": {
   805  				setup: func(_ *mock.Runtime, _ *marketActorTestHarness, d *market.DealProposal) {
   806  					d.PieceSize = abi.PaddedPieceSize(0)
   807  				},
   808  				exitCode: exitcode.ErrIllegalArgument,
   809  			},
   810  			"piece size less than 128 bytes": {
   811  				setup: func(_ *mock.Runtime, _ *marketActorTestHarness, d *market.DealProposal) {
   812  					d.PieceSize = abi.PaddedPieceSize(64)
   813  				},
   814  				exitCode: exitcode.ErrIllegalArgument,
   815  			},
   816  			"piece size is not a power of 2": {
   817  				setup: func(_ *mock.Runtime, _ *marketActorTestHarness, d *market.DealProposal) {
   818  					d.PieceSize = abi.PaddedPieceSize(254)
   819  				},
   820  				exitCode: exitcode.ErrIllegalArgument,
   821  			},
   822  		}
   823  
   824  		for name, tc := range tcs {
   825  			t.Run(name, func(t *testing.T) {
   826  				_ = name
   827  				rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   828  				dealProposal := generateDealProposal(client, provider, startEpoch, endEpoch)
   829  				rt.SetEpoch(currentEpoch)
   830  				tc.setup(rt, actor, &dealProposal)
   831  				params := mkPublishStorageParams(dealProposal)
   832  
   833  				rt.ExpectValidateCallerType(builtin.AccountActorCodeID, builtin.MultisigActorCodeID)
   834  				rt.ExpectSend(provider, builtin.MethodsMiner.ControlAddresses, nil, abi.NewTokenAmount(0), &miner.GetControlAddressesReturn{Worker: worker, Owner: owner}, 0)
   835  				expectQueryNetworkInfo(rt, actor)
   836  				rt.SetCaller(worker, builtin.AccountActorCodeID)
   837  				rt.ExpectVerifySignature(crypto.Signature{}, dealProposal.Client, mustCbor(&dealProposal), tc.signatureVerificationError)
   838  				rt.ExpectAbort(tc.exitCode, func() {
   839  					rt.Call(actor.PublishStorageDeals, params)
   840  				})
   841  
   842  				rt.Verify()
   843  				actor.checkState(rt)
   844  			})
   845  		}
   846  	}
   847  
   848  	// fails when client or provider has some funds but not enough to cover a deal
   849  	{
   850  		t.Run("fail when client has some funds but not enough for a deal", func(t *testing.T) {
   851  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   852  
   853  			//
   854  			actor.addParticipantFunds(rt, client, abi.NewTokenAmount(100))
   855  			startEpoch := abi.ChainEpoch(42)
   856  			deal1 := generateDealProposal(client, provider, startEpoch, startEpoch+200*builtin.EpochsInDay)
   857  			actor.addProviderFunds(rt, deal1.ProviderCollateral, mAddrs)
   858  			params := mkPublishStorageParams(deal1)
   859  
   860  			rt.ExpectValidateCallerType(builtin.AccountActorCodeID, builtin.MultisigActorCodeID)
   861  			rt.ExpectSend(provider, builtin.MethodsMiner.ControlAddresses, nil, abi.NewTokenAmount(0), &miner.GetControlAddressesReturn{Worker: worker, Owner: owner}, 0)
   862  			expectQueryNetworkInfo(rt, actor)
   863  			rt.SetCaller(worker, builtin.AccountActorCodeID)
   864  			rt.ExpectVerifySignature(crypto.Signature{}, deal1.Client, mustCbor(&deal1), nil)
   865  			rt.ExpectAbort(exitcode.ErrInsufficientFunds, func() {
   866  				rt.Call(actor.PublishStorageDeals, params)
   867  			})
   868  
   869  			rt.Verify()
   870  			actor.checkState(rt)
   871  		})
   872  
   873  		t.Run("fail when provider has some funds but not enough for a deal", func(t *testing.T) {
   874  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   875  
   876  			actor.addProviderFunds(rt, abi.NewTokenAmount(1), mAddrs)
   877  			deal1 := generateDealProposal(client, provider, startEpoch, endEpoch)
   878  			actor.addParticipantFunds(rt, client, deal1.ClientBalanceRequirement())
   879  
   880  			params := mkPublishStorageParams(deal1)
   881  
   882  			rt.ExpectValidateCallerType(builtin.AccountActorCodeID, builtin.MultisigActorCodeID)
   883  			rt.ExpectSend(provider, builtin.MethodsMiner.ControlAddresses, nil, abi.NewTokenAmount(0), &miner.GetControlAddressesReturn{Worker: worker, Owner: owner}, 0)
   884  			expectQueryNetworkInfo(rt, actor)
   885  			rt.SetCaller(worker, builtin.AccountActorCodeID)
   886  			rt.ExpectVerifySignature(crypto.Signature{}, deal1.Client, mustCbor(&deal1), nil)
   887  			rt.ExpectAbort(exitcode.ErrInsufficientFunds, func() {
   888  				rt.Call(actor.PublishStorageDeals, params)
   889  			})
   890  
   891  			rt.Verify()
   892  			actor.checkState(rt)
   893  		})
   894  	}
   895  
   896  	// fail when deals have different providers
   897  	{
   898  		t.Run("fail when deals have different providers", func(t *testing.T) {
   899  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   900  			deal1 := actor.generateDealAndAddFunds(rt, client, mAddrs, startEpoch, endEpoch)
   901  			m2 := &minerAddrs{owner, worker, tutil.NewIDAddr(t, 1000), nil}
   902  
   903  			deal2 := actor.generateDealAndAddFunds(rt, client, m2, abi.ChainEpoch(1), endEpoch)
   904  
   905  			params := mkPublishStorageParams(deal1, deal2)
   906  
   907  			rt.ExpectValidateCallerType(builtin.AccountActorCodeID, builtin.MultisigActorCodeID)
   908  			rt.ExpectSend(provider, builtin.MethodsMiner.ControlAddresses, nil, abi.NewTokenAmount(0), &miner.GetControlAddressesReturn{Worker: worker, Owner: owner}, 0)
   909  			expectQueryNetworkInfo(rt, actor)
   910  			rt.SetCaller(worker, builtin.AccountActorCodeID)
   911  			rt.ExpectVerifySignature(crypto.Signature{}, deal1.Client, mustCbor(&deal1), nil)
   912  			rt.ExpectVerifySignature(crypto.Signature{}, deal2.Client, mustCbor(&deal2), nil)
   913  
   914  			actor.expectGetRandom(rt, &deal1, abi.ChainEpoch(100))
   915  
   916  			rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
   917  				rt.Call(actor.PublishStorageDeals, params)
   918  			})
   919  
   920  			rt.Verify()
   921  			actor.checkState(rt)
   922  		})
   923  
   924  		//  failures because of incorrect call params
   925  		t.Run("fail when caller is not of signable type", func(t *testing.T) {
   926  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   927  			params := mkPublishStorageParams(generateDealProposal(client, provider, startEpoch, endEpoch))
   928  			w := tutil.NewIDAddr(t, 1000)
   929  			rt.SetCaller(w, builtin.StorageMinerActorCodeID)
   930  			rt.ExpectValidateCallerType(builtin.AccountActorCodeID, builtin.MultisigActorCodeID)
   931  			rt.ExpectAbort(exitcode.SysErrForbidden, func() {
   932  				rt.Call(actor.PublishStorageDeals, params)
   933  			})
   934  			actor.checkState(rt)
   935  		})
   936  
   937  		t.Run("fail when no deals in params", func(t *testing.T) {
   938  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   939  			params := mkPublishStorageParams()
   940  			rt.SetCaller(worker, builtin.AccountActorCodeID)
   941  			rt.ExpectValidateCallerType(builtin.AccountActorCodeID, builtin.MultisigActorCodeID)
   942  			rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
   943  				rt.Call(actor.PublishStorageDeals, params)
   944  			})
   945  			actor.checkState(rt)
   946  		})
   947  
   948  		t.Run("fail to resolve provider address", func(t *testing.T) {
   949  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   950  			deal := generateDealProposal(client, provider, startEpoch, endEpoch)
   951  			deal.Provider = tutil.NewBLSAddr(t, 100)
   952  
   953  			params := mkPublishStorageParams(deal)
   954  			rt.SetCaller(worker, builtin.AccountActorCodeID)
   955  			rt.ExpectValidateCallerType(builtin.AccountActorCodeID, builtin.MultisigActorCodeID)
   956  			rt.ExpectAbort(exitcode.ErrNotFound, func() {
   957  				rt.Call(actor.PublishStorageDeals, params)
   958  			})
   959  			actor.checkState(rt)
   960  		})
   961  
   962  		t.Run("caller is not the same as the worker address for miner", func(t *testing.T) {
   963  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   964  			deal := generateDealProposal(client, provider, startEpoch, endEpoch)
   965  			params := mkPublishStorageParams(deal)
   966  			rt.ExpectValidateCallerType(builtin.AccountActorCodeID, builtin.MultisigActorCodeID)
   967  			rt.ExpectSend(provider, builtin.MethodsMiner.ControlAddresses, nil, abi.NewTokenAmount(0), &miner.GetControlAddressesReturn{Worker: tutil.NewIDAddr(t, 999), Owner: owner}, 0)
   968  			rt.SetCaller(worker, builtin.AccountActorCodeID)
   969  			rt.ExpectAbort(exitcode.ErrForbidden, func() {
   970  				rt.Call(actor.PublishStorageDeals, params)
   971  			})
   972  
   973  			rt.Verify()
   974  			actor.checkState(rt)
   975  		})
   976  	}
   977  
   978  	t.Run("fails if provider is not a storage miner actor", func(t *testing.T) {
   979  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
   980  
   981  		// deal provider will be a Storage Miner Actor.
   982  		p2 := tutil.NewIDAddr(t, 505)
   983  		rt.SetAddressActorType(p2, builtin.StoragePowerActorCodeID)
   984  		deal := generateDealProposal(client, p2, abi.ChainEpoch(1), abi.ChainEpoch(5))
   985  
   986  		params := mkPublishStorageParams(deal)
   987  		rt.ExpectValidateCallerType(builtin.AccountActorCodeID, builtin.MultisigActorCodeID)
   988  		rt.SetCaller(worker, builtin.AccountActorCodeID)
   989  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
   990  			rt.Call(actor.PublishStorageDeals, params)
   991  		})
   992  
   993  		rt.Verify()
   994  		actor.checkState(rt)
   995  	})
   996  }
   997  
   998  func TestActivateDeals(t *testing.T) {
   999  
  1000  	owner := tutil.NewIDAddr(t, 101)
  1001  	provider := tutil.NewIDAddr(t, 102)
  1002  	worker := tutil.NewIDAddr(t, 103)
  1003  	client := tutil.NewIDAddr(t, 104)
  1004  	mAddrs := &minerAddrs{owner, worker, provider, nil}
  1005  
  1006  	startEpoch := abi.ChainEpoch(10)
  1007  	endEpoch := startEpoch + 200*builtin.EpochsInDay
  1008  	currentEpoch := abi.ChainEpoch(5)
  1009  	sectorExpiry := endEpoch + 100
  1010  
  1011  	t.Run("active deals multiple times with different providers", func(t *testing.T) {
  1012  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1013  		rt.SetEpoch(currentEpoch)
  1014  
  1015  		// provider 1 publishes deals1 and deals2 and deal3
  1016  		dealId1 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1017  		dealId2 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch+1, startEpoch)
  1018  		dealId3 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch+2, startEpoch)
  1019  
  1020  		// provider2 publishes deal4 and deal5
  1021  		provider2 := tutil.NewIDAddr(t, 401)
  1022  		mAddrs.provider = provider2
  1023  		dealId4 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1024  		dealId5 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch+1, startEpoch)
  1025  
  1026  		// provider1 activates deal 1 and deal2 but that does not activate deal3 to deal5
  1027  		actor.activateDeals(rt, sectorExpiry, provider, currentEpoch, dealId1, dealId2)
  1028  		actor.assertDealsNotActivated(rt, currentEpoch, dealId3, dealId4, dealId5)
  1029  
  1030  		// provider3 activates deal5 but that does not activate deal3 or deal4
  1031  		actor.activateDeals(rt, sectorExpiry, provider2, currentEpoch, dealId5)
  1032  		actor.assertDealsNotActivated(rt, currentEpoch, dealId3, dealId4)
  1033  
  1034  		// provider1 activates deal3
  1035  		actor.activateDeals(rt, sectorExpiry, provider, currentEpoch, dealId3)
  1036  		actor.assertDealsNotActivated(rt, currentEpoch, dealId4)
  1037  
  1038  		actor.checkState(rt)
  1039  	})
  1040  }
  1041  
  1042  func TestActivateDealFailures(t *testing.T) {
  1043  	owner := tutil.NewIDAddr(t, 101)
  1044  	provider := tutil.NewIDAddr(t, 102)
  1045  	worker := tutil.NewIDAddr(t, 103)
  1046  	client := tutil.NewIDAddr(t, 104)
  1047  	mAddrs := &minerAddrs{owner, worker, provider, nil}
  1048  
  1049  	startEpoch := abi.ChainEpoch(10)
  1050  	endEpoch := startEpoch + 200*builtin.EpochsInDay
  1051  	sectorExpiry := endEpoch + 100
  1052  
  1053  	// caller is not the provider
  1054  	{
  1055  		t.Run("fail when caller is not the provider of the deal", func(t *testing.T) {
  1056  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1057  			provider2 := tutil.NewIDAddr(t, 201)
  1058  			mAddrs2 := &minerAddrs{owner, worker, provider2, nil}
  1059  			dealId := actor.generateAndPublishDeal(rt, client, mAddrs2, startEpoch, endEpoch, startEpoch)
  1060  
  1061  			params := mkActivateDealParams(sectorExpiry, dealId)
  1062  
  1063  			rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  1064  			rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
  1065  			rt.ExpectAbort(exitcode.ErrForbidden, func() {
  1066  				rt.Call(actor.ActivateDeals, params)
  1067  			})
  1068  
  1069  			rt.Verify()
  1070  			actor.checkState(rt)
  1071  		})
  1072  	}
  1073  
  1074  	// caller is not a StorageMinerActor
  1075  	{
  1076  		t.Run("fail when caller is not a StorageMinerActor", func(t *testing.T) {
  1077  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1078  			rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  1079  			rt.SetCaller(provider, builtin.AccountActorCodeID)
  1080  			rt.ExpectAbort(exitcode.SysErrForbidden, func() {
  1081  				rt.Call(actor.ActivateDeals, &market.ActivateDealsParams{})
  1082  			})
  1083  
  1084  			rt.Verify()
  1085  			actor.checkState(rt)
  1086  		})
  1087  	}
  1088  
  1089  	// deal has not been published before
  1090  	{
  1091  		t.Run("fail when deal has not been published before", func(t *testing.T) {
  1092  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1093  			params := mkActivateDealParams(sectorExpiry, abi.DealID(42))
  1094  
  1095  			rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  1096  			rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
  1097  			rt.ExpectAbort(exitcode.ErrNotFound, func() {
  1098  				rt.Call(actor.ActivateDeals, params)
  1099  			})
  1100  
  1101  			rt.Verify()
  1102  			actor.checkState(rt)
  1103  		})
  1104  	}
  1105  
  1106  	// deal has ALREADY been activated
  1107  	{
  1108  		t.Run("fail when deal has already been activated", func(t *testing.T) {
  1109  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1110  			dealId := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1111  			actor.activateDeals(rt, sectorExpiry, provider, 0, dealId)
  1112  
  1113  			rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  1114  			rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
  1115  			rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  1116  				rt.Call(actor.ActivateDeals, mkActivateDealParams(sectorExpiry, dealId))
  1117  			})
  1118  
  1119  			rt.Verify()
  1120  			actor.checkState(rt)
  1121  		})
  1122  	}
  1123  
  1124  	// deal has invalid params
  1125  	{
  1126  		t.Run("fail when current epoch greater than start epoch of deal", func(t *testing.T) {
  1127  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1128  			dealId := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1129  
  1130  			rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  1131  			rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
  1132  			rt.SetEpoch(startEpoch + 1)
  1133  			rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  1134  				rt.Call(actor.ActivateDeals, mkActivateDealParams(sectorExpiry, dealId))
  1135  			})
  1136  
  1137  			rt.Verify()
  1138  			actor.checkState(rt)
  1139  		})
  1140  
  1141  		t.Run("fail when end epoch of deal greater than sector expiry", func(t *testing.T) {
  1142  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1143  			dealId := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1144  
  1145  			rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  1146  			rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
  1147  			rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  1148  				rt.Call(actor.ActivateDeals, mkActivateDealParams(endEpoch-1, dealId))
  1149  			})
  1150  
  1151  			rt.Verify()
  1152  			actor.checkState(rt)
  1153  		})
  1154  	}
  1155  
  1156  	// all fail if one fails
  1157  	{
  1158  		t.Run("fail to activate all deals if one deal fails", func(t *testing.T) {
  1159  			rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1160  
  1161  			// activate deal1 so it fails later
  1162  			dealId1 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1163  			actor.activateDeals(rt, sectorExpiry, provider, 0, dealId1)
  1164  
  1165  			dealId2 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch+1, startEpoch)
  1166  
  1167  			rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  1168  			rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
  1169  			rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  1170  				rt.Call(actor.ActivateDeals, mkActivateDealParams(sectorExpiry, dealId1, dealId2))
  1171  			})
  1172  			rt.Verify()
  1173  
  1174  			// no state for deal2 means deal2 activation has failed
  1175  			var st market.State
  1176  			rt.GetState(&st)
  1177  
  1178  			states, err := market.AsDealStateArray(adt.AsStore(rt), st.States)
  1179  			require.NoError(t, err)
  1180  
  1181  			_, found, err := states.Get(dealId2)
  1182  			require.NoError(t, err)
  1183  			require.False(t, found)
  1184  
  1185  			actor.checkState(rt)
  1186  
  1187  		})
  1188  	}
  1189  
  1190  }
  1191  
  1192  func TestOnMinerSectorsTerminate(t *testing.T) {
  1193  	owner := tutil.NewIDAddr(t, 101)
  1194  	provider := tutil.NewIDAddr(t, 102)
  1195  	worker := tutil.NewIDAddr(t, 103)
  1196  	client := tutil.NewIDAddr(t, 104)
  1197  	mAddrs := &minerAddrs{owner, worker, provider, nil}
  1198  
  1199  	startEpoch := abi.ChainEpoch(10)
  1200  	endEpoch := startEpoch + 200*builtin.EpochsInDay
  1201  	currentEpoch := abi.ChainEpoch(5)
  1202  	sectorExpiry := endEpoch + 100
  1203  
  1204  	t.Run("terminate multiple deals from multiple providers", func(t *testing.T) {
  1205  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1206  		rt.SetEpoch(currentEpoch)
  1207  
  1208  		// provider1 publishes deal1,2 and 3
  1209  		dealId1 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1210  		dealId2 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch+1, startEpoch)
  1211  		dealId3 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch+2, startEpoch)
  1212  		actor.activateDeals(rt, sectorExpiry, provider, currentEpoch, dealId1, dealId2, dealId3)
  1213  
  1214  		// provider2 publishes deal4 and deal5
  1215  		provider2 := tutil.NewIDAddr(t, 501)
  1216  		maddrs2 := &minerAddrs{owner, worker, provider2, nil}
  1217  		dealId4 := actor.generateAndPublishDeal(rt, client, maddrs2, startEpoch, endEpoch, startEpoch)
  1218  		dealId5 := actor.generateAndPublishDeal(rt, client, maddrs2, startEpoch, endEpoch+1, startEpoch)
  1219  		actor.activateDeals(rt, sectorExpiry, provider2, currentEpoch, dealId4, dealId5)
  1220  
  1221  		// provider1 terminates deal1 but that does not terminate deals2-5
  1222  		actor.terminateDeals(rt, provider, dealId1)
  1223  		actor.assertDealsTerminated(rt, currentEpoch, dealId1)
  1224  		actor.assertDeaslNotTerminated(rt, dealId2, dealId3, dealId4, dealId5)
  1225  
  1226  		// provider2 terminates deal5 but that does not terminate delals 2-4
  1227  		actor.terminateDeals(rt, provider2, dealId5)
  1228  		actor.assertDealsTerminated(rt, currentEpoch, dealId5)
  1229  		actor.assertDeaslNotTerminated(rt, dealId2, dealId3, dealId4)
  1230  
  1231  		// provider1 terminates deal2 and deal3
  1232  		actor.terminateDeals(rt, provider, dealId2, dealId3)
  1233  		actor.assertDealsTerminated(rt, currentEpoch, dealId2, dealId3)
  1234  		actor.assertDeaslNotTerminated(rt, dealId4)
  1235  
  1236  		// provider2 terminates deal4
  1237  		actor.terminateDeals(rt, provider2, dealId4)
  1238  		actor.assertDealsTerminated(rt, currentEpoch, dealId4)
  1239  
  1240  		actor.checkState(rt)
  1241  	})
  1242  
  1243  	t.Run("ignore deal proposal that does not exist", func(t *testing.T) {
  1244  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1245  		rt.SetEpoch(currentEpoch)
  1246  
  1247  		// deal1 will be terminated and the other deal will be ignored because it does not exist
  1248  		dealId1 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1249  		actor.activateDeals(rt, sectorExpiry, provider, currentEpoch, dealId1)
  1250  
  1251  		actor.terminateDeals(rt, provider, dealId1, abi.DealID(42))
  1252  		st := actor.getDealState(rt, dealId1)
  1253  		require.EqualValues(t, currentEpoch, st.SlashEpoch)
  1254  
  1255  		actor.checkState(rt)
  1256  	})
  1257  
  1258  	t.Run("terminate valid deals along with expired deals - only valid deals are terminated", func(t *testing.T) {
  1259  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1260  		rt.SetEpoch(currentEpoch)
  1261  
  1262  		// provider1 publishes deal1 and 2 and deal3 -> deal3 has the lowest endepoch
  1263  		dealId1 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1264  		dealId2 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch+1, startEpoch)
  1265  		dealId3 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch-1, startEpoch)
  1266  		actor.activateDeals(rt, sectorExpiry, provider, currentEpoch, dealId1, dealId2, dealId3)
  1267  
  1268  		// set current epoch such that deal3 expires but the other two do not
  1269  		newEpoch := endEpoch - 1
  1270  		rt.SetEpoch(newEpoch)
  1271  
  1272  		// terminating all three deals ONLY terminates deal1 and deal2 because deal3 has expired
  1273  		actor.terminateDeals(rt, provider, dealId1, dealId2, dealId3)
  1274  		actor.assertDealsTerminated(rt, newEpoch, dealId1, dealId2)
  1275  		actor.assertDeaslNotTerminated(rt, dealId3)
  1276  
  1277  		actor.checkState(rt)
  1278  	})
  1279  
  1280  	t.Run("terminating a deal the second time does not change it's slash epoch", func(t *testing.T) {
  1281  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1282  		rt.SetEpoch(currentEpoch)
  1283  
  1284  		dealId1 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1285  		actor.activateDeals(rt, sectorExpiry, provider, currentEpoch, dealId1)
  1286  
  1287  		// terminating the deal so slash epoch is the current epoch
  1288  		actor.terminateDeals(rt, provider, dealId1)
  1289  
  1290  		// set a new epoch and terminate again -> however slash epoch will still be the old epoch.
  1291  		newEpoch := currentEpoch + 1
  1292  		rt.SetEpoch(newEpoch)
  1293  		actor.terminateDeals(rt, provider, dealId1)
  1294  		st := actor.getDealState(rt, dealId1)
  1295  		require.EqualValues(t, currentEpoch, st.SlashEpoch)
  1296  
  1297  		actor.checkState(rt)
  1298  	})
  1299  
  1300  	t.Run("terminating new deals and an already terminated deal only terminates the new deals", func(t *testing.T) {
  1301  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1302  		rt.SetEpoch(currentEpoch)
  1303  
  1304  		// provider1 publishes deal1 and 2 and deal3 -> deal3 has the lowest endepoch
  1305  		dealId1 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1306  		dealId2 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch+1, startEpoch)
  1307  		dealId3 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch-1, startEpoch)
  1308  		actor.activateDeals(rt, sectorExpiry, provider, currentEpoch, dealId1, dealId2, dealId3)
  1309  
  1310  		// terminating the deal so slash epoch is the current epoch
  1311  		actor.terminateDeals(rt, provider, dealId1)
  1312  
  1313  		// set a new epoch and terminate again -> however slash epoch will still be the old epoch.
  1314  		newEpoch := currentEpoch + 1
  1315  		rt.SetEpoch(newEpoch)
  1316  		actor.terminateDeals(rt, provider, dealId1, dealId2, dealId3)
  1317  
  1318  		st := actor.getDealState(rt, dealId1)
  1319  		require.EqualValues(t, currentEpoch, st.SlashEpoch)
  1320  
  1321  		st2 := actor.getDealState(rt, dealId2)
  1322  		require.EqualValues(t, newEpoch, st2.SlashEpoch)
  1323  
  1324  		st3 := actor.getDealState(rt, dealId3)
  1325  		require.EqualValues(t, newEpoch, st3.SlashEpoch)
  1326  
  1327  		actor.checkState(rt)
  1328  	})
  1329  
  1330  	t.Run("do not terminate deal if end epoch is equal to or less than current epoch", func(t *testing.T) {
  1331  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1332  		rt.SetEpoch(currentEpoch)
  1333  
  1334  		// deal1 has endepoch equal to current epoch when terminate is called
  1335  		dealId1 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1336  		actor.activateDeals(rt, sectorExpiry, provider, currentEpoch, dealId1)
  1337  		rt.SetEpoch(endEpoch)
  1338  		actor.terminateDeals(rt, provider, dealId1)
  1339  		actor.assertDeaslNotTerminated(rt, dealId1)
  1340  
  1341  		// deal2 has end epoch less than current epoch when terminate is called
  1342  		rt.SetEpoch(currentEpoch)
  1343  		dealId2 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch+1, endEpoch, startEpoch+1)
  1344  		actor.activateDeals(rt, sectorExpiry, provider, currentEpoch, dealId2)
  1345  		rt.SetEpoch(endEpoch + 1)
  1346  		actor.terminateDeals(rt, provider, dealId2)
  1347  		actor.assertDeaslNotTerminated(rt, dealId2)
  1348  
  1349  		actor.checkState(rt)
  1350  	})
  1351  
  1352  	t.Run("fail when caller is not a StorageMinerActor", func(t *testing.T) {
  1353  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1354  		rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  1355  		rt.SetCaller(provider, builtin.AccountActorCodeID)
  1356  		rt.ExpectAbort(exitcode.SysErrForbidden, func() {
  1357  			rt.Call(actor.OnMinerSectorsTerminate, &market.OnMinerSectorsTerminateParams{})
  1358  		})
  1359  
  1360  		rt.Verify()
  1361  		actor.checkState(rt)
  1362  
  1363  	})
  1364  
  1365  	t.Run("fail when caller is not the provider of the deal", func(t *testing.T) {
  1366  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1367  		rt.SetEpoch(currentEpoch)
  1368  
  1369  		dealId := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1370  		actor.activateDeals(rt, sectorExpiry, provider, currentEpoch, dealId)
  1371  
  1372  		params := mkTerminateDealParams(currentEpoch, dealId)
  1373  
  1374  		provider2 := tutil.NewIDAddr(t, 501)
  1375  		rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  1376  		rt.SetCaller(provider2, builtin.StorageMinerActorCodeID)
  1377  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalState, "caller t0501 is not the provider t0102 of deal 0", func() {
  1378  			rt.Call(actor.OnMinerSectorsTerminate, params)
  1379  		})
  1380  
  1381  		rt.Verify()
  1382  		actor.checkState(rt)
  1383  
  1384  	})
  1385  
  1386  	t.Run("fail when deal has been published but not activated", func(t *testing.T) {
  1387  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1388  		rt.SetEpoch(currentEpoch)
  1389  
  1390  		dealId := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1391  
  1392  		params := mkTerminateDealParams(currentEpoch, dealId)
  1393  		rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  1394  		rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
  1395  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  1396  			rt.Call(actor.OnMinerSectorsTerminate, params)
  1397  		})
  1398  
  1399  		rt.Verify()
  1400  		actor.checkState(rt)
  1401  
  1402  	})
  1403  
  1404  	t.Run("termination of all deals should fail when one deal fails", func(t *testing.T) {
  1405  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1406  		rt.SetEpoch(currentEpoch)
  1407  
  1408  		// deal1 would terminate but deal2 will fail because deal2 has not been activated
  1409  		dealId1 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1410  		actor.activateDeals(rt, sectorExpiry, provider, currentEpoch, dealId1)
  1411  		dealId2 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch+1, startEpoch)
  1412  
  1413  		params := mkTerminateDealParams(currentEpoch, dealId1, dealId2)
  1414  		rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  1415  		rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
  1416  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  1417  			rt.Call(actor.OnMinerSectorsTerminate, params)
  1418  		})
  1419  
  1420  		rt.Verify()
  1421  
  1422  		// verify deal1 has not been terminated
  1423  		actor.assertDeaslNotTerminated(rt, dealId1)
  1424  
  1425  		actor.checkState(rt)
  1426  	})
  1427  }
  1428  
  1429  func TestCronTick(t *testing.T) {
  1430  	owner := tutil.NewIDAddr(t, 101)
  1431  	provider := tutil.NewIDAddr(t, 102)
  1432  	worker := tutil.NewIDAddr(t, 103)
  1433  	client := tutil.NewIDAddr(t, 104)
  1434  	mAddrs := &minerAddrs{owner, worker, provider, nil}
  1435  
  1436  	startEpoch := abi.ChainEpoch(50)
  1437  	endEpoch := startEpoch + 200*builtin.EpochsInDay
  1438  	sectorExpiry := endEpoch + 100
  1439  
  1440  	t.Run("fail when deal is activated but proposal is not found", func(t *testing.T) {
  1441  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1442  		dealId := actor.publishAndActivateDeal(rt, client, mAddrs, startEpoch, endEpoch, 0, sectorExpiry, startEpoch)
  1443  
  1444  		// delete the deal proposal (this breaks state invariants)
  1445  		actor.deleteDealProposal(rt, dealId)
  1446  
  1447  		// move the current epoch to the start epoch of the deal
  1448  		rt.SetEpoch(startEpoch)
  1449  		rt.ExpectAbort(exitcode.ErrNotFound, func() {
  1450  			actor.cronTick(rt)
  1451  		})
  1452  	})
  1453  
  1454  	t.Run("fail when deal update epoch is in the future", func(t *testing.T) {
  1455  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1456  		dealId := actor.publishAndActivateDeal(rt, client, mAddrs, startEpoch, endEpoch, 0, sectorExpiry, startEpoch)
  1457  
  1458  		// move the current epoch such that the deal's last updated field is set to the start epoch of the deal
  1459  		// and the next tick for it is scheduled at the endepoch.
  1460  		rt.SetEpoch(startEpoch)
  1461  		actor.cronTick(rt)
  1462  
  1463  		// update last updated to some time in the future
  1464  		actor.updateLastUpdated(rt, dealId, endEpoch+1000)
  1465  
  1466  		// set current epoch of the deal to the end epoch so it's picked up for "processing" in the next cron tick.
  1467  		rt.SetEpoch(endEpoch)
  1468  
  1469  		rt.ExpectAbort(exitcode.ErrIllegalState, func() {
  1470  			actor.cronTick(rt)
  1471  		})
  1472  	})
  1473  
  1474  	t.Run("crontick for a deal at it's start epoch results in zero payment and no slashing", func(t *testing.T) {
  1475  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1476  		dealId := actor.publishAndActivateDeal(rt, client, mAddrs, startEpoch, endEpoch, 0, sectorExpiry, startEpoch)
  1477  
  1478  		// move the current epoch to startEpoch
  1479  		current := startEpoch
  1480  		rt.SetEpoch(current)
  1481  		pay, slashed := actor.cronTickAndAssertBalances(rt, client, provider, current, dealId)
  1482  		require.EqualValues(t, big.Zero(), pay)
  1483  		require.EqualValues(t, big.Zero(), slashed)
  1484  
  1485  		// deal proposal and state should NOT be deleted
  1486  		require.NotNil(t, actor.getDealProposal(rt, dealId))
  1487  		require.NotNil(t, actor.getDealState(rt, dealId))
  1488  
  1489  		actor.checkState(rt)
  1490  	})
  1491  
  1492  	t.Run("slash a deal and make payment for another deal in the same epoch", func(t *testing.T) {
  1493  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1494  
  1495  		dealId1 := actor.publishAndActivateDeal(rt, client, mAddrs, startEpoch, endEpoch, 0, sectorExpiry, startEpoch)
  1496  		d1 := actor.getDealProposal(rt, dealId1)
  1497  
  1498  		dealId2 := actor.publishAndActivateDeal(rt, client, mAddrs, startEpoch+1, endEpoch+1, 0, sectorExpiry, startEpoch+1)
  1499  
  1500  		// slash deal1
  1501  		slashEpoch := abi.ChainEpoch(150)
  1502  		rt.SetEpoch(slashEpoch)
  1503  		actor.terminateDeals(rt, provider, dealId1)
  1504  
  1505  		// cron tick will slash deal1 and make payment for deal2
  1506  		current := abi.ChainEpoch(151)
  1507  		rt.SetEpoch(current)
  1508  		rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, d1.ProviderCollateral, nil, exitcode.Ok)
  1509  		actor.cronTick(rt)
  1510  
  1511  		actor.assertDealDeleted(rt, dealId1, d1)
  1512  		s2 := actor.getDealState(rt, dealId2)
  1513  		require.EqualValues(t, current, s2.LastUpdatedEpoch)
  1514  
  1515  		actor.checkState(rt)
  1516  	})
  1517  
  1518  	t.Run("cannot publish the same deal twice BEFORE a cron tick", func(t *testing.T) {
  1519  		// Publish a deal
  1520  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1521  		dealId1 := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1522  		d1 := actor.getDealProposal(rt, dealId1)
  1523  
  1524  		// now try to publish it again and it should fail because it will still be in pending state
  1525  		d2 := actor.generateDealAndAddFunds(rt, client, mAddrs, startEpoch, endEpoch)
  1526  		params := mkPublishStorageParams(d2)
  1527  		rt.ExpectValidateCallerType(builtin.AccountActorCodeID, builtin.MultisigActorCodeID)
  1528  		rt.ExpectSend(provider, builtin.MethodsMiner.ControlAddresses, nil, abi.NewTokenAmount(0), &miner.GetControlAddressesReturn{Worker: worker, Owner: owner}, 0)
  1529  		expectQueryNetworkInfo(rt, actor)
  1530  		rt.SetCaller(worker, builtin.AccountActorCodeID)
  1531  		rt.ExpectVerifySignature(crypto.Signature{}, d2.Client, mustCbor(&d2), nil)
  1532  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  1533  			rt.Call(actor.PublishStorageDeals, params)
  1534  		})
  1535  		rt.Verify()
  1536  
  1537  		// now a cron tick happens -> deal1 is no longer pending and then publishing the same deal again should work
  1538  		rt.SetEpoch(d1.StartEpoch - 1)
  1539  		actor.activateDeals(rt, sectorExpiry, provider, d1.StartEpoch-1, dealId1)
  1540  		rt.SetEpoch(d1.StartEpoch)
  1541  		actor.cronTick(rt)
  1542  		rt.SetCaller(worker, builtin.AccountActorCodeID)
  1543  		actor.publishDeals(rt, mAddrs, publishDealReq{deal: d2})
  1544  
  1545  		actor.checkState(rt)
  1546  	})
  1547  }
  1548  
  1549  func TestRandomCronEpochDuringPublish(t *testing.T) {
  1550  	owner := tutil.NewIDAddr(t, 101)
  1551  	provider := tutil.NewIDAddr(t, 102)
  1552  	worker := tutil.NewIDAddr(t, 103)
  1553  	client := tutil.NewIDAddr(t, 104)
  1554  	mAddrs := &minerAddrs{owner, worker, provider, nil}
  1555  
  1556  	startEpoch := abi.ChainEpoch(50)
  1557  	endEpoch := startEpoch + 200*builtin.EpochsInDay
  1558  	sectorExpiry := endEpoch + 1
  1559  
  1560  	t.Run("a random epoch in chosen as the cron processing epoch for a deal during publishing", func(t *testing.T) {
  1561  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1562  		processEpoch := startEpoch + 5
  1563  		dealId := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, processEpoch)
  1564  		d := actor.getDealProposal(rt, dealId)
  1565  
  1566  		// activate the deal
  1567  		rt.SetEpoch(startEpoch - 1)
  1568  		actor.activateDeals(rt, sectorExpiry, provider, d.StartEpoch-1, dealId)
  1569  
  1570  		// cron tick at deal start epoch does not do anything
  1571  		rt.SetEpoch(startEpoch)
  1572  		actor.cronTickNoChange(rt, client, provider)
  1573  
  1574  		// first cron tick at process epoch will make payment and schedule the deal for next epoch
  1575  		rt.SetEpoch(processEpoch)
  1576  		pay, _ := actor.cronTickAndAssertBalances(rt, client, provider, processEpoch, dealId)
  1577  		duration := big.Sub(big.NewInt(int64(processEpoch)), big.NewInt(int64(startEpoch)))
  1578  		require.EqualValues(t, big.Mul(duration, d.StoragePricePerEpoch), pay)
  1579  
  1580  		// payment at next epoch
  1581  		current := processEpoch + market.DealUpdatesInterval
  1582  		rt.SetEpoch(current)
  1583  		pay, _ = actor.cronTickAndAssertBalances(rt, client, provider, current, dealId)
  1584  		duration = big.Sub(big.NewInt(int64(current)), big.NewInt(int64(processEpoch)))
  1585  		require.EqualValues(t, big.Mul(duration, d.StoragePricePerEpoch), pay)
  1586  
  1587  		actor.checkState(rt)
  1588  	})
  1589  
  1590  	t.Run("deals are scheduled for expiry later than the end epoch", func(t *testing.T) {
  1591  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1592  		dealId := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1593  		d := actor.getDealProposal(rt, dealId)
  1594  
  1595  		rt.SetEpoch(startEpoch - 1)
  1596  		actor.activateDeals(rt, sectorExpiry, provider, d.StartEpoch-1, dealId)
  1597  
  1598  		// a cron tick at end epoch -1 schedules the deal for later than end epoch
  1599  		curr := endEpoch - 1
  1600  		rt.SetEpoch(curr)
  1601  		duration := big.NewInt(int64(curr - startEpoch))
  1602  		pay, _ := actor.cronTickAndAssertBalances(rt, client, provider, curr, dealId)
  1603  		require.EqualValues(t, big.Mul(duration, d.StoragePricePerEpoch), pay)
  1604  
  1605  		// cron tick at end epoch does NOT expire the deal
  1606  		rt.SetEpoch(endEpoch)
  1607  		actor.cronTickNoChange(rt, client, provider)
  1608  		require.NotNil(t, actor.getDealProposal(rt, dealId))
  1609  
  1610  		// cron tick at nextEpoch expires the deal -> payment is ONLY for one epoch
  1611  		curr = curr + market.DealUpdatesInterval
  1612  		rt.SetEpoch(curr)
  1613  		pay, _ = actor.cronTickAndAssertBalances(rt, client, provider, curr, dealId)
  1614  		require.EqualValues(t, d.StoragePricePerEpoch, pay)
  1615  		actor.assertDealDeleted(rt, dealId, d)
  1616  
  1617  		actor.checkState(rt)
  1618  	})
  1619  
  1620  	t.Run("deal is processed after it's end epoch -> should expire correctly", func(t *testing.T) {
  1621  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1622  		processEpoch := endEpoch + 100
  1623  
  1624  		activationEpoch := startEpoch - 1
  1625  		rt.SetEpoch(activationEpoch)
  1626  		dealId := actor.publishAndActivateDeal(rt, client, mAddrs, startEpoch, endEpoch, activationEpoch, sectorExpiry, processEpoch)
  1627  		d := actor.getDealProposal(rt, dealId)
  1628  
  1629  		rt.SetEpoch(processEpoch)
  1630  		pay, slashed := actor.cronTickAndAssertBalances(rt, client, provider, processEpoch, dealId)
  1631  		require.EqualValues(t, big.Zero(), slashed)
  1632  		duration := big.Sub(big.NewInt(int64(endEpoch)), big.NewInt(int64(startEpoch)))
  1633  		require.EqualValues(t, big.Mul(duration, d.StoragePricePerEpoch), pay)
  1634  
  1635  		actor.assertDealDeleted(rt, dealId, d)
  1636  
  1637  		actor.checkState(rt)
  1638  	})
  1639  
  1640  	t.Run("activation after deal start epoch but before it is processed fails", func(t *testing.T) {
  1641  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1642  		processEpoch := startEpoch + 5
  1643  		dealId := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, processEpoch)
  1644  
  1645  		// activate the deal after the start epoch
  1646  		rt.SetEpoch(startEpoch + 1)
  1647  
  1648  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  1649  			actor.activateDeals(rt, sectorExpiry, provider, startEpoch+1, dealId)
  1650  		})
  1651  
  1652  		actor.checkState(rt)
  1653  	})
  1654  
  1655  	t.Run("cron processing of deal after missed activation should fail and slash", func(t *testing.T) {
  1656  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1657  		processEpoch := startEpoch + 5
  1658  		dealId := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, processEpoch)
  1659  		d := actor.getDealProposal(rt, dealId)
  1660  
  1661  		rt.SetEpoch(processEpoch)
  1662  
  1663  		rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, d.ProviderCollateral, nil, exitcode.Ok)
  1664  		actor.cronTick(rt)
  1665  
  1666  		actor.assertDealDeleted(rt, dealId, d)
  1667  
  1668  		actor.checkState(rt)
  1669  	})
  1670  
  1671  }
  1672  
  1673  func TestLockedFundTrackingStates(t *testing.T) {
  1674  	t.Parallel()
  1675  	owner := tutil.NewIDAddr(t, 101)
  1676  	worker := tutil.NewIDAddr(t, 103)
  1677  
  1678  	p1 := tutil.NewIDAddr(t, 201)
  1679  	p2 := tutil.NewIDAddr(t, 202)
  1680  	p3 := tutil.NewIDAddr(t, 203)
  1681  
  1682  	c1 := tutil.NewIDAddr(t, 104)
  1683  	c2 := tutil.NewIDAddr(t, 105)
  1684  	c3 := tutil.NewIDAddr(t, 106)
  1685  
  1686  	m1 := &minerAddrs{owner, worker, p1, nil}
  1687  	m2 := &minerAddrs{owner, worker, p2, nil}
  1688  	m3 := &minerAddrs{owner, worker, p3, nil}
  1689  
  1690  	startEpoch := abi.ChainEpoch(50)
  1691  	endEpoch := startEpoch + 200*builtin.EpochsInDay
  1692  	sectorExpiry := endEpoch + 400
  1693  
  1694  	var st market.State
  1695  
  1696  	// assert values are zero
  1697  	rt, actor := basicMarketSetup(t, owner, p1, worker, c1)
  1698  	rt.GetState(&st)
  1699  	require.True(t, st.TotalClientLockedCollateral.IsZero())
  1700  	require.True(t, st.TotalProviderLockedCollateral.IsZero())
  1701  	require.True(t, st.TotalClientStorageFee.IsZero())
  1702  
  1703  	// Publish deal1, deal2 and deal3  with different client and provider
  1704  	dealId1 := actor.generateAndPublishDeal(rt, c1, m1, startEpoch, endEpoch, startEpoch)
  1705  	d1 := actor.getDealProposal(rt, dealId1)
  1706  
  1707  	dealId2 := actor.generateAndPublishDeal(rt, c2, m2, startEpoch, endEpoch, startEpoch)
  1708  	d2 := actor.getDealProposal(rt, dealId2)
  1709  
  1710  	dealId3 := actor.generateAndPublishDeal(rt, c3, m3, startEpoch, endEpoch, startEpoch)
  1711  	d3 := actor.getDealProposal(rt, dealId3)
  1712  
  1713  	csf := big.Sum(d1.TotalStorageFee(), d2.TotalStorageFee(), d3.TotalStorageFee())
  1714  	plc := big.Sum(d1.ProviderCollateral, d2.ProviderCollateral, d3.ProviderCollateral)
  1715  	clc := big.Sum(d1.ClientCollateral, d2.ClientCollateral, d3.ClientCollateral)
  1716  
  1717  	actor.assertLockedFundStates(rt, csf, plc, clc)
  1718  
  1719  	// activation dosen't change anything
  1720  	curr := startEpoch - 1
  1721  	rt.SetEpoch(curr)
  1722  	actor.activateDeals(rt, sectorExpiry, p1, curr, dealId1)
  1723  	actor.activateDeals(rt, sectorExpiry, p2, curr, dealId2)
  1724  
  1725  	actor.assertLockedFundStates(rt, csf, plc, clc)
  1726  
  1727  	// make payment for p1 and p2, p3 times out as it has not been activated
  1728  	curr = 51 // startEpoch + 1
  1729  	rt.SetEpoch(curr)
  1730  	rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, d3.ProviderCollateral, nil, exitcode.Ok)
  1731  	actor.cronTick(rt)
  1732  	payment := big.Product(big.NewInt(2), d1.StoragePricePerEpoch)
  1733  	csf = big.Sub(big.Sub(csf, payment), d3.TotalStorageFee())
  1734  	plc = big.Sub(plc, d3.ProviderCollateral)
  1735  	clc = big.Sub(clc, d3.ClientCollateral)
  1736  	actor.assertLockedFundStates(rt, csf, plc, clc)
  1737  
  1738  	// deal1 and deal2 will now be charged at epoch curr + market.DealUpdatesInterval, so nothing changes before that.
  1739  	rt.SetEpoch(curr + market.DealUpdatesInterval - 1)
  1740  	actor.cronTick(rt)
  1741  	actor.assertLockedFundStates(rt, csf, plc, clc)
  1742  
  1743  	// one more round of payment for deal1 and deal2
  1744  	curr2 := curr + market.DealUpdatesInterval
  1745  	rt.SetEpoch(curr2)
  1746  	duration := big.NewInt(int64(curr2 - curr))
  1747  	payment = big.Product(big.NewInt(2), d1.StoragePricePerEpoch, duration)
  1748  	csf = big.Sub(csf, payment)
  1749  	actor.cronTick(rt)
  1750  	actor.assertLockedFundStates(rt, csf, plc, clc)
  1751  
  1752  	// slash deal1 at 201
  1753  	slashEpoch := curr2 + 1
  1754  	rt.SetEpoch(slashEpoch)
  1755  	actor.terminateDeals(rt, m1.provider, dealId1)
  1756  
  1757  	// cron tick to slash deal1 and expire deal2
  1758  	rt.SetEpoch(endEpoch)
  1759  	csf = big.Zero()
  1760  	clc = big.Zero()
  1761  	plc = big.Zero()
  1762  	rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, d1.ProviderCollateral, nil, exitcode.Ok)
  1763  	actor.cronTick(rt)
  1764  	actor.assertLockedFundStates(rt, csf, plc, clc)
  1765  
  1766  	actor.checkState(rt)
  1767  }
  1768  
  1769  func TestCronTickTimedoutDeals(t *testing.T) {
  1770  	owner := tutil.NewIDAddr(t, 101)
  1771  	provider := tutil.NewIDAddr(t, 102)
  1772  	worker := tutil.NewIDAddr(t, 103)
  1773  	client := tutil.NewIDAddr(t, 104)
  1774  	mAddrs := &minerAddrs{owner, worker, provider, nil}
  1775  
  1776  	startEpoch := abi.ChainEpoch(50)
  1777  	endEpoch := startEpoch + 200*builtin.EpochsInDay
  1778  
  1779  	t.Run("timed out deal is slashed and deleted", func(t *testing.T) {
  1780  		// publish a deal but do NOT activate it
  1781  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1782  		dealId := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1783  		d := actor.getDealProposal(rt, dealId)
  1784  
  1785  		cEscrow := actor.getEscrowBalance(rt, client)
  1786  
  1787  		// do a cron tick for it -> should time out and get slashed
  1788  		rt.SetEpoch(startEpoch)
  1789  		rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, d.ProviderCollateral, nil, exitcode.Ok)
  1790  		actor.cronTick(rt)
  1791  
  1792  		require.Equal(t, cEscrow, actor.getEscrowBalance(rt, client))
  1793  		require.Equal(t, big.Zero(), actor.getLockedBalance(rt, client))
  1794  
  1795  		actor.assertAccountZero(rt, provider)
  1796  
  1797  		actor.assertDealDeleted(rt, dealId, d)
  1798  
  1799  		actor.checkState(rt)
  1800  	})
  1801  
  1802  	t.Run("publishing timed out deal again should work after cron tick as it should no longer be pending", func(t *testing.T) {
  1803  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1804  		dealId := actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1805  		d := actor.getDealProposal(rt, dealId)
  1806  
  1807  		// publishing will fail as it will be in pending
  1808  		d2 := actor.generateDealAndAddFunds(rt, client, mAddrs, startEpoch, endEpoch)
  1809  		params := mkPublishStorageParams(d2)
  1810  		rt.ExpectValidateCallerType(builtin.AccountActorCodeID, builtin.MultisigActorCodeID)
  1811  		rt.ExpectSend(provider, builtin.MethodsMiner.ControlAddresses, nil, abi.NewTokenAmount(0), &miner.GetControlAddressesReturn{Worker: worker, Owner: owner}, 0)
  1812  		expectQueryNetworkInfo(rt, actor)
  1813  		rt.SetCaller(worker, builtin.AccountActorCodeID)
  1814  		rt.ExpectVerifySignature(crypto.Signature{}, d2.Client, mustCbor(&d2), nil)
  1815  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  1816  			rt.Call(actor.PublishStorageDeals, params)
  1817  		})
  1818  		rt.Verify()
  1819  
  1820  		// do a cron tick for it -> should time out and get slashed
  1821  		rt.SetEpoch(startEpoch)
  1822  		rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, d.ProviderCollateral, nil, exitcode.Ok)
  1823  		actor.cronTick(rt)
  1824  		actor.assertDealDeleted(rt, dealId, d)
  1825  
  1826  		// now publishing should work
  1827  		actor.generateAndPublishDeal(rt, client, mAddrs, startEpoch, endEpoch, startEpoch)
  1828  
  1829  		actor.checkState(rt)
  1830  	})
  1831  
  1832  	t.Run("timed out and verified deals are slashed, deleted AND sent to the Registry actor", func(t *testing.T) {
  1833  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1834  		// deal1 and deal2 are verified
  1835  		deal1 := actor.generateDealAndAddFunds(rt, client, mAddrs, startEpoch, endEpoch)
  1836  		deal1.VerifiedDeal = true
  1837  		deal2 := actor.generateDealAndAddFunds(rt, client, mAddrs, startEpoch, endEpoch+1)
  1838  		deal2.VerifiedDeal = true
  1839  
  1840  		// deal3 is NOT verified
  1841  		deal3 := actor.generateDealAndAddFunds(rt, client, mAddrs, startEpoch, endEpoch+2)
  1842  
  1843  		//  publishing verified deals
  1844  		rt.SetCaller(worker, builtin.AccountActorCodeID)
  1845  		dealIds := actor.publishDeals(rt, mAddrs, publishDealReq{deal1, startEpoch},
  1846  			publishDealReq{deal2, startEpoch}, publishDealReq{deal3, startEpoch})
  1847  
  1848  		// do a cron tick for it -> all should time out and get slashed
  1849  		// ONLY deal1 and deal2 should be sent to the Registry actor
  1850  		rt.SetEpoch(startEpoch)
  1851  
  1852  		// expected sends to the registry actor
  1853  		param1 := &verifreg.RestoreBytesParams{
  1854  			Address:  deal1.Client,
  1855  			DealSize: big.NewIntUnsigned(uint64(deal1.PieceSize)),
  1856  		}
  1857  		param2 := &verifreg.RestoreBytesParams{
  1858  			Address:  deal2.Client,
  1859  			DealSize: big.NewIntUnsigned(uint64(deal2.PieceSize)),
  1860  		}
  1861  
  1862  		rt.ExpectSend(builtin.VerifiedRegistryActorAddr, builtin.MethodsVerifiedRegistry.RestoreBytes, param1,
  1863  			abi.NewTokenAmount(0), nil, exitcode.Ok)
  1864  		rt.ExpectSend(builtin.VerifiedRegistryActorAddr, builtin.MethodsVerifiedRegistry.RestoreBytes, param2,
  1865  			abi.NewTokenAmount(0), nil, exitcode.Ok)
  1866  
  1867  		expectedBurn := big.Mul(big.NewInt(3), deal1.ProviderCollateral)
  1868  		rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, expectedBurn, nil, exitcode.Ok)
  1869  		actor.cronTick(rt)
  1870  
  1871  		// a second cron tick for the same epoch should not change anything
  1872  		actor.cronTickNoChange(rt, client, provider)
  1873  
  1874  		actor.assertAccountZero(rt, provider)
  1875  		actor.assertDealDeleted(rt, dealIds[0], &deal1)
  1876  		actor.assertDealDeleted(rt, dealIds[1], &deal2)
  1877  		actor.assertDealDeleted(rt, dealIds[2], &deal3)
  1878  
  1879  		actor.checkState(rt)
  1880  	})
  1881  }
  1882  
  1883  func TestCronTickDealExpiry(t *testing.T) {
  1884  	owner := tutil.NewIDAddr(t, 101)
  1885  	provider := tutil.NewIDAddr(t, 102)
  1886  	worker := tutil.NewIDAddr(t, 103)
  1887  	client := tutil.NewIDAddr(t, 104)
  1888  	mAddrs := &minerAddrs{owner, worker, provider, nil}
  1889  
  1890  	startEpoch := abi.ChainEpoch(50)
  1891  	endEpoch := startEpoch + 200*builtin.EpochsInDay
  1892  	sectorExpiry := endEpoch + 400
  1893  
  1894  	t.Run("deal expiry -> deal is correctly processed twice in the same crontick", func(t *testing.T) {
  1895  		t.Parallel()
  1896  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1897  		dealId := actor.publishAndActivateDeal(rt, client, mAddrs, startEpoch, endEpoch, 0, sectorExpiry, startEpoch)
  1898  		d := actor.getDealProposal(rt, dealId)
  1899  
  1900  		// move the current epoch to startEpoch and scheduled next epoch at endepoch -1
  1901  		current := startEpoch
  1902  		rt.SetEpoch(current)
  1903  		pay, slashed := actor.cronTickAndAssertBalances(rt, client, provider, current, dealId)
  1904  		require.EqualValues(t, big.Zero(), pay)
  1905  		require.EqualValues(t, big.Zero(), slashed)
  1906  		// assert deal exists
  1907  		actor.getDealProposal(rt, dealId)
  1908  
  1909  		// move the epoch to endEpoch+5(anything greater than endEpoch), so deal is first processed at endEpoch - 1 AND then at it's end epoch
  1910  		// total payment = (end - start)
  1911  		current = endEpoch + 5
  1912  		rt.SetEpoch(current)
  1913  		pay, slashed = actor.cronTickAndAssertBalances(rt, client, provider, current, dealId)
  1914  		duration := big.NewInt(int64(endEpoch - startEpoch))
  1915  		require.EqualValues(t, big.Mul(duration, d.StoragePricePerEpoch), pay)
  1916  		require.EqualValues(t, big.Zero(), slashed)
  1917  
  1918  		// deal should be deleted as it should have expired
  1919  		actor.assertDealDeleted(rt, dealId, d)
  1920  
  1921  		actor.checkState(rt)
  1922  	})
  1923  
  1924  	t.Run("deal expiry -> regular payments till deal expires and then locked funds are unlocked", func(t *testing.T) {
  1925  		t.Parallel()
  1926  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1927  		dealId := actor.publishAndActivateDeal(rt, client, mAddrs, startEpoch, endEpoch, 0, sectorExpiry, startEpoch)
  1928  		d := actor.getDealProposal(rt, dealId)
  1929  
  1930  		// move the current epoch to startEpoch + 5 so payment is made
  1931  		current := startEpoch + 5 // 55
  1932  		rt.SetEpoch(current)
  1933  		// assert payment
  1934  		pay, slashed := actor.cronTickAndAssertBalances(rt, client, provider, current, dealId)
  1935  		require.EqualValues(t, pay, big.Mul(big.NewInt(5), d.StoragePricePerEpoch))
  1936  		require.EqualValues(t, big.Zero(), slashed)
  1937  
  1938  		// Setting the current epoch to anything less than next schedule wont make any payment
  1939  		rt.SetEpoch(current + market.DealUpdatesInterval - 1)
  1940  		actor.cronTickNoChange(rt, client, provider)
  1941  
  1942  		// however setting the current epoch to next schedle will make the payment
  1943  		current2 := current + market.DealUpdatesInterval
  1944  		rt.SetEpoch(current2)
  1945  		duration := big.NewInt(int64(current2 - current))
  1946  		pay, slashed = actor.cronTickAndAssertBalances(rt, client, provider, current2, dealId)
  1947  		require.EqualValues(t, big.Mul(duration, d.StoragePricePerEpoch), pay)
  1948  		require.EqualValues(t, big.Zero(), slashed)
  1949  
  1950  		// a second cron tick for the same epoch should not change anything
  1951  		actor.cronTickNoChange(rt, client, provider)
  1952  
  1953  		// next epoch schedule
  1954  		current3 := current2 + market.DealUpdatesInterval
  1955  		rt.SetEpoch(current3)
  1956  		duration = big.NewInt(int64(current3 - current2))
  1957  		pay, slashed = actor.cronTickAndAssertBalances(rt, client, provider, current3, dealId)
  1958  		require.EqualValues(t, pay, big.Mul(duration, d.StoragePricePerEpoch))
  1959  		require.EqualValues(t, big.Zero(), slashed)
  1960  
  1961  		// setting epoch to greater than end will expire the deal, make the payment and unlock all funds
  1962  		current4 := endEpoch + 300
  1963  		rt.SetEpoch(current4)
  1964  		pay, slashed = actor.cronTickAndAssertBalances(rt, client, provider, current4, dealId)
  1965  		duration = big.NewInt(int64(endEpoch - current3))
  1966  		require.EqualValues(t, big.Mul(duration, d.StoragePricePerEpoch), pay)
  1967  		require.EqualValues(t, big.Zero(), slashed)
  1968  
  1969  		// deal should be deleted as it should have expired
  1970  		actor.assertDealDeleted(rt, dealId, d)
  1971  
  1972  		actor.checkState(rt)
  1973  	})
  1974  
  1975  	t.Run("deal expiry -> payment for a deal if deal is already expired before a cron tick", func(t *testing.T) {
  1976  		t.Parallel()
  1977  		start := abi.ChainEpoch(5)
  1978  		end := start + 200*builtin.EpochsInDay
  1979  
  1980  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  1981  		dealId := actor.publishAndActivateDeal(rt, client, mAddrs, start, end, 0, sectorExpiry, startEpoch)
  1982  		d := actor.getDealProposal(rt, dealId)
  1983  
  1984  		current := end + 25
  1985  		rt.SetEpoch(current)
  1986  
  1987  		pay, slashed := actor.cronTickAndAssertBalances(rt, client, provider, current, dealId)
  1988  		require.EqualValues(t, pay, big.Mul(big.NewInt(int64(end-start)), d.StoragePricePerEpoch))
  1989  		require.EqualValues(t, big.Zero(), slashed)
  1990  
  1991  		actor.assertDealDeleted(rt, dealId, d)
  1992  
  1993  		// running cron tick again doesn't do anything
  1994  		actor.cronTickNoChange(rt, client, provider)
  1995  
  1996  		actor.checkState(rt)
  1997  	})
  1998  
  1999  	t.Run("expired deal should unlock the remaining client and provider locked balance after payment and deal should be deleted", func(t *testing.T) {
  2000  		t.Parallel()
  2001  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2002  		dealId := actor.publishAndActivateDeal(rt, client, mAddrs, startEpoch, endEpoch, 0, sectorExpiry, startEpoch)
  2003  		deal := actor.getDealProposal(rt, dealId)
  2004  
  2005  		cEscrow := actor.getEscrowBalance(rt, client)
  2006  		pEscrow := actor.getEscrowBalance(rt, provider)
  2007  
  2008  		// move the current epoch so that deal is expired
  2009  		rt.SetEpoch(endEpoch + 1000)
  2010  		actor.cronTick(rt)
  2011  
  2012  		// assert balances
  2013  		payment := deal.TotalStorageFee()
  2014  
  2015  		require.EqualValues(t, big.Sub(cEscrow, payment), actor.getEscrowBalance(rt, client))
  2016  		require.EqualValues(t, big.Zero(), actor.getLockedBalance(rt, client))
  2017  
  2018  		require.EqualValues(t, big.Add(pEscrow, payment), actor.getEscrowBalance(rt, provider))
  2019  		require.EqualValues(t, big.Zero(), actor.getLockedBalance(rt, provider))
  2020  
  2021  		// deal should be deleted
  2022  		actor.assertDealDeleted(rt, dealId, deal)
  2023  
  2024  		actor.checkState(rt)
  2025  	})
  2026  
  2027  	t.Run("all payments are made for a deal -> deal expires -> client withdraws collateral and client account is removed", func(t *testing.T) {
  2028  		t.Parallel()
  2029  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2030  		dealId := actor.publishAndActivateDeal(rt, client, mAddrs, startEpoch, endEpoch, 0, sectorExpiry, startEpoch)
  2031  		deal := actor.getDealProposal(rt, dealId)
  2032  
  2033  		// move the current epoch so that deal is expired
  2034  		rt.SetEpoch(endEpoch + 100)
  2035  		actor.cronTick(rt)
  2036  		require.EqualValues(t, deal.ClientCollateral, actor.getEscrowBalance(rt, client))
  2037  
  2038  		// client withdraws collateral -> account should be removed as it now has zero balance
  2039  		actor.withdrawClientBalance(rt, client, deal.ClientCollateral, deal.ClientCollateral)
  2040  		actor.assertAccountZero(rt, client)
  2041  
  2042  		actor.checkState(rt)
  2043  	})
  2044  }
  2045  
  2046  func TestCronTickDealSlashing(t *testing.T) {
  2047  	owner := tutil.NewIDAddr(t, 101)
  2048  	provider := tutil.NewIDAddr(t, 102)
  2049  	worker := tutil.NewIDAddr(t, 103)
  2050  	client := tutil.NewIDAddr(t, 104)
  2051  	mAddrs := &minerAddrs{owner, worker, provider, nil}
  2052  	sectorExpiry := abi.ChainEpoch(400 + 200*builtin.EpochsInDay)
  2053  
  2054  	// hairy edge cases
  2055  	{
  2056  
  2057  		tcs := map[string]struct {
  2058  			dealStart        abi.ChainEpoch
  2059  			dealEnd          abi.ChainEpoch
  2060  			activationEpoch  abi.ChainEpoch
  2061  			terminationEpoch abi.ChainEpoch
  2062  			cronTickEpoch    abi.ChainEpoch
  2063  			payment          abi.TokenAmount
  2064  		}{
  2065  			"deal is slashed after the startepoch and then the first crontick happens": {
  2066  				dealStart:        abi.ChainEpoch(10),
  2067  				dealEnd:          abi.ChainEpoch(10 + 200*builtin.EpochsInDay),
  2068  				activationEpoch:  abi.ChainEpoch(5),
  2069  				terminationEpoch: abi.ChainEpoch(15),
  2070  				cronTickEpoch:    abi.ChainEpoch(16),
  2071  				payment:          abi.NewTokenAmount(50), // (15 - 10) * 10 as deal storage fee is 10 per epoch
  2072  			},
  2073  			"deal is slashed at the startepoch and then the first crontick happens": {
  2074  				dealStart:        abi.ChainEpoch(10),
  2075  				dealEnd:          abi.ChainEpoch(10 + 200*builtin.EpochsInDay),
  2076  				activationEpoch:  abi.ChainEpoch(5),
  2077  				terminationEpoch: abi.ChainEpoch(10),
  2078  				cronTickEpoch:    abi.ChainEpoch(11),
  2079  				payment:          abi.NewTokenAmount(0), // (10 - 10) * 10
  2080  			},
  2081  			"deal is slashed before the startepoch and then the first crontick happens": {
  2082  				dealStart:        abi.ChainEpoch(10),
  2083  				dealEnd:          abi.ChainEpoch(10 + 200*builtin.EpochsInDay),
  2084  				activationEpoch:  abi.ChainEpoch(5),
  2085  				terminationEpoch: abi.ChainEpoch(6),
  2086  				cronTickEpoch:    abi.ChainEpoch(10),
  2087  				payment:          abi.NewTokenAmount(0), // (10 - 10) * 10
  2088  			},
  2089  			"deal is terminated at the activation epoch and then the first crontick happens": {
  2090  				dealStart:        abi.ChainEpoch(10),
  2091  				dealEnd:          abi.ChainEpoch(10 + 200*builtin.EpochsInDay),
  2092  				activationEpoch:  abi.ChainEpoch(5),
  2093  				terminationEpoch: abi.ChainEpoch(5),
  2094  				cronTickEpoch:    abi.ChainEpoch(10),
  2095  				payment:          abi.NewTokenAmount(0), // (10 - 10) * 10
  2096  			},
  2097  			"deal is slashed and then deal expiry happens on crontick, but slashing still occurs": {
  2098  				dealStart:        abi.ChainEpoch(10),
  2099  				dealEnd:          abi.ChainEpoch(10 + 200*builtin.EpochsInDay),
  2100  				activationEpoch:  abi.ChainEpoch(5),
  2101  				terminationEpoch: abi.ChainEpoch(15),
  2102  				cronTickEpoch:    abi.ChainEpoch(25), // deal has expired
  2103  				payment:          abi.NewTokenAmount(50),
  2104  			},
  2105  			"deal is slashed just BEFORE the end epoch": {
  2106  				dealStart:        abi.ChainEpoch(10),
  2107  				dealEnd:          abi.ChainEpoch(10 + 200*builtin.EpochsInDay),
  2108  				activationEpoch:  abi.ChainEpoch(5),
  2109  				terminationEpoch: abi.ChainEpoch(19),
  2110  				cronTickEpoch:    abi.ChainEpoch(19),
  2111  				payment:          abi.NewTokenAmount(90), // (19 - 10) * 10
  2112  			},
  2113  		}
  2114  
  2115  		for n, tc := range tcs {
  2116  			t.Run(n, func(t *testing.T) {
  2117  				rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2118  
  2119  				// publish and activate
  2120  				rt.SetEpoch(tc.activationEpoch)
  2121  				dealId := actor.publishAndActivateDeal(rt, client, mAddrs, tc.dealStart, tc.dealEnd, tc.activationEpoch, sectorExpiry, tc.dealStart)
  2122  				d := actor.getDealProposal(rt, dealId)
  2123  
  2124  				// terminate
  2125  				rt.SetEpoch(tc.terminationEpoch)
  2126  				actor.terminateDeals(rt, provider, dealId)
  2127  
  2128  				//  cron tick
  2129  				rt.SetEpoch(tc.cronTickEpoch)
  2130  
  2131  				pay, slashed := actor.cronTickAndAssertBalances(rt, client, provider, tc.cronTickEpoch, dealId)
  2132  				require.EqualValues(t, tc.payment, pay)
  2133  				require.EqualValues(t, d.ProviderCollateral, slashed)
  2134  				actor.assertDealDeleted(rt, dealId, d)
  2135  
  2136  				// if there has been no payment, provider will have zero balance and hence should be slashed
  2137  				if tc.payment.Equals(big.Zero()) {
  2138  					actor.assertAccountZero(rt, provider)
  2139  					// client balances should not change
  2140  					cLocked := actor.getLockedBalance(rt, client)
  2141  					cEscrow := actor.getEscrowBalance(rt, client)
  2142  					actor.cronTick(rt)
  2143  					require.EqualValues(t, cEscrow, actor.getEscrowBalance(rt, client))
  2144  					require.EqualValues(t, cLocked, actor.getLockedBalance(rt, client))
  2145  				} else {
  2146  					// running cron tick again dosen't do anything
  2147  					actor.cronTickNoChange(rt, client, provider)
  2148  				}
  2149  				actor.checkState(rt)
  2150  			})
  2151  		}
  2152  	}
  2153  
  2154  	startEpoch := abi.ChainEpoch(50)
  2155  	endEpoch := abi.ChainEpoch(50 + 200*builtin.EpochsInDay)
  2156  
  2157  	t.Run("deal is slashed AT the end epoch -> should NOT be slashed and should be considered expired", func(t *testing.T) {
  2158  		t.Parallel()
  2159  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2160  		dealId := actor.publishAndActivateDeal(rt, client, mAddrs, startEpoch, endEpoch, 0, sectorExpiry, startEpoch)
  2161  		d := actor.getDealProposal(rt, dealId)
  2162  
  2163  		// set current epoch to deal end epoch and attempt to slash it -> should not be slashed
  2164  		// as deal is considered to be expired.
  2165  		current := endEpoch
  2166  		rt.SetEpoch(current)
  2167  		actor.terminateDeals(rt, provider, dealId)
  2168  
  2169  		// on the next cron tick, it will be processed as expired
  2170  		current = endEpoch + 300
  2171  		rt.SetEpoch(current)
  2172  		pay, slashed := actor.cronTickAndAssertBalances(rt, client, provider, current, dealId)
  2173  		duration := big.NewInt(int64(endEpoch - startEpoch)) // end - start
  2174  		require.EqualValues(t, big.Mul(duration, d.StoragePricePerEpoch), pay)
  2175  		require.EqualValues(t, big.Zero(), slashed)
  2176  
  2177  		// deal should be deleted as it should have expired
  2178  		actor.assertDealDeleted(rt, dealId, d)
  2179  
  2180  		actor.checkState(rt)
  2181  	})
  2182  
  2183  	t.Run("deal is correctly processed twice in the same crontick and slashed", func(t *testing.T) {
  2184  		t.Parallel()
  2185  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2186  		dealId := actor.publishAndActivateDeal(rt, client, mAddrs, startEpoch, endEpoch, 0, sectorExpiry, startEpoch)
  2187  		d := actor.getDealProposal(rt, dealId)
  2188  
  2189  		// move the current epoch to startEpoch so next cron epoch will be start + Interval
  2190  		current := startEpoch
  2191  		rt.SetEpoch(current)
  2192  		pay, slashed := actor.cronTickAndAssertBalances(rt, client, provider, current, dealId)
  2193  		require.EqualValues(t, big.Zero(), pay)
  2194  		require.EqualValues(t, big.Zero(), slashed)
  2195  
  2196  		// set slash epoch of deal
  2197  		slashEpoch := current + market.DealUpdatesInterval + 1
  2198  		rt.SetEpoch(slashEpoch)
  2199  		actor.terminateDeals(rt, provider, dealId)
  2200  
  2201  		current2 := current + market.DealUpdatesInterval + 2
  2202  		rt.SetEpoch(current2)
  2203  		duration := big.NewInt(int64(slashEpoch - current))
  2204  		pay, slashed = actor.cronTickAndAssertBalances(rt, client, provider, current2, dealId)
  2205  		require.EqualValues(t, big.Mul(duration, d.StoragePricePerEpoch), pay)
  2206  		require.EqualValues(t, d.ProviderCollateral, slashed)
  2207  
  2208  		// deal should be deleted as it should have expired
  2209  		actor.assertDealDeleted(rt, dealId, d)
  2210  
  2211  		actor.checkState(rt)
  2212  	})
  2213  
  2214  	// end-end tests for slashing
  2215  	t.Run("slash multiple deals in the same epoch", func(t *testing.T) {
  2216  		t.Parallel()
  2217  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2218  
  2219  		// three deals for slashing
  2220  		dealId1 := actor.publishAndActivateDeal(rt, client, mAddrs, startEpoch, endEpoch, 0, sectorExpiry, startEpoch)
  2221  		d1 := actor.getDealProposal(rt, dealId1)
  2222  
  2223  		dealId2 := actor.publishAndActivateDeal(rt, client, mAddrs, startEpoch, endEpoch+1, 0, sectorExpiry, startEpoch)
  2224  		d2 := actor.getDealProposal(rt, dealId2)
  2225  
  2226  		dealId3 := actor.publishAndActivateDeal(rt, client, mAddrs, startEpoch, endEpoch+2, 0, sectorExpiry, startEpoch)
  2227  		d3 := actor.getDealProposal(rt, dealId3)
  2228  
  2229  		// set slash epoch of deal at 151
  2230  		current := abi.ChainEpoch(151)
  2231  		rt.SetEpoch(current)
  2232  		actor.terminateDeals(rt, provider, dealId1, dealId2, dealId3)
  2233  
  2234  		// process slashing of deals
  2235  		current = 300
  2236  		rt.SetEpoch(current)
  2237  		totalSlashed := big.Sum(d1.ProviderCollateral, d2.ProviderCollateral, d3.ProviderCollateral)
  2238  		rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, totalSlashed, nil, exitcode.Ok)
  2239  
  2240  		actor.cronTick(rt)
  2241  
  2242  		actor.assertDealDeleted(rt, dealId1, d1)
  2243  		actor.assertDealDeleted(rt, dealId2, d2)
  2244  		actor.assertDealDeleted(rt, dealId3, d3)
  2245  
  2246  		actor.checkState(rt)
  2247  	})
  2248  
  2249  	t.Run("regular payments till deal is slashed and then slashing is processed", func(t *testing.T) {
  2250  		t.Parallel()
  2251  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2252  		dealId := actor.publishAndActivateDeal(rt, client, mAddrs, startEpoch, endEpoch, 0, sectorExpiry, startEpoch)
  2253  		d := actor.getDealProposal(rt, dealId)
  2254  
  2255  		// move the current epoch to startEpoch + 5 so payment is made
  2256  		current := startEpoch + 5
  2257  		rt.SetEpoch(current)
  2258  		// assert payment
  2259  		pay, slashed := actor.cronTickAndAssertBalances(rt, client, provider, current, dealId)
  2260  		require.EqualValues(t, pay, big.Mul(big.NewInt(5), d.StoragePricePerEpoch))
  2261  		require.EqualValues(t, big.Zero(), slashed)
  2262  
  2263  		// Setting the current epoch to before the next schedule will NOT make any changes as the deal
  2264  		// is still not scheduled
  2265  		current2 := current + market.DealUpdatesInterval - 1
  2266  		rt.SetEpoch(current2)
  2267  		actor.cronTickNoChange(rt, client, provider)
  2268  
  2269  		// a second cron tick for the same epoch should not change anything
  2270  		actor.cronTickNoChange(rt, client, provider)
  2271  
  2272  		//  make another payment
  2273  		current3 := current2 + 1
  2274  		rt.SetEpoch(current3)
  2275  		duration := big.NewInt(int64(current3 - current))
  2276  		pay, slashed = actor.cronTickAndAssertBalances(rt, client, provider, current3, dealId)
  2277  		require.EqualValues(t, pay, big.Mul(duration, d.StoragePricePerEpoch))
  2278  		require.EqualValues(t, big.Zero(), slashed)
  2279  
  2280  		// a second cron tick for the same epoch should not change anything
  2281  		actor.cronTickNoChange(rt, client, provider)
  2282  
  2283  		// now terminate the deal
  2284  		slashEpoch := current3 + 1
  2285  		rt.SetEpoch(slashEpoch)
  2286  		actor.terminateDeals(rt, provider, dealId)
  2287  
  2288  		// Setting the epoch to anything less than next schedule will not make any change even though the deal is slashed
  2289  		current4 := current3 + market.DealUpdatesInterval - 1
  2290  		rt.SetEpoch(current4)
  2291  		actor.cronTickNoChange(rt, client, provider)
  2292  
  2293  		// next epoch for cron schedule  -> payment will be made and deal will be slashed
  2294  		current5 := current4 + 1
  2295  		rt.SetEpoch(current5)
  2296  		duration = big.NewInt(int64(slashEpoch - current3))
  2297  		pay, slashed = actor.cronTickAndAssertBalances(rt, client, provider, current5, dealId)
  2298  		require.EqualValues(t, pay, big.Mul(duration, d.StoragePricePerEpoch))
  2299  		require.EqualValues(t, d.ProviderCollateral, slashed)
  2300  
  2301  		// deal should be deleted as it should have expired
  2302  		actor.assertDealDeleted(rt, dealId, d)
  2303  
  2304  		actor.checkState(rt)
  2305  	})
  2306  
  2307  	// expired deals should NOT be slashed
  2308  	t.Run("regular payments till deal expires and then we attempt to slash it but it will NOT be slashed", func(t *testing.T) {
  2309  		t.Parallel()
  2310  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2311  		dealId := actor.publishAndActivateDeal(rt, client, mAddrs, startEpoch, endEpoch, 0, sectorExpiry, startEpoch)
  2312  		d := actor.getDealProposal(rt, dealId)
  2313  
  2314  		// move the current epoch to startEpoch + 5 so payment is made and assert payment
  2315  		current := startEpoch + 5 // 55
  2316  		rt.SetEpoch(current)
  2317  		pay, slashed := actor.cronTickAndAssertBalances(rt, client, provider, current, dealId)
  2318  		require.EqualValues(t, pay, big.Mul(big.NewInt(5), d.StoragePricePerEpoch))
  2319  		require.EqualValues(t, big.Zero(), slashed)
  2320  
  2321  		//  Setting the current epoch to 155 will make another payment
  2322  		current2 := current + market.DealUpdatesInterval
  2323  		rt.SetEpoch(current2)
  2324  		duration := big.NewInt(int64(current2 - current))
  2325  		pay, slashed = actor.cronTickAndAssertBalances(rt, client, provider, current2, dealId)
  2326  		require.EqualValues(t, pay, big.Mul(duration, d.StoragePricePerEpoch))
  2327  		require.EqualValues(t, big.Zero(), slashed)
  2328  
  2329  		// set current epoch to deal end epoch and attempt to slash it -> should not be slashed
  2330  		// as deal is considered to be expired.
  2331  		rt.SetEpoch(endEpoch)
  2332  		actor.terminateDeals(rt, provider, dealId)
  2333  
  2334  		// next epoch for cron schedule is endEpoch + 300 ->
  2335  		// setting epoch to higher than that will cause deal to be expired, payment will be made
  2336  		// and deal will NOT be slashed
  2337  		current = endEpoch + 300
  2338  		rt.SetEpoch(current)
  2339  		pay, slashed = actor.cronTickAndAssertBalances(rt, client, provider, current, dealId)
  2340  		duration = big.NewInt(int64(endEpoch - current2))
  2341  		require.EqualValues(t, big.Mul(duration, d.StoragePricePerEpoch), pay)
  2342  		require.EqualValues(t, big.Zero(), slashed)
  2343  
  2344  		// deal should be deleted as it should have expired
  2345  		actor.assertDealDeleted(rt, dealId, d)
  2346  
  2347  		actor.checkState(rt)
  2348  	})
  2349  }
  2350  
  2351  func TestMarketActorDeals(t *testing.T) {
  2352  	owner := tutil.NewIDAddr(t, 101)
  2353  	provider := tutil.NewIDAddr(t, 102)
  2354  	worker := tutil.NewIDAddr(t, 103)
  2355  	client := tutil.NewIDAddr(t, 104)
  2356  	minerAddrs := &minerAddrs{owner, worker, provider, nil}
  2357  
  2358  	var st market.State
  2359  
  2360  	// Test adding provider funds from both worker and owner address
  2361  	rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2362  	actor.addProviderFunds(rt, abi.NewTokenAmount(20000000), minerAddrs)
  2363  	rt.GetState(&st)
  2364  	assert.Equal(t, abi.NewTokenAmount(20000000), actor.getEscrowBalance(rt, provider))
  2365  
  2366  	actor.addParticipantFunds(rt, client, abi.NewTokenAmount(20000000))
  2367  
  2368  	dealProposal := generateDealProposal(client, provider, abi.ChainEpoch(1), abi.ChainEpoch(200*builtin.EpochsInDay))
  2369  	params := &market.PublishStorageDealsParams{Deals: []market.ClientDealProposal{{Proposal: dealProposal}}}
  2370  
  2371  	// First attempt at publishing the deal should work
  2372  	{
  2373  		rt.SetCaller(worker, builtin.AccountActorCodeID)
  2374  		actor.publishDeals(rt, minerAddrs, publishDealReq{deal: dealProposal})
  2375  	}
  2376  
  2377  	// Second attempt at publishing the same deal should fail
  2378  	{
  2379  		rt.ExpectValidateCallerType(builtin.AccountActorCodeID, builtin.MultisigActorCodeID)
  2380  		rt.ExpectSend(provider, builtin.MethodsMiner.ControlAddresses, nil, abi.NewTokenAmount(0), &miner.GetControlAddressesReturn{Worker: worker, Owner: owner}, 0)
  2381  		expectQueryNetworkInfo(rt, actor)
  2382  		rt.ExpectVerifySignature(crypto.Signature{}, client, mustCbor(&params.Deals[0].Proposal), nil)
  2383  		rt.SetCaller(worker, builtin.AccountActorCodeID)
  2384  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  2385  			rt.Call(actor.PublishStorageDeals, params)
  2386  		})
  2387  
  2388  		rt.Verify()
  2389  	}
  2390  
  2391  	dealProposal.Label = "foo"
  2392  
  2393  	// Same deal with a different label should work
  2394  	{
  2395  		rt.SetCaller(worker, builtin.AccountActorCodeID)
  2396  		actor.publishDeals(rt, minerAddrs, publishDealReq{deal: dealProposal})
  2397  	}
  2398  	actor.checkState(rt)
  2399  }
  2400  
  2401  func TestMaxDealLabelSize(t *testing.T) {
  2402  	owner := tutil.NewIDAddr(t, 101)
  2403  	provider := tutil.NewIDAddr(t, 102)
  2404  	worker := tutil.NewIDAddr(t, 103)
  2405  	client := tutil.NewIDAddr(t, 104)
  2406  	minerAddrs := &minerAddrs{owner, worker, provider, nil}
  2407  
  2408  	var st market.State
  2409  
  2410  	// Test adding provider funds from both worker and owner address
  2411  	rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2412  	actor.addProviderFunds(rt, abi.NewTokenAmount(20000000), minerAddrs)
  2413  	rt.GetState(&st)
  2414  	assert.Equal(t, abi.NewTokenAmount(20000000), actor.getEscrowBalance(rt, provider))
  2415  
  2416  	actor.addParticipantFunds(rt, client, abi.NewTokenAmount(20000000))
  2417  
  2418  	dealProposal := generateDealProposal(client, provider, abi.ChainEpoch(1), abi.ChainEpoch(200*builtin.EpochsInDay))
  2419  	dealProposal.Label = string(make([]byte, market.DealMaxLabelSize))
  2420  	params := &market.PublishStorageDealsParams{Deals: []market.ClientDealProposal{{Proposal: dealProposal}}}
  2421  
  2422  	// Label at max size should work.
  2423  	{
  2424  		rt.SetCaller(worker, builtin.AccountActorCodeID)
  2425  		actor.publishDeals(rt, minerAddrs, publishDealReq{deal: dealProposal})
  2426  	}
  2427  
  2428  	dealProposal.Label = string(make([]byte, market.DealMaxLabelSize+1))
  2429  
  2430  	// Label greater than max size should fail.
  2431  	{
  2432  		rt.ExpectValidateCallerType(builtin.AccountActorCodeID, builtin.MultisigActorCodeID)
  2433  		rt.ExpectSend(provider, builtin.MethodsMiner.ControlAddresses, nil, abi.NewTokenAmount(0), &miner.GetControlAddressesReturn{Worker: worker, Owner: owner}, 0)
  2434  		expectQueryNetworkInfo(rt, actor)
  2435  		rt.ExpectVerifySignature(crypto.Signature{}, client, mustCbor(&params.Deals[0].Proposal), nil)
  2436  		rt.SetCaller(worker, builtin.AccountActorCodeID)
  2437  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  2438  			rt.Call(actor.PublishStorageDeals, params)
  2439  		})
  2440  
  2441  		rt.Verify()
  2442  	}
  2443  	actor.checkState(rt)
  2444  }
  2445  
  2446  func TestComputeDataCommitment(t *testing.T) {
  2447  	owner := tutil.NewIDAddr(t, 101)
  2448  	provider := tutil.NewIDAddr(t, 102)
  2449  	worker := tutil.NewIDAddr(t, 103)
  2450  	client := tutil.NewIDAddr(t, 104)
  2451  	mAddrs := &minerAddrs{owner, worker, provider, nil}
  2452  	start := abi.ChainEpoch(10)
  2453  	end := start + 200*builtin.EpochsInDay
  2454  
  2455  	t.Run("successfully compute cid", func(t *testing.T) {
  2456  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2457  		dealId1 := actor.generateAndPublishDeal(rt, client, mAddrs, start, end, start)
  2458  		d1 := actor.getDealProposal(rt, dealId1)
  2459  
  2460  		dealId2 := actor.generateAndPublishDeal(rt, client, mAddrs, start, end+1, start)
  2461  		d2 := actor.getDealProposal(rt, dealId2)
  2462  
  2463  		param := &market.ComputeDataCommitmentParams{DealIDs: []abi.DealID{dealId1, dealId2}, SectorType: 1}
  2464  
  2465  		p1 := abi.PieceInfo{Size: d1.PieceSize, PieceCID: d1.PieceCID}
  2466  		p2 := abi.PieceInfo{Size: d2.PieceSize, PieceCID: d2.PieceCID}
  2467  
  2468  		c := tutil.MakeCID("100", &market.PieceCIDPrefix)
  2469  
  2470  		rt.ExpectComputeUnsealedSectorCID(1, []abi.PieceInfo{p1, p2}, c, nil)
  2471  		rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
  2472  		rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  2473  
  2474  		ret := rt.Call(actor.ComputeDataCommitment, param)
  2475  		val, ok := ret.(*cbg.CborCid)
  2476  		require.True(t, ok)
  2477  		require.Equal(t, c, *(*cid.Cid)(val))
  2478  		rt.Verify()
  2479  
  2480  		actor.checkState(rt)
  2481  	})
  2482  
  2483  	t.Run("fail when deal proposal is absent", func(t *testing.T) {
  2484  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2485  		param := &market.ComputeDataCommitmentParams{DealIDs: []abi.DealID{1}, SectorType: 1}
  2486  		rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
  2487  		rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  2488  		rt.ExpectAbort(exitcode.ErrNotFound, func() {
  2489  			rt.Call(actor.ComputeDataCommitment, param)
  2490  		})
  2491  		actor.checkState(rt)
  2492  	})
  2493  
  2494  	t.Run("fail when syscall returns an error", func(t *testing.T) {
  2495  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2496  		dealId := actor.generateAndPublishDeal(rt, client, mAddrs, start, end, start)
  2497  		d := actor.getDealProposal(rt, dealId)
  2498  		param := &market.ComputeDataCommitmentParams{DealIDs: []abi.DealID{dealId}, SectorType: 1}
  2499  
  2500  		pi := abi.PieceInfo{Size: d.PieceSize, PieceCID: d.PieceCID}
  2501  
  2502  		rt.ExpectComputeUnsealedSectorCID(1, []abi.PieceInfo{pi}, cid.Cid{}, errors.New("error"))
  2503  		rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
  2504  		rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  2505  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  2506  			rt.Call(actor.ComputeDataCommitment, param)
  2507  		})
  2508  		actor.checkState(rt)
  2509  	})
  2510  }
  2511  
  2512  func TestVerifyDealsForActivation(t *testing.T) {
  2513  	owner := tutil.NewIDAddr(t, 101)
  2514  	provider := tutil.NewIDAddr(t, 102)
  2515  	worker := tutil.NewIDAddr(t, 103)
  2516  	client := tutil.NewIDAddr(t, 104)
  2517  	mAddrs := &minerAddrs{owner, worker, provider, nil}
  2518  	start := abi.ChainEpoch(10)
  2519  	end := start + 200*builtin.EpochsInDay
  2520  	sectorExpiry := end + 200
  2521  
  2522  	t.Run("verify deal and get deal weight for unverified deal proposal", func(t *testing.T) {
  2523  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2524  		dealId := actor.generateAndPublishDeal(rt, client, mAddrs, start, end, start)
  2525  		d := actor.getDealProposal(rt, dealId)
  2526  
  2527  		resp := actor.verifyDealsForActivation(rt, provider, []market.SectorDeals{{
  2528  			SectorExpiry: sectorExpiry,
  2529  			DealIDs:      []abi.DealID{dealId},
  2530  		}})
  2531  		require.EqualValues(t, big.Zero(), resp.Sectors[0].VerifiedDealWeight)
  2532  		require.EqualValues(t, market.DealWeight(d), resp.Sectors[0].DealWeight)
  2533  
  2534  		actor.checkState(rt)
  2535  	})
  2536  
  2537  	t.Run("verify deal and get deal weight for verified deal proposal", func(t *testing.T) {
  2538  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2539  		deal := actor.generateDealAndAddFunds(rt, client, mAddrs, start, end)
  2540  		deal.VerifiedDeal = true
  2541  		rt.SetCaller(worker, builtin.AccountActorCodeID)
  2542  		dealIds := actor.publishDeals(rt, mAddrs, publishDealReq{deal: deal})
  2543  
  2544  		resp := actor.verifyDealsForActivation(rt, provider, []market.SectorDeals{{
  2545  			SectorExpiry: sectorExpiry,
  2546  			DealIDs:      dealIds,
  2547  		}})
  2548  		require.EqualValues(t, market.DealWeight(&deal), resp.Sectors[0].VerifiedDealWeight)
  2549  		require.EqualValues(t, big.Zero(), resp.Sectors[0].DealWeight)
  2550  
  2551  		actor.checkState(rt)
  2552  	})
  2553  
  2554  	t.Run("verification and weights for verified and unverified deals", func(T *testing.T) {
  2555  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2556  
  2557  		vd1 := actor.generateDealAndAddFunds(rt, client, mAddrs, start, end)
  2558  		vd1.VerifiedDeal = true
  2559  
  2560  		vd2 := actor.generateDealAndAddFunds(rt, client, mAddrs, start, end+1)
  2561  		vd2.VerifiedDeal = true
  2562  
  2563  		d1 := actor.generateDealAndAddFunds(rt, client, mAddrs, start, end+2)
  2564  		d2 := actor.generateDealAndAddFunds(rt, client, mAddrs, start, end+3)
  2565  
  2566  		rt.SetCaller(worker, builtin.AccountActorCodeID)
  2567  		dealIds := actor.publishDeals(rt, mAddrs, publishDealReq{deal: vd1}, publishDealReq{deal: vd2},
  2568  			publishDealReq{deal: d1}, publishDealReq{deal: d2})
  2569  
  2570  		resp := actor.verifyDealsForActivation(rt, provider, []market.SectorDeals{{
  2571  			SectorExpiry: sectorExpiry,
  2572  			DealIDs:      dealIds,
  2573  		}})
  2574  
  2575  		verifiedWeight := big.Add(market.DealWeight(&vd1), market.DealWeight(&vd2))
  2576  		nvweight := big.Add(market.DealWeight(&d1), market.DealWeight(&d2))
  2577  		require.EqualValues(t, verifiedWeight, resp.Sectors[0].VerifiedDealWeight)
  2578  		require.EqualValues(t, nvweight, resp.Sectors[0].DealWeight)
  2579  
  2580  		actor.checkState(rt)
  2581  	})
  2582  
  2583  	t.Run("fail when caller is not a StorageMinerActor", func(t *testing.T) {
  2584  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2585  		dealId := actor.generateAndPublishDeal(rt, client, mAddrs, start, end, start)
  2586  
  2587  		param := &market.VerifyDealsForActivationParams{Sectors: []market.SectorDeals{{
  2588  			SectorExpiry: sectorExpiry,
  2589  			DealIDs:      []abi.DealID{dealId},
  2590  		}}}
  2591  		rt.SetCaller(worker, builtin.AccountActorCodeID)
  2592  		rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  2593  		rt.ExpectAbort(exitcode.SysErrForbidden, func() {
  2594  			rt.Call(actor.VerifyDealsForActivation, param)
  2595  		})
  2596  		actor.checkState(rt)
  2597  	})
  2598  
  2599  	t.Run("fail when deal proposal is not found", func(t *testing.T) {
  2600  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2601  		param := &market.VerifyDealsForActivationParams{Sectors: []market.SectorDeals{{
  2602  			SectorExpiry: sectorExpiry,
  2603  			DealIDs:      []abi.DealID{1},
  2604  		}}}
  2605  		rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
  2606  		rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  2607  		rt.ExpectAbort(exitcode.ErrNotFound, func() {
  2608  			rt.Call(actor.VerifyDealsForActivation, param)
  2609  		})
  2610  		actor.checkState(rt)
  2611  	})
  2612  
  2613  	t.Run("fail when caller is not the provider", func(t *testing.T) {
  2614  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2615  		dealId := actor.generateAndPublishDeal(rt, client, mAddrs, start, end, start)
  2616  
  2617  		param := &market.VerifyDealsForActivationParams{Sectors: []market.SectorDeals{{
  2618  			SectorExpiry: sectorExpiry,
  2619  			DealIDs:      []abi.DealID{dealId},
  2620  		}}}
  2621  		provider2 := tutil.NewIDAddr(t, 205)
  2622  		rt.SetCaller(provider2, builtin.StorageMinerActorCodeID)
  2623  		rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  2624  		rt.ExpectAbort(exitcode.ErrForbidden, func() {
  2625  			rt.Call(actor.VerifyDealsForActivation, param)
  2626  		})
  2627  		actor.checkState(rt)
  2628  	})
  2629  
  2630  	t.Run("fail when current epoch is greater than proposal start epoch", func(t *testing.T) {
  2631  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2632  		dealId := actor.generateAndPublishDeal(rt, client, mAddrs, start, end, start)
  2633  
  2634  		rt.SetEpoch(start + 1)
  2635  		param := &market.VerifyDealsForActivationParams{Sectors: []market.SectorDeals{{
  2636  			SectorExpiry: sectorExpiry,
  2637  			DealIDs:      []abi.DealID{dealId},
  2638  		}}}
  2639  		rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
  2640  		rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  2641  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  2642  			rt.Call(actor.VerifyDealsForActivation, param)
  2643  		})
  2644  		actor.checkState(rt)
  2645  	})
  2646  
  2647  	t.Run("fail when deal end epoch is greater than sector expiration", func(t *testing.T) {
  2648  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2649  		dealId := actor.generateAndPublishDeal(rt, client, mAddrs, start, end, start)
  2650  
  2651  		param := &market.VerifyDealsForActivationParams{Sectors: []market.SectorDeals{{
  2652  			SectorExpiry: end - 1,
  2653  			DealIDs:      []abi.DealID{dealId},
  2654  		}}}
  2655  		rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
  2656  		rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  2657  		rt.ExpectAbort(exitcode.ErrIllegalArgument, func() {
  2658  			rt.Call(actor.VerifyDealsForActivation, param)
  2659  		})
  2660  		actor.checkState(rt)
  2661  	})
  2662  
  2663  	t.Run("fail when the same deal ID is passed multiple times", func(t *testing.T) {
  2664  		rt, actor := basicMarketSetup(t, owner, provider, worker, client)
  2665  		dealId := actor.generateAndPublishDeal(rt, client, mAddrs, start, end, start)
  2666  
  2667  		param := &market.VerifyDealsForActivationParams{Sectors: []market.SectorDeals{{
  2668  			SectorExpiry: sectorExpiry,
  2669  			DealIDs:      []abi.DealID{dealId, dealId},
  2670  		}}}
  2671  		rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
  2672  		rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  2673  		rt.ExpectAbortContainsMessage(exitcode.ErrIllegalArgument, "multiple times", func() {
  2674  			rt.Call(actor.VerifyDealsForActivation, param)
  2675  		})
  2676  		actor.checkState(rt)
  2677  	})
  2678  }
  2679  
  2680  type marketActorTestHarness struct {
  2681  	market.Actor
  2682  	t testing.TB
  2683  
  2684  	networkQAPower       abi.StoragePower
  2685  	networkBaselinePower abi.StoragePower
  2686  }
  2687  
  2688  func (h *marketActorTestHarness) constructAndVerify(rt *mock.Runtime) {
  2689  	rt.ExpectValidateCallerAddr(builtin.SystemActorAddr)
  2690  	ret := rt.Call(h.Constructor, nil)
  2691  	assert.Nil(h.t, ret)
  2692  	rt.Verify()
  2693  }
  2694  
  2695  func (h *marketActorTestHarness) verifyDealsForActivation(rt *mock.Runtime, provider address.Address,
  2696  	sectorDeals []market.SectorDeals) *market.VerifyDealsForActivationReturn {
  2697  	param := &market.VerifyDealsForActivationParams{Sectors: sectorDeals}
  2698  	rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  2699  	rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
  2700  
  2701  	ret := rt.Call(h.VerifyDealsForActivation, param)
  2702  	rt.Verify()
  2703  
  2704  	val, ok := ret.(*market.VerifyDealsForActivationReturn)
  2705  	require.True(h.t, ok)
  2706  	require.NotNil(h.t, val)
  2707  	return val
  2708  }
  2709  
  2710  type minerAddrs struct {
  2711  	owner    address.Address
  2712  	worker   address.Address
  2713  	provider address.Address
  2714  	control  []address.Address
  2715  }
  2716  
  2717  // addProviderFunds is a helper method to setup provider market funds
  2718  func (h *marketActorTestHarness) addProviderFunds(rt *mock.Runtime, amount abi.TokenAmount, minerAddrs *minerAddrs) {
  2719  	rt.SetReceived(amount)
  2720  	rt.SetAddressActorType(minerAddrs.provider, builtin.StorageMinerActorCodeID)
  2721  	rt.SetCaller(minerAddrs.owner, builtin.AccountActorCodeID)
  2722  	rt.ExpectValidateCallerType(builtin.CallerTypesSignable...)
  2723  
  2724  	expectGetControlAddresses(rt, minerAddrs.provider, minerAddrs.owner, minerAddrs.worker)
  2725  
  2726  	rt.Call(h.AddBalance, &minerAddrs.provider)
  2727  
  2728  	rt.Verify()
  2729  
  2730  	rt.SetBalance(big.Add(rt.Balance(), amount))
  2731  }
  2732  
  2733  // addParticipantFunds is a helper method to setup non-provider storage market participant funds
  2734  func (h *marketActorTestHarness) addParticipantFunds(rt *mock.Runtime, addr address.Address, amount abi.TokenAmount) {
  2735  	rt.SetReceived(amount)
  2736  	rt.SetCaller(addr, builtin.AccountActorCodeID)
  2737  	rt.ExpectValidateCallerType(builtin.CallerTypesSignable...)
  2738  
  2739  	rt.Call(h.AddBalance, &addr)
  2740  
  2741  	rt.Verify()
  2742  
  2743  	rt.SetBalance(big.Add(rt.Balance(), amount))
  2744  }
  2745  
  2746  func (h *marketActorTestHarness) withdrawProviderBalance(rt *mock.Runtime, withDrawAmt, expectedSend abi.TokenAmount, miner *minerAddrs) {
  2747  	rt.SetCaller(miner.worker, builtin.AccountActorCodeID)
  2748  	rt.ExpectValidateCallerAddr(miner.owner, miner.worker)
  2749  	expectGetControlAddresses(rt, miner.provider, miner.owner, miner.worker)
  2750  
  2751  	params := market.WithdrawBalanceParams{
  2752  		ProviderOrClientAddress: miner.provider,
  2753  		Amount:                  withDrawAmt,
  2754  	}
  2755  
  2756  	rt.ExpectSend(miner.owner, builtin.MethodSend, nil, expectedSend, nil, exitcode.Ok)
  2757  	rt.Call(h.WithdrawBalance, &params)
  2758  	rt.Verify()
  2759  }
  2760  
  2761  func (h *marketActorTestHarness) withdrawClientBalance(rt *mock.Runtime, client address.Address, withDrawAmt, expectedSend abi.TokenAmount) {
  2762  	rt.SetCaller(client, builtin.AccountActorCodeID)
  2763  	rt.ExpectSend(client, builtin.MethodSend, nil, expectedSend, nil, exitcode.Ok)
  2764  	rt.ExpectValidateCallerAddr(client)
  2765  
  2766  	params := market.WithdrawBalanceParams{
  2767  		ProviderOrClientAddress: client,
  2768  		Amount:                  withDrawAmt,
  2769  	}
  2770  
  2771  	rt.Call(h.WithdrawBalance, &params)
  2772  	rt.Verify()
  2773  }
  2774  
  2775  func (h *marketActorTestHarness) cronTickNoChange(rt *mock.Runtime, client, provider address.Address) {
  2776  	var st market.State
  2777  	rt.GetState(&st)
  2778  	epochCid := st.DealOpsByEpoch
  2779  
  2780  	// fetch current client and provider escrow balances
  2781  	cLocked := h.getLockedBalance(rt, client)
  2782  	cEscrow := h.getEscrowBalance(rt, client)
  2783  	pLocked := h.getLockedBalance(rt, provider)
  2784  	pEscrow := h.getEscrowBalance(rt, provider)
  2785  
  2786  	h.cronTick(rt)
  2787  
  2788  	rt.GetState(&st)
  2789  	require.True(h.t, epochCid.Equals(st.DealOpsByEpoch))
  2790  
  2791  	require.EqualValues(h.t, cEscrow, h.getEscrowBalance(rt, client))
  2792  	require.EqualValues(h.t, cLocked, h.getLockedBalance(rt, client))
  2793  	require.EqualValues(h.t, pEscrow, h.getEscrowBalance(rt, provider))
  2794  	require.EqualValues(h.t, pLocked, h.getLockedBalance(rt, provider))
  2795  }
  2796  
  2797  // if this is the first crontick for the deal, it's next tick will be scheduled at `desiredNextEpoch`
  2798  // if this is not the first crontick, the `desiredNextEpoch` param is ignored.
  2799  func (h *marketActorTestHarness) cronTickAndAssertBalances(rt *mock.Runtime, client, provider address.Address,
  2800  	currentEpoch abi.ChainEpoch, dealId abi.DealID) (payment abi.TokenAmount, amountSlashed abi.TokenAmount) {
  2801  	// fetch current client and provider escrow balances
  2802  	cLocked := h.getLockedBalance(rt, client)
  2803  	cEscrow := h.getEscrowBalance(rt, client)
  2804  	pLocked := h.getLockedBalance(rt, provider)
  2805  	pEscrow := h.getEscrowBalance(rt, provider)
  2806  	amountSlashed = big.Zero()
  2807  
  2808  	s := h.getDealState(rt, dealId)
  2809  	d := h.getDealProposal(rt, dealId)
  2810  
  2811  	// end epoch for payment calc
  2812  	paymentEnd := d.EndEpoch
  2813  	if s.SlashEpoch != -1 {
  2814  		rt.ExpectSend(builtin.BurntFundsActorAddr, builtin.MethodSend, nil, d.ProviderCollateral, nil, exitcode.Ok)
  2815  		amountSlashed = d.ProviderCollateral
  2816  
  2817  		if s.SlashEpoch < d.StartEpoch {
  2818  			paymentEnd = d.StartEpoch
  2819  		} else {
  2820  			paymentEnd = s.SlashEpoch
  2821  		}
  2822  	} else if currentEpoch < paymentEnd {
  2823  		paymentEnd = currentEpoch
  2824  	}
  2825  
  2826  	// start epoch for payment calc
  2827  	paymentStart := d.StartEpoch
  2828  	if s.LastUpdatedEpoch != -1 {
  2829  		paymentStart = s.LastUpdatedEpoch
  2830  	}
  2831  	duration := paymentEnd - paymentStart
  2832  	payment = big.Mul(big.NewInt(int64(duration)), d.StoragePricePerEpoch)
  2833  
  2834  	// expected updated amounts
  2835  	updatedClientEscrow := big.Sub(cEscrow, payment)
  2836  	updatedProviderEscrow := big.Add(pEscrow, payment)
  2837  	updatedProviderEscrow = big.Sub(updatedProviderEscrow, amountSlashed)
  2838  	updatedClientLocked := big.Sub(cLocked, payment)
  2839  	updatedProviderLocked := pLocked
  2840  	// if the deal has expired or been slashed, locked amount will be zero for provider and client.
  2841  	isDealExpired := paymentEnd == d.EndEpoch
  2842  	if isDealExpired || s.SlashEpoch != -1 {
  2843  		updatedClientLocked = big.Zero()
  2844  		updatedProviderLocked = big.Zero()
  2845  	}
  2846  
  2847  	h.cronTick(rt)
  2848  
  2849  	require.EqualValues(h.t, updatedClientEscrow, h.getEscrowBalance(rt, client))
  2850  	require.EqualValues(h.t, updatedClientLocked, h.getLockedBalance(rt, client))
  2851  	require.Equal(h.t, updatedProviderLocked, h.getLockedBalance(rt, provider))
  2852  	require.Equal(h.t, updatedProviderEscrow.Int64(), h.getEscrowBalance(rt, provider).Int64())
  2853  
  2854  	return
  2855  }
  2856  
  2857  func (h *marketActorTestHarness) cronTick(rt *mock.Runtime) {
  2858  	rt.ExpectValidateCallerAddr(builtin.CronActorAddr)
  2859  	rt.SetCaller(builtin.CronActorAddr, builtin.CronActorCodeID)
  2860  	param := abi.EmptyValue{}
  2861  
  2862  	rt.Call(h.CronTick, &param)
  2863  	rt.Verify()
  2864  }
  2865  
  2866  type publishDealReq struct {
  2867  	deal                 market.DealProposal
  2868  	requiredProcessEpoch abi.ChainEpoch
  2869  }
  2870  
  2871  func (h *marketActorTestHarness) expectGetRandom(rt *mock.Runtime, deal *market.DealProposal, requiredProcessEpoch abi.ChainEpoch) {
  2872  	dealBuf := bytes.Buffer{}
  2873  	epochBuf := bytes.Buffer{}
  2874  
  2875  	diff := uint64(requiredProcessEpoch - deal.StartEpoch)
  2876  	require.NoError(h.t, deal.MarshalCBOR(&dealBuf))
  2877  	require.NoError(h.t, binary.Write(&epochBuf, binary.BigEndian, diff))
  2878  	rt.ExpectGetRandomnessBeacon(crypto.DomainSeparationTag_MarketDealCronSeed, rt.Epoch()-1, dealBuf.Bytes(), epochBuf.Bytes())
  2879  }
  2880  
  2881  func (h *marketActorTestHarness) publishDeals(rt *mock.Runtime, minerAddrs *minerAddrs, publishDealReqs ...publishDealReq) []abi.DealID {
  2882  	for _, pdr := range publishDealReqs {
  2883  		h.expectGetRandom(rt, &pdr.deal, pdr.requiredProcessEpoch)
  2884  	}
  2885  
  2886  	rt.ExpectValidateCallerType(builtin.CallerTypesSignable...)
  2887  	rt.ExpectSend(
  2888  		minerAddrs.provider,
  2889  		builtin.MethodsMiner.ControlAddresses,
  2890  		nil,
  2891  		big.Zero(),
  2892  		&miner.GetControlAddressesReturn{Owner: minerAddrs.owner, Worker: minerAddrs.worker, ControlAddrs: minerAddrs.control},
  2893  		exitcode.Ok,
  2894  	)
  2895  	expectQueryNetworkInfo(rt, h)
  2896  
  2897  	var params market.PublishStorageDealsParams
  2898  
  2899  	for _, pdr := range publishDealReqs {
  2900  		//  create a client proposal with a valid signature
  2901  		buf := bytes.Buffer{}
  2902  		require.NoError(h.t, pdr.deal.MarshalCBOR(&buf), "failed to marshal deal proposal")
  2903  		sig := crypto.Signature{Type: crypto.SigTypeBLS, Data: []byte("does not matter")}
  2904  		clientProposal := market.ClientDealProposal{Proposal: pdr.deal, ClientSignature: sig}
  2905  		params.Deals = append(params.Deals, clientProposal)
  2906  
  2907  		// expect a call to verify the above signature
  2908  		rt.ExpectVerifySignature(sig, pdr.deal.Client, buf.Bytes(), nil)
  2909  		if pdr.deal.VerifiedDeal {
  2910  			param := &verifreg.UseBytesParams{
  2911  				Address:  pdr.deal.Client,
  2912  				DealSize: big.NewIntUnsigned(uint64(pdr.deal.PieceSize)),
  2913  			}
  2914  
  2915  			rt.ExpectSend(builtin.VerifiedRegistryActorAddr, builtin.MethodsVerifiedRegistry.UseBytes, param, abi.NewTokenAmount(0), nil, exitcode.Ok)
  2916  		}
  2917  	}
  2918  
  2919  	ret := rt.Call(h.PublishStorageDeals, &params)
  2920  	rt.Verify()
  2921  
  2922  	resp, ok := ret.(*market.PublishStorageDealsReturn)
  2923  	require.True(h.t, ok, "unexpected type returned from call to PublishStorageDeals")
  2924  	require.Len(h.t, resp.IDs, len(publishDealReqs))
  2925  
  2926  	// assert state after publishing the deals
  2927  	dealIds := resp.IDs
  2928  	for i, deaId := range dealIds {
  2929  		expected := publishDealReqs[i].deal
  2930  		p := h.getDealProposal(rt, deaId)
  2931  
  2932  		require.Equal(h.t, expected.StartEpoch, p.StartEpoch)
  2933  		require.Equal(h.t, expected.EndEpoch, p.EndEpoch)
  2934  		require.Equal(h.t, expected.PieceCID, p.PieceCID)
  2935  		require.Equal(h.t, expected.PieceSize, p.PieceSize)
  2936  		require.Equal(h.t, expected.Client, p.Client)
  2937  		require.Equal(h.t, expected.Provider, p.Provider)
  2938  		require.Equal(h.t, expected.Label, p.Label)
  2939  		require.Equal(h.t, expected.VerifiedDeal, p.VerifiedDeal)
  2940  		require.Equal(h.t, expected.StoragePricePerEpoch, p.StoragePricePerEpoch)
  2941  		require.Equal(h.t, expected.ClientCollateral, p.ClientCollateral)
  2942  		require.Equal(h.t, expected.ProviderCollateral, p.ProviderCollateral)
  2943  	}
  2944  
  2945  	return resp.IDs
  2946  }
  2947  
  2948  func (h *marketActorTestHarness) assertDealsNotActivated(rt *mock.Runtime, epoch abi.ChainEpoch, dealIDs ...abi.DealID) {
  2949  	var st market.State
  2950  	rt.GetState(&st)
  2951  
  2952  	states, err := market.AsDealStateArray(adt.AsStore(rt), st.States)
  2953  	require.NoError(h.t, err)
  2954  
  2955  	for _, d := range dealIDs {
  2956  		_, found, err := states.Get(d)
  2957  		require.NoError(h.t, err)
  2958  		require.False(h.t, found)
  2959  	}
  2960  }
  2961  
  2962  func (h *marketActorTestHarness) activateDeals(rt *mock.Runtime, sectorExpiry abi.ChainEpoch, provider address.Address, currentEpoch abi.ChainEpoch, dealIDs ...abi.DealID) {
  2963  	rt.SetCaller(provider, builtin.StorageMinerActorCodeID)
  2964  	rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  2965  
  2966  	params := &market.ActivateDealsParams{DealIDs: dealIDs, SectorExpiry: sectorExpiry}
  2967  
  2968  	ret := rt.Call(h.ActivateDeals, params)
  2969  	rt.Verify()
  2970  
  2971  	require.Nil(h.t, ret)
  2972  
  2973  	for _, d := range dealIDs {
  2974  		s := h.getDealState(rt, d)
  2975  		require.EqualValues(h.t, currentEpoch, s.SectorStartEpoch)
  2976  	}
  2977  }
  2978  
  2979  func (h *marketActorTestHarness) getDealProposal(rt *mock.Runtime, dealID abi.DealID) *market.DealProposal {
  2980  	var st market.State
  2981  	rt.GetState(&st)
  2982  
  2983  	deals, err := market.AsDealProposalArray(adt.AsStore(rt), st.Proposals)
  2984  	require.NoError(h.t, err)
  2985  
  2986  	d, found, err := deals.Get(dealID)
  2987  	require.NoError(h.t, err)
  2988  	require.True(h.t, found)
  2989  	require.NotNil(h.t, d)
  2990  
  2991  	return d
  2992  }
  2993  
  2994  func (h *marketActorTestHarness) assertAccountZero(rt *mock.Runtime, addr address.Address) {
  2995  	var st market.State
  2996  	rt.GetState(&st)
  2997  
  2998  	et, err := adt.AsBalanceTable(adt.AsStore(rt), st.EscrowTable)
  2999  	require.NoError(h.t, err)
  3000  
  3001  	b, err := et.Get(addr)
  3002  	require.NoError(h.t, err)
  3003  	require.Equal(h.t, big.Zero(), b)
  3004  
  3005  	lt, err := adt.AsBalanceTable(adt.AsStore(rt), st.LockedTable)
  3006  	require.NoError(h.t, err)
  3007  	b, err = lt.Get(addr)
  3008  	require.NoError(h.t, err)
  3009  	require.Equal(h.t, big.Zero(), b)
  3010  }
  3011  
  3012  func (h *marketActorTestHarness) getEscrowBalance(rt *mock.Runtime, addr address.Address) abi.TokenAmount {
  3013  	var st market.State
  3014  	rt.GetState(&st)
  3015  
  3016  	et, err := adt.AsBalanceTable(adt.AsStore(rt), st.EscrowTable)
  3017  	require.NoError(h.t, err)
  3018  
  3019  	bal, err := et.Get(addr)
  3020  	require.NoError(h.t, err)
  3021  
  3022  	return bal
  3023  }
  3024  
  3025  func (h *marketActorTestHarness) getLockedBalance(rt *mock.Runtime, addr address.Address) abi.TokenAmount {
  3026  	var st market.State
  3027  	rt.GetState(&st)
  3028  
  3029  	lt, err := adt.AsBalanceTable(adt.AsStore(rt), st.LockedTable)
  3030  	require.NoError(h.t, err)
  3031  
  3032  	bal, err := lt.Get(addr)
  3033  	require.NoError(h.t, err)
  3034  
  3035  	return bal
  3036  }
  3037  
  3038  func (h *marketActorTestHarness) getDealState(rt *mock.Runtime, dealID abi.DealID) *market.DealState {
  3039  	var st market.State
  3040  	rt.GetState(&st)
  3041  
  3042  	states, err := market.AsDealStateArray(adt.AsStore(rt), st.States)
  3043  	require.NoError(h.t, err)
  3044  
  3045  	s, found, err := states.Get(dealID)
  3046  	require.NoError(h.t, err)
  3047  	require.True(h.t, found)
  3048  	require.NotNil(h.t, s)
  3049  
  3050  	return s
  3051  }
  3052  
  3053  func (h *marketActorTestHarness) assertLockedFundStates(rt *mock.Runtime, storageFee, providerCollateral, clientCollateral abi.TokenAmount) {
  3054  	var st market.State
  3055  	rt.GetState(&st)
  3056  
  3057  	require.Equal(h.t, clientCollateral, st.TotalClientLockedCollateral)
  3058  	require.Equal(h.t, providerCollateral, st.TotalProviderLockedCollateral)
  3059  	require.Equal(h.t, storageFee, st.TotalClientStorageFee)
  3060  }
  3061  
  3062  func (h *marketActorTestHarness) assertDealDeleted(rt *mock.Runtime, dealId abi.DealID, p *market.DealProposal) {
  3063  	var st market.State
  3064  	rt.GetState(&st)
  3065  
  3066  	proposals, err := market.AsDealProposalArray(adt.AsStore(rt), st.Proposals)
  3067  	require.NoError(h.t, err)
  3068  	_, found, err := proposals.Get(dealId)
  3069  	require.NoError(h.t, err)
  3070  	require.False(h.t, found)
  3071  
  3072  	states, err := market.AsDealStateArray(adt.AsStore(rt), st.States)
  3073  	require.NoError(h.t, err)
  3074  	_, found, err = states.Get(dealId)
  3075  	require.NoError(h.t, err)
  3076  	require.False(h.t, found)
  3077  
  3078  	pcid, err := p.Cid()
  3079  	require.NoError(h.t, err)
  3080  	pending, err := adt.AsMap(adt.AsStore(rt), st.PendingProposals, builtin.DefaultHamtBitwidth)
  3081  	require.NoError(h.t, err)
  3082  	found, err = pending.Get(abi.CidKey(pcid), nil)
  3083  	require.NoError(h.t, err)
  3084  	require.False(h.t, found)
  3085  }
  3086  
  3087  func (h *marketActorTestHarness) assertDealsTerminated(rt *mock.Runtime, epoch abi.ChainEpoch, dealIds ...abi.DealID) {
  3088  	for _, d := range dealIds {
  3089  		s := h.getDealState(rt, d)
  3090  		require.EqualValues(h.t, epoch, s.SlashEpoch)
  3091  	}
  3092  }
  3093  
  3094  func (h *marketActorTestHarness) assertDeaslNotTerminated(rt *mock.Runtime, dealIds ...abi.DealID) {
  3095  	for _, d := range dealIds {
  3096  		s := h.getDealState(rt, d)
  3097  		require.EqualValues(h.t, abi.ChainEpoch(-1), s.SlashEpoch)
  3098  	}
  3099  }
  3100  
  3101  func (h *marketActorTestHarness) terminateDeals(rt *mock.Runtime, minerAddr address.Address, dealIds ...abi.DealID) {
  3102  	rt.SetCaller(minerAddr, builtin.StorageMinerActorCodeID)
  3103  	rt.ExpectValidateCallerType(builtin.StorageMinerActorCodeID)
  3104  
  3105  	params := mkTerminateDealParams(rt.Epoch(), dealIds...)
  3106  
  3107  	ret := rt.Call(h.OnMinerSectorsTerminate, params)
  3108  	rt.Verify()
  3109  	require.Nil(h.t, ret)
  3110  }
  3111  
  3112  func (h *marketActorTestHarness) publishAndActivateDeal(rt *mock.Runtime, client address.Address, minerAddrs *minerAddrs,
  3113  	startEpoch, endEpoch, currentEpoch, sectorExpiry abi.ChainEpoch, requiredProcessEpoch abi.ChainEpoch) abi.DealID {
  3114  	deal := h.generateDealAndAddFunds(rt, client, minerAddrs, startEpoch, endEpoch)
  3115  	rt.SetCaller(minerAddrs.worker, builtin.AccountActorCodeID)
  3116  	dealIds := h.publishDeals(rt, minerAddrs, publishDealReq{deal: deal, requiredProcessEpoch: requiredProcessEpoch})
  3117  	h.activateDeals(rt, sectorExpiry, minerAddrs.provider, currentEpoch, dealIds[0])
  3118  	return dealIds[0]
  3119  }
  3120  
  3121  func (h *marketActorTestHarness) updateLastUpdated(rt *mock.Runtime, dealId abi.DealID, newLastUpdated abi.ChainEpoch) {
  3122  	var st market.State
  3123  	rt.GetState(&st)
  3124  
  3125  	states, err := market.AsDealStateArray(adt.AsStore(rt), st.States)
  3126  	require.NoError(h.t, err)
  3127  	s, found, err := states.Get(dealId)
  3128  	require.True(h.t, found)
  3129  	require.NoError(h.t, err)
  3130  	require.NotNil(h.t, s)
  3131  
  3132  	require.NoError(h.t, states.Set(dealId, &market.DealState{s.SectorStartEpoch, newLastUpdated, s.SlashEpoch}))
  3133  	st.States, err = states.Root()
  3134  	require.NoError(h.t, err)
  3135  	rt.ReplaceState(&st)
  3136  }
  3137  
  3138  func (h *marketActorTestHarness) deleteDealProposal(rt *mock.Runtime, dealId abi.DealID) {
  3139  	var st market.State
  3140  	rt.GetState(&st)
  3141  	deals, err := market.AsDealProposalArray(adt.AsStore(rt), st.Proposals)
  3142  	require.NoError(h.t, err)
  3143  	require.NoError(h.t, deals.Delete(dealId))
  3144  	st.Proposals, err = deals.Root()
  3145  	require.NoError(h.t, err)
  3146  	rt.ReplaceState(&st)
  3147  }
  3148  
  3149  func (h *marketActorTestHarness) generateAndPublishDeal(rt *mock.Runtime, client address.Address, minerAddrs *minerAddrs,
  3150  	startEpoch, endEpoch abi.ChainEpoch, requiredProcessEpoch abi.ChainEpoch) abi.DealID {
  3151  
  3152  	deal := h.generateDealAndAddFunds(rt, client, minerAddrs, startEpoch, endEpoch)
  3153  	rt.SetCaller(minerAddrs.worker, builtin.AccountActorCodeID)
  3154  	dealIds := h.publishDeals(rt, minerAddrs, publishDealReq{deal: deal, requiredProcessEpoch: requiredProcessEpoch})
  3155  	return dealIds[0]
  3156  }
  3157  
  3158  func (h *marketActorTestHarness) generateDealAndAddFunds(rt *mock.Runtime, client address.Address, minerAddrs *minerAddrs,
  3159  	startEpoch, endEpoch abi.ChainEpoch) market.DealProposal {
  3160  	deal4 := generateDealProposal(client, minerAddrs.provider, startEpoch, endEpoch)
  3161  	h.addProviderFunds(rt, deal4.ProviderCollateral, minerAddrs)
  3162  	h.addParticipantFunds(rt, client, deal4.ClientBalanceRequirement())
  3163  
  3164  	return deal4
  3165  }
  3166  
  3167  func (h *marketActorTestHarness) generateDealWithCollateralAndAddFunds(rt *mock.Runtime, client address.Address,
  3168  	minerAddrs *minerAddrs, providerCollateral, clientCollateral abi.TokenAmount, startEpoch, endEpoch abi.ChainEpoch) market.DealProposal {
  3169  	deal := generateDealProposalWithCollateral(client, minerAddrs.provider, providerCollateral, clientCollateral,
  3170  		startEpoch, endEpoch)
  3171  	h.addProviderFunds(rt, deal.ProviderCollateral, minerAddrs)
  3172  	h.addParticipantFunds(rt, client, deal.ClientBalanceRequirement())
  3173  
  3174  	return deal
  3175  }
  3176  
  3177  func (h *marketActorTestHarness) checkState(rt *mock.Runtime) {
  3178  	var st market.State
  3179  	rt.GetState(&st)
  3180  	_, msgs := market.CheckStateInvariants(&st, rt.AdtStore(), rt.Balance(), rt.Epoch())
  3181  	assert.True(h.t, msgs.IsEmpty(), strings.Join(msgs.Messages(), "\n"))
  3182  }
  3183  
  3184  func generateDealProposalWithCollateral(client, provider address.Address, providerCollateral, clientCollateral abi.TokenAmount, startEpoch, endEpoch abi.ChainEpoch) market.DealProposal {
  3185  	pieceCid := tutil.MakeCID("1", &market.PieceCIDPrefix)
  3186  	pieceSize := abi.PaddedPieceSize(2048)
  3187  	storagePerEpoch := big.NewInt(10)
  3188  
  3189  	return market.DealProposal{PieceCID: pieceCid, PieceSize: pieceSize, Client: client, Provider: provider, Label: "label", StartEpoch: startEpoch,
  3190  		EndEpoch: endEpoch, StoragePricePerEpoch: storagePerEpoch, ProviderCollateral: providerCollateral, ClientCollateral: clientCollateral}
  3191  }
  3192  
  3193  func generateDealProposal(client, provider address.Address, startEpoch, endEpoch abi.ChainEpoch) market.DealProposal {
  3194  	clientCollateral := big.NewInt(10)
  3195  	providerCollateral := big.NewInt(10)
  3196  
  3197  	return generateDealProposalWithCollateral(client, provider, clientCollateral, providerCollateral, startEpoch, endEpoch)
  3198  }
  3199  
  3200  func basicMarketSetup(t *testing.T, owner, provider, worker, client address.Address) (*mock.Runtime, *marketActorTestHarness) {
  3201  	builder := mock.NewBuilder(builtin.StorageMarketActorAddr).
  3202  		WithCaller(builtin.SystemActorAddr, builtin.InitActorCodeID).
  3203  		WithBalance(big.Mul(big.NewInt(10), big.NewInt(1e18)), big.Zero()).
  3204  		WithActorType(owner, builtin.AccountActorCodeID).
  3205  		WithActorType(worker, builtin.AccountActorCodeID).
  3206  		WithActorType(provider, builtin.StorageMinerActorCodeID).
  3207  		WithActorType(client, builtin.AccountActorCodeID)
  3208  
  3209  	rt := builder.Build(t)
  3210  	power := abi.NewStoragePower(1 << 50)
  3211  	actor := marketActorTestHarness{
  3212  		t:                    t,
  3213  		networkQAPower:       power,
  3214  		networkBaselinePower: power,
  3215  	}
  3216  	actor.constructAndVerify(rt)
  3217  
  3218  	return rt, &actor
  3219  }
  3220  
  3221  func mkPublishStorageParams(proposals ...market.DealProposal) *market.PublishStorageDealsParams {
  3222  	m := &market.PublishStorageDealsParams{}
  3223  	for _, p := range proposals {
  3224  		m.Deals = append(m.Deals, market.ClientDealProposal{Proposal: p})
  3225  	}
  3226  	return m
  3227  }
  3228  
  3229  func mkActivateDealParams(sectorExpiry abi.ChainEpoch, dealIds ...abi.DealID) *market.ActivateDealsParams {
  3230  	return &market.ActivateDealsParams{SectorExpiry: sectorExpiry, DealIDs: dealIds}
  3231  }
  3232  
  3233  func mkTerminateDealParams(epoch abi.ChainEpoch, dealIds ...abi.DealID) *market.OnMinerSectorsTerminateParams {
  3234  	return &market.OnMinerSectorsTerminateParams{Epoch: epoch, DealIDs: dealIds}
  3235  }
  3236  
  3237  func expectGetControlAddresses(rt *mock.Runtime, provider address.Address, owner, worker address.Address, controls ...address.Address) {
  3238  	result := &miner.GetControlAddressesReturn{Owner: owner, Worker: worker, ControlAddrs: controls}
  3239  	rt.ExpectSend(
  3240  		provider,
  3241  		builtin.MethodsMiner.ControlAddresses,
  3242  		nil,
  3243  		big.Zero(),
  3244  		result,
  3245  		exitcode.Ok,
  3246  	)
  3247  }
  3248  
  3249  func expectQueryNetworkInfo(rt *mock.Runtime, h *marketActorTestHarness) {
  3250  	currentPower := power.CurrentTotalPowerReturn{
  3251  		QualityAdjPower: h.networkQAPower,
  3252  	}
  3253  	currentReward := reward.ThisEpochRewardReturn{
  3254  		ThisEpochBaselinePower: h.networkBaselinePower,
  3255  	}
  3256  	rt.ExpectSend(
  3257  		builtin.RewardActorAddr,
  3258  		builtin.MethodsReward.ThisEpochReward,
  3259  		nil,
  3260  		big.Zero(),
  3261  		&currentReward,
  3262  		exitcode.Ok,
  3263  	)
  3264  
  3265  	rt.ExpectSend(
  3266  		builtin.StoragePowerActorAddr,
  3267  		builtin.MethodsPower.CurrentTotalPower,
  3268  		nil,
  3269  		big.Zero(),
  3270  		&currentPower,
  3271  		exitcode.Ok,
  3272  	)
  3273  }