S Price: $0.570821 (-3.85%)

Contract Diff Checker

Contract Name:
ImpermaxWhitelist

Contract Source Code:

pragma solidity =0.5.16;
pragma experimental ABIEncoderV2;

interface IBorrowable {
	function reserveFactor() external view returns (uint);
	function borrowTracker() external view returns (address);
	function kinkUtilizationRate() external view returns (uint);
	function adjustSpeed() external view returns (uint);

	function RESERVE_FACTOR_MAX() external pure returns (uint);
	function KINK_UR_MIN() external pure returns (uint);
	function KINK_UR_MAX() external pure returns (uint);
	function ADJUST_SPEED_MIN() external pure returns (uint);
	function ADJUST_SPEED_MAX() external pure returns (uint);

	function _setReserveFactor(uint newReserveFactor) external;
	function _setKinkUtilizationRate(uint newKinkUtilizationRate) external;
	function _setAdjustSpeed(uint newAdjustSpeed) external;
	function _setBorrowTracker(address newBorrowTracker) external;
}

interface ICollateral {
	function safetyMarginSqrt() external view returns (uint);
	function liquidationIncentive() external view returns (uint);
	function liquidationFee() external view returns (uint);

	function SAFETY_MARGIN_SQRT_MIN() external pure returns (uint);
	function SAFETY_MARGIN_SQRT_MAX() external pure returns (uint);
	function LIQUIDATION_INCENTIVE_MIN() external pure returns (uint);
	function LIQUIDATION_INCENTIVE_MAX() external pure returns (uint);
	function LIQUIDATION_FEE_MAX() external pure returns (uint);
	
	function _setSafetyMarginSqrt(uint newSafetyMarginSqrt) external;
	function _setLiquidationIncentive(uint newLiquidationIncentive) external;
	function _setLiquidationFee(uint newLiquidationFee) external;
}

interface IFactory {
	function admin() external view returns (address);
	function pendingAdmin() external view returns (address);
	function reservesAdmin() external view returns (address);
	function reservesPendingAdmin() external view returns (address);
	function reservesManager() external view returns (address);

	function getLendingPool(address uniswapV2Pair) external view returns (
		bool initialized, 
		uint24 lendingPoolId, 
		address collateral, 
		address borrowable0, 
		address borrowable1
	);
	function allLendingPools(uint) external view returns (address uniswapV2Pair);
	function allLendingPoolsLength() external view returns (uint);

	function _setPendingAdmin(address newPendingAdmin) external;
	function _acceptAdmin() external;
	function _setReservesPendingAdmin(address newPendingAdmin) external;
	function _acceptReservesAdmin() external;
	function _setReservesManager(address newReservesManager) external;
}


contract Ownable {
    address public admin;
    address public pendingAdmin;

    event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);
	event NewAdmin(address oldAdmin, address newAdmin);
    
    constructor(address _admin) public {
        admin = _admin;
        emit NewAdmin(address(0), admin);
    }

    function _setPendingAdmin(address newPendingAdmin) external onlyOwner {
		address oldPendingAdmin = pendingAdmin;
		pendingAdmin = newPendingAdmin;
		emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);
	}

	function _acceptAdmin() external {
		require(msg.sender == pendingAdmin, "ImpermaxOwnable: UNAUTHORIZED");
		address oldAdmin = admin;
		address oldPendingAdmin = pendingAdmin;
		admin = pendingAdmin;
		pendingAdmin = address(0);
		emit NewAdmin(oldAdmin, admin);
		emit NewPendingAdmin(oldPendingAdmin, address(0));
	}

	modifier onlyOwner() {
		require(msg.sender == admin, "ImpermaxOwnable: UNAUTHORIZED");
		_;
	}
}

interface IImpermaxWhitelist {
	enum State {
		Unlisted,
		Listed,
		Deprecated,
		Blacklisted
	}
    function pairsState(address factory, address pair) external view returns(State);
    event ChangedState(address indexed factory, address indexed pair, State state);
    function setPairState(address factory, address pair, State state) external;
}

contract ImpermaxWhitelist is Ownable, IImpermaxWhitelist {
	mapping(address => mapping(address => State)) public pairsState; 

    constructor(address _admin) public Ownable(_admin) {}

    function setPairState(address factory, address pair, State state) onlyOwner external {
        pairsState[factory][pair] = state;
        emit ChangedState(factory, pair, state);
    }
}


interface IImpermaxConfigManager {

    struct CollateralConfig {
        uint safetyMarginSqrt;
        uint liquidationIncentive;
        uint liquidationFee;
    }

    struct BorrowableConfig {
        uint reserveFactor;
        uint kinkUtilizationRate;
        uint adjustSpeed;
        address borrowTracker;
    }

    struct PairConfig {
        address factory;
        address pair;
        CollateralConfig collateralConfig;
        BorrowableConfig borrowable0Config;
        BorrowableConfig borrowable1Config;
        IImpermaxWhitelist.State whitelistState;
    }

    event NewProposal(uint indexed index, PairConfig[] proposal);
    event RejectedProposal(uint indexed index, PairConfig[] proposal);
    event ApprovedProposal(uint indexed index, PairConfig[] proposal);
    event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);
	event NewAdmin(address oldAdmin, address newAdmin);
    event BecomeContractAdmin(address factory);
    event TransferContractOwnership(address factory, address newPendingAdmin);
	
    function admin() external view returns(address);
    function pendingAdmin() external view returns(address);
    function proposals(uint, uint) external view returns(PairConfig memory);
    function proposalsLength() external view returns(uint);
    function getProposal(uint) external view returns (PairConfig[] memory);
    function whitelist() external view returns(address);
	
	function makeProposal(PairConfig[] calldata proposal) external;
    function rejectProposal(uint index) external;
    function approveProposal(uint index) external;

    function _setPendingAdmin(address newPendingAdmin) external;
	function _acceptAdmin() external;
    function _becomeContractAdmin(address ownableContract) external;
    function _setContractAdmin(address ownableContract, address newPendingAdmin) external;
}


contract ImpermaxConfigManager is IImpermaxConfigManager, Ownable {

    mapping(uint => PairConfig[]) public proposals;
    uint public proposalsLength;

    function getProposal(uint index) external view returns (PairConfig[] memory) {
        return proposals[index];
    }

    address public whitelist;
    
    constructor(address _admin, address _whitelist) public Ownable(_admin) {
        whitelist = _whitelist;
    }

	/* Internal */

    function _checkSetting(uint parameter, uint min, uint max) internal pure {
		require(parameter >= min, "ImpermaxConfigManager: INVALID_SETTING");
		require(parameter <= max, "ImpermaxConfigManager: INVALID_SETTING");
	}

    function _checkCSetting(address collateral, CollateralConfig memory config) internal pure {
        _checkSetting(config.safetyMarginSqrt, ICollateral(collateral).SAFETY_MARGIN_SQRT_MIN(), ICollateral(collateral).SAFETY_MARGIN_SQRT_MAX());
        _checkSetting(config.liquidationIncentive, ICollateral(collateral).LIQUIDATION_INCENTIVE_MIN(), ICollateral(collateral).LIQUIDATION_INCENTIVE_MAX());
        _checkSetting(config.liquidationFee, 0, ICollateral(collateral).LIQUIDATION_FEE_MAX());
    }

    function _checkBSetting(address borrowable, BorrowableConfig memory config) internal pure {
        _checkSetting(config.reserveFactor, 0, IBorrowable(borrowable).RESERVE_FACTOR_MAX());
        _checkSetting(config.kinkUtilizationRate, IBorrowable(borrowable).KINK_UR_MIN(), IBorrowable(borrowable).KINK_UR_MAX());
        _checkSetting(config.adjustSpeed, IBorrowable(borrowable).ADJUST_SPEED_MIN(), IBorrowable(borrowable).ADJUST_SPEED_MAX());
    }

    function _removeProposal(uint index) internal {
        delete proposals[index];
    }

    function _checkPending(uint index) internal view {
        require(proposals[index][0].factory != address(0), "ImpermaxConfigManager: NOT_PENDING");
    }

    function _actualCollateralConfig(address collateral) internal view returns (CollateralConfig memory oldConfig) {
        oldConfig.safetyMarginSqrt = ICollateral(collateral).safetyMarginSqrt();
        oldConfig.liquidationIncentive = ICollateral(collateral).liquidationIncentive();
        oldConfig.liquidationFee = ICollateral(collateral).liquidationFee();
    }

    function _actualBorrowableConfig(address borrowable) internal view returns (BorrowableConfig memory oldConfig) {
        oldConfig.reserveFactor = IBorrowable(borrowable).reserveFactor();
        oldConfig.kinkUtilizationRate = IBorrowable(borrowable).kinkUtilizationRate();
        oldConfig.adjustSpeed = IBorrowable(borrowable).adjustSpeed();
        oldConfig.borrowTracker = IBorrowable(borrowable).borrowTracker();
    }

    function _setCollateralConfig(address collateral, CollateralConfig memory newConfig) internal {
		CollateralConfig memory oldConfig = _actualCollateralConfig(collateral);
        if(newConfig.safetyMarginSqrt != oldConfig.safetyMarginSqrt)
            ICollateral(collateral)._setSafetyMarginSqrt(newConfig.safetyMarginSqrt);
        if(newConfig.liquidationIncentive != oldConfig.liquidationIncentive)
            ICollateral(collateral)._setLiquidationIncentive(newConfig.liquidationIncentive);
        if(newConfig.liquidationFee != oldConfig.liquidationFee)
            ICollateral(collateral)._setLiquidationFee(newConfig.liquidationFee);
    }

    function _setBorrowableConfig(address borrowable, BorrowableConfig memory newConfig) internal {
		BorrowableConfig memory oldConfig = _actualBorrowableConfig(borrowable);
        if(newConfig.reserveFactor != oldConfig.reserveFactor)
            IBorrowable(borrowable)._setReserveFactor(newConfig.reserveFactor);
        if(newConfig.kinkUtilizationRate != oldConfig.kinkUtilizationRate)
            IBorrowable(borrowable)._setKinkUtilizationRate(newConfig.kinkUtilizationRate);
        if(newConfig.adjustSpeed != oldConfig.adjustSpeed)
            IBorrowable(borrowable)._setAdjustSpeed(newConfig.adjustSpeed);
        if(newConfig.borrowTracker != oldConfig.borrowTracker)
            IBorrowable(borrowable)._setBorrowTracker(newConfig.borrowTracker);
    }

	/* External */

    function makeProposal(PairConfig[] calldata proposal) external nonReentrant {
        for(uint i = 0; i < proposal.length; i++) {
			PairConfig memory config = proposal[i];
            (,, address collateral, address borrowable0, address borrowable1) = IFactory(config.factory).getLendingPool(config.pair);
            _checkCSetting(collateral, config.collateralConfig);
            _checkBSetting(borrowable0, config.borrowable0Config);
            _checkBSetting(borrowable1, config.borrowable1Config);
			proposals[proposalsLength].push(config);
        }
        emit NewProposal(proposalsLength, proposal);
        proposalsLength++;
    }

    function rejectProposal(uint index) external onlyOwner nonReentrant {
        _checkPending(index);
        emit RejectedProposal(index, proposals[index]);
        _removeProposal(index);
    }

    function approveProposal(uint index) external onlyOwner nonReentrant {
        _checkPending(index);
		PairConfig[] memory proposal = proposals[index];
        uint length = proposal.length;
        for(uint i = 0; i < length; i++) {
			PairConfig memory config = proposal[i];
            (,, address collateral, address borrowable0, address borrowable1) = IFactory(config.factory).getLendingPool(config.pair);
            _setCollateralConfig(collateral, config.collateralConfig);
            _setBorrowableConfig(borrowable0, config.borrowable0Config);
            _setBorrowableConfig(borrowable1, config.borrowable1Config);
            IImpermaxWhitelist(whitelist).setPairState(config.factory, config.pair, config.whitelistState);
        }
        emit ApprovedProposal(index, proposal);
        _removeProposal(index);
    }

	/* Ownership management */

    function _becomeContractAdmin(address ownableContract) external onlyOwner nonReentrant {
        Ownable(ownableContract)._acceptAdmin();
		emit BecomeContractAdmin(ownableContract);
    }

    function _setContractAdmin(address ownableContract, address newPendingAdmin) external onlyOwner nonReentrant {
        Ownable(ownableContract)._setPendingAdmin(newPendingAdmin);
		emit TransferContractOwnership(ownableContract, newPendingAdmin);
    }

	/* Utils */

	// prevents a contract from calling itself, directly or indirectly.
	bool internal _notEntered = true;
	modifier nonReentrant() {
		require(_notEntered, "ImpermaxConfigManager: REENTERED");
		_notEntered = false;
		_;
		_notEntered = true;
	}
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):