Skip to content

Instantly share code, notes, and snippets.

@nmushegian
Last active September 1, 2019 00:55
Show Gist options
  • Save nmushegian/5a2752e6d0e19ff2ccd0608a36490139 to your computer and use it in GitHub Desktop.
Save nmushegian/5a2752e6d0e19ff2ccd0608a36490139 to your computer and use it in GitHub Desktop.
continuous growth/decay with variable rate - from maker-core
// This is a really bad and wasteful pattern from a long time ago!
// Just prorate against an internal continuously-growing conversion rate!
// See Maker code or similar
import 'dappsys/auth.sol';
import 'misc/math.sol';
// maintain a `last_touched` with each balance, then prorate it before any time it is touched.
// addPoint to change the rate
// this will ensure all balances appear to have the correct continuous growth/decay even if
// there were multiple rate updates since the last time it was touched
// all in O(1)
contract RateAccumulator is DSAuth, MathUser {
uint _last_rate;
uint64 _last_touched;
mapping (uint64 => uint) _accumulators;
function RateAccumulator(uint64 time) {
_last_rate = uint(UNIT);
_last_touched = time;
_accumulators[_last_touched] = _last_rate;
}
function addPoint(uint64 time) auth {
if (_accumulators[time] != 0) return;
var old_value = _accumulators[_last_touched];
var duration = time - _last_touched;
var exponent = uint(UNIT) * duration / 60 / 60 / 24 / 365;
var scale = uint(pow(int(_last_rate), exponent));
var new_value = old_value * scale / uint(UNIT);
_accumulators[time] = new_value;
_last_touched = time;
}
function prorate(uint64 start, uint start_amount, uint64 end)
returns (uint end_amount)
{
var a = _accumulators[start];
var b = _accumulators[end];
if (a == 0 || b == 0) throw;
end_amount = start_amount * b / a;
}
function updateRate(uint64 time, uint new_rate) auth {
addPoint(time);
_last_rate = new_rate;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment