creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "/contracts/DecubateVestingv2.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\n//** Decubate vesting Contract */\n//** Author Aceson : Decubate Vesting Contract 2022.4 */\n\npragma solidity ^0.8.10;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/interfaces/IERC20.sol\";\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\nimport \"./libraries/DateTime.sol\";\n\ncontract DecubateVestingV2 is Ownable, DateTime {\n  using SafeMath for uint256;\n\n  enum Type {\n    Linear,\n    Monthly,\n    Interval\n  }\n\n  struct VestingInfo {\n    string name;\n    uint256 cliff;\n    uint256 start;\n    uint256 duration;\n    uint256 initialUnlockPercent;\n    bool revocable;\n    Type vestType;\n    uint256 interval;\n    uint256 unlockPerInterval;\n    uint256[] timestamps;\n  }\n\n  struct VestingPool {\n    string name;\n    uint256 cliff;\n    uint256 start;\n    uint256 duration;\n    uint256 initialUnlockPercent;\n    WhitelistInfo[] whitelistPool;\n    mapping(address => HasWhitelist) hasWhitelist;\n    bool revocable;\n    Type vestType;\n    uint256 interval;\n    uint256 unlockPerInterval;\n    uint256[] timestamps;\n  }\n\n  struct MaxTokenTransferValue {\n    uint256 amount;\n    bool active;\n  }\n\n  /**\n   *\n   * @dev WhiteInfo is the struct type which store whitelist information\n   *\n   */\n  struct WhitelistInfo {\n    address wallet;\n    uint256 dcbAmount;\n    uint256 distributedAmount;\n    uint256 joinDate;\n    uint256 revokeDate;\n    bool revoke;\n    bool disabled;\n  }\n\n  struct HasWhitelist {\n    uint256 arrIdx;\n    bool active;\n  }\n\n  MaxTokenTransferValue public maxTokenTransfer;\n  VestingPool[] public vestingPools;\n\n  IERC20 private token;\n\n  event AddToken(address indexed token);\n\n  event Claim(address indexed token, uint256 amount, uint256 indexed option, uint256 time);\n\n  event AddWhitelist(address indexed wallet);\n\n  event Revoked(address indexed wallet);\n\n  event StatusChanged(address indexed wallet, bool status);\n\n  modifier optionExists(uint256 _option) {\n    require(_option < vestingPools.length, \"Vesting option does not exist\");\n    _;\n  }\n\n  modifier userInWhitelist(uint256 _option, address _wallet) {\n    require(_option < vestingPools.length, \"Vesting option does not exist\");\n    require(vestingPools[_option].hasWhitelist[_wallet].active, \"User is not in whitelist\");\n    _;\n  }\n\n  constructor(address _token) {\n    token = IERC20(_token);\n  }\n\n  function addVestingStrategy(\n    string memory _name,\n    uint256 _cliff,\n    uint256 _start,\n    uint256 _duration,\n    uint256 _initialUnlockPercent,\n    bool _revocable,\n    uint256 _interval,\n    uint16 _unlockPerInterval,\n    uint8 _monthGap,\n    Type _type\n  ) external onlyOwner returns (bool) {\n    VestingPool storage newStrategy = vestingPools.push();\n\n    newStrategy.cliff = _start.add(_cliff);\n    newStrategy.name = _name;\n    newStrategy.start = _start;\n    newStrategy.duration = _duration;\n    newStrategy.initialUnlockPercent = _initialUnlockPercent;\n    newStrategy.revocable = _revocable;\n    newStrategy.vestType = _type;\n\n    if (_type == Type.Interval) {\n      require(_interval > 0, \"Invalid interval\");\n      require(_unlockPerInterval > 0, \"Invalid unlock per interval\");\n\n      newStrategy.interval = _interval;\n      newStrategy.unlockPerInterval = _unlockPerInterval;\n    } else if (_type == Type.Monthly) {\n      require(_unlockPerInterval > 0, \"Invalid unlock per interval\");\n      require(_monthGap > 0, \"Invalid month gap\");\n\n      newStrategy.unlockPerInterval = _unlockPerInterval;\n\n      uint8 day = getDay(newStrategy.cliff);\n      uint8 month = getMonth(newStrategy.cliff);\n      uint16 year = getYear(newStrategy.cliff);\n      uint8 hour = getHour(newStrategy.cliff);\n      uint8 minute = getMinute(newStrategy.cliff);\n      uint8 second = getSecond(newStrategy.cliff);\n\n      for (uint16 i = 0; i <= 1000; i += _unlockPerInterval) {\n        month += _monthGap;\n\n        if (month > 12) {\n          month = month - 12;\n          year++;\n        }\n\n        uint256 time = toTimestamp(year, month, day, hour, minute, second);\n        newStrategy.timestamps.push(time);\n      }\n    }\n\n    return true;\n  }\n\n  function setVestingStrategy(\n    uint256 _strategy,\n    string memory _name,\n    uint256 _cliff,\n    uint256 _start,\n    uint256 _duration,\n    uint256 _initialUnlockPercent,\n    bool _revocable,\n    uint256 _interval,\n    uint16 _unlockPerInterval\n  ) external onlyOwner returns (bool) {\n    require(_strategy < vestingPools.length, \"Strategy does not exist\");\n\n    VestingPool storage vest = vestingPools[_strategy];\n\n    require(vest.vestType != Type.Monthly, \"Changing monthly not supported\");\n\n    vest.cliff = _start.add(_cliff);\n    vest.name = _name;\n    vest.start = _start;\n    vest.duration = _duration;\n    vest.initialUnlockPercent = _initialUnlockPercent;\n    vest.revocable = _revocable;\n\n    if (vest.vestType == Type.Interval) {\n      vest.interval = _interval;\n      vest.unlockPerInterval = _unlockPerInterval;\n    }\n\n    return true;\n  }\n\n  function setMaxTokenTransfer(uint256 _amount, bool _active) external onlyOwner returns (bool) {\n    maxTokenTransfer.amount = _amount;\n    maxTokenTransfer.active = _active;\n    return true;\n  }\n\n  function setToken(address _addr) external onlyOwner returns (bool) {\n    token = IERC20(_addr);\n    return true;\n  }\n\n  function batchAddWhitelist(\n    address[] memory wallets,\n    uint256[] memory amounts,\n    uint256 option\n  ) external onlyOwner returns (bool) {\n    require(wallets.length == amounts.length, \"Sizes of inputs do not match\");\n\n    for (uint256 i = 0; i < wallets.length; i++) {\n      addWhitelist(wallets[i], amounts[i], option);\n    }\n\n    return true;\n  }\n\n  /**\n   *\n   * @dev set the address as whitelist user address\n   *\n   * @param {address} address of the user\n   *\n   * @return {bool} return status of the whitelist\n   *\n   */\n  function setWhitelist(\n    address _wallet,\n    uint256 _dcbAmount,\n    uint256 _option\n  ) external onlyOwner userInWhitelist(_option, _wallet) returns (bool) {\n    uint256 idx = vestingPools[_option].hasWhitelist[_wallet].arrIdx;\n    WhitelistInfo storage info = vestingPools[_option].whitelistPool[idx];\n    info.dcbAmount = _dcbAmount;\n\n    return true;\n  }\n\n  function revoke(uint256 _option, address _wallet)\n    external\n    onlyOwner\n    userInWhitelist(_option, _wallet)\n  {\n    uint256 idx = vestingPools[_option].hasWhitelist[_wallet].arrIdx;\n    WhitelistInfo storage whitelist = vestingPools[_option].whitelistPool[idx];\n\n    require(vestingPools[_option].revocable, \"Strategy is not revocable\");\n    require(!whitelist.revoke, \"already revoked\");\n\n    if (calculateReleasableAmount(_option, _wallet) > 0) {\n      claimDistribution(_option, _wallet);\n    }\n\n    whitelist.revoke = true;\n    whitelist.revokeDate = block.timestamp;\n\n    emit Revoked(_wallet);\n  }\n\n  function setVesting(\n    uint256 _option,\n    address _wallet,\n    bool _status\n  ) external onlyOwner userInWhitelist(_option, _wallet) {\n    uint256 idx = vestingPools[_option].hasWhitelist[_wallet].arrIdx;\n    WhitelistInfo storage whitelist = vestingPools[_option].whitelistPool[idx];\n\n    whitelist.disabled = _status;\n\n    emit StatusChanged(_wallet, _status);\n  }\n\n  function transferToken(address _addr, uint256 _amount) external onlyOwner returns (bool) {\n    IERC20 _token = IERC20(_addr);\n    bool success = _token.transfer(address(owner()), _amount);\n    return success;\n  }\n\n  function getWhitelist(uint256 _option, address _wallet)\n    external\n    view\n    userInWhitelist(_option, _wallet)\n    returns (WhitelistInfo memory)\n  {\n    uint256 idx = vestingPools[_option].hasWhitelist[_wallet].arrIdx;\n    return vestingPools[_option].whitelistPool[idx];\n  }\n\n  function getAllVestingPools() external view returns (VestingInfo[] memory) {\n    VestingInfo[] memory infoArr = new VestingInfo[](vestingPools.length);\n\n    for (uint256 i = 0; i < vestingPools.length; i++) {\n      infoArr[i] = getVestingInfo(i);\n    }\n\n    return infoArr;\n  }\n\n  function getToken() external view returns (address) {\n    return address(token);\n  }\n\n  function getTotalToken(address _addr) external view returns (uint256) {\n    IERC20 _token = IERC20(_addr);\n    return _token.balanceOf(address(this));\n  }\n\n  function hasWhitelist(uint256 _option, address _wallet) external view returns (bool) {\n    return vestingPools[_option].hasWhitelist[_wallet].active;\n  }\n\n  function getVestAmount(uint256 _option, address _wallet) external view returns (uint256) {\n    return calculateVestAmount(_option, _wallet);\n  }\n\n  function getReleasableAmount(uint256 _option, address _wallet) external view returns (uint256) {\n    return calculateReleasableAmount(_option, _wallet);\n  }\n\n  function getWhitelistPool(uint256 _option)\n    external\n    view\n    optionExists(_option)\n    returns (WhitelistInfo[] memory)\n  {\n    return vestingPools[_option].whitelistPool;\n  }\n\n  function claimDistribution(uint256 _option, address _wallet) public returns (bool) {\n    uint256 idx = vestingPools[_option].hasWhitelist[_wallet].arrIdx;\n    WhitelistInfo storage whitelist = vestingPools[_option].whitelistPool[idx];\n\n    require(!whitelist.disabled, \"User is disabled from claiming token\");\n\n    uint256 releaseAmount = calculateReleasableAmount(_option, _wallet);\n\n    require(releaseAmount > 0, \"Zero amount to claim\");\n\n    if (maxTokenTransfer.active && releaseAmount > maxTokenTransfer.amount) {\n      releaseAmount = maxTokenTransfer.amount;\n    }\n\n    whitelist.distributedAmount = whitelist.distributedAmount.add(releaseAmount);\n\n    token.transfer(_wallet, releaseAmount);\n\n    emit Claim(_wallet, releaseAmount, _option, block.timestamp);\n\n    return true;\n  }\n\n  function addWhitelist(\n    address _wallet,\n    uint256 _dcbAmount,\n    uint256 _option\n  ) public onlyOwner optionExists(_option) returns (bool) {\n    HasWhitelist storage whitelist = vestingPools[_option].hasWhitelist[_wallet];\n    require(!whitelist.active, \"Whitelist already available\");\n\n    WhitelistInfo[] storage pool = vestingPools[_option].whitelistPool;\n\n    whitelist.active = true;\n    whitelist.arrIdx = pool.length;\n\n    pool.push(\n      WhitelistInfo({\n        wallet: _wallet,\n        dcbAmount: _dcbAmount,\n        distributedAmount: 0,\n        joinDate: block.timestamp,\n        revokeDate: 0,\n        revoke: false,\n        disabled: false\n      })\n    );\n\n    emit AddWhitelist(_wallet);\n\n    return true;\n  }\n\n  function getVestingInfo(uint256 _strategy)\n    public\n    view\n    optionExists(_strategy)\n    returns (VestingInfo memory)\n  {\n    return\n      VestingInfo({\n        name: vestingPools[_strategy].name,\n        cliff: vestingPools[_strategy].cliff,\n        start: vestingPools[_strategy].start,\n        duration: vestingPools[_strategy].duration,\n        initialUnlockPercent: vestingPools[_strategy].initialUnlockPercent,\n        revocable: vestingPools[_strategy].revocable,\n        vestType: vestingPools[_strategy].vestType,\n        interval: vestingPools[_strategy].interval,\n        unlockPerInterval: vestingPools[_strategy].unlockPerInterval,\n        timestamps: vestingPools[_strategy].timestamps\n      });\n  }\n\n  function calculateVestAmount(uint256 _option, address _wallet)\n    internal\n    view\n    userInWhitelist(_option, _wallet)\n    returns (uint256 amount)\n  {\n    uint256 idx = vestingPools[_option].hasWhitelist[_wallet].arrIdx;\n    WhitelistInfo memory whitelist = vestingPools[_option].whitelistPool[idx];\n    VestingPool storage vest = vestingPools[_option];\n\n    // initial unlock\n    uint256 initial = whitelist.dcbAmount.mul(vest.initialUnlockPercent).div(1000);\n\n    if (whitelist.revoke) {\n      return whitelist.distributedAmount;\n    }\n\n    if (block.timestamp < vest.start) {\n      return 0;\n    } else if (block.timestamp >= vest.start && block.timestamp < vest.cliff) {\n      return initial;\n    } else if (block.timestamp >= vest.cliff) {\n      if (vestingPools[_option].vestType == Type.Interval) {\n        return calculateVestAmountForInterval(whitelist, vest);\n      } else if (vestingPools[_option].vestType == Type.Linear) {\n        return calculateVestAmountForLinear(whitelist, vest);\n      } else {\n        return calculateVestAmountForMonthly(whitelist, vest);\n      }\n    }\n  }\n\n  function calculateVestAmountForLinear(WhitelistInfo memory whitelist, VestingPool storage vest)\n    internal\n    view\n    returns (uint256)\n  {\n    uint256 initial = whitelist.dcbAmount.mul(vest.initialUnlockPercent).div(1000);\n\n    uint256 remaining = whitelist.dcbAmount.sub(initial);\n\n    if (block.timestamp >= vest.cliff.add(vest.duration)) {\n      return whitelist.dcbAmount;\n    } else {\n      return initial + remaining.mul(block.timestamp.sub(vest.cliff)).div(vest.duration);\n    }\n  }\n\n  function calculateVestAmountForInterval(WhitelistInfo memory whitelist, VestingPool storage vest)\n    internal\n    view\n    returns (uint256)\n  {\n    uint256 initial = whitelist.dcbAmount.mul(vest.initialUnlockPercent).div(1000);\n    uint256 remaining = whitelist.dcbAmount.sub(initial);\n\n    uint256 intervalsPassed = (block.timestamp.sub(vest.cliff)).div(vest.interval);\n    uint256 totalUnlocked = intervalsPassed.mul(vest.unlockPerInterval);\n\n    if (totalUnlocked >= 1000) {\n      return whitelist.dcbAmount;\n    } else {\n      return initial + remaining.mul(totalUnlocked).div(1000);\n    }\n  }\n\n  function calculateVestAmountForMonthly(WhitelistInfo memory whitelist, VestingPool storage vest)\n    internal\n    view\n    returns (uint256)\n  {\n    uint256 initial = whitelist.dcbAmount.mul(vest.initialUnlockPercent).div(1000);\n    uint256 remaining = whitelist.dcbAmount.sub(initial);\n\n    if (block.timestamp > vest.timestamps[vest.timestamps.length - 1]) {\n      return whitelist.dcbAmount;\n    } else {\n      uint256 multi = findCurrentTimestamp(vest.timestamps, block.timestamp);\n      uint256 totalUnlocked = multi.mul(vest.unlockPerInterval);\n\n      return initial + remaining.mul(totalUnlocked).div(1000);\n    }\n  }\n\n  function calculateReleasableAmount(uint256 _option, address _wallet)\n    internal\n    view\n    userInWhitelist(_option, _wallet)\n    returns (uint256)\n  {\n    uint256 idx = vestingPools[_option].hasWhitelist[_wallet].arrIdx;\n    return\n      calculateVestAmount(_option, _wallet).sub(\n        vestingPools[_option].whitelistPool[idx].distributedAmount\n      );\n  }\n\n  function findCurrentTimestamp(uint256[] memory timestamps, uint256 target)\n    internal\n    pure\n    returns (uint256 pos)\n  {\n    uint256 last = timestamps.length;\n    uint256 first = 0;\n    uint256 mid = 0;\n\n    if (target < timestamps[first]) {\n      return 0;\n    }\n\n    if (target >= timestamps[last - 1]) {\n      return last - 1;\n    }\n\n    while (first < last) {\n      mid = (first + last) / 2;\n\n      if (timestamps[mid] == target) {\n        return mid + 1;\n      }\n\n      if (target < timestamps[mid]) {\n        if (mid > 0 && target > timestamps[mid - 1]) {\n          return mid;\n        }\n\n        last = mid;\n      } else {\n        if (mid < last - 1 && target < timestamps[mid + 1]) {\n          return mid + 1;\n        }\n\n        first = mid + 1;\n      }\n    }\n    return mid + 1;\n  }\n}\n"
      },
      "/contracts/libraries/DateTime.sol": {
        "content": "//SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.10;\n\ncontract DateTime {\n  /*\n   *  Date and Time utilities for ethereum contracts\n   *\n   */\n  struct _DateTime {\n    uint16 year;\n    uint8 month;\n    uint8 day;\n    uint8 hour;\n    uint8 minute;\n    uint8 second;\n    uint8 weekday;\n  }\n\n  uint256 internal constant DAY_IN_SECONDS = 86400;\n  uint256 internal constant YEAR_IN_SECONDS = 31536000;\n  uint256 internal constant LEAP_YEAR_IN_SECONDS = 31622400;\n\n  uint256 internal constant HOUR_IN_SECONDS = 3600;\n  uint256 internal constant MINUTE_IN_SECONDS = 60;\n\n  uint16 internal constant ORIGIN_YEAR = 1970;\n\n  function isLeapYear(uint16 year) public pure returns (bool) {\n    if (year % 4 != 0) {\n      return false;\n    }\n    if (year % 100 != 0) {\n      return true;\n    }\n    if (year % 400 != 0) {\n      return false;\n    }\n    return true;\n  }\n\n  function leapYearsBefore(uint256 year) public pure returns (uint256) {\n    year -= 1;\n    return year / 4 - year / 100 + year / 400;\n  }\n\n  function getDaysInMonth(uint8 month, uint16 year) public pure returns (uint8) {\n    if (\n      month == 1 ||\n      month == 3 ||\n      month == 5 ||\n      month == 7 ||\n      month == 8 ||\n      month == 10 ||\n      month == 12\n    ) {\n      return 31;\n    } else if (month == 4 || month == 6 || month == 9 || month == 11) {\n      return 30;\n    } else if (isLeapYear(year)) {\n      return 29;\n    } else {\n      return 28;\n    }\n  }\n\n  function getYear(uint256 timestamp) public pure returns (uint16) {\n    uint256 secondsAccountedFor = 0;\n    uint16 year;\n    uint256 numLeapYears;\n\n    // Year\n    year = uint16(ORIGIN_YEAR + timestamp / YEAR_IN_SECONDS);\n    numLeapYears = leapYearsBefore(year) - leapYearsBefore(ORIGIN_YEAR);\n\n    secondsAccountedFor += LEAP_YEAR_IN_SECONDS * numLeapYears;\n    secondsAccountedFor += YEAR_IN_SECONDS * (year - ORIGIN_YEAR - numLeapYears);\n\n    while (secondsAccountedFor > timestamp) {\n      if (isLeapYear(uint16(year - 1))) {\n        secondsAccountedFor -= LEAP_YEAR_IN_SECONDS;\n      } else {\n        secondsAccountedFor -= YEAR_IN_SECONDS;\n      }\n      year -= 1;\n    }\n    return year;\n  }\n\n  function getMonth(uint256 timestamp) public pure returns (uint8) {\n    return parseTimestamp(timestamp).month;\n  }\n\n  function getDay(uint256 timestamp) public pure returns (uint8) {\n    return parseTimestamp(timestamp).day;\n  }\n\n  function getHour(uint256 timestamp) public pure returns (uint8) {\n    return uint8((timestamp / 60 / 60) % 24);\n  }\n\n  function getMinute(uint256 timestamp) public pure returns (uint8) {\n    return uint8((timestamp / 60) % 60);\n  }\n\n  function getSecond(uint256 timestamp) public pure returns (uint8) {\n    return uint8(timestamp % 60);\n  }\n\n  function getWeekday(uint256 timestamp) public pure returns (uint8) {\n    return uint8((timestamp / DAY_IN_SECONDS + 4) % 7);\n  }\n\n  function toTimestamp(\n    uint16 year,\n    uint8 month,\n    uint8 day\n  ) public pure returns (uint256 timestamp) {\n    return toTimestamp(year, month, day, 0, 0, 0);\n  }\n\n  function toTimestamp(\n    uint16 year,\n    uint8 month,\n    uint8 day,\n    uint8 hour\n  ) public pure returns (uint256 timestamp) {\n    return toTimestamp(year, month, day, hour, 0, 0);\n  }\n\n  function toTimestamp(\n    uint16 year,\n    uint8 month,\n    uint8 day,\n    uint8 hour,\n    uint8 minute\n  ) public pure returns (uint256 timestamp) {\n    return toTimestamp(year, month, day, hour, minute, 0);\n  }\n\n  function toTimestamp(\n    uint16 year,\n    uint8 month,\n    uint8 day,\n    uint8 hour,\n    uint8 minute,\n    uint8 second\n  ) public pure returns (uint256 timestamp) {\n    uint16 i;\n\n    // Year\n    for (i = ORIGIN_YEAR; i < year; i++) {\n      if (isLeapYear(i)) {\n        timestamp += LEAP_YEAR_IN_SECONDS;\n      } else {\n        timestamp += YEAR_IN_SECONDS;\n      }\n    }\n\n    // Month\n    uint8[12] memory monthDayCounts;\n    monthDayCounts[0] = 31;\n    if (isLeapYear(year)) {\n      monthDayCounts[1] = 29;\n    } else {\n      monthDayCounts[1] = 28;\n    }\n    monthDayCounts[2] = 31;\n    monthDayCounts[3] = 30;\n    monthDayCounts[4] = 31;\n    monthDayCounts[5] = 30;\n    monthDayCounts[6] = 31;\n    monthDayCounts[7] = 31;\n    monthDayCounts[8] = 30;\n    monthDayCounts[9] = 31;\n    monthDayCounts[10] = 30;\n    monthDayCounts[11] = 31;\n\n    for (i = 1; i < month; i++) {\n      timestamp += DAY_IN_SECONDS * monthDayCounts[i - 1];\n    }\n\n    // Day\n    timestamp += DAY_IN_SECONDS * (day - 1);\n\n    // Hour\n    timestamp += HOUR_IN_SECONDS * (hour);\n\n    // Minute\n    timestamp += MINUTE_IN_SECONDS * (minute);\n\n    // Second\n    timestamp += second;\n\n    return timestamp;\n  }\n\n  function parseTimestamp(uint256 timestamp) internal pure returns (_DateTime memory dt) {\n    uint256 secondsAccountedFor = 0;\n    uint256 buf;\n    uint8 i;\n\n    // Year\n    dt.year = getYear(timestamp);\n    buf = leapYearsBefore(dt.year) - leapYearsBefore(ORIGIN_YEAR);\n\n    secondsAccountedFor += LEAP_YEAR_IN_SECONDS * buf;\n    secondsAccountedFor += YEAR_IN_SECONDS * (dt.year - ORIGIN_YEAR - buf);\n\n    // Month\n    uint256 secondsInMonth;\n    for (i = 1; i <= 12; i++) {\n      secondsInMonth = DAY_IN_SECONDS * getDaysInMonth(i, dt.year);\n      if (secondsInMonth + secondsAccountedFor > timestamp) {\n        dt.month = i;\n        break;\n      }\n      secondsAccountedFor += secondsInMonth;\n    }\n\n    // Day\n    for (i = 1; i <= getDaysInMonth(dt.month, dt.year); i++) {\n      if (DAY_IN_SECONDS + secondsAccountedFor > timestamp) {\n        dt.day = i;\n        break;\n      }\n      secondsAccountedFor += DAY_IN_SECONDS;\n    }\n\n    // Hour\n    dt.hour = getHour(timestamp);\n\n    // Minute\n    dt.minute = getMinute(timestamp);\n\n    // Second\n    dt.second = getSecond(timestamp);\n\n    // Day of week.\n    dt.weekday = getWeekday(timestamp);\n  }\n}\n"
      },
      "@openzeppelin/contracts/utils/math/SafeMath.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)\n\npragma solidity ^0.8.0;\n\n// CAUTION\n// This version of SafeMath should only be used with Solidity 0.8 or later,\n// because it relies on the compiler's built in overflow checks.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations.\n *\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\n * now has built in overflow checking.\n */\nlibrary SafeMath {\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            uint256 c = a + b;\n            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n            // benefit is lost if 'b' is also tested.\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a == 0) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `+` operator.\n     *\n     * Requirements:\n     *\n     * - Addition cannot overflow.\n     */\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a + b;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a - b;\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `*` operator.\n     *\n     * Requirements:\n     *\n     * - Multiplication cannot overflow.\n     */\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a * b;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator.\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a / b;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting when dividing by zero.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a % b;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n     * overflow (when the result is negative).\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {trySub}.\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(\n        uint256 a,\n        uint256 b,\n        string memory errorMessage\n    ) internal pure returns (uint256) {\n        unchecked {\n            require(b <= a, errorMessage);\n            return a - b;\n        }\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(\n        uint256 a,\n        uint256 b,\n        string memory errorMessage\n    ) internal pure returns (uint256) {\n        unchecked {\n            require(b > 0, errorMessage);\n            return a / b;\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting with custom message when dividing by zero.\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {tryMod}.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(\n        uint256 a,\n        uint256 b,\n        string memory errorMessage\n    ) internal pure returns (uint256) {\n        unchecked {\n            require(b > 0, errorMessage);\n            return a % b;\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 amount\n    ) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/interfaces/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../token/ERC20/IERC20.sol\";\n"
      },
      "@openzeppelin/contracts/access/Ownable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor() {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
      }
    },
    "settings": {
      "remappings": [],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "evmVersion": "london",
      "libraries": {},
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      }
    }
  }}