Created
February 15, 2017 09:30
-
-
Save yutelin/bfba53d11bcee899443a66f18ce2c09a to your computer and use it in GitHub Desktop.
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
pragma solidity ^0.4.8; | |
contract NegativeCompoundCoin { | |
address public _minter; | |
// Ledger | |
mapping (address => uint) public _balances; | |
// Last interest duduction blocks, for checking how many periods apply | |
mapping (address => uint) public _lastCalculated; | |
// how many blocks per peroid. | |
uint public _period; | |
// deduction interest rate = _rate * 10000. say if you want 90% of deduction interest rate, then you need to set the _rate to 9000 | |
// which means after each period, the new balance will be 90% of the original balance. | |
uint public _rate; | |
function NegativeCompoundCoin(uint period, uint rate) { | |
_minter = msg.sender; | |
_period = period; | |
_rate = rate; | |
} | |
// Mint coin to receiver | |
function mint(address receiver, uint amount) { | |
if (msg.sender != _minter) return; | |
_balances[receiver] += amount; | |
//Setup starting checkpoint if not set yet. | |
if(_lastCalculated[receiver] == 0){ | |
_lastCalculated[receiver] = block.number; | |
} | |
} | |
// Send coin from sender to receiver. | |
function send(address receiver, uint amount) { | |
//Before EACH sending, we need to deduct appropriate amount from both sender and receiver | |
calculateBalance(msg.sender); | |
calculateBalance(receiver); | |
if (_balances[msg.sender] < amount) return; | |
_balances[msg.sender] -= amount; | |
_balances[receiver] += amount; | |
//Setup starting checkpoint if not set yet. | |
if(_lastCalculated[receiver] == 0){ | |
_lastCalculated[receiver] = block.number; | |
} | |
} | |
// Calculate new balance by given balance, rate, and period number. | |
// The calcuation is expensive due to some limitations of current EVM. | |
// Probably can be optimized in later improved EVM implementations. | |
function calculateNewBalance(uint balance, uint rate, uint periodNumber) constant returns (uint){ | |
uint result = balance; | |
for(uint ix = 0; ix < periodNumber; ix++){ | |
result = result * rate / 10000; | |
} | |
return result; | |
} | |
// Calculate deducted new blanace of the given address. | |
// All interest will go to the _minter. | |
function calculateBalance(address addr) { | |
uint balance = _balances[addr]; | |
if(balance > 0) { | |
uint periodNumber = (block.number - _lastCalculated[addr]) / _period; | |
uint newBalance = calculateNewBalance(balance, _rate, periodNumber); | |
uint interest = balance - newBalance; | |
_balances[_minter] = _balances[_minter] + interest; | |
_balances[addr] = newBalance; | |
_lastCalculated[addr] = _lastCalculated[addr] + _period * periodNumber; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment