diff options
author | Péter Szilágyi <peterke@gmail.com> | 2016-05-20 17:29:28 +0800 |
---|---|---|
committer | Péter Szilágyi <peterke@gmail.com> | 2016-05-20 17:29:28 +0800 |
commit | 1580ec180414bce1e37acc614bc2445f778efb75 (patch) | |
tree | 7c8276f3f1558b5ce62edd0bff87745956084a4c /accounts/abi/bind/base.go | |
parent | e798e4fd750745cec99c5a531e42998d9a7be85e (diff) | |
download | go-tangerine-1580ec180414bce1e37acc614bc2445f778efb75.tar go-tangerine-1580ec180414bce1e37acc614bc2445f778efb75.tar.gz go-tangerine-1580ec180414bce1e37acc614bc2445f778efb75.tar.bz2 go-tangerine-1580ec180414bce1e37acc614bc2445f778efb75.tar.lz go-tangerine-1580ec180414bce1e37acc614bc2445f778efb75.tar.xz go-tangerine-1580ec180414bce1e37acc614bc2445f778efb75.tar.zst go-tangerine-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.go | 27 |
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) |