如何在Cardano上建立一个拍卖市场

注:这是2021年12月我的项目中的一篇文章的转帖
漫画
. 我把它转贴到这里,因为这将是我今后写技术文章的主要账户。

今天,我很高兴在Cardano上推出ADA Blobs智能合约市场!这是第一个拍卖NFT市场。这是Cardano区块链上的第一个拍卖NFT市场,我将在这个Blob帖子中解释它是如何工作的。

ADA Blobs项目是完全开源的。你可以关注网站的源代码以及Plutus的源代码。这篇Blob文章将向你展示如何用Haskell和Plutus创建一个拍卖合约,同时用Javascript、Cardano序列化库和Nami钱包构建一个向Cardano区块链提交的交易。

一个可爱的ADA Blob,名叫Bob
简介

Cardano使用扩展的UTxO模型,与比特币使用的UTxO模型类似,但有额外的能力将任意数据添加到交易中。

UTxO代表 “未花费的交易输出”,其工作方式类似于你在商店用现金支付。比方说,你想在玩具店花10美元买一个可爱的毛绒动物Blob,但你只有20美元的钞票。你可以把整张20美元的钞票给收银员,他们会给你一张10美元的零钱。现在让我们说,你同样想给别人发送10个ADA(10₳),但你的Cardano钱包里只有1个UTxO,上面有20₳。交易的输入是20₳的UTxO,你会得到一个10₳的UTxO。

比特币UTxO模型
这个模型对于在区块链上发送和验证交易很有效,但有一个基本的限制。我们无法创建更复杂的交易,因为我们无法获得额外的区块链数据或可编程的验证器。

一个名为Yolg的恶性和攻击性的ADA Blob
eUTxO模型

为了解决这个问题,为Cardano开发了eUTxO模型。这使开发人员能够访问Plutus语言,使他们能够创建自定义的链上验证器。与Plutus一起,eUTxO模型允许开发人员将称为datum的数据附加到交易中,以及当坐在脚本地址的UTxO试图被花费时提供称为赎回者的数据。

下面的例子展示了Bob向一个脚本地址发送资金,以及Yolg在Plutus验证器评估为 "真 "后提取这些资金的交易。

image
Bob向Plutus脚本地址发送资金
image
Yolg从脚本地址提取资金

在上面的例子中,Bob向一个脚本地址发送了40₳。他提供了一个100₳的UTXO作为输入,并指示输出是一个60₳的UTXO作为变化返回给Bob,以及一个40₳的UTXO给脚本地址。Bob还提供了一个名为State 0的基准点。Plutus验证器评估为真,脚本被发送到40₳。

现在Bob的朋友Yolg想提取Bob发送到脚本地址的一些资金。Yolg创建了一个新的交易,脚本地址的UTxO被用作输入,输出是一个20₳的UTxO给Yolg,另一个20₳的UTxO返回到脚本地址。Yolg提供一个 "Withdraw "赎回器,在脚本的输出UTxO上的数据从状态0过渡到状态1。

一个Plutus验证器将接受3个输入并返回真或假。Validator(Datum, Redeemer, ScriptContext) = True. 如果验证器评估为真,则交易成功。如果不是,则交易失败。

一个名为Glob的可压缩ADA Blob
创建ADA Blobs验证器

为了创建ADA Blobs的Plutus拍卖验证器,我们需要处理3种可能的用户行为。

开始拍卖
竞价拍卖
关闭拍卖
开始拍卖

为了启动Blob NFT的拍卖,我们需要向我们的脚本地址发送一个UTxO,其中包含Blob NFT和一个基准点,这个基准点将被Plutus验证器用来决定其他人如何对Blob出价。
image

例如,如果我们的数据集有一个最小出价值,而出价人试图出价低于该值,那么出价人的交易将返回错误,并失败。

我们的拍卖数据集的Haskell数据类型
从上面可以看出,我们的AuctionDatum将有2个部分,一个AuctionDetails和一个Maybe BidDetails。

我们希望拍卖细节在整个拍卖过程中始终是相同的,所以我们将在开始拍卖时设置拍卖细节。我们还不会设置竞标细节,因为我们会让竞标者在竞标ADA Blobs时设置这个值。

在这篇Blob文章的后面,我将向你展示我们如何使用Javascript和Cardano序列化库来构建启动拍卖的交易链。

鲍勃为Blob NFT开始拍卖
拍卖出价
image

现在我们已经提交了一个交易来启动我们的Blob拍卖,我们需要给其他人提供一个方法来竞拍。

竞标者将提供一个新的数据和他们更新的出价,以及一个 "竞标 "赎回者(行动)来花费脚本地址上的UTxO。验证器脚本将检查,以确保出价是有效的(大于所有其他出价和保留金额),并确保我们正确设置下一个基准点(验证bidDetails数据与投标人实际发送到脚本地址的金额相同)。

ADA Blobs Plutus验证器的 "投标 "赎回者

Glob为一个Blob NFT出价100₳。
举个例子,我们说Glob为Bob拍卖的Blob NFT出价100₳。现在脚本地址有101₳和一个Blob NFT。

注意:额外的1₳是因为Cardano原生代币不能出现在没有₳的脚本地址。这是因为这样你就无法发送代币,因为你无法支付Cardano区块链费用。

Yolg出价200₳购买一个Blob NFT。这比Globs出价100₳。
现在Yolg来了,想出价200₳购买Blob NFT。Yolg将发送200₳到脚本地址,而坐在脚本地址的100₳将被退回给Glob。

我们必须确保在投标交易中,如果投标人被出价,他们的资金将被正确地返还给他们。所有这些验证都是在验证器的投标部分进行的。完整的源代码包含了这个过程的额外帮助函数。你可以在这里跟随完整的Plutus源代码。

关闭一个拍卖

拍卖完成后,任何人都可以关闭拍卖,这将把投标资金发送给卖方,并将Blob NFT发送给投标人。我们需要 "关闭 "救世主来关闭拍卖。关闭拍卖的验证包括确保拍卖期限已过的代码。你可以查看下面验证器关闭部分的代码。

ADA Blobs Plutus验证器的 "关闭 "赎回器
在我们的例子中,让我们假设拍卖已经结束。Yolg会得到Blob NFT和脚本地址的1₳,Bob会得到脚本地址的200₳。

当拍卖结束时,Yolg得到1₳和Blob NFT,而Bob得到200₳。

一个名为Rooboo的罕见的、软绵绵的ADA Blob
用Javascript构建交易

Plutus被分成On Chain和Off Chain代码。上述内容解决了On Chain的验证代码,但我们仍然需要建立交易并将其提交给Cardano区块链。在创建这个项目的时候,Plutus后端应用程序(PAB)与钱包的集成有困难。因此,ADA Blobs没有使用Haskell来构建将提交给Cardano区块链的交易,而是使用Javascript和Cardano序列化库。

构建所有3种类型交易的代码可以在这个源代码中找到。

构建开始拍卖交易

为了开始我们的拍卖,我们需要构建我们的初始AuctionDatum,构建交易的预期输出,并选择我们的输入UTxOs,其中必须包含我们打算拍卖的Blob NFT。

匹配Haskell数据类型的Typescript数据类型
我们现在需要把我们的typescript对象转换为Plutus可以理解的数据。为此,我们需要使用Cardano序列化库。然而,在写这篇文章的时候,我们需要添加一些自定义的功能来使其正常工作。最初SpaceBudz实现了这个库的一个自定义版本,以正确建立交易。我在这里复制了他们的实现。

Cardano要求我们的数据必须是特定的格式,以便正确提交交易。我建议阅读Cardano文档的这一页,以便了解所需的JSON格式。

在我的datum.ts文件中。我已经评论了与函数试图建立的Haskell数据类型相对应的JSON结构。了解如何使用Cardano序列化库构建数据的最简单方法是阅读我在这里创建的START_DATUM函数。

将提交给Cardano区块链的Auction Datum Haskell数据类型的JSON结构

一个名为Oobby的blobby ADA Blob
有了我们的Datum,我们现在需要创建我们想要的输出并选择我们的输入UTxOs。对于我们的输出,我们希望创建一个具有Blob NFT的UTxO。同时,在这个时候,将数据集作为元数据包含在交易中是一个很好的做法,这样我们就可以在以后的投标链Javascript代码中查看它。下面的代码构建了这样一个输出。

image

构建 "开始拍卖 "输出
最后,我们需要为交易选择我们的输入UTxOs。为了做到这一点,我们将使用随机改进的硬币选择算法。我不想在这里对这个算法进行太多技术性的讨论,所以我在上面提供了一个来自IOHK的算法链接。从本质上讲,该算法选择UTxOs的方式是,输出将允许未来的支付,而输入的数量最少。

对于ADA Blobs,我在CoinSelection.ts文件中复制了SpaceBudz的算法实现。我建议也复制这个。

最后,有了我们的数据、输入和输出,我们可以构建、签署和提交交易。

提交我们的拍卖交易!

一个名为Blurp的过大的ADA Blob
构建竞价交易

我们将以与拍卖交易非常相似的方式建立竞标交易。不同之处在于我们的竞价交易输出和我们设置交易时间的要求(ttl)。对于我们的输出,如果我们的ADA Blob已经有一个现有的投标,我们需要用下面的代码将前一个投标人的资金送回他们的地址。

在我们的交易输出中,向前一个出价人还款
我们还需要设置一个有效性开始时间间隔和生存时间,因为投标验证将取决于投标交易发生的时间。

为我们的投标交易设置一个有效的开始时间间隔和时间。
有了这个数据集,再加上我们更新的数据、输出和输入,我们就可以签署和提交我们的投标交易了!

一个叫Peep的小的、吱吱作响的ADA Blob
建立关闭交易

我们就快完成了! 我们需要建立我们的成交交易,给最高出价者提供ADA Blob NFT,给卖家提供最高出价。有一种情况我们也必须考虑到,即没有人出价拍卖可爱的宠物Blob(但现实中这种情况永远不会发生,因为它们太可爱了)。然而,为了完整起见,我们应该在我们的 "关闭 "代码中包括这一点。

关闭输出将给投标人提供Blob NFT,给卖家提供最高出价
上面的代码将给最高出价者提供可爱的Blob NFT,给卖家提供最高的出价金额。你所看到的 "splitAmount "函数将输出结果在卖家和ADA Blobs市场费用之间进行分割,该费用为1%。On Chain验证代码将这一费用考虑在内,你可以在源代码中看到。

在输出的同时,我们还需要为关闭交易设置一个生存时间(ttl),因为关闭交易也取决于时间。

一个名为Broogr的美味巧克力ADA Blob
摘要

经过几周在Cardano测试网和主网的测试,ADA Blob项目正在完美地运行!有300个可爱的宠物Blob。有300个可爱的宠物Blob NFT,将在未来6年内每周发布一个。我很高兴能发布这个项目,并将其开源给社区,供大家学习。

如果你想加入Blob社区,我们有一个Discord服务器和一个Twitter来满足你所有的Blob需求。

Cardano项目现在正在快速发展,这是一个令人兴奋的时刻,可以成为社区的一部分。请随时查看ADA Blobs的源代码,以便在你自己的项目中使用!

ADA Blobs网站源代码:GitHub - NicholasMaselli/ADABlobs: This repository is for the ADABlobs website
ADA Blobs Plutus智能合约源代码:GitHub - NicholasMaselli/ADABlobsPlutus: This code repository is the Plutus code repository for the ADABlobs community NFT project.