# Nouns 合约分析

By [harlan009](https://paragraph.com/@harlan009) · 2023-03-06

---

最近在学习eth上的智能合约开发，本文主要是对Lil Nouns合约的学习总结。你将了解到Nouns拍卖的过程， 如何将NFT svg以节省gas的方式完全存放在链上，以及如何在下一轮拍卖前提前获取到Nouns的traits（并且我制作了一个可以实时获取下一个lil Nouns traits的工具)

拍卖合约
----

参与过Lil Nouns 拍卖的朋友会知道，每一轮拍卖结束后需要有人手动去settle，当你点击官网上的Pick the next lil Noun按钮后，会唤起你的钱包去调用NounsAuctionHouse合约的settleCurrentAndCreateNewAuction(), 这个函数进行了两个操作，首先调用\_settleAuction() settle上一轮拍卖,如果这一轮没有人出价那么会把这轮的lil noun销毁，如果有人出价，那么会把lil noun转到winner的钱包。最后会把bid资金转给lil nouns dao。

![\_](https://storage.googleapis.com/papyrus_images/03ca85d05a5e12321bf5070983a19101683ce2e169b569fd530ca9087f068741.png)

\\\_

下面看一下createAuction的实现。创建auction时首先会mint一个新的noun（这里除了每第10和第11个lil noun，都会mint给auction合约）, 并将返回的noun id作为参数更新当前的auction变量状态，同时会更新开始结束时间，将settled变量设置为false。

![](https://storage.googleapis.com/papyrus_images/7444c4051a623aa03f229ae149bec96b7a1425e75a4eaab503b7775f30899b82.png)

在用户进行出价时，必须大于等于前一个人的出价的105%(第四个require）。首先会把前一个出价人的eth还回去，然后会在auction变量中记录当前的出价人和出价。最后如果是在拍卖结束前90s出价，会让当前拍卖延长90s

![](https://storage.googleapis.com/papyrus_images/2848235e5b665b9fcfd2a33e5afccb2211d46a1ac583e92c02ca171360c83043.png)

seed 合约
-------

下面说一下mint时nouns的traits是如何确定的。nouns是使用前一个区块的blockhash和前一个nounId作为seed生成伪随机数，然后使用把这个伪随机数对各个trait的总量取模作为该trait id的值。当然每次会把伪随机数进行右移，不然在不同trait总量相同时生成的trait id总是相同的

![](https://storage.googleapis.com/papyrus_images/836de8bb445d62d46f4b7984da25c27048761d390149855733eece288195ce79.png)

既然是伪随机数，那么我们就可以对下一个nouns的traits进行预测，只要遵守上面代码的算法，我们就能得到正确的traits。为了方便大家我制作了一个可以实时看到下一个lil noun的网站，只要输入上一个拍卖的lil noun的编号就能看到下一个lil noun的样子当然你要保证自己settle auction的交易被当前区块打包才行。

[https://lil-nouns-predict.vercel.app](https://lil-nouns-predict.vercel.app)

最后讲一个非常酷的trick，大家都知道eth上的存储是非常贵的，所以nft项目方大多选在将nft metadata存放在ipfs等平台上。Nouns 使用了[@0xsequence](https://twitter.com/0xsequence)的SSTORE2合约来优化gas。SSTORE2选择把数据编码成字节码部署成智能合约，在读取的时候直接读取合约的EXTCODECOPY(第一次知道这种骚操作），唯一的缺点是不能像状态变量一样修改，很适合存储静态的数据。这样写入和读取数据的gas都能得到可观的优化。

[Subscribe](null)

---

*Originally published on [harlan009](https://paragraph.com/@harlan009/nouns)*
