github.com/klaytn/klaytn@v1.12.1/accounts/abi/bind/util.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2016 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from accounts/abi/bind/util.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package bind 22 23 import ( 24 "context" 25 "errors" 26 "time" 27 28 "github.com/klaytn/klaytn/blockchain" 29 "github.com/klaytn/klaytn/blockchain/types" 30 "github.com/klaytn/klaytn/common" 31 "github.com/klaytn/klaytn/log" 32 ) 33 34 var ( 35 Logger = log.NewModuleLogger(log.AccountsAbiBind) 36 ErrEmptyTx = errors.New("Transaction must not be nil") 37 ) 38 39 // WaitMined waits for tx to be mined on the blockchain. 40 // It stops waiting when the context is canceled. 41 func WaitMined(ctx context.Context, b DeployBackend, tx *types.Transaction) (*types.Receipt, error) { 42 if tx == nil { 43 return nil, ErrEmptyTx 44 } 45 queryTicker := time.NewTicker(time.Second) 46 defer queryTicker.Stop() 47 48 localLogger := Logger.NewWith("hash", tx.Hash()) 49 for { 50 receipt, err := b.TransactionReceipt(ctx, tx.Hash()) 51 if receipt != nil { 52 return receipt, nil 53 } 54 if err != nil { 55 localLogger.Trace("Receipt retrieval failed", "err", err) 56 } else { 57 localLogger.Trace("Transaction not yet mined") 58 } 59 // Wait for the next round. 60 select { 61 case <-ctx.Done(): 62 return nil, ctx.Err() 63 case <-queryTicker.C: 64 } 65 } 66 } 67 68 // CheckWaitMined returns an error if the transaction is not found or not successful status. 69 func CheckWaitMined(b DeployBackend, tx *types.Transaction) error { 70 timeoutContext, cancelTimeout := context.WithTimeout(context.Background(), 3*time.Second) 71 defer cancelTimeout() 72 73 receipt, err := WaitMined(timeoutContext, b, tx) 74 if err != nil { 75 return err 76 } 77 78 if receipt == nil { 79 return errors.New("receipt not found") 80 } 81 82 result := blockchain.ExecutionResult{ 83 VmExecutionStatus: receipt.Status, 84 } 85 return result.Unwrap() 86 } 87 88 // WaitDeployed waits for a contract deployment transaction and returns the on-chain 89 // contract address when it is mined. It stops waiting when ctx is canceled. 90 func WaitDeployed(ctx context.Context, b DeployBackend, tx *types.Transaction) (common.Address, error) { 91 if tx == nil { 92 return common.Address{}, ErrEmptyTx 93 } 94 if tx.To() != nil { 95 return common.Address{}, errors.New("tx is not contract creation") 96 } 97 receipt, err := WaitMined(ctx, b, tx) 98 if err != nil { 99 return common.Address{}, err 100 } 101 if receipt.ContractAddress == (common.Address{}) { 102 return common.Address{}, errors.New("zero address") 103 } 104 // Check that code has indeed been deployed at the address. 105 // This matters on pre-Homestead chains: OOG in the constructor 106 // could leave an empty account behind. 107 code, err := b.CodeAt(ctx, receipt.ContractAddress, nil) 108 if err == nil && len(code) == 0 { 109 err = ErrNoCodeAfterDeploy 110 } 111 return receipt.ContractAddress, err 112 }