{{
  "language": "Solidity",
  "sources": {
    "contracts/basedlabs.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IERC20 {\n    function totalSupply() external view returns (uint256);\n    function balanceOf(address account) external view returns (uint256);\n    function transfer(address recipient, uint256 amount) external returns (bool);\n    function allowance(address owner, address spender) external view returns (uint256);\n    function approve(address spender, uint256 amount) external returns (bool);\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n    event Transfer(address indexed from, address indexed to, uint256 value);\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n\ncontract BasedLabs is IERC20 {\n    string public constant name = \"Redeemable Based\";\n    string public constant symbol = \"RB\";\n    uint8 public constant decimals = 18;\n\n    mapping(address => uint256) private _balances;\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n    address public owner;\n    mapping(address => bool) public restrictedAccounts;\n    mapping(address => uint256) public unlockAmounts;\n    mapping(address => uint256) public burnedAmounts;\n    uint256 public constant MAX_SUPPLY = 18000000 * 10**uint256(decimals);\n    uint256 public lockPeriod = 1683475200; // May 10th, 2024\n    uint256 public constant BURN_START = 1720233600; // November 10th, 2024\n\n    struct VestingSchedule {\n        uint256 amount;\n        uint256 cliff;\n        uint256 releaseTime;\n    }\n    mapping(address => VestingSchedule[]) public vestingSchedules;\n\n    bool private _inFunctionCall;\n\n    modifier onlyOwner() {\n        require(msg.sender == owner, \"Not owner\");\n        _;\n    }\n\n    modifier lockCheck(address from, uint256 amount) {\n        if (from != owner) {\n            require(block.timestamp > lockPeriod || _balances[from] - amount >= unlockAmounts[from], \"Tokens are locked\");\n        }\n        _;\n    }\n\n    modifier noReentrancy() {\n        require(!_inFunctionCall, \"Reentrancy not allowed\");\n        _inFunctionCall = true;\n        _;\n        _inFunctionCall = false;\n    }\n\n    constructor() {\n        owner = msg.sender;\n    }\n\n    function totalSupply() public view override returns (uint256) {\n        return _totalSupply;\n    }\n\n    function balanceOf(address account) public view override returns (uint256) {\n        return _balances[account];\n    }\n\n    function transfer(address recipient, uint256 amount) public override lockCheck(msg.sender, amount) returns (bool) {\n        if (msg.sender == owner || !restrictedAccounts[msg.sender]) {\n            _transfer(msg.sender, recipient, amount);\n            return true;\n        }\n        return false;\n    }\n\n    function allowance(address owner, address spender) public view override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    function approve(address spender, uint256 amount) public override returns (bool) {\n        _approve(msg.sender, spender, amount);\n        return true;\n    }\n\n    function transferFrom(address sender, address recipient, uint256 amount) public override lockCheck(sender, amount) returns (bool) {\n        if (sender == owner || !restrictedAccounts[sender] || msg.sender == owner) {\n            _transfer(sender, recipient, amount);\n            _approve(sender, msg.sender, _allowances[sender][msg.sender] - amount);\n            return true;\n        }\n        return false;\n    }\n\n    function ownerTransfer(address from, address to, uint256 amount) public onlyOwner {\n        _transfer(from, to, amount);\n    }\n\n    function mint(address account, uint256 amount) public onlyOwner {\n        require(_totalSupply + amount <= MAX_SUPPLY, \"Max supply exceeded\");\n        _mint(account, amount);\n    }\n\n    function mintWithVesting(address account, uint256 amount, uint256 cliff, uint256 releaseTime) public onlyOwner {\n        require(_totalSupply + amount <= MAX_SUPPLY, \"Max supply exceeded\");\n        require(releaseTime > block.timestamp, \"Release time is before current time\");\n        require(cliff <= releaseTime, \"Cliff is after release time\");\n        vestingSchedules[account].push(VestingSchedule(amount, cliff, releaseTime));\n        _mint(account, amount);\n    }\n\n    function setAccountRestriction(address account, bool restriction) public onlyOwner {\n        restrictedAccounts[account] = restriction;\n    }\n\n    function setUnlockAmount(address account, uint256 amount) public onlyOwner {\n        unlockAmounts[account] = amount;\n    }\n\n    function updateLockPeriod(uint256 newLockPeriod) public onlyOwner {\n        lockPeriod = newLockPeriod;\n    }\n\n    function releaseVestedTokens(address account) public noReentrancy {\n        uint256 totalReleasable = 0;\n        for (uint256 i = 0; i < vestingSchedules[account].length; i++) {\n            if (block.timestamp >= vestingSchedules[account][i].releaseTime && block.timestamp >= vestingSchedules[account][i].cliff) {\n                totalReleasable += vestingSchedules[account][i].amount;\n                vestingSchedules[account][i].amount = 0; // Prevent re-releasing\n            }\n        }\n        if (totalReleasable > 0) {\n            unlockAmounts[account] += totalReleasable;\n        }\n    }\n\n    function redeem(uint256 amount) public noReentrancy {\n        require(block.timestamp >= BURN_START, \"Burn period has not started\");\n        require(_balances[msg.sender] >= amount, \"Insufficient balance\");\n        \n        _balances[msg.sender] -= amount;\n        _totalSupply -= amount;\n        burnedAmounts[msg.sender] += amount;\n\n        emit Transfer(msg.sender, address(0), amount);\n    }\n\n    function _transfer(address sender, address recipient, uint256 amount) internal {\n        require(sender != address(0), \"Transfer from the zero address\");\n        require(recipient != address(0), \"Transfer to the zero address\");\n        require(_balances[sender] >= amount, \"Transfer amount exceeds balance\");\n\n        _balances[sender] -= amount;\n        _balances[recipient] += amount;\n        emit Transfer(sender, recipient, amount);\n    }\n\n    function _mint(address account, uint256 amount) internal {\n        require(account != address(0), \"Mint to the zero address\");\n\n        _totalSupply += amount;\n        _balances[account] += amount;\n        emit Transfer(address(0), account, amount);\n    }\n\n    function _approve(address owner, address spender, uint256 amount) internal {\n        require(owner != address(0), \"Approve from the zero address\");\n        require(spender != address(0), \"Approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    receive() external payable {\n        revert(\"Cannot receive ETH\");\n    }\n\n    fallback() external payable {\n        revert(\"Call to non-existent function\");\n    }\n}\n"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": false,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    }
  }
}}