实现 CLG 合约的关键创新是代币访问控制。代币访问控制背后的概念是,除非你用含有特定访问代币的钱包连接到主机,否则你不能访问主机上的特定数据。
例如,你可以对 IPFS 上的内容进行代币访问控制,这样只有用钱包中的特定 NFT 连接到端点的读者才能查看特定的文件。
CLG 使用令牌门为我们的社交合约增加了一些间接性,因此,社交 NFT 不是代表一种特定类型的关系--关注、静音或屏蔽--而是代表对你的社交图谱的一部分的读取权限。
很明显,为了使代币门槛发挥作用,平台必须尊重它。据推测,如果平台不尊重代币访问控制,你会把你的关系列表转移到其他平台,并改变你的合约,必要时重新发布任何 NFT。
另外,要清楚的是,有些人的名单在某些时候会泄露。我们生活在一个个人数据泄露的世界,所以如果数据被托管在某个地方,那么有些数据就会被泄露。我将在后面的章节中讨论一些可能的缓解措施。下面的合约将是一个标准的 ERC721 NTFT 合约,与上述 OCG 的合约非常接近:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; contract CLGFollows is ERC721, Pausable, Ownable, ERC721Burnable { using Counters for Counters.Counter; Counters.Counter private _tokenIdCounter; constructor() ERC721("CLGFollows", "CLGF") {} function _baseURI() internal pure override returns (string memory) { return "https://jonstokes.com/clgfollows/"; } function listURI() public { return "https://jonstokes.com/clgfollows/list"; } function relationship() public { return "clg follows"; } function pause() public onlyOwner { _pause(); } function unpause() public onlyOwner { _unpause(); } function safeMint(address to) public onlyOwner { uint256 tokenId = _tokenIdCounter.current(); _tokenIdCounter.increment(); _safeMint(to, tokenId); } function _beforeTokenTransfer(address from, address to, uint256) pure override internal { //Disable token transfers. require(from == address(0) || to == address(0), "Cannot be transferred."); } }
所有的扩展都与 OCG 相同,只是我没有包括 ERC721Enumerable,因为不清楚是否有人想让他们的 CLG Follows 代币被列举出来(另外它提高了铸币的 gas 成本)
至于函数方面,我对OpenZeppelin向导的输出做了以下修改:
relationship(): 与 OLG 一样,它返回社交合约的类型。同样,对于 Solidity 合约来说,这可能没有必要,我也没有见过这样做,但尽管如此,我觉得我想让合约自我报告它的类型。所以我不知道--如果这冒犯了你,请忽略。
listURI() 返回一个指向 JSON 对象的链接,该对象是你正在关注(或静音或屏蔽,取决于合约类型)的 ENS 名称列表。我们希望这个 URI 能被标记为隐私,但这并不是必须的。
大多数情况下,你会使用 CLG Follows NTFT,把它发布到社交平台拥有的地址。这样,该平台可以读取你的关注列表,并向你展示正确的帖子。
但你也可以把这些 NTFTs 发给追随者,以便你的追随者可以发现其他追随者。你可以通过空投给追随者,或者通过解禁造币,让任何人造币来实现。
所有其他合约的工作方式与上述完全相同,但有不同的名称和符号,并从 relationship() 和 listURI() 返回不同的值。如果你担心你的列表从不同的服务中泄漏,那么把 listURI() 变成更像 tokenURI(uint256 tokenId) 的东西是非常直接的,即签名是 listURI(uint256 tokenId),它把 tokenID 连接到一个基本URI的末尾,这样每个 token 持有者就可以得到自己的列表URL。这个功能与列表主机上的一些逻辑相结合,可以让你把列表隔离开来,使不同的令牌持有者得到主图的不同子图。这样一来,如果一个平台被拥有,那么只有我的图的那一部分被泄露了。
和 OCG 一样,你可以把 safemint 变成一个可支付的函数,并向访问你的列表的人收费。请看 OCG 部分的代码,以了解这个例子的情况。
你可能希望能够更新 tokenURI() 和 / 或 listURI() 返回的 URLs,在这种情况下,你需要将这些 URLs 存储在变量中,在构造函数中初始化它们,并为更新它们提供 onlyOwner setter 函数。这将增加你的铸币成本,但如果你只打算把它们给服务而不是个人,这可能并不重要。
