mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 13:46:43 +00:00
87 lines
2.5 KiB
Go
87 lines
2.5 KiB
Go
package contract
|
|
|
|
import (
|
|
"math/big"
|
|
"strings"
|
|
|
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/core"
|
|
"github.com/ethereum/go-ethereum/core/state"
|
|
)
|
|
|
|
type Contract struct {
|
|
backend core.Backend
|
|
abi.ABI
|
|
Address common.Address
|
|
}
|
|
|
|
func getAccount(backend core.Backend) *state.StateObject {
|
|
statedb, _ := state.New(backend.BlockChain().CurrentHeader().Root, backend.ChainDb())
|
|
accounts, err := backend.AccountManager().Accounts()
|
|
if err != nil || len(accounts) == 0 {
|
|
return statedb.GetOrNewStateObject(common.Address{})
|
|
} else {
|
|
return statedb.GetOrNewStateObject(accounts[0].Address)
|
|
}
|
|
}
|
|
|
|
func New(definition string, addr common.Address, backend core.Backend) (*Contract, error) {
|
|
abi, err := abi.JSON(strings.NewReader(definition))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &Contract{
|
|
backend: backend,
|
|
ABI: abi,
|
|
Address: addr,
|
|
}, nil
|
|
}
|
|
|
|
func (c *Contract) Call(method string, args ...interface{}) ([]byte, *big.Int, error) {
|
|
msg := CallMessage{
|
|
gas: new(big.Int).Set(common.MaxBig),
|
|
gasPrice: new(big.Int),
|
|
value: new(big.Int),
|
|
from: getAccount(c.backend),
|
|
}
|
|
return c.CallWithMessage(msg, method, args...)
|
|
}
|
|
|
|
func (c *Contract) CallWithMessage(msg CallMessage, method string, args ...interface{}) ([]byte, *big.Int, error) {
|
|
input, err := c.ABI.Pack(method, args...)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
msg.data = input
|
|
msg.to = &c.Address
|
|
|
|
header := c.backend.BlockChain().CurrentHeader()
|
|
statedb, err := state.New(header.Root, c.backend.ChainDb())
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
vmenv := core.NewEnv(statedb, c.backend.BlockChain(), msg, header)
|
|
gp := new(core.GasPool).AddGas(common.MaxBig)
|
|
|
|
return core.ApplyMessage(vmenv, msg, gp)
|
|
}
|
|
|
|
// CallMessage is the message type used for call transations.
|
|
type CallMessage struct {
|
|
from *state.StateObject
|
|
to *common.Address
|
|
gas, gasPrice *big.Int
|
|
value *big.Int
|
|
data []byte
|
|
}
|
|
|
|
// accessor boilerplate to implement core.Message
|
|
func (m CallMessage) From() (common.Address, error) { return m.from.Address(), nil }
|
|
func (m CallMessage) Nonce() uint64 { return m.from.Nonce() }
|
|
func (m CallMessage) To() *common.Address { return m.to }
|
|
func (m CallMessage) GasPrice() *big.Int { return m.gasPrice }
|
|
func (m CallMessage) Gas() *big.Int { return m.gas }
|
|
func (m CallMessage) Value() *big.Int { return m.value }
|
|
func (m CallMessage) Data() []byte { return m.data }
|