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 }