github.com/klaytn/klaytn@v1.10.2/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 Logger = log.NewModuleLogger(log.AccountsAbiBind) 35 36 // WaitMined waits for tx to be mined on the blockchain. 37 // It stops waiting when the context is canceled. 38 func WaitMined(ctx context.Context, b DeployBackend, tx *types.Transaction) (*types.Receipt, error) { 39 queryTicker := time.NewTicker(time.Second) 40 defer queryTicker.Stop() 41 42 localLogger := Logger.NewWith("hash", tx.Hash()) 43 for { 44 receipt, err := b.TransactionReceipt(ctx, tx.Hash()) 45 if receipt != nil { 46 return receipt, nil 47 } 48 if err != nil { 49 localLogger.Trace("Receipt retrieval failed", "err", err) 50 } else { 51 localLogger.Trace("Transaction not yet mined") 52 } 53 // Wait for the next round. 54 select { 55 case <-ctx.Done(): 56 return nil, ctx.Err() 57 case <-queryTicker.C: 58 } 59 } 60 } 61 62 // CheckWaitMined returns an error if the transaction is not found or not successful status. 63 func CheckWaitMined(b DeployBackend, tx *types.Transaction) error { 64 timeoutContext, cancelTimeout := context.WithTimeout(context.Background(), 3*time.Second) 65 defer cancelTimeout() 66 67 receipt, err := WaitMined(timeoutContext, b, tx) 68 if err != nil { 69 return err 70 } 71 72 if receipt == nil { 73 return errors.New("receipt not found") 74 } 75 76 if receipt.Status != types.ReceiptStatusSuccessful { 77 return blockchain.GetVMerrFromReceiptStatus(receipt.Status) 78 } 79 return nil 80 } 81 82 // WaitDeployed waits for a contract deployment transaction and returns the on-chain 83 // contract address when it is mined. It stops waiting when ctx is canceled. 84 func WaitDeployed(ctx context.Context, b DeployBackend, tx *types.Transaction) (common.Address, error) { 85 if tx.To() != nil { 86 return common.Address{}, errors.New("tx is not contract creation") 87 } 88 receipt, err := WaitMined(ctx, b, tx) 89 if err != nil { 90 return common.Address{}, err 91 } 92 if receipt.ContractAddress == (common.Address{}) { 93 return common.Address{}, errors.New("zero address") 94 } 95 // Check that code has indeed been deployed at the address. 96 // This matters on pre-Homestead chains: OOG in the constructor 97 // could leave an empty account behind. 98 code, err := b.CodeAt(ctx, receipt.ContractAddress, nil) 99 if err == nil && len(code) == 0 { 100 err = ErrNoCodeAfterDeploy 101 } 102 return receipt.ContractAddress, err 103 }