智能公器

智能公器(Smart Common)是指遵循 SCC0 许可协议、拥有自己的估值通证、能够让其开发者基于 PoV 价值证明获得奖励的智能创造公共物(包括dApp、EIPs、AI、论文、技术标准等)。

在道易程网站上,为简化使用,菜单"工作室"同时也是开发者对其公器的版本及其所获奖金进行管理的入口。

{
    {
        string name; // Smart Common 名称,唯一,不能与其它Smart Common同名.
        string symbol; // Smart Common 代币名称,唯一,不能与其它Smart Common代币同名
        string desc; // Smart Common 描述
        address manager; // Smart Common 管理员
        uint16 version; // Smart Common 版本号,mint 时从1开始
        string SC_Type // Smart Common 的类型
    },
    address[] calldata _members, //成员列表
    uint16[] calldata _dividendRights, // 成员票权(分红权),与_members 一一对应
    uint16 _strategy,  //提案投票通过率.百分之百(全票通过)是2的16次方减1(65535), 可以通过提案更改此值
    uint32 _lifetime, //提案存活时间,以秒为单位,提案从创建开始计时,经过该时间后没有完成的就作废
    uint32 _coolingPeriod // 提案冷却时间,单位是秒,从提案创建开始计时,要经过该数值的时间后才能建新的提案.特别注意:冷却时间必须大于存活时间
    {
        string filetype  // logo 的后缀名, 只能是svg
        string fileContent // svg 的纯文本内容
    }
}

如果你的智能合约是一个 EIP 或者一篇论文,可先阅读《将 PoV 价值证明应用到 EIPs 或者 AI 等领域》了解PoV价值证明带来的奖励机制。并且:

  • 我们建议将 EIP 或论文以 HTML 源码写在智能合约里:
    function eipContent() external view returns(string memory);
  • 如果是一个已经通过github发表了的EIP,譬如ERC-2569,可以不要以上 EIP 的 HTML 源码而以一个链接替代 EIP 的内容。如这个地址可以是https://eips.ethereum.org/EIPS/erc-2569。同时,请作者在原EIP里补充一个和写在智能合约里的owner地址完全相同的地址。如下:
    owner = 这里写入一个以太坊帐户(地址)
  • 非dApp类的智能公器,在Mint时都要注意其专属的估值通证的命名方法。相关内容在本文底部

如何在道易程上Mint一个智能公器

  • dapp类的智能公器只有 智能合约 的所有者(owner)才能 mint 智能公器,所以 mint 智能公器前,要先部署好自己的智能合约。
  • Mint智能公器的合约可以是某个 dApp 中的任何你指定的智能合约。需要特别注意的是,每个合约地址仅有权限创建一个智能公器。
  • 非dapp 类的智能公器不需要部署合约。
  • Mint 智能公器时,你还可以同时 Mint 任意套数的荣誉通证(一种纪念你的智能公器诞生的NFT)。所谓套数,是指其数量可以是你的智能公器分红成员的N倍。请注意你的智能合约里,要事先写好调用相关接口的合约代码。

请注意:因以太坊gas非常昂贵,建议 logo 在2K以下,并且只能为 SVG 矢量图形。

智能公器的合约示例

    // SPDX-License-Identifier: MIT 
    pragma solidity ^0.8.20;
    contract ThreeDapp {
        address public owner;
    
        constructor(){
            owner = tx.origin;
        }
        
        function ownerOf() public view returns(address){
            return owner;
        }
    }

利用hardhat发布并 mint Smart Common 示例

const fs=require('fs')
const { ethers } = require('hardhat')

async function main(){
    await hre.run('compile');
    const [owner] = await ethers.getSigners();
    // dapp合约名称,请换成你的合约
    const contractName = 'ThreeDapp';
    //SC 注册器地址,请换成最新的地址,网页上mint智能公器窗口中的示例代码中是最新的
    const daismRegistrar_='0x3Bf70f9BfCfF20a90f0F36bAAF0d5afc3Ee232b7' ;
    // 荣誉通证合约地址,请换成最新的地址,网页上mint智能公器窗口中的示例代码中是最新的
    const daismHonorTokens_='0xC473f79875F202D15b128f2a40dff7e35B972Fc4' ;
    //发布dapp 合约, ThreeDapp 是自己的合约,符合道易程的要求 
    //注:一个dApp 只能mint 一次, 所以在此需要重新发布一个新的dApp
    const dappContract = await daism_deploy(owner,contractName,[])
    let registerAbi=[
        {"inputs": 
          [
            {
              "components": [
                {"internalType": "string","name": "name","type": "string"},
                {"internalType": "string","name": "symbol","type": "string"},
                {"internalType": "string","name": "desc","type": "string"},
                {"internalType": "address","name": "manager","type": "address"},
                {"internalType": "uint16","name": "version","type": "uint16"},
                {"internalType": "string","name": "SCType","type": "string" }
              ],
              "internalType": "struct SCInfo","name": "_SCInfo","type": "tuple"
            },
            {"internalType": "address[]","name": "_members","type": "address[]"},
            {"internalType": "uint16[]","name": "_dividendRights","type": "uint16[]"},
            {"internalType": "uint16","name": "_strategy","type": "uint16"},
            {"internalType": "uint32","name": "_lifetime","type": "uint32"},
            {"internalType": "uint32","name": "_coolingPeriod","type": "uint32"},
            {
              "components": [
                {"internalType": "string","name": "fileType","type": "string"},
                {"internalType": "string","name": "fileContent","type": "string"}
              ],
              "internalType": "struct File","name": "_logo","type": "tuple"
            },
            {"internalType": "bytes","name": "_data","type": "bytes"}
          ],
      "name": "createSC",
      "outputs": [{"internalType": "uint256","name": "","type": "uint256"}],
      "stateMutability": "nonpayable",
      "type": "function"
    }]
    const registerContract = new ethers.Contract(daismRegistrar_, registerAbi, owner)
    //道易程的SC(见上面的结构描述), 注:名称和代币名称 不允许重复
    let SCinfo=["scname5", "scsymbol5","scdesc5",await dappContract.getAddress(),1,'dapp']
    let res= await registerContract.createSC(   
        SCinfo,
        [owner.address], //成員列表
        [10], // 成員票權(分紅權),不能為1,2,3,4,因為這四個數有特殊用途
        (2 ** 16-1).toString(),  //提案投票通過率,百分之分(全票)
        7 * 24 * 3600, //壽命期為7天
        9 * 24 * 3600, //冷卻期九天
        [
        'svg',
        'ok' //svg的实际内容
        ],
        '0x'  //0x 表示不mint  荣誉通证
    )
  console.log('createSC hash: '+res.hash)
  await res.wait()
  console.log("createSC success")

   //EIP 类,同时 mint 荣誉通证
    let mintNum=1  //mint  份数
    let abicoder=new ethers.AbiCoder()
    //打包荣誉通证的owner列表及份数 
    let functionData=abicoder.encode(['address[]','uint256'],[[owner.address],mintNum])
    //打包荣誉通证合约地址及参数
    let paras=abicoder.encode([ "address", "bytes" ], [daismHonorTokens_, functionData ]);

  SCinfo=["scname6", "scsymbol6","scdesc6",await dappContract.getAddress(),1,'EIP']
  res= await registerContract.createSC(   
     SCinfo,
     [owner.address], //成員列表
     [10], // 成員票權(分紅權),不能為1,2,3,4,因為這四個數有特殊用途
     (2 ** 16-1).toString(),  //提案投票通過率,百分之分(全票)
     7 * 24 * 3600, //壽命期為7天
     9 * 24 * 3600, //冷卻期九天
     [
     'svg',
     'ok' //svg的实际内容
     ],
     paras
 )
console.log('createSC hash: '+res.hash)
await res.wait()
console.log("createSC success")

  console.log("--------------END--------------")
}

//发布合约
async function daism_deploy(signer,contractName,paras=[]){
  const factory = await ethers.getContractFactory(contractName,signer)
  const product = await factory.deploy.apply(factory,paras)
  await product.waitForDeployment()
  const contract_address=await product.getAddress()
  console.log('部署: '+contractName+' : '+contract_address)
  return await ethers.getContractAt(contractName,contract_address,signer)
}

main()
.then(() => process.exit(0))
.catch((error) => {
  console.error(error);
  process.exit(1);
});

网页 Mint 智能公器示例

首先发布能够调用 mint 智能公器的合约的智能合约(如你的dApp)。 并取提该智能合约或dApp的发布地址。

网页上填写相应信息并mint, 见下图:

估值通证的命名

我们借鉴了Unix操作系统和Windows里通用的方法(相关文档可查阅微软的“命名文件、路径和命名空间”),即:

  • 智能公器的分类体现在估值通证的扩展名上。
  • 估值通证的命名部分借鉴电脑操作系统的方法,即以”.“分成两部分:
    1. 估值通证的命名规则,为”XXXX.扩展名“。如:UL.eip(表明其智能公器是一个 EIP)。或者:ALOHA.ai(表明其为一个 AI 项目😂)。扩展名建议小写,以使得前面的名称更突出。任何人都可以任意设置其智能公器的扩展名——这是一种去中心化的命名规范。当然,如果其他人已经对某个分类做了没有瑕疵的命名,那么希望后面的开发者们能够沿用。
    2. 文件名是大小写不敏感。但前端会显示大小写。
    3. 扩展名不可为空。
    4. 扩展名只增加,不删除。
    5. 扩展名的修改,实际可能是新增,也可能是另选已经存在的另一个扩展名。
    6. 谁主张修改,谁迁移——如果某个智能公器的开发者决定修改其估值通证的扩展名,实际上是他新增了一个扩展名,或者是迁移到另一个已经存在的扩展名,然后他的智能公器就被划分到新的分类里。但原扩展名并没有被删除。这样之前主动加入到原分类(原扩展名)里的其它智能公器,就完全没有受到影响。
    7. 扩展名的调整,要通过提案来表决。
    8. (前端)已经存在的扩展名,在用户填写时,自动成为可选项。一旦选择,就会出现该扩展名的描述。这样就能避免不同的分类使用同一扩展名。
    9. (前端)扩展名的命名是去中心化的,没有限制。但考虑到越容易记住越好,还是要建议用户尽量使用简单易记的名称,即尽量使用英文字母和数字来命名估值通证。一般不建议在文件名中包含特殊字符。