The earlier crowdsale example combined token accounting with time-dependent acceptance of ETH. Its source recorded a March 2018 start, a March 2019 bonus cutoff, and a March 2020 end. These are closed historical dates, not an active sale.
The recorded mechanics
The note started supply at zero, minted on accepted payment, transferred the resulting tokens to the sender, and forwarded ETH to an owner. Its stated conversion rates were 100 tokens per ETH normally and 150 during the bonus period. These are example contract parameters, not a value or return claim.
Read the historical Solidity 0.4.21 contract
pragma solidity 0.4.21;
/**
ICO CrowdSale token contract
Abstract
Start date : Tuesday, March 27, 2018 5:31:11 PM GMT+07:00
Bonus end date : Wednesday, March 27, 2019 5:31:11 PM GMT+07:00
End date : Thursday, March 26, 2020 5:31:11 PM GMT+07:00
Normal price : 100 NKEM Tokens per 1 ETH
Bonus price : 150 NKEM Tokens per 1 ETH
Contract address: https://ropsten.etherscan.io/address/0xbb3c7bf0b58e23ea2ff9567fcc7ef8235cfe49b7
Token address : https://ropsten.etherscan.io/token/0xbb3c7bf0b58e23ea2ff9567fcc7ef8235cfe49b7
First transfer : https://ropsten.etherscan.io/tx/0xbd59b2562c589bb2a3736b590f9c046237134a167e495e52c3776429178c5908
Deployed at : 0xbb3c7bf0b58e23ea2ff9567fcc7ef8235cfe49b7
Symbol : NKEM
Name : NKem Token
Decimals : 18
@ nhancv MIT license
*/
// ---------------------------------------------------------------------
// ERC-20 Token Standard Interface
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
// ---------------------------------------------------------------------
contract ERC20Interface {
/**
Returns the name of the token - e.g. "MyToken"
*/
string public name;
/**
Returns the symbol of the token. E.g. "HIX".
*/
string public symbol;
/**
Returns the number of decimals the token uses - e. g. 8
*/
uint8 public decimals;
/**
Returns the total token supply.
*/
uint256 public totalSupply;
/**
Returns the account balance of another account with address _owner.
*/
function balanceOf(address _owner) public view returns (uint256 balance);
/**
Transfers _value amount of tokens to address _to, and MUST fire the Transfer event.
The function SHOULD throw if the _from account balance does not have enough tokens to spend.
*/
function transfer(address _to, uint256 _value) public returns (bool success);
/**
Transfers _value amount of tokens from address _from to address _to, and MUST fire the Transfer event.
*/
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
/**
Allows _spender to withdraw from your account multiple times, up to the _value amount.
If this function is called again it overwrites the current allowance with _value.
*/
function approve(address _spender, uint256 _value) public returns (bool success);
/**
Returns the amount which _spender is still allowed to withdraw from _owner.
*/
function allowance(address _owner, address _spender) public view returns (uint256 remaining);
/**
MUST trigger when tokens are transferred, including zero value transfers.
*/
event Transfer(address indexed _from, address indexed _to, uint256 _value);
/**
MUST trigger on any successful call to approve(address _spender, uint256 _value).
*/
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
/**
Owned contract
*/
contract Owned {
address public owner;
address public newOwner;
event OwnershipTransferred(address indexed _from, address indexed _to);
function Owned() public {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function transferOwnership(address _newOwner) public onlyOwner {
newOwner = _newOwner;
}
function acceptOwnership() public {
require(msg.sender == newOwner);
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
newOwner = address(0);
}
}
/**
Function to receive approval and execute function in one call.
*/
contract TokenRecipient {
function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public;
}
/**
Token implement
*/
contract Token is ERC20Interface, Owned {
mapping (address => uint256) public balances;
mapping (address => mapping (address => uint256)) public allowed;
// This notifies clients about the amount burnt
event Burn(address indexed from, uint256 value);
function balanceOf(address _owner) public view returns (uint256 balance) {
return balances[_owner];
}
function transfer(address _to, uint256 _value) public returns (bool success) {
_transfer(msg.sender, _to, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(_value <= allowed[_from][msg.sender]);
allowed[_from][msg.sender] -= _value;
_transfer(_from, _to, _value);
return true;
}
function approve(address _spender, uint256 _value) public returns (bool success) {
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
return allowed[_owner][_spender];
}
/**
Owner can transfer out any accidentally sent ERC20 tokens
*/
function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) {
return ERC20Interface(tokenAddress).transfer(owner, tokens);
}
/**
Approves and then calls the receiving contract
*/
function approveAndCall(address _spender, uint256 _value, bytes _extraData) public returns (bool success) {
TokenRecipient spender = TokenRecipient(_spender);
approve(_spender, _value);
spender.receiveApproval(msg.sender, _value, this, _extraData);
return true;
}
/**
Destroy tokens.
Remove `_value` tokens from the system irreversibly
*/
function burn(uint256 _value) public returns (bool success) {
require(balances[msg.sender] >= _value);
balances[msg.sender] -= _value;
totalSupply -= _value;
emit Burn(msg.sender, _value);
return true;
}
/**
Destroy tokens from other account.
Remove `_value` tokens from the system irreversibly on behalf of `_from`.
*/
function burnFrom(address _from, uint256 _value) public returns (bool success) {
require(balances[_from] >= _value);
require(_value <= allowed[_from][msg.sender]);
balances[_from] -= _value;
allowed[_from][msg.sender] -= _value;
totalSupply -= _value;
emit Burn(_from, _value);
return true;
}
/**
Internal transfer, only can be called by this contract
*/
function _transfer(address _from, address _to, uint _value) internal {
// Prevent transfer to 0x0 address. Use burn() instead
require(_to != 0x0);
// Check if the sender has enough
require(balances[_from] >= _value);
// Check for overflows
require(balances[_to] + _value > balances[_to]);
// Save this for an assertion in the future
uint previousBalances = balances[_from] + balances[_to];
// Subtract from the sender
balances[_from] -= _value;
// Add the same to the recipient
balances[_to] += _value;
emit Transfer(_from, _to, _value);
// Asserts are used to use static analysis to find bugs in your code. They should never fail
assert(balances[_from] + balances[_to] == previousBalances);
}
}
contract NKEM is Token {
uint public startDate;
uint public bonusEnds;
uint public normalPrice;
uint public bonusPrice;
uint public endDate;
function NKEM() public {
name = "Nkem Token";
symbol = "NKEM";
decimals = 18;
totalSupply = 0;
startDate = now;
bonusEnds = startDate + 1 years;
endDate = startDate + 2 years;
normalPrice = 100;
bonusPrice = 150;
}
/**
If ether is sent to this address, send it back.
*/
function () public payable {
require(now >= startDate && now <= endDate);
uint tokens;
if (now <= bonusEnds) {
tokens = msg.value * bonusPrice;
} else {
tokens = msg.value * normalPrice;
}
balances[msg.sender] += tokens;
totalSupply += tokens;
emit Transfer(address(0), msg.sender, tokens);
owner.transfer(msg.value);
}
}
Time units, boundary comparisons, rounding, forwarding failures, ownership, arithmetic, and supply obligations need independent review before any reuse. The old compiler predates current Solidity behavior; this listing is not an audited fundraising implementation.
Source: Gist revision. No funds, contract, or token was moved or created for this revision.