Created
May 19, 2017 13:23
-
-
Save anonymous/7fc3f3a48ad3e8b26aa1a7c55030c64f to your computer and use it in GitHub Desktop.
Created using browser-solidity: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://ethereum.github.io/browser-solidity/#version=soljson-v0.4.11+commit.68ef5810.js&optimize=undefined&gist=
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; | |
//© copyright 2017 - Catallax Bank and Rivvir Consulting | |
// Developed by Austin Fatheree | |
// http://catallax.info @hypercatallax | |
// All rights reserved. | |
contract DecayToken { | |
struct Rate { | |
uint256 nextblock; | |
uint256 rate; | |
bool initialized; | |
} | |
uint256 public totalSupply; | |
uint256 public startBlock; //holds the generation block for the contract so that we know where to start our linked list for decay rates | |
uint256 public demurrageHold; | |
uint256 public rateBase; | |
uint256 public maxCatchUpBlock; | |
mapping(address => uint256) balance; | |
mapping(address => uint256) catchUpBlock; | |
mapping(uint256 => Rate) rateMap; | |
string public name; //fancy name: eg Simon Bucks | |
uint8 public decimals; //How many decimals to show. ie. There could 1000 base units with 3 decimals. Meaning 0.980 SBX = 980 base units. It's like comparing 1 wei to 1 ether. | |
string public symbol; //An identifier: eg SBX | |
string public version = 'H0.1'; //human 0.1 standard. Just an arbitrary versioning scheme. | |
function () { | |
//if ether is sent to this address, send it back. | |
throw; | |
} | |
function DecayToken( | |
uint256 _initialAmount, | |
string _tokenName, | |
uint8 _decimalUnits, | |
string _tokenSymbol | |
){ | |
balance[msg.sender] = _initialAmount; // Give the creator all initial tokens | |
totalSupply = _initialAmount; // Update total supply | |
name = _tokenName; // Set the name for display purposes | |
decimals = _decimalUnits; // Amount of decimals for display purposes | |
symbol = _tokenSymbol; // Set the symbol for display purposes | |
//record the startblock that the currency came online -- used for cycling through rates | |
startBlock = block.number; | |
//create the first rate that goes from block 0 to the start block | |
rateMap[0].initialized = true; | |
rateMap[0].rate = 0; | |
rateMap[0].nextblock = startBlock; | |
//init the next rate | |
rateMap[startBlock].initialized = true; | |
//set the max catchup to the current block | |
maxCatchUpBlock = block.number; | |
rateBase = 10000000; //base used for rates. | |
} | |
//erc20 interface | |
function balanceOf( address who ) constant returns (uint value){ | |
//todo: check validity | |
return balance[who]; | |
} | |
function transfer( address to, uint value) returns (bool ok){ | |
if(value == 0) throw; | |
//test catch up | |
if(catchUpBlock[msg.sender] < maxCatchUpBlock) throw; | |
//make sure balance is positive | |
if(balance[msg.sender] < value) throw; | |
//update balances | |
balance[msg.sender] = balance[msg.sender] - value; | |
balance[to] = balance[to] + value; | |
Transfer(msg.sender, to, value); | |
return true; | |
} | |
function addRate(uint _startBlock, uint _endBlock, uint amount) returns (bool ok){ | |
if(rateMap[_startBlock].initialized == false) throw; //a rate doesnt exist for this startblock | |
if(rateMap[_endBlock].initialized != false) throw; //we cant correct rates here only append | |
//set the new rate | |
rateMap[_startBlock].nextblock = _endBlock; | |
rateMap[_startBlock].rate = amount; | |
rateMap[_endBlock].initialized = true; | |
//update the maxCatchUpBlock for everyoune | |
maxCatchUpBlock = _endBlock; | |
return true; | |
} | |
function getRate(uint _startBlock) constant returns(uint _TheRate, uint _EndBlock){ | |
_TheRate = rateMap[_startBlock].rate; | |
_EndBlock = rateMap[_startBlock].nextblock; | |
} | |
function catchup(address account) returns (bool ok){ | |
//todo: issuer can force catchup | |
if(msg.sender != account) throw; | |
uint transferAmount = 0; //the amount that will decay | |
uint nextblock = catchUpBlock[account]; //lookup the current catchup block for this account | |
uint startBalance = balance[account]; //lookup the current balance of an account | |
//loop through each rate from the last catch up to maxCatchUpBlock and decay the cash | |
while(nextblock < maxCatchUpBlock){ | |
Rate thisrate = rateMap[nextblock]; //what was the rate during this period? | |
uint removeAmount = (startBalance * thisrate.rate)/rateBase; //calculate the amount | |
transferAmount = transferAmount + removeAmount; //store the amount | |
startBalance = startBalance - removeAmount; //adjust balance used in calc so we don't go below 0 | |
nextblock = thisrate.nextblock; // update nextblock to advance loop | |
//todo: scheme to check remaining gas and bail if gas gets too low | |
} | |
balance[account] = balance[account] - transferAmount; //update the balance | |
demurrageHold = demurrageHold + transferAmount; //put the decayed amount into a place for everyone to see | |
catchUpBlock[account] = maxCatchUpBlock; //update the catchup block allowing the account to spend | |
CatchUp(account, maxCatchUpBlock, transferAmount); //broadcast catchup so issuer can act | |
return true; | |
} | |
event CatchUp(address indexed from, uint newMaxBlock, uint value); | |
event Transfer( address indexed from, address indexed to, uint value); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment