creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "Vault.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.0;\r\n\r\ninterface IERC20 {\r\n    function transfer(address recipient, uint256 amount) external returns (bool);\r\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\r\n    function balanceOf(address account) external view returns (uint256);\r\n    function swapTokensForTokens(uint256 amount, address recipient) external;\r\n}\r\n\r\ncontract Vault {\r\n    struct TokenInfo {\r\n        IERC20 token;\r\n        uint256 depositAPY;\r\n        uint256 borrowAPY;\r\n        uint256 maxLTV;\r\n        uint256 liquidationThreshold;\r\n        uint256 liquidationPenalty;\r\n        mapping(address => uint256) depositBalances;\r\n        mapping(address => uint256) borrowBalances;\r\n        mapping(address => uint256) depositTimestamps;\r\n        mapping(address => uint256) borrowTimestamps;\r\n        mapping(address => uint256) rewardBalances;\r\n    }\r\n\r\n    mapping(address => TokenInfo) public tokens;\r\n    address public owner;\r\n    bool public isDepositWithdrawActive;\r\n    bool public isBorrowActive;\r\n    IERC20 public hSTEX;\r\n    IERC20 public GovhSTEX;\r\n\r\n    constructor() {\r\n        owner = msg.sender;\r\n        isDepositWithdrawActive = false;\r\n        isBorrowActive = false; \r\n    }\r\n\r\n    modifier onlyOwner() {\r\n        require(msg.sender == owner, \"Not owner\");\r\n        _;\r\n    }\r\n\r\n    function updateTokenParameters(address _tokenAddress, uint256 _depositAPY, uint256 _borrowAPY, uint256 _maxLTV, uint256 _liquidationThreshold, uint256 _liquidationPenalty) external onlyOwner {\r\n        TokenInfo storage token = tokens[_tokenAddress];\r\n        require(address(token.token) != address(0), \"Token not supported\");\r\n        token.depositAPY = _depositAPY;\r\n        token.borrowAPY = _borrowAPY;\r\n        token.maxLTV = _maxLTV;\r\n        token.liquidationThreshold = _liquidationThreshold;\r\n        token.liquidationPenalty = _liquidationPenalty;\r\n    }\r\n\r\n    // Function to add new token to the pool\r\n    function addToken(address _tokenAddress, uint256 _depositAPY, uint256 _borrowAPY, uint256 _maxLTV, uint256 _liquidationThreshold, uint256 _liquidationPenalty) external onlyOwner {\r\n        TokenInfo storage token = tokens[_tokenAddress];\r\n        token.token = IERC20(_tokenAddress);\r\n        token.depositAPY = _depositAPY;\r\n        token.borrowAPY = _borrowAPY;\r\n        token.maxLTV = _maxLTV;\r\n        token.liquidationThreshold = _liquidationThreshold;\r\n        token.liquidationPenalty = _liquidationPenalty;\r\n    }\r\n\r\n    // Deposit function\r\n    function deposit(address _tokenAddress, uint256 _amount) external {\r\n        require(isDepositWithdrawActive, \"Pool is not active\");\r\n        TokenInfo storage token = tokens[_tokenAddress];\r\n        require(address(token.token) != address(0), \"Token not supported\");\r\n\r\n        token.token.transferFrom(msg.sender, address(this), _amount);\r\n        _compoundInterest(_tokenAddress, msg.sender, true);\r\n        token.depositBalances[msg.sender] += _amount;\r\n        token.depositTimestamps[msg.sender] = block.timestamp;\r\n    }\r\n\r\n    // Withdraw function\r\n    function withdraw(address _tokenAddress, uint256 _amount) external {\r\n        TokenInfo storage token = tokens[_tokenAddress];\r\n        require(token.depositBalances[msg.sender] >= _amount, \"Insufficient balance\");\r\n\r\n        _compoundInterest(_tokenAddress, msg.sender, true);\r\n        token.depositBalances[msg.sender] -= _amount;\r\n        token.token.transfer(msg.sender, _amount);\r\n    }\r\n\r\n    // Borrow function\r\n    function borrow(address _tokenAddress, uint256 _amount) external {\r\n        TokenInfo storage token = tokens[_tokenAddress];\r\n        uint256 maxBorrowValue = token.depositBalances[msg.sender] * token.maxLTV / 100;\r\n        require(_amount <= maxBorrowValue, \"Borrow amount exceeds max LTV\");\r\n\r\n        _compoundInterest(_tokenAddress, msg.sender, false);\r\n        token.borrowBalances[msg.sender] += _amount;\r\n        token.borrowTimestamps[msg.sender] = block.timestamp;\r\n        token.token.transfer(msg.sender, _amount);\r\n    }\r\n\r\n    // Repay function\r\n    function repay(address _tokenAddress, uint256 _amount) external {\r\n        TokenInfo storage token = tokens[_tokenAddress];\r\n        require(token.borrowBalances[msg.sender] >= _amount, \"Repay amount exceeds borrow\");\r\n\r\n        _compoundInterest(_tokenAddress, msg.sender, false);\r\n        token.borrowBalances[msg.sender] -= _amount;\r\n        token.token.transferFrom(msg.sender, address(this), _amount);\r\n    }\r\n\r\n    // Check for liquidation\r\n    function checkLiquidation(address _tokenAddress, address _user) public view returns (bool) {\r\n        TokenInfo storage token = tokens[_tokenAddress];\r\n        uint256 collateralValue = token.depositBalances[_user];\r\n        uint256 borrowValue = token.borrowBalances[_user];\r\n        return borrowValue >= (collateralValue * token.liquidationThreshold) / 100;\r\n    }\r\n\r\n    // Liquidation function\r\n    function liquidate(address _tokenAddress, address _user) external {\r\n        TokenInfo storage token = tokens[_tokenAddress];\r\n        require(checkLiquidation(_tokenAddress, _user), \"Position not subject to liquidation\");\r\n\r\n        uint256 collateralValue = token.depositBalances[_user];\r\n        uint256 debtValue = token.borrowBalances[_user];\r\n        uint256 discountedCollateral = collateralValue * (100 - token.liquidationPenalty) / 100;\r\n        \r\n        require(debtValue <= discountedCollateral, \"Not enough collateral to cover the debt\");\r\n\r\n        uint256 collateralToLiquidate = debtValue * 100 / (100 - token.liquidationPenalty);\r\n        token.depositBalances[_user] -= collateralToLiquidate;\r\n        token.token.transfer(msg.sender, collateralToLiquidate);\r\n        token.borrowBalances[_user] -= debtValue;\r\n    }\r\n\r\n    function swaphSTEXToGovhSTEX(uint256 amount) external {\r\n        require(hSTEX.balanceOf(msg.sender) >= amount, \"Insufficient hSTEX balance\");\r\n        hSTEX.transferFrom(msg.sender, address(this), amount);\r\n        GovhSTEX.swapTokensForTokens(amount, msg.sender);\r\n    }\r\n\r\n    function swapRewardTohSTEX(uint256 amount) external {\r\n        require(GovhSTEX.balanceOf(msg.sender) >= amount, \"Insufficient GovhSTEX balance\");\r\n        GovhSTEX.transferFrom(msg.sender, address(this), amount);\r\n        hSTEX.swapTokensForTokens(amount, msg.sender);\r\n    }\r\n\r\n    function activateBaseCurrency(address _hSTEX) external onlyOwner {\r\n        require(address(hSTEX) == address(0), \"hSTEX already set\");\r\n        hSTEX = IERC20(_hSTEX);\r\n    }\r\n\r\n    function establishRewardAsset(address _GovhSTEX) external onlyOwner {\r\n        require(address(GovhSTEX) == address(0), \"GovhSTEX already set\");\r\n        GovhSTEX = IERC20(_GovhSTEX);\r\n    }\r\n\r\n        function claimGovhSTEXs(address _tokenAddress) external {\r\n        TokenInfo storage token = tokens[_tokenAddress];\r\n        require(token.rewardBalances[msg.sender] > 0, \"No rewards available\");\r\n        uint256 rewardAmount = token.rewardBalances[msg.sender];\r\n        token.rewardBalances[msg.sender] = 0;\r\n        GovhSTEX.transfer(msg.sender, rewardAmount);\r\n    }\r\n\r\n    // Toggle pool activity\r\n    function toggleDepositWithdrawActivity() external onlyOwner {\r\n        isDepositWithdrawActive = !isDepositWithdrawActive;\r\n    }\r\n\r\n    function toggleBorrowActivity() external onlyOwner {\r\n        isBorrowActive = !isBorrowActive;\r\n    }\r\n    function _compoundInterest(address _tokenAddress, address _user, bool isDepositor) internal {\r\n        TokenInfo storage token = tokens[_tokenAddress];\r\n        uint256 principal = isDepositor ? token.depositBalances[_user] : token.borrowBalances[_user];\r\n        uint256 rate = isDepositor ? token.depositAPY : token.borrowAPY;\r\n        uint256 timeElapsed = block.timestamp - (isDepositor ? token.depositTimestamps[_user] : token.borrowTimestamps[_user]);\r\n        \r\n        if (timeElapsed > 0 && principal > 0) {\r\n            uint256 interest = principal * rate / 100 * timeElapsed / 365 days;\r\n            if (isDepositor) {\r\n                token.depositBalances[_user] += interest;\r\n            } else {\r\n                token.borrowBalances[_user] += interest;\r\n            }\r\n        }\r\n    }\r\n}"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      }
    }
  }}