github.com/ava-labs/subnet-evm@v0.6.4/accounts/abi/bind/util.go (about)

     1  // (c) 2019-2020, Ava Labs, Inc.
     2  //
     3  // This file is a derived work, based on the go-ethereum library whose original
     4  // notices appear below.
     5  //
     6  // It is distributed under a license compatible with the licensing terms of the
     7  // original code from which it is derived.
     8  //
     9  // Much love to the original authors for their work.
    10  // **********
    11  // Copyright 2016 The go-ethereum Authors
    12  // This file is part of the go-ethereum library.
    13  //
    14  // The go-ethereum library is free software: you can redistribute it and/or modify
    15  // it under the terms of the GNU Lesser General Public License as published by
    16  // the Free Software Foundation, either version 3 of the License, or
    17  // (at your option) any later version.
    18  //
    19  // The go-ethereum library is distributed in the hope that it will be useful,
    20  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    22  // GNU Lesser General Public License for more details.
    23  //
    24  // You should have received a copy of the GNU Lesser General Public License
    25  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    26  
    27  package bind
    28  
    29  import (
    30  	"context"
    31  	"errors"
    32  	"time"
    33  
    34  	"github.com/ava-labs/subnet-evm/core/types"
    35  	"github.com/ava-labs/subnet-evm/interfaces"
    36  	"github.com/ethereum/go-ethereum/common"
    37  	"github.com/ethereum/go-ethereum/log"
    38  )
    39  
    40  // WaitMined waits for tx to be mined on the blockchain.
    41  // It stops waiting when the context is canceled.
    42  func WaitMined(ctx context.Context, b DeployBackend, tx *types.Transaction) (*types.Receipt, error) {
    43  	queryTicker := time.NewTicker(time.Second)
    44  	defer queryTicker.Stop()
    45  
    46  	logger := log.New("hash", tx.Hash())
    47  	for {
    48  		receipt, err := b.TransactionReceipt(ctx, tx.Hash())
    49  		if err == nil {
    50  			return receipt, nil
    51  		}
    52  
    53  		if errors.Is(err, interfaces.NotFound) {
    54  			logger.Trace("Transaction not yet mined")
    55  		} else {
    56  			logger.Trace("Receipt retrieval failed", "err", err)
    57  		}
    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  // WaitDeployed waits for a contract deployment transaction and returns the on-chain
    69  // contract address when it is mined. It stops waiting when ctx is canceled.
    70  func WaitDeployed(ctx context.Context, b DeployBackend, tx *types.Transaction) (common.Address, error) {
    71  	if tx.To() != nil {
    72  		return common.Address{}, errors.New("tx is not contract creation")
    73  	}
    74  	receipt, err := WaitMined(ctx, b, tx)
    75  	if err != nil {
    76  		return common.Address{}, err
    77  	}
    78  	if receipt.ContractAddress == (common.Address{}) {
    79  		return common.Address{}, errors.New("zero address")
    80  	}
    81  	// Check that code has indeed been deployed at the address.
    82  	// This matters on pre-Homestead chains: OOG in the constructor
    83  	// could leave an empty account behind.
    84  	code, err := b.CodeAt(ctx, receipt.ContractAddress, nil)
    85  	if err == nil && len(code) == 0 {
    86  		err = ErrNoCodeAfterDeploy
    87  	}
    88  	return receipt.ContractAddress, err
    89  }