pragma solidity ^0.4.24;
library SafeMath {
function mul(uint a, uint b) internal pure returns (uint) {
uint c = a * b;
require(a == 0 || c / a == b);
return c;
}
function div(uint a, uint b) internal pure returns (uint) {
uint c = a / b;
return c;
}
function sub(uint a, uint b) internal pure returns (uint) {
require(b <= a);
return a - b;
}
function add(uint a, uint b) internal pure returns (uint) {
uint c = a + b;
require(c >= a);
return c;
}
function max(uint a, uint b) internal pure returns (uint) {
return a >= b ? a : b;
}
function min(uint a, uint b) internal pure returns (uint) {
return a < b ? a : b;
}
}
// @title The Contract is Mongolian National MDEX Token Issue.
//
// @Author: Tim Wars
// @Date: 2018.8.1
// @Seealso: ERC20
//
contract MntToken {
// === Event ===
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
event Burn(address indexed from, uint value);
event TransferLocked(address indexed from, address indexed to, uint value, uint8 locktype);
event Purchased(address indexed recipient, uint purchase, uint amount);
// === Defined ===
using SafeMath for uint;
// --- Owner Section ---
address public owner;
bool public frozen = false; //
// --- ERC20 Token Section ---
uint8 constant public decimals = 6;
uint public totalSupply = 100*10**(8+uint256(decimals)); // ***** 100 * 100 Million
string constant public name = "MDEX Platform Token | Mongolia National Blockchain Digital Assets Exchange Token";
string constant public symbol = "MNT";
mapping(address => uint) ownerance; // Owner Balance
mapping(address => mapping(address => uint)) public allowance; // Allower Balance
// --- Locked Section ---
uint8 LOCKED_TYPE_MAX = 2; // ***** Max locked type
uint private constant RELEASE_BASE_TIME = 1533686888; // ***** (2018-08-08 08:08:08) Private Lock phase start datetime (UTC seconds)
address[] private lockedOwner;
mapping(address => uint) public lockedance; // Lockeder Balance
mapping(address => uint8) public lockedtype; // Locked Type
mapping(address => uint8) public unlockedstep; // Unlocked Step
uint public totalCirculating; // Total circulating token amount
// === Modifier ===
// --- Owner Section ---
modifier isOwner() {
require(msg.sender == owner);
_;
}
modifier isNotFrozen() {
require(!frozen);
_;
}
// --- ERC20 Section ---
modifier hasEnoughBalance(uint _amount) {
require(ownerance[msg.sender] >= _amount);
_;
}
modifier overflowDetected(address _owner, uint _amount) {
require(ownerance[_owner] + _amount >= ownerance[_owner]);
_;
}
modifier hasAllowBalance(address _owner, address _allower, uint _amount) {
require(allowance[_owner][_allower] >= _amount);
_;
}
modifier isNotEmpty(address _addr, uint _value) {
require(_addr != address(0));
require(_value != 0);
_;
}
modifier isValidAddress {
assert(0x0 != msg.sender);
_;
}
// --- Locked Section ---
modifier hasntLockedBalance(address _checker) {
require(lockedtype[_checker] == 0);
_;
}
modifier checkLockedType(uint8 _locktype) {
require(_locktype > 0 && _locktype <= LOCKED_TYPE_MAX);
_;
}
// === Constructor ===
constructor() public {
owner = msg.sender;
ownerance[msg.sender] = totalSupply;
totalCirculating = totalSupply;
emit Transfer(address(0), msg.sender, totalSupply);
}
// --- ERC20 Token Section ---
function approve(address _spender, uint _value)
isNotFrozen
isValidAddress
public returns (bool success)
{
require(_value == 0 || allowance[msg.sender][_spender] == 0); // must spend to 0 where pre approve balance.
allowance[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
function transferFrom(address _from, address _to, uint _value)
isNotFrozen
isValidAddress
overflowDetected(_to, _value)
public returns (bool success)
{
require(ownerance[_from] >= _value);
require(allowance[_from][msg.sender] >= _value);
ownerance[_to] = ownerance[_to].add(_value);
ownerance[_from] = ownerance[_from].sub(_value);
allowance[_from][msg.sender] = allowance[_from][msg.sender].sub(_value);
emit Transfer(_from, _to, _value);
return true;
}
function balanceOf(address _owner) public
constant returns (uint balance)
{
balance = ownerance[_owner] + lockedance[_owner];
return balance;
}
function available(address _owner) public
constant returns (uint)
{
return ownerance[_owner];
}
function transfer(address _to, uint _value) public
isNotFrozen
isValidAddress
isNotEmpty(_to, _value)
hasEnoughBalance(_value)
overflowDetected(_to, _value)
returns (bool success)
{
ownerance[msg.sender] = ownerance[msg.sender].sub(_value);
ownerance[_to] = ownerance[_to].add(_value);
emit Transfer(msg.sender, _to, _value);
return true;
}
// --- Owner Section ---
function transferOwner(address _newOwner)
isOwner
public returns (bool success)
{
if (_newOwner != address(0)) {
owner = _newOwner;
}
return true;
}
function freeze()
isOwner
public returns (bool success)
{
frozen = true;
return true;
}
function unfreeze()
isOwner
public returns (bool success)
{
frozen = false;
return true;
}
function burn(uint _value)
isNotFrozen
isValidAddress
hasEnoughBalance(_value)
public returns (bool success)
{
ownerance[msg.sender] = ownerance[msg.sender].sub(_value);
ownerance[0x0] = ownerance[0x0].add(_value);
totalSupply = totalSupply.sub(_value);
totalCirculating = totalCirculating.sub(_value);
emit Burn(msg.sender, _value);
return true;
}
// --- Locked Section ---
function transferLocked(address _to, uint _value, uint8 _locktype) public
isNotFrozen
isOwner
isValidAddress
isNotEmpty(_to, _value)
hasEnoughBalance(_value)
hasntLockedBalance(_to)
checkLockedType(_locktype)
returns (bool success)
{
require(msg.sender != _to);
ownerance[msg.sender] = ownerance[msg.sender].sub(_value);
if (_locktype == 1) {
lockedance[_to] = _value;
lockedtype[_to] = _locktype;
lockedOwner.push(_to);
totalCirculating = totalCirculating.sub(_value);
emit TransferLocked(msg.sender, _to, _value, _locktype);
} else if (_locktype == 2) {
uint _first = _value / 100 * 8; // prevent overflow
ownerance[_to] = ownerance[_to].add(_first);
lockedance[_to] = _value.sub(_first);
lockedtype[_to] = _locktype;
lockedOwner.push(_to);
totalCirculating = totalCirculating.sub(_value.sub(_first));
emit Transfer(msg.sender, _to, _first);
emit TransferLocked(msg.sender, _to, _value.sub(_first), _locktype);
}
return true;
}
// *****
// Because too many unlocking steps * accounts, it will burn lots of GAS !!!!!!!!!!!!!!!!!!!!!!!!!!!
// Because too many unlocking steps * accounts, it will burn lots of GAS !!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// LockedType 1 : after 6 monthes / release 10 % per month; 10 steps
// LockedType 2 : before 0 monthes / release 8 % per month; 11 steps / 1 step has release real balance init.
function unlock(address _locker, uint _delta, uint8 _locktype) private
returns (bool success)
{
if (_locktype == 1) {
if (_delta < 6 * 30 days) {
return false;
}
uint _more1 = _delta.sub(6 * 30 days);
uint _step1 = _more1 / 30 days;
for(uint8 i = 0; i < 10; i++) {
if (unlockedstep[_locker] == i && i < 9 && i <= _step1 ) {
ownerance[_locker] = ownerance[_locker].add(lockedance[_locker] / (10 - i));
lockedance[_locker] = lockedance[_locker].sub(lockedance[_locker] / (10 - i));
unlockedstep[_locker] = i + 1;
} else if (i == 9 && unlockedstep[_locker] == 9 && _step1 == 9){
ownerance[_locker] = ownerance[_locker].add(lockedance[_locker]);
lockedance[_locker] = 0;
unlockedstep[_locker] = 0;
lockedtype[_locker] = 0;
}
}
} else if (_locktype == 2) {
if (_delta < 30 days) {
return false;
}
uint _more2 = _delta - 30 days;
uint _step2 = _more2 / 30 days;
for(uint8 j = 0; j < 11; j++) {
if (unlockedstep[_locker] == j && j < 10 && j <= _step2 ) {
ownerance[_locker] = ownerance[_locker].add(lockedance[_locker] / (11 - j));
lockedance[_locker] = lockedance[_locker].sub(lockedance[_locker] / (11 - j));
unlockedstep[_locker] = j + 1;
} else if (j == 10 && unlockedstep[_locker] == 10 && _step2 == 10){
ownerance[_locker] = ownerance[_locker].add(lockedance[_locker]);
lockedance[_locker] = 0;
unlockedstep[_locker] = 0;
lockedtype[_locker] = 0;
}
}
}
return true;
}
function lockedCounts() public view
returns (uint counts)
{
return lockedOwner.length;
}
function releaseLocked() public
isNotFrozen
returns (bool success)
{
require(now > RELEASE_BASE_TIME);
uint delta = now - RELEASE_BASE_TIME;
uint lockedAmount;
for (uint i = 0; i < lockedOwner.length; i++) {
if ( lockedance[lockedOwner[i]] > 0) {
lockedAmount = lockedance[lockedOwner[i]];
unlock(lockedOwner[i], delta, lockedtype[lockedOwner[i]]);
totalCirculating = totalCirculating.add(lockedAmount - lockedance[lockedOwner[i]]);
}
}
return true;
}
}
{
"compilationTarget": {
"MntToken.sol": "MntToken"
},
"evmVersion": "byzantium",
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[],"name":"frozen","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"available","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"lockedtype","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lockedCounts","outputs":[{"name":"counts","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"burn","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalCirculating","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwner","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"releaseLocked","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"freeze","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unfreeze","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"unlockedstep","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_locktype","type":"uint8"}],"name":"transferLocked","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"lockedance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"locktype","type":"uint8"}],"name":"TransferLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"recipient","type":"address"},{"indexed":false,"name":"purchase","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Purchased","type":"event"}]