I've been toying around with the English Auction example and I have two questions:

  1. After an invalid bid (less than the minimum bet set for the auction) from a wallet, a second valid bid from the same wallet is also not successful. Is this intended? The trace shows the first invalid bid but not the second one, the last trace message is "Contract instance stopped with error: "bid lower than minimal bid 10000000".

  2. Considering the following sequence of actions: auction starts, wallet 2 bids, wallet 3 outbids wallet 2, wallet 2 outbids wallet 3, auction closes. The image below shows the transaction corresponding to the second bid of wallet 2. Why do we have wallet 2 twice as an input of the transaction? I thought only wallet 2 created by slot 3 should appear as an input. enter image description here

  • For (1), anytime someone bids < minumum, the contract does "throwError" which seems to cause this problem. I would have thought that just the wallet/transcation that bids would fail, not the entire smart contract !
    – wakathi
    Jan 16, 2022 at 13:03
  • You're right, this should be two questions (you will get twice the votes and reputation). It will probably help you to write a better title for the questions too. e.g. "English auction: Is prevention of valid bid by previous invalid bid intended behavior?"
    – gRebel
    Jan 16, 2022 at 22:22

2 Answers 2


For question 1: It seems to be an issue with the way the English Auction contract is written. I believe this is a bug that someone with more knowledge of Plutus would be able to fix in the contract code.

For question 2:

When Wallet 2 was outbid, the script created a UTxO to give it back Wallet 2's original 11000000 bid.

When Wallet 2 bid again, it bid 15000000. First the unspent 11000000 was used as an input, but that's not enough to cover the 15000000 bid. So Wallet 2's other UTxO containing 88991363 is needed as an additional input.

  • Note: I have suggested the original poster break this into two questions.
    – gRebel
    Jan 16, 2022 at 22:25

Q1: As @Travis mentioned, that's the way the offchain code was implemented. Try as follows and you'll have a second opportunity to bid.

bid :: forall w s. BidParams -> Contract w s Text ()
bid BidParams{..} = do
  (oref, o, d@AuctionDatum{..}) <- findAuction bpCurrency bpToken
  logInfo @P.String $ printf "found auction utxo with datum %s" (P.show d)

  if (bpBid < minBid d) 
    then logError @P.String $ printf "bid lower than minimal bid %d" (minBid d)
    else do 
        pkh <- ownPaymentPubKeyHash
        let b  = Bid {bBidder = pkh, bBid = bpBid}
            d' = d {adHighestBid = Just b}
            v  = Value.singleton bpCurrency bpToken 1 <> Ada.lovelaceValueOf (minLovelace + bpBid)
            r  = Redeemer $ PlutusTx.toBuiltinData $ MkBid b

            lookups = Constraints.typedValidatorLookups typedAuctionValidator P.<>
                    Constraints.otherScript auctionValidator                P.<>
                    Constraints.unspentOutputs (Map.singleton oref o)
            tx      = case adHighestBid of
                        Nothing      -> Constraints.mustPayToTheScript d' v                            <>
                                        Constraints.mustValidateIn (to $ aDeadline adAuction)          <>
                                        Constraints.mustSpendScriptOutput oref r
                        Just Bid{..} -> Constraints.mustPayToTheScript d' v                            <>
                                        Constraints.mustPayToPubKey bBidder (Ada.lovelaceValueOf bBid) <>
                                        Constraints.mustValidateIn (to $ aDeadline adAuction)          <>
                                        Constraints.mustSpendScriptOutput oref r
        ledgerTx <- submitTxConstraintsWith lookups tx
        void $ awaitTxConfirmed $ getCardanoTxId ledgerTx
        logInfo @P.String $ printf "made bid of %d lovelace in auction %s for token (%s, %s)"
            (P.show adAuction)
            (P.show bpCurrency)
            (P.show bpToken)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.