Files
evm/precompile/contracts/rewardmanager/contract.go
zeekayandHanzo Dev b50fd4ba8f Take the geth address conversion locally now that BlackholeAddr is an array
constants.BlackholeAddr is a plain [20]byte, so constants no longer imports
geth. The fourteen sites here all want a geth common.Address, and each file
already imports geth/common, so each takes the free conversion itself.

Only one site was a compile error: the .Bytes() method call in
rewardmanager.DisableFeeRewards. Everywhere else [20]byte is assignable to
common.Address, so the change was invisible to the compiler, and the two
require.Equal assertions in rewardmanager would have compiled and then failed
at run time, because reflect.DeepEqual compares types before bytes. Those two
are wrapped for that reason, not for style.

The two failures in core, TestHeadPin_Across4096Boundary_NoLeak and the
invalid-chainID-0 panic in TestCreateThenDeletePostByzantium, reproduce
identically with these lines reverted and are unrelated.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-06 00:28:23 -07:00

340 lines
14 KiB
Go

// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
// Code generated
// This file is a generated precompile contract with stubbed abstract functions.
package rewardmanager
import (
_ "embed"
"errors"
"fmt"
"github.com/luxfi/constants"
"github.com/luxfi/evm/accounts/abi"
"github.com/luxfi/evm/precompile/allowlist"
"github.com/luxfi/evm/precompile/contract"
"github.com/luxfi/geth/core/types"
"github.com/luxfi/geth/common"
"github.com/luxfi/geth/core/vm"
)
const (
AllowFeeRecipientsGasCost uint64 = contract.WriteGasCostPerSlot + allowlist.ReadAllowListGasCost // write 1 slot + read allow list
AreFeeRecipientsAllowedGasCost uint64 = allowlist.ReadAllowListGasCost
CurrentRewardAddressGasCost uint64 = allowlist.ReadAllowListGasCost
DisableRewardsGasCost uint64 = contract.WriteGasCostPerSlot + allowlist.ReadAllowListGasCost // write 1 slot + read allow list
SetRewardAddressGasCost uint64 = contract.WriteGasCostPerSlot + allowlist.ReadAllowListGasCost // write 1 slot + read allow list
)
// Singleton StatefulPrecompiledContract and signatures.
var (
ErrCannotAllowFeeRecipients = errors.New("non-enabled cannot call allowFeeRecipients")
ErrCannotAreFeeRecipientsAllowed = errors.New("non-enabled cannot call areFeeRecipientsAllowed")
ErrCannotCurrentRewardAddress = errors.New("non-enabled cannot call currentRewardAddress")
ErrCannotDisableRewards = errors.New("non-enabled cannot call disableRewards")
ErrCannotSetRewardAddress = errors.New("non-enabled cannot call setRewardAddress")
ErrCannotEnableBothRewards = errors.New("cannot enable both fee recipients and reward address at the same time")
ErrEmptyRewardAddress = errors.New("reward address cannot be empty")
// RewardManagerRawABI contains the raw ABI of RewardManager contract.
//go:embed contract.abi
RewardManagerRawABI string
RewardManagerABI = contract.ParseABI(RewardManagerRawABI)
RewardManagerPrecompile = createRewardManagerPrecompile() // will be initialized by init function
rewardAddressStorageKey = common.Hash{'r', 'a', 's', 'k'}
allowFeeRecipientsAddressValue = common.Hash{'a', 'f', 'r', 'a', 'v'}
)
// GetRewardManagerAllowListStatus returns the role of [address] for the RewardManager list.
func GetRewardManagerAllowListStatus(stateDB contract.StateDB, address common.Address) allowlist.Role {
return allowlist.GetAllowListStatus(stateDB, ContractAddress, address)
}
// SetRewardManagerAllowListStatus sets the permissions of [address] to [role] for the
// RewardManager list. Assumes [role] has already been verified as valid.
func SetRewardManagerAllowListStatus(stateDB contract.StateDB, address common.Address, role allowlist.Role) {
allowlist.SetAllowListRole(stateDB, ContractAddress, address, role)
}
// PackAllowFeeRecipients packs the function selector (first 4 func signature bytes).
// This function is mostly used for tests.
func PackAllowFeeRecipients() ([]byte, error) {
return RewardManagerABI.Pack("allowFeeRecipients")
}
// EnableAllowFeeRecipients enables fee recipients.
func EnableAllowFeeRecipients(stateDB contract.StateDB) {
stateDB.SetState(ContractAddress, rewardAddressStorageKey, allowFeeRecipientsAddressValue)
}
// DisableFeeRewards disables rewards and burns them by sending to Blackhole Address.
func DisableFeeRewards(stateDB contract.StateDB) {
stateDB.SetState(ContractAddress, rewardAddressStorageKey, common.BytesToHash(common.Address(constants.BlackholeAddr).Bytes()))
}
func allowFeeRecipients(accessibleState contract.AccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
if remainingGas, err = contract.DeductGas(suppliedGas, AllowFeeRecipientsGasCost); err != nil {
return nil, 0, err
}
if readOnly {
return nil, remainingGas, vm.ErrWriteProtection
}
// no input provided for this function
// Allow list is enabled and AllowFeeRecipients is a state-changer function.
// This part of the code restricts the function to be called only by enabled/admin addresses in the allow list.
// You can modify/delete this code if you don't want this function to be restricted by the allow list.
stateDB := accessibleState.GetStateDB()
// Verify that the caller is in the allow list and therefore has the right to call this function.
callerStatus := allowlist.GetAllowListStatus(stateDB, ContractAddress, caller)
if !callerStatus.IsEnabled() {
return nil, remainingGas, fmt.Errorf("%w: %s", ErrCannotAllowFeeRecipients, caller)
}
// allow list code ends here.
if contract.IsDurangoActivated(accessibleState) {
if remainingGas, err = contract.DeductGas(remainingGas, FeeRecipientsAllowedEventGasCost); err != nil {
return nil, 0, err
}
topics, data, err := PackFeeRecipientsAllowedEvent(caller)
if err != nil {
return nil, remainingGas, err
}
stateDB.AddLog(&types.Log{
Address: ContractAddress,
Topics: topics,
Data: data,
BlockNumber: accessibleState.GetBlockContext().Number().Uint64(),
})
}
EnableAllowFeeRecipients(stateDB)
// Return the packed output and the remaining gas
return []byte{}, remainingGas, nil
}
// PackAreFeeRecipientsAllowed packs the include selector (first 4 func signature bytes).
// This function is mostly used for tests.
func PackAreFeeRecipientsAllowed() ([]byte, error) {
return RewardManagerABI.Pack("areFeeRecipientsAllowed")
}
// PackAreFeeRecipientsAllowedOutput attempts to pack given isAllowed of type bool
// to conform the ABI outputs.
func PackAreFeeRecipientsAllowedOutput(isAllowed bool) ([]byte, error) {
return RewardManagerABI.PackOutput("areFeeRecipientsAllowed", isAllowed)
}
func areFeeRecipientsAllowed(accessibleState contract.AccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
if remainingGas, err = contract.DeductGas(suppliedGas, AreFeeRecipientsAllowedGasCost); err != nil {
return nil, 0, err
}
// no input provided for this function
stateDB := accessibleState.GetStateDB()
var output bool
_, output = GetStoredRewardAddress(stateDB)
packedOutput, err := PackAreFeeRecipientsAllowedOutput(output)
if err != nil {
return nil, remainingGas, err
}
// Return the packed output and the remaining gas
return packedOutput, remainingGas, nil
}
// PackCurrentRewardAddress packs the include selector (first 4 func signature bytes).
// This function is mostly used for tests.
func PackCurrentRewardAddress() ([]byte, error) {
return RewardManagerABI.Pack("currentRewardAddress")
}
// PackCurrentRewardAddressOutput attempts to pack given rewardAddress of type common.Address
// to conform the ABI outputs.
func PackCurrentRewardAddressOutput(rewardAddress common.Address) ([]byte, error) {
return RewardManagerABI.PackOutput("currentRewardAddress", rewardAddress)
}
// GetStoredRewardAddress returns the current value of the address stored under rewardAddressStorageKey.
// Returns an empty address and true if allow fee recipients is enabled, otherwise returns current reward address and false.
func GetStoredRewardAddress(stateDB contract.StateReader) (common.Address, bool) {
val := stateDB.GetState(ContractAddress, rewardAddressStorageKey)
return common.BytesToAddress(val.Bytes()), val == allowFeeRecipientsAddressValue
}
// StoreRewardAddress stores the given [val] under rewardAddressStorageKey.
func StoreRewardAddress(stateDB contract.StateDB, val common.Address) {
stateDB.SetState(ContractAddress, rewardAddressStorageKey, common.BytesToHash(val.Bytes()))
}
// PackSetRewardAddress packs [addr] of type common.Address into the appropriate arguments for setRewardAddress.
// the packed bytes include selector (first 4 func signature bytes).
// This function is mostly used for tests.
func PackSetRewardAddress(addr common.Address) ([]byte, error) {
return RewardManagerABI.Pack("setRewardAddress", addr)
}
// UnpackSetRewardAddressInput attempts to unpack [input] into the common.Address type argument
// assumes that [input] does not include selector (omits first 4 func signature bytes)
// if [useStrictMode] is true, it will return an error if the length of [input] is not divisible by 32
func UnpackSetRewardAddressInput(input []byte, useStrictMode bool) (common.Address, error) {
res, err := RewardManagerABI.UnpackInput("setRewardAddress", input, useStrictMode)
if err != nil {
return common.Address{}, err
}
unpacked := *abi.ConvertType(res[0], new(common.Address)).(*common.Address)
return unpacked, nil
}
func setRewardAddress(accessibleState contract.AccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
if remainingGas, err = contract.DeductGas(suppliedGas, SetRewardAddressGasCost); err != nil {
return nil, 0, err
}
if readOnly {
return nil, remainingGas, vm.ErrWriteProtection
}
// attempts to unpack [input] into the arguments to the SetRewardAddressInput.
// Assumes that [input] does not include selector
// do not use strict mode after Durango
useStrictMode := !contract.IsDurangoActivated(accessibleState)
rewardAddress, err := UnpackSetRewardAddressInput(input, useStrictMode)
if err != nil {
return nil, remainingGas, err
}
// Allow list is enabled and SetRewardAddress is a state-changer function.
// This part of the code restricts the function to be called only by enabled/admin addresses in the allow list.
// You can modify/delete this code if you don't want this function to be restricted by the allow list.
stateDB := accessibleState.GetStateDB()
// Verify that the caller is in the allow list and therefore has the right to call this function.
callerStatus := allowlist.GetAllowListStatus(stateDB, ContractAddress, caller)
if !callerStatus.IsEnabled() {
return nil, remainingGas, fmt.Errorf("%w: %s", ErrCannotSetRewardAddress, caller)
}
// allow list code ends here.
// if input is empty, return an error
if rewardAddress == (common.Address{}) {
return nil, remainingGas, ErrEmptyRewardAddress
}
// Add a log to be handled if this action is finalized.
if contract.IsDurangoActivated(accessibleState) {
if remainingGas, err = contract.DeductGas(remainingGas, RewardAddressChangedEventGasCost); err != nil {
return nil, 0, err
}
oldRewardAddress, _ := GetStoredRewardAddress(stateDB)
topics, data, err := PackRewardAddressChangedEvent(caller, oldRewardAddress, rewardAddress)
if err != nil {
return nil, remainingGas, err
}
stateDB.AddLog(&types.Log{
Address: ContractAddress,
Topics: topics,
Data: data,
BlockNumber: accessibleState.GetBlockContext().Number().Uint64(),
})
}
StoreRewardAddress(stateDB, rewardAddress)
// Return the packed output and the remaining gas
return []byte{}, remainingGas, nil
}
func currentRewardAddress(accessibleState contract.AccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
if remainingGas, err = contract.DeductGas(suppliedGas, CurrentRewardAddressGasCost); err != nil {
return nil, 0, err
}
// no input provided for this function
stateDB := accessibleState.GetStateDB()
output, _ := GetStoredRewardAddress(stateDB)
packedOutput, err := PackCurrentRewardAddressOutput(output)
if err != nil {
return nil, remainingGas, err
}
// Return the packed output and the remaining gas
return packedOutput, remainingGas, nil
}
// PackDisableRewards packs the include selector (first 4 func signature bytes).
// This function is mostly used for tests.
func PackDisableRewards() ([]byte, error) {
return RewardManagerABI.Pack("disableRewards")
}
func disableRewards(accessibleState contract.AccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
if remainingGas, err = contract.DeductGas(suppliedGas, DisableRewardsGasCost); err != nil {
return nil, 0, err
}
if readOnly {
return nil, remainingGas, vm.ErrWriteProtection
}
// no input provided for this function
// Allow list is enabled and DisableRewards is a state-changer function.
// This part of the code restricts the function to be called only by enabled/admin addresses in the allow list.
// You can modify/delete this code if you don't want this function to be restricted by the allow list.
stateDB := accessibleState.GetStateDB()
// Verify that the caller is in the allow list and therefore has the right to call this function.
callerStatus := allowlist.GetAllowListStatus(stateDB, ContractAddress, caller)
if !callerStatus.IsEnabled() {
return nil, remainingGas, fmt.Errorf("%w: %s", ErrCannotDisableRewards, caller)
}
// allow list code ends here.
if contract.IsDurangoActivated(accessibleState) {
if remainingGas, err = contract.DeductGas(remainingGas, RewardsDisabledEventGasCost); err != nil {
return nil, 0, err
}
topics, data, err := PackRewardsDisabledEvent(caller)
if err != nil {
return nil, remainingGas, err
}
stateDB.AddLog(&types.Log{
Address: ContractAddress,
Topics: topics,
Data: data,
BlockNumber: accessibleState.GetBlockContext().Number().Uint64(),
})
}
DisableFeeRewards(stateDB)
// Return the packed output and the remaining gas
return []byte{}, remainingGas, nil
}
// createRewardManagerPrecompile returns a StatefulPrecompiledContract with getters and setters for the precompile.
// Access to the getters/setters is controlled by an allow list for [precompileAddr].
func createRewardManagerPrecompile() contract.StatefulPrecompiledContract {
var functions []*contract.StatefulPrecompileFunction
functions = append(functions, allowlist.CreateAllowListFunctions(ContractAddress)...)
abiFunctionMap := map[string]contract.RunStatefulPrecompileFunc{
"allowFeeRecipients": allowFeeRecipients,
"areFeeRecipientsAllowed": areFeeRecipientsAllowed,
"currentRewardAddress": currentRewardAddress,
"disableRewards": disableRewards,
"setRewardAddress": setRewardAddress,
}
for name, function := range abiFunctionMap {
method, ok := RewardManagerABI.Methods[name]
if !ok {
panic(fmt.Errorf("given method (%s) does not exist in the ABI", name))
}
functions = append(functions, contract.NewStatefulPrecompileFunction(method.ID, function))
}
// Construct the contract with no fallback function.
statefulContract, err := contract.NewStatefulPrecompileContract(nil, functions)
if err != nil {
panic(err)
}
return statefulContract
}