智能公器
智能公器(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一個智能公器
- 只有 智能合約 的所有者(owner)才能 mint 智能公器,所以 mint 智能公器前,要先部署好自己的智能合約。
- Mint 智能公器的合約可以是某個 dApp 中的任何你指定的智能合約。需要特別註意的是,每個合約地址僅有權限創建一個智能公器。
- Mint 智能公器時,你還可以同時 Mint 任意套數的榮譽通證(一種紀念你的智能公器誕生的NFT)。所謂套數,是指其數量可以是你的智能公器分紅成員的N倍。請註意你的智能合約裏,要事先寫好調用相關接口的合約代碼。
請註意:因以太坊gas非常昂貴,建議 logo 在2K以下,並且只能為 SVG 矢量圖形。
智能公器的合約示例
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../interfaces/IDAismInterface.sol";
contract ThreeDapp {
address public daismRegistrar;
address public nftAddress;
address public owner;
constructor(address daismRegistrar_,address nftAddress_){
require(daismRegistrar==address(0)&&nftAddress==address(0));
daismRegistrar = daismRegistrar_;
nftAddress = nftAddress_;
owner = tx.origin;
}
function ownerOf() public view returns(address){
return owner;
}
function mintSCandNFT(
IDAismInterface.SCInfo memory _SCInfo,
address[] calldata _members,
uint16[] calldata _dividendRights,
uint16 _strategy,
uint32 _lifetime,
uint32 _coolingPeriod,
IDAismInterface.File memory _logo,
uint256 _num
) public returns(uint256[][] memory){
uint256 scId = IDAismInterface(daismRegistrar).createSC(_SCInfo, _members, _dividendRights, _strategy, _lifetime, _coolingPeriod, _logo);
return IDAismInterface(nftAddress).mintBatch(scId, _members, _num);
}
function createSC(
IDAismInterface.SCInfo memory _SCInfo,
address[] calldata _members,
uint16[] calldata _dividendRights,
uint16 _strategy,
uint32 _lifetime,
uint32 _coolingPeriod,
IDAismInterface.File memory _logo
) external returns(uint) {
return IDAismInterface(daismRegistrar).createSC(_SCInfo, _members, _dividendRights, _strategy, _lifetime, _coolingPeriod, _logo);
}
}
//IDAismInterface 接口
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface IDAismInterface {
struct SCInfo {
string name; // The name of the SC.
string symbol; // The symbol of the SC.
string desc; // The description of the SC.
address manager; // The address of the SC manager.
uint16 version; // The version of the SC.
string SC_Type;
}
struct File{
string fileType;
string fileContent;
}
function creator(uint256 _scId) external view returns (address);
function SCLogo() external view returns(address);
function SCInfos(uint SC_id) external view returns (SCInfo memory);
function getLogo(uint SC_id) external view returns (File memory);
function ownerOf() external view returns(address);
function toProxy(uint256 _scId) external view returns (address);
function createSC(
SCInfo memory _SCInfo,
address[] calldata _members,
uint16[] calldata _dividendRights,
uint16 _strategy,
uint32 _lifetime,
uint32 _coolingPeriod,
File memory _logo
) external returns(uint) ;
function mintBatch(uint256 _scId, address[] calldata _to, uint256 _num) external returns(uint256[][] memory);
}
利用hardhat發布並 mint Smart Common 示例
const fs=require('fs')
const { ethers } = require('hardhat')
async function main(){
await hre.run('compile');
const [owner] = await ethers.getSigners();
// 合約名稱 /請換成你的合約
const contractName = 'ThreeDapp';
//請換成最新的地址,當前使用的地址在mint 智能公器窗口的示例代碼中
const daismRegistrar_='0x4E0430f2ad966861846245340b1bA64b829AA069' ;
//請換成最新的地址,當前使用的地址在mint 智能公器窗口的示例代碼中
const nftAddress_ ='0xDcf063A9E95318e0Abf8dAAAC1f146ad83C844d8';
//發布合約
const contractObj1 = await daism_deploy(owner,contractName,[daismRegistrar_,nftAddress_]);
// mint 道易程的 Smart Common
let res= await contractObj1.createSC(
['名稱1', '代幣名稱1','描述1', owner.address,1,'dApp'], //道易程的SC(見上面的結構描述), 註:名稱和代幣名稱 不允許重復
[owner.address], //成員列表
[10], // 成員票權(分紅權),不能為1,2,3,因為這三個數有特殊用途
(2 ** 16-1), //提案投票通過率,百分之分(全票)
7 * 24 * 3600, //壽命期為7天
9 * 24 * 3600, //冷卻期九天
['svg','<svg fill="#f7861c" height="24" viewBox="113.789 0 24.088 24" width="24.088" xmlns="http://www.w3.org/2000/svg"><path d="M134.613 6.85h-3.499l-2.035-2.009-.006-.006-.004-.003a1.698 1.698 0 00-1.189-.482h-4.23c-.491 0-.93.209-1.238.539l-.003-.005-1.991 1.966h-3.571c-.935 0-1.691.747-1.691 1.667v10c0 .92.757 1.668 1.691 1.668h17.768a1.68 1.68 0 001.691-1.668v-10a1.682 1.682 0 00-1.693-1.667zm.846 11.668a.843.843 0 01-.846.834h-17.768a.841.841 0 01-.846-.834v-10c0-.459.38-.833.846-.833h3.922l.248-.245 1.024-1.011.021.062.971-1.035a.843.843 0 01.618-.271h4.23c.223 0 .435.086.602.247l2.033 2.008.247.245H134.613c.465 0 .846.374.846.833z"/><path d="M125.729 9.351c-2.104 0-3.808 1.678-3.808 3.749 0 2.072 1.703 3.752 3.808 3.752 2.104 0 3.808-1.68 3.808-3.752s-1.704-3.749-3.808-3.749zm0 6.667c-1.633 0-2.962-1.31-2.962-2.918s1.329-2.916 2.962-2.916 2.961 1.307 2.961 2.916-1.328 2.918-2.961 2.918z"/></svg>']
);
console.log('createSC hash: '+res.hash)
await res.wait()
console.log("createSC success")
//註:一個dApp 只能mint 一次, 所以在此需要重新發布一個新的dApp
const contractObj2 = await daism_deploy(owner,contractName,[daismRegistrar_,nftAddress_]);
res=await contractObj2.mintSCandNFT(
['名稱2', '代幣名稱2','描述2', owner.address,1,'dApp'], //道易程的SC(見上面的結構描述), 註:名稱和代幣名稱 不允許重復
[owner.address], //成員列表
[10], // 成員票權(分紅權),不能為1,2,3,因為這三個數有特殊用途
(2 ** 16-1), //提案投票通過率,百分之分(全票)
7 * 24 * 3600, //壽命期為7天
9 * 24 * 3600, //冷卻期九天
['svg','<svg fill="#f7861c" height="24" viewBox="113.789 0 24.088 24" width="24.088" xmlns="http://www.w3.org/2000/svg"><path d="M134.613 6.85h-3.499l-2.035-2.009-.006-.006-.004-.003a1.698 1.698 0 00-1.189-.482h-4.23c-.491 0-.93.209-1.238.539l-.003-.005-1.991 1.966h-3.571c-.935 0-1.691.747-1.691 1.667v10c0 .92.757 1.668 1.691 1.668h17.768a1.68 1.68 0 001.691-1.668v-10a1.682 1.682 0 00-1.693-1.667zm.846 11.668a.843.843 0 01-.846.834h-17.768a.841.841 0 01-.846-.834v-10c0-.459.38-.833.846-.833h3.922l.248-.245 1.024-1.011.021.062.971-1.035a.843.843 0 01.618-.271h4.23c.223 0 .435.086.602.247l2.033 2.008.247.245H134.613c.465 0 .846.374.846.833z"/><path d="M125.729 9.351c-2.104 0-3.808 1.678-3.808 3.749 0 2.072 1.703 3.752 3.808 3.752 2.104 0 3.808-1.68 3.808-3.752s-1.704-3.749-3.808-3.749zm0 6.667c-1.633 0-2.962-1.31-2.962-2.918s1.329-2.916 2.962-2.916 2.961 1.307 2.961 2.916-1.328 2.918-2.961 2.918z"/></svg>'],
2 // 每個成員mint兩份榮譽通證
);
console.log('threeDapp.mintScAndNFT hash: '+res.hash);
await res.wait();
console.log("mintScAndNFT 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裏通用的方法(相關文檔可查閱微軟的「命名文件、路徑和命名空間」),即:
- 智能公器的分類體現在估值通證的擴展名上。
- 估值通證的命名部分借鑒電腦操作系統的方法,即以」.「分成兩部分:
- 估值通證的命名規則,為」XXXX.擴展名「。如:UL.eip(表明其智能公器是一個 EIP)。或者:ALOHA.ai(表明其為一個 AI 項目😂)。擴展名建議小寫,以使得前面的名稱更突出。任何人都可以任意設置其智能公器的擴展名——這是一種去中心化的命名規範。當然,如果其他人已經對某個分類做了沒有瑕疵的命名,那麽希望後面的開發者們能夠沿用。
- 文件名是大小寫不敏感。但前端會顯示大小寫。
- 擴展名不可為空。
- 擴展名只增加,不刪除。
- 擴展名的修改,實際可能是新增,也可能是另選已經存在的另一個擴展名。
- 誰主張修改,誰遷移——如果某個智能公器的開發者決定修改其估值通證的擴展名,實際上是他新增了一個擴展名,或者是遷移到另一個已經存在的擴展名,然後他的智能公器就被劃分到新的分類裏。但原擴展名並沒有被刪除。這樣之前主動加入到原分類(原擴展名)裏的其它智能公器,就完全沒有受到影響。
- 擴展名的調整,要通過提案來表決。
- (前端)已經存在的擴展名,在用戶填寫時,自動成為可選項。一旦選擇,就會出現該擴展名的描述。這樣就能避免不同的分類使用同一擴展名。
- (前端)擴展名的命名是去中心化的,沒有限製。但考慮到越容易記住越好,還是要建議用戶盡量使用簡單易記的名稱,即盡量使用英文字母和數字來命名估值通證。一般不建議在文件名中包含特殊字符。