github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/contract_comm/gasprice_minimum/gasprice_minimum.go (about)

     1  // Copyright 2017 The Celo Authors
     2  // This file is part of the celo library.
     3  //
     4  // The celo library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The celo library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the celo library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package gasprice_minimum
    18  
    19  import (
    20  	"math/big"
    21  	"strings"
    22  
    23  	"github.com/ethereum/go-ethereum/accounts/abi"
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/contract_comm"
    26  	"github.com/ethereum/go-ethereum/contract_comm/errors"
    27  	"github.com/ethereum/go-ethereum/core/types"
    28  	"github.com/ethereum/go-ethereum/core/vm"
    29  	"github.com/ethereum/go-ethereum/log"
    30  	"github.com/ethereum/go-ethereum/params"
    31  )
    32  
    33  // TODO (jarmg 5/22/19): Store ABIs in a central location
    34  const (
    35  	gasPriceMinimumABIString = `[
    36      {
    37        "constant": true,
    38        "inputs": [
    39          {
    40            "name": "_tokenAddress",
    41            "type": "address"
    42          }
    43        ],
    44        "name": "getGasPriceMinimum",
    45        "outputs": [
    46          {
    47            "name": "",
    48            "type": "uint256"
    49          }
    50        ],
    51        "payable": false,
    52        "stateMutability": "view",
    53        "type": "function"
    54      },
    55      {
    56        "constant": false,
    57        "inputs": [
    58          {
    59            "name": "_blockGasTotal",
    60            "type": "uint256"
    61          },
    62          {
    63            "name": "_blockGasLimit",
    64            "type": "uint256"
    65          }
    66        ],
    67        "name": "updateGasPriceMinimum",
    68        "outputs": [
    69          {
    70            "name": "",
    71            "type": "uint256"
    72          }
    73        ],
    74        "payable": false,
    75        "stateMutability": "nonpayable",
    76        "type": "function"
    77        } 
    78      
    79    ]`
    80  )
    81  
    82  var (
    83  	gasPriceMinimumABI, _            = abi.JSON(strings.NewReader(gasPriceMinimumABIString))
    84  	FallbackGasPriceMinimum *big.Int = big.NewInt(0) // gas price minimum to return if unable to fetch from contract
    85  	suggestionMultiplier    *big.Int = big.NewInt(5) // The multiplier that we apply to the minimum when suggesting gas price
    86  )
    87  
    88  func GetGasPriceSuggestion(currency *common.Address, header *types.Header, state vm.StateDB) (*big.Int, error) {
    89  	gasPriceMinimum, err := GetGasPriceMinimum(currency, header, state)
    90  	return new(big.Int).Mul(gasPriceMinimum, suggestionMultiplier), err
    91  }
    92  
    93  func GetGasPriceMinimum(currency *common.Address, header *types.Header, state vm.StateDB) (*big.Int, error) {
    94  	var currencyAddress *common.Address
    95  	var err error
    96  
    97  	if currency == nil {
    98  		currencyAddress, err = contract_comm.GetRegisteredAddress(params.GoldTokenRegistryId, header, state)
    99  
   100  		if err == errors.ErrSmartContractNotDeployed || err == errors.ErrRegistryContractNotDeployed {
   101  			return FallbackGasPriceMinimum, nil
   102  		}
   103  		if err == errors.ErrNoInternalEvmHandlerSingleton {
   104  			log.Error(err.Error())
   105  			return FallbackGasPriceMinimum, nil
   106  		}
   107  		if err != nil {
   108  			log.Error(err.Error())
   109  			return FallbackGasPriceMinimum, err
   110  		}
   111  	} else {
   112  		currencyAddress = currency
   113  	}
   114  
   115  	var gasPriceMinimum *big.Int
   116  	_, err = contract_comm.MakeStaticCall(
   117  		params.GasPriceMinimumRegistryId,
   118  		gasPriceMinimumABI,
   119  		"getGasPriceMinimum",
   120  		[]interface{}{currencyAddress},
   121  		&gasPriceMinimum,
   122  		params.MaxGasForGetGasPriceMinimum,
   123  		header,
   124  		state,
   125  	)
   126  
   127  	if err != nil {
   128  		return FallbackGasPriceMinimum, err
   129  	}
   130  
   131  	return gasPriceMinimum, err
   132  }
   133  
   134  func UpdateGasPriceMinimum(header *types.Header, state vm.StateDB) (*big.Int, error) {
   135  	var updatedGasPriceMinimum *big.Int
   136  
   137  	_, err := contract_comm.MakeCall(
   138  		params.GasPriceMinimumRegistryId,
   139  		gasPriceMinimumABI,
   140  		"updateGasPriceMinimum",
   141  		[]interface{}{big.NewInt(int64(header.GasUsed)),
   142  			big.NewInt(int64(header.GasLimit))},
   143  		&updatedGasPriceMinimum,
   144  		params.MaxGasForUpdateGasPriceMinimum,
   145  		big.NewInt(0),
   146  		header,
   147  		state,
   148  		false,
   149  	)
   150  	if err != nil {
   151  		return nil, err
   152  	}
   153  	return updatedGasPriceMinimum, err
   154  }