我们来发行一个自己的币吧,我先抛个砖,一个游戏币:Bullet 子弹币。
Bullet的发行
如果你向Bullet的智能合约打10000个REV,你就能马上得到200个Bullet,比例是2%,这个打币的过程可以叫做质押。
质押的时间是100天。100天后,你向智能合约发起提币,10000个REV打回到你原来的钱包里。
目前运行在测试网上,质押时间暂定为一天。一天后可以提币。
Bullet的使用
Bullet有什么用呢?可以用来打游戏。前提是游戏dApp的开发者愿意选用Bullet作为自己的游戏币。
为什么游戏开发者要选用Bullet? 因为Bullet完全由智能合约控制,并且没有后门。游戏开发者使用Bullet没有成本。
Bullet有什么好处
- 对REV质押挖矿的人来说,多了一个选择。可以质押给节点挖REV,也可以打到Bullet的智能合约里挖Bullet
- Bullet的利率和REV的年利率7%差不多
- Bullet能够锁定不少REV,有助于REV的价格稳定
Bullet的下一步规划
目前Bullet智能合约部署在测试网上进行测试,合适的时候会转到主网。为了证明Bullet的工作原理可行,并且帮助建立Bullet的生态,我打算在锐Rui钱包里集成对Bullet的支持,包括转账、质押、提币等,甚至可能包括Bullet的交易。第二,打算把老母鸡(Oldhen)游戏跑起来,大家就可以用Bullet打游戏了。
如何测试
在不跑节点的情况下,目前最好的测试方法是通过RNode client testing page( tgrospic.github.io/rnode-client-js/ )。
我还在尝试Dappy,没有成功,有一些问题没解决。
BulletVault在测试网的地址是:
rho:id:auz8oqkczecbiq7jmeeeoyackumqybo4pijfec3rnjccwz6mhtqr9t
质押币的大池子地址是:11112QLdkH7gj4KmJbZSG45jLpFMd9i7pQ2YZKk6iSkPVFJGb8mUro
不要向大池子直接打测试币,必须通过调用deposit函数才能触发Bullet铸币。
下面开始技术讲解:
基本概念
Purse: 是REV存放的地方,REV在purse里放着,REV不能离开Purse。 所谓REV转账,其实就是Purse的来回移动。
Vault: 就是Purse存放的地方,可以是一个公钥,也可以是一个Unforgeable Name, 比如多重签名钱包。
Purse和Vault不同于我们理解的钱包Wallet,Wallet是私钥存储的地方,在链下。而Purse和Vault是链上概念。
REV Mint: 通过生成Purse的方式铸币。
用到了哪些库
RevAddress(`rho:rev:address`) // 生成钱包地址
deployerId(`rho:rchain:deployerId`) //获得调用者的deployerId
deployId(`rho:rchain:deployId`) //获得调者的deployId,因为部署于链上的智能合约不适合使用stdout显示运行结果,故采用deployId作为信息返回通道。
DeployerIdOps(`rho:rchain:deployerId:ops`) //用于从调用者的公钥计算出其REV钱包地址。
blockData(`rho:block:data`) //获得调用者的出块时间戳
insertArbitrary(`rho:registry:insertArbitrary`) //在链上注册智能合约
rl!(`rho:rchain:makeMint`, *MakeMintCh) //铸币智能合约
rl!(`rho:rchain:authKey`, *AuthKeyCh) //鉴权智能合约
rl!(`rho:lang:either`, *EitherCh) //Either是一种数据类型,用于处理异常
rl!(`rho:lang:treeHashMap`, *TreeHashMapCh) //TreeHashMap是一种数据结构,用于提高数据的读写效率
rl!(`rho:rchain:revVault`, *RevVaultCh) //REV的智能合约
如何存储
采用了两个TreeHashMap,一个用于存储Bullet的所有钱包账户信息,另一个用于存储打入的REV的账户信息。
// mapstore for depositing REV
TreeHashMap!("init", 2, *revMapStore)
// mapstore for bullet token
TreeHashMap!("init", 2, *bulletMapStore)
REV大池子
REV质押在一个智能合约大池子里,任何人没有权限动用。方法是生成一个新的Unforgeable name,基于此生成一个钱包地址。好处是该钱包地址没有对应任何私钥,所以没人能够设置后门。
RevAddress!("fromUnforgeable", *unf, *revHouseAddrCh) |
for (@revHouseVaultAuthKey <- authKeyCh; @revHouseAddr <- revHouseAddrCh) {
...
}
如何鉴权
采用authKey对每一个调用者的身份进行鉴权,在key的生成过程中,加入了一个“环境变量”,为了防止黑客将key偷出。
rl!(`rho:rchain:authKey`, *AuthKeyCh) |
for (@(_, AuthKey) <- AuthKeyCh}
...
@AuthKey!("make", (*_bulletVault, deployerRevAddress), *ret)
...
@AuthKey!("check", *authKey, (*_bulletVault, ownRevAddress), *authKeyValidCh)
...
}
如何发行
任何人调用deposit函数,质押一定数量的REV都可以得到Bullet。deposit函数会从用户REV账户里扣取REV,并更新revMap总账本,成功后,即打出相应数量的Bullet到用户账户。
contract BulletVault(@"deposit", @amount, retCh) = {
...
}
如何提币
100天后,目前在测试网是1天,用户可以调用withdraw函数,程序检查时间跨度是否满足要求,合格后即打回原有REV。
contract BulletVault(@"withdraw", retCh) = {
...
}
智能合约如何判断时间
在用户调用时,从blockData返回三个参数,中间的参数就是timestamp。
new blockData(`rho:block:data`), tCh in {
blockData!(*tCh) |
for (@_, @t, @_ <- tCh) {
stdout!(["Current timestamp is: ",t])
}
欢迎关注 “Rholang中文社区” 公众号
欢迎开发者加入 “RChain开发者” 微信群。加群请加lowbird微信,拉你入群。非开发者请勿加,会有一轮测试,通过者方可入群。