智能合约编写注意事项

简介: 智能合约编写注意事项

今天区块链技术圈被美链(BEC)智能合约的漏洞导致代币价值几乎归零的事件刷遍朋友圈。这篇文章就带大家了解一些智能合约编写的注意事项。

Overflow 与 Underflow

Solidity 可以处理 256 位数字, 最高为 2256 - 1, 所以对 (2 256 - 1) 加 1 会导致归 0。同理, 对 unsigned 类型 0 做减 1 运算会得到 (2**256 - 1)

测试代码如下:

  1. pragma solidity 0.4.18;
  2. contract OverflowUnderflow{
  3.    uintpublic zero =0;
  4.    uintpublic max =2**256-1;
  5.    // zero will end up at  2 ** 256 - 1
  6.    function underflow()public{
  7.        zero -=1;
  8.    }
  9.    function overflow()public{
  10.        max +=1;
  11.    }
  12. }

尽管他们同样危险, 但是在智能合约中, underflow 造成的影响更大.

比如, 账号 A 持有 X tokens, 如果他发起一笔 X + 1 tokens 的交易, 如果代码不进行校验, 则账号 A 的余额可能发生 underflow 导致余额变多.

可以引入 SafeMath Library 解决:

  1. pragma solidity 0.4.18;
  2. library SafeMath{
  3.    function mul(uint256 a, uint256 b)internal pure returns (uint256){
  4.        if(a==0){
  5.            return0;
  6.        }
  7.        uint c = a * b;
  8.        assert(c / a == b);
  9.        return c;
  10.    }
  11.    function div(uint256 a, uint256 b)internal pure returns (uint256){
  12.        uint256 c = a / b;
  13.        return c;
  14.    }
  15.    functionsub(uint256 a, uint256 b)internal pure returns (uint256){
  16.        assert(b <= a);
  17.        return a - b;
  18.    }
  19.    function add(uint256 a, uint256 b)internal pure returns (uint256){
  20.        uint256 c = a + b;
  21.        assert(c >= a);
  22.        return c;
  23.    }
  24. }
  25. contract OverflowUnderflow{
  26.    usingSafeMathforuint;
  27.    uintpublic zero =0;
  28.    uintpublic max =2**256-1;
  29.    function underflow()public{
  30.        zero = zero.sub(1);
  31.    }
  32.    function overflow()public{
  33.        max = max.add(1);
  34.    }
  35. }

Visibility 与 Delegatecall

  • Public functions 可以被任意地址调用
  • External functions 只能从合约外部调用
  • Private functions 只能从合约内部调用
  • Internal functions 允许从合约及其子合约调用

External functions 消耗的 gas 比 public 少, 因为其使用 calldata 而 Public 需要复制所有参数到 memory。

Delegatecall

Delegatecall is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract and msg.sender and msg.value do not change their values. This means that a contract can dynamically load code from a different address at runtime. Storage, current address and balance still refer to the calling contract, only the code is taken from the called address.

这个特性可以用于构建 Library 和模块化代码. 但是与此同时, 这也有可能造成别人对你的代码进行操作。

下例中, 攻击者调用 pwn 方法获得了合约的拥有权。

  1. pragma solidity 0.4.18;
  2. contract Delegate{
  3.    address public owner;
  4.    functionDelegate(address _owner)public{
  5.        owner = _owner;
  6.    }
  7.    function pwn()public{
  8.        owner = msg.sender;
  9.    }
  10. }
  11. contract Deletagion{
  12.    address public owner;
  13.    Delegatedelegate;
  14.    functionDelegation(address _delegateAddreses)public{
  15.        delegate=Delegate(_delegateAddreses);
  16.        owner = msg.sender;
  17.    }
  18.    // an attacker can call Delegate.pwn() in the context of Delegation, this means that pwn() will modify the state of **Delegation** and not Delegate, the result is that the attacker takes unauthorized ownership of the contract.
  19.    function()public{
  20.        if(delegate.delegatecall(msg.data)){
  21.            this;
  22.        }
  23.    }
  24. }

Reentrancy(TheDAO hack)

Solidity 中 call 函数被调用时, 如果带有 value 参数, 则会转发所有他所收到的 gas。

在一下代码片段中, call函数在sender的余额实际减少前被调用。这里有一个漏洞曾导致TheDAO攻击。

  1. function withdraw(uint _amount)public{
  2.  if(balances[msg.sender]>= _amount){
  3.    if(msg.sender.call.value(_amount)()){
  4.      _amount;
  5.    }
  6.    balances[msg.sender]-= amount;
  7.  }
  8. }

引自Reddit的解释:

  1. In simple words, its like the bank teller doesnt change your balance until she has given you all the money you requested.Can I withdraw $500?Wait, before that , can I withdraw $500?”

  2. And so on.The smart contracts as designed only check you have $500 at beginning once,and allow themselves to be interrupted

目录
相关文章
|
11天前
|
存储 监控 测试技术
测试脚本编写和维护的最佳实践有哪些?
测试脚本编写和维护的最佳实践有哪些?
api一键自动合约跟单模式 | 程序化交易系统开发讲解【附样板源码实例分析】
“量化交易”有着两层含义:一是从狭义上来讲,是指量化交易的内容,将交易条件转变成为程序,自动下单;二是从广义上来讲,是指系统交易方法,就是一个整合的交易系统。
|
6月前
|
前端开发 安全 JavaScript
dapp智能合约系统开发解决方案/需求指南/案例步骤/源码程序
定义需求:明确系统的需求和功能。确定你的DApp将提供哪些服务,并了解相关的业务流程和规则。考虑如何实现这些功能,以及你打算使用的智能合约平台(如以太坊、EOS等)。
|
6月前
|
存储 区块链
DAPP二二复制合约系统开发|步骤逻辑|详情方案
智能合约是一种计算机协议,在协议制定和部署后,不需要外加人为干预,即可实现自我执行和自我验证
|
运维 监控 测试技术
Optimism(OP链)公链智能合约系统开发详细介绍丨案例设计丨功能逻辑丨需求步骤丨源码程序
Optimism(OP链)是一种二级扩展解决方案,旨在构建可扩展、低费用的区块链应用。
|
机器学习/深度学习 人工智能 自然语言处理
秒合约开发原理丨秒合约系统开发(详细规则)丨秒合约源码案例部署
秒合约开发原理丨秒合约系统开发(详细规则)丨秒合约源码案例部署
|
前端开发 JavaScript 区块链
链上DApp开发智能合约代码编写示例
链上DApp开发源码demo是指链上DApp的完整源代码示例。这些示例通常包括前端、后端和智能合约等多个部分,展示如何使用各种编程语言和工具构建基于区块链的应用程序。
|
区块链
秒合约系统开发逻辑实现,秒合约系统开发部分源码参考
随着数字货币期货近几年来的发展,如今大众持有的各种方式的资产越来越多,虚拟货币的交易方式也变的多种多样。因而高效的交易结算方式变得火热,为此,秒合约也就受到了极大的推崇。
|
开发框架 前端开发 安全
秒合约系统丨秒合约系统开发(逻辑及方案)丨秒合约开发源码案例设计
 用户界面是交易的脸面,在很大程度上也决定了用户的体验感。确保以简约的方式构建用户友好且直观的界面,以提供令人惊喜的交易体验,使用户更容易执行交易订单。另外我们使用前后台分离,数据库分离,保护数据安全与系统安全
|
Go 区块链 数据安全/隐私保护
佛萨奇2.0系统智能合约程序编写逻辑方案
FORGE循环仪中使用的矩阵大小为3×1和2×2。3×1矩阵本质上很简单,只需要填充三个位置即可。2×2矩阵从第一层的两个位置开始,然后扩展到第二层的四个位置。职位通过直接和间接招募Forsage会员来填补。一旦矩阵中的所有位置都被填满,就激活循环佣金。从矩阵出来的位置也将输入相同大小的新矩阵。
佛萨奇2.0系统智能合约程序编写逻辑方案
下一篇
无影云桌面