Hello everyone, I’m trying to create a Auction smart contract and I’m using the Playground to test my work.
My rationale is to create two triggers:
- The auctioner collects the value stored at the end of the deadline of the auction.
- A refund trigger that activates whenever the values at the address of the auction is greater than the value they have bidded.
Unfortunatelly I’m not being able to trigger the refund trigger, and when the collection trigger appears it shows the following message:
Message from wallet #1: Attempting to collect transaction outputs from 'AddressOf {getAddress = dbbbddc30862a29da5ee2bca83de3411646f444eb0beb1dc569d9f22edb3d38d}', but there are no known outputs at that address. An empty transaction will be submitted.
Can anybody give me any advice/pointer on what is going on, or places of where I can find exemples of Plutus Smart Contracts?
This is the code:
import qualified Language.PlutusTx as PlutusTx
import Language.PlutusTx.Prelude
import Ledger (Address, DataScript (DataScript), PendingTx, PubKey,
RedeemerScript (RedeemerScript), TxId, ValidatorScript (ValidatorScript),
applyScript, compileScript, hashTx, lifted, pendingTxValidRange,
scriptAddress, valueSpent)
import qualified Ledger.Interval as Interval
import Ledger.Slot (Slot, SlotRange)
import qualified Ledger.Validation as V
import Ledger.Value (Value)
import qualified Ledger.Value as Value
import Playground.Contract
import Wallet (EventHandler (EventHandler), EventTrigger, MonadWallet, andT,
collectFromScript, collectFromScriptTxn, fundsAtAddressGeqT, logMsg,
defaultSlotRange,fundsAtAddressGtT, ownPubKey, notT, payToScript, register, slotRangeT, registerOnce)
import qualified Wallet as W
import Wallet.Emulator (Wallet)
import qualified Wallet.Emulator as EM
data Auction = Auction
{ auctionDeadline :: Slot
, auctionOwner :: PubKey
, buyNow :: Value
} deriving (Generic, ToJSON, FromJSON, ToSchema)
PlutusTx.makeLift ''Auction
mkAuction :: Slot -> Wallet -> Value -> Auction
mkAuction ddl ownerWallet value =
Auction
{ auctionDeadline = ddl
, auctionOwner = EM.walletPubKey ownerWallet
, buyNow = value
}
collectionRange :: Auction -> SlotRange
collectionRange cmp =
W.interval 1 (auctionDeadline cmp)
refundRange :: Auction -> SlotRange
refundRange cmp =
W.interval 1 (auctionDeadline cmp)
data AuctionAction = Collect | Refund
deriving (Generic, ToJSON, FromJSON)
PlutusTx.makeLift ''AuctionAction
type AuctionValidator = PubKey -> AuctionAction -> PendingTx -> Bool
validCollection :: Auction -> PendingTx -> Bool
validCollection auction p = (p `V.txSignedBy` auctionOwner auction)
validRefund :: Auction -> PubKey -> PendingTx -> Bool
validRefund auction contributor p =
(collectionRange auction `Interval.contains` pendingTxValidRange p)
&& (p `V.txSignedBy` contributor)
mkValidator :: Auction -> AuctionValidator
mkValidator auction con act p = case act of
Collect -> validCollection auction p
Refund -> validRefund auction con p
contributionScript :: Auction -> ValidatorScript
contributionScript cmp = ValidatorScript $
$$(Ledger.compileScript [|| mkValidator ||])
`Ledger.applyScript`
Ledger.lifted cmp
auctionAddress :: Auction -> Ledger.Address
auctionAddress = Ledger.scriptAddress . contributionScript
bid :: MonadWallet m => Slot -> Wallet -> Value -> m ()
bid deadline ownerWallet value = do
let auc = mkAuction deadline ownerWallet value
ownPK <- ownPubKey
let ds = DataScript (Ledger.lifted ownPK)
range = W.interval 1 (auctionDeadline auc)
tx <- payToScript range (auctionAddress auc) value ds
logMsg "Submitted bid"
register (refundTrigger value auc) (refundHandler (Ledger.hashTx tx) auc)
logMsg "Registered refund trigger for bid"
scheduleCollection :: MonadWallet m => Slot -> Wallet -> Value -> m ()
scheduleCollection deadline ownerWallet lowest = do
let cmp = mkAuction deadline ownerWallet lowest
register (collectFundsTrigger cmp) (EventHandler (\_ -> do
logMsg "Collecting funds"
let redeemerScript = Ledger.RedeemerScript (Ledger.lifted Collect)
range = collectionRange cmp
collectFromScript range (contributionScript cmp) redeemerScript))
collectFundsTrigger :: Auction -> EventTrigger
collectFundsTrigger c = (notT (slotRangeT (collectionRange c)))
refundTrigger :: Value -> Auction -> EventTrigger
refundTrigger vl a = (fundsAtAddressGtT (auctionAddress a) vl)
refundHandler :: MonadWallet m => TxId -> Auction -> EventHandler m
refundHandler txid auc = EventHandler (\_ -> do
logMsg "Refunding because higher bid has arrived"
let validatorScript = contributionScript auc
redeemerScript = Ledger.RedeemerScript (Ledger.lifted Refund)
collectFromScriptTxn (refundRange auc) validatorScript redeemerScript txid)
$(mkFunctions ['scheduleCollection, 'bid])
$(mkIotsDefinitions ['scheduleCollection, 'bid])
Thanks in advance