Skip to content

Instantly share code, notes, and snippets.

@Physes
Last active November 23, 2017 23:01
Show Gist options
  • Save Physes/21a1c622e62072e35085ee4a75b00f0d to your computer and use it in GitHub Desktop.
Save Physes/21a1c622e62072e35085ee4a75b00f0d to your computer and use it in GitHub Desktop.
Example funneling contract
pragma solidity ^0.4.18;
import "browser/SafeMath.sol";
import "browser/Ownable.sol";
import "browser/ESTToken.sol";
/**
* @title Example funneling contract
* @author Philip Saunders <[email protected]>
*/
contract Funnel is ESTToken, Ownable, SafeMath {
bool public onTarget; // true if token funneling is on target
uint constant epochLasts = 73 days; // amount of time per funneling interval
uint minSupplyAtEpoch; // minimum token supply during epoch
uint maxSupplyAtEpoch; // maximum token supply during epoch
uint epoch; // the current epoch (1-35)
uint tokenLaunchTime; // timestamp of token launch
event Burn(address from, uint value); // triggered when EST is burned
event OffTarget(uint minSupply, uint maxSupply); // triggered if funneling is off target
/// @dev constructor
/// @param _tokenLaunchTime Set timestamp to initiate funneling
function Funnel(uint _tokenLaunchTime) {
tokenLaunchTime = _tokenLaunchTime;
}
/// @dev Standard burn method
/// @param _value The amount of tokens to be burned
function burn(uint _value) public onlyOwner {
require(_value > 0);
require(_value <= balances[msg.sender]);
require(minSupplyAtEpoch < (totalSupply - _value));
balances[msg.sender] -= _value;
totalSupply -= _value;
Burn(msg.sender, _value);
}
/// @dev calculates an exponential decay function
/// @param _initialSupply The starting supply when EST is launched (i.e. 10^8)
/// @param _epoch The current epoch (new epoch every 73 days after tokenLaunchTime)
/// @return _minSupplyAtEpoch The resulting supply at given epoch
function decay(uint _initialSupply, uint _epoch) internal pure returns(uint _minSupplyAtEpoch) {
uint supply = mul(_initialSupply, 100); // multiply input by 100 for precision
for(uint i = 0; i < _epoch; i++) {
supply = sub(supply, div(supply, 50)); // reduces supply by 2% - 1/50
}
return div(supply, 100); // divide output by 100 before returning
}
/// @dev calculates the current epoch
/// @return _newepoch the result
function setEpoch() internal view returns(uint _newepoch) {
uint timeElapsed = sub(now, tokenLaunchTime);
// The equivalent of (timeElapsed - (timeElapsed % interval)) / interval;
return div(sub(timeElapsed, (timeElapsed % epochLasts)), epochLasts);
}
/// @dev the fallback function
/// @dev allows public to poll the contract to check if funneling is on target
function () public {
epoch = setEpoch(); // recalculate the present epoch
require(epoch < 36); // return if epoch is greater than 35
// recalculate target min and max supply at epoch
minSupplyAtEpoch = decay(initialSupply, epoch);
maxSupplyAtEpoch = decay(initialSupply, epoch - 1);
// check if totalSupply is within range of target
// if not set "onTarget" to false and trigger notification
if(totalSupply < minSupplyAtEpoch || totalSupply > maxSupplyAtEpoch) {
onTarget = false;
OffTarget(minSupplyAtEpoch, maxSupplyAtEpoch);
} else {
onTarget = true;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment