122 lines
5.2 KiB
Text
122 lines
5.2 KiB
Text
{-# STDLIB_VERSION 3 #-}
|
|
{-# CONTENT_TYPE DAPP #-}
|
|
{-# SCRIPT_TYPE ACCOUNT #-}
|
|
|
|
|
|
let maxAuctionDuration = 1440 * 30
|
|
# ~ 30 days
|
|
|
|
# priceAssetId = "WAVES" or assetId
|
|
@Callable(i)
|
|
func startAuction(duration: Int, startPrice: Int, priceAssetId:String) = {
|
|
|
|
let auctionId = toBase58String(i.transactionId)
|
|
let endHeight = lastBlock.height + duration
|
|
|
|
let pmt = extract(i.payment)
|
|
|
|
if (duration > maxAuctionDuration) then throw("Duration is too long. Must be less than " + toString(maxAuctionDuration)) else
|
|
WriteSet(
|
|
[ DataEntry(auctionId, endHeight),
|
|
DataEntry(auctionId + "_organizer", i.caller.bytes.toBase58String()),
|
|
DataEntry(auctionId + "_lot_assetId", if (isDefined(pmt.assetId)) then toBase58String(value(pmt.assetId)) else "WAVES"),
|
|
DataEntry(auctionId + "_lot_amount", pmt.amount),
|
|
DataEntry(auctionId + "_startPrice", startPrice),
|
|
DataEntry(auctionId + "_priceAssetId", priceAssetId)
|
|
])
|
|
}
|
|
|
|
@Callable(i)
|
|
func bid(auctionId: String) = {
|
|
|
|
let pmt = extract(i.payment)
|
|
let pmtAssetIdStr = if (isDefined(pmt.assetId)) then toBase58String(value(pmt.assetId)) else "WAVES"
|
|
let callerAddressStr = i.caller.bytes.toBase58String()
|
|
|
|
let endHeight = getIntegerValue(this, auctionId)
|
|
let startPrice = getIntegerValue(this, auctionId + "_startPrice")
|
|
let priceAssetId = getStringValue(this, auctionId + "_priceAssetId")
|
|
let winAmount = getInteger(this, auctionId + "_winAmount")
|
|
let winner = getString(this, auctionId + "_winner")
|
|
|
|
let bidFromTheSameUser = isDefined(winner) && value(winner) == callerAddressStr
|
|
let totalBidAmount = pmt.amount + if bidFromTheSameUser then
|
|
value(winAmount) else 0
|
|
|
|
if (lastBlock.height >= endHeight) then
|
|
throw("Auction already finished") else
|
|
if (priceAssetId != pmtAssetIdStr) then
|
|
throw("Bid must be in asset '" + priceAssetId + "'") else
|
|
if (isDefined(winAmount) && totalBidAmount <= value(winAmount) ||
|
|
!isDefined(winAmount) && totalBidAmount <= startPrice) then
|
|
throw("Bid must be more then "
|
|
+ toString(if isDefined(winAmount) then value(winAmount) else startPrice))
|
|
else
|
|
if (bidFromTheSameUser || !isDefined(winner)) then
|
|
WriteSet([
|
|
DataEntry(auctionId + "_winner", callerAddressStr),
|
|
DataEntry(auctionId + "_winAmount", totalBidAmount)
|
|
])
|
|
else {
|
|
let previousBidderAddr = addressFromStringValue(value(winner))
|
|
let priceAsset = if (priceAssetId == "WAVES" || priceAssetId == "") then unit else fromBase58String(priceAssetId)
|
|
ScriptResult(
|
|
WriteSet([
|
|
DataEntry(auctionId + "_winner", callerAddressStr),
|
|
DataEntry(auctionId + "_winAmount", totalBidAmount)
|
|
]),
|
|
TransferSet([
|
|
ScriptTransfer(previousBidderAddr, value(winAmount), priceAsset)
|
|
])
|
|
)
|
|
}
|
|
|
|
}
|
|
|
|
|
|
@Callable(i)
|
|
func withdraw(auctionId: String) = {
|
|
|
|
let pmt = extract(i.payment)
|
|
let pmtAssetIdStr = if (isDefined(pmt.assetId)) then toBase58String(value(pmt.assetId)) else "WAVES"
|
|
let callerAddressStr = i.caller.bytes.toBase58String()
|
|
|
|
let endHeight = getIntegerValue(this, auctionId)
|
|
let organizer = getStringValue(this, auctionId + "_organizer")
|
|
let winner = getString(this, auctionId + "_winner")
|
|
let lotAssetId = getStringValue(this, auctionId + "_lot_assetId")
|
|
let lotAmount = getIntegerValue(this, auctionId + "_lot_amount")
|
|
let priceAssetId = getStringValue(this, auctionId + "_priceAssetId")
|
|
let winAmount = getIntegerValue(this, auctionId + "_winAmount")
|
|
|
|
let lotAsset = if (lotAssetId == "WAVES") then unit else fromBase58String(lotAssetId)
|
|
let priceAsset = if (priceAssetId == "WAVES" || priceAssetId == "") then unit else fromBase58String(priceAssetId)
|
|
let winnerAddr = addressFromStringValue(value(winner))
|
|
let organizerAddr = addressFromStringValue(value(organizer))
|
|
|
|
let betAmount = getInteger(this, auctionId + "_bidder_" + callerAddressStr)
|
|
|
|
if (lastBlock.height < endHeight) then
|
|
throw("Auction is not finished yet") else
|
|
|
|
if (!isDefined(winner)) then {
|
|
if (isDefined(getString(this, auctionId + "_lot_passed"))) then
|
|
throw("Organizer has already got his lot back")
|
|
else
|
|
ScriptResult(
|
|
WriteSet([DataEntry(auctionId + "_lot_passed", organizer)]),
|
|
TransferSet([ScriptTransfer(organizerAddr, lotAmount, lotAsset)])
|
|
)
|
|
}
|
|
else {
|
|
# Lot -> winner, winner's bet -> organizer
|
|
if (isDefined(getString(this, auctionId + "_lot_passed"))) then
|
|
throw("Lot is already passed to the winner, and organizer got his reward")
|
|
else
|
|
ScriptResult(
|
|
WriteSet([DataEntry(auctionId + "_lot_passed", winnerAddr.bytes.toBase58String())]),
|
|
TransferSet([ScriptTransfer(winnerAddr, lotAmount, lotAsset),
|
|
ScriptTransfer(organizerAddr, winAmount, priceAsset)])
|
|
)
|
|
}
|
|
}
|