├── migrations ├── 2_deploy_contracts.js └── 1_initial_migration.js ├── truffle.js ├── package.json ├── contracts ├── v0.1 │ ├── ERC20Basic.sol │ ├── ERC20.sol │ ├── SafeMath.sol │ ├── Ownable.sol │ ├── BasicToken.sol │ ├── ReservationStorage.sol │ ├── StandardToken.sol │ └── DMTokenContract.sol ├── Migrations.sol ├── v0.2 │ └── DMToken.sol └── v0.3 │ └── DMToken.sol ├── README.md └── LICENSE /migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | var DMToken = artifacts.require("./v0.2/DMToken.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(DMToken); 5 | }; 6 | -------------------------------------------------------------------------------- /migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./v0.2/Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8545, 6 | network_id: "*" // Match any network id 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dmarket-token", 3 | "description": "Cryptocurrency for trading any virtual in-game items on any platform globally", 4 | "author": "Ilya Sinyakin ", 5 | "license": "MIT", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/suntechsoft/dmarket-smartcontract.git" 9 | }, 10 | "dependencies": { 11 | "zeppelin-solidity": "^1.2.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /contracts/v0.1/ERC20Basic.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | /** 4 | * @title ERC20Basic 5 | * @dev Simpler version of ERC20 interface 6 | * @dev see https://github.com/ethereum/EIPs/issues/179 7 | */ 8 | contract ERC20Basic { 9 | uint256 public totalSupply; 10 | function balanceOf(address who) constant returns (uint256); 11 | function transfer(address to, uint256 value) returns (bool); 12 | event Transfer(address indexed from, address indexed to, uint256 value); 13 | } 14 | 15 | -------------------------------------------------------------------------------- /contracts/v0.1/ERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | import './ERC20Basic.sol'; 4 | 5 | /** 6 | * @title ERC20 interface 7 | * @dev see https://github.com/ethereum/EIPs/issues/20 8 | */ 9 | contract ERC20 is ERC20Basic { 10 | function allowance(address owner, address spender) constant returns (uint256); 11 | function transferFrom(address from, address to, uint256 value) returns (bool); 12 | function approve(address spender, uint256 value) returns (bool); 13 | event Approval(address indexed owner, address indexed spender, uint256 value); 14 | } 15 | 16 | -------------------------------------------------------------------------------- /contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.1; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## DMarket token 2 | 3 | Cryptocurrency for trading any virtual in-game items on any platform globally. 4 | 5 | ## Requirements 6 | 7 | To run tests you need to install the following software: 8 | 9 | - [Truffle v3.2.4](https://github.com/trufflesuite/truffle-core) 10 | - [EthereumJS TestRPC v3.0.5](https://github.com/ethereumjs/testrpc) 11 | - [Zeppelin Solidity v1.2.0](https://github.com/OpenZeppelin/zeppelin-solidity) 12 | 13 | ## How to test 14 | 15 | Open the terminal and run the following commands: 16 | 17 | ```sh 18 | $ cd dmarket-smartcontract 19 | $ truffle migrate 20 | ``` 21 | 22 | NOTE: All tests must be run separately as specified. 23 | 24 | 25 | ## Deployment 26 | 27 | To deploy smart contracts to live network do the following steps: 28 | 1. Go to the smart contract folder and run truffle console: 29 | ```sh 30 | $ cd dmarket-smartcontract 31 | $ truffle console 32 | ``` 33 | 2. Inside truffle console, invoke "migrate" command to deploy contracts: 34 | ```sh 35 | truffle> migrate 36 | ``` 37 | -------------------------------------------------------------------------------- /contracts/v0.1/SafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | /** 4 | * @title SafeMath 5 | * @dev Math operations with safety checks that throw on error 6 | */ 7 | library SafeMath { 8 | function mul(uint256 a, uint256 b) internal constant returns (uint256) { 9 | uint256 c = a * b; 10 | assert(a == 0 || c / a == b); 11 | return c; 12 | } 13 | 14 | function div(uint256 a, uint256 b) internal constant returns (uint256) { 15 | // assert(b > 0); // Solidity automatically throws when dividing by 0 16 | uint256 c = a / b; 17 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 18 | return c; 19 | } 20 | 21 | function sub(uint256 a, uint256 b) internal constant returns (uint256) { 22 | assert(b <= a); 23 | return a - b; 24 | } 25 | 26 | function add(uint256 a, uint256 b) internal constant returns (uint256) { 27 | uint256 c = a + b; 28 | assert(c >= a); 29 | return c; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contracts/v0.1/Ownable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | /** 4 | * @title Ownable 5 | * @dev The Ownable contract has an owner address, and provides basic authorization control 6 | * functions, this simplifies the implementation of "user permissions". 7 | */ 8 | contract Ownable { 9 | address public owner; 10 | 11 | /** 12 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender 13 | * account. 14 | */ 15 | function Ownable() { 16 | owner = msg.sender; 17 | } 18 | 19 | /** 20 | * @dev Throws if called by any account other than the owner. 21 | */ 22 | modifier onlyOwner() { 23 | assert(msg.sender == owner); 24 | _; 25 | } 26 | 27 | /** 28 | * @dev Allows the current owner to transfer control of the contract to a newOwner. 29 | * @param newOwner The address to transfer ownership to. 30 | */ 31 | function transferOwnership(address newOwner) onlyOwner { 32 | if (newOwner != address(0)) { 33 | owner = newOwner; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /contracts/v0.1/BasicToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | import './ERC20Basic.sol'; 4 | import './SafeMath.sol'; 5 | 6 | /** 7 | * @title Basic token 8 | * @dev Basic version of StandardToken, with no allowances. 9 | */ 10 | contract BasicToken is ERC20Basic { 11 | using SafeMath for uint256; 12 | 13 | mapping(address => uint256) balances; 14 | 15 | /** 16 | * @dev transfer token for a specified address 17 | * @param _to The address to transfer to. 18 | * @param _value The amount to be transferred. 19 | */ 20 | function transfer(address _to, uint256 _value) returns (bool) { 21 | balances[_to] = balances[_to].add(_value); 22 | Transfer(msg.sender, _to, _value); 23 | return true; 24 | } 25 | 26 | /** 27 | * @dev Gets the balance of the specified address. 28 | * @param _owner The address to query the the balance of. 29 | * @return An uint256 representing the amount owned by the passed address. 30 | */ 31 | function balanceOf(address _owner) constant returns (uint256 balance) { 32 | return balances[_owner]; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 SunTechSoft 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /contracts/v0.1/ReservationStorage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | import './Ownable.sol'; 4 | 5 | 6 | contract ReservationStorage is Ownable{ 7 | 8 | struct Box { 9 | address recipient; 10 | uint256 token; 11 | uint256 value; 12 | uint createAt; 13 | } 14 | 15 | /** 16 | * coinId => [ehterAccount => box ] 17 | */ 18 | mapping ( uint => mapping (address => Box[]) ) public storageEthereumData; 19 | mapping ( uint => mapping (bytes32 => Box[]) ) public storageCoinsData; 20 | 21 | function reservationFromEthereum(address _to, uint256 _value, uint _token) onlyOwner { 22 | require(_to != 0x0); 23 | storageEthereumData[0][_to].push(Box({ 24 | recipient: _to, 25 | token: _token, 26 | value:_value, 27 | createAt: now 28 | })); 29 | } 30 | 31 | function reservationFromBackend(uint coinId, bytes32 coinAccount, address etherAccount, uint256 value, uint token) onlyOwner { 32 | require(etherAccount != 0x0); 33 | 34 | storageCoinsData[coinId][coinAccount].push(Box({ 35 | recipient: etherAccount, 36 | token: token, 37 | value: value, 38 | createAt: now 39 | })); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /contracts/v0.2/DMToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | import 'zeppelin-solidity/contracts/token/StandardToken.sol'; 4 | import 'zeppelin-solidity/contracts/ownership/Ownable.sol'; 5 | 6 | contract MintableToken is StandardToken, Ownable { 7 | 8 | uint256 public hardCap; 9 | 10 | event Mint(address indexed to, uint256 amount); 11 | 12 | modifier canMint() { 13 | require(totalSupply == 0); 14 | _; 15 | } 16 | 17 | /** 18 | * @dev Function to mint tokens 19 | * @param _to The address that will receive the minted tokens. 20 | * @param _amount The amount of tokens to mint. 21 | * @return A boolean that indicates if the operation was successful. 22 | */ 23 | function mint(address _to, uint256 _amount) onlyOwner canMint public returns (bool) { 24 | require(_amount < hardCap); 25 | totalSupply = totalSupply.add(_amount); 26 | balances[_to] = balances[_to].add(_amount); 27 | Mint(_to, _amount); 28 | Transfer(0x0, _to, _amount); 29 | return true; 30 | } 31 | 32 | /** 33 | * @dev Function to stop minting new tokens. 34 | * @return True if the operation was successful. 35 | */ 36 | } 37 | contract DMToken is MintableToken { 38 | 39 | string public name = "DMarket Token"; 40 | string public symbol = "Mark"; 41 | uint256 public decimals = 8; 42 | 43 | function DMToken() { 44 | 45 | /** 46 | * 1-Phase: 36037245 * 10^8 tokens 47 | * 2-Phase: 100000000 * 10^8 tokens 48 | * Additionaly issued tokens: (36037245 + 100000000) % 15 = 20405587 * 10^8 tokens 49 | * HardCap will be equal to: 36037245 + 100000000 + 20405587 = 156442831 * 10^8 tokens 50 | */ 51 | hardCap = 15644283100000000; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /contracts/v0.1/StandardToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | import './ERC20.sol'; 4 | import './BasicToken.sol'; 5 | 6 | /** 7 | * @title Standard ERC20 token 8 | * 9 | * @dev Implementation of the basic standard token. 10 | * @dev https://github.com/ethereum/EIPs/issues/20 11 | * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol 12 | */ 13 | contract StandardToken is ERC20, BasicToken { 14 | 15 | mapping (address => mapping (address => uint256)) allowed; 16 | 17 | 18 | /** 19 | * @dev Transfer tokens from one address to another 20 | * @param _from address The address which you want to send tokens from 21 | * @param _to address The address which you want to transfer to 22 | * @param _value uint256 the amout of tokens to be transfered 23 | */ 24 | function transferFrom(address _from, address _to, uint256 _value) returns (bool) { 25 | var _allowance = allowed[_from][msg.sender]; 26 | 27 | // Check is not needed because sub(_allowance, _value) will already throw if this condition is not met 28 | // require (_value <= _allowance); 29 | 30 | balances[_to] = balances[_to].add(_value); 31 | balances[_from] = balances[_from].sub(_value); 32 | allowed[_from][msg.sender] = _allowance.sub(_value); 33 | Transfer(_from, _to, _value); 34 | return true; 35 | } 36 | 37 | /** 38 | * @dev Aprove the passed address to spend the specified amount of tokens on behalf of msg.sender. 39 | * @param _spender The address which will spend the funds. 40 | * @param _value The amount of tokens to be spent. 41 | */ 42 | function approve(address _spender, uint256 _value) returns (bool) { 43 | 44 | // To change the approve amount you first have to reduce the addresses` 45 | // allowance to zero by calling `approve(_spender, 0)` if it is not 46 | // already 0 to mitigate the race condition described here: 47 | // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 48 | require((_value == 0) || (allowed[msg.sender][_spender] == 0)); 49 | 50 | allowed[msg.sender][_spender] = _value; 51 | Approval(msg.sender, _spender, _value); 52 | return true; 53 | } 54 | 55 | /** 56 | * @dev Function to check the amount of tokens that an owner allowed to a spender. 57 | * @param _owner address The address which owns the funds. 58 | * @param _spender address The address which will spend the funds. 59 | * @return A uint256 specifing the amount of tokens still avaible for the spender. 60 | */ 61 | function allowance(address _owner, address _spender) constant returns (uint256 remaining) { 62 | return allowed[_owner][_spender]; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /contracts/v0.1/DMTokenContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | import './StandardToken.sol'; 4 | import './Ownable.sol'; 5 | 6 | 7 | contract DMarketToken is StandardToken, Ownable { 8 | string public constant name = "Dmarket token"; 9 | string public constant symbol = "DMT"; 10 | uint public constant decimals = 8; 11 | 12 | using SafeMath for uint256; 13 | 14 | // timestamps for first and second Steps 15 | uint public startFirstStep; 16 | uint public endFirstStep; 17 | uint public starSecondStep; 18 | uint public endSecondStep; 19 | 20 | // address where funds are collected 21 | address public wallet; 22 | 23 | // how many token units a buyer gets per wei 24 | uint256 public rate; 25 | 26 | uint256 public minTransactionAmount; 27 | 28 | uint256 public raisedForEther = 0; 29 | uint256 public raisedForBitCoin = 0; 30 | uint256 public raisedForSkin = 0; 31 | 32 | modifier inActivePeriod() { 33 | require((startFirstStep < now && now <= endFirstStep) || (starSecondStep < now && now <= endSecondStep)); 34 | _; 35 | } 36 | 37 | function DMarketToken(address _wallet, uint _startF, uint _endF, uint _startS, uint _endS) { 38 | require(_wallet != 0x0); 39 | require(_startF < _endF); 40 | require(_startS < _endS); 41 | 42 | // accumulation wallet 43 | wallet = _wallet; 44 | 45 | //50,000,000 Dmarket tokens 46 | totalSupply = 50000000; 47 | 48 | // 1 ETH = 1,000 Dmarket 49 | rate = 1000; 50 | 51 | // minimal invest 52 | minTransactionAmount = 0.1 ether; 53 | 54 | startFirstStep = _startF; 55 | endFirstStep = _endF; 56 | starSecondStep = _startS; 57 | endSecondStep = _endS; 58 | 59 | } 60 | 61 | function setupPeriodForFirstStep(uint _start, uint _end) onlyOwner { 62 | require(_start < _end); 63 | startFirstStep = _start; 64 | endFirstStep = _end; 65 | } 66 | 67 | function setupPeriodForSecondStep(uint _start, uint _end) onlyOwner { 68 | require(_start < _end); 69 | starSecondStep = _start; 70 | endSecondStep = _end; 71 | } 72 | 73 | // fallback function can be used to buy tokens 74 | function () inActivePeriod payable { 75 | buyTokens(msg.sender); 76 | } 77 | 78 | // low level token purchase function 79 | function buyTokens(address _sender) inActivePeriod payable { 80 | require(_sender != 0x0); 81 | require(msg.value >= minTransactionAmount); 82 | 83 | uint256 weiAmount = msg.value; 84 | 85 | raisedForEther = raisedForEther.add(weiAmount); 86 | 87 | // calculate token amount to be created 88 | uint256 tokens = weiAmount.mul(rate); 89 | tokens += getBonus(tokens); 90 | 91 | tokenReserve(_sender, tokens); 92 | 93 | forwardFunds(); 94 | } 95 | 96 | // send ether to the fund collection wallet 97 | // override to create custom fund forwarding mechanisms 98 | function forwardFunds() internal { 99 | wallet.transfer(msg.value); 100 | } 101 | 102 | /* 103 | * Step 1: 104 | * Day 1: +10% bonus 105 | * Day 2: +5% bonus 106 | * Day 3: +3% bonus 107 | * Day 4: no bonuses 108 | */ 109 | function getBonus(uint256 _tokens) constant returns (uint256 bonus) { 110 | require(_tokens != 0); 111 | if (1 == getCurrentPeriod()) { 112 | if (startFirstStep <= now && now < startFirstStep + 1 days) { 113 | return _tokens.div(10); 114 | } else if (startFirstStep + 1 days <= now && now < startFirstStep + 2 days ) { 115 | return _tokens.div(20); 116 | } else if (startFirstStep + 2 days <= now && now < startFirstStep + 3 days ) { 117 | return _tokens.mul(3).div(100); 118 | } 119 | } 120 | 121 | return 0; 122 | } 123 | 124 | function getCurrentPeriod() inActivePeriod constant returns (uint){ 125 | if ((startFirstStep < now && now <= endFirstStep)) { 126 | return 1; 127 | } else if ((starSecondStep < now && now <= endSecondStep)) { 128 | return 2; 129 | } else { 130 | return 0; 131 | } 132 | } 133 | 134 | function tokenReserve(address _to, uint256 _value) internal returns (bool) { 135 | balances[_to] = balances[_to].add(_value); 136 | Transfer(msg.sender, _to, _value); 137 | return true; 138 | } 139 | } -------------------------------------------------------------------------------- /contracts/v0.3/DMToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.18; 2 | 3 | import "github.com/OpenZeppelin/zeppelin-solidity/contracts/math/SafeMath.sol"; 4 | import "github.com/OpenZeppelin/zeppelin-solidity/contracts/token/ERC20Basic.sol"; 5 | import "github.com/OpenZeppelin/zeppelin-solidity/contracts/token/ERC20.sol"; 6 | import "github.com/OpenZeppelin/zeppelin-solidity/contracts/ownership/Ownable.sol"; 7 | 8 | contract ApprovalContract is ERC20 { 9 | using SafeMath for uint256; 10 | 11 | mapping (address => mapping (address => uint256)) public allowed; 12 | 13 | /** 14 | * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. 15 | * 16 | * Beware that changing an allowance with this method brings the risk that someone may use both the old 17 | * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this 18 | * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: 19 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 20 | * @param _spender The address which will spend the funds. 21 | * @param _value The amount of tokens to be spent. 22 | */ 23 | function approve(address _spender, uint256 _value) public returns (bool) { 24 | allowed[msg.sender][_spender] = _value; 25 | Approval(msg.sender, _spender, _value); 26 | return true; 27 | } 28 | 29 | /** 30 | * @dev Function to check the amount of tokens that an owner allowed to a spender. 31 | * @param _owner address The address which owns the funds. 32 | * @param _spender address The address which will spend the funds. 33 | * @return A uint256 specifying the amount of tokens still available for the spender. 34 | */ 35 | function allowance(address _owner, address _spender) public constant returns (uint256 remaining) { 36 | return allowed[_owner][_spender]; 37 | } 38 | 39 | /** 40 | * approve should be called when allowed[_spender] == 0. To increment 41 | * allowed value is better to use this function to avoid 2 calls (and wait until 42 | * the first transaction is mined) 43 | * From MonolithDAO Token.sol 44 | */ 45 | function increaseApproval (address _spender, uint _addedValue) public 46 | returns (bool success) { 47 | allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue); 48 | Approval(msg.sender, _spender, allowed[msg.sender][_spender]); 49 | return true; 50 | } 51 | 52 | function decreaseApproval (address _spender, uint _subtractedValue) public 53 | returns (bool success) { 54 | uint oldValue = allowed[msg.sender][_spender]; 55 | if (_subtractedValue > oldValue) { 56 | allowed[msg.sender][_spender] = 0; 57 | } else { 58 | allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue); 59 | } 60 | Approval(msg.sender, _spender, allowed[msg.sender][_spender]); 61 | return true; 62 | } 63 | } 64 | 65 | /** 66 | * @title Mintable token 67 | * @dev Simple ERC20 Token example, with mintable token creation 68 | * @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120 69 | * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol 70 | */ 71 | contract MintableToken is ApprovalContract, Ownable { 72 | 73 | uint256 public hardCap; 74 | mapping(address => uint256) public balances; 75 | 76 | event Mint(address indexed to, uint256 amount); 77 | 78 | modifier canMint() { 79 | require(totalSupply == 0); 80 | _; 81 | } 82 | 83 | /** 84 | * @dev Function to mint tokens 85 | * @param _to The address that will receive the minted tokens. 86 | * @param _amount The amount of tokens to mint. 87 | * @return A boolean that indicates if the operation was successful. 88 | */ 89 | function mint(address _to, uint256 _amount) onlyOwner canMint public returns (bool) { 90 | require(_amount < hardCap); 91 | totalSupply = totalSupply.add(_amount); 92 | balances[_to] = balances[_to].add(_amount); 93 | Mint(_to, _amount); 94 | Transfer(0x0, _to, _amount); 95 | return true; 96 | } 97 | } 98 | 99 | /** 100 | * @title Vesting token 101 | */ 102 | contract Vesting is MintableToken { 103 | 104 | event VestingMemberAdded(address indexed _address, uint256 _amount, uint _start, uint _end); 105 | 106 | struct _Vesting { 107 | uint256 totalSum; //total amount 108 | uint256 start; //start block 109 | uint256 end; //end block 110 | uint256 usedAmount; //the amount of paid payments 111 | } 112 | 113 | mapping (address => _Vesting ) public vestingMembers; 114 | 115 | function addVestingMember( 116 | address _address, 117 | uint256 _amount, 118 | uint256 _start, 119 | uint256 _end 120 | ) onlyOwner public returns (bool) { 121 | require( 122 | _address != address(0) && 123 | _amount > 0 && 124 | _start < _end && 125 | vestingMembers[_address].totalSum == 0 && 126 | balances[msg.sender] > _amount 127 | ); 128 | 129 | balances[msg.sender] = balances[msg.sender].sub(_amount); 130 | 131 | vestingMembers[_address].totalSum = _amount; //total amount 132 | vestingMembers[_address].start = _start; //start block 133 | vestingMembers[_address].end = _end; //end block 134 | vestingMembers[_address].usedAmount = 0; //the amount of paid payments 135 | 136 | VestingMemberAdded(_address, _amount, _start, _end); 137 | 138 | return true; 139 | } 140 | 141 | function currentPart(address _address) private constant returns (uint256) { 142 | if (vestingMembers[_address].totalSum == 0 || block.number <= vestingMembers[_address].start) { 143 | return 0; 144 | } 145 | if (block.number >= vestingMembers[_address].end) { 146 | return vestingMembers[_address].totalSum.sub(vestingMembers[_address].usedAmount); 147 | } 148 | 149 | return vestingMembers[_address].totalSum 150 | .mul(block.number - vestingMembers[_address].start) 151 | .div(vestingMembers[_address].end - vestingMembers[_address].start) 152 | .sub(vestingMembers[_address].usedAmount); 153 | } 154 | 155 | function subFromBalance(address _address, uint256 _amount) private returns (uint256) { 156 | require(_address != address(0)); 157 | 158 | if (vestingMembers[_address].totalSum == 0) { 159 | balances[_address] = balances[_address].sub(_amount); 160 | return balances[_address]; 161 | } 162 | uint256 summary = balanceOf(_address); 163 | require(summary >= _amount); 164 | 165 | if (balances[_address] > _amount) { 166 | balances[_address] = balances[_address].sub(_amount); 167 | } else { 168 | uint256 part = currentPart(_address); 169 | if (block.number >= vestingMembers[_address].end) { 170 | vestingMembers[_address].totalSum = 0; //total amount 171 | vestingMembers[_address].start = 0; //start block 172 | vestingMembers[_address].end = 0; //end block 173 | vestingMembers[_address].usedAmount = 0; //the amount of paid payments 174 | } else { 175 | vestingMembers[_address].usedAmount = vestingMembers[_address].usedAmount.add(part); 176 | } 177 | balances[_address] = balances[_address].add(part).sub(_amount); 178 | } 179 | 180 | return balances[_address]; 181 | } 182 | 183 | function balanceOf(address _owner) public constant returns (uint256 balance) { 184 | if (vestingMembers[_owner].totalSum == 0) { 185 | return balances[_owner]; 186 | } else { 187 | return balances[_owner].add(currentPart(_owner)); 188 | } 189 | } 190 | 191 | function transfer(address _to, uint256 _value) public returns (bool) { 192 | require(_to != address(0)); 193 | require(_value <= balanceOf(msg.sender)); 194 | 195 | subFromBalance(msg.sender, _value); 196 | 197 | balances[_to] = balances[_to].add(_value); 198 | Transfer(msg.sender, _to, _value); 199 | return true; 200 | } 201 | 202 | function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { 203 | require(_to != address(0)); 204 | 205 | uint256 _allowance = allowed[_from][msg.sender]; 206 | 207 | subFromBalance(_from, _value); 208 | 209 | balances[_to] = balances[_to].add(_value); 210 | allowed[_from][msg.sender] = _allowance.sub(_value); 211 | Transfer(_from, _to, _value); 212 | return true; 213 | } 214 | } 215 | 216 | 217 | contract DMToken is Vesting { 218 | 219 | string public name = "DMarket Token"; 220 | string public symbol = "DMT"; 221 | uint256 public decimals = 8; 222 | 223 | function DMToken() public { 224 | hardCap = 15644283100000000; 225 | } 226 | 227 | function multiTransfer(address[] recipients, uint256[] amounts) public { 228 | require(recipients.length == amounts.length); 229 | for (uint i = 0; i < recipients.length; i++) { 230 | transfer(recipients[i], amounts[i]); 231 | } 232 | } 233 | 234 | function multiVesting( 235 | address[] _address, 236 | uint256[] _amount, 237 | uint256[] _start, 238 | uint256[] _end 239 | ) public onlyOwner { 240 | require( 241 | _address.length == _amount.length && 242 | _address.length == _start.length && 243 | _address.length == _end.length 244 | ); 245 | for (uint i = 0; i < _address.length; i++) { 246 | addVestingMember(_address[i], _amount[i], _start[i], _end[i]); 247 | } 248 | } 249 | } --------------------------------------------------------------------------------