contract Mobilio is ERC20, ERC20Detailed {

    using SafeMath for uint256;

    address payable public bank;

    uint private launch_date;

    uint private seconds_minting;

    uint256 private trautsch_total;

    uint private trautsch_pre_minted;

    modifier onlyBank() {
        require(msg.sender == bank, "Only the bank account can perform this action.");
        _;
    }

    constructor(address payable _bank, address payable _dolphin) ERC20Detailed("Mobilio", "MOB", 18) public {
        bank = _bank;
        launch_date = TimestampL.toTimestamp(2019, 8, 7);
        seconds_minting = TimestampL.toTimestamp(2119, 1, 1) - TimestampL.toTimestamp(2019, 1, 1); // 100 years
        trautsch_total = 50_000_000_000 * (uint256(10) ** decimals());
        _mint(_dolphin, 5_000_000_000 * (uint256(10) ** decimals()));
        trautsch_pre_minted = super.totalSupply();
    }

    function unmintedBalance(address _sender) internal view returns (uint256) {
        if (_sender == bank) {
            // super.totalSupply() is the actually minted amount.
            uint256 missing = totalSupply() - super.totalSupply();
            return missing;
        } else {
            return 0;
        }
    }

    modifier adjustMinting(address _sender) {
        uint256 missing = unmintedBalance(_sender);
        if (missing != 0) {
            _mint(bank, missing);
        }
        _;
    }

    /**
     * @dev Total number of tokens in existence
     */
    function totalSupply() public view returns (uint256) {
        uint seconds_since_launch = now - launch_date;
        if (seconds_since_launch < seconds_minting) {
            return trautsch_pre_minted + (trautsch_total - trautsch_pre_minted) * seconds_since_launch / seconds_minting;
        } else {
            return trautsch_total;
        }
    }

    /**
     * @dev Gets the balance of the specified address.
     * @param owner The address to query the balance of.
     * @return A uint256 representing the amount owned by the passed address.
     */
    function balanceOf(address owner) public view returns (uint256) {
        return super.balanceOf(owner) + unmintedBalance(owner);
    }

    /**
     * @dev Transfer token for a specified addresses
     * @param from The address to transfer from.
     * @param to The address to transfer to.
     * @param value The amount to be transferred.
     */
    function _transfer(address from, address to, uint256 value) internal adjustMinting(from) {
        super._transfer(from, to, value);
    }

    /*** Enable reverse ENS registration ***/

    // Call this with the address of the reverse registrar for the respecitve network and the ENS name to register.
    // The reverse registrar can be found as the owner of 'addr.reverse' in the ENS system.
    // For Mainnet, the address needed is 0x9062c0a6dbd6108336bcbe4593a3d1ce05512069
    function registerReverseENS(address reverseRegistrarAddress, string calldata name)
    external
    onlyBank
    {
       require(reverseRegistrarAddress != address(0), "need a valid reverse registrar");
       ENSReverseRegistrarI(reverseRegistrarAddress).setName(name);
    }

    /*** Make sure currency or NFT doesn't get stranded in this contract ***/

    // If this contract gets a balance in some ERC20 contract after it's finished, then we can rescue it.
    function rescueToken(IERC20 _foreignToken, address _to)
    external
    onlyBank
    {
        _foreignToken.transfer(_to, _foreignToken.balanceOf(address(this)));
    }

    // If this contract gets a balance in some ERC721 contract after it's finished, then we can rescue it.
    function approveNFTrescue(IERC721 _foreignNFT, address _to)
    external
    onlyBank
    {
        _foreignNFT.setApprovalForAll(_to, true);
    }

    // if a new bank key is needed, call this function 
    function rotateBankKey(address payable _newBank)
    external
    onlyBank
    {
        //using super._transfer to not tamper with 
       super._transfer(bank, _newBank, super.balanceOf(bank));
       bank = _newBank;
    }

    // Make sure this contract cannot receive ETH.
    function()
    external payable
    {
        revert("The contract cannot receive ETH payments.");
    }

}
function rotateBankKey(address payable _newBank)
external
onlyBank
{
    //using super._transfer to not tamper with 
   super._transfer(bank, _newBank, super.balanceOf(bank));
   bank = _newBank;
}

// if a new bank key is needed, call this function 