aboutsummaryrefslogtreecommitdiffstats
path: root/accounts/abi/bind/base.go
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2016-05-20 17:29:28 +0800
committerPéter Szilágyi <peterke@gmail.com>2016-05-20 17:29:28 +0800
commit1580ec180414bce1e37acc614bc2445f778efb75 (patch)
tree7c8276f3f1558b5ce62edd0bff87745956084a4c /accounts/abi/bind/base.go
parente798e4fd750745cec99c5a531e42998d9a7be85e (diff)
downloaddexon-1580ec180414bce1e37acc614bc2445f778efb75.tar
dexon-1580ec180414bce1e37acc614bc2445f778efb75.tar.gz
dexon-1580ec180414bce1e37acc614bc2445f778efb75.tar.bz2
dexon-1580ec180414bce1e37acc614bc2445f778efb75.tar.lz
dexon-1580ec180414bce1e37acc614bc2445f778efb75.tar.xz
dexon-1580ec180414bce1e37acc614bc2445f778efb75.tar.zst
dexon-1580ec180414bce1e37acc614bc2445f778efb75.zip
accounts/abi/bind, eth: rely on getCode for sanity checks, not estimate and call
Diffstat (limited to 'accounts/abi/bind/base.go')
-rw-r--r--accounts/abi/bind/base.go27
1 files changed, 27 insertions, 0 deletions
diff --git a/accounts/abi/bind/base.go b/accounts/abi/bind/base.go
index 06621c5ad..75e8d5bc8 100644
--- a/accounts/abi/bind/base.go
+++ b/accounts/abi/bind/base.go
@@ -20,6 +20,7 @@ import (
"errors"
"fmt"
"math/big"
+ "sync/atomic"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
@@ -56,6 +57,9 @@ type BoundContract struct {
abi abi.ABI // Reflect based ABI to access the correct Ethereum methods
caller ContractCaller // Read interface to interact with the blockchain
transactor ContractTransactor // Write interface to interact with the blockchain
+
+ latestHasCode uint32 // Cached verification that the latest state contains code for this contract
+ pendingHasCode uint32 // Cached verification that the pending state contains code for this contract
}
// NewBoundContract creates a low level contract interface through which calls
@@ -96,6 +100,19 @@ func (c *BoundContract) Call(opts *CallOpts, result interface{}, method string,
if opts == nil {
opts = new(CallOpts)
}
+ // Make sure we have a contract to operate on, and bail out otherwise
+ if (opts.Pending && atomic.LoadUint32(&c.pendingHasCode) == 0) || (!opts.Pending && atomic.LoadUint32(&c.latestHasCode) == 0) {
+ if code, err := c.caller.HasCode(c.address, opts.Pending); err != nil {
+ return err
+ } else if !code {
+ return ErrNoCode
+ }
+ if opts.Pending {
+ atomic.StoreUint32(&c.pendingHasCode, 1)
+ } else {
+ atomic.StoreUint32(&c.latestHasCode, 1)
+ }
+ }
// Pack the input, call and unpack the results
input, err := c.abi.Pack(method, params...)
if err != nil {
@@ -153,6 +170,16 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
}
gasLimit := opts.GasLimit
if gasLimit == nil {
+ // Gas estimation cannot succeed without code for method invocations
+ if contract != nil && atomic.LoadUint32(&c.pendingHasCode) == 0 {
+ if code, err := c.transactor.HasCode(c.address, true); err != nil {
+ return nil, err
+ } else if !code {
+ return nil, ErrNoCode
+ }
+ atomic.StoreUint32(&c.pendingHasCode, 1)
+ }
+ // If the contract surely has code (or code is not needed), estimate the transaction
gasLimit, err = c.transactor.EstimateGasLimit(opts.From, contract, value, input)
if err != nil {
return nil, fmt.Errorf("failed to exstimate gas needed: %v", err)