-
Notifications
You must be signed in to change notification settings - Fork 12
/
call_evm.go
92 lines (82 loc) · 2.59 KB
/
call_evm.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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package crosschain
import (
"errors"
"fmt"
"math/big"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
fxserverconfig "github.com/functionx/fx-core/v4/server/config"
fxtypes "github.com/functionx/fx-core/v4/types"
)
type CallerRef struct {
addr common.Address
}
func (cr CallerRef) Address() common.Address {
return cr.addr
}
type ContractCall struct {
ctx sdk.Context
evm *vm.EVM
caller CallerRef
contract common.Address
maxGas uint64
}
func NewContractCall(ctx sdk.Context, evm *vm.EVM, caller, contract common.Address) *ContractCall {
cc := &ContractCall{
ctx: ctx,
evm: evm,
caller: CallerRef{addr: caller},
contract: contract,
maxGas: fxserverconfig.DefaultGasCap,
}
params := ctx.ConsensusParams()
if params != nil && params.Block != nil && params.Block.MaxGas > 0 {
cc.maxGas = uint64(params.Block.MaxGas)
}
return cc
}
func (cc *ContractCall) ERC20Burn(amount *big.Int) error {
data, err := fxtypes.GetFIP20().ABI.Pack("burn", cc.caller.Address(), amount)
if err != nil {
return fmt.Errorf("pack burn: %s", err.Error())
}
_, _, err = cc.evm.Call(cc.caller, cc.contract, data, cc.maxGas, big.NewInt(0))
if err != nil {
return fmt.Errorf("call burn: %s", err.Error())
}
return nil
}
func (cc *ContractCall) ERC20TransferFrom(from, to common.Address, amount *big.Int) error {
data, err := fxtypes.GetFIP20().ABI.Pack("transferFrom", from, to, amount)
if err != nil {
return fmt.Errorf("pack transferFrom: %s", err.Error())
}
ret, _, err := cc.evm.Call(cc.caller, cc.contract, data, cc.maxGas, big.NewInt(0))
if err != nil {
return fmt.Errorf("call transferFrom: %s", err.Error())
}
var unpackedRet struct{ Value bool }
if err := fxtypes.GetFIP20().ABI.UnpackIntoInterface(&unpackedRet, "transferFrom", ret); err != nil {
return fmt.Errorf("unpack transferFrom: %s", err.Error())
}
if !unpackedRet.Value {
return errors.New("transferFrom failed")
}
return nil
}
func (cc *ContractCall) ERC20TotalSupply() (*big.Int, error) {
data, err := fxtypes.GetFIP20().ABI.Pack("totalSupply")
if err != nil {
return nil, fmt.Errorf("pack totalSupply: %s", err.Error())
}
ret, _, err := cc.evm.StaticCall(cc.caller, cc.contract, data, cc.maxGas)
if err != nil {
return nil, fmt.Errorf("StaticCall totalSupply: %s", err.Error())
}
var unpackedRet struct{ Value *big.Int }
if err := fxtypes.GetFIP20().ABI.UnpackIntoInterface(&unpackedRet, "totalSupply", ret); err != nil {
return nil, fmt.Errorf("unpack totalSupply: %s", err.Error())
}
return unpackedRet.Value, nil
}