Skip to content

Instantly share code, notes, and snippets.

@yutelin
Created February 15, 2017 09:30
Show Gist options
  • Save yutelin/bfba53d11bcee899443a66f18ce2c09a to your computer and use it in GitHub Desktop.
Save yutelin/bfba53d11bcee899443a66f18ce2c09a to your computer and use it in GitHub Desktop.
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