昨天群內(nèi)有朋友問,智能合約內(nèi)是否可以實(shí)現(xiàn)幫用戶購買ram或者幫用戶抵押資源(cpu及net),以及如何來實(shí)現(xiàn)這個(gè)功能。今天我們一起來看下這個(gè)問題。文章的內(nèi)容分為以下兩個(gè)部分:
buyram及delegatebw的實(shí)現(xiàn)
合約內(nèi)實(shí)現(xiàn)替用戶購買ram及抵押資源
1、buyram及delegatebw的實(shí)現(xiàn)
我們知道在執(zhí)行buyram的時(shí)候是分為兩種情況的:
以eos的單位來購買ram
以ram的單位來購買ram
那么buyram這個(gè)功能在哪里實(shí)現(xiàn)的呢,我們通過cleos中的main.cpp很容易查找到這兩個(gè)操作都是在系統(tǒng)合約eosio.system中實(shí)現(xiàn)的,以buyram為例,其分為了兩種,代碼如下:
1 //這個(gè)action將會(huì)以市場價(jià)格且單位bytes的形式購買ram 2 void system_contract::buyrambytes( account_name payer, account_name receiver, uint32_t bytes ) { 3 auto itr = _rammarket.find(S(4,RAMCORE)); 4 auto tmp = *itr; 5 auto eosout = tmp.convert( asset(bytes,S(0,RAM)), CORE_SYMBOL ); 6 7 buyram( payer, receiver, eosout ); 8 } 9 //當(dāng)購買ram的時(shí)候,支付的用戶會(huì)將eos交易至系統(tǒng)合約賬戶,而接收ram的用戶可以通過sellram這個(gè)action換回token,接收方支付這次action執(zhí)行所需內(nèi)存。10 void system_contract::buyram( account_name payer, account_name receiver, asset quant )11 {12 require_auth( payer );13 eosio_assert( quant.amount > 0, "must purchase a positive amount" );14 auto fee = quant;15 fee.amount = ( fee.amount + 199 ) / 200; /// .5% fee (round up)16 auto quant_after_fee = quant;17 quant_after_fee.amount -= fee.amount;18 INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {payer,N(active)},19 { payer, N(eosio.ram), quant_after_fee, std::string("buy ram") } );20 if( fee.amount > 0 ) {21 INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {payer,N(active)},22 { payer, N(eosio.ramfee), fee, std::string("ram fee") } );23 }2425 int64_t bytes_out;2627 const auto& market = _rammarket.get(S(4,RAMCORE), "ram market does not exist");28 _rammarket.modify( market, 0, [&]( auto& es ) {29 bytes_out = es.convert( quant_after_fee, S(0,RAM) ).amount;30 });3132 eosio_assert( bytes_out > 0, "must reserve a positive amount" );3334 _gstate.total_ram_bytes_reserved += uint64_t(bytes_out);35 _gstate.total_ram_stake += quant_after_fee.amount;3637 user_resources_table userres( _self, receiver );38 auto res_itr = userres.find( receiver );39 if( res_itr == userres.end() ) {40 res_itr = userres.emplace( receiver, [&]( auto& res ) {41 res.owner = receiver;42 res.ram_bytes = bytes_out;43 });44 } else {45 userres.modify( res_itr, receiver, [&]( auto& res ) {46 res.ram_bytes += bytes_out;47 });48 }49 set_resource_limits( res_itr->owner, res_itr->ram_bytes, res_itr->net_weight.amount, res_itr->cpu_weight.amount );50 }
可以看出,buyrambytes最終還是調(diào)用了buyram,當(dāng)購買ram的時(shí)候,支付的用戶會(huì)將eos交易至系統(tǒng)合約賬戶,而接收ram的用戶可以通過sellram這個(gè)action換回token,接收方支付這次action執(zhí)行所需內(nèi)存。我們大多已經(jīng)知道ram的價(jià)格是動(dòng)態(tài)變化的,因?yàn)槠涫褂昧薭ancor算法,就像現(xiàn)在大熱的fibos一樣,使用bancor算法可以更自主的給ram【定價(jià)】,本篇重點(diǎn)不在此,筆者正在嘗試使用該算法進(jìn)行測試,以后的文章中會(huì)逐步提及。同樣的,delegatebw的操作也是類似的,我們不再進(jìn)行代碼的粘貼,感興趣的朋友可以自行測試。
2、合約內(nèi)實(shí)現(xiàn)替用戶購買ram及抵押資源
為用戶抵押資源是可以解除質(zhì)押,最終是不消耗我們的token的,但是為用戶購買ram卻是消耗合約開發(fā)者自己的token的,我們假設(shè)一種情況如下,用戶支付我們10 EOS,我們便為其購買100kbytes的ram,而為其抵押10 EOS的資源,代碼如下:
1void tianlongbabu::buysilver(account_name user,asset quanitity,string memo) 2{ 3 if (user != _this_contract && quanitity.symbol == S(4,EOS)) 4 { 5 //購買ram 6 action( 7 {permission_level{_this_contract,N(active)}}, 8 N(eosio), N(buyrambytes), 9 std::make_tuple(_this_contract,user,quanitity.amount * 10)10 ).send(); 11 //抵押資源1213 asset delquan = quanitity;14 delquan.amount /= 10;15 action(16 {permission_level{_this_contract,N(active)}}, 17 N(eosio), N(delegatebw),18 std::make_tuple(_this_contract,user,delquan,delquan,true)19 ).send();20 }21}
通過上面的代碼我們可以看到,本合約調(diào)用了系統(tǒng)合約eosio.system,在代碼中的體現(xiàn)就是N(eosio),以及其對(duì)應(yīng)的action--buyrambytes以及delegatebw,inline action執(zhí)行之后,通過合約內(nèi)部為用戶購買ram以及質(zhì)押資源便可實(shí)現(xiàn)了。當(dāng)然購買和質(zhì)押實(shí)現(xiàn)之后,我們也可以實(shí)現(xiàn)賣出ram以及解除質(zhì)押資源,感興趣的話可以去嘗試下。
在合約部署成功之后,我們可以通過命令行簡單的測試下該合約是否生效:
1cleos push action mycontract buysilver '["user","10.0000 EOS","test"]' -p user@active
本文從群內(nèi)朋友問題出發(fā),首先查看了eos中buyram的邏輯,然后以合約內(nèi)部調(diào)用調(diào)用系統(tǒng)合約eosio.system中的buyram及delegatebw來實(shí)現(xiàn)替用戶購買ram以及質(zhì)押資源,關(guān)于buyram中的bancor算法筆者會(huì)在后續(xù)的文章中繼續(xù)進(jìn)行說明及測試。
如果你覺得我的文章對(duì)你有一定的幫助,請(qǐng)點(diǎn)擊文章末尾的喜歡該作者。
如果你對(duì)eos開發(fā)感興趣,歡迎關(guān)注本公眾號(hào),一起學(xué)習(xí)eos開發(fā)。