Contract 0x474dff730a8a2e216d86ef5366cec27934f16a28

Contract Overview

Balance:
0 DEV
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xace6b04e4e2c38935be77d7ed278349179edb6ae664f57a9d3adc0558be711be0x6080604027778202022-09-04 14:41:24266 days 15 hrs ago0xb6010d7ac4a8e9fa3e88b25f287fe725f2215208 IN  Contract Creation0 DEV0.000662185
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x79cabee35c10f186178356202e66a55f0ced9829b5d509aee29498d14fe4247f29700702022-10-07 13:59:18233 days 16 hrs ago 0x474dff730a8a2e216d86ef5366cec27934f16a280xb575a3d12d95e72249acbfce0f90abe28515d9f90 DEV
0x79cabee35c10f186178356202e66a55f0ced9829b5d509aee29498d14fe4247f29700702022-10-07 13:59:18233 days 16 hrs ago 0x474dff730a8a2e216d86ef5366cec27934f16a280xb575a3d12d95e72249acbfce0f90abe28515d9f90 DEV
0x79cabee35c10f186178356202e66a55f0ced9829b5d509aee29498d14fe4247f29700702022-10-07 13:59:18233 days 16 hrs ago 0x303d9f5a6241827621be657ec02f03d1a3e60cac0x474dff730a8a2e216d86ef5366cec27934f16a280 DEV
0x64b821a466dd94712f82c1cb864507f8a33775a07f86d81320251e4e2b486cfe29700532022-10-07 13:55:42233 days 16 hrs ago 0x474dff730a8a2e216d86ef5366cec27934f16a280xb575a3d12d95e72249acbfce0f90abe28515d9f90 DEV
0x64b821a466dd94712f82c1cb864507f8a33775a07f86d81320251e4e2b486cfe29700532022-10-07 13:55:42233 days 16 hrs ago 0x474dff730a8a2e216d86ef5366cec27934f16a280xb575a3d12d95e72249acbfce0f90abe28515d9f90 DEV
0x64b821a466dd94712f82c1cb864507f8a33775a07f86d81320251e4e2b486cfe29700532022-10-07 13:55:42233 days 16 hrs ago 0xc321e1a42af0e2186d06ab88f9ebdba083648fc90x474dff730a8a2e216d86ef5366cec27934f16a280 DEV
0xff86e1227def3e6825435e368c2c1761dbf7e3f3c95dd0ff3dcfa227cdf6fad829700352022-10-07 13:51:36233 days 16 hrs ago 0x474dff730a8a2e216d86ef5366cec27934f16a280xb575a3d12d95e72249acbfce0f90abe28515d9f90 DEV
0xff86e1227def3e6825435e368c2c1761dbf7e3f3c95dd0ff3dcfa227cdf6fad829700352022-10-07 13:51:36233 days 16 hrs ago 0x474dff730a8a2e216d86ef5366cec27934f16a280xb575a3d12d95e72249acbfce0f90abe28515d9f90 DEV
0xff86e1227def3e6825435e368c2c1761dbf7e3f3c95dd0ff3dcfa227cdf6fad829700352022-10-07 13:51:36233 days 16 hrs ago 0x4e7fc6a2740a47d93f81d5bdb54a2b7e412d0df90x474dff730a8a2e216d86ef5366cec27934f16a280 DEV
0x0d036c4adda0784f32b759d7764ba4d0e7456db1dcff987cacd66b2163598bdc29700272022-10-07 13:49:12233 days 16 hrs ago 0x474dff730a8a2e216d86ef5366cec27934f16a280xb575a3d12d95e72249acbfce0f90abe28515d9f90 DEV
0x0d036c4adda0784f32b759d7764ba4d0e7456db1dcff987cacd66b2163598bdc29700272022-10-07 13:49:12233 days 16 hrs ago 0x474dff730a8a2e216d86ef5366cec27934f16a280xb575a3d12d95e72249acbfce0f90abe28515d9f90 DEV
0x0d036c4adda0784f32b759d7764ba4d0e7456db1dcff987cacd66b2163598bdc29700272022-10-07 13:49:12233 days 16 hrs ago 0x4e7fc6a2740a47d93f81d5bdb54a2b7e412d0df90x474dff730a8a2e216d86ef5366cec27934f16a280 DEV
0x67332e6a1d17a6d45d57a34d52c1ea461fefcf31bf9ca04e398e429925d3003029700162022-10-07 13:46:42233 days 16 hrs ago 0x474dff730a8a2e216d86ef5366cec27934f16a280xb575a3d12d95e72249acbfce0f90abe28515d9f90 DEV
0x67332e6a1d17a6d45d57a34d52c1ea461fefcf31bf9ca04e398e429925d3003029700162022-10-07 13:46:42233 days 16 hrs ago 0x474dff730a8a2e216d86ef5366cec27934f16a280xb575a3d12d95e72249acbfce0f90abe28515d9f90 DEV
0x67332e6a1d17a6d45d57a34d52c1ea461fefcf31bf9ca04e398e429925d3003029700162022-10-07 13:46:42233 days 16 hrs ago 0x303d9f5a6241827621be657ec02f03d1a3e60cac0x474dff730a8a2e216d86ef5366cec27934f16a280 DEV
0xa37aaf7169750946be09f2ac3dba3fbf050bef98cdf49504a9e39a1c7697846b29700062022-10-07 13:43:42233 days 16 hrs ago 0x474dff730a8a2e216d86ef5366cec27934f16a280xb575a3d12d95e72249acbfce0f90abe28515d9f90 DEV
0xa37aaf7169750946be09f2ac3dba3fbf050bef98cdf49504a9e39a1c7697846b29700062022-10-07 13:43:42233 days 16 hrs ago 0x474dff730a8a2e216d86ef5366cec27934f16a280xb575a3d12d95e72249acbfce0f90abe28515d9f90 DEV
0xa37aaf7169750946be09f2ac3dba3fbf050bef98cdf49504a9e39a1c7697846b29700062022-10-07 13:43:42233 days 16 hrs ago 0x303d9f5a6241827621be657ec02f03d1a3e60cac0x474dff730a8a2e216d86ef5366cec27934f16a280 DEV
0x5912080c39f6683b97a9bead2cc6f44d2d10385dabb764a749514f7620ac1be629699412022-10-07 13:27:12233 days 16 hrs ago 0x474dff730a8a2e216d86ef5366cec27934f16a280xb575a3d12d95e72249acbfce0f90abe28515d9f90 DEV
0x5912080c39f6683b97a9bead2cc6f44d2d10385dabb764a749514f7620ac1be629699412022-10-07 13:27:12233 days 16 hrs ago 0x474dff730a8a2e216d86ef5366cec27934f16a280xb575a3d12d95e72249acbfce0f90abe28515d9f90 DEV
0x5912080c39f6683b97a9bead2cc6f44d2d10385dabb764a749514f7620ac1be629699412022-10-07 13:27:12233 days 16 hrs ago 0xc321e1a42af0e2186d06ab88f9ebdba083648fc90x474dff730a8a2e216d86ef5366cec27934f16a280 DEV
0x5ffb63ad01a772e998af22037bb0b6bede5636a0ae6f6cae61811fe3538ab7da29699392022-10-07 13:26:42233 days 16 hrs ago 0x474dff730a8a2e216d86ef5366cec27934f16a280xb575a3d12d95e72249acbfce0f90abe28515d9f90 DEV
0x5ffb63ad01a772e998af22037bb0b6bede5636a0ae6f6cae61811fe3538ab7da29699392022-10-07 13:26:42233 days 16 hrs ago 0x474dff730a8a2e216d86ef5366cec27934f16a280xb575a3d12d95e72249acbfce0f90abe28515d9f90 DEV
0x5ffb63ad01a772e998af22037bb0b6bede5636a0ae6f6cae61811fe3538ab7da29699392022-10-07 13:26:42233 days 16 hrs ago 0x303d9f5a6241827621be657ec02f03d1a3e60cac0x474dff730a8a2e216d86ef5366cec27934f16a280 DEV
0x6e7460f9955e64d6676312e82429fd26ddb7ae8b3ef85652edeb8a7654d474b929699322022-10-07 13:24:54233 days 16 hrs ago 0x474dff730a8a2e216d86ef5366cec27934f16a280xb575a3d12d95e72249acbfce0f90abe28515d9f90 DEV
[ Download CSV Export 
Loading

Similar Match Source Code
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0xc58d3032f51972A621545fdD2b9eCf60FC21805c

Contract Name:
TradingEmissionsQontroller

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 10 : TradingEmissionsQontroller.sol
//SPDX-License-Identifier: NONE
pragma solidity ^0.8.9;

import "./interfaces/IQAdmin.sol";
import "./interfaces/ITradingEmissionsQontroller.sol";
import "./interfaces/IQodaERC20.sol";

contract TradingEmissionsQontroller is ITradingEmissionsQontroller {

  struct EmissionsPhase {

    /// @notice Token reward per $1 USD in txn fees
    uint rewardRate;
    
    ///@ notice Current amount of tokens accrued in the current phase
    uint tokensAccrued;

    /// @notice Total amount of tokens reserved for the current phase
    uint tokensTotal;
  }
  
  /// @notice Contract storing all global Qoda parameters
  IQAdmin private _qAdmin;

  /// @notice Address of underlying QODA token
  IQodaERC20 private _qodaERC20;
  
  /// @notice Number of emissions phases
  uint private _numPhases;
  
  /// @notice Current phase for emissions
  uint private _currentPhase;

  /// @notice Total tokens allocated to reward for `TradingEmissionsQontroller`
  uint private _totalAllocation;
  
  /// @notice Track unclaimed rewards
  mapping(address => uint) private _claimableEmissions;

  /// @notice Map defining the emissions phase and associated configurations
  mapping(uint => EmissionsPhase) private _emissionsPhase;

  /// @notice Emitted when user claims emissions
  event ClaimEmissions(address account, uint amount);
  
  constructor(
              address qodaERC20Address,
              address qAdminAddress,
              uint[] memory rewardRate_,
              uint[] memory tokensTotal_,
              uint numPhases_,
              uint totalAllocation_
              ) {

    require(
            rewardRate_.length == numPhases_ &&
            tokensTotal_.length == numPhases_,
            "TEQ2 length mismatch"
            );
    
    // Initialize values
    _qodaERC20 = IQodaERC20(qodaERC20Address);
    _qAdmin = IQAdmin(qAdminAddress);
    _numPhases = numPhases_;
    _currentPhase = 0;
    _totalAllocation = totalAllocation_;
    
    // Initialize emissions phases and rewards config
    for (uint i = 0; i < numPhases_; i++){
      _emissionsPhase[i] = EmissionsPhase({
        rewardRate: rewardRate_[i],
        tokensTotal: tokensTotal_[i],
        tokensAccrued: 0
        });
    }

    // Sanity check on rewards
    uint totalRewards = 0;
    for(uint i=0; i<_numPhases; i++){
      totalRewards += _emissionsPhase[i].tokensTotal;
    }
    require(_totalAllocation == totalRewards, "TEQ0 incorrect rewards");
  }

  modifier onlyMarket() {
    require(_qAdmin.hasRole(_qAdmin.MARKET_ROLE(), msg.sender), "TEQ1 only market");
    _;
  }

  /** ACCESS CONTROLLED FUNCTIONS **/
  
  /// @notice Use the fees generated (in USD) as basis to calculate how much
  /// token reward to disburse for trading volumes. Only `FixedRateMarket`
  /// contracts may call this function.
  /// @param borrower Address of the borrower
  /// @param lender Address of the lender
  /// @param feeUSD Fees generated (in USD, scaled to 1e6)
  function updateRewards(
                         address borrower,
                         address lender,
                         uint feeUSD
                         ) external onlyMarket {

    _updateRewards(borrower, feeUSD);
    _updateRewards(lender, feeUSD);
  }

  
  /** USER INTERFACE **/

  /// @notice Mint the unclaimed rewards to user and reset their claimable emissions
  function claimEmissions() external {

    // Get the emissions accrued for the user
    uint reward = _claimableEmissions[msg.sender];

    require(reward > 0, "TEQ3 reward must be positive");
    
    // Reset user's claimable emissions
    _claimableEmissions[msg.sender] = 0;

    // Transfer the rewards directly from `TradingEmissionsQontroller` contract
    // to user. The assumption is that total supply of reward tokens have been
    // pre-minted to this contract address. This limits the maximum damage of
    // a potential hack to just tokens within the contract (compared to an
    // infinite mint of tokens if this contract were allowed to mint on a
    // callable function
    _qodaERC20.transfer(msg.sender, reward);

    // Emit the event
    emit ClaimEmissions(msg.sender, reward);
  }

  
  /** VIEW FUNCTIONS **/

  /// @notice Checks the amount of unclaimed trading rewards that the user can claim
  /// @param account Address of the user
  /// @return uint Amount of QODA token rewards the user may claim
  function claimableEmissions(address account) external view returns(uint){
    return _claimableEmissions[account];
  }

  function qAdmin() external view returns(address) {
    return address(_qAdmin);
  }

  function qodaERC20() external view returns(address) {
    return address(_qodaERC20);
  }

  function numPhases() external view returns(uint) {
    return _numPhases;
  }

  function currentPhase() external view returns(uint) {
    return _currentPhase;
  }

  function totalAllocation() external view returns(uint) {
    return _totalAllocation;
  }

  function emissionsPhase(uint phase) external view returns(uint, uint, uint) {
    uint rewardRate = _emissionsPhase[phase].rewardRate;
    uint tokensAccrued = _emissionsPhase[phase].tokensAccrued;
    uint tokensTotal = _emissionsPhase[phase].tokensTotal;
    return (rewardRate, tokensAccrued, tokensTotal);
  }
  
  /** INTERNAL FUNCTIONS **/

  /// @notice Use the fees generated (in USD) as basis to calculate how much
  /// token reward to disburse for trading volumes.
  /// @param account Address of the user
  /// @param feeUSD Fees generated (in USD, scaled to 1e6)
  function _updateRewards(address account, uint feeUSD) internal {

    if(_currentPhase == _numPhases){
      // All trading rewards have already been distributed
      return;
    }
          
    uint tokensTotal = _emissionsPhase[_currentPhase].tokensTotal;
    uint tokensAccrued = _emissionsPhase[_currentPhase].tokensAccrued;

    // One USD is 1000000 by convention (see QPriceOracle)
    uint proposedReward = _emissionsPhase[_currentPhase].rewardRate * feeUSD / 1000000;

    // Check if the `proposedReward` will push the emission schedule into the next phase
    if(proposedReward + tokensAccrued > tokensTotal) {

      // Total reward under old phase can't be more than the remaining reserved tokens in the phase
      uint rewardOldPhase = tokensTotal - tokensAccrued;
      
      // The reward is enough to move us to the next emissions phase
      // First, set `tokensAccrued` = `tokensTotal` in the current phase
      _emissionsPhase[_currentPhase].tokensAccrued = tokensTotal;

      // Move to next phase
      _currentPhase++;
      
      // Accrue the remaining amount of reward in `tokensAccrued` of next phase
      uint rewardNewPhase = proposedReward - rewardOldPhase;

      // Scale the remaining reward by the reward rate of the new phase
      rewardNewPhase = rewardNewPhase * _emissionsPhase[_currentPhase].rewardRate / _emissionsPhase[_currentPhase-1].rewardRate;
      _emissionsPhase[_currentPhase].tokensAccrued = rewardNewPhase;

      // Store the amount of claimable emissions for the user
      _claimableEmissions[account] += rewardOldPhase + rewardNewPhase;
      
    }else {

      // Accrue the full amount of reward in `tokensAccrued` of the current phase
      _emissionsPhase[_currentPhase].tokensAccrued += proposedReward;

      // Store the amount of claimable emissions for the user
      _claimableEmissions[account] += proposedReward;
    }

  }



}

File 2 of 10 : IQAdmin.sol
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

import "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./IFixedRateMarket.sol";
import "../libraries/QTypes.sol";

interface IQAdmin is IAccessControlUpgradeable {

  /// @notice Emitted when a new FixedRateMarket is deployed
  event CreateFixedRateMarket(address indexed marketAddress, address indexed tokenAddress, uint maturity);
  
  /// @notice Emitted when a new `Asset` is added
  event AddAsset(
                 address indexed tokenAddress,
                 bool isYieldBearing,
                 address oracleFeed,
                 uint collateralFactor,
                 uint marketFactor);

  /// @notice Emitted when setting `_qollateralManager`
  event SetQollateralManager(address qollateralManagerAddress);

  /// @notice Emitted when setting `_stakingEmissionsQontroller`
  event SetStakingEmissionsQontroller(address stakingEmissionsQontrollerAddress);

  /// @notice Emitted when setting `_tradingEmissionsQontroller`
  event SetTradingEmissionsQontroller(address tradingEmissionsQontrollerAddress);

  /// @notice Emitted when setting `_feeEmissionsQontroller`
  event SetFeeEmissionsQontroller(address feeEmissionsQontrollerAddress);

  /// @notice Emitted when setting `_veQoda`
  event SetVeQoda(address veQodaAddress);
  
  /// @notice Emitted when setting `collateralFactor`
  event SetCollateralFactor(address indexed tokenAddress, uint oldValue, uint newValue);

  /// @notice Emitted when setting `marketFactor`
  event SetMarketFactor(address indexed tokenAddress, uint oldValue, uint newValue);

  /// @notice Emitted when setting `minQuoteSize`
  event SetMinQuoteSize(address indexed tokenAddress, uint oldValue, uint newValue);
  
  /// @notice Emitted when `_initCollateralRatio` gets updated
  event SetInitCollateralRatio(uint oldValue, uint newValue);

  /// @notice Emitted when `_closeFactor` gets updated
  event SetCloseFactor(uint oldValue, uint newValue);

  /// @notice Emitted when `_repaymentGracePeriod` gets updated
  event SetRepaymentGracePeriod(uint oldValue, uint newValue);
  
  /// @notice Emitted when `_maturityGracePeriod` gets updated
  event SetMaturityGracePeriod(uint oldValue, uint newValue);
  
  /// @notice Emitted when `_liquidationIncentive` gets updated
  event SetLiquidationIncentive(uint oldValue, uint newValue);

  /// @notice Emitted when `_protocolFee` gets updated
  event SetProtocolFee(uint oldValue, uint newValue);
  
  /// @notice Emitted when `creditLimit` gets updated
  event SetCreditLimit(address accountAddress, uint oldValue, uint newValue); 
  
  /** ADMIN FUNCTIONS **/

  /// @notice Call upon initialization after deploying `QollateralManager` contract
  /// @param qollateralManagerAddress Address of `QollateralManager` deployment
  function _setQollateralManager(address qollateralManagerAddress) external;

  /// @notice Call upon initialization after deploying `StakingEmissionsQontroller` contract
  /// @param stakingEmissionsQontrollerAddress Address of `StakingEmissionsQontroller` deployment
  function _setStakingEmissionsQontroller(address stakingEmissionsQontrollerAddress) external;

  /// @notice Call upon initialization after deploying `TradingEmissionsQontroller` contract
  /// @param tradingEmissionsQontrollerAddress Address of `TradingEmissionsQontroller` deployment
  function _setTradingEmissionsQontroller(address tradingEmissionsQontrollerAddress) external;

  /// @notice Call upon initialization after deploying `FeeEmissionsQontroller` contract
  /// @param feeEmissionsQontroller Address of `FeeEmissionsQontroller` deployment
  function _setFeeEmissionsQontroller(address feeEmissionsQontroller) external;

  /// @notice Call upon initialization after deploying `veQoda` contract
  /// @param veQodaAddress Address of `veQoda` deployment
  function _setVeQoda(address veQodaAddress) external;
  
  /// @notice Call to adjust allowed limit in USD for given address to do uncollateralized borrow
  /// Note that if credit limit is lowered, there might be chance where user's loan is subjected to 
  /// instant liquidations. So it's crucial to notify the user in advance before attempting the action.
  /// @param accountAddress accoutn for credit limit adjustment
  /// @param creditLimit_ new credit limit in USD, scaled by 1e6
  function _setCreditLimit(address accountAddress, uint creditLimit_) external;

  /// @notice Admin function for adding new Assets. An Asset must be added before it
  /// can be used as collateral or borrowed. Note: We can create functionality for
  /// allowing borrows of a token but not using it as collateral by setting
  /// `collateralFactor` to zero.
  /// @param token ERC20 token corresponding to the Asset
  /// @param isYieldBearing True if token bears interest (eg aToken, cToken, mToken, etc)
  /// @param underlying Address of the underlying token
  /// @param oracleFeed Chainlink price feed address
  /// @param collateralFactor 0.0 to 1.0 (scaled to 1e8) for discounting risky assets
  /// @param marketFactor 0.0 to 1.0 (scaled to 1e8) for premium on risky borrows
  function _addAsset(
                     IERC20 token,
                     bool isYieldBearing,
                     address underlying,
                     address oracleFeed,
                     uint collateralFactor,
                     uint marketFactor
                     ) external;

  /// @notice Adds a new `FixedRateMarket` contract into the internal mapping of
  /// whitelisted market addresses
  /// @param market New `FixedRateMarket` contract
  function _addFixedRateMarket(IFixedRateMarket market) external;
  
  /// @notice Update the `collateralFactor` for a given `Asset`
  /// @param token ERC20 token corresponding to the Asset
  /// @param collateralFactor 0.0 to 1.0 (scaled to 1e8) for discounting risky assets
  function _setCollateralFactor(IERC20 token, uint collateralFactor) external;

  /// @notice Update the `marketFactor` for a given `Asset`
  /// @param token Address of the token corresponding to the Asset
  /// @param marketFactor 0.0 to 1.0 (scaled to 1e8) for discounting risky assets
  function _setMarketFactor(IERC20 token, uint marketFactor) external;

  /// @notice Set the minimum quote size for a particular `FixedRateMarket`
  /// @param market Address of the `FixedRateMarket` contract
  /// @param minQuoteSize_ Size in PV terms, local currency
  function _setMinQuoteSize(IFixedRateMarket market, uint minQuoteSize_) external;
  
  /// @notice Set the global initial collateral ratio
  /// @param initCollateralRatio_ New collateral ratio value
  function _setInitCollateralRatio(uint initCollateralRatio_) external;

  /// @notice Set the global close factor
  /// @param closeFactor_ New close factor value
  function _setCloseFactor(uint closeFactor_) external;

  /// @notice Set the global repayment grace period
  /// @param repaymentGracePeriod_ New repayment grace period
  function _setRepaymentGracePeriod(uint repaymentGracePeriod_) external;

  /// @notice Set the global maturity grace period
  /// @param maturityGracePeriod_ New maturity grace period
  function _setMaturityGracePeriod(uint maturityGracePeriod_) external;
  
  /// @notice Set the global liquidation incetive
  /// @param liquidationIncentive_ New liquidation incentive value
  function _setLiquidationIncentive(uint liquidationIncentive_) external;

  /// @notice Set the global annualized protocol fees for each market in basis points
  /// @param market Address of the `FixedRateMarket` contract
  /// @param protocolFee_ New protocol fee value (scaled to 1e4)
  function _setProtocolFee(IFixedRateMarket market, uint protocolFee_) external;
  
  /// @notice Set the global threshold in USD for protocol fee transfer
  /// @param thresholdUSD_ New threshold USD value (scaled by 1e6)
  function _setThresholdUSD(uint thresholdUSD_) external;
  
  /** VIEW FUNCTIONS **/

  function ADMIN_ROLE() external view returns(bytes32);

  function MARKET_ROLE() external view returns(bytes32);

  function MINTER_ROLE() external view returns(bytes32);

  function VETOKEN_ROLE() external view returns(bytes32);
  
  /// @notice Get the address of the `QollateralManager` contract
  function qollateralManager() external view returns(address);

  /// @notice Get the address of the `QPriceOracle` contract
  function qPriceOracle() external view returns(address);

  /// @notice Get the address of the `StakingEmissionsQontroller` contract
  function stakingEmissionsQontroller() external view returns(address);

  /// @notice Get the address of the `TradingEmissionsQontroller` contract
  function tradingEmissionsQontroller() external view returns(address);

  /// @notice Get the address of the `FeeEmissionsQontroller` contract
  function feeEmissionsQontroller() external view returns(address);

  /// @notice Get the address of the `veQoda` contract
  function veQoda() external view returns(address);

  /// @notice Get the credit limit with associated address, scaled by 1e6
  function creditLimit(address accountAddress) external view returns(uint);
  
  /// @notice Gets the `Asset` mapped to the address of a ERC20 token
  /// @param token ERC20 token
  /// @return QTypes.Asset Associated `Asset`
  function assets(IERC20 token) external view returns(QTypes.Asset memory);

  /// @notice Get all enabled `Asset`s
  /// @return address[] iterable list of enabled `Asset`s
  function allAssets() external view returns(address[] memory);
  
  /// @notice Gets the `CollateralFactor` associated with a ERC20 token
  /// @param token ERC20 token
  /// @return uint Collateral Factor, scaled by 1e8
  function collateralFactor(IERC20 token) external view returns(uint);

  /// @notice Gets the `MarketFactor` associated with a ERC20 token
  /// @param token ERC20 token
  /// @return uint Market Factor, scaled by 1e8
  function marketFactor(IERC20 token) external view returns(uint);

  /// @notice Gets the `maturities` associated with a ERC20 token
  /// @param token ERC20 token
  /// @return uint[] array of UNIX timestamps (in seconds) of the maturity dates
  function maturities(IERC20 token) external view returns(uint[] memory);
  
  /// @notice Get the MToken market corresponding to any underlying ERC20
  /// tokenAddress => mTokenAddress
  function underlyingToMToken(IERC20 token) external view returns(address);
  
  /// @notice Gets the address of the `FixedRateMarket` contract
  /// @param token ERC20 token
  /// @param maturity UNIX timestamp of the maturity date
  /// @return IFixedRateMarket Address of `FixedRateMarket` contract
  function fixedRateMarkets(IERC20 token, uint maturity) external view returns(IFixedRateMarket);

  /// @notice Check whether an address is a valid FixedRateMarket address.
  /// Can be used for checks for inter-contract admin/restricted function call.
  /// @param market `FixedRateMarket` contract
  /// @return bool True if valid false otherwise
  function isMarketEnabled(IFixedRateMarket market) external view returns(bool);

  function minQuoteSize(IFixedRateMarket market) external view returns(uint);
  
  function minCollateralRatio() external view returns(uint);

  function initCollateralRatio() external view returns(uint);

  function closeFactor() external view returns(uint);

  function repaymentGracePeriod() external view returns(uint);
  
  function maturityGracePeriod() external view returns(uint);
  
  function liquidationIncentive() external view returns(uint);

  /// @notice Annualized protocol fee in basis points, scaled by 1e4
  function protocolFee(IFixedRateMarket market) external view returns(uint);

  /// @notice threshold in USD where protocol fee from each market will be transferred into `FeeEmissionsQontroller`
  /// once this amount is reached, scaled by 1e6
  function thresholdUSD() external view returns(uint);
  
  /// @notice 2**256 - 1
  function UINT_MAX() external pure returns(uint);
  
  /// @notice Generic mantissa corresponding to ETH decimals
  function MANTISSA_DEFAULT() external pure returns(uint);

  /// @notice Mantissa for stablecoins
  function MANTISSA_STABLECOIN() external pure returns(uint);
  
  /// @notice Mantissa for collateral ratio
  function MANTISSA_COLLATERAL_RATIO() external pure returns(uint);

  /// @notice `assetFactor` and `marketFactor` have up to 8 decimal places precision
  function MANTISSA_FACTORS() external pure returns(uint);

  /// @notice Basis points have 4 decimal place precision
  function MANTISSA_BPS() external pure returns(uint);

  /// @notice Staked Qoda has 6 decimal place precision
  function MANTISSA_STAKING() external pure returns(uint);

  /// @notice `collateralFactor` cannot be above 1.0
  function MAX_COLLATERAL_FACTOR() external pure returns(uint);

  /// @notice `marketFactor` cannot be above 1.0
  function MAX_MARKET_FACTOR() external pure returns(uint);

  /// @notice version number of this contract, will be bumped upon contractual change
  function VERSION_NUMBER() external pure returns(string memory);
}

File 3 of 10 : ITradingEmissionsQontroller.sol
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

interface ITradingEmissionsQontroller {

  /** ACCESS CONTROLLED FUNCTIONS **/
  
  /// @notice Use the fees generated (in USD) as basis to calculate how much
  /// token reward to disburse for trading volumes. Only `FixedRateMarket`
  /// contracts may call this function.
  /// @param borrower Address of the borrower
  /// @param lender Address of the lender
  /// @param feeUSD Fees generated (in USD, scaled to 1e6)
  function updateRewards(address borrower, address lender, uint feeUSD) external;

  
  /** USER INTERFACE **/

  /// @notice Mint the unclaimed rewards to user and reset their claimable emissions
  function claimEmissions() external;

  
  /** VIEW FUNCTIONS **/

  /// @notice Checks the amount of unclaimed trading rewards that the user can claim
  /// @param account Address of the user
  /// @return uint Amount of QODA token rewards the user may claim
  function claimableEmissions(address account) external view returns(uint);

  function qAdmin() external view returns(address);

  function qodaERC20() external view returns(address);

  function numPhases() external view returns(uint);

  function currentPhase() external view returns(uint);

  function totalAllocation() external view returns(uint);

  function emissionsPhase(uint phase) external view returns(uint, uint, uint);
  
}

File 4 of 10 : IQodaERC20.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IQodaERC20 is IERC20 {
  
  /// @notice Mints tokens to a recipient, as long as it is under the
  /// supply cap. Reverts if the caller does not have the minter role.
  /// @param recipient Account to mint tokens to
  /// @param amount Amount of tokens to mint
  function mint(address recipient, uint amount) external returns(bool);
  
  function supplyCap() external view returns(uint);
}

File 5 of 10 : IAccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControlUpgradeable {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

File 6 of 10 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 7 of 10 : IFixedRateMarket.sol
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IFixedRateMarket is IERC20Upgradeable, IERC20MetadataUpgradeable {

  /// @notice Emitted when a borrower repays borrow.
  /// Boolean flag `withQTokens`= true if repaid via qTokens, false otherwise.
  event RepayBorrow(address indexed borrower, uint amount, bool withQTokens);

  /// @notice Emitted when a borrower is liquidated
  event LiquidateBorrow(
    address indexed borrower,
    address indexed liquidator,
    uint amount,
    address collateralTokenAddress,
    uint reward
  );

  /// @notice Emitted when a borrower and lender are matched for a fixed rate loan
  event FixedRateLoan(
    bytes32 indexed quoteId,
    address indexed borrower,
    address indexed lender,
    uint amountPV,
    uint amountFV,
    uint feeIncurred);

  /// @notice Emitted when an account cancels their Quote
  event CancelQuote(address indexed account, uint nonce);

  /// @notice Emitted when an account redeems their qTokens
  event RedeemQTokens(address indexed account, uint amount);
    
  /** USER INTERFACE **/

  /// @notice Execute against Quote as a borrower.
  /// @param amountPV Amount that the borrower wants to execute as PV
  /// @param lender Account of the lender
  /// @param quoteType *Lender's* type preference, 0 for PV+APR, 1 for FV+APR
  /// @param quoteExpiryTime Timestamp after which the quote is no longer valid
  /// @param APR In decimal form scaled by 1e4 (ex. 10.52% = 1052)
  /// @param cashflow Can be PV or FV depending on `quoteType`
  /// @param nonce For uniqueness of signature
  /// @param signature signed hash of the Quote message
  /// @return uint, uint Loan amount (`amountPV`) and repayment amount (`amountFV`)
  function borrow(
                  uint amountPV,
                  address lender,
                  uint8 quoteType,
                  uint64 quoteExpiryTime,
                  uint64 APR,
                  uint cashflow,
                  uint nonce,
                  bytes memory signature
                  ) external returns(uint, uint);

  /// @notice Execute against Quote as a lender.
  /// @param amountPV Amount that the lender wants to execute as PV
  /// @param borrower Account of the borrower
  /// @param quoteType *Borrower's* type preference, 0 for PV+APR, 1 for FV+APR
  /// @param quoteExpiryTime Timestamp after which the quote is no longer valid
  /// @param APR In decimal form scaled by 1e4 (ex. 10.52% = 1052)
  /// @param cashflow Can be PV or FV depending on `quoteType`
  /// @param nonce For uniqueness of signature
  /// @param signature signed hash of the Quote message
  /// @return uint, uint Loan amount (`amountPV`) and repayment amount (`amountFV`)
  function lend(
                uint amountPV,
                address borrower,
                uint8 quoteType,
                uint64 quoteExpiryTime,
                uint64 APR,
                uint cashflow,
                uint nonce,
                bytes memory signature
                ) external returns(uint, uint);
  
  /// @notice Borrower will make repayments to the smart contract, which
  /// holds the value in escrow until maturity to release to lenders.
  /// @param amount Amount to repay
  /// @return uint Remaining account borrow amount
  function repayBorrow(uint amount) external returns(uint);

  /// @notice By setting the nonce in `_voidNonces` to true, this is equivalent to
  /// invalidating the Quote (i.e. cancelling the quote)
  /// param nonce Nonce of the Quote to be cancelled
  function cancelQuote(uint nonce) external;

  /// @notice This function allows net lenders to redeem qTokens for the
  /// underlying token. Redemptions may only be permitted after loan maturity
  /// plus `_maturityGracePeriod`. The public interface redeems specified amount
  /// of qToken from existing balance.
  /// @param amount Amount of qTokens to redeem
  /// @return uint Amount of qTokens redeemed
  function redeemQTokens(uint amount) external returns(uint);

  /// @notice This function allows net lenders to redeem qTokens for the
  /// underlying token. Redemptions may only be permitted after loan maturity
  /// plus `_maturityGracePeriod`. The public interface redeems the entire qToken
  /// balance.
  /// @return uint Amount of qTokens redeemed
  function redeemAvailableQTokens() external returns(uint);

  /// @notice Get amount of qTokens user can redeem based on current loan repayment ratio
  /// @return uint amount of qTokens user can redeem
  function redeemableQTokens() external view returns(uint);

  /// @notice If an account is in danger of being undercollateralized (i.e.
  /// collateralRatio < 1.0) or has not repaid past maturity plus `_repaymentGracePeriod`,
  /// any user may liquidate that account by paying back the loan on behalf of the account. 
  /// In return, the liquidator receives collateral belonging to the account equal in value to 
  /// the repayment amount in USD plus the liquidation incentive amount as a bonus.
  /// @param borrower Address of account that is undercollateralized
  /// @param amount Amount to repay on behalf of account
  /// @param collateralToken Liquidator's choice of which currency to be paid in
  function liquidateBorrow(
                           address borrower,
                           uint amount,
                           IERC20 collateralToken
                           ) external;
  
  /** VIEW FUNCTIONS **/
  
  /// @notice Get the address of the `QollateralManager`
  /// @return address
  function qollateralManager() external view returns(address);

  /// @notice Get the address of the ERC20 token which the loan will be denominated
  /// @return IERC20
  function underlyingToken() external view returns(IERC20);

  /// @notice Get the UNIX timestamp (in seconds) when the market matures
  /// @return uint
  function maturity() external view returns(uint);

  /// @notice Get the minimum quote size for this market
  /// @return uint Minimum quote size, in PV terms, local currency
  function minQuoteSize() external view returns(uint);
  
  /// @notice True if a nonce for a Quote is voided, false otherwise.
  /// Used for checking if a Quote is a duplicated.
  /// @param account Account to query
  /// @param nonce Nonce to query
  /// @return bool True if used, false otherwise
  function isNonceVoid(address account, uint nonce) external view returns(bool);

  /// @notice Get the total balance of borrows by user
  /// @param account Account to query
  /// @return uint Borrows
  function accountBorrows(address account) external view returns(uint);

  /// @notice Get the current total partial fill for a Quote
  /// @param quoteId ID of the Quote - this is the keccak256 hash of the signature
  /// @return uint Partial fill
  function quoteFill(bytes32 quoteId) external view returns(uint);

  /// @notice Get the `protocolFee` associated with this market
  /// @return uint annualized protocol fee, scaled by 1e4
  function protocolFee() external view returns(uint);

  /// @notice Get the `protocolFee` associated with this market, prorated by time till maturity 
  /// @param amount loan amount
  /// @param timeNow block timestamp for calculating time till maturity 
  /// @return uint prorated protocol fee, scaled by 1e4
  function proratedProtocolFee(uint amount, uint timeNow) external view returns(uint);

  /// @notice Get the `protocolFee` associated with this market, prorated by time till maturity from now 
  /// @param amount loan amount
  /// @return uint prorated protocol fee, scaled by 1e4
  function proratedProtocolFeeNow(uint amount) external view returns(uint);

  /// @notice Gets the current `redemptionRatio` where owned qTokens can be redeemed up to
  /// @return uint redemption ratio, scaled by 1e18
  function redemptionRatio() external view returns(uint);

  /// @notice Tokens redeemed across all users so far
  /// @return uint redeemed amount of qToken
  function tokensRedeemedTotal() external view returns(uint);

  /// @notice Get total protocol fee accrued in this market so far, in local currency
  /// @return uint accrued fee
  function totalAccruedFees() external view returns(uint);

}

File 8 of 10 : QTypes.sol
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

library QTypes {

  /// @notice Contains all the details of an Asset. Assets  must be defined
  /// before they can be used as collateral.
  /// @member isEnabled True if an asset is defined, false otherwise
  /// @member isYieldBearing True if token bears interest (eg aToken, cToken, mToken, etc)
  /// @member underlying Address of the underlying token
  /// @member oracleFeed Address of the corresponding chainlink oracle feed
  /// @member collateralFactor 0.0 to 1.0 (scaled to 1e8) for discounting risky assets
  /// @member marketFactor 0.0 1.0 for premium on risky borrows
  /// @member maturities Iterable storage for all enabled maturities
  struct Asset {
    bool isEnabled;
    bool isYieldBearing;
    address underlying;
    address oracleFeed;
    uint collateralFactor;
    uint marketFactor;
    uint[] maturities;
  }

  /// @notice Contains all the fields of a published Quote
  /// @notice quoteId ID of the quote - this is the keccak256 hash of signature
  /// @param marketAddress Address of `FixedRateLoanMarket` contract
  /// @param quoter Account of the Quoter
  /// @param quoteType 0 for PV+APR, 1 for FV+APR
  /// @param side 0 if Quoter is borrowing, 1 if Quoter is lending
  /// @param quoteExpiryTime Timestamp after which the quote is no longer valid
  /// @param APR In decimal form scaled by 1e4 (ex. 10.52% = 1052)
  /// @param cashflow Can be PV or FV depending on `quoteType`
  /// @param nonce For uniqueness of signature
  /// @param signature Signed hash of the Quote message
  struct Quote {
    bytes32 quoteId;
    address marketAddress;
    address quoter;
    uint8 quoteType;
    uint8 side;
    uint64 quoteExpiryTime; //if 0, then quote never expires
    uint64 APR;
    uint cashflow;
    uint nonce;
    bytes signature;
  }
  

}

File 9 of 10 : IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20Upgradeable {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 10 of 10 : IERC20MetadataUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20Upgradeable.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20MetadataUpgradeable is IERC20Upgradeable {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"qodaERC20Address","type":"address"},{"internalType":"address","name":"qAdminAddress","type":"address"},{"internalType":"uint256[]","name":"rewardRate_","type":"uint256[]"},{"internalType":"uint256[]","name":"tokensTotal_","type":"uint256[]"},{"internalType":"uint256","name":"numPhases_","type":"uint256"},{"internalType":"uint256","name":"totalAllocation_","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClaimEmissions","type":"event"},{"inputs":[],"name":"claimEmissions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"claimableEmissions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentPhase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"phase","type":"uint256"}],"name":"emissionsPhase","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numPhases","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"qAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"qodaERC20","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAllocation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"borrower","type":"address"},{"internalType":"address","name":"lender","type":"address"},{"internalType":"uint256","name":"feeUSD","type":"uint256"}],"name":"updateRewards","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b5060405162000b5a38038062000b5a8339810160408190526200003491620002f1565b818451148015620000455750818351145b620000975760405162461bcd60e51b815260206004820152601460248201527f54455132206c656e677468206d69736d6174636800000000000000000000000060448201526064015b60405180910390fd5b600180546001600160a01b038089166001600160a01b03199283161790925560008054928816929091169190911781556002839055600381905560048290555b828110156200017457604051806060016040528086838151811062000100576200010062000393565b602002602001015181526020016000815260200185838151811062000129576200012962000393565b602090810291909101810151909152600083815260068252604090819020835181559183015160018301559190910151600290910155806200016b81620003bf565b915050620000d7565b506000805b600254811015620001b957600081815260066020526040902060020154620001a29083620003dd565b915080620001b081620003bf565b91505062000179565b5080600454146200020d5760405162461bcd60e51b815260206004820152601660248201527f5445513020696e636f727265637420726577617264730000000000000000000060448201526064016200008e565b50505050505050620003f8565b80516001600160a01b03811681146200023257600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200025f57600080fd5b815160206001600160401b03808311156200027e576200027e62000237565b8260051b604051601f19603f83011681018181108482111715620002a657620002a662000237565b604052938452858101830193838101925087851115620002c557600080fd5b83870191505b84821015620002e657815183529183019190830190620002cb565b979650505050505050565b60008060008060008060c087890312156200030b57600080fd5b62000316876200021a565b955062000326602088016200021a565b60408801519095506001600160401b03808211156200034457600080fd5b620003528a838b016200024d565b955060608901519150808211156200036957600080fd5b506200037889828a016200024d565b9350506080870151915060a087015190509295509295509295565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415620003d657620003d6620003a9565b5060010190565b60008219821115620003f357620003f3620003a9565b500190565b61075280620004086000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063a591a6f411610066578063a591a6f414610107578063bf5d433214610111578063c0cb9acf14610136578063ce4013081461015f578063fd4368311461017057600080fd5b8063055ad42e146100985780630e101b1e146100af57806379203dc4146100f75780638b5a6d7e146100ff575b600080fd5b6003545b6040519081526020015b60405180910390f35b6100dc6100bd3660046105ad565b6000908152600660205260409020805460018201546002909201549092565b604080519384526020840192909252908201526060016100a6565b60045461009c565b60025461009c565b61010f610183565b005b6001546001600160a01b03165b6040516001600160a01b0390911681526020016100a6565b61009c6101443660046105e2565b6001600160a01b031660009081526005602052604090205490565b6000546001600160a01b031661011e565b61010f61017e366004610604565b6102b9565b33600090815260056020526040902054806101e55760405162461bcd60e51b815260206004820152601c60248201527f5445513320726577617264206d75737420626520706f7369746976650000000060448201526064015b60405180910390fd5b3360008181526005602052604080822091909155600154905163a9059cbb60e01b81526004810192909252602482018390526001600160a01b03169063a9059cbb90604401602060405180830381600087803b15801561024457600080fd5b505af1158015610258573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027c9190610640565b5060408051338152602081018390527f0d962b580b08e94b6cd0d0ed9da8371103adfad40f998c68bda1f58c7a97ffa4910160405180910390a150565b60005460408051633e27ec9b60e01b815290516001600160a01b03909216916391d14854918391633e27ec9b91600480820192602092909190829003018186803b15801561030657600080fd5b505afa15801561031a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061033e9190610662565b6040516001600160e01b031960e084901b168152600481019190915233602482015260440160206040518083038186803b15801561037b57600080fd5b505afa15801561038f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b39190610640565b6103f25760405162461bcd60e51b815260206004820152601060248201526f1511544c481bdb9b1e481b585c9ad95d60821b60448201526064016101dc565b6103fc838261040b565b610406828261040b565b505050565b600254600354141561041b575050565b6003546000908152600660205260408120600281015460018201549154909290620f42409061044b908690610691565b61045591906106b0565b90508261046283836106d2565b111561054f57600061047483856106ea565b600380546000908152600660205260408120600101879055815492935061049a83610701565b90915550600090506104ac82846106ea565b90506006600060016003546104c191906106ea565b815260208082019290925260409081016000908120546003548252600690935220546104ed9083610691565b6104f791906106b0565b6003546000908152600660205260409020600101819055905061051a81836106d2565b6001600160a01b038816600090815260056020526040812080549091906105429084906106d2565b909155506105a692505050565b600354600090815260066020526040812060010180548392906105739084906106d2565b90915550506001600160a01b038516600090815260056020526040812080548392906105a09084906106d2565b90915550505b5050505050565b6000602082840312156105bf57600080fd5b5035919050565b80356001600160a01b03811681146105dd57600080fd5b919050565b6000602082840312156105f457600080fd5b6105fd826105c6565b9392505050565b60008060006060848603121561061957600080fd5b610622846105c6565b9250610630602085016105c6565b9150604084013590509250925092565b60006020828403121561065257600080fd5b815180151581146105fd57600080fd5b60006020828403121561067457600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156106ab576106ab61067b565b500290565b6000826106cd57634e487b7160e01b600052601260045260246000fd5b500490565b600082198211156106e5576106e561067b565b500190565b6000828210156106fc576106fc61067b565b500390565b60006000198214156107155761071561067b565b506001019056fea264697066735822122079ce79efe074fb8b227d4710b7f8a5eb70a325a73f2ece1030754bd2eeb0951164736f6c63430008090033000000000000000000000000329602da21a8d686fa192e13e00af0bd23c74f730000000000000000000000002dedeb6310d209f9a89ab3b0941ae2c6a424e2c100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000001851b1318cbc171700000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000120d4da7b0bd14000000000000000000000000000000000000000000000000000d8d726b7177a8000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000c28d898c65e0b8b8000000000000000000000000000000000000000000000000c28d898c65e0b8b800000

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading