github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/rpcclient/notary/contract_test.go (about)

     1  package notary
     2  
     3  import (
     4  	"errors"
     5  	"math"
     6  	"math/big"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/nspcc-dev/neo-go/internal/testserdes"
    11  	"github.com/nspcc-dev/neo-go/pkg/core/transaction"
    12  	"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
    13  	"github.com/nspcc-dev/neo-go/pkg/util"
    14  	"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  type testAct struct {
    19  	err error
    20  	res *result.Invoke
    21  	tx  *transaction.Transaction
    22  	txh util.Uint256
    23  	vub uint32
    24  }
    25  
    26  func (t *testAct) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) {
    27  	return t.res, t.err
    28  }
    29  func (t *testAct) MakeRun(script []byte) (*transaction.Transaction, error) {
    30  	return t.tx, t.err
    31  }
    32  func (t *testAct) MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) {
    33  	return t.tx, t.err
    34  }
    35  func (t *testAct) SendRun(script []byte) (util.Uint256, uint32, error) {
    36  	return t.txh, t.vub, t.err
    37  }
    38  func (t *testAct) MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) {
    39  	return t.tx, t.err
    40  }
    41  func (t *testAct) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) {
    42  	return t.tx, t.err
    43  }
    44  func (t *testAct) SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) {
    45  	return t.txh, t.vub, t.err
    46  }
    47  
    48  func TestBalanceOf(t *testing.T) {
    49  	ta := &testAct{}
    50  	ntr := NewReader(ta)
    51  
    52  	ta.err = errors.New("")
    53  	_, err := ntr.BalanceOf(util.Uint160{})
    54  	require.Error(t, err)
    55  
    56  	ta.err = nil
    57  	ta.res = &result.Invoke{
    58  		State: "HALT",
    59  		Stack: []stackitem.Item{
    60  			stackitem.Make(42),
    61  		},
    62  	}
    63  	res, err := ntr.BalanceOf(util.Uint160{})
    64  	require.NoError(t, err)
    65  	require.Equal(t, big.NewInt(42), res)
    66  }
    67  
    68  func TestUint32Getters(t *testing.T) {
    69  	ta := &testAct{}
    70  	ntr := NewReader(ta)
    71  
    72  	for name, fun := range map[string]func() (uint32, error){
    73  		"ExpirationOf": func() (uint32, error) {
    74  			return ntr.ExpirationOf(util.Uint160{1, 2, 3})
    75  		},
    76  		"GetMaxNotValidBeforeDelta": ntr.GetMaxNotValidBeforeDelta,
    77  	} {
    78  		t.Run(name, func(t *testing.T) {
    79  			ta.err = errors.New("")
    80  			_, err := fun()
    81  			require.Error(t, err)
    82  
    83  			ta.err = nil
    84  			ta.res = &result.Invoke{
    85  				State: "HALT",
    86  				Stack: []stackitem.Item{
    87  					stackitem.Make(42),
    88  				},
    89  			}
    90  			res, err := fun()
    91  			require.NoError(t, err)
    92  			require.Equal(t, uint32(42), res)
    93  
    94  			ta.res = &result.Invoke{
    95  				State: "HALT",
    96  				Stack: []stackitem.Item{
    97  					stackitem.Make(-1),
    98  				},
    99  			}
   100  			_, err = fun()
   101  			require.Error(t, err)
   102  		})
   103  	}
   104  }
   105  
   106  func TestTxSenders(t *testing.T) {
   107  	ta := new(testAct)
   108  	ntr := New(ta)
   109  
   110  	for name, fun := range map[string]func() (util.Uint256, uint32, error){
   111  		"LockDepositUntil": func() (util.Uint256, uint32, error) {
   112  			return ntr.LockDepositUntil(util.Uint160{1, 2, 3}, 100500)
   113  		},
   114  		"SetMaxNotValidBeforeDelta": func() (util.Uint256, uint32, error) {
   115  			return ntr.SetMaxNotValidBeforeDelta(42)
   116  		},
   117  		"Withdraw": func() (util.Uint256, uint32, error) {
   118  			return ntr.Withdraw(util.Uint160{1, 2, 3}, util.Uint160{3, 2, 1})
   119  		},
   120  	} {
   121  		t.Run(name, func(t *testing.T) {
   122  			ta.err = errors.New("")
   123  			_, _, err := fun()
   124  			require.Error(t, err)
   125  
   126  			ta.err = nil
   127  			ta.txh = util.Uint256{1, 2, 3}
   128  			ta.vub = 42
   129  			h, vub, err := fun()
   130  			require.NoError(t, err)
   131  			require.Equal(t, ta.txh, h)
   132  			require.Equal(t, ta.vub, vub)
   133  		})
   134  	}
   135  }
   136  
   137  func TestTxMakers(t *testing.T) {
   138  	ta := new(testAct)
   139  	ntr := New(ta)
   140  
   141  	for name, fun := range map[string]func() (*transaction.Transaction, error){
   142  		"LockDepositUntilTransaction": func() (*transaction.Transaction, error) {
   143  			return ntr.LockDepositUntilTransaction(util.Uint160{1, 2, 3}, 100500)
   144  		},
   145  		"LockDepositUntilUnsigned": func() (*transaction.Transaction, error) {
   146  			return ntr.LockDepositUntilUnsigned(util.Uint160{1, 2, 3}, 100500)
   147  		},
   148  		"SetMaxNotValidBeforeDeltaTransaction": func() (*transaction.Transaction, error) {
   149  			return ntr.SetMaxNotValidBeforeDeltaTransaction(42)
   150  		},
   151  		"SetMaxNotValidBeforeDeltaUnsigned": func() (*transaction.Transaction, error) {
   152  			return ntr.SetMaxNotValidBeforeDeltaUnsigned(42)
   153  		},
   154  		"WithdrawTransaction": func() (*transaction.Transaction, error) {
   155  			return ntr.WithdrawTransaction(util.Uint160{1, 2, 3}, util.Uint160{3, 2, 1})
   156  		},
   157  		"WithdrawUnsigned": func() (*transaction.Transaction, error) {
   158  			return ntr.WithdrawUnsigned(util.Uint160{1, 2, 3}, util.Uint160{3, 2, 1})
   159  		},
   160  	} {
   161  		t.Run(name, func(t *testing.T) {
   162  			ta.err = errors.New("")
   163  			_, err := fun()
   164  			require.Error(t, err)
   165  
   166  			ta.err = nil
   167  			ta.tx = &transaction.Transaction{Nonce: 100500, ValidUntilBlock: 42}
   168  			tx, err := fun()
   169  			require.NoError(t, err)
   170  			require.Equal(t, ta.tx, tx)
   171  		})
   172  	}
   173  }
   174  
   175  func TestOnNEP17PaymentData_Convertible(t *testing.T) {
   176  	t.Run("non-empty owner", func(t *testing.T) {
   177  		d := &OnNEP17PaymentData{
   178  			Account: &util.Uint160{1, 2, 3},
   179  			Till:    123,
   180  		}
   181  		testserdes.ToFromStackItem(t, d, new(OnNEP17PaymentData))
   182  	})
   183  	t.Run("empty owner", func(t *testing.T) {
   184  		d := &OnNEP17PaymentData{
   185  			Account: nil,
   186  			Till:    123,
   187  		}
   188  		testserdes.ToFromStackItem(t, d, new(OnNEP17PaymentData))
   189  	})
   190  }
   191  
   192  func TestOnNEP17PaymentDataToStackItem(t *testing.T) {
   193  	testCases := map[string]struct {
   194  		data     *OnNEP17PaymentData
   195  		expected stackitem.Item
   196  	}{
   197  		"non-empty owner": {
   198  			data: &OnNEP17PaymentData{
   199  				Account: &util.Uint160{1, 2, 3},
   200  				Till:    123,
   201  			},
   202  			expected: stackitem.NewArray([]stackitem.Item{
   203  				stackitem.Make(util.Uint160{1, 2, 3}),
   204  				stackitem.Make(123),
   205  			}),
   206  		},
   207  		"empty owner": {
   208  			data: &OnNEP17PaymentData{
   209  				Account: nil,
   210  				Till:    123,
   211  			},
   212  			expected: stackitem.NewArray([]stackitem.Item{
   213  				stackitem.Null{},
   214  				stackitem.Make(123),
   215  			}),
   216  		},
   217  	}
   218  	for name, tc := range testCases {
   219  		t.Run(name, func(t *testing.T) {
   220  			actual, err := tc.data.ToStackItem()
   221  			require.NoError(t, err)
   222  			require.Equal(t, tc.expected, actual)
   223  		})
   224  	}
   225  }
   226  
   227  func TestOnNEP17PaymentData_FromStackItem(t *testing.T) {
   228  	errCases := map[string]stackitem.Item{
   229  		"unexpected stackitem type":            stackitem.NewBool(true),
   230  		"unexpected number of fields":          stackitem.NewArray([]stackitem.Item{stackitem.NewBool(true)}),
   231  		"failed to retrieve account bytes":     stackitem.NewArray([]stackitem.Item{stackitem.NewInterop(nil), stackitem.Make(1)}),
   232  		"failed to decode account bytes":       stackitem.NewArray([]stackitem.Item{stackitem.Make([]byte{1}), stackitem.Make(1)}),
   233  		"failed to retrieve till":              stackitem.NewArray([]stackitem.Item{stackitem.Make(util.Uint160{1}), stackitem.NewInterop(nil)}),
   234  		"till is not an int64":                 stackitem.NewArray([]stackitem.Item{stackitem.Make(util.Uint160{1}), stackitem.NewBigInteger(new(big.Int).Add(big.NewInt(math.MaxInt64), big.NewInt(1)))}),
   235  		"till is larger than max uint32 value": stackitem.NewArray([]stackitem.Item{stackitem.Make(util.Uint160{1}), stackitem.Make(math.MaxUint32 + 1)}),
   236  	}
   237  	for name, errCase := range errCases {
   238  		t.Run(name, func(t *testing.T) {
   239  			d := new(OnNEP17PaymentData)
   240  			err := d.FromStackItem(errCase)
   241  			require.Error(t, err)
   242  			require.True(t, strings.Contains(err.Error(), name), name)
   243  		})
   244  	}
   245  }