contract EcomToken is BurnableToken, Owned {
    string public constant name = "Omnitude Token";
    string public constant symbol = "ECOM";
    uint8 public constant decimals = 18;

    /// Maximum tokens to be allocated (100 million)
    uint256 public constant HARD_CAP = 100000000 * 10**uint256(decimals);

    /// Maximum tokens to be allocated on the sale (55 million)
    uint256 public constant TOKENS_SALE_HARD_CAP = 55000000 * 10**uint256(decimals);

    /// The owner of this address will
    address public omniTeamAddress;

    /// The owner of this address will
    address public foundationAddress;

    /// contract to be called to release the Omni team tokens for Year 1
    address public year1LockAddress;

    /// contract to be called to release the Omni team tokens for Year 2
    address public year2LockAddress;

    /// contract to be called to release the Omni team tokens for Year 3
    address public year3LockAddress;

    /// contract to be called to release the Omni team tokens for Year 4
    address public year4LockAddress;

    /// contract to be called to release the Omni team tokens for Year 5
    address public year5LockAddress;

    /// Year 1 lock date (01.01.2019)
    uint64 private constant date01Jan2019 = 1546300800;

    /// Year 2 lock date (01.01.2020)
    uint64 private constant date01Jan2020 = 1577836800;

    /// Year 3 lock date (01.01.2021)
    uint64 private constant date01Jan2021 = 1609459200;

    /// Year 4 lock date (01.01.2022)
    uint64 private constant date01Jan2022 = 1640995200;

    /// Year 5 lock date (01.01.2023)
    uint64 private constant date01Jan2023 = 1672531200;

    /// no tokens can be ever issued when this is set to "true"
    bool public tokenSaleClosed = false;

    /// Only allowed to execute while tokens can be sold
    modifier inProgress {
        require(totalSupply < TOKENS_SALE_HARD_CAP && !tokenSaleClosed);
        _;
    }

    /// Only allowed to execute while the sale is not yet closed
    modifier beforeEnd {
        require(!tokenSaleClosed);
        _;
    }

    function EcomToken(address _omniTeamAddress, address _foundationAddress) public {
        require(_omniTeamAddress != address(0));
        require(_foundationAddress != address(0));

        omniTeamAddress = _omniTeamAddress;
        foundationAddress = _foundationAddress;
        totalSupply = TOKENS_SALE_HARD_CAP;
        balances[owner] = TOKENS_SALE_HARD_CAP;
    }

    /// @dev Close the sale; issue foundation and team tokens
    function close() public onlyOwner beforeEnd {
        /// burn everything unsold
        uint256 saleTokensToBurn = balances[owner];
        balances[owner] = 0;
        totalSupply = totalSupply.sub(saleTokensToBurn);
        Burn(owner, saleTokensToBurn);

        /// Foundation tokens - 33M
        uint256 foundationTokens = 33000000 * 10**uint256(decimals);
        totalSupply = totalSupply.add(foundationTokens);
        balances[foundationAddress] = foundationTokens;

        /// Lock team tokens - 12M
        uint256 teamTokens = 12000000 * 10**uint256(decimals);
        totalSupply = totalSupply.add(teamTokens);

        /// YEAR 1 - 2.4M
        uint256 teamTokensY1 = 2400000 * 10**uint256(decimals);
        /// team tokens are locked until this date (01.01.2019)
        TokenTimelock year1Lock = new TokenTimelock(this, omniTeamAddress, date01Jan2019);
        year1LockAddress = address(year1Lock);
        balances[year1LockAddress] = teamTokensY1;

        /// YEAR 2 - 2.4M
        uint256 teamTokensY2 = 2400000 * 10**uint256(decimals);
        /// team tokens are locked until this date (01.01.2020)
        TokenTimelock year2Lock = new TokenTimelock(this, omniTeamAddress, date01Jan2020);
        year2LockAddress = address(year2Lock);
        balances[year2LockAddress] = teamTokensY2;

        /// YEAR 3 - 2.4M
        uint256 teamTokensY3 = 2400000 * 10**uint256(decimals);
        /// team tokens are locked until this date (01.01.2021)
        TokenTimelock year3Lock = new TokenTimelock(this, omniTeamAddress, date01Jan2021);
        year3LockAddress = address(year3Lock);
        balances[year3LockAddress] = teamTokensY3;

        /// YEAR 4 - 2.4M
        uint256 teamTokensY4 = 2400000 * 10**uint256(decimals);
        /// team tokens are locked until this date (01.01.2022)
        TokenTimelock year4Lock = new TokenTimelock(this, omniTeamAddress, date01Jan2022);
        year4LockAddress = address(year4Lock);
        balances[year4LockAddress] = teamTokensY4;

        /// YEAR 5 - 2.4M
        uint256 teamTokensY5 = 2400000 * 10**uint256(decimals);
        /// team tokens are locked until this date (01.01.2023)
        TokenTimelock year5Lock = new TokenTimelock(this, omniTeamAddress, date01Jan2023);
        year5LockAddress = address(year5Lock);
        balances[year5LockAddress] = teamTokensY5;

        tokenSaleClosed = true;
    }

    /// @dev Trading limited - requires the sale to have closed
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
        if(msg.sender != owner && !tokenSaleClosed) return false;
        return super.transferFrom(_from, _to, _value);
    }

    /// @dev Trading limited - requires the sale to have closed
    function transfer(address _to, uint256 _value) public returns (bool) {
        if(msg.sender != owner && !tokenSaleClosed) return false;
        return super.transfer(_to, _value);
    }
}
function transfer(address _to, uint256 _value) public returns (bool) {
    if(msg.sender != owner && !tokenSaleClosed) return false;
    return super.transfer(_to, _value);
}

/// @dev Trading limited - requires the sale to have closed