solidity智能合约[52]-安全-storage陷阱-创新互联

storage陷阱

下面的合约是一个锁定金额的合约,用户将资金存储在此合约中,只有当过了一段时间时候才能够提取出来。
下面的案例是为了说明storage属性预设性带来的陷阱。payIn函数是当用户存储金额时调用的函数。传递的参数似乎解锁的时间。在合约payIn中,HoldRecord newRecord; 其实默认为storage类型,并且,当不为storage变量赋值的时候,变量默认引用的位置是storage空间中的0号位置。这也意味着在当前的案例中,newRecord指针指向了ownerAmount,当对newRecord 执行newRecord.amount += msg.value; 实则将ownerAmount即合约拥有者的金额增加了。 这时,合约拥有者就可以调用ownerWithdrawal将用户存储在合约的钱转移出来。

成都创新互联公司专注于企业成都营销网站建设、网站重做改版、南岳网站定制设计、自适应品牌网站建设、H5响应式网站电子商务商城网站建设、集团公司官网建设、成都外贸网站建设公司、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为南岳等各大城市提供网站开发制作服务。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
pragma solidity ^0.4.23;

contract HodlFraud {
   uint public ownerAmount;  //合约拥有者的金钱
   uint public  numberOfPayouts; //次数
   address public owner;  //合约的拥有者

   struct HoldRecord {
       uint amount;  //存储的金钱
       uint unlockTime;  //解锁的时间
   }

   mapping (address => HoldRecord) public balance;  //地址  => 存储的金钱,时间

   //构造函数初始化
   function HodlFraud () public payable {
       owner = msg.sender;
       ownerAmount = msg.value;
   }

   //某一个用户存储金钱,
   //@param  holdTime 代表的是解锁时间
   function payIn(uint holdTime) public payable {
       require(msg.value > 0);


       HoldRecord  newRecord;


       newRecord.amount += msg.value;
       newRecord.unlockTime = now + holdTime;
       balance[msg.sender] = newRecord;
   }

   //转账,使用这笔钱
   function withdraw () public {
       require(balance[msg.sender].unlockTime < now && balance[msg.sender].amount > 0);

       msg.sender.transfer(balance[msg.sender].amount);

       balance[msg.sender].amount = 0;
       numberOfPayouts++;
   }

   //合约的拥有着,转移自己的钱
   function ownerWithdrawal () public {
       require(msg.sender == owner && ownerAmount > 0);
       msg.sender.transfer(ownerAmount);
       ownerAmount = 0;
   }
}

解决办法

HoldRecord newRecord 修改为 HoldRecord memory newRecord

总结

1
2
3
// 这个例子是要举出在 smart contract 中 storage 预设行为的危险性。其实只要维持一个原则就可以避免这个问题。
// 养成明确定义使用 storage 还是 memory 的好习惯
// 一般来说,指定 storage 时就直接给初始值;而在 function 里面需要用到的缓存器都用 memory,除非想要直接修改链上的值。现在 compiler 都会很聪明的提醒开发者要定义 storage 还是 memory,而当 storage pointer 没有初始值时也会提醒开发者。
  • 本文链接: https://dreamerjonson.com/2018/11/25/solidity-52-security-storage/

  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY 4.0 CN协议 许可协议。转载请注明出处!

solidity智能合约[52]-安全-storage陷阱

创新互联www.cdcxhl.cn,专业提供香港、美国云服务器,动态BGP最优骨干路由自动选择,持续稳定高效的网络助力业务部署。公司持有工信部办法的idc、isp许可证, 机房独有T级流量清洗系统配攻击溯源,准确进行流量调度,确保服务器高可用性。佳节活动现已开启,新人活动云服务器买多久送多久。


当前文章:solidity智能合约[52]-安全-storage陷阱-创新互联
分享路径:http://scyanting.com/article/cccdgg.html