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