Nouns 合约分析

最近在学习 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。

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

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

seed 合约

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

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

https://lil-nouns-predict.vercel.app

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

subscribe://