/** * Source Code first verified at https://etherscan.io on Wednesday, May 8, 2019 (UTC) */ pragma solidity 0.5.4; /** * @title SafeMath * @dev Math operations with safety checks that throw on error */ library SafeMath { /** * @dev Multiplies two numbers, throws on overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { // Gas optimization: this is cheaper than asserting 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (a == 0) { return 0; } c = a * b; assert(c / a == b); return c; } /** * @dev Integer division of two numbers, truncating the quotient. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // assert(b > 0); // Solidity automatically throws when dividing by 0 // uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return a / b; } /** * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } /** * @dev Adds two numbers, throws on overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256 c) { c = a + b; assert(c >= a); return c; } } /** * @title MultiOwnable * * @dev Require majority approval of multiple owners to use and access to features * when restrictions on access to critical functions are required. * */ contract MultiOwnable { using SafeMath for uint8; struct CommitteeStatusPack{ /** * Key informations for decisions. * To save some gas, choosing the struct. */ uint8 numOfOwners; uint8 numOfVotes; uint8 numOfMinOwners; bytes proposedFuncData; } CommitteeStatusPack public committeeStatus; address[] public ballot; // To make sure if it already was voted mapping(address => bool) public owner; event Vote(address indexed proposer, bytes indexed proposedFuncData); event Propose(address indexed proposer, bytes indexed proposedFuncData); event Dismiss(address indexed proposer, bytes indexed proposedFuncData); event AddedOwner(address newOwner); event RemovedOwner(address removedOwner); event TransferOwnership(address from, address to); /** * Organize initial committee. * * @notice committee must be 3 at least. * you have to use this contract to be inherited because it is internal. * * @param _coOwner1 _coOwner2 _coOwner3 _coOwner4 _coOwner5 committee members */ constructor(address _coOwner1, address _coOwner2, address _coOwner3, address _coOwner4, address _coOwner5) internal { require(_coOwner1 != address(0x0) && _coOwner2 != address(0x0) && _coOwner3 != address(0x0) && _coOwner4 != address(0x0) && _coOwner5 != address(0x0)); require(_coOwner1 != _coOwner2 && _coOwner1 != _coOwner3 && _coOwner1 != _coOwner4 && _coOwner1 != _coOwner5 && _coOwner2 != _coOwner3 && _coOwner2 != _coOwner4 && _coOwner2 != _coOwner5 && _coOwner3 != _coOwner4 && _coOwner3 != _coOwner5 && _coOwner4 != _coOwner5); // SmartDec Recommendations owner[_coOwner1] = true; owner[_coOwner2] = true; owner[_coOwner3] = true; owner[_coOwner4] = true; owner[_coOwner5] = true; committeeStatus.numOfOwners = 5; committeeStatus.numOfMinOwners = 5; emit AddedOwner(_coOwner1); emit AddedOwner(_coOwner2); emit AddedOwner(_coOwner3); emit AddedOwner(_coOwner4); emit AddedOwner(_coOwner5); } modifier onlyOwner() { require(owner[msg.sender]); _; } /** * Pre-check if it's decided by committee * * @notice If there is a majority approval, * the function with this modifier will not be executed. */ modifier committeeApproved() { /* check if proposed Function Name and real function Name are correct */ require( keccak256(committeeStatus.proposedFuncData) == keccak256(msg.data) ); // SmartDec Recommendations /* To check majority */ require(committeeStatus.numOfVotes > committeeStatus.numOfOwners.div(2)); _; _dismiss(); //Once a commission-approved proposal is made, the proposal is initialized. } /** * Suggest the functions you want to use. * * @notice To use some importan functions, propose function must be done first and voted. */ function propose(bytes memory _targetFuncData) onlyOwner public { /* Check if there're any ongoing proposals */ require(committeeStatus.numOfVotes == 0); require(committeeStatus.proposedFuncData.length == 0); /* regist function informations that proposer want to run */ committeeStatus.proposedFuncData = _targetFuncData; emit Propose(msg.sender, _targetFuncData); } /** * Proposal is withdrawn * * @notice When the proposed function is no longer used or deprecated, * proposal is discarded */ function dismiss() onlyOwner public { _dismiss(); } /** * Suggest the functions you want to use. * * @notice 'dismiss' is executed even after successfully executing the proposed function. * If 'msg.sender' want to pass permission, he can't pass the 'committeeApproved' modifier. * internal functions are required to enable this. */ function _dismiss() internal { emit Dismiss(msg.sender, committeeStatus.proposedFuncData); committeeStatus.numOfVotes = 0; committeeStatus.proposedFuncData = ""; delete ballot; } /** * Owners vote for proposed item * * @notice if only there're proposals, 'vote' is processed. * the result must be majority. * one ticket for each owner. */ function vote() onlyOwner public { // Check duplicated voting list. uint length = ballot.length; // SmartDec Recommendations for(uint i=0; i committeeStatus.numOfVotes); // SmartDec Recommendations committeeStatus.numOfVotes++; ballot.push(msg.sender); emit Vote(msg.sender, committeeStatus.proposedFuncData); } /** * Existing owner transfers permissions to new owner. * * @notice It transfers authority to the person who was not the owner. * Approval from the committee is required. */ function transferOwnership(address _newOwner) onlyOwner committeeApproved public { require( _newOwner != address(0x0) ); // callisto recommendation require( owner[_newOwner] == false ); owner[msg.sender] = false; owner[_newOwner] = true; emit TransferOwnership(msg.sender, _newOwner); } /** * Add new Owner to committee * * @notice Approval from the committee is required. * */ function addOwner(address _newOwner) onlyOwner committeeApproved public { require( _newOwner != address(0x0) ); require( owner[_newOwner] != true ); owner[_newOwner] = true; committeeStatus.numOfOwners++; emit AddedOwner(_newOwner); } /** * Remove the Owner from committee * * @notice Approval from the committee is required. * */ function removeOwner(address _toRemove) onlyOwner committeeApproved public { require( _toRemove != address(0x0) ); require( owner[_toRemove] == true ); require( committeeStatus.numOfOwners > committeeStatus.numOfMinOwners ); // must keep Number of Minimum Owners at least. owner[_toRemove] = false; committeeStatus.numOfOwners--; emit RemovedOwner(_toRemove); } } contract Pausable is MultiOwnable { event Pause(); event Unpause(); bool internal paused; modifier whenNotPaused() { require(!paused); _; } modifier whenPaused() { require(paused); _; } modifier noReentrancy() { require(!paused); paused = true; _; paused = false; } /* When you discover your smart contract is under attack, you can buy time to upgrade the contract by immediately pausing the contract. */ function pause() public onlyOwner committeeApproved whenNotPaused { paused = true; emit Pause(); } function unpause() public onlyOwner committeeApproved whenPaused { paused = false; emit Unpause(); } } /** * Contract Managing TokenExchanger's address used by ProxyNemodax */ contract RunningContractManager is Pausable { address public implementation; //SmartDec Recommendations event Upgraded(address indexed newContract); function upgrade(address _newAddr) onlyOwner committeeApproved external { require(implementation != _newAddr); implementation = _newAddr; emit Upgraded(_newAddr); // SmartDec Recommendations } /* SmartDec Recommendations function runningAddress() onlyOwner external view returns (address){ return implementation; } */ } /** * NemoLab ERC20 Token * Written by Shin HyunJae * version 12 */ contract TokenERC20 is RunningContractManager { using SafeMath for uint256; // Public variables of the token string public name; string public symbol; uint8 public decimals = 18; // 18 decimals is the strongly suggested default, avoid changing it uint256 public totalSupply; /* This creates an array with all balances */ mapping (address => uint256) internal balances; mapping (address => mapping (address => uint256)) internal allowed; //mapping (address => bool) public frozenAccount; // SmartDec Recommendations mapping (address => uint256) public frozenExpired; //bool private initialized = false; bool private initialized; // SmartDec Recommendations /** * This is area for some variables to add. * Please add variables from the end of pre-declared variables * if you would have added some variables and re-deployed the contract, * tokenPerEth would get garbage value. so please reset tokenPerEth variable * * uint256 something..; */ // This generates a public event on the blockchain that will notify clients event Transfer(address indexed from, address indexed to, uint256 value); event LastBalance(address indexed account, uint256 value); // This notifies clients about the allowance of balance event Approval(address indexed _owner, address indexed _spender, uint256 _value); // This notifies clients about the amount burnt // event Burn(address indexed from, uint256 value); // callisto recommendation // This notifies clients about the freezing address //event FrozenFunds(address target, bool frozen); // callisto recommendation event FrozenFunds(address target, uint256 expirationDate); // SmartDec Recommendations /** * Initialize Token Function * * Initializes contract with initial supply tokens to the creator of the contract */ function initToken( string memory _tokenName, string memory _tokenSymbol, uint256 _initialSupply, address _marketSaleManager, address _serviceOperationManager, address _dividendManager, address _incentiveManager, address _reserveFundManager ) internal onlyOwner committeeApproved { require( initialized == false ); require(_initialSupply > 0 && _initialSupply <= 2**uint256(184)); // [2019.03.05] Fixed for Mythril Vulerablity SWC ID:101 => _initialSupply <= 2^184 <= (2^256 / 10^18) name = _tokenName; // Set the name for display purposes symbol = _tokenSymbol; // Set the symbol for display purposes //totalSupply = convertToDecimalUnits(_initialSupply); // Update total supply with the decimal amount /*balances[msg.sender] = totalSupply; // Give the creator all initial tokens emit Transfer(address(this), address(0), totalSupply); emit LastBalance(address(this), 0); emit LastBalance(msg.sender, totalSupply);*/ // SmartDec Recommendations uint256 tempSupply = convertToDecimalUnits(_initialSupply); uint256 dividendBalance = tempSupply.div(10); // dividendBalance = 10% uint256 reserveFundBalance = dividendBalance; // reserveFundBalance = 10% uint256 marketSaleBalance = tempSupply.div(5); // marketSaleBalance = 20% uint256 serviceOperationBalance = marketSaleBalance.mul(2); // serviceOperationBalance = 40% uint256 incentiveBalance = marketSaleBalance; // incentiveBalance = 20% balances[_marketSaleManager] = marketSaleBalance; balances[_serviceOperationManager] = serviceOperationBalance; balances[_dividendManager] = dividendBalance; balances[_incentiveManager] = incentiveBalance; balances[_reserveFundManager] = reserveFundBalance; totalSupply = tempSupply; emit Transfer(address(0), _marketSaleManager, marketSaleBalance); emit Transfer(address(0), _serviceOperationManager, serviceOperationBalance); emit Transfer(address(0), _dividendManager, dividendBalance); emit Transfer(address(0), _incentiveManager, incentiveBalance); emit Transfer(address(0), _reserveFundManager, reserveFundBalance); emit LastBalance(address(this), 0); emit LastBalance(_marketSaleManager, marketSaleBalance); emit LastBalance(_serviceOperationManager, serviceOperationBalance); emit LastBalance(_dividendManager, dividendBalance); emit LastBalance(_incentiveManager, incentiveBalance); emit LastBalance(_reserveFundManager, reserveFundBalance); assert( tempSupply == marketSaleBalance.add(serviceOperationBalance). add(dividendBalance). add(incentiveBalance). add(reserveFundBalance) ); initialized = true; } /** * Convert tokens units to token decimal units * * @param _value Tokens units without decimal units */ function convertToDecimalUnits(uint256 _value) internal view returns (uint256 value) { value = _value.mul(10 ** uint256(decimals)); return value; } /** * Get tokens balance * * @notice Query tokens balance of the _account * * @param _account Account address to query tokens balance */ function balanceOf(address _account) public view returns (uint256 balance) { balance = balances[_account]; return balance; } /** * Get allowed tokens balance * * @notice Query tokens balance allowed to _spender * * @param _owner Owner address to query tokens balance * @param _spender The address allowed tokens balance */ function allowance(address _owner, address _spender) external view returns (uint256 remaining) { remaining = allowed[_owner][_spender]; return remaining; } /** * Internal transfer, only can be called by this contract */ function _transfer(address _from, address _to, uint256 _value) internal { require(_to != address(0x0)); // Prevent transfer to 0x0 address. require(balances[_from] >= _value); // Check if the sender has enough if(frozenExpired[_from] != 0 ){ // Check if sender is frozen require(block.timestamp > frozenExpired[_from]); _unfreezeAccount(_from); } if(frozenExpired[_to] != 0 ){ // Check if recipient is frozen require(block.timestamp > frozenExpired[_to]); _unfreezeAccount(_to); } uint256 previousBalances = balances[_from].add(balances[_to]); // Save this for an assertion in the future balances[_from] = balances[_from].sub(_value); // Subtract from the sender balances[_to] = balances[_to].add(_value); // Add the same to the recipient emit Transfer(_from, _to, _value); emit LastBalance(_from, balances[_from]); emit LastBalance(_to, balances[_to]); // Asserts are used to use static analysis to find bugs in your code. They should never fail assert(balances[_from] + balances[_to] == previousBalances); } /** * Transfer tokens * * @notice Send `_value` tokens to `_to` from your account * * @param _to The address of the recipient * @param _value the amount to send */ function transfer(address _to, uint256 _value) public noReentrancy returns (bool success) { _transfer(msg.sender, _to, _value); success = true; return success; } /** * Transfer tokens from other address * * Send `_value` tokens to `_to` on behalf of `_from` * * @param _from The address of the sender * @param _to The address of the recipient * @param _value the amount to send */ function transferFrom(address _from, address _to, uint256 _value) public noReentrancy returns (bool success) { require(_value <= allowed[_from][msg.sender]); // Check allowance allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); _transfer(_from, _to, _value); success = true; return success; } /** * Internal approve, only can be called by this contract * * @param _spender The address authorized to spend * @param _value the max amount they can spend */ function _approve(address _spender, uint256 _value) internal returns (bool success) { allowed[msg.sender][_spender] = _value; emit Approval(msg.sender, _spender, _value); success = true; return success; } /** * Set allowance for other address * * Allows `_spender` to spend no more than `_value` tokens on your behalf * * @param _spender The address authorized to spend * @param _value the max amount they can spend */ function approve(address _spender, uint256 _value) public noReentrancy returns (bool success) { success = _approve(_spender, _value); return success; } /** * @dev Increase the amount of tokens that an owner allowed to a spender. * approve should be called when allowed[_spender] == 0. To increment * allowed value is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol * @param _spender The address which will spend the funds. * @param _addedValue The amount of tokens to increase the allowance by. */ function increaseApproval(address _spender, uint256 _addedValue) public returns (bool) { allowed[msg.sender][_spender] = ( allowed[msg.sender][_spender].add(_addedValue)); emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; } /** * @dev Decrease the amount of tokens that an owner allowed to a spender. * approve should be called when allowed[_spender] == 0. To decrement * allowed value is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol * @param _spender The address which will spend the funds. * @param _subtractedValue The amount of tokens to decrease the allowance by. */ function decreaseApproval(address _spender, uint256 _subtractedValue) public returns (bool) { uint256 oldValue = allowed[msg.sender][_spender]; if (_subtractedValue >= oldValue) { allowed[msg.sender][_spender] = 0; } else { allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue); } emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; } /// @notice `freeze? Prevent` `target` from sending & receiving tokens /// @param target Address to be frozen function freezeAccount(address target, uint256 freezeExpiration) onlyOwner committeeApproved public { frozenExpired[target] = freezeExpiration; //emit FrozenFunds(target, true); emit FrozenFunds(target, freezeExpiration); // SmartDec Recommendations } /// @notice `freeze? Allow` `target` from sending & receiving tokens /// @notice if expiration date was over, when this is called with transfer transaction, auto-unfreeze is occurred without committeeApproved /// the reason why it's separated from wrapper function. /// @param target Address to be unfrozen function _unfreezeAccount(address target) internal returns (bool success) { frozenExpired[target] = 0; //emit FrozenFunds(target, false); emit FrozenFunds(target, 0); // SmartDec Recommendations success = true; return success; } /// @notice _unfreezeAccount wrapper function. /// @param target Address to be unfrozen function unfreezeAccount(address target) onlyOwner committeeApproved public returns(bool success) { success = _unfreezeAccount(target); return success; } } /** * @title TokenExchanger * @notice This is for exchange between Ether and 'Nemo' token * It won't be needed after being listed on the exchange. */ contract TokenExchanger is TokenERC20{ using SafeMath for uint256; uint256 internal tokenPerEth; bool public opened; event ExchangeEtherToToken(address indexed from, uint256 etherValue, uint256 tokenPerEth); event ExchangeTokenToEther(address indexed from, uint256 etherValue, uint256 tokenPerEth); event WithdrawToken(address indexed to, uint256 value); event WithdrawEther(address indexed to, uint256 value); event SetExchangeRate(address indexed from, uint256 tokenPerEth); constructor(address _coOwner1, address _coOwner2, address _coOwner3, address _coOwner4, address _coOwner5) MultiOwnable( _coOwner1, _coOwner2, _coOwner3, _coOwner4, _coOwner5) public { opened = true; } /** * Initialize Exchanger Function * * Initialize Exchanger contract with tokenPerEth * and Initialize NemoCoin by calling initToken * It would call initToken in TokenERC20 with _tokenName, _tokenSymbol, _initalSupply * Last five arguments are manager account to supply currency (_marketSaleManager, _serviceOperationManager, _dividendManager, _incentiveManager, _reserveFundManager) * */ function initExchanger( string calldata _tokenName, string calldata _tokenSymbol, uint256 _initialSupply, uint256 _tokenPerEth, address _marketSaleManager, address _serviceOperationManager, address _dividendManager, address _incentiveManager, address _reserveFundManager ) external onlyOwner committeeApproved { require(opened); //require(_tokenPerEth > 0 && _initialSupply > 0); // [2019.03.05] Fixed for Mythril Vulerablity SWC ID:101 require(_tokenPerEth > 0); // SmartDec Recommendations require(_marketSaleManager != address(0) && _serviceOperationManager != address(0) && _dividendManager != address(0) && _incentiveManager != address(0) && _reserveFundManager != address(0)); require(_marketSaleManager != _serviceOperationManager && _marketSaleManager != _dividendManager && _marketSaleManager != _incentiveManager && _marketSaleManager != _reserveFundManager && _serviceOperationManager != _dividendManager && _serviceOperationManager != _incentiveManager && _serviceOperationManager != _reserveFundManager && _dividendManager != _incentiveManager && _dividendManager != _reserveFundManager && _incentiveManager != _reserveFundManager); // SmartDec Recommendations super.initToken(_tokenName, _tokenSymbol, _initialSupply, // SmartDec Recommendations _marketSaleManager, _serviceOperationManager, _dividendManager, _incentiveManager, _reserveFundManager ); tokenPerEth = _tokenPerEth; emit SetExchangeRate(msg.sender, tokenPerEth); } /** * Change tokenPerEth variable only by owner * * Because "TokenExchaner" is only used until be listed on the exchange, * tokenPerEth is needed by then and it would be managed by manager. */ function setExchangeRate(uint256 _tokenPerEth) onlyOwner committeeApproved external returns (bool success){ require(opened); require( _tokenPerEth > 0); tokenPerEth = _tokenPerEth; emit SetExchangeRate(msg.sender, tokenPerEth); success = true; return success; } function getExchangerRate() external view returns(uint256){ return tokenPerEth; } /** * Exchange Ether To Token * * @notice Send `Nemo` tokens to msg sender as much as amount of ether received considering exchangeRate. */ function exchangeEtherToToken() payable external noReentrancy returns (bool success){ require(opened); uint256 tokenPayment; uint256 ethAmount = msg.value; require(ethAmount > 0); require(tokenPerEth != 0); tokenPayment = ethAmount.mul(tokenPerEth); super._transfer(address(this), msg.sender, tokenPayment); emit ExchangeEtherToToken(msg.sender, msg.value, tokenPerEth); success = true; return success; } /** * Exchange Token To Ether * * @notice Send Ether to msg sender as much as amount of 'Nemo' Token received considering exchangeRate. * * @param _value Amount of 'Nemo' token */ function exchangeTokenToEther(uint256 _value) external noReentrancy returns (bool success){ require(opened); require(tokenPerEth != 0); uint256 remainingEthBalance = address(this).balance; uint256 etherPayment = _value.div(tokenPerEth); uint256 remainder = _value % tokenPerEth; // [2019.03.06 Fixing Securify vulnerabilities-Division influences Transfer Amount] require(remainingEthBalance >= etherPayment); uint256 tokenAmount = _value.sub(remainder); // [2019.03.06 Fixing Securify vulnerabilities-Division influences Transfer Amount] super._transfer(msg.sender, address(this), tokenAmount); // [2019.03.06 Fixing Securify vulnerabilities-Division influences Transfer Amount] //require(address(msg.sender).send(etherPayment)); address(msg.sender).transfer(etherPayment); // SmartDec Recommendations emit ExchangeTokenToEther(address(this), etherPayment, tokenPerEth); success = true; return success; } /** * Withdraw token from TokenExchanger contract * * @notice Withdraw charged Token to _recipient. * * @param _recipient The address to which the token was issued. * @param _value Amount of token to withdraw. */ function withdrawToken(address _recipient, uint256 _value) onlyOwner committeeApproved noReentrancy public { //require(opened); super._transfer(address(this) ,_recipient, _value); emit WithdrawToken(_recipient, _value); } /** * Withdraw Ether from TokenExchanger contract * * @notice Withdraw charged Ether to _recipient. * * @param _recipient The address to which the Ether was issued. * @param _value Amount of Ether to withdraw. */ function withdrawEther(address payable _recipient, uint256 _value) onlyOwner committeeApproved noReentrancy public { //require(opened); //require(_recipient.send(_value)); _recipient.transfer(_value); // SmartDec Recommendations emit WithdrawEther(_recipient, _value); } /** * close the TokenExchanger functions permanently * * @notice This contract would be closed when the coin is actively traded and judged that its TokenExchanger function is not needed. */ function closeExchanger() onlyOwner committeeApproved external { opened = false; } } /** * @title NemodaxStorage * * @dev This is contract for proxyNemodax data order list. * Contract shouldn't be changed as possible. * If it should be edited, please add from the end of the contract . */ contract NemodaxStorage is RunningContractManager { // Never ever change the order of variables below!!!! // Public variables of the token string public name; string public symbol; uint8 public decimals = 18; // 18 decimals is the strongly suggested default, avoid changing it uint256 public totalSupply; /* This creates an array with all balances */ mapping (address => uint256) internal balances; mapping (address => mapping (address => uint256)) internal allowed; mapping (address => uint256) public frozenExpired; // SmartDec Recommendations bool private initialized; uint256 internal tokenPerEth; bool public opened = true; } /** * @title ProxyNemodax * * @dev The only fallback function will forward transaction to TokenExchanger Contract. * and the result of calculation would be stored in ProxyNemodax * */ contract ProxyNemodax is NemodaxStorage { /* Initialize new committee. this will be real committee accounts, not from TokenExchanger contract */ constructor(address _coOwner1, address _coOwner2, address _coOwner3, address _coOwner4, address _coOwner5) MultiOwnable( _coOwner1, _coOwner2, _coOwner3, _coOwner4, _coOwner5) public {} function () payable external { address localImpl = implementation; require(localImpl != address(0x0)); assembly { let ptr := mload(0x40) switch calldatasize case 0 { } // just to receive ethereum default{ calldatacopy(ptr, 0, calldatasize) let result := delegatecall(gas, localImpl, ptr, calldatasize, 0, 0) let size := returndatasize returndatacopy(ptr, 0, size) switch result case 0 { revert(ptr, size) } default { return(ptr, size) } } } } }