github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evm/types/contract_verifier.go (about)

     1  package types
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/ethereum/go-ethereum/common"
     6  	"github.com/ethereum/go-ethereum/common/hexutil"
     7  	"github.com/ethereum/go-ethereum/core/vm"
     8  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     9  	"math/big"
    10  )
    11  
    12  // ContractVerifier which verify contract method whether blocked
    13  type ContractVerifier struct {
    14  	params Params
    15  	hook   *GuFactorHook
    16  }
    17  
    18  // NewContractVerifier return a point of ContractVerifier
    19  func NewContractVerifier(params Params) *ContractVerifier {
    20  	return &ContractVerifier{params: params, hook: &GuFactorHook{}}
    21  }
    22  
    23  // Verify check the contract whether is blocked.
    24  // It never return error,because in this chain if it blocked, not allow to execute next opCode.In Ethereum call failed,the call err is deal in contract code ether evm.
    25  // If current call/delegatecall/callcode contract method is blocked,it will be panic,then it's deal logic at defer{recover}.
    26  // If contract all method blocked,it will not be panic in Verify. it will be panic in stateDb.GetCode().
    27  func (cv ContractVerifier) Verify(stateDB vm.StateDB, op vm.OpCode, from, to common.Address, input []byte, value *big.Int) error {
    28  	csdb, ok := stateDB.(*CommitStateDB)
    29  	//If stateDB is not native stateDB ,then return error
    30  	if !ok {
    31  		panic(ErrContractBlockedVerify{"unknown stateDB expected CommitStateDB"})
    32  	}
    33  
    34  	cv.hook.UpdateGuFactor(csdb, op, from, to, input, value)
    35  
    36  	//check whether contract has been blocked
    37  	if !cv.params.EnableContractBlockedList {
    38  		return nil
    39  	}
    40  	if op == vm.SELFDESTRUCT {
    41  		//contract not allowed selfdestruct,check from is blocked
    42  		bc := csdb.GetContractMethodBlockedByAddress(from.Bytes())
    43  		if bc != nil && !bc.IsAllMethodBlocked() {
    44  			err := ErrContractBlockedVerify{fmt.Sprintf("Contract %s has been blocked. It's not allow to SELFDESTRUCT", from.String())}
    45  			panic(err)
    46  		}
    47  	} else if op == vm.CALL || op == vm.DELEGATECALL || op == vm.CALLCODE {
    48  		//contract not allowed to call delegateCall and callcode ,check from and input is blocked 。STATICCALL could not check because ,it's readonly.
    49  		if len(input) > 4 {
    50  			input = input[:4]
    51  		}
    52  		method := hexutil.Encode(input)
    53  		if csdb.IsContractMethodBlocked(sdk.AccAddress(to.Bytes()), method) {
    54  			err := ErrContractBlockedVerify{fmt.Sprintf("The method %s of contract %s has been blocked. It's not allow to %s", method, to.String(), op.String())}
    55  			panic(err)
    56  		}
    57  	}
    58  	return nil
    59  }