# 深入分析Friend.Tech项目

By [cryptonora.eth](https://paragraph.com/@cryptonora) · 2024-05-09

---

Friend.Tech是一个新兴的区块链社交平台，在短时间内引起了广泛关注；该平台的注册需要绑定X(twitter) 账户，每个账户都有其「社交价值」，可以购买自己和别人的账户股权，当你持有别人账户的股权时，就可以和此账户聊天。

**本文仅从技术层面分析下** [**friend.tech**](https://link.zhihu.com/?target=http%3A//friend.tech) **项目，不构成任何投资建议**。

friend.tech是Base链上的的SocialFi项目，在Base浏览器上可以找到项目的[合约代码](https://link.zhihu.com/?target=https%3A//basescan.org/address/0xCF205808Ed36593aa40a44F10c7f7C2F67d4A4d4%23code)：

合约名称：**FriendtechSharesV1**

合约地址：**0xCF205808Ed36593aa40a44F10c7f7C2F67d4A4d4**

### **主要变量**

    address public protocolFeeDestination; // 协议收费地址
    uint256 public protocolFeePercent; // 协议收费比率
    uint256 public subjectFeePercent; // 股权持有者收费比率
    

每次买入卖出一个账户的股权（key），账户和项目方都要收手续费，目前根据链上数据可知手续费都是5% 。

[https://basescan.org/tx/0x98e5b449b3545a0d35f683f3df9c7b7658a0ece7a8ec479c946ebdbde2315814](https://basescan.org/tx/0x98e5b449b3545a0d35f683f3df9c7b7658a0ece7a8ec479c946ebdbde2315814)

### **事件**

    event Trade(address trader, address subject, bool isBuy, uint256 shareAmount, uint256 ethAmount, uint256 protocolEthAmount, uint256 subjectEthAmount, uint256 supply);
    

每次买卖行为都会触发交易事件，交易事件记录了买方和卖方的地址，买入 key 的数量和使用的 eth 数量，以及收取的手续费和交易后 key 的供应量。 可以在区块中监听此事件来进行链上数据分析。

### **获取价格**

    function getPrice(uint256 supply, uint256 amount) public pure returns (uint256) {
        uint256 sum1 = supply == 0 ? 0 : (supply - 1 )* (supply) * (2 * (supply - 1) + 1) / 6;
        uint256 sum2 = supply == 0 && amount == 1 ? 0 : (supply - 1 + amount) * (supply + amount) * (2 * (supply - 1 + amount) + 1) / 6;
        uint256 summation = sum2 - sum1;
        return summation * 1 ether / 16000;
    }
    

其中 supply 表示 key 的供应量，amount 表示要交易的 key 数量。可以从公式中看到当买 key 的第一个份额是免费的（合约要求 key 的拥有账户才能买第一个份额）。

对于 sum1 和 sum2 的计算用到了前 n 个数的平方和公式： 推导见[这里](https://link.zhihu.com/?target=https%3A//www.bilibili.com/video/BV1QS4y1i7hz/%3Fvd_source%3D97409223eab1f5918d64a93735c63e46)。

(1)𝑠𝑢𝑚=𝑛⋅(𝑛+1)⋅(2𝑛+1)6

对于价格的计算：

(2)𝑝𝑟𝑖𝑐𝑒=summation16000×1ether

假设 amount 为1，则 summation = sum2 - sum1 = n^2：

(3)𝑝𝑟𝑖𝑐𝑒=𝑛216000×1ether

后面乘 1ether 是使用因子使结果转换为 wei，可以简化为：

(4)𝑝𝑟𝑖𝑐𝑒=𝑛216000

这就是项目的经济模型，即 Price in ETH = supply^ 2 / 16000。在 [friend.tech](https://link.zhihu.com/?target=http%3A//friend.tech) 的交互中也验证了这一点。

### **经济模型**

每组key的价格都会随着持有人的增加而呈现“指数增长”，所以当key被购买或者出售时，key 的价格都会产生波动。price = supply^2 是一个指数函数，而 16000 只是为了使价格增长平缓一点，从而更符合市场的匹配关系。

[https://onedrive.live.com/view.aspx?resid=C078415A103A3F40%211094&authkey=!ANE0-sqb5hAftiI\\](https://onedrive.live.com/view.aspx?resid=C078415A103A3F40%211094&authkey=!ANE0-sqb5hAftiI%5C)\*

随着发行股份总量的不断增长，买卖股份之间的价差净值会越来越大，但价差率（价差/卖价）会越来越小。价差存在的原因并不复杂，股份的增长是从 0 开始，因而必然是先有买后有卖，卖方总是要落后于买方的。在如下函数中体现：

    function getBuyPrice(address sharesSubject, uint256 amount) public view returns (uint256) {
        return getPrice(sharesSupply[sharesSubject], amount);                      
    }                                                                              
    
    function getSellPrice(address sharesSubject, uint256 amount) public view returns (uint256) {
        return getPrice(sharesSupply[sharesSubject] - amount, amount);             
    }
    

可以看出买 key 时候的 supply 是当前 key 的供应量，而卖 key 时的 supply=当前的供应量-卖出的数量；

不同供应量对应的价格关系：

[https://onedrive.live.com/view.aspx?resid=C078415A103A3F40%211094&authkey=!ANE0-sqb5hAftiI](https://onedrive.live.com/view.aspx?resid=C078415A103A3F40%211094&authkey=!ANE0-sqb5hAftiI)

使用公式进行验证，假设某个 key 的供应量为 supply=100, 购买量为 amount=1, 计算价格：

𝑠𝑢𝑚1=(100−1)⋅100⋅(2⋅(100−1)+1)6=328350𝑠𝑢𝑚2=100⋅101⋅(2⋅100+1)6=338350

summation = sum2 - sum1 = 10000，则价格为：

price=summation×1 ether16000=10000×116000=0.625

[https://www.desmos.com/calculator/clnecohl2s](https://www.desmos.com/calculator/clnecohl2s)

### **购买**

    function buyShares(address sharesSubject, uint256 amount) public payable {   
        uint256 supply = sharesSupply[sharesSubject]; 
        // 要求key的拥有账户购买第一个份额                          
        require(supply > 0 || sharesSubject == msg.sender, "Only the shares' subject can buy the first share");
        uint256 price = getPrice(supply, amount);   
        // 计算协议收取的手续费                            
        uint256 protocolFee = price * protocolFeePercent / 1 ether;    
        // 计算key拥有者账户收取的手续费         
        uint256 subjectFee = price * subjectFeePercent / 1 ether;   
        // 检查交易金额            
        require(msg.value >= price + protocolFee + subjectFee, "Insufficient payment");
        // 更新购买者的持有量
        sharesBalance[sharesSubject][msg.sender] = sharesBalance[sharesSubject][msg.sender] + amount;
        // 更新key的供应量
        sharesSupply[sharesSubject] = supply + amount;
          // 触发交易事件                          
        emit Trade(msg.sender, sharesSubject, true, amount, price, protocolFee, subjectFee, supply + amount);
        // 转账手续费给协议账户
        (bool success1, ) = protocolFeeDestination.call{value: protocolFee}("");
        // 转账手续费给key的拥有者账户
        (bool success2, ) = sharesSubject.call{value: subjectFee}("");          
        require(success1 && success2, "Unable to send funds");                  
     }
    

### **售出**

    function sellShares(address sharesSubject, uint256 amount) public payable { 
        uint256 supply = sharesSupply[sharesSubject]; 
        // 检查购买量                          
        require(supply > amount, "Cannot sell the last share");                 
        uint256 price = getPrice(supply - amount, amount);
        // 计算协议收取的手续费                      
        uint256 protocolFee = price * protocolFeePercent / 1 ether;  
        // 计算key拥有者账户收取的手续费           
        uint256 subjectFee = price * subjectFeePercent / 1 ether;  
        // 检查交易金额               
        require(sharesBalance[sharesSubject][msg.sender] >= amount, "Insufficient shares");
        // 更新购买者的持有量
        sharesBalance[sharesSubject][msg.sender] = sharesBalance[sharesSubject][msg.sender] - amount;
        // 更新key的供应量
        sharesSupply[sharesSubject] = supply - amount;   
        // 触发交易事件                       
        emit Trade(msg.sender, sharesSubject, false, amount, price, protocolFee, subjectFee, supply - amount);
        // 转账售卖收入到卖出者钱包
        (bool success1, ) = msg.sender.call{value: price - protocolFee - subjectFee}("");
        // 转账手续费给协议账户
        (bool success2, ) = protocolFeeDestination.call{value: protocolFee}("");
        // 转账手续费给key的拥有者账户
        (bool success3, ) = sharesSubject.call{value: subjectFee}("");          
        require(success1 && success2 && success3, "Unable to send funds");      
    }
    

从购买和售出函数中可以看出在 Trade 事件函数签名中，供应量 supply 是当次交易之后的 key 供应量，在做链上数据分析时注意甄别。

### **总结**

本文撰写时 [friend.tech](https://link.zhihu.com/?target=http%3A//friend.tech) 项目的链上数据：

[https://dune.com/cryptokoryo/friendtech](https://dune.com/cryptokoryo/friendtech)

截至 12 月 19 日 18: 00 ，friend.tech交易量已超过 1.5 万 ETH，累计完成了超过 1247万笔交易。在深入探讨了friend.tech 项目的智能合约逻辑和经济模型后，可以看到这个项目在 Web3 领域展现出了显著的创新性和潜力。通过巧妙地结合区块链技术和社交媒体的动态，friend.tech不仅为用户提供了一个独特的交互平台，还开辟了一条新的路径，能够在去中心化环境中实现社交影响力的货币化。不过从10月开始交易量逐渐减少，也标示着项目的热度的逐渐降低，决定其产品是否可持续的因素是有影响力的用户是否愿意持续经营以创造价值，并最终转化为向外的能量，最终形成破圈效应。期待其后续的表现，期待更多的 SocialFi 赛道优质项目。

**声明：本文只做技术分享，不构成任何投资建议。**

---

*Originally published on [cryptonora.eth](https://paragraph.com/@cryptonora/friend-tech)*
