长篇干货|以太坊智能合约 —— ***安全开发指南(附代码) (10)

由于断路器在满足一定条件时将会停止执行,如果发现错误时可以使用断路器。例如,如果发现错误,大多数操作可能会在合约中被挂起,这是唯一的操作就是撤销。你可以授权给任何你受信任的一方,提供给他们触发断路器的能力,或者设计一个在满足某些条件时自动触发某个断路器的程序规则。

例如:

bool private stopped = false; address private owner;

modifier isAdmin() {    if(msg.sender != owner) {        throw;    }    _; }

function toggleContractActive() isAdmin public {    // You can add an additional modifier that restricts stopping a contract to be based on another action, such as a vote of users    stopped = !stopped; }

modifier stopInEmergency { if (!stopped) _; } modifier onlyInEmergency { if (stopped) _; }

function deposit() stopInEmergency public {    // some code }

function withdraw() onlyInEmergency public {    // some code }

速度碰撞(延迟合约动作)

速度碰撞使动作变慢,所以如果发生了恶意操作便有时间恢复。例如,The DAO 从发起分割DAO请求到真正执行动作需要27天。这样保证了资金在此期间被锁定在合约里,增加了系统的可恢复性。在DAO攻击事件中,虽然在速度碰撞给定的时间段内没有有效的措施可以采取,但结合我们其他的技术,它们是非常有效的。

例如:

struct RequestedWithdrawal {    uint amount;    uint time; }

mapping (address => uint) private balances; mapping (address => RequestedWithdrawal) private requestedWithdrawals; uint constant withdrawalWaitPeriod = 28 days; // 4 weeks

function requestWithdrawal() public {    if (balances[msg.sender] > 0) {        uint amountToWithdraw = balances[msg.sender];        balances[msg.sender] = 0; // for simplicity, we withdraw everything;        // presumably, the deposit function prevents new deposits when withdrawals are in progress

requestedWithdrawals[msg.sender] = RequestedWithdrawal({            amount: amountToWithdraw,            time: now        });    } }

function withdraw() public {    if(requestedWithdrawals[msg.sender].amount > 0 && now > requestedWithdrawals[msg.sender].time + withdrawalWaitPeriod) {        uint amountToWithdraw = requestedWithdrawals[msg.sender].amount;

requestedWithdrawals[msg.sender].amount = 0;

if(!msg.sender.send(amountToWithdraw)) {            throw;        }    } }

速率限制

速率限制暂停或需要批准进行实质性更改。 例如,只允许存款人在一段时间内提取总存款的一定数量或百分比(例如,1天内最多100个ether) - 该时间段内的额外提款可能会失败或需要某种特别批准。 或者将速率限制做在合约级别,合约期限内只能发出发送一定数量的代币。

合约发布

在将大量资金放入合约之前,合约应当进行大量的长时间的测试。

至少应该:

拥有100%测试覆盖率的完整测试套件(或接近它)

在自己的testnet上部署

在公共测试网上部署大量测试和错误奖励

彻底的测试应该允许各种玩家与合约进行大规模互动

在主网上部署beta版以限制风险总额

自动弃用

在合约测试期间,你可以在一段时间后强制执行自动弃用以阻止任何操作继续进行。例如,alpha版本的合约工作几周,然后自动关闭所有除最终退出操作的操作。

modifier isActive() {    if (block.number > SOME_BLOCK_NUMBER) {        throw;    }    _; }

function deposit() public isActive() {    // some code }

function withdraw() public {    // some code }

#####限制每个用户/合约的Ether数量

在早期阶段,你可以限制任何用户(或整个合约)的Ether数量 - 以降低风险。

Bug赏金计划

运行赏金计划的一些提示:

决定赏金以哪一种代币分配(BTC和/或ETH)

决定赏金奖励的预算总额

从预算来看,确定三级奖励:    - 你愿意发放的最小奖励    - 通常可发放的最高奖励    - 设置额外的限额以避免非常严重的漏洞被发现

确定赏金发放给谁(3是一个典型)

核心开发人员应该是赏金评委之一

当收到错误报告时,核心开发人员应该评估bug的严重性

在这个阶段的工作应该在私有仓库进行,并且在Github上的issue板块提出问题

如果这个bug需要被修复,开发人员应该在私有仓库编写测试用例来复现这个bug

开发人员需要修复bug并编写额外测试代码进行测试确保所有测试都通过

展示赏金猎人的修复;并将修复合并回公共仓库也是一种方式

确定赏金猎人是否有任何关于修复的其他反馈

赏金评委根据bug的可能性和影响来确定奖励的大小

在整个过程中保持赏金猎人参与讨论,并确保赏金发放不会延迟

有关三级奖励的例子,参见 Ethereum\'s Bounty Program:

(地址:https://bounty.ethereum.org/)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgxdjj.html