func (c *ContractBackend) ConfirmTransaction(ctx context.Context, tx *types.Transaction, acc accounts.Account) (*types.Receipt, error) {
	receipt, err := bind.WaitMined(ctx, c, tx)
	if err != nil {
		return nil, errors.Wrap(err, "sending transaction")
	}
	if receipt.Status == types.ReceiptStatusFailed {
		reason, err := errorReason(ctx, c, tx, receipt.BlockNumber, acc)
		if err != nil {
			log.Error("TX failed; error determining reason: ", err)
			if receipt.GasUsed+1000 > tx.Gas() {
				log.WithFields(log.Fields{"Used": receipt.GasUsed, "Limit": tx.Gas()}).Warn("TX could be out of gas")
			}
		} else {
			log.Warn("TX failed with reason: ", reason)
		}
		return receipt, errors.WithStack(ErrTxFailed)
	}
	return receipt, nil
}
ConfirmTransaction returns whether a transaction was mined successfully or not
and the receipt if it could be retrieved.
package channel
import (
	"context"
	stderrors "errors"
	"math/big"
	"github.com/ethereum/go-ethereum"
	"github.com/ethereum/go-ethereum/accounts"
	"github.com/ethereum/go-ethereum/accounts/abi"
	"github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/pkg/errors"
	"perun.network/go-perun/log"
)
const startBlockOffset = 100
const GasLimit = 500000
type ContractInterface interface {
	bind.ContractBackend
	ethereum.ChainReader
	ethereum.TransactionReader
}
type Transactor interface {
	NewTransactor(account accounts.Account) (*bind.TransactOpts, error)
}
type ContractBackend struct {
	ContractInterface
	tr Transactor
}
func NewContractBackend(cf ContractInterface, tr Transactor) ContractBackend {
	return ContractBackend{
		ContractInterface: cf,
		tr:                tr,
	}
}
func (c *ContractBackend) NewWatchOpts(ctx context.Context) (*bind.WatchOpts, error) {
	blockNum, err := c.pastOffsetBlockNum(ctx)
	if err != nil {
		return nil, errors.WithMessage(err, "new watch opts")
	}
	return &bind.WatchOpts{
		Start:   &blockNum,
		Context: ctx,
	}, nil
}
func (c *ContractBackend) NewFilterOpts(ctx context.Context) (*bind.FilterOpts, error) {
	blockNum, err := c.pastOffsetBlockNum(ctx)
	if err != nil {
		return nil, errors.WithMessage(err, "new filter opts")
	}
	return &bind.FilterOpts{
		Start:   blockNum,
		End:     nil,
		Context: ctx,
	}, nil
}
func (c *ContractBackend) pastOffsetBlockNum(ctx context.Context) (uint64, error) {
	h, err := c.HeaderByNumber(ctx, nil)
	if err != nil {
		return uint64(0), errors.Wrap(err, "retrieving latest block")
	}
	if h.Number.Uint64() <= startBlockOffset {
		return 1, nil
	}
	return h.Number.Uint64() - startBlockOffset, nil
}
func (c *ContractBackend) NewTransactor(ctx context.Context, gasLimit uint64,
	acc accounts.Account) (*bind.TransactOpts, error) {
	auth, err := c.tr.NewTransactor(acc)
	if err != nil {
		return nil, errors.WithMessage(err, "creating transactor")
	}
	auth.GasLimit = gasLimit
	auth.Context = ctx
	return auth, nil
}