Modum Token
ERC20
This contract is an ERC20 token.
Name
Modum Token
Symbol
MOD
Decimals
0
Total Supply
21,266,200 MOD
About
Stats
Public Functions
21
Event Types
4
Code Size
19,367 bytes
Library Use
Uses SafeMath for uint256.
Events (4) keyboard_arrow_up
Structs (2) keyboard_arrow_up
Constants (7) keyboard_arrow_up
State Variables (10) keyboard_arrow_up
Functions
balanceOf keyboard_arrow_up
transfer keyboard_arrow_up
Source Code
function transfer(address _to, uint256 _value) public returns (bool success) {
require(mintDone);
require(_value > 0);
Account memory tmpFrom = accounts[msg.sender];
require(tmpFrom.valueMod >= _value);
Account storage from = updateAccount(msg.sender, UpdateMode.Both);
Account storage to = updateAccount(_to, UpdateMode.Both);
from.valueMod = from.valueMod.sub(_value);
to.valueMod = to.valueMod.add(_value);
Transfer(msg.sender, _to, _value);
return true;
}
allowance keyboard_arrow_up
transferFrom keyboard_arrow_up
Source Code
function transferFrom(
address _from,
address _to,
uint256 _value
) public returns (bool success) {
require(mintDone);
require(_value > 0);
Account memory tmpFrom = accounts[_from];
require(tmpFrom.valueMod >= _value);
require(allowed[_from][msg.sender] >= _value);
Account storage from = updateAccount(_from, UpdateMode.Both);
Account storage to = updateAccount(_to, UpdateMode.Both);
from.valueMod = from.valueMod.sub(_value);
to.valueMod = to.valueMod.add(_value);
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
Transfer(msg.sender, _to, _value);
return true;
}
approve keyboard_arrow_up
Requirements help
One or more of the following:
Source Code
function approve(address _spender, uint256 _value) public returns (bool) {
// To change the approve amount you first have to reduce the addresses`
// allowance to zero by calling `approve(_spender, 0)` if it is not
// already 0 to mitigate the race condition described here:
// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
require((_value == 0) || (allowed[msg.sender][_spender] == 0));
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
transferOwnership keyboard_arrow_up
Requirements help
Source Code
function transferOwnership(address _newOwner) public {
require(msg.sender == owner);
require(_newOwner != address(0));
owner = _newOwner;
}
votingProposal keyboard_arrow_up
Source Code
function votingProposal(
string _addr,
bytes32 _hash,
uint256 _value
) public {
require(msg.sender == owner); // proposal ony by onwer
require(!isProposalActive()); // no proposal is active, cannot vote in parallel
require(_value <= lockedTokens); //proposal cannot be larger than remaining locked tokens
require(_value > 0); //there needs to be locked tokens to make proposal, at least 1 locked token
require(_hash != bytes32(0)); //hash need to be set
require(bytes(_addr).length > 0); //the address need to be set and non-empty
require(mintDone); //minting phase needs to be over
//in case of negative vote, wait 90 days. If no lastNegativeVoting have
//occured, lastNegativeVoting is 0 and now is always larger than 14.1.1970
//(1.1.1970 plus blockingDuration).
require(now >= lastNegativeVoting.add(blockingDuration));
currentProposal = Proposal(_addr, _hash, _value, now, 0, 0);
}
vote keyboard_arrow_up
Source Code
function vote(bool _vote) public returns (uint256) {
require(isVoteOngoing()); // vote needs to be ongoing
Account storage account = updateAccount(msg.sender, UpdateMode.Vote);
uint256 votes = account.valueModVote; //available votes
require(votes > 0); //voter must have a vote left, either by not voting yet, or have modum tokens
if (_vote) {
currentProposal.yay = currentProposal.yay.add(votes);
} else {
currentProposal.nay = currentProposal.nay.add(votes);
}
account.valueModVote = 0;
Voted(msg.sender, _vote, votes);
return votes;
}
showVotes keyboard_arrow_up
Source Code
function showVotes(address _addr) public constant returns (uint256) {
Account memory account = accounts[_addr];
if (
account.lastProposalStartTime < currentProposal.startTime || // the user did set his token power yet
(account.lastProposalStartTime == 0 && currentProposal.startTime == 0)
) {
return account.valueMod;
}
return account.valueModVote;
}
claimVotingProposal keyboard_arrow_up
Parameters help
This function has no parameters.
Requirements help
Source Code
function claimVotingProposal() public {
require(msg.sender == owner); //only owner can claim proposal
require(isProposalActive()); // proposal active
require(isVotingPhaseOver()); // voting has already ended
if (
currentProposal.yay > currentProposal.nay && currentProposal.valueMod > 0
) {
//Vote was accepted
Account storage account = updateAccount(owner, UpdateMode.Both);
uint256 valueMod = currentProposal.valueMod;
account.valueMod = account.valueMod.add(valueMod); //add tokens to owner
totalSupply = totalSupply.add(valueMod);
lockedTokens = lockedTokens.sub(valueMod);
} else if (currentProposal.yay <= currentProposal.nay) {
//in case of a negative vote, set the time of this negative
//vote to the end of the negative voting period.
//This will prevent any new voting to be conducted.
lastNegativeVoting = currentProposal.startTime.add(votingDuration);
}
delete currentProposal; //proposal ended
}
isProposalActive keyboard_arrow_up
isVoteOngoing keyboard_arrow_up
Parameters help
This function has no parameters.
Source Code
function isVoteOngoing() public constant returns (bool) {
return
isProposalActive() &&
now >= currentProposal.startTime &&
now < currentProposal.startTime.add(votingDuration);
//its safe to use it for longer periods:
//https://ethereum.stackexchange.com/questions/6795/is-block-timestamp-safe-for-longer-time-periods
}
isVotingPhaseOver keyboard_arrow_up
Parameters help
This function has no parameters.
Source Code
function isVotingPhaseOver() public constant returns (bool) {
//its safe to use it for longer periods:
//https://ethereum.stackexchange.com/questions/6795/is-block-timestamp-safe-for-longer-time-periods
return now >= currentProposal.startTime.add(votingDuration);
}
mint keyboard_arrow_up
Requirements help
Source Code
function mint(address[] _recipient, uint256[] _value) public {
require(msg.sender == owner); //only owner can claim proposal
require(!mintDone); //only during minting
//require(_recipient.length == _value.length); //input need to be of same size
//we know what we are doing... remove check to save gas
//we want to mint a couple of accounts
for (uint8 i = 0; i < _recipient.length; i++) {
//require(lockedTokens.add(totalSupply).add(_value[i]) <= maxTokens);
//do the check in the mintDone
//121 gas can be saved by creating temporary variables
address tmpRecipient = _recipient[i];
uint256 tmpValue = _value[i];
//no need to update account, as we have not set minting to true. This means
//nobody can start a proposal (isVoteOngoing() is always false) and airdrop
//cannot be done either totalDropPerUnlockedToken is 0 thus, bonus is always
//zero.
Account storage account = accounts[tmpRecipient];
account.valueMod = account.valueMod.add(tmpValue);
//if this remains 0, we cannot calculate the time period when the user claimed
//his airdrop, thus, set it to now
account.lastAirdropClaimTime = now;
totalSupply = totalSupply.add(tmpValue); //create the tokens and add to recipient
Transfer(msg.sender, tmpRecipient, tmpValue);
}
}
setMintDone keyboard_arrow_up
Parameters help
This function has no parameters.
Requirements help
Source Code
function setMintDone() public {
require(msg.sender == owner);
require(!mintDone); //only in minting phase
//here we check that we never exceed the 30mio max tokens. This includes
//the locked and the unlocked tokens.
require(lockedTokens.add(totalSupply) <= maxTokens);
mintDone = true; //end the minting
}
constructor keyboard_arrow_up
Parameters help
This function has no parameters.
Source Code
function() public payable {
require(mintDone); //minting needs to be over
require(msg.sender == owner); //ETH payment need to be one-way only, from modum to tokenholders, confirmed by Lykke
payout(msg.value);
}
payBonus keyboard_arrow_up
Requirements help
Source Code
function payBonus(address[] _addr) public payable {
require(msg.sender == owner); //ETH payment need to be one-way only, from modum to tokenholders, confirmed by Lykke
uint256 totalWei = 0;
for (uint8 i = 0; i < _addr.length; i++) {
Account storage account = updateAccount(_addr[i], UpdateMode.Wei);
if (now >= account.lastAirdropClaimTime + redistributionTimeout) {
totalWei += account.bonusWei;
account.bonusWei = 0;
account.lastAirdropClaimTime = now;
} else {
revert();
}
}
payout(msg.value.add(totalWei));
}
showBonus keyboard_arrow_up
Source Code
function showBonus(address _addr) public constant returns (uint256) {
uint256 bonus = totalDropPerUnlockedToken.sub(accounts[_addr].lastAirdropWei);
if (bonus != 0) {
return accounts[_addr].bonusWei.add(bonus.mul(accounts[_addr].valueMod));
}
return accounts[_addr].bonusWei;
}
claimBonus keyboard_arrow_up
Parameters help
This function has no parameters.
Source Code
function claimBonus() public returns (uint256) {
require(mintDone); //minting needs to be over
Account storage account = updateAccount(msg.sender, UpdateMode.Wei);
uint256 sendValue = account.bonusWei; //fetch the values
if (sendValue != 0) {
account.bonusWei = 0; //set to zero (before, against reentry)
account.lastAirdropClaimTime = now; //mark as collected now
msg.sender.transfer(sendValue); //send the bonus to the correct account
return sendValue;
}
return 0;
}
increaseApproval keyboard_arrow_up
Source Code
function increaseApproval(address _spender, uint256 _addedValue)
public
returns (bool success)
{
allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(
_addedValue
);
Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
return true;
}
decreaseApproval keyboard_arrow_up
Source Code
function decreaseApproval(address _spender, uint256 _subtractedValue)
public
returns (bool success)
{
uint256 oldValue = allowed[msg.sender][_spender];
if (_subtractedValue > oldValue) {
allowed[msg.sender][_spender] = 0;
} else {
allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
}
Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
return true;
}
Internal Functions
Internal functions are parts of the contract that can't be used directly, but instead are used by the public functions listed above.
internal ModumToken.updateAccount keyboard_arrow_up
Source Code
function updateAccount(address _addr, UpdateMode mode)
internal
returns (Account storage)
{
Account storage account = accounts[_addr];
if (mode == UpdateMode.Vote || mode == UpdateMode.Both) {
if (
isVoteOngoing() &&
account.lastProposalStartTime < currentProposal.startTime
) {
// the user did set his token power yet
account.valueModVote = account.valueMod;
account.lastProposalStartTime = currentProposal.startTime;
}
}
if (mode == UpdateMode.Wei || mode == UpdateMode.Both) {
uint256 bonus = totalDropPerUnlockedToken.sub(account.lastAirdropWei);
if (bonus != 0) {
account.bonusWei = account.bonusWei.add(bonus.mul(account.valueMod));
account.lastAirdropWei = totalDropPerUnlockedToken;
}
}
return account;
}
internal ModumToken.payout keyboard_arrow_up
Source Code
function payout(uint256 valueWei) internal {
uint256 value = valueWei.add(rounding); //add old rounding
rounding = value % totalSupply; //ensure no rounding error
uint256 weiPerToken = value.sub(rounding).div(totalSupply);
totalDropPerUnlockedToken = totalDropPerUnlockedToken.add(weiPerToken); //account for locked tokens and add the drop
Payout(weiPerToken);
}