From 0f5b286e2af45bb22693e2380a7b9eb07d8bb9c9 Mon Sep 17 00:00:00 2001 From: Larscola <32717463+Larscola@users.noreply.github.com> Date: Mon, 18 Dec 2023 15:35:33 +0300 Subject: [PATCH] contract report CMT --- CMT | 744 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 744 insertions(+) create mode 100644 CMT diff --git a/CMT b/CMT new file mode 100644 index 0000000..ed8219e --- /dev/null +++ b/CMT @@ -0,0 +1,744 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +pragma solidity ^0.4.23; + + +/** + * @title ERC20Basic + * @dev Simpler version of ERC20 interface + * @dev see https://github.com/ethereum/EIPs/issues/179 + */ +contract ERC20Basic { + function totalSupply() public view returns (uint256); + function balanceOf(address who) public view returns (uint256); + function transfer(address to, uint256 value) public returns (bool); + event Transfer(address indexed from, address indexed to, uint256 value); +} + + + +/** + * @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 Basic token + * @dev Basic version of StandardToken, with no allowances. + */ +contract BasicToken is ERC20Basic { + using SafeMath for uint256; + + mapping(address => uint256) balances; + + uint256 totalSupply_; + + /** + * @dev total number of tokens in existence + */ + function totalSupply() public view returns (uint256) { + return totalSupply_; + } + + /** + * @dev transfer token for a specified address + * @param _to The address to transfer to. + * @param _value The amount to be transferred. + */ + function transfer(address _to, uint256 _value) public returns (bool) { + require(_to != address(0)); + require(_value <= balances[msg.sender]); + + balances[msg.sender] = balances[msg.sender].sub(_value); + balances[_to] = balances[_to].add(_value); + emit Transfer(msg.sender, _to, _value); + return true; + } + + /** + * @dev Gets the balance of the specified address. + * @param _owner The address to query the the balance of. + * @return An uint256 representing the amount owned by the passed address. + */ + function balanceOf(address _owner) public view returns (uint256) { + return balances[_owner]; + } + +} + + +/** + * @title ERC20 interface + * @dev see https://github.com/ethereum/EIPs/issues/20 + */ +contract ERC20 is ERC20Basic { + function allowance(address owner, address spender) + public view returns (uint256); + + function transferFrom(address from, address to, uint256 value) + public returns (bool); + + function approve(address spender, uint256 value) public returns (bool); + event Approval( + address indexed owner, + address indexed spender, + uint256 value + ); +} + + +/** + * @title Standard ERC20 token + * + * @dev Implementation of the basic standard token. + * @dev https://github.com/ethereum/EIPs/issues/20 + * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol + */ +contract StandardToken is ERC20, BasicToken { + + mapping (address => mapping (address => uint256)) internal allowed; + + + /** + * @dev Transfer tokens from one address to another + * @param _from address The address which you want to send tokens from + * @param _to address The address which you want to transfer to + * @param _value uint256 the amount of tokens to be transferred + */ + function transferFrom( + address _from, + address _to, + uint256 _value + ) + public + returns (bool) + { + require(_to != address(0)); + require(_value <= balances[_from]); + require(_value <= allowed[_from][msg.sender]); + + balances[_from] = balances[_from].sub(_value); + balances[_to] = balances[_to].add(_value); + allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); + emit Transfer(_from, _to, _value); + return true; + } + + /** + * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. + * + * Beware that changing an allowance with this method brings the risk that someone may use both the old + * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this + * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * @param _spender The address which will spend the funds. + * @param _value The amount of tokens to be spent. + */ + function approve(address _spender, uint256 _value) public returns (bool) { + allowed[msg.sender][_spender] = _value; + emit Approval(msg.sender, _spender, _value); + return true; + } + + /** + * @dev Function to check the amount of tokens that an owner allowed to a spender. + * @param _owner address The address which owns the funds. + * @param _spender address The address which will spend the funds. + * @return A uint256 specifying the amount of tokens still available for the spender. + */ + function allowance( + address _owner, + address _spender + ) + public + view + returns (uint256) + { + return allowed[_owner][_spender]; + } + + /** + * @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, + uint _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, + uint _subtractedValue + ) + public + returns (bool) + { + uint 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; + } + +} + + + +/** + * @title Ownable + * @dev The Ownable contract has an owner address, and provides basic authorization control + * functions, this simplifies the implementation of "user permissions". + */ +contract Ownable { + address public owner; + + + event OwnershipRenounced(address indexed previousOwner); + event OwnershipTransferred( + address indexed previousOwner, + address indexed newOwner + ); + + + /** + * @dev The Ownable constructor sets the original `owner` of the contract to the sender + * account. + */ + constructor() public { + owner = msg.sender; + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + /** + * @dev Allows the current owner to relinquish control of the contract. + */ + function renounceOwnership() public onlyOwner { + emit OwnershipRenounced(owner); + owner = address(0); + } + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param _newOwner The address to transfer ownership to. + */ + function transferOwnership(address _newOwner) public onlyOwner { + _transferOwnership(_newOwner); + } + + /** + * @dev Transfers control of the contract to a newOwner. + * @param _newOwner The address to transfer ownership to. + */ + function _transferOwnership(address _newOwner) internal { + require(_newOwner != address(0)); + emit OwnershipTransferred(owner, _newOwner); + owner = _newOwner; + } +} + + +/** + * @title Mintable token + * @dev Simple ERC20 Token example, with mintable token creation + * @dev Issue: * https://github.com/OpenZeppelin/openzeppelin-solidity/issues/120 + * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol + */ +contract MintableToken is StandardToken, Ownable { + event Mint(address indexed to, uint256 amount); + event MintFinished(); + + bool public mintingFinished = false; + + + modifier canMint() { + require(!mintingFinished); + _; + } + + modifier hasMintPermission() { + require(msg.sender == owner); + _; + } + + /** + * @dev Function to mint tokens + * @param _to The address that will receive the minted tokens. + * @param _amount The amount of tokens to mint. + * @return A boolean that indicates if the operation was successful. + */ + function mint( + address _to, + uint256 _amount + ) + hasMintPermission + canMint + public + returns (bool) + { + totalSupply_ = totalSupply_.add(_amount); + balances[_to] = balances[_to].add(_amount); + emit Mint(_to, _amount); + emit Transfer(address(0), _to, _amount); + return true; + } + + /** + * @dev Function to stop minting new tokens. + * @return True if the operation was successful. + */ + function finishMinting() onlyOwner canMint public returns (bool) { + mintingFinished = true; + emit MintFinished(); + return true; + } +} + + +contract FreezableToken is StandardToken { + // freezing chains + mapping (bytes32 => uint64) internal chains; + // freezing amounts for each chain + mapping (bytes32 => uint) internal freezings; + // total freezing balance per address + mapping (address => uint) internal freezingBalance; + + event Freezed(address indexed to, uint64 release, uint amount); + event Released(address indexed owner, uint amount); + + /** + * @dev Gets the balance of the specified address include freezing tokens. + * @param _owner The address to query the the balance of. + * @return An uint256 representing the amount owned by the passed address. + */ + function balanceOf(address _owner) public view returns (uint256 balance) { + return super.balanceOf(_owner) + freezingBalance[_owner]; + } + + /** + * @dev Gets the balance of the specified address without freezing tokens. + * @param _owner The address to query the the balance of. + * @return An uint256 representing the amount owned by the passed address. + */ + function actualBalanceOf(address _owner) public view returns (uint256 balance) { + return super.balanceOf(_owner); + } + + function freezingBalanceOf(address _owner) public view returns (uint256 balance) { + return freezingBalance[_owner]; + } + + /** + * @dev gets freezing count + * @param _addr Address of freeze tokens owner. + */ + function freezingCount(address _addr) public view returns (uint count) { + uint64 release = chains[toKey(_addr, 0)]; + while (release != 0) { + count++; + release = chains[toKey(_addr, release)]; + } + } + + /** + * @dev gets freezing end date and freezing balance for the freezing portion specified by index. + * @param _addr Address of freeze tokens owner. + * @param _index Freezing portion index. It ordered by release date descending. + */ + function getFreezing(address _addr, uint _index) public view returns (uint64 _release, uint _balance) { + for (uint i = 0; i < _index + 1; i++) { + _release = chains[toKey(_addr, _release)]; + if (_release == 0) { + return; + } + } + _balance = freezings[toKey(_addr, _release)]; + } + + /** + * @dev freeze your tokens to the specified address. + * Be careful, gas usage is not deterministic, + * and depends on how many freezes _to address already has. + * @param _to Address to which token will be freeze. + * @param _amount Amount of token to freeze. + * @param _until Release date, must be in future. + */ + function freezeTo(address _to, uint _amount, uint64 _until) public { + require(_to != address(0)); + require(_amount <= balances[msg.sender]); + + balances[msg.sender] = balances[msg.sender].sub(_amount); + + bytes32 currentKey = toKey(_to, _until); + freezings[currentKey] = freezings[currentKey].add(_amount); + freezingBalance[_to] = freezingBalance[_to].add(_amount); + + freeze(_to, _until); + emit Transfer(msg.sender, _to, _amount); + emit Freezed(_to, _until, _amount); + } + + /** + * @dev release first available freezing tokens. + */ + function releaseOnce() public { + bytes32 headKey = toKey(msg.sender, 0); + uint64 head = chains[headKey]; + require(head != 0); + require(uint64(block.timestamp) > head); + bytes32 currentKey = toKey(msg.sender, head); + + uint64 next = chains[currentKey]; + + uint amount = freezings[currentKey]; + delete freezings[currentKey]; + + balances[msg.sender] = balances[msg.sender].add(amount); + freezingBalance[msg.sender] = freezingBalance[msg.sender].sub(amount); + + if (next == 0) { + delete chains[headKey]; + } else { + chains[headKey] = next; + delete chains[currentKey]; + } + emit Released(msg.sender, amount); + } + + /** + * @dev release all available for release freezing tokens. Gas usage is not deterministic! + * @return how many tokens was released + */ + function releaseAll() public returns (uint tokens) { + uint release; + uint balance; + (release, balance) = getFreezing(msg.sender, 0); + while (release != 0 && block.timestamp > release) { + releaseOnce(); + tokens += balance; + (release, balance) = getFreezing(msg.sender, 0); + } + } + + function toKey(address _addr, uint _release) internal pure returns (bytes32 result) { + // WISH masc to increase entropy + result = 0x5749534800000000000000000000000000000000000000000000000000000000; + assembly { + result := or(result, mul(_addr, 0x10000000000000000)) + result := or(result, and(_release, 0xffffffffffffffff)) + } + } + + function freeze(address _to, uint64 _until) internal { + require(_until > block.timestamp); + bytes32 key = toKey(_to, _until); + bytes32 parentKey = toKey(_to, uint64(0)); + uint64 next = chains[parentKey]; + + if (next == 0) { + chains[parentKey] = _until; + return; + } + + bytes32 nextKey = toKey(_to, next); + uint parent; + + while (next != 0 && _until > next) { + parent = next; + parentKey = nextKey; + + next = chains[nextKey]; + nextKey = toKey(_to, next); + } + + if (_until == next) { + return; + } + + if (next != 0) { + chains[key] = next; + } + + chains[parentKey] = _until; + } +} + + +/** + * @title Burnable Token + * @dev Token that can be irreversibly burned (destroyed). + */ +contract BurnableToken is BasicToken { + + event Burn(address indexed burner, uint256 value); + + /** + * @dev Burns a specific amount of tokens. + * @param _value The amount of token to be burned. + */ + function burn(uint256 _value) public { + _burn(msg.sender, _value); + } + + function _burn(address _who, uint256 _value) internal { + require(_value <= balances[_who]); + // no need to require value <= totalSupply, since that would imply the + // sender's balance is greater than the totalSupply, which *should* be an assertion failure + + balances[_who] = balances[_who].sub(_value); + totalSupply_ = totalSupply_.sub(_value); + emit Burn(_who, _value); + emit Transfer(_who, address(0), _value); + } +} + + + +/** + * @title Pausable + * @dev Base contract which allows children to implement an emergency stop mechanism. + */ +contract Pausable is Ownable { + event Pause(); + event Unpause(); + + bool public paused = false; + + + /** + * @dev Modifier to make a function callable only when the contract is not paused. + */ + modifier whenNotPaused() { + require(!paused); + _; + } + + /** + * @dev Modifier to make a function callable only when the contract is paused. + */ + modifier whenPaused() { + require(paused); + _; + } + + /** + * @dev called by the owner to pause, triggers stopped state + */ + function pause() onlyOwner whenNotPaused public { + paused = true; + emit Pause(); + } + + /** + * @dev called by the owner to unpause, returns to normal state + */ + function unpause() onlyOwner whenPaused public { + paused = false; + emit Unpause(); + } +} + + +contract FreezableMintableToken is FreezableToken, MintableToken { + /** + * @dev Mint the specified amount of token to the specified address and freeze it until the specified date. + * Be careful, gas usage is not deterministic, + * and depends on how many freezes _to address already has. + * @param _to Address to which token will be freeze. + * @param _amount Amount of token to mint and freeze. + * @param _until Release date, must be in future. + * @return A boolean that indicates if the operation was successful. + */ + function mintAndFreeze(address _to, uint _amount, uint64 _until) public onlyOwner canMint returns (bool) { + totalSupply_ = totalSupply_.add(_amount); + + bytes32 currentKey = toKey(_to, _until); + freezings[currentKey] = freezings[currentKey].add(_amount); + freezingBalance[_to] = freezingBalance[_to].add(_amount); + + freeze(_to, _until); + emit Mint(_to, _amount); + emit Freezed(_to, _until, _amount); + emit Transfer(msg.sender, _to, _amount); + return true; + } +} + + + +contract Consts { + uint public constant TOKEN_DECIMALS = 18; + uint8 public constant TOKEN_DECIMALS_UINT8 = 18; + uint public constant TOKEN_DECIMAL_MULTIPLIER = 10 ** TOKEN_DECIMALS; + + string public constant TOKEN_NAME = "CryptoMarketToken"; + string public constant TOKEN_SYMBOL = "CMT"; + bool public constant PAUSED = false; + address public constant TARGET_USER = 0x8fe6e7BeAf60b3dB5EDB3D28f6Cee815BD67dC6B; + + bool public constant CONTINUE_MINTING = false; +} + + + + +contract MainToken is Consts, FreezableMintableToken, BurnableToken, Pausable + +{ + + event Initialized(); + bool public initialized = false; + + constructor() public { + init(); + transferOwnership(TARGET_USER); + } + + + function name() public pure returns (string _name) { + return TOKEN_NAME; + } + + function symbol() public pure returns (string _symbol) { + return TOKEN_SYMBOL; + } + + function decimals() public pure returns (uint8 _decimals) { + return TOKEN_DECIMALS_UINT8; + } + + function transferFrom(address _from, address _to, uint256 _value) public returns (bool _success) { + require(!paused); + return super.transferFrom(_from, _to, _value); + } + + function transfer(address _to, uint256 _value) public returns (bool _success) { + require(!paused); + return super.transfer(_to, _value); + } + + + function init() private { + require(!initialized); + initialized = true; + + if (PAUSED) { + pause(); + } + + + address[5] memory addresses = [address(0xe0fe23efe5dcfaa6aefd2cb7cc8c68956bd9a65b),address(0x17faebb744e0289355785c22202dc8fe0c735862),address(0x50cc7d2afc6301b90e72931a7e60173e306e9731),address(0x2af11e91e75a23e47efa8a7b78434c48ef90a7d7),address(0x3674228ddc38f80c3d2b25f765f1bc41ae781385)]; + uint[5] memory amounts = [uint(16666666000000000000000000),uint(16666667000000000000000000),uint(16666667000000000000000000),uint(650000000000000000000000000),uint(300000000000000000000000000)]; + uint64[5] memory freezes = [uint64(1734188406),uint64(1734188406),uint64(1734188406),uint64(0),uint64(1860418806)]; + + for (uint i = 0; i < addresses.length; i++) { + if (freezes[i] == 0) { + mint(addresses[i], amounts[i]); + } else { + mintAndFreeze(addresses[i], amounts[i], freezes[i]); + } + } + + + if (!CONTINUE_MINTING) { + finishMinting(); + } + + emit Initialized(); + } + +} + +