Xing

Posted on Dec 25, 2021Read on Mirror.xyz

SOS项目学习记录

上一篇关于Render Network的学习记录分享,被很多人转发点赞,也让我这个nobody涨粉接近1000,也激发了我今天在遛娃完之后,继续给大家分享我的这篇学习记录。

学习一个项目比较快就可以完成,但是把学习内容分享给大家需要花费不少时间梳理,大家的关注给了我继续分享的动力,这里谢谢各位。

惯例申明,本文只是本人的学习记录分享,不构成任何投资建议。

SOS项目简介

这个项目很真诚,没有一些高大上概念的包装。目的也很明确,感谢OpenSea的用户对NFT行业的支持,所以给OpenSea的用户空投 $SOS 币,同时会用$SOS币为NFT事业的发展贡献力量。

$SOS的分配

  • 发行总量:100 trillion

    100,000,000,000,000,这个是我手打的数字。大家数下多少0,又是一场消零运动

  • 50%分配给空投用户

    如何分配参考下文的空投规则

  • 20%作为质押激励

    参考下文的合约分析

  • 20%留给OpenDAO

    这部分$SOS会用作:

    • 补偿在OpenSea上被诈骗的用户
    • 支持创作者
    • 支持NFT社区
    • 支持艺术保护
    • 授予参与$SOS生态的开发者
  • 10%作为流动性提供者的激励

    参考下文的合约分析

空投规则

该项目同步了OpenSea的链上交易记录,用户连接钱包之后,会根据用户在OpenSea的交易数据计算出可以领到(claim)的$SOS。大概的计算原则如下:

花费的钱(ETH、DAI、USDC)占70%的权重;产生的交易次数占30%的权重。

由于本人比较穷,没在opensea上买过NFT,所以无法计算具体最终可以拿到的$SOS个数。空投代币领取数量的具体计算公式在官网合约中也都未找到(参考下文的合约分析),不过总的原则是在OpenSea上交易的金额及次数越多,拿到的$SOS代币奖励也就越多。

合约分析

项目合约比较简单明了,就是ERC20的token合约加了一个claim(领取空投)的方法。

contract OpenDAO is ERC20, EIP712 {
    uint256 public constant MAX_SUPPLY = uint248(1e14 ether);

    // for DAO.
    uint256 public constant AMOUNT_DAO = MAX_SUPPLY / 100 * 20;
    address public constant ADDR_DAO = 0x06bB1467b38d726b3eb39eB2FBAE6021feAE935F;

    // for staking
    uint256 public constant AMOUNT_STAKING = MAX_SUPPLY / 100 * 20;
    address public constant ADDR_STAKING = 0x7d28988391034A4C756f0c3E1A3E033175B04C77;

    // for liquidity providers
    uint256 public constant AMOUNT_LP = MAX_SUPPLY / 100 * 10;
    address public constant ADDR_LP = 0x709CD2aAAe592930616720115b6a3Dbdf1407664;

    // for airdrop
    uint256 public constant AMOUNT_AIREDROP = MAX_SUPPLY - (AMOUNT_DAO + AMOUNT_STAKING + AMOUNT_LP);

    constructor(string memory _name, string memory _symbol, address _signer) ERC20(_name, _symbol) EIP712("OpenDAO", "1") {
        _mint(ADDR_DAO, AMOUNT_DAO);
        _mint(ADDR_STAKING, AMOUNT_STAKING);
        _mint(ADDR_LP, AMOUNT_LP);
        _totalSupply = AMOUNT_DAO + AMOUNT_STAKING + AMOUNT_LP;
        cSigner = _signer;
    }

    bytes32 constant public MINT_CALL_HASH_TYPE = keccak256("mint(address receiver,uint256 amount)");

    address public immutable cSigner;

    function claim(uint256 amountV, bytes32 r, bytes32 s) external {
        uint256 amount = uint248(amountV);
        uint8 v = uint8(amountV >> 248);
        uint256 total = _totalSupply + amount;
        require(total <= MAX_SUPPLY, "OpenDAO: Exceed max supply");
        require(minted(msg.sender) == 0, "OpenDAO: Claimed");
        bytes32 digest = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", 
            ECDSA.toTypedDataHash(_domainSeparatorV4(),
                keccak256(abi.encode(MINT_CALL_HASH_TYPE, msg.sender, amount))
        )));
        require(ecrecover(digest, v, r, s) == cSigner, "OpenDAO: Invalid signer");
        _totalSupply = total;
        _mint(msg.sender, amount);
    }
}

可以看到合约初始化的时候,就按照上述的分配比例对总数100 trillion的代币进行分发。需要注意两个部分:

  • 初始分配

    官网对$SOS的分配比例中,20%作为质押的激励,10%作为流动性提供者的激励。在上述合约初始化的时候这两部分的$SOS分别进入了两个钱包地址0x7d28988391034A4C756f0c3E1A3E033175B04C770x709CD2aAAe592930616720115b6a3Dbdf1407664。加上OpenDAO自己保留的20%比例,相当于目前OpenDAO保管了50%总发行量的代币

  • 奖励代币数量计算

    合约中claim()方法就是用户去领取空投所调用的方法。这个方法需要传入领取空投的数量,以及项目方的签名信息。签名信息通过项目方地址(cSigner)校验通过后,就能够给用户发送$SOS空投奖励。上文说到用户能够领取多少$SOS的空投,具体的计算方法并没有公开。所以理论上,保管cSigner这个地址私钥的人可以向任何人空投任意数量的$SOS。注意我说的是理论上!

项目特色

这个项目最巧妙的一点就是吸引了OpenSea上的大量优质客户。要知道能得到$SOS越多的用户,都是在OpenSea上挥金如土的大佬(顺便说一句本人的梦想就是可以买个CryptoPunk),这些大佬会给OpenDAO带来不少资源,例如市场推广、上交易所等等,相当于项目启动就把大佬们的资源整合到一块了,含着金钥匙出生。