// Contract: CosmoDistributor
// Target function: function drawDown() nonReentrant external returns (bool)
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;

library SafeMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;
        return c;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
        return 0;
        }
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        return c;
    }
}

interface IERC20 {
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
}


contract CosmoDistributor {
    using SafeMath for uint256;
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;
    uint256 private _status = _NOT_ENTERED;

    address private _owner;

    address public constant token = 0x27cd7375478F189bdcF55616b088BE03d9c4339c;
    uint256 public constant timeStart = 1615820400;  // 2021-03-15T15:00:00.000Z = 1615820400
    uint256 public constant timeEnd = 1647356400;    // 2022-03-15T15:00:00.000Z = 1647356400

    mapping(address => uint256) public vestedAmount;
    mapping(address => uint256) public totalDrawn;
    mapping(address => uint256) public lastDrawnAt;

    string public url = "https://CosmoFund.space/";

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    event ScheduleCreated(address indexed beneficiary);
    event DrawDown(address indexed beneficiary, uint256 indexed amount);

    constructor() public {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
        setup();
    }

    function setup() internal {
        vestedAmount[0xB2F8234571eEF9B222DEca1307A03c6c2E376b73] = 1800000000e18;
        vestedAmount[0x3A7F0d57928d7dCE60E11470e528c47CF5084f33] = 18000000e18;
    }

    /**
    * @notice Create new vesting schedules in a batch
    * @notice A transfer is used to bring tokens into the VestingDepositAccount so pre-approval is required
    * @param beneficiaries array of beneficiaries of the vested tokens
    * @param amounts array of amount of tokens (in wei)
    * @dev array index of address should be the same as the array index of the amount
    */
    function createVestingSchedules(address[] calldata beneficiaries, uint256[] calldata amounts) external onlyOwner returns (bool) {
        require(beneficiaries.length > 0, "Empty Data");
        require(beneficiaries.length == amounts.length, "Array lengths do not match");
        for (uint256 i = 0; i < beneficiaries.length; i = i.add(1)) {
            address beneficiary = beneficiaries[i];
            uint256 amount = amounts[i];
            _createVestingSchedule(beneficiary, amount);
        }
        return true;
    }

    /**
    * @notice Create a new vesting schedule
    * @notice A transfer is used to bring tokens into the VestingDepositAccount so pre-approval is required
    * @param beneficiary beneficiary of the vested tokens
    * @param amount amount of tokens (in wei)
    */
    function createVestingSchedule(address beneficiary, uint256 amount) external onlyOwner returns (bool) {
        return _createVestingSchedule(beneficiary, amount);
    }