Skip to content

Commit 205d009

Browse files
committed
use new precompile base
1 parent e1eca59 commit 205d009

File tree

1 file changed

+50
-47
lines changed

1 file changed

+50
-47
lines changed

precompiles/bank2/bank.go

Lines changed: 50 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package bank2
33
import (
44
"encoding/binary"
55
"encoding/hex"
6+
"errors"
7+
"fmt"
68
"math"
79
"math/big"
810

@@ -12,10 +14,11 @@ import (
1214

1315
_ "embed"
1416

15-
"github.com/cosmos/evm/x/vm/statedb"
17+
cmn "github.com/cosmos/evm/precompiles/common"
1618
evmtypes "github.com/cosmos/evm/x/vm/types"
1719

1820
sdkmath "cosmossdk.io/math"
21+
storetypes "cosmossdk.io/store/types"
1922

2023
sdk "github.com/cosmos/cosmos-sdk/types"
2124
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
@@ -33,6 +36,14 @@ var (
3336
Create2FactoryAddress = common.HexToAddress("0x4e59b44847b379578588920ca78fbf26c0b4956c")
3437
)
3538

39+
var (
40+
ErrInputTooShort = errors.New("input too short")
41+
ErrDenomNotFound = errors.New("denom not found")
42+
ErrUnauthorized = errors.New("unauthorized")
43+
44+
ErrUnknownMethod = "unknown method: %d"
45+
)
46+
3647
func init() {
3748
var err error
3849
ERC20Bin, err = hex.DecodeString(ERC20BinHex)
@@ -52,24 +63,38 @@ const (
5263
MethodTransferFrom
5364
)
5465

55-
var _ vm.PrecompiledContract = &Precompile{}
66+
var (
67+
_ vm.PrecompiledContract = &Precompile{}
68+
_ cmn.NativeExecutor = &Precompile{}
69+
)
5670

5771
type Precompile struct {
72+
cmn.Precompile
73+
5874
msgServer BankMsgServer
5975
bankKeeper BankKeeper
6076
}
6177

6278
func NewPrecompile(msgServer BankMsgServer, bankKeeper BankKeeper) *Precompile {
63-
return &Precompile{msgServer, bankKeeper}
79+
return &Precompile{
80+
Precompile: cmn.Precompile{
81+
KvGasConfig: storetypes.GasConfig{},
82+
TransientKVGasConfig: storetypes.GasConfig{},
83+
ContractAddress: common.HexToAddress(evmtypes.Bank2PrecompileAddress),
84+
},
85+
msgServer: msgServer,
86+
bankKeeper: bankKeeper,
87+
}
6488
}
6589

66-
func (p Precompile) Address() common.Address {
67-
return common.HexToAddress(evmtypes.Bank2PrecompileAddress)
90+
func (p Precompile) RequiredGas(input []byte) uint64 {
91+
return p.Precompile.RequiredGas(input, p.IsTransaction(BankMethod(input[0])))
6892
}
6993

70-
func (p Precompile) RequiredGas(input []byte) uint64 {
71-
// FIXME
72-
return 21000
94+
// IsTransaction checks if the given method name corresponds to a transaction or query.
95+
// It returns false since all bank methods are queries.
96+
func (Precompile) IsTransaction(method BankMethod) bool {
97+
return BankMethod(method) == MethodTransferFrom
7398
}
7499

75100
// Name
@@ -78,7 +103,7 @@ func (p Precompile) RequiredGas(input []byte) uint64 {
78103
func (p Precompile) Name(ctx sdk.Context, input []byte) ([]byte, error) {
79104
metadata, found := p.bankKeeper.GetDenomMetaData(ctx, string(input))
80105
if !found {
81-
return nil, vm.ErrExecutionReverted
106+
return nil, ErrDenomNotFound
82107
}
83108

84109
return []byte(metadata.Name), nil
@@ -91,7 +116,7 @@ func (p Precompile) Name(ctx sdk.Context, input []byte) ([]byte, error) {
91116
func (p Precompile) Symbol(ctx sdk.Context, input []byte) ([]byte, error) {
92117
metadata, found := p.bankKeeper.GetDenomMetaData(ctx, string(input))
93118
if !found {
94-
return nil, vm.ErrExecutionReverted
119+
return nil, ErrDenomNotFound
95120
}
96121

97122
return []byte(metadata.Symbol), nil
@@ -104,11 +129,11 @@ func (p Precompile) Symbol(ctx sdk.Context, input []byte) ([]byte, error) {
104129
func (p Precompile) Decimals(ctx sdk.Context, input []byte) ([]byte, error) {
105130
m, found := p.bankKeeper.GetDenomMetaData(ctx, string(input))
106131
if !found {
107-
return nil, vm.ErrExecutionReverted
132+
return nil, ErrDenomNotFound
108133
}
109134

110135
if len(m.DenomUnits) == 0 {
111-
return []byte{0}, nil
136+
return []byte{0}, errors.New("denom metadata has no denom units")
112137
}
113138

114139
// look up Display denom unit
@@ -128,7 +153,7 @@ func (p Precompile) Decimals(ctx sdk.Context, input []byte) ([]byte, error) {
128153
}
129154

130155
if exponent > math.MaxUint8 {
131-
return nil, vm.ErrExecutionReverted
156+
return nil, errors.New("exponent too large")
132157
}
133158

134159
return []byte{uint8(exponent)}, nil
@@ -146,7 +171,7 @@ func (p Precompile) TotalSupply(ctx sdk.Context, input []byte) ([]byte, error) {
146171
// input format: abi.encodePacked(address account, string denom)
147172
func (p Precompile) BalanceOf(ctx sdk.Context, input []byte) ([]byte, error) {
148173
if len(input) < 20 {
149-
return nil, vm.ErrExecutionReverted
174+
return nil, ErrInputTooShort
150175
}
151176
account := common.BytesToAddress(input[:20])
152177
denom := string(input[20:])
@@ -158,7 +183,7 @@ func (p Precompile) BalanceOf(ctx sdk.Context, input []byte) ([]byte, error) {
158183
// input format: abi.encodePacked(address from, address to, uint256 amount, string denom)
159184
func (p Precompile) TransferFrom(ctx sdk.Context, caller common.Address, input []byte) ([]byte, error) {
160185
if len(input) < 20*2+32 {
161-
return nil, vm.ErrExecutionReverted
186+
return nil, ErrInputTooShort
162187
}
163188

164189
from := common.BytesToAddress(input[:20])
@@ -168,63 +193,41 @@ func (p Precompile) TransferFrom(ctx sdk.Context, caller common.Address, input [
168193

169194
// don't handle gas token here
170195
if denom == evmtypes.GetEVMCoinDenom() {
171-
return nil, vm.ErrExecutionReverted
196+
return nil, errors.New("cannot transfer gas token with bank precompile")
172197
}
173198

174199
// authorization: only from address or deterministic erc20 contract address can call this method
175200
if caller != from && caller != ERC20ContractAddress(p.Address(), denom) {
176-
return nil, vm.ErrExecutionReverted
201+
return nil, ErrUnauthorized
177202
}
178203

179204
coins := sdk.Coins{{Denom: denom, Amount: sdkmath.NewIntFromBigInt(amount)}}
180205
if err := coins.Validate(); err != nil {
181-
return nil, vm.ErrExecutionReverted
206+
return nil, fmt.Errorf("invalid coins: %w", err)
182207
}
183208

184209
// execute the transfer with bank keeper
185210
msg := banktypes.NewMsgSend(from.Bytes(), to.Bytes(), coins)
186211
if _, err := p.msgServer.Send(ctx, msg); err != nil {
187-
return nil, vm.ErrExecutionReverted
212+
return nil, fmt.Errorf("failed to send coins: %w", err)
188213
}
189214

190215
return []byte{1}, nil
191216
}
192217

193-
func (p Precompile) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) {
194-
stateDB, ok := evm.StateDB.(*statedb.StateDB)
195-
if !ok {
196-
return nil, vm.ErrExecutionReverted
197-
}
198-
199-
ctx, err := stateDB.GetCacheContext()
200-
if err != nil {
201-
return nil, vm.ErrExecutionReverted
202-
}
203-
204-
// take a snapshot of the current state before any changes
205-
// to be able to revert the changes
206-
snapshot := stateDB.MultiStoreSnapshot()
207-
events := ctx.EventManager().Events()
208-
209-
// add precompileCall entry on the stateDB journal
210-
// this allows to revert the changes within an evm tx
211-
err = stateDB.AddPrecompileFn(p.Address(), snapshot, events)
212-
if err != nil {
213-
return nil, vm.ErrExecutionReverted
214-
}
215-
218+
func (p Precompile) Execute(ctx sdk.Context, evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) {
216219
// 1 byte method selector
217220
if len(contract.Input) == 0 {
218-
return nil, vm.ErrExecutionReverted
221+
return nil, ErrInputTooShort
219222
}
220223

221-
action := BankMethod(contract.Input[0])
222-
if readonly && action == MethodTransferFrom {
224+
method := BankMethod(contract.Input[0])
225+
if readonly && p.IsTransaction(method) {
223226
return nil, vm.ErrWriteProtection
224227
}
225228

226229
input := contract.Input[1:]
227-
switch action {
230+
switch method {
228231
case MethodName:
229232
return p.Name(ctx, input)
230233
case MethodSymbol:
@@ -239,7 +242,7 @@ func (p Precompile) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]by
239242
return p.TransferFrom(ctx, contract.Caller(), input)
240243
}
241244

242-
return nil, vm.ErrExecutionReverted
245+
return nil, fmt.Errorf(ErrUnknownMethod, method)
243246
}
244247

245248
// ERC20ContractAddress computes the contract address deployed with create2 factory contract.

0 commit comments

Comments
 (0)