gitlab.com/flarenetwork/coreth@v0.1.1/core/keeper.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  	"fmt"
     8  	"math/big"
     9  
    10  	"github.com/ethereum/go-ethereum/common"
    11  	"github.com/ethereum/go-ethereum/log"
    12  
    13  	"gitlab.com/flarenetwork/coreth/core/vm"
    14  )
    15  
    16  // Define errors
    17  type ErrInvalidKeeperData struct{}
    18  
    19  func (e *ErrInvalidKeeperData) Error() string { return "invalid return data from keeper trigger" }
    20  
    21  type ErrKeeperDataEmpty struct{}
    22  
    23  func (e *ErrKeeperDataEmpty) Error() string { return "return data from keeper trigger empty" }
    24  
    25  type ErrMaxMintExceeded struct {
    26  	mintMax     *big.Int
    27  	mintRequest *big.Int
    28  }
    29  
    30  func (e *ErrMaxMintExceeded) Error() string {
    31  	return fmt.Sprintf("mint request of %s exceeded max of %s", e.mintRequest.Text(10), e.mintMax.Text(10))
    32  }
    33  
    34  type ErrMintNegative struct{}
    35  
    36  func (e *ErrMintNegative) Error() string { return "mint request cannot be negative" }
    37  
    38  // Define interface for dependencies
    39  type EVMCaller interface {
    40  	Call(caller vm.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error)
    41  	GetBlockNumber() *big.Int
    42  	GetGasLimit() uint64
    43  	AddBalance(addr common.Address, amount *big.Int)
    44  }
    45  
    46  // Define maximums that can change by block height
    47  func GetKeeperGasMultiplier(blockNumber *big.Int) uint64 {
    48  	switch {
    49  	default:
    50  		return 100
    51  	}
    52  }
    53  
    54  func GetSystemTriggerContractAddr(blockNumber *big.Int) string {
    55  	switch {
    56  	default:
    57  		return "0x1000000000000000000000000000000000000002"
    58  	}
    59  }
    60  
    61  func GetSystemTriggerSelector(blockNumber *big.Int) []byte {
    62  	switch {
    63  	default:
    64  		return []byte{0x7f, 0xec, 0x8d, 0x38}
    65  	}
    66  }
    67  
    68  func GetPrioritisedFTSOContract(blockTime *big.Int) string {
    69  	switch {
    70  	default:
    71  		return "0x1000000000000000000000000000000000000003"
    72  	}
    73  }
    74  
    75  func GetMaximumMintRequest(blockNumber *big.Int) *big.Int {
    76  	switch {
    77  	default:
    78  		maxRequest, _ := new(big.Int).SetString("50000000000000000000000000", 10)
    79  		return maxRequest
    80  	}
    81  }
    82  
    83  func triggerKeeper(evm EVMCaller) (*big.Int, error) {
    84  	bigZero := big.NewInt(0)
    85  	// Get the contract to call
    86  	systemTriggerContract := common.HexToAddress(GetSystemTriggerContractAddr(evm.GetBlockNumber()))
    87  	// Call the method
    88  	triggerRet, _, triggerErr := evm.Call(
    89  		vm.AccountRef(systemTriggerContract),
    90  		systemTriggerContract,
    91  		GetSystemTriggerSelector(evm.GetBlockNumber()),
    92  		GetKeeperGasMultiplier(evm.GetBlockNumber())*evm.GetGasLimit(),
    93  		bigZero)
    94  	// If no error and a value came back...
    95  	if triggerErr == nil && triggerRet != nil {
    96  		// Did we get one big int?
    97  		if len(triggerRet) == 32 {
    98  			// Convert to big int
    99  			// Mint request cannot be less than 0 as SetBytes treats value as unsigned
   100  			mintRequest := new(big.Int).SetBytes(triggerRet)
   101  			// return the mint request
   102  			return mintRequest, nil
   103  		} else {
   104  			// Returned length was not 32 bytes
   105  			return bigZero, &ErrInvalidKeeperData{}
   106  		}
   107  	} else {
   108  		if triggerErr != nil {
   109  			return bigZero, triggerErr
   110  		} else {
   111  			return bigZero, &ErrKeeperDataEmpty{}
   112  		}
   113  	}
   114  }
   115  
   116  func mint(evm EVMCaller, mintRequest *big.Int) error {
   117  	// If the mint request is greater than zero and less than max
   118  	max := GetMaximumMintRequest(evm.GetBlockNumber())
   119  	if mintRequest.Cmp(big.NewInt(0)) > 0 &&
   120  		mintRequest.Cmp(max) <= 0 {
   121  		// Mint the amount asked for on to the keeper contract
   122  		evm.AddBalance(common.HexToAddress(GetSystemTriggerContractAddr(evm.GetBlockNumber())), mintRequest)
   123  	} else if mintRequest.Cmp(max) > 0 {
   124  		// Return error
   125  		return &ErrMaxMintExceeded{
   126  			mintRequest: mintRequest,
   127  			mintMax:     max,
   128  		}
   129  	} else if mintRequest.Cmp(big.NewInt(0)) < 0 {
   130  		// Cannot mint negatives
   131  		return &ErrMintNegative{}
   132  	}
   133  	// No error
   134  	return nil
   135  }
   136  
   137  func triggerKeeperAndMint(evm EVMCaller, log log.Logger) {
   138  	// Call the keeper
   139  	mintRequest, triggerErr := triggerKeeper(evm)
   140  	// If no error...
   141  	if triggerErr == nil {
   142  		// time to mint
   143  		if mintError := mint(evm, mintRequest); mintError != nil {
   144  			log.Warn("Error minting inflation request", "error", mintError)
   145  		}
   146  	} else {
   147  		log.Warn("Keeper trigger in error", "error", triggerErr)
   148  	}
   149  }