all files / contracts/modules/ Governance.sol

97.78% Statements 44/45
95.45% Branches 21/22
100% Functions 8/8
100% Lines 44/44
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109                        1154×   1154× 1152×               734× 733×   733×       394× 394×   393× 393×   393×   393×   393×   393×   393×                     16× 16×   15×   14× 14×   14×   14×                                          
// SPDX-License-Identifier: GPL-2.0-or-later
 
pragma solidity ^0.8.0;
 
import "../BaseLogic.sol";
import "../BaseIRM.sol";
 
 
contract Governance is BaseLogic {
    constructor(bytes32 moduleGitCommit_) BaseLogic(MODULEID__GOVERNANCE, moduleGitCommit_) {}
 
    modifier governorOnly {
        address msgSender = unpackTrailingParamMsgSender();
 
        require(msgSender == governorAdmin, "e/gov/unauthorized");
        _;
    }
 
 
 
    // setters
 
    function setAssetConfig(address underlying, AssetConfig calldata newConfig) external nonReentrant governorOnly {
        require(underlyingLookup[underlying].eTokenAddress == newConfig.eTokenAddress, "e/gov/etoken-mismatch");
        underlyingLookup[underlying] = newConfig;
 
        emit GovSetAssetConfig(underlying, newConfig);
    }
 
    function setIRM(address underlying, uint interestRateModel, bytes calldata resetParams) external nonReentrant governorOnly {
        address eTokenAddr = underlyingLookup[underlying].eTokenAddress;
        require(eTokenAddr != address(0), "e/gov/underlying-not-activated");
 
        AssetStorage storage assetStorage = eTokenLookup[eTokenAddr];
        AssetCache memory assetCache = loadAssetCache(underlying, assetStorage);
 
        callInternalModule(interestRateModel, abi.encodeWithSelector(BaseIRM.reset.selector, underlying, resetParams));
 
        assetStorage.interestRateModel = assetCache.interestRateModel = uint32(interestRateModel);
 
        updateInterestRate(assetStorage, assetCache);
 
        logAssetStatus(assetCache);
 
        emit GovSetIRM(underlying, interestRateModel, resetParams);
    }
 
    function setPricingConfig(address underlying, uint16 newPricingType, uint32 newPricingParameter) external nonReentrant governorOnly {
        address eTokenAddr = underlyingLookup[underlying].eTokenAddress;
        require(eTokenAddr != address(0), "e/gov/underlying-not-activated");
 
        AssetStorage storage assetStorage = eTokenLookup[eTokenAddr];
        AssetCache memory assetCache = loadAssetCache(underlying, assetStorage);
 
        require(newPricingType == assetCache.pricingType, "e/gov/pricing-type-change-not-supported");
 
        assetStorage.pricingType = assetCache.pricingType = newPricingType;
        assetStorage.pricingParameters = assetCache.pricingParameters = newPricingParameter;
 
        emit GovSetPricingConfig(underlying, newPricingType, newPricingParameter);
    }
 
    function setReserveFee(address underlying, uint32 newReserveFee) external nonReentrant governorOnly {
        address eTokenAddr = underlyingLookup[underlying].eTokenAddress;
        require(eTokenAddr != address(0), "e/gov/underlying-not-activated");
 
        require(newReserveFee <= RESERVE_FEE_SCALE || newReserveFee == type(uint32).max, "e/gov/bad-reserve-fee");
 
        AssetStorage storage assetStorage = eTokenLookup[eTokenAddr];
        AssetCache memory assetCache = loadAssetCache(underlying, assetStorage);
 
        assetStorage.reserveFee = assetCache.reserveFee = newReserveFee;
 
        emit GovSetReserveFee(underlying, newReserveFee);
    }
 
    function convertReserves(address underlying, address recipient, uint amount) external nonReentrant governorOnly {
        address eTokenAddress = underlyingLookup[underlying].eTokenAddress;
        require(eTokenAddress != address(0), "e/gov/underlying-not-activated");
 
        updateAverageLiquidity(recipient);
 
        AssetStorage storage assetStorage = eTokenLookup[eTokenAddress];
        AssetCache memory assetCache = loadAssetCache(underlying, assetStorage);
 
        if (amount == type(uint).max) amount = assetStorage.reserveBalance;
        require(amount <= assetStorage.reserveBalance, "e/gov/insufficient-reserves");
 
        assetStorage.reserveBalance = assetCache.reserveBalance = assetCache.reserveBalance - uint96(amount);
        // Decrease totalBalances because increaseBalance will increase it by amount
        assetStorage.totalBalances = assetCache.totalBalances = encodeAmount(assetCache.totalBalances - amount);
 
        increaseBalance(assetStorage, assetCache, eTokenAddress, recipient, amount);
 
        Iif (assetStorage.users[recipient].owed != 0) checkLiquidity(recipient);
 
        logAssetStatus(assetCache);
 
        emit GovConvertReserves(underlying, recipient, balanceToUnderlyingAmount(assetCache, amount));
    }
 
 
    // getters
 
    function getGovernorAdmin() external view returns (address) {
        return governorAdmin;
    }
}