mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 13:46:43 +00:00
accounts/contract: implemented callable contracts
This commit is contained in:
parent
e165c2d23c
commit
c97b4e89fe
1 changed files with 87 additions and 0 deletions
87
accounts/contract/contract.go
Normal file
87
accounts/contract/contract.go
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
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 }
|
||||
Loading…
Reference in a new issue