zoukankan      html  css  js  c++  java
  • eos智能合约开发最佳实践

    安全问题

    1.可能的错误

    智能合约终止
    限制转账限额 限制速率
    有效途径来进行bug修复和提升

    2.谨慎发布智能合约

    对智能合约进行彻底的测试 并在任何新的攻击手法被发现后及时制止
    赏金计划和审计合约

    3.合约的简介
    确保智能合约逻辑简单
    确保合约和函数模块化

    4.保持更新
    在任何新发现的漏洞之前进行修复
    利用最新技术

    5.潜在特性
    可能会调用同名函数

    漏洞
    溢出漏洞

    typedef struct acnts {
    account_name name0;
    account_name name1;
    account_name name2;
    account_name name3;
    } account_names;

    void transfer(symbol_name symbol, account_name from, account_names to, uint64_t balance)
    {
    require_auth(from);
    account fromaccount;

    require_recipient(from);
    require_recipient(to.name0);
    require_recipient(to.name1);
    require_recipient(to.name2);
    require_recipient(to.name3);
    
    eosio_assert(is_balance_within_range(balance), "invalid balance");
    eosio_assert(balance > 0, "must transfer positive balance");
    
    uint64_t amount = balance * 4; //乘法溢出
    
    int itr = db_find_i64(_self, symbol, N(table), from);
    eosio_assert(itr >= 0, "Sub-- wrong name");
    db_get_i64(itr, &fromaccount, (account));
    eosio_assert(fromaccount.balance >= amount, "overdrawn balance");
    
    sub_balance(symbol, from, amount);
    
    add_balance(symbol, to.name0, balance);
    add_balance(symbol, to.name1, balance);
    add_balance(symbol, to.name2, balance);
    add_balance(symbol, to.name3, balance);
    

    }
    提示 使用assert进行检查 而不是把balance提出来进行运算

    权限校验
    严格判断入参函数和实际调用使得否一致

    void token::transfer( account_name from,
    account_name to,
    asset quantity,
    string memo )
    {
    eosio_assert( from != to, "cannot transfer to self" );
    eosio_assert( is_account( to ), "to account does not exist");
    auto sym = quantity.symbol.name();
    stats statstable( _self, sym );
    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" );
    eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" );
    eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" );
    
    auto payer = has_auth( to ) ? to : from;
    
    sub_balance( from, quantity );
    add_balance( to, quantity, payer );
    

    }
    提示:检验资产转出账户和调用账户是否一致

    确保每一个action和code满足关联要求
    // extend from EOSIO_ABI

    define EOSIO_ABI_EX( TYPE, MEMBERS )

    extern "C" {
    void apply( uint64_t receiver, uint64_t code, uint64_t action ) {
    auto self = receiver;
    if( action == N(onerror)) {
    /* onerror is only valid if it is for the "eosio" code account and authorized by "eosio"'s "active permission /
    eosio_assert(code == N(eosio), "onerror action's are only valid from the "eosio" system account");
    }
    if( code == self || code == N(eosio.token) || action == N(onerror) ) {
    TYPE thiscontract( self );
    switch( action ) {
    EOSIO_API( TYPE, MEMBERS )
    }
    /
    does not allow destructor of thiscontract to run: eosio_exit(0); */
    }
    }
    }

    EOSIO_ABI_EX(eosio::charity, (hi)(transfer))

    提示:关键检查

    相关文章:
    eosbet被盗事件合约分析

    被盗合约 受攻击代码

    有问题的合约代码

    // extend from EOSIO_ABI, because we need to listen to incoming eosio.token transfers

    define EOSIO_ABI_EX( TYPE, MEMBERS )

    extern "C" {
    void apply( uint64_t receiver, uint64_t code, uint64_t action ) {
    auto self = receiver;
    if( action == N(onerror)) {
    /* onerror is only valid if it is for the "eosio" code account and authorized by "eosio"'s "active permission /
    eosio_assert(code == N(eosio), "onerror action's are only valid from the "eosio" system account");
    }
    if( code == self || code == N(eosio.token) || action == N(onerror) ) {
    TYPE thiscontract( self );
    switch( action ) {
    EOSIO_API( TYPE, MEMBERS )
    }
    /
    does not allow destructor of thiscontract to run: eosio_exit(0); */
    }
    }
    }

    问题原因:

    由于abi转发器允许下注而不将eos转移到合同中。

    修改措施:
    1.去掉错误判断
    2.过滤传入操作 只将eosio.token的行为传入合同

    提醒:
    更强大的代码测试
    至少两次审计
    资金监控

  • 相关阅读:
    js 获取asp.net TextBox值
    项目笔记一
    如何取GridView中隐藏列的值
    使用bablepolyfill
    border: 0.5px
    选择查询固定位置的数据
    SQL用户数据库权限设置
    Java.1 HelloWorld的分析
    Java.2 面向对象
    【drupal实践】windows下drupal7.22develop版本安装
  • 原文地址:https://www.cnblogs.com/xiaocongcong888/p/9807150.html
Copyright © 2011-2022 走看看