Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
contract CircuitBreaker {
struct Transfer { uint amount; address to; uint releaseBlock; bool released; bool stopped; }
Transfer[] public transfers;
address public curator;
address public authorizedSender;
uint public period;
uint public limit;
uint public currentPeriodEnd;
uint public currentPeriodAmount;
event PendingTransfer(uint id, uint amount, address to, uint releaseBlock);
function CircuitBreaker(address _curator, address _authorizedSender, uint _period, uint _limit) {
curator = _curator;
period = _period;
limit = _limit;
authorizedSender = _authorizedSender;
currentPeriodEnd = block.number + period;
function transfer(uint amount, address to) {
if (msg.sender == authorizedSender) {
if (currentPeriodAmount + amount > limit) {
uint releaseBlock = block.number + period;
PendingTransfer(transfers.length, amount, to, releaseBlock);
transfers.push(Transfer(amount, to, releaseBlock, false, false));
} else {
currentPeriodAmount += amount;
transfers.push(Transfer(amount, to, block.number, true, false));
if(!to.send(amount)) throw;
function updatePeriod() {
if (currentPeriodEnd < block.number) {
currentPeriodEnd = block.number + period;
currentPeriodAmount = 0;
function releasePendingTransfer(uint id) {
Transfer transfer = transfers[id];
if (transfer.releaseBlock <= block.number && !transfer.released && !transfer.stopped) {
transfer.released = true;
if(! throw;
function stopTransfer(uint id) {
if (msg.sender == curator) {
transfers[id].stopped = true;
Copy link

Nice work. Why is updatePeriod() necessarily part of transfer()?

Copy link

Why is updatePeriod() necessarily part of transfer()?

Because whether we can or cannot transfer funds depends on the periodical limit. If there's a new period we don't want to use previous period's currentPeriodAmount.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment