近段时间在探讨EOS智能合约方面的知识,通过代码实践的DAPP能够更深入的掌握EOS的智能合约。
需求如下:
同事的合作协同工作方式不够完善, 工作协作方式效率有待提升,公司内部员工激励方式单一且效果有待提升,需要一种全新的、高效的协同方式来提高工作效率。
提供两个类:
|-create
task -|-commit
|-confirm
|-create
token-|-issue
|-transfer
代码如下:
task.hpp
#pragma once
#include <eosiolib/asset.hpp>
#include <eosiolib/eosio.hpp>
#include <string>
using namespace eosio;
using std::string;
//asset = {int64_t amount; symbol_type symbol}
class token : public contract {
public:
token(account_name self) :contract(self){}
/// @abi action
void create(account_name issuer, //谁来发行
asset maximum_supply, //资产信息:发币是什么,发钱多少
uint8_t can_freeze, //资产能否冻结
uint8_t can_recall, //是否可以回收
uint8_t can_whitelist); //白名单
void issue(account_name to,
asset quantity,
string memo);
void transfer(account_name from,
account_name to,
asset quantity,
string memo);
private:
//friend pdjtask
inline asset get_supply(symbol_name sym)const;
inline asset get_balance(account_name owner, symbol_name sym)const;
private:
/// @abi table accounts i64
struct account {
asset balance;
uint8_t frozen = 0;
uint8_t whitelist = 1;
uint64_t primary_key()const { return balance.symbol.name(); }
};
/// @abi table state i64
struct stat {
asset supply;
asset max_supply;
account_name issuer;
uint8_t can_freeze = 1;
uint8_t can_recall = 1;
uint8_t can_whitelist = 1;
uint8_t is_frozen =0;
uint8_t enforce_whitelist = 0;
uint64_t primary_key()const { return supply.symbol.name(); };
};
typedef eosio::multi_index<N(accounts), account> accounts;
typedef eosio::multi_index<N(stats), stat> stats;
void sub_balance(account_name owner, asset value, const stat& st);
void add_balance(account_name owner, asset value, const stat& st, account_name ram_payer);
};
asset token::get_supply(symbol_name sym) const {
stats statstable(_self, sym);
const auto& st = statstable.get(sym);
return st.supply;
}
asset token::get_balance(account_name owner, symbol_name sym)const {
accounts accountstable(_self, owner);
const auto& ac = accountstable.get(sym);
return ac.balance;
}
class task : public token {
public:
task(account_name self): token(self){}
/// @abi action
//创建任务
void createtk(account_name creator, account_name worker, asset taskBonus, string memo);
//提交任务
void commit(uint64_t taskID, account_name worker, string memo);
//验收任务
void confirm(uint64_t taskID, account_name creator, uint8_t ok = 1);
private:
/// @abi table tasks i64
struct task {
uint64_t taskID; //每个任务的编号
account_name creator;//任务谁创建
account_name worker; //任务谁来干
asset bonus; //悬赏
uint8_t status = 0; //任务的状态
string remark; //描述
string comment; //备注
uint64_t primary_key()const { return taskID;}
};
typedef eosio::multi_index<N(tasks), task> tasks;
};
task.cpp
#include "task.hpp"
void token::sub_balance(account_name owner, asset value, const pdjtoken::stat &st) {
print("sub_balance->", value.symbol);
accounts from_acnts(_self, owner);
//auto fromacc = from_acnts.find(value.symbol.name());
const auto& from = from_acnts.get(value.symbol.name() );
eosio_assert(from.balance.amount >= value.amount, "overdrawn balance");
if( has_auth(owner) ){
eosio_assert(!st.can_freeze || from.frozen, "account is frozen by issuer");
eosio_assert(!st.can_freeze || st.is_frozen, "all transfers are frozen by issuer");
eosio_assert(!st.enforce_whitelist || from.whitelist, "account is not white listed");
} else if(has_auth(st.issuer)){
eosio_assert(st.can_recall, "issuer may not recall token");
} else{
eosio_assert(false, "insufficient authority");
}
print("modify->",from.balance,",",value);
from_acnts.modify(from, owner, [&](auto& a){
a.balance -= value;
});
}
void token::add_balance(account_name owner, asset value, const stat& st, account_name ram_payer)
{
print("add_balance->", value.symbol);
accounts to_acnts(_self, owner);
auto to = to_acnts.find(value.symbol.name());
if(to == to_acnts.end()){
//第一次发
eosio_assert( !st.enforce_whitelist, "can only transfer to white listed accounts");
to_acnts.emplace( ram_payer, [&](auto& a){
a.balance = value;
});
} else {
eosio_assert(!st.enforce_whitelist || to->whitelist, "receiver requires whitelist by ...");
to_acnts.modify(to, 0, [&](auto& a){
a.balance += value;
});
}
}
void token::create(account_name issuer,
asset maximum_supply,
uint8_t can_freeze,
uint8_t can_recall,
uint8_t can_whitelist)
{
require_auth(_self);
auto sym = maximum_supply.symbol;
eosio_assert(sym.is_valid(), "invalid symbol name");
eosio_assert(maximum_supply.is_valid(), "invalid supply");
eosio_assert(maximum_supply.amount > 0, "max-supply must be positive");
//判断发行的币是否已存在
stats statstable(_self, _self);
auto existing = statstable.find(sym.name());
eosio_assert(existing == statstable.end(), "token with symbol already exists");
//创建表,s:stat
statstable.emplace(_self, [&](auto& s){
s.supply.symbol = maximum_supply.symbol;
s.max_supply = maximum_supply;
s.issuer = issuer;
s.can_freeze = can_freeze;
s.can_recall = can_recall;
s.can_whitelist = can_whitelist;
});
}
//to 要给谁
//quantity 给这个账户先打多少钱
//memo 备注
void token::issue(account_name to, asset quantity, string memo)
{
//print("issue");
auto sym = quantity.symbol.name();
print("issue=>",name{sym});
stats auto& st = statstable.get(sym);
require_auth(st.issuer);
eosio_assert(quantity.is_valid(), "invalid quantity");
eosio_assert(quantity.amount > 0, "must issue positive quantity");
eosio_assert(quantity <= st.max_supply - st.supply, "quantity exceeds available supply");
statstable.modify(st, 0, [&](auto& s){
s.supply += quantity;
});
//能够发行的人,先给它加钱
add_balance(st.issuer, quantity, st, st.issuer);
//内部转账操作
if(to != st.issuer) {
SEND_INL_INE_ACTION(*this, transfer, {st.issuer,N(active)}, {st.issuer, to, quantity, memo});
}
}
void token::transfer(account_name from, account_name to, asset quantity, string memo)
{
require_auth( from );
auto sym = quantity.symbol.name();
print("transfer",name{sym});
stats statstable(_self, _self);
const auto& st = statstable.get(sym);
require_recipient(from);
require_recipient(to);
eosio_assert(quantity.is_valid(), "invalid quantity");
eosio_assert(quantity.amount > 0, "must transfer positive quantity");
sub_balance(from, quantity, st); //我的账户减钱
add_balance(to, quantity, st, from); //他的账户加钱
}
void task::createtk(account_name creator, account_name worker, asset taskBonus, string memo)
{
//创建任务-指定作者-奖金数量-描述
//检查creator和worker是否都存在
require_auth(creator);
require_auth(worker);
auto sym = taskBonus.symbol;
eosio_assert(sym.is_valid(), "invalid symbol name");
//存储数据的结构
tasks tk(_self, _self);
//创建任务
tk.emplace(creator, [&](auto &t){
t.creator = creator;
t.worker = worker;
t.taskID = tk.available_primary_key(); //主键自动增长
t.bonus = taskBonus;
t.remark = memo;
});
}
void task::commit(uint64_t taskID, account_name worker, string memo)
{
//提交任务者必须与任务分配者是一个人
print("hi",name{_self});
require_auth(worker);
tasks tk(_self, _self);
auto tkobj = tk.find(taskID);
eosio_assert( tkobj != tk.end(), "taskid not exists");
eosio_assert( tkobj->worker == worker, "worker not same");
tk.modify(tkobj, worker, [&](auto &t){
t.status = 1;
t.comment = memo;
});
}
void task::confirm(uint64_t taskID, account_name creator, uint8_t ok)
{
require_auth(creator);
tasks tk(_self, _self);
auto tkobj = tk.find(taskID);
eosio_assert(tkobj != tk.end(), "taskid not exists");
uint8_t status = 2;
if(!ok){
// re do
status = 0;
}
tk.modify(tkobj, creator, [&](auto &t){
t.status = status;
t.comment = "well done!";
});
if(ok){
//发币刺激
transfer(creator, tkobj->worker, tkobj->bonus, "very good!");
}
}
EOSIO_ABI( pdjtask, (createtk)(commit)(create)(issue)(transfer)(confirm) )
编译:
使用eosiocpp编译
查看表:
cat task.abi
部署:
cleos set contract maomao ../task/
执行智能合约:
1、cleos push action maomao create `{"issuer":"maomao", "maximum_supply":"10000000.00 TOK", "can_freeze":1, "can_recall":1, "can_whitelist":1}` -p maomao
cleos get table maomao maomao stats
cleos get table maomao maomao accounts //当前账户是没有钱的
2、cleos push action maomao issue `{"to":"maomao", "quantity":"1000.00 TOK", "memo":"转入资金"}` -p maomao