creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "OperaLocker.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\n\nimport \"IERC20.sol\";\n\n\ncontract OperaLocker {\n    address public owner;\n    mapping(address => bool) public lockDisabled;\n\n    mapping(address => mapping(address => uint256)) public accountsLockedTokens;\n    mapping(address => mapping(address => uint256))\n        public accountsLockedTimeOfToken;\n\n    event tokenLocked(\n        address account,\n        address token,\n        uint256 amount,\n        uint256 locktime\n    );\n    event tokenWithdrawn(address account, address token, uint256 amount);\n\n    constructor() {\n        owner = msg.sender;\n    }\n\n    modifier onlyOwner() {\n        require(owner == msg.sender, \"only owner\");\n        _;\n    }\n\n    function getAddressLockedTokens(\n        address user,\n        address token\n    ) public view returns (uint256) {\n        return accountsLockedTokens[user][token];\n    }\n\n    function changeLockEnabled(bool locked, address addy) external onlyOwner {\n        lockDisabled[addy] = locked;\n    }\n\n    function getAddressLockedTime(\n        address user,\n        address token\n    ) public view returns (uint256) {\n        return accountsLockedTimeOfToken[user][token];\n    }\n\n    function withdrawTokenAmount(\n        address tokenAddress,\n        uint256 amount\n    ) external {\n        if (!lockDisabled[tokenAddress]) {\n            require(\n                accountsLockedTimeOfToken[msg.sender][tokenAddress] > 0 &&\n                    accountsLockedTimeOfToken[msg.sender][tokenAddress] <=\n                    block.timestamp,\n                \"Tokens are not ready to be unlocked.\"\n            );\n        }\n\n        require(\n            accountsLockedTokens[msg.sender][tokenAddress] >= amount,\n            \"You did not lock this many tokens.\"\n        );\n        if (accountsLockedTokens[msg.sender][tokenAddress] == amount) {\n            accountsLockedTimeOfToken[msg.sender][tokenAddress] = 0; //resetting timer for lock to indicate no tokens locked\n        }\n        accountsLockedTokens[msg.sender][tokenAddress] -= amount;\n        IERC20 tokenToLock = IERC20(tokenAddress);\n        uint256 balanceBefore = tokenToLock.balanceOf(address(this));\n        tokenToLock.transfer(msg.sender, amount);\n        uint256 balanceAfter = tokenToLock.balanceOf(address(this));\n        require(\n            balanceBefore - amount == balanceAfter,\n            \"Failed to transfer amount of tokens when withdrawing.\"\n        );\n        emit tokenWithdrawn(msg.sender, tokenAddress, amount);\n    }\n\n    function lockTokens(\n        address tokenAddress,\n        uint256 amount,\n        uint256 locktimeInSeconds\n    ) external {\n        require(\n            accountsLockedTimeOfToken[msg.sender][tokenAddress] == 0,\n            \"You already have this tocken locked.\"\n        );\n        // require(amount > 0, \"Cannot Lock 0 tokens\");\n        IERC20 tokenToLock = IERC20(tokenAddress);\n        uint256 balanceBefore = tokenToLock.balanceOf(address(this));\n        tokenToLock.transferFrom(msg.sender, address(this), amount);\n        uint256 balanceAfter = tokenToLock.balanceOf(address(this));\n        require(\n            balanceAfter - amount == balanceBefore,\n            \"Failed to transfer amount of tokens when locking.\"\n        );\n        accountsLockedTokens[msg.sender][tokenAddress] = amount;\n        accountsLockedTimeOfToken[msg.sender][tokenAddress] =\n            block.timestamp +\n            locktimeInSeconds;\n        emit tokenLocked(\n            msg.sender,\n            tokenAddress,\n            accountsLockedTokens[msg.sender][tokenAddress],\n            block.timestamp + locktimeInSeconds\n        );\n    }\n\n    function increaseLockTime(\n        address tokenAddress,\n        uint256 increasedSeconds\n    ) external {\n        require(\n            accountsLockedTimeOfToken[msg.sender][tokenAddress] > 0,\n            \"You have no tokens locked.\"\n        );\n        require(increasedSeconds > 0, \"Cannot Lock 0 seconds\");\n        accountsLockedTimeOfToken[msg.sender][tokenAddress] += increasedSeconds;\n        emit tokenLocked(\n            msg.sender,\n            tokenAddress,\n            accountsLockedTokens[msg.sender][tokenAddress],\n            accountsLockedTimeOfToken[msg.sender][tokenAddress]\n        );\n    }\n\n    function increaseTokenAmount(\n        address tokenAddress,\n        uint256 amount\n    ) external {\n        require(\n            accountsLockedTimeOfToken[msg.sender][tokenAddress] > 0,\n            \"You have no tokens locked.\"\n        );\n        require(amount > 0, \"Cannot Lock 0 tokens\");\n        IERC20 tokenToLock = IERC20(tokenAddress);\n        uint256 balanceBefore = tokenToLock.balanceOf(address(this));\n        tokenToLock.transferFrom(msg.sender, address(this), amount);\n        uint256 balanceAfter = tokenToLock.balanceOf(address(this));\n        require(\n            balanceAfter - amount == balanceBefore,\n            \"Failed to transfer amount of tokens when locking.\"\n        );\n        accountsLockedTokens[msg.sender][tokenAddress] += amount;\n        emit tokenLocked(\n            msg.sender,\n            tokenAddress,\n            accountsLockedTokens[msg.sender][tokenAddress],\n            accountsLockedTimeOfToken[msg.sender][tokenAddress]\n        );\n    }\n\n    function withdraw() external onlyOwner {\n        payable(owner).transfer(address(this).balance);\n    }\n\n    function emergencyRescue(address token, uint256 amount) external onlyOwner {\n        IERC20 tokenToRescue = IERC20(token);\n        tokenToRescue.transfer(owner, amount);\n    }\n\n    receive() external payable {}\n}\n"
      },
      "IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\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(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n    event Transfer(address indexed from, address indexed to, uint256 value);\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
      }
    },
    "settings": {
      "evmVersion": "istanbul",
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "libraries": {
        "OperaLocker.sol": {}
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      }
    }
  }}