// Vulnerability label: locked
pragma solidity ^0.4.16;
/* åå»ºä¸ä¸ªç¶ç±»ï¼ è´¦æ·ç®¡çå */
contract owned {

    address public owner;

    function owned() public {
    owner = msg.sender;
    }

    /* modifieræ¯ä¿®æ¹æ å¿ */
    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }

    /* ä¿®æ¹ç®¡çåè´¦æ·ï¼ onlyOwnerä»£è¡¨åªè½æ¯ç¨æ·ç®¡çåæ¥ä¿®æ¹ */
    function transferOwnership(address newOwner) onlyOwner public {
        owner = newOwner;
    }   
}

/* receiveApprovalæå¡åçº¦æç¤ºä»£å¸åçº¦å°ä»£å¸ä»åéèçè´¦æ·è½¬ç§»å°æå¡åçº¦çè´¦æ·ï¼éè¿è°ç¨æå¡åçº¦ç */
interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; }

contract TokenERC20 {
    // ä»£å¸ï¼tokenï¼çå¬å±åé
    string public name;             //ä»£å¸åå­
    string public symbol;           //ä»£å¸ç¬¦å·
    uint8 public decimals = 18;     //ä»£å¸å°æ°ç¹ä½æ°ï¼ 18æ¯é»è®¤ï¼ å°½éä¸è¦æ´æ¹

    uint256 public totalSupply;     //ä»£å¸æ»é

    // è®°å½åä¸ªè´¦æ·çä»£å¸æ°ç®
    mapping (address => uint256) public balanceOf;

    // Aè´¦æ·å­å¨Bè´¦æ·èµé
    mapping (address => mapping (address => uint256)) public allowance;

    // è½¬è´¦éç¥äºä»¶
    event Transfer(address indexed from, address indexed to, uint256 value);

    // éæ¯éé¢éç¥äºä»¶
    event Burn(address indexed from, uint256 value);

    /* æé å½æ° */
    function TokenERC20(
        uint256 initialSupply,
        string tokenName,
        string tokenSymbol
    ) public {
        totalSupply = initialSupply * 10 ** uint256(decimals);  // æ ¹æ®decimalsè®¡ç®ä»£å¸çæ°é
        balanceOf[msg.sender] = totalSupply;                    // ç»çæèææçä»£å¸æ°é
        name = tokenName;                                       // è®¾ç½®ä»£å¸çåå­
        symbol = tokenSymbol;                                   // è®¾ç½®ä»£å¸çç¬¦å·
    }

    /* ç§æçäº¤æå½æ° */
    function _transfer(address _from, address _to, uint _value) internal {
        // é²æ­¢è½¬ç§»å°0x0ï¼ ç¨burnä»£æ¿è¿ä¸ªåè½
        require(_to != 0x0);
        // æ£æµåéèæ¯å¦æè¶³å¤çèµé
        require(balanceOf[_from] >= _value);
        // æ£æ¥æ¯å¦æº¢åºï¼æ°æ®ç±»åçæº¢åºï¼
        require(balanceOf[_to] + _value > balanceOf[_to]);
        // å°æ­¤ä¿å­ä¸ºå°æ¥çæ­è¨ï¼ å½æ°æåä¼æä¸ä¸ªæ£éª
        uint previousBalances = balanceOf[_from] + balanceOf[_to];
        // åå°åéèèµäº§
        balanceOf[_from] -= _value;
        // å¢å æ¥æ¶èçèµäº§
        balanceOf[_to] += _value;
        Transfer(_from, _to, _value);
        // æ­è¨æ£æµï¼ ä¸åºè¯¥ä¸ºé
        assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
    }

    /* ä¼ étokens */
    function transfer(address _to, uint256 _value) public {
        _transfer(msg.sender, _to, _value);
    }

    /* ä»å¶ä»è´¦æ·è½¬ç§»èµäº§ */
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        require(_value <= allowance[_from][msg.sender]);     // Check allowance
        allowance[_from][msg.sender] -= _value;
        _transfer(_from, _to, _value);
        return true;
    }

    /*  ææç¬¬ä¸æ¹ä»åéèè´¦æ·è½¬ç§»ä»£å¸ï¼ç¶åéè¿transferFrom()å½æ°æ¥æ§è¡ç¬¬ä¸æ¹çè½¬ç§»æä½ */
    function approve(address _spender, uint256 _value) public
        returns (bool success) {
        allowance[msg.sender][_spender] = _value;
        return true;
    }

    /*
    ä¸ºå¶ä»å°åè®¾ç½®æ´¥è´´ï¼ å¹¶éç¥
    åéèéç¥ä»£å¸åçº¦, ä»£å¸åçº¦éç¥æå¡åçº¦receiveApproval, æå¡åçº¦æç¤ºä»£å¸åçº¦å°ä»£å¸ä»åéèçè´¦æ·è½¬ç§»å°æå¡åçº¦çè´¦æ·ï¼éè¿è°ç¨æå¡åçº¦çtransferFrom)
    */

    function approveAndCall(address _spender, uint256 _value, bytes _extraData)
        public
        returns (bool success) {
        tokenRecipient spender = tokenRecipient(_spender);
        if (approve(_spender, _value)) {
            spender.receiveApproval(msg.sender, _value, this, _extraData);
            return true;
        }
    }

    /**
    * éæ¯ä»£å¸
    */
    function burn(uint256 _value) public returns (bool success) {
        require(balanceOf[msg.sender] >= _value);   // Check if the sender has enough
        balanceOf[msg.sender] -= _value;            // Subtract from the sender
        totalSupply -= _value;                      // Updates totalSupply
        Burn(msg.sender, _value);
        return true;
    }

    /**
    * ä»å¶ä»è´¦æ·éæ¯ä»£å¸
    */
    function burnFrom(address _from, uint256 _value) public returns (bool success) {
        require(balanceOf[_from] >= _value);                // Check if the targeted balance is enough
        require(_value <= allowance[_from][msg.sender]);    // Check allowance
        balanceOf[_from] -= _value;                         // Subtract from the targeted balance
        allowance[_from][msg.sender] -= _value;             // Subtract from the sender's allowance
        totalSupply -= _value;                              // Update totalSupply
        Burn(_from, _value);
        return true;
    }
}

/******************************************/
/*       ADVANCED TOKEN STARTS HERE       */
/******************************************/

contract ROSCtoken is owned, TokenERC20 {

    uint256 public sellPrice;
    uint256 public buyPrice;

    /* å»ç»è´¦æ· */
    mapping (address => bool) public frozenAccount;

    /* This generates a public event on the blockchain that will notify clients */
    event FrozenFunds(address target, bool frozen);

    /* æé å½æ° */
    function ROSCtoken(
        uint256 initialSupply,
        string tokenName,
        string tokenSymbol
    ) TokenERC20(initialSupply, tokenName, tokenSymbol) public {}

    /* è½¬è´¦ï¼ æ¯ç¶ç±»å å¥äºè´¦æ·å»ç» */
    function _transfer(address _from, address _to, uint _value) internal {
        require (_to != 0x0);                               // Prevent transfer to 0x0 address. Use burn() instead
        require (balanceOf[_from] >= _value);               // Check if the sender has enough
        require (balanceOf[_to] + _value > balanceOf[_to]); // Check for overflows
        require(!frozenAccount[_from]);                     // Check if sender is frozen
        require(!frozenAccount[_to]);                       // Check if recipient is frozen
        balanceOf[_from] -= _value;                         // Subtract from the sender
        balanceOf[_to] += _value;                           // Add the same to the recipient
        Transfer(_from, _to, _value);
    }

/// åæå®è´¦æ·å¢åèµé
    function mintToken(address target, uint256 mintedAmount) onlyOwner public {
        balanceOf[target] += mintedAmount;
        totalSupply += mintedAmount;
        Transfer(0, this, mintedAmount);
        Transfer(this, target, mintedAmount);

    }


    /// å»ç» or è§£å»è´¦æ·
    function freezeAccount(address target, bool freeze) onlyOwner public {
        frozenAccount[target] = freeze;
        FrozenFunds(target, freeze);
    }

    function setPrices(uint256 newSellPrice, uint256 newBuyPrice) onlyOwner public {
        sellPrice = newSellPrice;
        buyPrice = newBuyPrice;
    }

    /// @notice Buy tokens from contract by sending ether
    function buy() payable public {
        uint amount = msg.value / buyPrice;               // calculates the amount
        _transfer(this, msg.sender, amount);              // makes the transfers
    }

    function sell(uint256 amount) public {
        require(this.balance >= amount * sellPrice);      // checks if the contract has enough ether to buy
        _transfer(msg.sender, this, amount);              // makes the transfers
        msg.sender.transfer(amount * sellPrice);          // sends ether to the seller. It's important to do this last to avoid recursion attacks
    }
}