# Moonbirds Smart Contract Nesting 功能浅析

By [JCONE](https://paragraph.com/@jcone) · 2022-04-18

---

Moonbirds Smart Contract Nesting 功能浅析

Moonbirds可以说是近几天来最炙手可热的NFT项目，2.5E的高昂公售价格，短短2天时间已经涨到19E的地板价，并实现了超过70,000E的二级市场交易量，项目上线以来一直盘踞Opensea日交易量榜单第一。

除了有私密俱乐部会员资格（private club membership）、PROOF私有Discord会员资格以及 PROOF未来元宇宙项目access等utility外，Moonbirds还有一个全新开发的功能：Nesting。

根据项目[官网](https://moonbirds.xyz/)说明，在开启Nesting之后，拥有者可以在其Moonbirds不离开钱包的情况下进行锁定（lock up），并通过累积Nesting时间让Moonbirds得到升级，以获得未来项目方更多的空投与奖励。

让我们阅读Moonbirds智能合约的[源代码](https://etherscan.io/address/0x23581767a106ae21c074b2276d25e5c3e136a68b#code)，看看其Nesting功能是如何实现的。

    mapping(uint256 => uint256) private nestingStarted;
    

首先为每一个`tokenId`映射一个`nestingStarted`的开始时间值，0即此Moonbirds没有在nesting；

    mapping(uint256 => uint256) private nestingTotal;
    

然后再为每一个tokenId映射一个nestingTotal的时间数值，即某个tokenId的Moonbirds的nesting总时间累积值；这里可以注意到，nestingTotal总累积值是根据某一个具体tokenId进行积累，与token owner无关，因此Moonbirds交易与转移并不会重置`nestingTotal`的数值；

    function nestingPeriod(uint256 tokenId)
        external
        view
        returns (
            bool nesting,
            uint256 current,
            uint256 total
        )
    {
        uint256 start = nestingStarted[tokenId];
        if (start != 0) {
            nesting = true;
            current = block.timestamp - start;
        }
        total = current + nestingTotal[tokenId];
    }
    

这里定义了一个外部调用的可视函数`nestingPeriod`，对每一个输入的`tokenId`返回三个值：

是否正在nesting（`nestingStarted`不等于0就表明正在nesting）；

当前nesting值（等于当前时间值减去`nestingStarted`时间值）；

total总值（等于当前nesting值加上`nestingTotal`）；

    uint256 private nestingTransfer = 1;
    
    function safeTransferWhileNesting(
        address from,
        address to,
        uint256 tokenId
    ) external {
        require(ownerOf(tokenId) == _msgSender(), "Moonbirds: Only owner");
        nestingTransfer = 2;
        safeTransferFrom(from, to, tokenId);
        nestingTransfer = 1;
    }
    

这里定义了一个`safeTransferWhileNesting`函数，NFT拥有者可以将正在nesting中的Moonbirds手动转移到另一个钱包地址，可用于owner进行NFT个人钱包转移或定向赠送，而不影响nesting值；

    function _beforeTokenTransfers(
        address,
        address,
        uint256 startTokenId,
        uint256 quantity
    ) internal view override {
        uint256 tokenId = startTokenId;
        for (uint256 end = tokenId + quantity; tokenId < end; ++tokenId) {
            require(
                nestingStarted[tokenId] == 0 || nestingTransfer == 2,
                "Moonbirds: nesting"
            );
        }
    }
    

这里override了ERC721A标准中的`_beforeTokenTransfers`函数，使ERC721A标准的`_transfer`功能被调用时增加了一个`nestingStarted`必须等于0的条件，因此正在nesting中的Moonbirds无法被调用`_transfer`功能，也就无法在marketplace中进行交易，或被其他外部智能合约调用转移（比如即使误点了钓鱼偷盗网站，Moonbirds也无法被盗走，形成锁定与保护作用）；

    event Nested(uint256 indexed tokenId);
    
    event Unnested(uint256 indexed tokenId);
    
    event Expelled(uint256 indexed tokenId);
    

三个参数信息输出，用于将某一个tokenId的nest情况传至链下；

    bool public nestingOpen = false;
    
    function setNestingOpen(bool open) external onlyOwner {
        nestingOpen = open;
    }
    

智能合约owner启动nesting功能；

    function toggleNesting(uint256 tokenId)
        internal
        onlyApprovedOrOwner(tokenId)
    {
        uint256 start = nestingStarted[tokenId];
        if (start == 0) {
            require(nestingOpen, "Moonbirds: nesting closed");
            nestingStarted[tokenId] = block.timestamp;
            emit Nested(tokenId);
        } else {
            nestingTotal[tokenId] += block.timestamp - start;
            nestingStarted[tokenId] = 0;
            emit Unnested(tokenId);
        }
    }
    

这里为Nesting开关功能函数，`nestingStarted`等于0时，调用此function即开启nesting并记录`nestingStarted`值为当前时间值；`nestingStarted`不等于0时，更新`nestingTotal`值（等于原总累积值加上当前时间值减去`nestingStarted`开始时间值），并将`nestingStarted`重置为0，即停止了nesting；

    function toggleNesting(uint256[] calldata tokenIds) external {
        uint256 n = tokenIds.length;
        for (uint256 i = 0; i < n; ++i) {
            toggleNesting(tokenIds[i]);
        }
    }
    

批量Nesting开关，可为一个array的tokenId进行`toggleNesting`函数调用；

    function expelFromNest(uint256 tokenId) external onlyRole(EXPULSION_ROLE) {
        require(nestingStarted[tokenId] != 0, "Moonbirds: not nested");
        nestingTotal[tokenId] += block.timestamp - nestingStarted[tokenId];
        nestingStarted[tokenId] = 0;
        emit Unnested(tokenId);
        emit Expelled(tokenId);
    }
    

这里定义了`expelFromNest`功能函数，让智能合约管理员拥有关闭某个tokenId的nesting的权力，但已经nesting的记录值会得以保留。

总结：Moonbirds通过对智能合约进行原创开发，实现了NFT功能的创新，展示了项目方的技术能力；nesting功能的存在，不仅有效保护了NFT的安全，降低被盗风险，又在不移出owner钱包的基础上进行了某种类staking操作，增加了长期持有者的潜在收益可能，为钻石手提供动力，也在一定程度上抑制了卖盘，从而抬高了NFT二级市场价格。

JCONE.eth

2022/4/18

---

*Originally published on [JCONE](https://paragraph.com/@jcone/moonbirds-smart-contract-nesting)*
