github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/transactionPayerBalanceChecker_test.go (about)

     1  package fvm_test
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/mock"
     8  	"github.com/stretchr/testify/require"
     9  
    10  	"github.com/onflow/cadence"
    11  
    12  	"github.com/onflow/flow-go/fvm"
    13  	fvmmock "github.com/onflow/flow-go/fvm/environment/mock"
    14  	"github.com/onflow/flow-go/fvm/errors"
    15  	"github.com/onflow/flow-go/fvm/storage/testutils"
    16  	"github.com/onflow/flow-go/model/flow"
    17  )
    18  
    19  func TestTransactionPayerBalanceChecker(t *testing.T) {
    20  	payer := flow.HexToAddress("1")
    21  	t.Run("TransactionFeesEnabled == false disables the balance check", func(t *testing.T) {
    22  		env := &fvmmock.Environment{}
    23  		env.On("TransactionFeesEnabled").Return(false)
    24  
    25  		proc := &fvm.TransactionProcedure{}
    26  		proc.Transaction = &flow.TransactionBody{}
    27  		proc.Transaction.Payer = payer
    28  
    29  		txnState := testutils.NewSimpleTransaction(nil)
    30  
    31  		d := fvm.TransactionPayerBalanceChecker{}
    32  		maxFees, err := d.CheckPayerBalanceAndReturnMaxFees(proc, txnState, env)
    33  		require.NoError(t, err)
    34  		require.Equal(t, uint64(0), maxFees)
    35  	})
    36  
    37  	t.Run("errors during CheckPayerBalanceAndGetMaxTxFees invocation are wrapped and returned", func(t *testing.T) {
    38  		someError := fmt.Errorf("some error")
    39  
    40  		env := &fvmmock.Environment{}
    41  		env.On("TransactionFeesEnabled").Return(true)
    42  		env.On("CheckPayerBalanceAndGetMaxTxFees", mock.Anything, mock.Anything, mock.Anything).Return(
    43  			nil,
    44  			someError)
    45  
    46  		proc := &fvm.TransactionProcedure{}
    47  		proc.Transaction = &flow.TransactionBody{}
    48  		proc.Transaction.Payer = payer
    49  
    50  		txnState := testutils.NewSimpleTransaction(nil)
    51  
    52  		d := fvm.TransactionPayerBalanceChecker{}
    53  		maxFees, err := d.CheckPayerBalanceAndReturnMaxFees(proc, txnState, env)
    54  		require.Error(t, err)
    55  		require.True(t, errors.HasFailureCode(err, errors.FailureCodePayerBalanceCheckFailure))
    56  		require.ErrorIs(t, err, someError)
    57  		require.Equal(t, uint64(0), maxFees)
    58  	})
    59  
    60  	t.Run("unexpected result type from CheckPayerBalanceAndGetMaxTxFees causes error", func(t *testing.T) {
    61  		env := &fvmmock.Environment{}
    62  		env.On("TransactionFeesEnabled").Return(true)
    63  		env.On("CheckPayerBalanceAndGetMaxTxFees", mock.Anything, mock.Anything, mock.Anything).Return(
    64  			cadence.Struct{},
    65  			nil)
    66  
    67  		proc := &fvm.TransactionProcedure{}
    68  		proc.Transaction = &flow.TransactionBody{}
    69  		proc.Transaction.Payer = payer
    70  
    71  		txnState := testutils.NewSimpleTransaction(nil)
    72  
    73  		d := fvm.TransactionPayerBalanceChecker{}
    74  		maxFees, err := d.CheckPayerBalanceAndReturnMaxFees(proc, txnState, env)
    75  		require.Error(t, err)
    76  		require.True(t, errors.HasFailureCode(err, errors.FailureCodePayerBalanceCheckFailure))
    77  		require.Equal(t, uint64(0), maxFees)
    78  	})
    79  
    80  	t.Run("if payer can pay return max fees", func(t *testing.T) {
    81  		env := &fvmmock.Environment{}
    82  		env.On("TransactionFeesEnabled").Return(true)
    83  		env.On(
    84  			"CheckPayerBalanceAndGetMaxTxFees",
    85  			mock.Anything,
    86  			mock.Anything,
    87  			mock.Anything,
    88  		).Return(
    89  			cadence.NewStruct([]cadence.Value{
    90  				cadence.NewBool(true),
    91  				cadence.UFix64(100),
    92  				cadence.UFix64(100),
    93  			}).WithType(fvm.VerifyPayerBalanceResultType),
    94  			nil,
    95  		)
    96  
    97  		proc := &fvm.TransactionProcedure{}
    98  		proc.Transaction = &flow.TransactionBody{}
    99  		proc.Transaction.Payer = payer
   100  
   101  		txnState := testutils.NewSimpleTransaction(nil)
   102  
   103  		d := fvm.TransactionPayerBalanceChecker{}
   104  		maxFees, err := d.CheckPayerBalanceAndReturnMaxFees(proc, txnState, env)
   105  		require.NoError(t, err)
   106  		require.Equal(t, uint64(100), maxFees)
   107  	})
   108  
   109  	t.Run("if payer cannot pay return insufficient balance error", func(t *testing.T) {
   110  		env := &fvmmock.Environment{}
   111  		env.On("TransactionFeesEnabled").Return(true)
   112  		env.On(
   113  			"CheckPayerBalanceAndGetMaxTxFees",
   114  			mock.Anything,
   115  			mock.Anything,
   116  			mock.Anything,
   117  		).Return(
   118  			cadence.NewStruct([]cadence.Value{
   119  				cadence.NewBool(false),
   120  				cadence.UFix64(100),
   121  				cadence.UFix64(101),
   122  			}).WithType(fvm.VerifyPayerBalanceResultType),
   123  			nil,
   124  		)
   125  
   126  		proc := &fvm.TransactionProcedure{}
   127  		proc.Transaction = &flow.TransactionBody{}
   128  		proc.Transaction.Payer = payer
   129  
   130  		txnState := testutils.NewSimpleTransaction(nil)
   131  
   132  		d := fvm.TransactionPayerBalanceChecker{}
   133  		maxFees, err := d.CheckPayerBalanceAndReturnMaxFees(proc, txnState, env)
   134  		require.Error(t, err)
   135  		require.Contains(t, err.Error(), errors.NewInsufficientPayerBalanceError(payer, 100).Error())
   136  		require.Equal(t, uint64(0), maxFees)
   137  	})
   138  }