call.go 3.03 KB
Newer Older
1 2 3 4 5 6
package batching

import (
	"fmt"
	"math/big"

7
	"github.com/ethereum-optimism/optimism/op-service/txmgr"
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
	"github.com/ethereum/go-ethereum"
	"github.com/ethereum/go-ethereum/accounts/abi"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/common/hexutil"
)

type ContractCall struct {
	Abi    *abi.ABI
	Addr   common.Address
	Method string
	Args   []interface{}
}

func NewContractCall(abi *abi.ABI, addr common.Address, method string, args ...interface{}) *ContractCall {
	return &ContractCall{
		Abi:    abi,
		Addr:   addr,
		Method: method,
		Args:   args,
	}
}

30 31 32 33
func (c *ContractCall) Pack() ([]byte, error) {
	return c.Abi.Pack(c.Method, c.Args...)
}

34
func (c *ContractCall) ToCallArgs() (interface{}, error) {
35
	data, err := c.Pack()
36 37 38 39 40 41 42 43 44 45
	if err != nil {
		return nil, fmt.Errorf("failed to pack arguments: %w", err)
	}
	msg := ethereum.CallMsg{
		To:   &c.Addr,
		Data: data,
	}
	return toCallArg(msg), nil
}

46
func (c *ContractCall) Unpack(hex hexutil.Bytes) (*CallResult, error) {
47 48 49 50
	out, err := c.Abi.Unpack(c.Method, hex)
	if err != nil {
		return nil, fmt.Errorf("failed to unpack data: %w", err)
	}
51
	return &CallResult{out: out}, nil
52 53
}

54 55 56 57 58 59
func toCallArg(msg ethereum.CallMsg) interface{} {
	arg := map[string]interface{}{
		"from": msg.From,
		"to":   msg.To,
	}
	if len(msg.Data) > 0 {
60
		arg["input"] = hexutil.Bytes(msg.Data)
61 62 63 64 65 66 67 68 69 70 71 72 73
	}
	if msg.Value != nil {
		arg["value"] = (*hexutil.Big)(msg.Value)
	}
	if msg.Gas != 0 {
		arg["gas"] = hexutil.Uint64(msg.Gas)
	}
	if msg.GasPrice != nil {
		arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice)
	}
	return arg
}

74 75 76 77 78 79 80 81 82 83 84
func (c *ContractCall) ToTxCandidate() (txmgr.TxCandidate, error) {
	data, err := c.Pack()
	if err != nil {
		return txmgr.TxCandidate{}, fmt.Errorf("failed to pack arguments: %w", err)
	}
	return txmgr.TxCandidate{
		TxData: data,
		To:     &c.Addr,
	}, nil
}

85 86 87 88 89 90 91 92 93 94 95 96
type CallResult struct {
	out []interface{}
}

func (c *CallResult) GetUint8(i int) uint8 {
	return *abi.ConvertType(c.out[i], new(uint8)).(*uint8)
}

func (c *CallResult) GetUint32(i int) uint32 {
	return *abi.ConvertType(c.out[i], new(uint32)).(*uint32)
}

Adrian Sutton's avatar
Adrian Sutton committed
97 98 99 100
func (c *CallResult) GetUint64(i int) uint64 {
	return *abi.ConvertType(c.out[i], new(uint64)).(*uint64)
}

101 102 103 104 105 106 107 108
func (c *CallResult) GetBool(i int) bool {
	return *abi.ConvertType(c.out[i], new(bool)).(*bool)
}

func (c *CallResult) GetHash(i int) common.Hash {
	return *abi.ConvertType(c.out[i], new([32]byte)).(*[32]byte)
}

109 110 111 112
func (c *CallResult) GetAddress(i int) common.Address {
	return *abi.ConvertType(c.out[i], new([20]byte)).(*[20]byte)
}

113 114 115
func (c *CallResult) GetBigInt(i int) *big.Int {
	return *abi.ConvertType(c.out[i], new(*big.Int)).(**big.Int)
}
116 117 118 119

func (c *CallResult) GetStruct(i int, target interface{}) {
	abi.ConvertType(c.out[i], target)
}
120

121 122 123 124
func (c *CallResult) GetBytes(i int) []byte {
	return *abi.ConvertType(c.out[i], new([]byte)).(*[]byte)
}

125 126 127
func (c *CallResult) GetBytes32(i int) [32]byte {
	return *abi.ConvertType(c.out[i], new([32]byte)).(*[32]byte)
}
128 129 130 131

func (c *CallResult) GetBytes32Slice(i int) [][32]byte {
	return *abi.ConvertType(c.out[i], new([][32]byte)).(*[][32]byte)
}