gitlab.com/flarenetwork/coreth@v0.1.1/core/keeper_test.go (about)

     1  // (c) 2021, Flare Networks Limited. All rights reserved.
     2  // Please see the file LICENSE for licensing terms.
     3  
     4  package core
     5  
     6  import (
     7  	"errors"
     8  	"math/big"
     9  	"testing"
    10  
    11  	"github.com/ethereum/go-ethereum/common"
    12  	"github.com/ethereum/go-ethereum/log"
    13  
    14  	"gitlab.com/flarenetwork/coreth/core/vm"
    15  )
    16  
    17  // Define a mock structure to spy and mock values for keeper calls
    18  type MockEVMCallerData struct {
    19  	callCalls            int
    20  	addBalanceCalls      int
    21  	blockNumber          big.Int
    22  	gasLimit             uint64
    23  	mintRequestReturn    big.Int
    24  	lastAddBalanceAddr   common.Address
    25  	lastAddBalanceAmount *big.Int
    26  }
    27  
    28  // Define a mock structure to spy and mock values for logger calls
    29  type MockLoggerData struct {
    30  	warnCalls int
    31  }
    32  
    33  // Set up default mock method calls
    34  func defautCall(e *MockEVMCallerData, caller vm.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
    35  	e.callCalls++
    36  
    37  	buffer := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    38  	return e.mintRequestReturn.FillBytes(buffer), 0, nil
    39  }
    40  
    41  func defaultGetBlockNumber(e *MockEVMCallerData) *big.Int {
    42  	return &e.blockNumber
    43  }
    44  
    45  func defaultGetGasLimit(e *MockEVMCallerData) uint64 {
    46  	return e.gasLimit
    47  }
    48  
    49  func defaultAddBalance(e *MockEVMCallerData, addr common.Address, amount *big.Int) {
    50  	e.addBalanceCalls++
    51  	e.lastAddBalanceAddr = addr
    52  	e.lastAddBalanceAmount = amount
    53  }
    54  
    55  // Define the default EVM mock and define default mock receiver functions
    56  type DefaultEVMMock struct {
    57  	mockEVMCallerData MockEVMCallerData
    58  }
    59  
    60  func (e *DefaultEVMMock) Call(caller vm.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
    61  	return defautCall(&e.mockEVMCallerData, caller, addr, input, gas, value)
    62  }
    63  
    64  func (e *DefaultEVMMock) GetBlockNumber() *big.Int {
    65  	return defaultGetBlockNumber(&e.mockEVMCallerData)
    66  }
    67  
    68  func (e *DefaultEVMMock) GetGasLimit() uint64 {
    69  	return defaultGetGasLimit(&e.mockEVMCallerData)
    70  }
    71  
    72  func (e *DefaultEVMMock) AddBalance(addr common.Address, amount *big.Int) {
    73  	defaultAddBalance(&e.mockEVMCallerData, addr, amount)
    74  }
    75  
    76  func TestKeeperTriggerShouldReturnMintRequest(t *testing.T) {
    77  	mintRequestReturn, _ := new(big.Int).SetString("50000000000000000000000000", 10)
    78  	mockEVMCallerData := &MockEVMCallerData{
    79  		blockNumber:       *big.NewInt(0),
    80  		gasLimit:          0,
    81  		mintRequestReturn: *mintRequestReturn,
    82  	}
    83  	defaultEVMMock := &DefaultEVMMock{
    84  		mockEVMCallerData: *mockEVMCallerData,
    85  	}
    86  
    87  	mintRequest, _ := triggerKeeper(defaultEVMMock)
    88  
    89  	if mintRequest.Cmp(mintRequestReturn) != 0 {
    90  		t.Errorf("got %s want %q", mintRequest.Text(10), "50000000000000000000000000")
    91  	}
    92  }
    93  
    94  func TestKeeperTriggerShouldNotLetMintRequestOverflow(t *testing.T) {
    95  	var mintRequestReturn big.Int
    96  	// TODO: Compact with exponent?
    97  	buffer := []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}
    98  	mintRequestReturn.SetBytes(buffer)
    99  
   100  	mockEVMCallerData := &MockEVMCallerData{
   101  		blockNumber:       *big.NewInt(0),
   102  		gasLimit:          0,
   103  		mintRequestReturn: mintRequestReturn,
   104  	}
   105  	defaultEVMMock := &DefaultEVMMock{
   106  		mockEVMCallerData: *mockEVMCallerData,
   107  	}
   108  
   109  	mintRequest, mintRequestError := triggerKeeper(defaultEVMMock)
   110  
   111  	if mintRequestError != nil {
   112  		t.Errorf("received unexpected error %s", mintRequestError)
   113  	}
   114  
   115  	if mintRequest.Sign() < 1 {
   116  		t.Errorf("unexpected negative")
   117  	}
   118  }
   119  
   120  // Define a bad mint request return size mock
   121  type BadMintReturnSizeEVMMock struct {
   122  	mockEVMCallerData MockEVMCallerData
   123  }
   124  
   125  func (e *BadMintReturnSizeEVMMock) Call(caller vm.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
   126  	e.mockEVMCallerData.callCalls++
   127  	// Should be size 32 bytes
   128  	buffer := []byte{0}
   129  	return e.mockEVMCallerData.mintRequestReturn.FillBytes(buffer), 0, nil
   130  }
   131  
   132  func (e *BadMintReturnSizeEVMMock) GetBlockNumber() *big.Int {
   133  	return defaultGetBlockNumber(&e.mockEVMCallerData)
   134  }
   135  
   136  func (e *BadMintReturnSizeEVMMock) GetGasLimit() uint64 {
   137  	return defaultGetGasLimit(&e.mockEVMCallerData)
   138  }
   139  
   140  func (e *BadMintReturnSizeEVMMock) AddBalance(addr common.Address, amount *big.Int) {
   141  	defaultAddBalance(&e.mockEVMCallerData, addr, amount)
   142  }
   143  
   144  func TestKeeperTriggerValidatesMintRequestReturnValueSize(t *testing.T) {
   145  	var mintRequestReturn big.Int
   146  	// TODO: Compact with exponent?
   147  	buffer := []byte{255}
   148  	mintRequestReturn.SetBytes(buffer)
   149  
   150  	mockEVMCallerData := &MockEVMCallerData{
   151  		blockNumber:       *big.NewInt(0),
   152  		gasLimit:          0,
   153  		mintRequestReturn: mintRequestReturn,
   154  	}
   155  	badMintReturnSizeEVMMock := &BadMintReturnSizeEVMMock{
   156  		mockEVMCallerData: *mockEVMCallerData,
   157  	}
   158  	// Call to return less than 32 bytes
   159  	_, err := triggerKeeper(badMintReturnSizeEVMMock)
   160  
   161  	if err != nil {
   162  		if err, ok := err.(*ErrInvalidKeeperData); !ok {
   163  			want := &ErrInvalidKeeperData{}
   164  			t.Errorf("got '%s' want '%s'", err.Error(), want.Error())
   165  		}
   166  	} else {
   167  		t.Errorf("no error returned as expected")
   168  	}
   169  }
   170  
   171  // Define a mock to simulate keeper trigger returning an error from Call
   172  type BadTriggerCallEVMMock struct {
   173  	mockEVMCallerData MockEVMCallerData
   174  }
   175  
   176  func (e *BadTriggerCallEVMMock) Call(caller vm.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
   177  	e.mockEVMCallerData.callCalls++
   178  
   179  	buffer := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
   180  	return e.mockEVMCallerData.mintRequestReturn.FillBytes(buffer), 0, errors.New("Call error happened")
   181  }
   182  
   183  func (e *BadTriggerCallEVMMock) GetBlockNumber() *big.Int {
   184  	return defaultGetBlockNumber(&e.mockEVMCallerData)
   185  }
   186  
   187  func (e *BadTriggerCallEVMMock) GetGasLimit() uint64 {
   188  	return defaultGetGasLimit(&e.mockEVMCallerData)
   189  }
   190  
   191  func (e *BadTriggerCallEVMMock) AddBalance(addr common.Address, amount *big.Int) {
   192  	defaultAddBalance(&e.mockEVMCallerData, addr, amount)
   193  }
   194  
   195  func TestKeeperTriggerReturnsCallError(t *testing.T) {
   196  	mockEVMCallerData := &MockEVMCallerData{}
   197  	badTriggerCallEVMMock := &BadTriggerCallEVMMock{
   198  		mockEVMCallerData: *mockEVMCallerData,
   199  	}
   200  	// Call to return less than 32 bytes
   201  	_, err := triggerKeeper(badTriggerCallEVMMock)
   202  
   203  	if err == nil {
   204  		t.Errorf("no error received")
   205  	} else {
   206  		if err.Error() != "Call error happened" {
   207  			t.Errorf("did not get expected error")
   208  		}
   209  	}
   210  }
   211  
   212  type LoggerMock struct {
   213  	mockLoggerData MockLoggerData
   214  }
   215  
   216  func (l *LoggerMock) New(ctx ...interface{}) log.Logger {
   217  	return nil
   218  }
   219  
   220  func (l *LoggerMock) GetHandler() log.Handler {
   221  	return nil
   222  }
   223  
   224  func (l *LoggerMock) SetHandler(h log.Handler) {
   225  }
   226  
   227  func (l *LoggerMock) Trace(msg string, ctx ...interface{}) {}
   228  func (l *LoggerMock) Debug(msg string, ctx ...interface{}) {}
   229  func (l *LoggerMock) Info(msg string, ctx ...interface{})  {}
   230  func (l *LoggerMock) Error(msg string, ctx ...interface{}) {}
   231  func (l *LoggerMock) Crit(msg string, ctx ...interface{})  {}
   232  
   233  func (l *LoggerMock) Warn(msg string, ctx ...interface{}) {
   234  	l.mockLoggerData.warnCalls++
   235  }
   236  
   237  func TestKeeperTriggerAndMintLogsError(t *testing.T) {
   238  	// Assemble
   239  	// Set up mock EVM call to return an error
   240  	mockEVMCallerData := &MockEVMCallerData{}
   241  	badTriggerCallEVMMock := &BadTriggerCallEVMMock{
   242  		mockEVMCallerData: *mockEVMCallerData,
   243  	}
   244  	// Set up a mock logger
   245  	mockLoggerData := &MockLoggerData{}
   246  	loggerMock := &LoggerMock{
   247  		mockLoggerData: *mockLoggerData,
   248  	}
   249  
   250  	// Act
   251  	triggerKeeperAndMint(badTriggerCallEVMMock, loggerMock)
   252  
   253  	// Assert
   254  	if loggerMock.mockLoggerData.warnCalls != 1 {
   255  		t.Errorf("Logger.Warn not called as expected")
   256  	}
   257  }
   258  
   259  // Define a mock to simulate keeper trigger returning nil for mint request
   260  type ReturnNilMintRequestEVMMock struct {
   261  	mockEVMCallerData MockEVMCallerData
   262  }
   263  
   264  func (e *ReturnNilMintRequestEVMMock) Call(caller vm.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
   265  	e.mockEVMCallerData.callCalls++
   266  
   267  	return nil, 0, nil
   268  }
   269  
   270  func (e *ReturnNilMintRequestEVMMock) GetBlockNumber() *big.Int {
   271  	return defaultGetBlockNumber(&e.mockEVMCallerData)
   272  }
   273  
   274  func (e *ReturnNilMintRequestEVMMock) GetGasLimit() uint64 {
   275  	return defaultGetGasLimit(&e.mockEVMCallerData)
   276  }
   277  
   278  func (e *ReturnNilMintRequestEVMMock) AddBalance(addr common.Address, amount *big.Int) {
   279  	defaultAddBalance(&e.mockEVMCallerData, addr, amount)
   280  }
   281  
   282  func TestKeeperTriggerHandlesNilMintRequest(t *testing.T) {
   283  	mockEVMCallerData := &MockEVMCallerData{}
   284  	returnNilMintRequestEVMMock := &ReturnNilMintRequestEVMMock{
   285  		mockEVMCallerData: *mockEVMCallerData,
   286  	}
   287  	// Call to return less than 32 bytes
   288  	_, err := triggerKeeper(returnNilMintRequestEVMMock)
   289  
   290  	if err != nil {
   291  		if err, ok := err.(*ErrKeeperDataEmpty); !ok {
   292  			want := &ErrKeeperDataEmpty{}
   293  			t.Errorf("got '%s' want '%s'", err.Error(), want.Error())
   294  		}
   295  	} else {
   296  		t.Errorf("no error returned as expected")
   297  	}
   298  }
   299  
   300  func TestKeeperTriggerShouldNotMintMoreThanMax(t *testing.T) {
   301  	mintRequest, _ := new(big.Int).SetString("50000000000000000000000001", 10)
   302  	mockEVMCallerData := &MockEVMCallerData{
   303  		blockNumber:       *big.NewInt(0),
   304  		gasLimit:          0,
   305  		mintRequestReturn: *big.NewInt(0),
   306  	}
   307  	defaultEVMMock := &DefaultEVMMock{
   308  		mockEVMCallerData: *mockEVMCallerData,
   309  	}
   310  
   311  	err := mint(defaultEVMMock, mintRequest)
   312  
   313  	if err != nil {
   314  		if err, ok := err.(*ErrMaxMintExceeded); !ok {
   315  			want := &ErrMaxMintExceeded{
   316  				mintRequest: mintRequest,
   317  				mintMax:     GetMaximumMintRequest(big.NewInt(0)),
   318  			}
   319  			t.Errorf("got '%s' want '%s'", err.Error(), want.Error())
   320  		}
   321  	} else {
   322  		t.Errorf("no error returned as expected")
   323  	}
   324  }
   325  
   326  func TestKeeperTriggerShouldNotMintNegative(t *testing.T) {
   327  	mintRequest := big.NewInt(-1)
   328  	mockEVMCallerData := &MockEVMCallerData{
   329  		blockNumber:       *big.NewInt(0),
   330  		gasLimit:          0,
   331  		mintRequestReturn: *big.NewInt(0),
   332  	}
   333  	defaultEVMMock := &DefaultEVMMock{
   334  		mockEVMCallerData: *mockEVMCallerData,
   335  	}
   336  
   337  	err := mint(defaultEVMMock, mintRequest)
   338  
   339  	if err != nil {
   340  		if err, ok := err.(*ErrMintNegative); !ok {
   341  			want := &ErrMintNegative{}
   342  			t.Errorf("got '%s' want '%s'", err.Error(), want.Error())
   343  		}
   344  	} else {
   345  		t.Errorf("no error returned as expected")
   346  	}
   347  }
   348  
   349  func TestKeeperTriggerShouldMint(t *testing.T) {
   350  	// Assemble
   351  	mintRequest, _ := new(big.Int).SetString("50000000000000000000000000", 10)
   352  	mockEVMCallerData := &MockEVMCallerData{
   353  		blockNumber:       *big.NewInt(0),
   354  		gasLimit:          0,
   355  		mintRequestReturn: *big.NewInt(0),
   356  	}
   357  	defaultEVMMock := &DefaultEVMMock{
   358  		mockEVMCallerData: *mockEVMCallerData,
   359  	}
   360  
   361  	// Act
   362  	err := mint(defaultEVMMock, mintRequest)
   363  
   364  	// Assert
   365  	if err == nil {
   366  		if defaultEVMMock.mockEVMCallerData.addBalanceCalls != 1 {
   367  			t.Errorf("AddBalance not called as expected")
   368  		}
   369  		if defaultEVMMock.mockEVMCallerData.lastAddBalanceAddr.String() != GetSystemTriggerContractAddr(big.NewInt(0)) {
   370  			t.Errorf("wanted addr %s; got addr %s", GetSystemTriggerContractAddr(big.NewInt(0)), defaultEVMMock.mockEVMCallerData.lastAddBalanceAddr)
   371  		}
   372  		if defaultEVMMock.mockEVMCallerData.lastAddBalanceAmount.Cmp(mintRequest) != 0 {
   373  			t.Errorf("wanted amount %s; got amount %s", mintRequest.Text(10), defaultEVMMock.mockEVMCallerData.lastAddBalanceAmount.Text(10))
   374  		}
   375  	} else {
   376  		t.Errorf("unexpected error returned; was = %s", err.Error())
   377  	}
   378  }
   379  
   380  func TestKeeperTriggerShouldNotErrorMintingZero(t *testing.T) {
   381  	// Assemble
   382  	mintRequest := big.NewInt(0)
   383  	mockEVMCallerData := &MockEVMCallerData{
   384  		blockNumber:       *big.NewInt(0),
   385  		gasLimit:          0,
   386  		mintRequestReturn: *big.NewInt(0),
   387  	}
   388  	defaultEVMMock := &DefaultEVMMock{
   389  		mockEVMCallerData: *mockEVMCallerData,
   390  	}
   391  
   392  	// Act
   393  	err := mint(defaultEVMMock, mintRequest)
   394  
   395  	// Assert
   396  	if err == nil {
   397  		if defaultEVMMock.mockEVMCallerData.addBalanceCalls != 0 {
   398  			t.Errorf("AddBalance called unexpectedly")
   399  		}
   400  	} else {
   401  		t.Errorf("unexpected error returned; was %s", err.Error())
   402  	}
   403  }
   404  
   405  func TestKeeperTriggerFiredAndMinted(t *testing.T) {
   406  	mintRequestReturn, _ := new(big.Int).SetString("50000000000000000000000000", 10)
   407  	mockEVMCallerData := &MockEVMCallerData{
   408  		blockNumber:       *big.NewInt(0),
   409  		gasLimit:          0,
   410  		mintRequestReturn: *mintRequestReturn,
   411  	}
   412  	defaultEVMMock := &DefaultEVMMock{
   413  		mockEVMCallerData: *mockEVMCallerData,
   414  	}
   415  
   416  	log := log.New()
   417  	triggerKeeperAndMint(defaultEVMMock, log)
   418  
   419  	// EVM Call function calling the keeper should have been cqlled
   420  	if defaultEVMMock.mockEVMCallerData.callCalls != 1 {
   421  		t.Errorf("EVM Call count not as expected. got %d want 1", defaultEVMMock.mockEVMCallerData.callCalls)
   422  	}
   423  	// AddBalance should have been called on the state database, minting the request asked for
   424  	if defaultEVMMock.mockEVMCallerData.addBalanceCalls != 1 {
   425  		t.Errorf("Add balance call count not as expected. got %d want 1", defaultEVMMock.mockEVMCallerData.addBalanceCalls)
   426  	}
   427  }
   428  
   429  func TestKeeperTriggerShouldNotMintMoreThanLimit(t *testing.T) {
   430  	mintRequestReturn, _ := new(big.Int).SetString("50000000000000000000000001", 10)
   431  	mockEVMCallerData := &MockEVMCallerData{
   432  		blockNumber:       *big.NewInt(0),
   433  		gasLimit:          0,
   434  		mintRequestReturn: *mintRequestReturn,
   435  	}
   436  	defaultEVMMock := &DefaultEVMMock{
   437  		mockEVMCallerData: *mockEVMCallerData,
   438  	}
   439  
   440  	log := log.New()
   441  	triggerKeeperAndMint(defaultEVMMock, log)
   442  
   443  	// EVM Call function calling the keeper should have been called
   444  	if defaultEVMMock.mockEVMCallerData.callCalls != 1 {
   445  		t.Errorf("EVM Call count not as expected. got %d want 1", defaultEVMMock.mockEVMCallerData.callCalls)
   446  	}
   447  	// AddBalance should not have been called on the state database, as the mint request was over the limit
   448  	if defaultEVMMock.mockEVMCallerData.addBalanceCalls != 0 {
   449  		t.Errorf("Add balance call count not as expected. got %d want 1", defaultEVMMock.mockEVMCallerData.addBalanceCalls)
   450  	}
   451  }