OpenSea : https://opensea.io/collection/pxnghostdivision
合约地址:https://etherscan.io/address/0x160c404b2b49cbc3240055ceaee026df1e8497a0#code
Tips:
自学有一段时间了,尝试看了一些项目的合约,这是第一次写总结,有不足或者有问题的地方欢迎在推特上私信或留言,一起讨论学习成长。
https://twitter.com/Bowei52748580
继承了 ERC721A;Ownable

//荷兰拍的数量 4k
DA_QUANTITY = 4000;
//白单可以mint 6k.
WL_QUANTITY = 6000;
//WL Price 白单地板价
WLprice = 0.35 ether;
//合拍开始价格 2e
DA_STARTING_PRICE = 2 ether;
//合拍结束价格 0.1
DA_ENDING_PRICE = 0.1 ether;
//合拍递减的价格 0.05
DA_DECREMENT = 0.05 ether;
//每15分钟降价一次
DA_DECREMENT_FREQUENCY = 900;
//荷兰拍开始的时间
DA_STARTING_TIMESTAMP = 1651719600
总结:
该项目共计 10k 个nft,荷兰拍起拍价 2e,之后每隔15分钟降价 0.05e,白单mint价格 0.35e
使用 Ownable 对函数调用的权限做了限制;
mint函数中,均采用了_safemint;
对关键性信息做了 require校验:每个钱包mint数量,项目总mint数量,钱包余额,mint地址,荷兰拍和不同种类 mint 时间的起始判断;
以上判断可防止「超发」「科学家非法手段mint」「Reentrancy 重入攻击」「一个钱包多次mint」
使用 callerIsUser() 防止合约调用;
modifier callerIsUser() { require(tx.origin == msg.sender, "The caller is another contract"); _; }
基础逻辑:
荷兰拍共提供 4000 个,起拍价 2e,然后每隔15分钟降价 0.05e。
荷兰拍开始时间是:

时间戳转换之后如下:

随着时间的推移,荷兰拍的价格会逐渐下降,当荷兰拍价格小于 0.7 时那么此时 WL mint的价格就是:「当前荷兰拍价格/ 2」。若当前荷兰拍结束后其价格是0.6 那么白单的mint价格从初始的 0.35e 变为 0.3e。所以荷兰拍的最终价格可能会影响到 WL 的mint 价格。

条件校验:
判断荷兰拍开始。DA_ACTIVE == TRUE 【合约状态校验】
判断前端页面传过来的的加密签名是不是和后端加密之后的一样,这样可以防止合约机器人调用合约。【校验合约调用者】
判断荷兰拍是否到4000个【防止超发】
通过获取当前区块时间来判断是否到荷兰拍的开始时间【荷兰拍时间校验】
若当前区块时间在白单开始时间之前那么此时荷兰拍尚未结束【荷兰拍结束时间校验】
白单mint 开始时间是荷兰拍进行24小时之后,换句话说,荷兰拍持续时间是24小时。
校验当前钱包mint的数量,要求数量最多 2 个【钱包 mint 数量校验】
判断当前钱包余额是否够支付【金额校验】
当上边的校验都通过之后开始执行 _safeMint()
第一个成功通过荷兰拍 mint 的人共花了 4k多刀的 gas fee。所以下次如果参加 荷兰拍想要提前确认交易,就尽可能提高你的 gas 设置吧。至于为什么这和 POW 共识机制有关,请自行Google。
整个荷兰拍在10分钟左右就结束了。所以说这个项目非常火。最后一个人mint 的gas fee 只有55刀,可见时机的把握可以节省不少 gas fee。

条件校验:
签名校验与荷兰拍的签名校验方法一样【校验合约调用者】
判断mint 数量不超过 6000 个【防止超发】
校验当前 mint 地址是否已经 mint 过,一个地址只能 mint 一次,mint 数量也是 1.【防止单个地址多次 mint 】
获取当前区块时间应大于白单开始 mint 的时间,否则白单 mint 尚未开始【校验mint 开始时间】
校验当前 msg.value 应该足够支付【看是否有足够的金额支付交易】
执行 _safeMint() 完成交易
白单mint 一天「24h」之后,dev 团队开始mint,dev团队mint 的数量就是项目总提供量 10k - 已经被mint的。
dev mint 的方法可以理解为将尚未mint 的全部打到dve 的地址中。他们mint的方式是10个10个的mint,这样应该是为了节省 gas fee。

条件校验:
team mint 时间和白单 mint 开始时间相同【mint 时间校验】
team 的mint 地址不能超过限定的数量,这个根据贡献度不同 mint 的数量不同【规则校验】
校验钱包的余额是否够支付此次交易【余额校验】
然后执行 _safeMint()
以上就是 PXN 项目的合约分析,如果有不懂的或者有问题的欢迎讨论在我的推特下留言。
知识点1:
在修改器 modifier 中我们看到 tx.origin == msg.sender,这段代码是什么意思呢?请看图
modifier callerIsUser() {
require(tx.origin == msg.sender, "The caller is another contract");
_;
}

msg.sender: 指直接调用智能合约函数的账户或智能合约地址;
**tx.origin:**指调用智能合约函数的账户地址,只有账户地址可以是tx.origin.
因此可以通过 callerIsUser() 这个修改器判断当前合约调用者是不是合约地址。
知识点2
如何具体查看Transaction失败的原因?
首先到 etherscan 上我们可以看到某些 transcation 是失败的,此时我们可以将这个失败的 Transaction Hash 粘贴到 tenderly 上去查看具体原因。如图所示,还可以看到那些改变链上状态的函数消耗了多少 gas fee,用来调试优化合约时候可以用到。毕竟每次修改链上状态都是要花真金白银的。

区块链的特点是匿名、公开、透明、不可更改,每一笔交易所有的细节都能在链上看到,从最开始尝试看懂链上数据,到后来决定走科学家这条路从中收获很多,虽才刚刚开始,但持之以恒总会有满意的收获。
以后遇到火爆的项目会持续解读欢迎关注我的推特
在成为科学家的道路上一起成长,在赚钱的道路上并肩前行,你好我是Jack_Zhang.
