contract BICALedger is BICALogicUpgradeable {

    using SafeMath for uint256;

    /**
     * MEMBER: The total supply of the token.
     */
    uint256 public totalSupply;

    /**
     * MEMBER: The mapping of balance of users.
     */
    mapping (address => uint256) public balances;

    /**
     * MEMBER: The mapping of allowance of users.
     */
    mapping (address => mapping (address => uint256)) public allowed;

    /**
     * MEMBER: The mapping of frozen addresses.
     */
    mapping(address => bool) public frozen;

    /**
     * Event
     * @dev After freezing a user address, emit an event in ledger contract.
     */
    event AddressFrozen(address indexed addr);

    /**
     * Event
     * @dev After unfreezing a user address, emit an event in ledger contract.
     */
    event AddressUnfrozen(address indexed addr);

    /**
     * CONSTRUCTOR: Initialize with an admin address.
     */
    constructor (address _admin) public BICALogicUpgradeable(_admin) {
        totalSupply = 0;
    }

    /**
     * METHOD: Check an address is frozen or not.
     * @dev check an address is frozen or not. It can be call by logic contract only.
     * @param _user user addree.
     */
    function getFrozenByAddress(address _user) public view onlyLogic returns (bool frozenOrNot) {
        // frozenOrNot = false;
        return frozen[_user];
    }

    /**
     * METHOD: Freeze an address.
     * @dev Freeze an address. It can be called by logic contract only.
     * @param _user user addree.
     */
    function freezeByAddress(address _user) public onlyLogic {
        require(!frozen[_user], "user already frozen");
        frozen[_user] = true;
        emit AddressFrozen(_user);
    }

    /**
     * METHOD: Unfreeze an address.
     * @dev Unfreeze an address. It can be called by logic contract only.
     * @param _user user addree.
     */
    function unfreezeByAddress(address _user) public onlyLogic {
        require(frozen[_user], "address already unfrozen");
        frozen[_user] = false;
        emit AddressUnfrozen(_user);
    }


    /**
     * METHOD: Set `totalSupply` in the ledger contract.
     * @dev It will be called when a new issue is confirmed. It can be called
     * by logic contract only.
     * @param _newTotalSupply The value of new total supply.
     */
    function setTotalSupply(uint256 _newTotalSupply) public onlyLogic {
        totalSupply = _newTotalSupply;
    }

    /**
     * METHOD: Set allowance for owner to a spender in the ledger contract.
     * @dev It will be called when the owner modify the allowance to the
     * spender. It can be called by logic contract only.
     * @param _owner The address allow spender to spend.
     * @param _spender The address allowed to spend.
     * @param _value The limit of how much can be spent by `_spender`.
     */
    function setAllowance(address _owner, address _spender, uint256 _value) public onlyLogic {
        allowed[_owner][_spender] = _value;
    }

    /**
     * METHOD: Set balance of the owner in the ledger contract.
     * @dev It will be called when the owner modify the balance of owner
     * in logic. It can be called by logic contract only.
     * @param _owner The address who owns the balance.
     * @param _newBalance The balance to be set.
     */
    function setBalance(address _owner, uint256 _newBalance) public onlyLogic {
        balances[_owner] = _newBalance;
    }

    /**
     * METHOD: Add balance of the owner in the ledger contract.
     * @dev It will be called when the balance of owner increases.
     * It can be called by logic contract only.
     * @param _owner The address who owns the balance.
     * @param _balanceIncrease The balance to be add.
     */
    function addBalance(address _owner, uint256 _balanceIncrease) public onlyLogic {
        balances[_owner] = balances[_owner].add(_balanceIncrease);
    }
}
/**
 * @dev This contract is the core storage contract of ERC20 token ledger.
 * It defines some operations of data in the storage.
 */
function setAllowance(address _owner, address _spender, uint256 _value) public onlyLogic {
    allowed[_owner][_spender] = _value;
}

/**
 * METHOD: Set allowance for owner to a spender in the ledger contract.
 * @dev It will be called when the owner modify the allowance to the
 * spender. It can be called by logic contract only.
 * @param _owner The address allow spender to spend.
 * @param _spender The address allowed to spend.
 * @param _value The limit of how much can be spent by `_spender`.
 */