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