Last active
September 1, 2019 00:55
-
-
Save nmushegian/5a2752e6d0e19ff2ccd0608a36490139 to your computer and use it in GitHub Desktop.
continuous growth/decay with variable rate - from maker-core
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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