diff --git a/src/aave/AaveWrapper.sol b/src/aave/AaveWrapper.sol index d58bb22..2a70802 100644 --- a/src/aave/AaveWrapper.sol +++ b/src/aave/AaveWrapper.sol @@ -19,7 +19,9 @@ import { console2 } from "forge-std/console2.sol"; contract AaveWrapper is IERC3156PPFlashLender, IFlashLoanSimpleReceiver { using TransferHelper for IERC20; - using FunctionCodec for function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory); + using + FunctionCodec + for function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory); using FunctionCodec for bytes24; using FixedPointMathLib for uint256; using ReserveConfiguration for DataTypes.ReserveConfigurationMap; @@ -37,24 +39,20 @@ contract AaveWrapper is IERC3156PPFlashLender, IFlashLoanSimpleReceiver { POOL = IPool(ADDRESSES_PROVIDER.getPool()); } - function flashFee(IERC20 asset, uint256 amount) - external - view - returns (uint256 fee) - { + function flashFee(IERC20 asset, uint256 amount) external view returns (uint256 fee) { DataTypes.ReserveData memory reserve = POOL.getReserveData(address(asset)); DataTypes.ReserveConfigurationMap memory configuration = reserve.configuration; - if (!configuration.getPaused() && - configuration.getActive() && - configuration.getFlashLoanEnabled() && - amount < asset.balanceOf(reserve.aTokenAddress) + if ( + !configuration.getPaused() && configuration.getActive() && configuration.getFlashLoanEnabled() + && amount < asset.balanceOf(reserve.aTokenAddress) ) fee = amount.mulWadUp(POOL.FLASHLOAN_PREMIUM_TOTAL() * 0.0001e18); else fee = type(uint256).max; } /// @dev Use the aggregator to serve an ERC3156++ flash loan. - /// @dev Forward the callback to the callback receiver. The borrower only needs to trust the aggregator and its governance, instead of the underlying lenders. + /// @dev Forward the callback to the callback receiver. The borrower only needs to trust the aggregator and its + /// governance, instead of the underlying lenders. /// @param loanReceiver The address receiving the flash loan /// @param asset The asset to be loaned /// @param amount The amount to loaned @@ -67,7 +65,8 @@ contract AaveWrapper is IERC3156PPFlashLender, IFlashLoanSimpleReceiver { uint256 amount, bytes calldata initiatorData, /// @dev callback. - /// This is a concatenation of (address, bytes4), where the address is the callback receiver, and the bytes4 is the signature of callback function. + /// This is a concatenation of (address, bytes4), where the address is the callback receiver, and the bytes4 is + /// the signature of callback function. /// The arguments in the callback function are fixed. /// If the callback receiver needs to know the loan receiver, it should be encoded by the initiator in `data`. /// @param initiator The address that called this function @@ -78,7 +77,10 @@ contract AaveWrapper is IERC3156PPFlashLender, IFlashLoanSimpleReceiver { /// @param data The ABI encoded data to be passed to the callback /// @return result ABI encoded result of the callback function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) callback - ) external returns (bytes memory result) { + ) + external + returns (bytes memory result) + { bytes memory data = abi.encode(msg.sender, loanReceiver, callback.encodeFunction(), initiatorData); POOL.flashLoanSimple({ @@ -103,7 +105,11 @@ contract AaveWrapper is IERC3156PPFlashLender, IFlashLoanSimpleReceiver { uint256 fee, address aaveInitiator, bytes calldata data - ) external override returns (bool) { + ) + external + override + returns (bool) + { console2.log("executeOperation"); require(msg.sender == address(POOL), "not pool"); require(aaveInitiator == address(this), "AaveFlashLoanProvider: not initiator"); @@ -117,7 +123,8 @@ contract AaveWrapper is IERC3156PPFlashLender, IFlashLoanSimpleReceiver { // decode data console2.log("abi decoding..."); - (initiator, loanReceiver, encodedCallback, initiatorData) = abi.decode(data, (address, address, bytes24, bytes)); + (initiator, loanReceiver, encodedCallback, initiatorData) = + abi.decode(data, (address, address, bytes24, bytes)); console2.log("callback decoding..."); callback = encodedCallback.decodeFunction(); @@ -125,15 +132,14 @@ contract AaveWrapper is IERC3156PPFlashLender, IFlashLoanSimpleReceiver { IERC20(asset).safeTransfer(loanReceiver, amount); } // release loanReceiver and encodedCallback from the stack - // call the callback and tell the calback receiver to repay the loan to this contract bytes memory result = callback(initiator, address(this), IERC20(asset), amount, fee, initiatorData); - if(result.length > 0) { + if (result.length > 0) { // if there's any result, it is kept in a storage variable to be retrieved later in this tx _callbackResult = result; } return true; } -} \ No newline at end of file +} diff --git a/src/aave/interfaces/DataTypes.sol b/src/aave/interfaces/DataTypes.sol index 7b2e4a2..20d2f8e 100644 --- a/src/aave/interfaces/DataTypes.sol +++ b/src/aave/interfaces/DataTypes.sol @@ -2,264 +2,267 @@ pragma solidity ^0.8.0; library DataTypes { - struct ReserveData { - //stores the reserve configuration - ReserveConfigurationMap configuration; - //the liquidity index. Expressed in ray - uint128 liquidityIndex; - //the current supply rate. Expressed in ray - uint128 currentLiquidityRate; - //variable borrow index. Expressed in ray - uint128 variableBorrowIndex; - //the current variable borrow rate. Expressed in ray - uint128 currentVariableBorrowRate; - //the current stable borrow rate. Expressed in ray - uint128 currentStableBorrowRate; - //timestamp of last update - uint40 lastUpdateTimestamp; - //the id of the reserve. Represents the position in the list of the active reserves - uint16 id; - //aToken address - address aTokenAddress; - //stableDebtToken address - address stableDebtTokenAddress; - //variableDebtToken address - address variableDebtTokenAddress; - //address of the interest rate strategy - address interestRateStrategyAddress; - //the current treasury balance, scaled - uint128 accruedToTreasury; - //the outstanding unbacked aTokens minted through the bridging feature - uint128 unbacked; - //the outstanding debt borrowed against this asset in isolation mode - uint128 isolationModeTotalDebt; - } + struct ReserveData { + //stores the reserve configuration + ReserveConfigurationMap configuration; + //the liquidity index. Expressed in ray + uint128 liquidityIndex; + //the current supply rate. Expressed in ray + uint128 currentLiquidityRate; + //variable borrow index. Expressed in ray + uint128 variableBorrowIndex; + //the current variable borrow rate. Expressed in ray + uint128 currentVariableBorrowRate; + //the current stable borrow rate. Expressed in ray + uint128 currentStableBorrowRate; + //timestamp of last update + uint40 lastUpdateTimestamp; + //the id of the reserve. Represents the position in the list of the active reserves + uint16 id; + //aToken address + address aTokenAddress; + //stableDebtToken address + address stableDebtTokenAddress; + //variableDebtToken address + address variableDebtTokenAddress; + //address of the interest rate strategy + address interestRateStrategyAddress; + //the current treasury balance, scaled + uint128 accruedToTreasury; + //the outstanding unbacked aTokens minted through the bridging feature + uint128 unbacked; + //the outstanding debt borrowed against this asset in isolation mode + uint128 isolationModeTotalDebt; + } - struct ReserveConfigurationMap { - //bit 0-15: LTV - //bit 16-31: Liq. threshold - //bit 32-47: Liq. bonus - //bit 48-55: Decimals - //bit 56: reserve is active - //bit 57: reserve is frozen - //bit 58: borrowing is enabled - //bit 59: stable rate borrowing enabled - //bit 60: asset is paused - //bit 61: borrowing in isolation mode is enabled - //bit 62: siloed borrowing enabled - //bit 63: flashloaning enabled - //bit 64-79: reserve factor - //bit 80-115 borrow cap in whole tokens, borrowCap == 0 => no cap - //bit 116-151 supply cap in whole tokens, supplyCap == 0 => no cap - //bit 152-167 liquidation protocol fee - //bit 168-175 eMode category - //bit 176-211 unbacked mint cap in whole tokens, unbackedMintCap == 0 => minting disabled - //bit 212-251 debt ceiling for isolation mode with (ReserveConfiguration::DEBT_CEILING_DECIMALS) decimals - //bit 252-255 unused + struct ReserveConfigurationMap { + //bit 0-15: LTV + //bit 16-31: Liq. threshold + //bit 32-47: Liq. bonus + //bit 48-55: Decimals + //bit 56: reserve is active + //bit 57: reserve is frozen + //bit 58: borrowing is enabled + //bit 59: stable rate borrowing enabled + //bit 60: asset is paused + //bit 61: borrowing in isolation mode is enabled + //bit 62: siloed borrowing enabled + //bit 63: flashloaning enabled + //bit 64-79: reserve factor + //bit 80-115 borrow cap in whole tokens, borrowCap == 0 => no cap + //bit 116-151 supply cap in whole tokens, supplyCap == 0 => no cap + //bit 152-167 liquidation protocol fee + //bit 168-175 eMode category + //bit 176-211 unbacked mint cap in whole tokens, unbackedMintCap == 0 => minting disabled + //bit 212-251 debt ceiling for isolation mode with (ReserveConfiguration::DEBT_CEILING_DECIMALS) decimals + //bit 252-255 unused + uint256 data; + } - uint256 data; - } + struct UserConfigurationMap { + /** + * @dev Bitmap of the users collaterals and borrows. It is divided in pairs of bits, one pair per asset. + * The first bit indicates if an asset is used as collateral by the user, the second whether an + * asset is borrowed by the user. + */ + uint256 data; + } - struct UserConfigurationMap { - /** - * @dev Bitmap of the users collaterals and borrows. It is divided in pairs of bits, one pair per asset. - * The first bit indicates if an asset is used as collateral by the user, the second whether an - * asset is borrowed by the user. - */ - uint256 data; - } + struct EModeCategory { + // each eMode category has a custom ltv and liquidation threshold + uint16 ltv; + uint16 liquidationThreshold; + uint16 liquidationBonus; + // each eMode category may or may not have a custom oracle to override the individual assets price oracles + address priceSource; + string label; + } - struct EModeCategory { - // each eMode category has a custom ltv and liquidation threshold - uint16 ltv; - uint16 liquidationThreshold; - uint16 liquidationBonus; - // each eMode category may or may not have a custom oracle to override the individual assets price oracles - address priceSource; - string label; - } + enum InterestRateMode { + NONE, + STABLE, + VARIABLE + } - enum InterestRateMode {NONE, STABLE, VARIABLE} + struct ReserveCache { + uint256 currScaledVariableDebt; + uint256 nextScaledVariableDebt; + uint256 currPrincipalStableDebt; + uint256 currAvgStableBorrowRate; + uint256 currTotalStableDebt; + uint256 nextAvgStableBorrowRate; + uint256 nextTotalStableDebt; + uint256 currLiquidityIndex; + uint256 nextLiquidityIndex; + uint256 currVariableBorrowIndex; + uint256 nextVariableBorrowIndex; + uint256 currLiquidityRate; + uint256 currVariableBorrowRate; + uint256 reserveFactor; + ReserveConfigurationMap reserveConfiguration; + address aTokenAddress; + address stableDebtTokenAddress; + address variableDebtTokenAddress; + uint40 reserveLastUpdateTimestamp; + uint40 stableDebtLastUpdateTimestamp; + } - struct ReserveCache { - uint256 currScaledVariableDebt; - uint256 nextScaledVariableDebt; - uint256 currPrincipalStableDebt; - uint256 currAvgStableBorrowRate; - uint256 currTotalStableDebt; - uint256 nextAvgStableBorrowRate; - uint256 nextTotalStableDebt; - uint256 currLiquidityIndex; - uint256 nextLiquidityIndex; - uint256 currVariableBorrowIndex; - uint256 nextVariableBorrowIndex; - uint256 currLiquidityRate; - uint256 currVariableBorrowRate; - uint256 reserveFactor; - ReserveConfigurationMap reserveConfiguration; - address aTokenAddress; - address stableDebtTokenAddress; - address variableDebtTokenAddress; - uint40 reserveLastUpdateTimestamp; - uint40 stableDebtLastUpdateTimestamp; - } + struct ExecuteLiquidationCallParams { + uint256 reservesCount; + uint256 debtToCover; + address collateralAsset; + address debtAsset; + address user; + bool receiveAToken; + address priceOracle; + uint8 userEModeCategory; + address priceOracleSentinel; + } - struct ExecuteLiquidationCallParams { - uint256 reservesCount; - uint256 debtToCover; - address collateralAsset; - address debtAsset; - address user; - bool receiveAToken; - address priceOracle; - uint8 userEModeCategory; - address priceOracleSentinel; - } + struct ExecuteSupplyParams { + address asset; + uint256 amount; + address onBehalfOf; + uint16 referralCode; + } - struct ExecuteSupplyParams { - address asset; - uint256 amount; - address onBehalfOf; - uint16 referralCode; - } + struct ExecuteBorrowParams { + address asset; + address user; + address onBehalfOf; + uint256 amount; + InterestRateMode interestRateMode; + uint16 referralCode; + bool releaseUnderlying; + uint256 maxStableRateBorrowSizePercent; + uint256 reservesCount; + address oracle; + uint8 userEModeCategory; + address priceOracleSentinel; + } - struct ExecuteBorrowParams { - address asset; - address user; - address onBehalfOf; - uint256 amount; - InterestRateMode interestRateMode; - uint16 referralCode; - bool releaseUnderlying; - uint256 maxStableRateBorrowSizePercent; - uint256 reservesCount; - address oracle; - uint8 userEModeCategory; - address priceOracleSentinel; - } + struct ExecuteRepayParams { + address asset; + uint256 amount; + InterestRateMode interestRateMode; + address onBehalfOf; + bool useATokens; + } - struct ExecuteRepayParams { - address asset; - uint256 amount; - InterestRateMode interestRateMode; - address onBehalfOf; - bool useATokens; - } + struct ExecuteWithdrawParams { + address asset; + uint256 amount; + address to; + uint256 reservesCount; + address oracle; + uint8 userEModeCategory; + } - struct ExecuteWithdrawParams { - address asset; - uint256 amount; - address to; - uint256 reservesCount; - address oracle; - uint8 userEModeCategory; - } + struct ExecuteSetUserEModeParams { + uint256 reservesCount; + address oracle; + uint8 categoryId; + } - struct ExecuteSetUserEModeParams { - uint256 reservesCount; - address oracle; - uint8 categoryId; - } + struct FinalizeTransferParams { + address asset; + address from; + address to; + uint256 amount; + uint256 balanceFromBefore; + uint256 balanceToBefore; + uint256 reservesCount; + address oracle; + uint8 fromEModeCategory; + } - struct FinalizeTransferParams { - address asset; - address from; - address to; - uint256 amount; - uint256 balanceFromBefore; - uint256 balanceToBefore; - uint256 reservesCount; - address oracle; - uint8 fromEModeCategory; - } + struct FlashloanParams { + address receiverAddress; + address[] assets; + uint256[] amounts; + uint256[] interestRateModes; + address onBehalfOf; + bytes params; + uint16 referralCode; + uint256 flashLoanPremiumToProtocol; + uint256 flashLoanPremiumTotal; + uint256 maxStableRateBorrowSizePercent; + uint256 reservesCount; + address addressesProvider; + uint8 userEModeCategory; + bool isAuthorizedFlashBorrower; + } - struct FlashloanParams { - address receiverAddress; - address[] assets; - uint256[] amounts; - uint256[] interestRateModes; - address onBehalfOf; - bytes params; - uint16 referralCode; - uint256 flashLoanPremiumToProtocol; - uint256 flashLoanPremiumTotal; - uint256 maxStableRateBorrowSizePercent; - uint256 reservesCount; - address addressesProvider; - uint8 userEModeCategory; - bool isAuthorizedFlashBorrower; - } + struct FlashloanSimpleParams { + address receiverAddress; + address asset; + uint256 amount; + bytes params; + uint16 referralCode; + uint256 flashLoanPremiumToProtocol; + uint256 flashLoanPremiumTotal; + } - struct FlashloanSimpleParams { - address receiverAddress; - address asset; - uint256 amount; - bytes params; - uint16 referralCode; - uint256 flashLoanPremiumToProtocol; - uint256 flashLoanPremiumTotal; - } + struct FlashLoanRepaymentParams { + uint256 amount; + uint256 totalPremium; + uint256 flashLoanPremiumToProtocol; + address asset; + address receiverAddress; + uint16 referralCode; + } - struct FlashLoanRepaymentParams { - uint256 amount; - uint256 totalPremium; - uint256 flashLoanPremiumToProtocol; - address asset; - address receiverAddress; - uint16 referralCode; - } + struct CalculateUserAccountDataParams { + UserConfigurationMap userConfig; + uint256 reservesCount; + address user; + address oracle; + uint8 userEModeCategory; + } - struct CalculateUserAccountDataParams { - UserConfigurationMap userConfig; - uint256 reservesCount; - address user; - address oracle; - uint8 userEModeCategory; - } + struct ValidateBorrowParams { + ReserveCache reserveCache; + UserConfigurationMap userConfig; + address asset; + address userAddress; + uint256 amount; + InterestRateMode interestRateMode; + uint256 maxStableLoanPercent; + uint256 reservesCount; + address oracle; + uint8 userEModeCategory; + address priceOracleSentinel; + bool isolationModeActive; + address isolationModeCollateralAddress; + uint256 isolationModeDebtCeiling; + } - struct ValidateBorrowParams { - ReserveCache reserveCache; - UserConfigurationMap userConfig; - address asset; - address userAddress; - uint256 amount; - InterestRateMode interestRateMode; - uint256 maxStableLoanPercent; - uint256 reservesCount; - address oracle; - uint8 userEModeCategory; - address priceOracleSentinel; - bool isolationModeActive; - address isolationModeCollateralAddress; - uint256 isolationModeDebtCeiling; - } + struct ValidateLiquidationCallParams { + ReserveCache debtReserveCache; + uint256 totalDebt; + uint256 healthFactor; + address priceOracleSentinel; + } - struct ValidateLiquidationCallParams { - ReserveCache debtReserveCache; - uint256 totalDebt; - uint256 healthFactor; - address priceOracleSentinel; - } + struct CalculateInterestRatesParams { + uint256 unbacked; + uint256 liquidityAdded; + uint256 liquidityTaken; + uint256 totalStableDebt; + uint256 totalVariableDebt; + uint256 averageStableBorrowRate; + uint256 reserveFactor; + address reserve; + address aToken; + } - struct CalculateInterestRatesParams { - uint256 unbacked; - uint256 liquidityAdded; - uint256 liquidityTaken; - uint256 totalStableDebt; - uint256 totalVariableDebt; - uint256 averageStableBorrowRate; - uint256 reserveFactor; - address reserve; - address aToken; - } - - struct InitReserveParams { - address asset; - address aTokenAddress; - address stableDebtAddress; - address variableDebtAddress; - address interestRateStrategyAddress; - uint16 reservesCount; - uint16 maxNumberReserves; - } -} \ No newline at end of file + struct InitReserveParams { + address asset; + address aTokenAddress; + address stableDebtAddress; + address variableDebtAddress; + address interestRateStrategyAddress; + uint16 reservesCount; + uint16 maxNumberReserves; + } +} diff --git a/src/aave/interfaces/Errors.sol b/src/aave/interfaces/Errors.sol index c7f9076..c948b15 100644 --- a/src/aave/interfaces/Errors.sol +++ b/src/aave/interfaces/Errors.sol @@ -7,94 +7,117 @@ pragma solidity ^0.8.0; * @notice Defines the error messages emitted by the different contracts of the Aave protocol */ library Errors { - string public constant CALLER_NOT_POOL_ADMIN = '1'; // 'The caller of the function is not a pool admin' - string public constant CALLER_NOT_EMERGENCY_ADMIN = '2'; // 'The caller of the function is not an emergency admin' - string public constant CALLER_NOT_POOL_OR_EMERGENCY_ADMIN = '3'; // 'The caller of the function is not a pool or emergency admin' - string public constant CALLER_NOT_RISK_OR_POOL_ADMIN = '4'; // 'The caller of the function is not a risk or pool admin' - string public constant CALLER_NOT_ASSET_LISTING_OR_POOL_ADMIN = '5'; // 'The caller of the function is not an asset listing or pool admin' - string public constant CALLER_NOT_BRIDGE = '6'; // 'The caller of the function is not a bridge' - string public constant ADDRESSES_PROVIDER_NOT_REGISTERED = '7'; // 'Pool addresses provider is not registered' - string public constant INVALID_ADDRESSES_PROVIDER_ID = '8'; // 'Invalid id for the pool addresses provider' - string public constant NOT_CONTRACT = '9'; // 'Address is not a contract' - string public constant CALLER_NOT_POOL_CONFIGURATOR = '10'; // 'The caller of the function is not the pool configurator' - string public constant CALLER_NOT_ATOKEN = '11'; // 'The caller of the function is not an AToken' - string public constant INVALID_ADDRESSES_PROVIDER = '12'; // 'The address of the pool addresses provider is invalid' - string public constant INVALID_FLASHLOAN_EXECUTOR_RETURN = '13'; // 'Invalid return value of the flashloan executor function' - string public constant RESERVE_ALREADY_ADDED = '14'; // 'Reserve has already been added to reserve list' - string public constant NO_MORE_RESERVES_ALLOWED = '15'; // 'Maximum amount of reserves in the pool reached' - string public constant EMODE_CATEGORY_RESERVED = '16'; // 'Zero eMode category is reserved for volatile heterogeneous assets' - string public constant INVALID_EMODE_CATEGORY_ASSIGNMENT = '17'; // 'Invalid eMode category assignment to asset' - string public constant RESERVE_LIQUIDITY_NOT_ZERO = '18'; // 'The liquidity of the reserve needs to be 0' - string public constant FLASHLOAN_PREMIUM_INVALID = '19'; // 'Invalid flashloan premium' - string public constant INVALID_RESERVE_PARAMS = '20'; // 'Invalid risk parameters for the reserve' - string public constant INVALID_EMODE_CATEGORY_PARAMS = '21'; // 'Invalid risk parameters for the eMode category' - string public constant BRIDGE_PROTOCOL_FEE_INVALID = '22'; // 'Invalid bridge protocol fee' - string public constant CALLER_MUST_BE_POOL = '23'; // 'The caller of this function must be a pool' - string public constant INVALID_MINT_AMOUNT = '24'; // 'Invalid amount to mint' - string public constant INVALID_BURN_AMOUNT = '25'; // 'Invalid amount to burn' - string public constant INVALID_AMOUNT = '26'; // 'Amount must be greater than 0' - string public constant RESERVE_INACTIVE = '27'; // 'Action requires an active reserve' - string public constant RESERVE_FROZEN = '28'; // 'Action cannot be performed because the reserve is frozen' - string public constant RESERVE_PAUSED = '29'; // 'Action cannot be performed because the reserve is paused' - string public constant BORROWING_NOT_ENABLED = '30'; // 'Borrowing is not enabled' - string public constant STABLE_BORROWING_NOT_ENABLED = '31'; // 'Stable borrowing is not enabled' - string public constant NOT_ENOUGH_AVAILABLE_USER_BALANCE = '32'; // 'User cannot withdraw more than the available balance' - string public constant INVALID_INTEREST_RATE_MODE_SELECTED = '33'; // 'Invalid interest rate mode selected' - string public constant COLLATERAL_BALANCE_IS_ZERO = '34'; // 'The collateral balance is 0' - string public constant HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD = '35'; // 'Health factor is lesser than the liquidation threshold' - string public constant COLLATERAL_CANNOT_COVER_NEW_BORROW = '36'; // 'There is not enough collateral to cover a new borrow' - string public constant COLLATERAL_SAME_AS_BORROWING_CURRENCY = '37'; // 'Collateral is (mostly) the same currency that is being borrowed' - string public constant AMOUNT_BIGGER_THAN_MAX_LOAN_SIZE_STABLE = '38'; // 'The requested amount is greater than the max loan size in stable rate mode' - string public constant NO_DEBT_OF_SELECTED_TYPE = '39'; // 'For repayment of a specific type of debt, the user needs to have debt that type' - string public constant NO_EXPLICIT_AMOUNT_TO_REPAY_ON_BEHALF = '40'; // 'To repay on behalf of a user an explicit amount to repay is needed' - string public constant NO_OUTSTANDING_STABLE_DEBT = '41'; // 'User does not have outstanding stable rate debt on this reserve' - string public constant NO_OUTSTANDING_VARIABLE_DEBT = '42'; // 'User does not have outstanding variable rate debt on this reserve' - string public constant UNDERLYING_BALANCE_ZERO = '43'; // 'The underlying balance needs to be greater than 0' - string public constant INTEREST_RATE_REBALANCE_CONDITIONS_NOT_MET = '44'; // 'Interest rate rebalance conditions were not met' - string public constant HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '45'; // 'Health factor is not below the threshold' - string public constant COLLATERAL_CANNOT_BE_LIQUIDATED = '46'; // 'The collateral chosen cannot be liquidated' - string public constant SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER = '47'; // 'User did not borrow the specified currency' - string public constant INCONSISTENT_FLASHLOAN_PARAMS = '49'; // 'Inconsistent flashloan parameters' - string public constant BORROW_CAP_EXCEEDED = '50'; // 'Borrow cap is exceeded' - string public constant SUPPLY_CAP_EXCEEDED = '51'; // 'Supply cap is exceeded' - string public constant UNBACKED_MINT_CAP_EXCEEDED = '52'; // 'Unbacked mint cap is exceeded' - string public constant DEBT_CEILING_EXCEEDED = '53'; // 'Debt ceiling is exceeded' - string public constant UNDERLYING_CLAIMABLE_RIGHTS_NOT_ZERO = '54'; // 'Claimable rights over underlying not zero (aToken supply or accruedToTreasury)' - string public constant STABLE_DEBT_NOT_ZERO = '55'; // 'Stable debt supply is not zero' - string public constant VARIABLE_DEBT_SUPPLY_NOT_ZERO = '56'; // 'Variable debt supply is not zero' - string public constant LTV_VALIDATION_FAILED = '57'; // 'Ltv validation failed' - string public constant INCONSISTENT_EMODE_CATEGORY = '58'; // 'Inconsistent eMode category' - string public constant PRICE_ORACLE_SENTINEL_CHECK_FAILED = '59'; // 'Price oracle sentinel validation failed' - string public constant ASSET_NOT_BORROWABLE_IN_ISOLATION = '60'; // 'Asset is not borrowable in isolation mode' - string public constant RESERVE_ALREADY_INITIALIZED = '61'; // 'Reserve has already been initialized' - string public constant USER_IN_ISOLATION_MODE_OR_LTV_ZERO = '62'; // 'User is in isolation mode or ltv is zero' - string public constant INVALID_LTV = '63'; // 'Invalid ltv parameter for the reserve' - string public constant INVALID_LIQ_THRESHOLD = '64'; // 'Invalid liquidity threshold parameter for the reserve' - string public constant INVALID_LIQ_BONUS = '65'; // 'Invalid liquidity bonus parameter for the reserve' - string public constant INVALID_DECIMALS = '66'; // 'Invalid decimals parameter of the underlying asset of the reserve' - string public constant INVALID_RESERVE_FACTOR = '67'; // 'Invalid reserve factor parameter for the reserve' - string public constant INVALID_BORROW_CAP = '68'; // 'Invalid borrow cap for the reserve' - string public constant INVALID_SUPPLY_CAP = '69'; // 'Invalid supply cap for the reserve' - string public constant INVALID_LIQUIDATION_PROTOCOL_FEE = '70'; // 'Invalid liquidation protocol fee for the reserve' - string public constant INVALID_EMODE_CATEGORY = '71'; // 'Invalid eMode category for the reserve' - string public constant INVALID_UNBACKED_MINT_CAP = '72'; // 'Invalid unbacked mint cap for the reserve' - string public constant INVALID_DEBT_CEILING = '73'; // 'Invalid debt ceiling for the reserve - string public constant INVALID_RESERVE_INDEX = '74'; // 'Invalid reserve index' - string public constant ACL_ADMIN_CANNOT_BE_ZERO = '75'; // 'ACL admin cannot be set to the zero address' - string public constant INCONSISTENT_PARAMS_LENGTH = '76'; // 'Array parameters that should be equal length are not' - string public constant ZERO_ADDRESS_NOT_VALID = '77'; // 'Zero address not valid' - string public constant INVALID_EXPIRATION = '78'; // 'Invalid expiration' - string public constant INVALID_SIGNATURE = '79'; // 'Invalid signature' - string public constant OPERATION_NOT_SUPPORTED = '80'; // 'Operation not supported' - string public constant DEBT_CEILING_NOT_ZERO = '81'; // 'Debt ceiling is not zero' - string public constant ASSET_NOT_LISTED = '82'; // 'Asset is not listed' - string public constant INVALID_OPTIMAL_USAGE_RATIO = '83'; // 'Invalid optimal usage ratio' - string public constant INVALID_OPTIMAL_STABLE_TO_TOTAL_DEBT_RATIO = '84'; // 'Invalid optimal stable to total debt ratio' - string public constant UNDERLYING_CANNOT_BE_RESCUED = '85'; // 'The underlying asset cannot be rescued' - string public constant ADDRESSES_PROVIDER_ALREADY_ADDED = '86'; // 'Reserve has already been added to reserve list' - string public constant POOL_ADDRESSES_DO_NOT_MATCH = '87'; // 'The token implementation pool address and the pool address provided by the initializing pool do not match' - string public constant STABLE_BORROWING_ENABLED = '88'; // 'Stable borrowing is enabled' - string public constant SILOED_BORROWING_VIOLATION = '89'; // 'User is trying to borrow multiple assets including a siloed one' - string public constant RESERVE_DEBT_NOT_ZERO = '90'; // the total debt of the reserve needs to be 0 - string public constant FLASHLOAN_DISABLED = '91'; // FlashLoaning for this asset is disabled -} \ No newline at end of file + string public constant CALLER_NOT_POOL_ADMIN = "1"; // 'The caller of the function is not a pool admin' + string public constant CALLER_NOT_EMERGENCY_ADMIN = "2"; // 'The caller of the function is not an emergency admin' + string public constant CALLER_NOT_POOL_OR_EMERGENCY_ADMIN = "3"; // 'The caller of the function is not a pool or + // emergency admin' + string public constant CALLER_NOT_RISK_OR_POOL_ADMIN = "4"; // 'The caller of the function is not a risk or pool + // admin' + string public constant CALLER_NOT_ASSET_LISTING_OR_POOL_ADMIN = "5"; // 'The caller of the function is not an asset + // listing or pool admin' + string public constant CALLER_NOT_BRIDGE = "6"; // 'The caller of the function is not a bridge' + string public constant ADDRESSES_PROVIDER_NOT_REGISTERED = "7"; // 'Pool addresses provider is not registered' + string public constant INVALID_ADDRESSES_PROVIDER_ID = "8"; // 'Invalid id for the pool addresses provider' + string public constant NOT_CONTRACT = "9"; // 'Address is not a contract' + string public constant CALLER_NOT_POOL_CONFIGURATOR = "10"; // 'The caller of the function is not the pool + // configurator' + string public constant CALLER_NOT_ATOKEN = "11"; // 'The caller of the function is not an AToken' + string public constant INVALID_ADDRESSES_PROVIDER = "12"; // 'The address of the pool addresses provider is invalid' + string public constant INVALID_FLASHLOAN_EXECUTOR_RETURN = "13"; // 'Invalid return value of the flashloan executor + // function' + string public constant RESERVE_ALREADY_ADDED = "14"; // 'Reserve has already been added to reserve list' + string public constant NO_MORE_RESERVES_ALLOWED = "15"; // 'Maximum amount of reserves in the pool reached' + string public constant EMODE_CATEGORY_RESERVED = "16"; // 'Zero eMode category is reserved for volatile + // heterogeneous assets' + string public constant INVALID_EMODE_CATEGORY_ASSIGNMENT = "17"; // 'Invalid eMode category assignment to asset' + string public constant RESERVE_LIQUIDITY_NOT_ZERO = "18"; // 'The liquidity of the reserve needs to be 0' + string public constant FLASHLOAN_PREMIUM_INVALID = "19"; // 'Invalid flashloan premium' + string public constant INVALID_RESERVE_PARAMS = "20"; // 'Invalid risk parameters for the reserve' + string public constant INVALID_EMODE_CATEGORY_PARAMS = "21"; // 'Invalid risk parameters for the eMode category' + string public constant BRIDGE_PROTOCOL_FEE_INVALID = "22"; // 'Invalid bridge protocol fee' + string public constant CALLER_MUST_BE_POOL = "23"; // 'The caller of this function must be a pool' + string public constant INVALID_MINT_AMOUNT = "24"; // 'Invalid amount to mint' + string public constant INVALID_BURN_AMOUNT = "25"; // 'Invalid amount to burn' + string public constant INVALID_AMOUNT = "26"; // 'Amount must be greater than 0' + string public constant RESERVE_INACTIVE = "27"; // 'Action requires an active reserve' + string public constant RESERVE_FROZEN = "28"; // 'Action cannot be performed because the reserve is frozen' + string public constant RESERVE_PAUSED = "29"; // 'Action cannot be performed because the reserve is paused' + string public constant BORROWING_NOT_ENABLED = "30"; // 'Borrowing is not enabled' + string public constant STABLE_BORROWING_NOT_ENABLED = "31"; // 'Stable borrowing is not enabled' + string public constant NOT_ENOUGH_AVAILABLE_USER_BALANCE = "32"; // 'User cannot withdraw more than the available + // balance' + string public constant INVALID_INTEREST_RATE_MODE_SELECTED = "33"; // 'Invalid interest rate mode selected' + string public constant COLLATERAL_BALANCE_IS_ZERO = "34"; // 'The collateral balance is 0' + string public constant HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD = "35"; // 'Health factor is lesser than the + // liquidation threshold' + string public constant COLLATERAL_CANNOT_COVER_NEW_BORROW = "36"; // 'There is not enough collateral to cover a new + // borrow' + string public constant COLLATERAL_SAME_AS_BORROWING_CURRENCY = "37"; // 'Collateral is (mostly) the same currency + // that is being borrowed' + string public constant AMOUNT_BIGGER_THAN_MAX_LOAN_SIZE_STABLE = "38"; // 'The requested amount is greater than the + // max loan size in stable rate mode' + string public constant NO_DEBT_OF_SELECTED_TYPE = "39"; // 'For repayment of a specific type of debt, the user needs + // to have debt that type' + string public constant NO_EXPLICIT_AMOUNT_TO_REPAY_ON_BEHALF = "40"; // 'To repay on behalf of a user an explicit + // amount to repay is needed' + string public constant NO_OUTSTANDING_STABLE_DEBT = "41"; // 'User does not have outstanding stable rate debt on + // this reserve' + string public constant NO_OUTSTANDING_VARIABLE_DEBT = "42"; // 'User does not have outstanding variable rate debt on + // this reserve' + string public constant UNDERLYING_BALANCE_ZERO = "43"; // 'The underlying balance needs to be greater than 0' + string public constant INTEREST_RATE_REBALANCE_CONDITIONS_NOT_MET = "44"; // 'Interest rate rebalance conditions + // were not met' + string public constant HEALTH_FACTOR_NOT_BELOW_THRESHOLD = "45"; // 'Health factor is not below the threshold' + string public constant COLLATERAL_CANNOT_BE_LIQUIDATED = "46"; // 'The collateral chosen cannot be liquidated' + string public constant SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER = "47"; // 'User did not borrow the specified + // currency' + string public constant INCONSISTENT_FLASHLOAN_PARAMS = "49"; // 'Inconsistent flashloan parameters' + string public constant BORROW_CAP_EXCEEDED = "50"; // 'Borrow cap is exceeded' + string public constant SUPPLY_CAP_EXCEEDED = "51"; // 'Supply cap is exceeded' + string public constant UNBACKED_MINT_CAP_EXCEEDED = "52"; // 'Unbacked mint cap is exceeded' + string public constant DEBT_CEILING_EXCEEDED = "53"; // 'Debt ceiling is exceeded' + string public constant UNDERLYING_CLAIMABLE_RIGHTS_NOT_ZERO = "54"; // 'Claimable rights over underlying not zero + // (aToken supply or accruedToTreasury)' + string public constant STABLE_DEBT_NOT_ZERO = "55"; // 'Stable debt supply is not zero' + string public constant VARIABLE_DEBT_SUPPLY_NOT_ZERO = "56"; // 'Variable debt supply is not zero' + string public constant LTV_VALIDATION_FAILED = "57"; // 'Ltv validation failed' + string public constant INCONSISTENT_EMODE_CATEGORY = "58"; // 'Inconsistent eMode category' + string public constant PRICE_ORACLE_SENTINEL_CHECK_FAILED = "59"; // 'Price oracle sentinel validation failed' + string public constant ASSET_NOT_BORROWABLE_IN_ISOLATION = "60"; // 'Asset is not borrowable in isolation mode' + string public constant RESERVE_ALREADY_INITIALIZED = "61"; // 'Reserve has already been initialized' + string public constant USER_IN_ISOLATION_MODE_OR_LTV_ZERO = "62"; // 'User is in isolation mode or ltv is zero' + string public constant INVALID_LTV = "63"; // 'Invalid ltv parameter for the reserve' + string public constant INVALID_LIQ_THRESHOLD = "64"; // 'Invalid liquidity threshold parameter for the reserve' + string public constant INVALID_LIQ_BONUS = "65"; // 'Invalid liquidity bonus parameter for the reserve' + string public constant INVALID_DECIMALS = "66"; // 'Invalid decimals parameter of the underlying asset of the + // reserve' + string public constant INVALID_RESERVE_FACTOR = "67"; // 'Invalid reserve factor parameter for the reserve' + string public constant INVALID_BORROW_CAP = "68"; // 'Invalid borrow cap for the reserve' + string public constant INVALID_SUPPLY_CAP = "69"; // 'Invalid supply cap for the reserve' + string public constant INVALID_LIQUIDATION_PROTOCOL_FEE = "70"; // 'Invalid liquidation protocol fee for the + // reserve' + string public constant INVALID_EMODE_CATEGORY = "71"; // 'Invalid eMode category for the reserve' + string public constant INVALID_UNBACKED_MINT_CAP = "72"; // 'Invalid unbacked mint cap for the reserve' + string public constant INVALID_DEBT_CEILING = "73"; // 'Invalid debt ceiling for the reserve + string public constant INVALID_RESERVE_INDEX = "74"; // 'Invalid reserve index' + string public constant ACL_ADMIN_CANNOT_BE_ZERO = "75"; // 'ACL admin cannot be set to the zero address' + string public constant INCONSISTENT_PARAMS_LENGTH = "76"; // 'Array parameters that should be equal length are not' + string public constant ZERO_ADDRESS_NOT_VALID = "77"; // 'Zero address not valid' + string public constant INVALID_EXPIRATION = "78"; // 'Invalid expiration' + string public constant INVALID_SIGNATURE = "79"; // 'Invalid signature' + string public constant OPERATION_NOT_SUPPORTED = "80"; // 'Operation not supported' + string public constant DEBT_CEILING_NOT_ZERO = "81"; // 'Debt ceiling is not zero' + string public constant ASSET_NOT_LISTED = "82"; // 'Asset is not listed' + string public constant INVALID_OPTIMAL_USAGE_RATIO = "83"; // 'Invalid optimal usage ratio' + string public constant INVALID_OPTIMAL_STABLE_TO_TOTAL_DEBT_RATIO = "84"; // 'Invalid optimal stable to total debt + // ratio' + string public constant UNDERLYING_CANNOT_BE_RESCUED = "85"; // 'The underlying asset cannot be rescued' + string public constant ADDRESSES_PROVIDER_ALREADY_ADDED = "86"; // 'Reserve has already been added to reserve list' + string public constant POOL_ADDRESSES_DO_NOT_MATCH = "87"; // 'The token implementation pool address and the pool + // address provided by the initializing pool do not match' + string public constant STABLE_BORROWING_ENABLED = "88"; // 'Stable borrowing is enabled' + string public constant SILOED_BORROWING_VIOLATION = "89"; // 'User is trying to borrow multiple assets including a + // siloed one' + string public constant RESERVE_DEBT_NOT_ZERO = "90"; // the total debt of the reserve needs to be 0 + string public constant FLASHLOAN_DISABLED = "91"; // FlashLoaning for this asset is disabled +} diff --git a/src/aave/interfaces/IFlashLoanSimpleReceiver.sol b/src/aave/interfaces/IFlashLoanSimpleReceiver.sol index 9a259be..2150092 100644 --- a/src/aave/interfaces/IFlashLoanSimpleReceiver.sol +++ b/src/aave/interfaces/IFlashLoanSimpleReceiver.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.0; -import {IPoolAddressesProvider} from "./IPoolAddressesProvider.sol"; -import {IPool} from "./IPool.sol"; +import { IPoolAddressesProvider } from "./IPoolAddressesProvider.sol"; +import { IPool } from "./IPool.sol"; /** * @title IFlashLoanSimpleReceiver @@ -11,26 +11,28 @@ import {IPool} from "./IPool.sol"; * @dev Implement this interface to develop a flashloan-compatible flashLoanReceiver contract */ interface IFlashLoanSimpleReceiver { - /** - * @notice Executes an operation after receiving the flash-borrowed asset - * @dev Ensure that the contract can return the debt + premium, e.g., has - * enough funds to repay and has approved the Pool to pull the total amount - * @param asset The address of the flash-borrowed asset - * @param amount The amount of the flash-borrowed asset - * @param premium The fee of the flash-borrowed asset - * @param initiator The address of the flashloan initiator - * @param params The byte-encoded params passed when initiating the flashloan - * @return True if the execution of the operation succeeds, false otherwise - */ - function executeOperation( - address asset, - uint256 amount, - uint256 premium, - address initiator, - bytes calldata params - ) external returns (bool); + /** + * @notice Executes an operation after receiving the flash-borrowed asset + * @dev Ensure that the contract can return the debt + premium, e.g., has + * enough funds to repay and has approved the Pool to pull the total amount + * @param asset The address of the flash-borrowed asset + * @param amount The amount of the flash-borrowed asset + * @param premium The fee of the flash-borrowed asset + * @param initiator The address of the flashloan initiator + * @param params The byte-encoded params passed when initiating the flashloan + * @return True if the execution of the operation succeeds, false otherwise + */ + function executeOperation( + address asset, + uint256 amount, + uint256 premium, + address initiator, + bytes calldata params + ) + external + returns (bool); - function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider); + function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider); - function POOL() external view returns (IPool); -} \ No newline at end of file + function POOL() external view returns (IPool); +} diff --git a/src/aave/interfaces/IPool.sol b/src/aave/interfaces/IPool.sol index 596dcbb..242d464 100644 --- a/src/aave/interfaces/IPool.sol +++ b/src/aave/interfaces/IPool.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.0; -import {IPoolAddressesProvider} from "./IPoolAddressesProvider.sol"; -import {DataTypes} from "./DataTypes.sol"; +import { IPoolAddressesProvider } from "./IPoolAddressesProvider.sol"; +import { DataTypes } from "./DataTypes.sol"; /** * @title IPool @@ -10,728 +10,710 @@ import {DataTypes} from "./DataTypes.sol"; * @notice Defines the basic interface for an Aave Pool. */ interface IPool { - /** - * @dev Emitted on mintUnbacked() - * @param reserve The address of the underlying asset of the reserve - * @param user The address initiating the supply - * @param onBehalfOf The beneficiary of the supplied assets, receiving the aTokens - * @param amount The amount of supplied assets - * @param referralCode The referral code used - */ - event MintUnbacked( - address indexed reserve, - address user, - address indexed onBehalfOf, - uint256 amount, - uint16 indexed referralCode - ); - - /** - * @dev Emitted on backUnbacked() - * @param reserve The address of the underlying asset of the reserve - * @param backer The address paying for the backing - * @param amount The amount added as backing - * @param fee The amount paid in fees - */ - event BackUnbacked(address indexed reserve, address indexed backer, uint256 amount, uint256 fee); - - /** - * @dev Emitted on supply() - * @param reserve The address of the underlying asset of the reserve - * @param user The address initiating the supply - * @param onBehalfOf The beneficiary of the supply, receiving the aTokens - * @param amount The amount supplied - * @param referralCode The referral code used - */ - event Supply( - address indexed reserve, - address user, - address indexed onBehalfOf, - uint256 amount, - uint16 indexed referralCode - ); - - /** - * @dev Emitted on withdraw() - * @param reserve The address of the underlying asset being withdrawn - * @param user The address initiating the withdrawal, owner of aTokens - * @param to The address that will receive the underlying - * @param amount The amount to be withdrawn - */ - event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount); - - /** - * @dev Emitted on borrow() and flashLoan() when debt needs to be opened - * @param reserve The address of the underlying asset being borrowed - * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just - * initiator of the transaction on flashLoan() - * @param onBehalfOf The address that will be getting the debt - * @param amount The amount borrowed out - * @param interestRateMode The rate mode: 1 for Stable, 2 for Variable - * @param borrowRate The numeric rate at which the user has borrowed, expressed in ray - * @param referralCode The referral code used - */ - event Borrow( - address indexed reserve, - address user, - address indexed onBehalfOf, - uint256 amount, - DataTypes.InterestRateMode interestRateMode, - uint256 borrowRate, - uint16 indexed referralCode - ); - - /** - * @dev Emitted on repay() - * @param reserve The address of the underlying asset of the reserve - * @param user The beneficiary of the repayment, getting his debt reduced - * @param repayer The address of the user initiating the repay(), providing the funds - * @param amount The amount repaid - * @param useATokens True if the repayment is done using aTokens, `false` if done with underlying asset directly - */ - event Repay( - address indexed reserve, - address indexed user, - address indexed repayer, - uint256 amount, - bool useATokens - ); - - /** - * @dev Emitted on swapBorrowRateMode() - * @param reserve The address of the underlying asset of the reserve - * @param user The address of the user swapping his rate mode - * @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable - */ - event SwapBorrowRateMode( - address indexed reserve, - address indexed user, - DataTypes.InterestRateMode interestRateMode - ); - - /** - * @dev Emitted on borrow(), repay() and liquidationCall() when using isolated assets - * @param asset The address of the underlying asset of the reserve - * @param totalDebt The total isolation mode debt for the reserve - */ - event IsolationModeTotalDebtUpdated(address indexed asset, uint256 totalDebt); - - /** - * @dev Emitted when the user selects a certain asset category for eMode - * @param user The address of the user - * @param categoryId The category id - */ - event UserEModeSet(address indexed user, uint8 categoryId); - - /** - * @dev Emitted on setUserUseReserveAsCollateral() - * @param reserve The address of the underlying asset of the reserve - * @param user The address of the user enabling the usage as collateral - */ - event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user); - - /** - * @dev Emitted on setUserUseReserveAsCollateral() - * @param reserve The address of the underlying asset of the reserve - * @param user The address of the user enabling the usage as collateral - */ - event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user); - - /** - * @dev Emitted on rebalanceStableBorrowRate() - * @param reserve The address of the underlying asset of the reserve - * @param user The address of the user for which the rebalance has been executed - */ - event RebalanceStableBorrowRate(address indexed reserve, address indexed user); - - /** - * @dev Emitted on flashLoan() - * @param target The address of the flash loan receiver contract - * @param initiator The address initiating the flash loan - * @param asset The address of the asset being flash borrowed - * @param amount The amount flash borrowed - * @param interestRateMode The flashloan mode: 0 for regular flashloan, 1 for Stable debt, 2 for Variable debt - * @param premium The fee flash borrowed - * @param referralCode The referral code used - */ - event FlashLoan( - address indexed target, - address initiator, - address indexed asset, - uint256 amount, - DataTypes.InterestRateMode interestRateMode, - uint256 premium, - uint16 indexed referralCode - ); - - /** - * @dev Emitted when a borrower is liquidated. - * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation - * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation - * @param user The address of the borrower getting liquidated - * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover - * @param liquidatedCollateralAmount The amount of collateral received by the liquidator - * @param liquidator The address of the liquidator - * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants - * to receive the underlying collateral asset directly - */ - event LiquidationCall( - address indexed collateralAsset, - address indexed debtAsset, - address indexed user, - uint256 debtToCover, - uint256 liquidatedCollateralAmount, - address liquidator, - bool receiveAToken - ); - - /** - * @dev Emitted when the state of a reserve is updated. - * @param reserve The address of the underlying asset of the reserve - * @param liquidityRate The next liquidity rate - * @param stableBorrowRate The next stable borrow rate - * @param variableBorrowRate The next variable borrow rate - * @param liquidityIndex The next liquidity index - * @param variableBorrowIndex The next variable borrow index - */ - event ReserveDataUpdated( - address indexed reserve, - uint256 liquidityRate, - uint256 stableBorrowRate, - uint256 variableBorrowRate, - uint256 liquidityIndex, - uint256 variableBorrowIndex - ); - - /** - * @dev Emitted when the protocol treasury receives minted aTokens from the accrued interest. - * @param reserve The address of the reserve - * @param amountMinted The amount minted to the treasury - */ - event MintedToTreasury(address indexed reserve, uint256 amountMinted); - - /** - * @notice Mints an `amount` of aTokens to the `onBehalfOf` - * @param asset The address of the underlying asset to mint - * @param amount The amount to mint - * @param onBehalfOf The address that will receive the aTokens - * @param referralCode Code used to register the integrator originating the operation, for potential rewards. - * 0 if the action is executed directly by the user, without any middle-man - */ - function mintUnbacked( - address asset, - uint256 amount, - address onBehalfOf, - uint16 referralCode - ) external; - - /** - * @notice Back the current unbacked underlying with `amount` and pay `fee`. - * @param asset The address of the underlying asset to back - * @param amount The amount to back - * @param fee The amount paid in fees - * @return The backed amount - */ - function backUnbacked(address asset, uint256 amount, uint256 fee) external returns (uint256); - - /** - * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. - * - E.g. User supplies 100 USDC and gets in return 100 aUSDC - * @param asset The address of the underlying asset to supply - * @param amount The amount to be supplied - * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user - * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens - * is a different wallet - * @param referralCode Code used to register the integrator originating the operation, for potential rewards. - * 0 if the action is executed directly by the user, without any middle-man - */ - function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external; - - /** - * @notice Supply with transfer approval of asset to be supplied done via permit function - * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713 - * @param asset The address of the underlying asset to supply - * @param amount The amount to be supplied - * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user - * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens - * is a different wallet - * @param deadline The deadline timestamp that the permit is valid - * @param referralCode Code used to register the integrator originating the operation, for potential rewards. - * 0 if the action is executed directly by the user, without any middle-man - * @param permitV The V parameter of ERC712 permit sig - * @param permitR The R parameter of ERC712 permit sig - * @param permitS The S parameter of ERC712 permit sig - */ - function supplyWithPermit( - address asset, - uint256 amount, - address onBehalfOf, - uint16 referralCode, - uint256 deadline, - uint8 permitV, - bytes32 permitR, - bytes32 permitS - ) external; - - /** - * @notice Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned - * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC - * @param asset The address of the underlying asset to withdraw - * @param amount The underlying amount to be withdrawn - * - Send the value type(uint256).max in order to withdraw the whole aToken balance - * @param to The address that will receive the underlying, same as msg.sender if the user - * wants to receive it on his own wallet, or a different address if the beneficiary is a - * different wallet - * @return The final amount withdrawn - */ - function withdraw(address asset, uint256 amount, address to) external returns (uint256); - - /** - * @notice Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower - * already supplied enough collateral, or he was given enough allowance by a credit delegator on the - * corresponding debt token (StableDebtToken or VariableDebtToken) - * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet - * and 100 stable/variable debt tokens, depending on the `interestRateMode` - * @param asset The address of the underlying asset to borrow - * @param amount The amount to be borrowed - * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable - * @param referralCode The code used to register the integrator originating the operation, for potential rewards. - * 0 if the action is executed directly by the user, without any middle-man - * @param onBehalfOf The address of the user who will receive the debt. Should be the address of the borrower itself - * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator - * if he has been given credit delegation allowance - */ - function borrow( - address asset, - uint256 amount, - uint256 interestRateMode, - uint16 referralCode, - address onBehalfOf - ) external; - - /** - * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned - * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address - * @param asset The address of the borrowed underlying asset previously borrowed - * @param amount The amount to repay - * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` - * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable - * @param onBehalfOf The address of the user who will get his debt reduced/removed. Should be the address of the - * user calling the function if he wants to reduce/remove his own debt, or the address of any other - * other borrower whose debt should be removed - * @return The final amount repaid - */ - function repay( - address asset, - uint256 amount, - uint256 interestRateMode, - address onBehalfOf - ) external returns (uint256); - - /** - * @notice Repay with transfer approval of asset to be repaid done via permit function - * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713 - * @param asset The address of the borrowed underlying asset previously borrowed - * @param amount The amount to repay - * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` - * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable - * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the - * user calling the function if he wants to reduce/remove his own debt, or the address of any other - * other borrower whose debt should be removed - * @param deadline The deadline timestamp that the permit is valid - * @param permitV The V parameter of ERC712 permit sig - * @param permitR The R parameter of ERC712 permit sig - * @param permitS The S parameter of ERC712 permit sig - * @return The final amount repaid - */ - function repayWithPermit( - address asset, - uint256 amount, - uint256 interestRateMode, - address onBehalfOf, - uint256 deadline, - uint8 permitV, - bytes32 permitR, - bytes32 permitS - ) external returns (uint256); - - /** - * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the - * equivalent debt tokens - * - E.g. User repays 100 USDC using 100 aUSDC, burning 100 variable/stable debt tokens - * @dev Passing uint256.max as amount will clean up any residual aToken dust balance, if the user aToken - * balance is not enough to cover the whole debt - * @param asset The address of the borrowed underlying asset previously borrowed - * @param amount The amount to repay - * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` - * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable - * @return The final amount repaid - */ - function repayWithATokens( - address asset, - uint256 amount, - uint256 interestRateMode - ) external returns (uint256); - - /** - * @notice Allows a borrower to swap his debt between stable and variable mode, or vice versa - * @param asset The address of the underlying asset borrowed - * @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable - */ - function swapBorrowRateMode(address asset, uint256 interestRateMode) external; - - /** - * @notice Rebalances the stable interest rate of a user to the current stable rate defined on the reserve. - * - Users can be rebalanced if the following conditions are satisfied: - * 1. Usage ratio is above 95% - * 2. the current supply APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too - * much has been borrowed at a stable rate and suppliers are not earning enough - * @param asset The address of the underlying asset borrowed - * @param user The address of the user to be rebalanced - */ - function rebalanceStableBorrowRate(address asset, address user) external; - - /** - * @notice Allows suppliers to enable/disable a specific supplied asset as collateral - * @param asset The address of the underlying asset supplied - * @param useAsCollateral True if the user wants to use the supply as collateral, false otherwise - */ - function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external; - - /** - * @notice Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1 - * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives - * a proportionally amount of the `collateralAsset` plus a bonus to cover market risk - * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation - * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation - * @param user The address of the borrower getting liquidated - * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover - * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants - * to receive the underlying collateral asset directly - */ - function liquidationCall( - address collateralAsset, - address debtAsset, - address user, - uint256 debtToCover, - bool receiveAToken - ) external; - - /** - * @notice Allows smartcontracts to access the liquidity of the pool within one transaction, - * as long as the amount taken plus a fee is returned. - * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept - * into consideration. For further details please visit https://docs.aave.com/developers/ - * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanReceiver interface - * @param assets The addresses of the assets being flash-borrowed - * @param amounts The amounts of the assets being flash-borrowed - * @param interestRateModes Types of the debt to open if the flash loan is not returned: - * 0 -> Don"t open any debt, just revert if funds can"t be transferred from the receiver - * 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address - * 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address - * @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2 - * @param params Variadic packed params to pass to the receiver as extra information - * @param referralCode The code used to register the integrator originating the operation, for potential rewards. - * 0 if the action is executed directly by the user, without any middle-man - */ - function flashLoan( - address receiverAddress, - address[] calldata assets, - uint256[] calldata amounts, - uint256[] calldata interestRateModes, - address onBehalfOf, - bytes calldata params, - uint16 referralCode - ) external; - - /** - * @notice Allows smartcontracts to access the liquidity of the pool within one transaction, - * as long as the amount taken plus a fee is returned. - * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept - * into consideration. For further details please visit https://docs.aave.com/developers/ - * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanSimpleReceiver interface - * @param asset The address of the asset being flash-borrowed - * @param amount The amount of the asset being flash-borrowed - * @param params Variadic packed params to pass to the receiver as extra information - * @param referralCode The code used to register the integrator originating the operation, for potential rewards. - * 0 if the action is executed directly by the user, without any middle-man - */ - function flashLoanSimple( - address receiverAddress, - address asset, - uint256 amount, - bytes calldata params, - uint16 referralCode - ) external; - - /** - * @notice Returns the user account data across all the reserves - * @param user The address of the user - * @return totalCollateralBase The total collateral of the user in the base currency used by the price feed - * @return totalDebtBase The total debt of the user in the base currency used by the price feed - * @return availableBorrowsBase The borrowing power left of the user in the base currency used by the price feed - * @return currentLiquidationThreshold The liquidation threshold of the user - * @return ltv The loan to value of The user - * @return healthFactor The current health factor of the user - */ - function getUserAccountData( - address user - ) - external - view - returns ( - uint256 totalCollateralBase, - uint256 totalDebtBase, - uint256 availableBorrowsBase, - uint256 currentLiquidationThreshold, - uint256 ltv, - uint256 healthFactor + /** + * @dev Emitted on mintUnbacked() + * @param reserve The address of the underlying asset of the reserve + * @param user The address initiating the supply + * @param onBehalfOf The beneficiary of the supplied assets, receiving the aTokens + * @param amount The amount of supplied assets + * @param referralCode The referral code used + */ + event MintUnbacked( + address indexed reserve, address user, address indexed onBehalfOf, uint256 amount, uint16 indexed referralCode ); - /** - * @notice Initializes a reserve, activating it, assigning an aToken and debt tokens and an - * interest rate strategy - * @dev Only callable by the PoolConfigurator contract - * @param asset The address of the underlying asset of the reserve - * @param aTokenAddress The address of the aToken that will be assigned to the reserve - * @param stableDebtAddress The address of the StableDebtToken that will be assigned to the reserve - * @param variableDebtAddress The address of the VariableDebtToken that will be assigned to the reserve - * @param interestRateStrategyAddress The address of the interest rate strategy contract - */ - function initReserve( - address asset, - address aTokenAddress, - address stableDebtAddress, - address variableDebtAddress, - address interestRateStrategyAddress - ) external; - - /** - * @notice Drop a reserve - * @dev Only callable by the PoolConfigurator contract - * @param asset The address of the underlying asset of the reserve - */ - function dropReserve(address asset) external; - - /** - * @notice Updates the address of the interest rate strategy contract - * @dev Only callable by the PoolConfigurator contract - * @param asset The address of the underlying asset of the reserve - * @param rateStrategyAddress The address of the interest rate strategy contract - */ - function setReserveInterestRateStrategyAddress( - address asset, - address rateStrategyAddress - ) external; - - /** - * @notice Sets the configuration bitmap of the reserve as a whole - * @dev Only callable by the PoolConfigurator contract - * @param asset The address of the underlying asset of the reserve - * @param configuration The new configuration bitmap - */ - function setConfiguration( - address asset, - DataTypes.ReserveConfigurationMap calldata configuration - ) external; - - /** - * @notice Returns the configuration of the reserve - * @param asset The address of the underlying asset of the reserve - * @return The configuration of the reserve - */ - function getConfiguration( - address asset - ) external view returns (DataTypes.ReserveConfigurationMap memory); - - /** - * @notice Returns the configuration of the user across all the reserves - * @param user The user address - * @return The configuration of the user - */ - function getUserConfiguration( - address user - ) external view returns (DataTypes.UserConfigurationMap memory); - - /** - * @notice Returns the normalized income of the reserve - * @param asset The address of the underlying asset of the reserve - * @return The reserve"s normalized income - */ - function getReserveNormalizedIncome(address asset) external view returns (uint256); - - /** - * @notice Returns the normalized variable debt per unit of asset - * @dev WARNING: This function is intended to be used primarily by the protocol itself to get a - * "dynamic" variable index based on time, current stored index and virtual rate at the current - * moment (approx. a borrower would get if opening a position). This means that is always used in - * combination with variable debt supply/balances. - * If using this function externally, consider that is possible to have an increasing normalized - * variable debt that is not equivalent to how the variable debt index would be updated in storage - * (e.g. only updates with non-zero variable debt supply) - * @param asset The address of the underlying asset of the reserve - * @return The reserve normalized variable debt - */ - function getReserveNormalizedVariableDebt(address asset) external view returns (uint256); - - /** - * @notice Returns the state and configuration of the reserve - * @param asset The address of the underlying asset of the reserve - * @return The state and configuration data of the reserve - */ - function getReserveData(address asset) external view returns (DataTypes.ReserveData memory); - - /** - * @notice Validates and finalizes an aToken transfer - * @dev Only callable by the overlying aToken of the `asset` - * @param asset The address of the underlying asset of the aToken - * @param from The user from which the aTokens are transferred - * @param to The user receiving the aTokens - * @param amount The amount being transferred/withdrawn - * @param balanceFromBefore The aToken balance of the `from` user before the transfer - * @param balanceToBefore The aToken balance of the `to` user before the transfer - */ - function finalizeTransfer( - address asset, - address from, - address to, - uint256 amount, - uint256 balanceFromBefore, - uint256 balanceToBefore - ) external; - - /** - * @notice Returns the list of the underlying assets of all the initialized reserves - * @dev It does not include dropped reserves - * @return The addresses of the underlying assets of the initialized reserves - */ - function getReservesList() external view returns (address[] memory); - - /** - * @notice Returns the address of the underlying asset of a reserve by the reserve id as stored in the DataTypes.ReserveData struct - * @param id The id of the reserve as stored in the DataTypes.ReserveData struct - * @return The address of the reserve associated with id - */ - function getReserveAddressById(uint16 id) external view returns (address); - - /** - * @notice Returns the PoolAddressesProvider connected to this contract - * @return The address of the PoolAddressesProvider - */ - function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider); - - /** - * @notice Updates the protocol fee on the bridging - * @param bridgeProtocolFee The part of the premium sent to the protocol treasury - */ - function updateBridgeProtocolFee(uint256 bridgeProtocolFee) external; - - /** - * @notice Updates flash loan premiums. Flash loan premium consists of two parts: - * - A part is sent to aToken holders as extra, one time accumulated interest - * - A part is collected by the protocol treasury - * @dev The total premium is calculated on the total borrowed amount - * @dev The premium to protocol is calculated on the total premium, being a percentage of `flashLoanPremiumTotal` - * @dev Only callable by the PoolConfigurator contract - * @param flashLoanPremiumTotal The total premium, expressed in bps - * @param flashLoanPremiumToProtocol The part of the premium sent to the protocol treasury, expressed in bps - */ - function updateFlashloanPremiums( - uint128 flashLoanPremiumTotal, - uint128 flashLoanPremiumToProtocol - ) external; - - /** - * @notice Configures a new category for the eMode. - * @dev In eMode, the protocol allows very high borrowing power to borrow assets of the same category. - * The category 0 is reserved as it"s the default for volatile assets - * @param id The id of the category - * @param config The configuration of the category - */ - function configureEModeCategory(uint8 id, DataTypes.EModeCategory memory config) external; - - /** - * @notice Returns the data of an eMode category - * @param id The id of the category - * @return The configuration data of the category - */ - function getEModeCategoryData(uint8 id) external view returns (DataTypes.EModeCategory memory); - - /** - * @notice Allows a user to use the protocol in eMode - * @param categoryId The id of the category - */ - function setUserEMode(uint8 categoryId) external; - - /** - * @notice Returns the eMode the user is using - * @param user The address of the user - * @return The eMode id - */ - function getUserEMode(address user) external view returns (uint256); - - /** - * @notice Resets the isolation mode total debt of the given asset to zero - * @dev It requires the given asset has zero debt ceiling - * @param asset The address of the underlying asset to reset the isolationModeTotalDebt - */ - function resetIsolationModeTotalDebt(address asset) external; - - /** - * @notice Returns the percentage of available liquidity that can be borrowed at once at stable rate - * @return The percentage of available liquidity to borrow, expressed in bps - */ - function MAX_STABLE_RATE_BORROW_SIZE_PERCENT() external view returns (uint256); - - /** - * @notice Returns the total fee on flash loans - * @return The total fee on flashloans - */ - function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128); - - /** - * @notice Returns the part of the bridge fees sent to protocol - * @return The bridge fee sent to the protocol treasury - */ - function BRIDGE_PROTOCOL_FEE() external view returns (uint256); - - /** - * @notice Returns the part of the flashloan fees sent to protocol - * @return The flashloan fee sent to the protocol treasury - */ - function FLASHLOAN_PREMIUM_TO_PROTOCOL() external view returns (uint128); - - /** - * @notice Returns the maximum number of reserves supported to be listed in this Pool - * @return The maximum number of reserves supported - */ - function MAX_NUMBER_RESERVES() external view returns (uint16); - - /** - * @notice Mints the assets accrued through the reserve factor to the treasury in the form of aTokens - * @param assets The list of reserves for which the minting needs to be executed - */ - function mintToTreasury(address[] calldata assets) external; - - /** - * @notice Rescue and transfer tokens locked in this contract - * @param token The address of the token - * @param to The address of the recipient - * @param amount The amount of token to transfer - */ - function rescueTokens(address token, address to, uint256 amount) external; - - /** - * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. - * - E.g. User supplies 100 USDC and gets in return 100 aUSDC - * @dev Deprecated: Use the `supply` function instead - * @param asset The address of the underlying asset to supply - * @param amount The amount to be supplied - * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user - * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens - * is a different wallet - * @param referralCode Code used to register the integrator originating the operation, for potential rewards. - * 0 if the action is executed directly by the user, without any middle-man - */ - function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external; -} \ No newline at end of file + /** + * @dev Emitted on backUnbacked() + * @param reserve The address of the underlying asset of the reserve + * @param backer The address paying for the backing + * @param amount The amount added as backing + * @param fee The amount paid in fees + */ + event BackUnbacked(address indexed reserve, address indexed backer, uint256 amount, uint256 fee); + + /** + * @dev Emitted on supply() + * @param reserve The address of the underlying asset of the reserve + * @param user The address initiating the supply + * @param onBehalfOf The beneficiary of the supply, receiving the aTokens + * @param amount The amount supplied + * @param referralCode The referral code used + */ + event Supply( + address indexed reserve, address user, address indexed onBehalfOf, uint256 amount, uint16 indexed referralCode + ); + + /** + * @dev Emitted on withdraw() + * @param reserve The address of the underlying asset being withdrawn + * @param user The address initiating the withdrawal, owner of aTokens + * @param to The address that will receive the underlying + * @param amount The amount to be withdrawn + */ + event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount); + + /** + * @dev Emitted on borrow() and flashLoan() when debt needs to be opened + * @param reserve The address of the underlying asset being borrowed + * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just + * initiator of the transaction on flashLoan() + * @param onBehalfOf The address that will be getting the debt + * @param amount The amount borrowed out + * @param interestRateMode The rate mode: 1 for Stable, 2 for Variable + * @param borrowRate The numeric rate at which the user has borrowed, expressed in ray + * @param referralCode The referral code used + */ + event Borrow( + address indexed reserve, + address user, + address indexed onBehalfOf, + uint256 amount, + DataTypes.InterestRateMode interestRateMode, + uint256 borrowRate, + uint16 indexed referralCode + ); + + /** + * @dev Emitted on repay() + * @param reserve The address of the underlying asset of the reserve + * @param user The beneficiary of the repayment, getting his debt reduced + * @param repayer The address of the user initiating the repay(), providing the funds + * @param amount The amount repaid + * @param useATokens True if the repayment is done using aTokens, `false` if done with underlying asset directly + */ + event Repay( + address indexed reserve, address indexed user, address indexed repayer, uint256 amount, bool useATokens + ); + + /** + * @dev Emitted on swapBorrowRateMode() + * @param reserve The address of the underlying asset of the reserve + * @param user The address of the user swapping his rate mode + * @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for + * Variable + */ + event SwapBorrowRateMode( + address indexed reserve, address indexed user, DataTypes.InterestRateMode interestRateMode + ); + + /** + * @dev Emitted on borrow(), repay() and liquidationCall() when using isolated assets + * @param asset The address of the underlying asset of the reserve + * @param totalDebt The total isolation mode debt for the reserve + */ + event IsolationModeTotalDebtUpdated(address indexed asset, uint256 totalDebt); + + /** + * @dev Emitted when the user selects a certain asset category for eMode + * @param user The address of the user + * @param categoryId The category id + */ + event UserEModeSet(address indexed user, uint8 categoryId); + + /** + * @dev Emitted on setUserUseReserveAsCollateral() + * @param reserve The address of the underlying asset of the reserve + * @param user The address of the user enabling the usage as collateral + */ + event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user); + + /** + * @dev Emitted on setUserUseReserveAsCollateral() + * @param reserve The address of the underlying asset of the reserve + * @param user The address of the user enabling the usage as collateral + */ + event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user); + + /** + * @dev Emitted on rebalanceStableBorrowRate() + * @param reserve The address of the underlying asset of the reserve + * @param user The address of the user for which the rebalance has been executed + */ + event RebalanceStableBorrowRate(address indexed reserve, address indexed user); + + /** + * @dev Emitted on flashLoan() + * @param target The address of the flash loan receiver contract + * @param initiator The address initiating the flash loan + * @param asset The address of the asset being flash borrowed + * @param amount The amount flash borrowed + * @param interestRateMode The flashloan mode: 0 for regular flashloan, 1 for Stable debt, 2 for Variable debt + * @param premium The fee flash borrowed + * @param referralCode The referral code used + */ + event FlashLoan( + address indexed target, + address initiator, + address indexed asset, + uint256 amount, + DataTypes.InterestRateMode interestRateMode, + uint256 premium, + uint16 indexed referralCode + ); + + /** + * @dev Emitted when a borrower is liquidated. + * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the + * liquidation + * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation + * @param user The address of the borrower getting liquidated + * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover + * @param liquidatedCollateralAmount The amount of collateral received by the liquidator + * @param liquidator The address of the liquidator + * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants + * to receive the underlying collateral asset directly + */ + event LiquidationCall( + address indexed collateralAsset, + address indexed debtAsset, + address indexed user, + uint256 debtToCover, + uint256 liquidatedCollateralAmount, + address liquidator, + bool receiveAToken + ); + + /** + * @dev Emitted when the state of a reserve is updated. + * @param reserve The address of the underlying asset of the reserve + * @param liquidityRate The next liquidity rate + * @param stableBorrowRate The next stable borrow rate + * @param variableBorrowRate The next variable borrow rate + * @param liquidityIndex The next liquidity index + * @param variableBorrowIndex The next variable borrow index + */ + event ReserveDataUpdated( + address indexed reserve, + uint256 liquidityRate, + uint256 stableBorrowRate, + uint256 variableBorrowRate, + uint256 liquidityIndex, + uint256 variableBorrowIndex + ); + + /** + * @dev Emitted when the protocol treasury receives minted aTokens from the accrued interest. + * @param reserve The address of the reserve + * @param amountMinted The amount minted to the treasury + */ + event MintedToTreasury(address indexed reserve, uint256 amountMinted); + + /** + * @notice Mints an `amount` of aTokens to the `onBehalfOf` + * @param asset The address of the underlying asset to mint + * @param amount The amount to mint + * @param onBehalfOf The address that will receive the aTokens + * @param referralCode Code used to register the integrator originating the operation, for potential rewards. + * 0 if the action is executed directly by the user, without any middle-man + */ + function mintUnbacked(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external; + + /** + * @notice Back the current unbacked underlying with `amount` and pay `fee`. + * @param asset The address of the underlying asset to back + * @param amount The amount to back + * @param fee The amount paid in fees + * @return The backed amount + */ + function backUnbacked(address asset, uint256 amount, uint256 fee) external returns (uint256); + + /** + * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. + * - E.g. User supplies 100 USDC and gets in return 100 aUSDC + * @param asset The address of the underlying asset to supply + * @param amount The amount to be supplied + * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user + * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens + * is a different wallet + * @param referralCode Code used to register the integrator originating the operation, for potential rewards. + * 0 if the action is executed directly by the user, without any middle-man + */ + function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external; + + /** + * @notice Supply with transfer approval of asset to be supplied done via permit function + * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713 + * @param asset The address of the underlying asset to supply + * @param amount The amount to be supplied + * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user + * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens + * is a different wallet + * @param deadline The deadline timestamp that the permit is valid + * @param referralCode Code used to register the integrator originating the operation, for potential rewards. + * 0 if the action is executed directly by the user, without any middle-man + * @param permitV The V parameter of ERC712 permit sig + * @param permitR The R parameter of ERC712 permit sig + * @param permitS The S parameter of ERC712 permit sig + */ + function supplyWithPermit( + address asset, + uint256 amount, + address onBehalfOf, + uint16 referralCode, + uint256 deadline, + uint8 permitV, + bytes32 permitR, + bytes32 permitS + ) + external; + + /** + * @notice Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned + * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC + * @param asset The address of the underlying asset to withdraw + * @param amount The underlying amount to be withdrawn + * - Send the value type(uint256).max in order to withdraw the whole aToken balance + * @param to The address that will receive the underlying, same as msg.sender if the user + * wants to receive it on his own wallet, or a different address if the beneficiary is a + * different wallet + * @return The final amount withdrawn + */ + function withdraw(address asset, uint256 amount, address to) external returns (uint256); + + /** + * @notice Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower + * already supplied enough collateral, or he was given enough allowance by a credit delegator on the + * corresponding debt token (StableDebtToken or VariableDebtToken) + * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet + * and 100 stable/variable debt tokens, depending on the `interestRateMode` + * @param asset The address of the underlying asset to borrow + * @param amount The amount to be borrowed + * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable + * @param referralCode The code used to register the integrator originating the operation, for potential rewards. + * 0 if the action is executed directly by the user, without any middle-man + * @param onBehalfOf The address of the user who will receive the debt. Should be the address of the borrower itself + * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator + * if he has been given credit delegation allowance + */ + function borrow( + address asset, + uint256 amount, + uint256 interestRateMode, + uint16 referralCode, + address onBehalfOf + ) + external; + + /** + * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned + * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address + * @param asset The address of the borrowed underlying asset previously borrowed + * @param amount The amount to repay + * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` + * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for + * Variable + * @param onBehalfOf The address of the user who will get his debt reduced/removed. Should be the address of the + * user calling the function if he wants to reduce/remove his own debt, or the address of any other + * other borrower whose debt should be removed + * @return The final amount repaid + */ + function repay( + address asset, + uint256 amount, + uint256 interestRateMode, + address onBehalfOf + ) + external + returns (uint256); + + /** + * @notice Repay with transfer approval of asset to be repaid done via permit function + * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713 + * @param asset The address of the borrowed underlying asset previously borrowed + * @param amount The amount to repay + * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` + * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for + * Variable + * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the + * user calling the function if he wants to reduce/remove his own debt, or the address of any other + * other borrower whose debt should be removed + * @param deadline The deadline timestamp that the permit is valid + * @param permitV The V parameter of ERC712 permit sig + * @param permitR The R parameter of ERC712 permit sig + * @param permitS The S parameter of ERC712 permit sig + * @return The final amount repaid + */ + function repayWithPermit( + address asset, + uint256 amount, + uint256 interestRateMode, + address onBehalfOf, + uint256 deadline, + uint8 permitV, + bytes32 permitR, + bytes32 permitS + ) + external + returns (uint256); + + /** + * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the + * equivalent debt tokens + * - E.g. User repays 100 USDC using 100 aUSDC, burning 100 variable/stable debt tokens + * @dev Passing uint256.max as amount will clean up any residual aToken dust balance, if the user aToken + * balance is not enough to cover the whole debt + * @param asset The address of the borrowed underlying asset previously borrowed + * @param amount The amount to repay + * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` + * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for + * Variable + * @return The final amount repaid + */ + function repayWithATokens(address asset, uint256 amount, uint256 interestRateMode) external returns (uint256); + + /** + * @notice Allows a borrower to swap his debt between stable and variable mode, or vice versa + * @param asset The address of the underlying asset borrowed + * @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for + * Variable + */ + function swapBorrowRateMode(address asset, uint256 interestRateMode) external; + + /** + * @notice Rebalances the stable interest rate of a user to the current stable rate defined on the reserve. + * - Users can be rebalanced if the following conditions are satisfied: + * 1. Usage ratio is above 95% + * 2. the current supply APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too + * much has been borrowed at a stable rate and suppliers are not earning enough + * @param asset The address of the underlying asset borrowed + * @param user The address of the user to be rebalanced + */ + function rebalanceStableBorrowRate(address asset, address user) external; + + /** + * @notice Allows suppliers to enable/disable a specific supplied asset as collateral + * @param asset The address of the underlying asset supplied + * @param useAsCollateral True if the user wants to use the supply as collateral, false otherwise + */ + function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external; + + /** + * @notice Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1 + * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives + * a proportionally amount of the `collateralAsset` plus a bonus to cover market risk + * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the + * liquidation + * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation + * @param user The address of the borrower getting liquidated + * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover + * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants + * to receive the underlying collateral asset directly + */ + function liquidationCall( + address collateralAsset, + address debtAsset, + address user, + uint256 debtToCover, + bool receiveAToken + ) + external; + + /** + * @notice Allows smartcontracts to access the liquidity of the pool within one transaction, + * as long as the amount taken plus a fee is returned. + * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept + * into consideration. For further details please visit https://docs.aave.com/developers/ + * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanReceiver interface + * @param assets The addresses of the assets being flash-borrowed + * @param amounts The amounts of the assets being flash-borrowed + * @param interestRateModes Types of the debt to open if the flash loan is not returned: + * 0 -> Don"t open any debt, just revert if funds can"t be transferred from the receiver + * 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address + * 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address + * @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2 + * @param params Variadic packed params to pass to the receiver as extra information + * @param referralCode The code used to register the integrator originating the operation, for potential rewards. + * 0 if the action is executed directly by the user, without any middle-man + */ + function flashLoan( + address receiverAddress, + address[] calldata assets, + uint256[] calldata amounts, + uint256[] calldata interestRateModes, + address onBehalfOf, + bytes calldata params, + uint16 referralCode + ) + external; + + /** + * @notice Allows smartcontracts to access the liquidity of the pool within one transaction, + * as long as the amount taken plus a fee is returned. + * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept + * into consideration. For further details please visit https://docs.aave.com/developers/ + * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanSimpleReceiver + * interface + * @param asset The address of the asset being flash-borrowed + * @param amount The amount of the asset being flash-borrowed + * @param params Variadic packed params to pass to the receiver as extra information + * @param referralCode The code used to register the integrator originating the operation, for potential rewards. + * 0 if the action is executed directly by the user, without any middle-man + */ + function flashLoanSimple( + address receiverAddress, + address asset, + uint256 amount, + bytes calldata params, + uint16 referralCode + ) + external; + + /** + * @notice Returns the user account data across all the reserves + * @param user The address of the user + * @return totalCollateralBase The total collateral of the user in the base currency used by the price feed + * @return totalDebtBase The total debt of the user in the base currency used by the price feed + * @return availableBorrowsBase The borrowing power left of the user in the base currency used by the price feed + * @return currentLiquidationThreshold The liquidation threshold of the user + * @return ltv The loan to value of The user + * @return healthFactor The current health factor of the user + */ + function getUserAccountData(address user) + external + view + returns ( + uint256 totalCollateralBase, + uint256 totalDebtBase, + uint256 availableBorrowsBase, + uint256 currentLiquidationThreshold, + uint256 ltv, + uint256 healthFactor + ); + + /** + * @notice Initializes a reserve, activating it, assigning an aToken and debt tokens and an + * interest rate strategy + * @dev Only callable by the PoolConfigurator contract + * @param asset The address of the underlying asset of the reserve + * @param aTokenAddress The address of the aToken that will be assigned to the reserve + * @param stableDebtAddress The address of the StableDebtToken that will be assigned to the reserve + * @param variableDebtAddress The address of the VariableDebtToken that will be assigned to the reserve + * @param interestRateStrategyAddress The address of the interest rate strategy contract + */ + function initReserve( + address asset, + address aTokenAddress, + address stableDebtAddress, + address variableDebtAddress, + address interestRateStrategyAddress + ) + external; + + /** + * @notice Drop a reserve + * @dev Only callable by the PoolConfigurator contract + * @param asset The address of the underlying asset of the reserve + */ + function dropReserve(address asset) external; + + /** + * @notice Updates the address of the interest rate strategy contract + * @dev Only callable by the PoolConfigurator contract + * @param asset The address of the underlying asset of the reserve + * @param rateStrategyAddress The address of the interest rate strategy contract + */ + function setReserveInterestRateStrategyAddress(address asset, address rateStrategyAddress) external; + + /** + * @notice Sets the configuration bitmap of the reserve as a whole + * @dev Only callable by the PoolConfigurator contract + * @param asset The address of the underlying asset of the reserve + * @param configuration The new configuration bitmap + */ + function setConfiguration(address asset, DataTypes.ReserveConfigurationMap calldata configuration) external; + + /** + * @notice Returns the configuration of the reserve + * @param asset The address of the underlying asset of the reserve + * @return The configuration of the reserve + */ + function getConfiguration(address asset) external view returns (DataTypes.ReserveConfigurationMap memory); + + /** + * @notice Returns the configuration of the user across all the reserves + * @param user The user address + * @return The configuration of the user + */ + function getUserConfiguration(address user) external view returns (DataTypes.UserConfigurationMap memory); + + /** + * @notice Returns the normalized income of the reserve + * @param asset The address of the underlying asset of the reserve + * @return The reserve"s normalized income + */ + function getReserveNormalizedIncome(address asset) external view returns (uint256); + + /** + * @notice Returns the normalized variable debt per unit of asset + * @dev WARNING: This function is intended to be used primarily by the protocol itself to get a + * "dynamic" variable index based on time, current stored index and virtual rate at the current + * moment (approx. a borrower would get if opening a position). This means that is always used in + * combination with variable debt supply/balances. + * If using this function externally, consider that is possible to have an increasing normalized + * variable debt that is not equivalent to how the variable debt index would be updated in storage + * (e.g. only updates with non-zero variable debt supply) + * @param asset The address of the underlying asset of the reserve + * @return The reserve normalized variable debt + */ + function getReserveNormalizedVariableDebt(address asset) external view returns (uint256); + + /** + * @notice Returns the state and configuration of the reserve + * @param asset The address of the underlying asset of the reserve + * @return The state and configuration data of the reserve + */ + function getReserveData(address asset) external view returns (DataTypes.ReserveData memory); + + /** + * @notice Validates and finalizes an aToken transfer + * @dev Only callable by the overlying aToken of the `asset` + * @param asset The address of the underlying asset of the aToken + * @param from The user from which the aTokens are transferred + * @param to The user receiving the aTokens + * @param amount The amount being transferred/withdrawn + * @param balanceFromBefore The aToken balance of the `from` user before the transfer + * @param balanceToBefore The aToken balance of the `to` user before the transfer + */ + function finalizeTransfer( + address asset, + address from, + address to, + uint256 amount, + uint256 balanceFromBefore, + uint256 balanceToBefore + ) + external; + + /** + * @notice Returns the list of the underlying assets of all the initialized reserves + * @dev It does not include dropped reserves + * @return The addresses of the underlying assets of the initialized reserves + */ + function getReservesList() external view returns (address[] memory); + + /** + * @notice Returns the address of the underlying asset of a reserve by the reserve id as stored in the + * DataTypes.ReserveData struct + * @param id The id of the reserve as stored in the DataTypes.ReserveData struct + * @return The address of the reserve associated with id + */ + function getReserveAddressById(uint16 id) external view returns (address); + + /** + * @notice Returns the PoolAddressesProvider connected to this contract + * @return The address of the PoolAddressesProvider + */ + function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider); + + /** + * @notice Updates the protocol fee on the bridging + * @param bridgeProtocolFee The part of the premium sent to the protocol treasury + */ + function updateBridgeProtocolFee(uint256 bridgeProtocolFee) external; + + /** + * @notice Updates flash loan premiums. Flash loan premium consists of two parts: + * - A part is sent to aToken holders as extra, one time accumulated interest + * - A part is collected by the protocol treasury + * @dev The total premium is calculated on the total borrowed amount + * @dev The premium to protocol is calculated on the total premium, being a percentage of `flashLoanPremiumTotal` + * @dev Only callable by the PoolConfigurator contract + * @param flashLoanPremiumTotal The total premium, expressed in bps + * @param flashLoanPremiumToProtocol The part of the premium sent to the protocol treasury, expressed in bps + */ + function updateFlashloanPremiums(uint128 flashLoanPremiumTotal, uint128 flashLoanPremiumToProtocol) external; + + /** + * @notice Configures a new category for the eMode. + * @dev In eMode, the protocol allows very high borrowing power to borrow assets of the same category. + * The category 0 is reserved as it"s the default for volatile assets + * @param id The id of the category + * @param config The configuration of the category + */ + function configureEModeCategory(uint8 id, DataTypes.EModeCategory memory config) external; + + /** + * @notice Returns the data of an eMode category + * @param id The id of the category + * @return The configuration data of the category + */ + function getEModeCategoryData(uint8 id) external view returns (DataTypes.EModeCategory memory); + + /** + * @notice Allows a user to use the protocol in eMode + * @param categoryId The id of the category + */ + function setUserEMode(uint8 categoryId) external; + + /** + * @notice Returns the eMode the user is using + * @param user The address of the user + * @return The eMode id + */ + function getUserEMode(address user) external view returns (uint256); + + /** + * @notice Resets the isolation mode total debt of the given asset to zero + * @dev It requires the given asset has zero debt ceiling + * @param asset The address of the underlying asset to reset the isolationModeTotalDebt + */ + function resetIsolationModeTotalDebt(address asset) external; + + /** + * @notice Returns the percentage of available liquidity that can be borrowed at once at stable rate + * @return The percentage of available liquidity to borrow, expressed in bps + */ + function MAX_STABLE_RATE_BORROW_SIZE_PERCENT() external view returns (uint256); + + /** + * @notice Returns the total fee on flash loans + * @return The total fee on flashloans + */ + function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128); + + /** + * @notice Returns the part of the bridge fees sent to protocol + * @return The bridge fee sent to the protocol treasury + */ + function BRIDGE_PROTOCOL_FEE() external view returns (uint256); + + /** + * @notice Returns the part of the flashloan fees sent to protocol + * @return The flashloan fee sent to the protocol treasury + */ + function FLASHLOAN_PREMIUM_TO_PROTOCOL() external view returns (uint128); + + /** + * @notice Returns the maximum number of reserves supported to be listed in this Pool + * @return The maximum number of reserves supported + */ + function MAX_NUMBER_RESERVES() external view returns (uint16); + + /** + * @notice Mints the assets accrued through the reserve factor to the treasury in the form of aTokens + * @param assets The list of reserves for which the minting needs to be executed + */ + function mintToTreasury(address[] calldata assets) external; + + /** + * @notice Rescue and transfer tokens locked in this contract + * @param token The address of the token + * @param to The address of the recipient + * @param amount The amount of token to transfer + */ + function rescueTokens(address token, address to, uint256 amount) external; + + /** + * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. + * - E.g. User supplies 100 USDC and gets in return 100 aUSDC + * @dev Deprecated: Use the `supply` function instead + * @param asset The address of the underlying asset to supply + * @param amount The amount to be supplied + * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user + * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens + * is a different wallet + * @param referralCode Code used to register the integrator originating the operation, for potential rewards. + * 0 if the action is executed directly by the user, without any middle-man + */ + function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external; +} diff --git a/src/aave/interfaces/IPoolAddressesProvider.sol b/src/aave/interfaces/IPoolAddressesProvider.sol index 3f708f4..3a32733 100644 --- a/src/aave/interfaces/IPoolAddressesProvider.sol +++ b/src/aave/interfaces/IPoolAddressesProvider.sol @@ -7,221 +7,217 @@ pragma solidity ^0.8.0; * @notice Defines the basic interface for a Pool Addresses Provider. */ interface IPoolAddressesProvider { - /** - * @dev Emitted when the market identifier is updated. - * @param oldMarketId The old id of the market - * @param newMarketId The new id of the market - */ - event MarketIdSet(string indexed oldMarketId, string indexed newMarketId); - - /** - * @dev Emitted when the pool is updated. - * @param oldAddress The old address of the Pool - * @param newAddress The new address of the Pool - */ - event PoolUpdated(address indexed oldAddress, address indexed newAddress); - - /** - * @dev Emitted when the pool configurator is updated. - * @param oldAddress The old address of the PoolConfigurator - * @param newAddress The new address of the PoolConfigurator - */ - event PoolConfiguratorUpdated(address indexed oldAddress, address indexed newAddress); - - /** - * @dev Emitted when the price oracle is updated. - * @param oldAddress The old address of the PriceOracle - * @param newAddress The new address of the PriceOracle - */ - event PriceOracleUpdated(address indexed oldAddress, address indexed newAddress); - - /** - * @dev Emitted when the ACL manager is updated. - * @param oldAddress The old address of the ACLManager - * @param newAddress The new address of the ACLManager - */ - event ACLManagerUpdated(address indexed oldAddress, address indexed newAddress); - - /** - * @dev Emitted when the ACL admin is updated. - * @param oldAddress The old address of the ACLAdmin - * @param newAddress The new address of the ACLAdmin - */ - event ACLAdminUpdated(address indexed oldAddress, address indexed newAddress); - - /** - * @dev Emitted when the price oracle sentinel is updated. - * @param oldAddress The old address of the PriceOracleSentinel - * @param newAddress The new address of the PriceOracleSentinel - */ - event PriceOracleSentinelUpdated(address indexed oldAddress, address indexed newAddress); - - /** - * @dev Emitted when the pool data provider is updated. - * @param oldAddress The old address of the PoolDataProvider - * @param newAddress The new address of the PoolDataProvider - */ - event PoolDataProviderUpdated(address indexed oldAddress, address indexed newAddress); - - /** - * @dev Emitted when a new proxy is created. - * @param id The identifier of the proxy - * @param proxyAddress The address of the created proxy contract - * @param implementationAddress The address of the implementation contract - */ - event ProxyCreated( - bytes32 indexed id, - address indexed proxyAddress, - address indexed implementationAddress - ); - - /** - * @dev Emitted when a new non-proxied contract address is registered. - * @param id The identifier of the contract - * @param oldAddress The address of the old contract - * @param newAddress The address of the new contract - */ - event AddressSet(bytes32 indexed id, address indexed oldAddress, address indexed newAddress); - - /** - * @dev Emitted when the implementation of the proxy registered with id is updated - * @param id The identifier of the contract - * @param proxyAddress The address of the proxy contract - * @param oldImplementationAddress The address of the old implementation contract - * @param newImplementationAddress The address of the new implementation contract - */ - event AddressSetAsProxy( - bytes32 indexed id, - address indexed proxyAddress, - address oldImplementationAddress, - address indexed newImplementationAddress - ); - - /** - * @notice Returns the id of the Aave market to which this contract points to. - * @return The market id - */ - function getMarketId() external view returns (string memory); - - /** - * @notice Associates an id with a specific PoolAddressesProvider. - * @dev This can be used to create an onchain registry of PoolAddressesProviders to - * identify and validate multiple Aave markets. - * @param newMarketId The market id - */ - function setMarketId(string calldata newMarketId) external; - - /** - * @notice Returns an address by its identifier. - * @dev The returned address might be an EOA or a contract, potentially proxied - * @dev It returns ZERO if there is no registered address with the given id - * @param id The id - * @return The address of the registered for the specified id - */ - function getAddress(bytes32 id) external view returns (address); - - /** - * @notice General function to update the implementation of a proxy registered with - * certain `id`. If there is no proxy registered, it will instantiate one and - * set as implementation the `newImplementationAddress`. - * @dev IMPORTANT Use this function carefully, only for ids that don't have an explicit - * setter function, in order to avoid unexpected consequences - * @param id The id - * @param newImplementationAddress The address of the new implementation - */ - function setAddressAsProxy(bytes32 id, address newImplementationAddress) external; - - /** - * @notice Sets an address for an id replacing the address saved in the addresses map. - * @dev IMPORTANT Use this function carefully, as it will do a hard replacement - * @param id The id - * @param newAddress The address to set - */ - function setAddress(bytes32 id, address newAddress) external; - - /** - * @notice Returns the address of the Pool proxy. - * @return The Pool proxy address - */ - function getPool() external view returns (address); - - /** - * @notice Updates the implementation of the Pool, or creates a proxy - * setting the new `pool` implementation when the function is called for the first time. - * @param newPoolImpl The new Pool implementation - */ - function setPoolImpl(address newPoolImpl) external; - - /** - * @notice Returns the address of the PoolConfigurator proxy. - * @return The PoolConfigurator proxy address - */ - function getPoolConfigurator() external view returns (address); - - /** - * @notice Updates the implementation of the PoolConfigurator, or creates a proxy - * setting the new `PoolConfigurator` implementation when the function is called for the first time. - * @param newPoolConfiguratorImpl The new PoolConfigurator implementation - */ - function setPoolConfiguratorImpl(address newPoolConfiguratorImpl) external; - - /** - * @notice Returns the address of the price oracle. - * @return The address of the PriceOracle - */ - function getPriceOracle() external view returns (address); - - /** - * @notice Updates the address of the price oracle. - * @param newPriceOracle The address of the new PriceOracle - */ - function setPriceOracle(address newPriceOracle) external; - - /** - * @notice Returns the address of the ACL manager. - * @return The address of the ACLManager - */ - function getACLManager() external view returns (address); - - /** - * @notice Updates the address of the ACL manager. - * @param newAclManager The address of the new ACLManager - */ - function setACLManager(address newAclManager) external; - - /** - * @notice Returns the address of the ACL admin. - * @return The address of the ACL admin - */ - function getACLAdmin() external view returns (address); - - /** - * @notice Updates the address of the ACL admin. - * @param newAclAdmin The address of the new ACL admin - */ - function setACLAdmin(address newAclAdmin) external; - - /** - * @notice Returns the address of the price oracle sentinel. - * @return The address of the PriceOracleSentinel - */ - function getPriceOracleSentinel() external view returns (address); - - /** - * @notice Updates the address of the price oracle sentinel. - * @param newPriceOracleSentinel The address of the new PriceOracleSentinel - */ - function setPriceOracleSentinel(address newPriceOracleSentinel) external; - - /** - * @notice Returns the address of the data provider. - * @return The address of the DataProvider - */ - function getPoolDataProvider() external view returns (address); - - /** - * @notice Updates the address of the data provider. - * @param newDataProvider The address of the new DataProvider - */ - function setPoolDataProvider(address newDataProvider) external; -} \ No newline at end of file + /** + * @dev Emitted when the market identifier is updated. + * @param oldMarketId The old id of the market + * @param newMarketId The new id of the market + */ + event MarketIdSet(string indexed oldMarketId, string indexed newMarketId); + + /** + * @dev Emitted when the pool is updated. + * @param oldAddress The old address of the Pool + * @param newAddress The new address of the Pool + */ + event PoolUpdated(address indexed oldAddress, address indexed newAddress); + + /** + * @dev Emitted when the pool configurator is updated. + * @param oldAddress The old address of the PoolConfigurator + * @param newAddress The new address of the PoolConfigurator + */ + event PoolConfiguratorUpdated(address indexed oldAddress, address indexed newAddress); + + /** + * @dev Emitted when the price oracle is updated. + * @param oldAddress The old address of the PriceOracle + * @param newAddress The new address of the PriceOracle + */ + event PriceOracleUpdated(address indexed oldAddress, address indexed newAddress); + + /** + * @dev Emitted when the ACL manager is updated. + * @param oldAddress The old address of the ACLManager + * @param newAddress The new address of the ACLManager + */ + event ACLManagerUpdated(address indexed oldAddress, address indexed newAddress); + + /** + * @dev Emitted when the ACL admin is updated. + * @param oldAddress The old address of the ACLAdmin + * @param newAddress The new address of the ACLAdmin + */ + event ACLAdminUpdated(address indexed oldAddress, address indexed newAddress); + + /** + * @dev Emitted when the price oracle sentinel is updated. + * @param oldAddress The old address of the PriceOracleSentinel + * @param newAddress The new address of the PriceOracleSentinel + */ + event PriceOracleSentinelUpdated(address indexed oldAddress, address indexed newAddress); + + /** + * @dev Emitted when the pool data provider is updated. + * @param oldAddress The old address of the PoolDataProvider + * @param newAddress The new address of the PoolDataProvider + */ + event PoolDataProviderUpdated(address indexed oldAddress, address indexed newAddress); + + /** + * @dev Emitted when a new proxy is created. + * @param id The identifier of the proxy + * @param proxyAddress The address of the created proxy contract + * @param implementationAddress The address of the implementation contract + */ + event ProxyCreated(bytes32 indexed id, address indexed proxyAddress, address indexed implementationAddress); + + /** + * @dev Emitted when a new non-proxied contract address is registered. + * @param id The identifier of the contract + * @param oldAddress The address of the old contract + * @param newAddress The address of the new contract + */ + event AddressSet(bytes32 indexed id, address indexed oldAddress, address indexed newAddress); + + /** + * @dev Emitted when the implementation of the proxy registered with id is updated + * @param id The identifier of the contract + * @param proxyAddress The address of the proxy contract + * @param oldImplementationAddress The address of the old implementation contract + * @param newImplementationAddress The address of the new implementation contract + */ + event AddressSetAsProxy( + bytes32 indexed id, + address indexed proxyAddress, + address oldImplementationAddress, + address indexed newImplementationAddress + ); + + /** + * @notice Returns the id of the Aave market to which this contract points to. + * @return The market id + */ + function getMarketId() external view returns (string memory); + + /** + * @notice Associates an id with a specific PoolAddressesProvider. + * @dev This can be used to create an onchain registry of PoolAddressesProviders to + * identify and validate multiple Aave markets. + * @param newMarketId The market id + */ + function setMarketId(string calldata newMarketId) external; + + /** + * @notice Returns an address by its identifier. + * @dev The returned address might be an EOA or a contract, potentially proxied + * @dev It returns ZERO if there is no registered address with the given id + * @param id The id + * @return The address of the registered for the specified id + */ + function getAddress(bytes32 id) external view returns (address); + + /** + * @notice General function to update the implementation of a proxy registered with + * certain `id`. If there is no proxy registered, it will instantiate one and + * set as implementation the `newImplementationAddress`. + * @dev IMPORTANT Use this function carefully, only for ids that don't have an explicit + * setter function, in order to avoid unexpected consequences + * @param id The id + * @param newImplementationAddress The address of the new implementation + */ + function setAddressAsProxy(bytes32 id, address newImplementationAddress) external; + + /** + * @notice Sets an address for an id replacing the address saved in the addresses map. + * @dev IMPORTANT Use this function carefully, as it will do a hard replacement + * @param id The id + * @param newAddress The address to set + */ + function setAddress(bytes32 id, address newAddress) external; + + /** + * @notice Returns the address of the Pool proxy. + * @return The Pool proxy address + */ + function getPool() external view returns (address); + + /** + * @notice Updates the implementation of the Pool, or creates a proxy + * setting the new `pool` implementation when the function is called for the first time. + * @param newPoolImpl The new Pool implementation + */ + function setPoolImpl(address newPoolImpl) external; + + /** + * @notice Returns the address of the PoolConfigurator proxy. + * @return The PoolConfigurator proxy address + */ + function getPoolConfigurator() external view returns (address); + + /** + * @notice Updates the implementation of the PoolConfigurator, or creates a proxy + * setting the new `PoolConfigurator` implementation when the function is called for the first time. + * @param newPoolConfiguratorImpl The new PoolConfigurator implementation + */ + function setPoolConfiguratorImpl(address newPoolConfiguratorImpl) external; + + /** + * @notice Returns the address of the price oracle. + * @return The address of the PriceOracle + */ + function getPriceOracle() external view returns (address); + + /** + * @notice Updates the address of the price oracle. + * @param newPriceOracle The address of the new PriceOracle + */ + function setPriceOracle(address newPriceOracle) external; + + /** + * @notice Returns the address of the ACL manager. + * @return The address of the ACLManager + */ + function getACLManager() external view returns (address); + + /** + * @notice Updates the address of the ACL manager. + * @param newAclManager The address of the new ACLManager + */ + function setACLManager(address newAclManager) external; + + /** + * @notice Returns the address of the ACL admin. + * @return The address of the ACL admin + */ + function getACLAdmin() external view returns (address); + + /** + * @notice Updates the address of the ACL admin. + * @param newAclAdmin The address of the new ACL admin + */ + function setACLAdmin(address newAclAdmin) external; + + /** + * @notice Returns the address of the price oracle sentinel. + * @return The address of the PriceOracleSentinel + */ + function getPriceOracleSentinel() external view returns (address); + + /** + * @notice Updates the address of the price oracle sentinel. + * @param newPriceOracleSentinel The address of the new PriceOracleSentinel + */ + function setPriceOracleSentinel(address newPriceOracleSentinel) external; + + /** + * @notice Returns the address of the data provider. + * @return The address of the DataProvider + */ + function getPoolDataProvider() external view returns (address); + + /** + * @notice Updates the address of the data provider. + * @param newDataProvider The address of the new DataProvider + */ + function setPoolDataProvider(address newDataProvider) external; +} diff --git a/src/aave/interfaces/ReserveConfiguration.sol b/src/aave/interfaces/ReserveConfiguration.sol index af58fb6..558e873 100644 --- a/src/aave/interfaces/ReserveConfiguration.sol +++ b/src/aave/interfaces/ReserveConfiguration.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; -import {Errors} from './Errors.sol'; -import {DataTypes} from './DataTypes.sol'; +import { Errors } from "./Errors.sol"; +import { DataTypes } from "./DataTypes.sol"; /** * @title ReserveConfiguration library @@ -10,602 +10,520 @@ import {DataTypes} from './DataTypes.sol'; * @notice Implements the bitmap logic to handle the reserve configuration */ library ReserveConfiguration { - uint256 internal constant LTV_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000; // prettier-ignore - uint256 internal constant LIQUIDATION_THRESHOLD_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF; // prettier-ignore - uint256 internal constant LIQUIDATION_BONUS_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF; // prettier-ignore - uint256 internal constant DECIMALS_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFF; // prettier-ignore - uint256 internal constant ACTIVE_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFF; // prettier-ignore - uint256 internal constant FROZEN_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFF; // prettier-ignore - uint256 internal constant BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFF; // prettier-ignore - uint256 internal constant STABLE_BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFF; // prettier-ignore - uint256 internal constant PAUSED_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFF; // prettier-ignore - uint256 internal constant BORROWABLE_IN_ISOLATION_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFFF; // prettier-ignore - uint256 internal constant SILOED_BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFFF; // prettier-ignore - uint256 internal constant FLASHLOAN_ENABLED_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF; // prettier-ignore - uint256 internal constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF; // prettier-ignore - uint256 internal constant BORROW_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFF; // prettier-ignore - uint256 internal constant SUPPLY_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore - uint256 internal constant LIQUIDATION_PROTOCOL_FEE_MASK = 0xFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore - uint256 internal constant EMODE_CATEGORY_MASK = 0xFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore - uint256 internal constant UNBACKED_MINT_CAP_MASK = 0xFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore - uint256 internal constant DEBT_CEILING_MASK = 0xF0000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore - - /// @dev For the LTV, the start bit is 0 (up to 15), hence no bitshifting is needed - uint256 internal constant LIQUIDATION_THRESHOLD_START_BIT_POSITION = 16; - uint256 internal constant LIQUIDATION_BONUS_START_BIT_POSITION = 32; - uint256 internal constant RESERVE_DECIMALS_START_BIT_POSITION = 48; - uint256 internal constant IS_ACTIVE_START_BIT_POSITION = 56; - uint256 internal constant IS_FROZEN_START_BIT_POSITION = 57; - uint256 internal constant BORROWING_ENABLED_START_BIT_POSITION = 58; - uint256 internal constant STABLE_BORROWING_ENABLED_START_BIT_POSITION = 59; - uint256 internal constant IS_PAUSED_START_BIT_POSITION = 60; - uint256 internal constant BORROWABLE_IN_ISOLATION_START_BIT_POSITION = 61; - uint256 internal constant SILOED_BORROWING_START_BIT_POSITION = 62; - uint256 internal constant FLASHLOAN_ENABLED_START_BIT_POSITION = 63; - uint256 internal constant RESERVE_FACTOR_START_BIT_POSITION = 64; - uint256 internal constant BORROW_CAP_START_BIT_POSITION = 80; - uint256 internal constant SUPPLY_CAP_START_BIT_POSITION = 116; - uint256 internal constant LIQUIDATION_PROTOCOL_FEE_START_BIT_POSITION = 152; - uint256 internal constant EMODE_CATEGORY_START_BIT_POSITION = 168; - uint256 internal constant UNBACKED_MINT_CAP_START_BIT_POSITION = 176; - uint256 internal constant DEBT_CEILING_START_BIT_POSITION = 212; - - uint256 internal constant MAX_VALID_LTV = 65535; - uint256 internal constant MAX_VALID_LIQUIDATION_THRESHOLD = 65535; - uint256 internal constant MAX_VALID_LIQUIDATION_BONUS = 65535; - uint256 internal constant MAX_VALID_DECIMALS = 255; - uint256 internal constant MAX_VALID_RESERVE_FACTOR = 65535; - uint256 internal constant MAX_VALID_BORROW_CAP = 68719476735; - uint256 internal constant MAX_VALID_SUPPLY_CAP = 68719476735; - uint256 internal constant MAX_VALID_LIQUIDATION_PROTOCOL_FEE = 65535; - uint256 internal constant MAX_VALID_EMODE_CATEGORY = 255; - uint256 internal constant MAX_VALID_UNBACKED_MINT_CAP = 68719476735; - uint256 internal constant MAX_VALID_DEBT_CEILING = 1099511627775; - - uint256 public constant DEBT_CEILING_DECIMALS = 2; - uint16 public constant MAX_RESERVES_COUNT = 128; - - /** - * @notice Sets the Loan to Value of the reserve - * @param self The reserve configuration - * @param ltv The new ltv - */ - function setLtv(DataTypes.ReserveConfigurationMap memory self, uint256 ltv) internal pure { - require(ltv <= MAX_VALID_LTV, Errors.INVALID_LTV); - - self.data = (self.data & LTV_MASK) | ltv; - } - - /** - * @notice Gets the Loan to Value of the reserve - * @param self The reserve configuration - * @return The loan to value - */ - function getLtv(DataTypes.ReserveConfigurationMap memory self) internal pure returns (uint256) { - return self.data & ~LTV_MASK; - } - - /** - * @notice Sets the liquidation threshold of the reserve - * @param self The reserve configuration - * @param threshold The new liquidation threshold - */ - function setLiquidationThreshold( - DataTypes.ReserveConfigurationMap memory self, - uint256 threshold - ) internal pure { - require(threshold <= MAX_VALID_LIQUIDATION_THRESHOLD, Errors.INVALID_LIQ_THRESHOLD); - - self.data = - (self.data & LIQUIDATION_THRESHOLD_MASK) | - (threshold << LIQUIDATION_THRESHOLD_START_BIT_POSITION); - } - - /** - * @notice Gets the liquidation threshold of the reserve - * @param self The reserve configuration - * @return The liquidation threshold - */ - function getLiquidationThreshold( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (uint256) { - return (self.data & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION; - } - - /** - * @notice Sets the liquidation bonus of the reserve - * @param self The reserve configuration - * @param bonus The new liquidation bonus - */ - function setLiquidationBonus( - DataTypes.ReserveConfigurationMap memory self, - uint256 bonus - ) internal pure { - require(bonus <= MAX_VALID_LIQUIDATION_BONUS, Errors.INVALID_LIQ_BONUS); - - self.data = - (self.data & LIQUIDATION_BONUS_MASK) | - (bonus << LIQUIDATION_BONUS_START_BIT_POSITION); - } - - /** - * @notice Gets the liquidation bonus of the reserve - * @param self The reserve configuration - * @return The liquidation bonus - */ - function getLiquidationBonus( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (uint256) { - return (self.data & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION; - } - - /** - * @notice Sets the decimals of the underlying asset of the reserve - * @param self The reserve configuration - * @param decimals The decimals - */ - function setDecimals( - DataTypes.ReserveConfigurationMap memory self, - uint256 decimals - ) internal pure { - require(decimals <= MAX_VALID_DECIMALS, Errors.INVALID_DECIMALS); - - self.data = (self.data & DECIMALS_MASK) | (decimals << RESERVE_DECIMALS_START_BIT_POSITION); - } - - /** - * @notice Gets the decimals of the underlying asset of the reserve - * @param self The reserve configuration - * @return The decimals of the asset - */ - function getDecimals( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (uint256) { - return (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION; - } - - /** - * @notice Sets the active state of the reserve - * @param self The reserve configuration - * @param active The active state - */ - function setActive(DataTypes.ReserveConfigurationMap memory self, bool active) internal pure { - self.data = - (self.data & ACTIVE_MASK) | - (uint256(active ? 1 : 0) << IS_ACTIVE_START_BIT_POSITION); - } - - /** - * @notice Gets the active state of the reserve - * @param self The reserve configuration - * @return The active state - */ - function getActive(DataTypes.ReserveConfigurationMap memory self) internal pure returns (bool) { - return (self.data & ~ACTIVE_MASK) != 0; - } - - /** - * @notice Sets the frozen state of the reserve - * @param self The reserve configuration - * @param frozen The frozen state - */ - function setFrozen(DataTypes.ReserveConfigurationMap memory self, bool frozen) internal pure { - self.data = - (self.data & FROZEN_MASK) | - (uint256(frozen ? 1 : 0) << IS_FROZEN_START_BIT_POSITION); - } - - /** - * @notice Gets the frozen state of the reserve - * @param self The reserve configuration - * @return The frozen state - */ - function getFrozen(DataTypes.ReserveConfigurationMap memory self) internal pure returns (bool) { - return (self.data & ~FROZEN_MASK) != 0; - } - - /** - * @notice Sets the paused state of the reserve - * @param self The reserve configuration - * @param paused The paused state - */ - function setPaused(DataTypes.ReserveConfigurationMap memory self, bool paused) internal pure { - self.data = - (self.data & PAUSED_MASK) | - (uint256(paused ? 1 : 0) << IS_PAUSED_START_BIT_POSITION); - } - - /** - * @notice Gets the paused state of the reserve - * @param self The reserve configuration - * @return The paused state - */ - function getPaused(DataTypes.ReserveConfigurationMap memory self) internal pure returns (bool) { - return (self.data & ~PAUSED_MASK) != 0; - } - - /** - * @notice Sets the borrowable in isolation flag for the reserve. - * @dev When this flag is set to true, the asset will be borrowable against isolated collaterals and the borrowed - * amount will be accumulated in the isolated collateral's total debt exposure. - * @dev Only assets of the same family (eg USD stablecoins) should be borrowable in isolation mode to keep - * consistency in the debt ceiling calculations. - * @param self The reserve configuration - * @param borrowable True if the asset is borrowable - */ - function setBorrowableInIsolation( - DataTypes.ReserveConfigurationMap memory self, - bool borrowable - ) internal pure { - self.data = - (self.data & BORROWABLE_IN_ISOLATION_MASK) | - (uint256(borrowable ? 1 : 0) << BORROWABLE_IN_ISOLATION_START_BIT_POSITION); - } - - /** - * @notice Gets the borrowable in isolation flag for the reserve. - * @dev If the returned flag is true, the asset is borrowable against isolated collateral. Assets borrowed with - * isolated collateral is accounted for in the isolated collateral's total debt exposure. - * @dev Only assets of the same family (eg USD stablecoins) should be borrowable in isolation mode to keep - * consistency in the debt ceiling calculations. - * @param self The reserve configuration - * @return The borrowable in isolation flag - */ - function getBorrowableInIsolation( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (bool) { - return (self.data & ~BORROWABLE_IN_ISOLATION_MASK) != 0; - } - - /** - * @notice Sets the siloed borrowing flag for the reserve. - * @dev When this flag is set to true, users borrowing this asset will not be allowed to borrow any other asset. - * @param self The reserve configuration - * @param siloed True if the asset is siloed - */ - function setSiloedBorrowing( - DataTypes.ReserveConfigurationMap memory self, - bool siloed - ) internal pure { - self.data = - (self.data & SILOED_BORROWING_MASK) | - (uint256(siloed ? 1 : 0) << SILOED_BORROWING_START_BIT_POSITION); - } - - /** - * @notice Gets the siloed borrowing flag for the reserve. - * @dev When this flag is set to true, users borrowing this asset will not be allowed to borrow any other asset. - * @param self The reserve configuration - * @return The siloed borrowing flag - */ - function getSiloedBorrowing( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (bool) { - return (self.data & ~SILOED_BORROWING_MASK) != 0; - } - - /** - * @notice Enables or disables borrowing on the reserve - * @param self The reserve configuration - * @param enabled True if the borrowing needs to be enabled, false otherwise - */ - function setBorrowingEnabled( - DataTypes.ReserveConfigurationMap memory self, - bool enabled - ) internal pure { - self.data = - (self.data & BORROWING_MASK) | - (uint256(enabled ? 1 : 0) << BORROWING_ENABLED_START_BIT_POSITION); - } - - /** - * @notice Gets the borrowing state of the reserve - * @param self The reserve configuration - * @return The borrowing state - */ - function getBorrowingEnabled( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (bool) { - return (self.data & ~BORROWING_MASK) != 0; - } - - /** - * @notice Enables or disables stable rate borrowing on the reserve - * @param self The reserve configuration - * @param enabled True if the stable rate borrowing needs to be enabled, false otherwise - */ - function setStableRateBorrowingEnabled( - DataTypes.ReserveConfigurationMap memory self, - bool enabled - ) internal pure { - self.data = - (self.data & STABLE_BORROWING_MASK) | - (uint256(enabled ? 1 : 0) << STABLE_BORROWING_ENABLED_START_BIT_POSITION); - } - - /** - * @notice Gets the stable rate borrowing state of the reserve - * @param self The reserve configuration - * @return The stable rate borrowing state - */ - function getStableRateBorrowingEnabled( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (bool) { - return (self.data & ~STABLE_BORROWING_MASK) != 0; - } - - /** - * @notice Sets the reserve factor of the reserve - * @param self The reserve configuration - * @param reserveFactor The reserve factor - */ - function setReserveFactor( - DataTypes.ReserveConfigurationMap memory self, - uint256 reserveFactor - ) internal pure { - require(reserveFactor <= MAX_VALID_RESERVE_FACTOR, Errors.INVALID_RESERVE_FACTOR); - - self.data = - (self.data & RESERVE_FACTOR_MASK) | - (reserveFactor << RESERVE_FACTOR_START_BIT_POSITION); - } - - /** - * @notice Gets the reserve factor of the reserve - * @param self The reserve configuration - * @return The reserve factor - */ - function getReserveFactor( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (uint256) { - return (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION; - } - - /** - * @notice Sets the borrow cap of the reserve - * @param self The reserve configuration - * @param borrowCap The borrow cap - */ - function setBorrowCap( - DataTypes.ReserveConfigurationMap memory self, - uint256 borrowCap - ) internal pure { - require(borrowCap <= MAX_VALID_BORROW_CAP, Errors.INVALID_BORROW_CAP); - - self.data = (self.data & BORROW_CAP_MASK) | (borrowCap << BORROW_CAP_START_BIT_POSITION); - } - - /** - * @notice Gets the borrow cap of the reserve - * @param self The reserve configuration - * @return The borrow cap - */ - function getBorrowCap( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (uint256) { - return (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION; - } - - /** - * @notice Sets the supply cap of the reserve - * @param self The reserve configuration - * @param supplyCap The supply cap - */ - function setSupplyCap( - DataTypes.ReserveConfigurationMap memory self, - uint256 supplyCap - ) internal pure { - require(supplyCap <= MAX_VALID_SUPPLY_CAP, Errors.INVALID_SUPPLY_CAP); - - self.data = (self.data & SUPPLY_CAP_MASK) | (supplyCap << SUPPLY_CAP_START_BIT_POSITION); - } - - /** - * @notice Gets the supply cap of the reserve - * @param self The reserve configuration - * @return The supply cap - */ - function getSupplyCap( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (uint256) { - return (self.data & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION; - } - - /** - * @notice Sets the debt ceiling in isolation mode for the asset - * @param self The reserve configuration - * @param ceiling The maximum debt ceiling for the asset - */ - function setDebtCeiling( - DataTypes.ReserveConfigurationMap memory self, - uint256 ceiling - ) internal pure { - require(ceiling <= MAX_VALID_DEBT_CEILING, Errors.INVALID_DEBT_CEILING); - - self.data = (self.data & DEBT_CEILING_MASK) | (ceiling << DEBT_CEILING_START_BIT_POSITION); - } - - /** - * @notice Gets the debt ceiling for the asset if the asset is in isolation mode - * @param self The reserve configuration - * @return The debt ceiling (0 = isolation mode disabled) - */ - function getDebtCeiling( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (uint256) { - return (self.data & ~DEBT_CEILING_MASK) >> DEBT_CEILING_START_BIT_POSITION; - } - - /** - * @notice Sets the liquidation protocol fee of the reserve - * @param self The reserve configuration - * @param liquidationProtocolFee The liquidation protocol fee - */ - function setLiquidationProtocolFee( - DataTypes.ReserveConfigurationMap memory self, - uint256 liquidationProtocolFee - ) internal pure { - require( - liquidationProtocolFee <= MAX_VALID_LIQUIDATION_PROTOCOL_FEE, - Errors.INVALID_LIQUIDATION_PROTOCOL_FEE - ); - - self.data = - (self.data & LIQUIDATION_PROTOCOL_FEE_MASK) | - (liquidationProtocolFee << LIQUIDATION_PROTOCOL_FEE_START_BIT_POSITION); - } - - /** - * @dev Gets the liquidation protocol fee - * @param self The reserve configuration - * @return The liquidation protocol fee - */ - function getLiquidationProtocolFee( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (uint256) { - return - (self.data & ~LIQUIDATION_PROTOCOL_FEE_MASK) >> LIQUIDATION_PROTOCOL_FEE_START_BIT_POSITION; - } - - /** - * @notice Sets the unbacked mint cap of the reserve - * @param self The reserve configuration - * @param unbackedMintCap The unbacked mint cap - */ - function setUnbackedMintCap( - DataTypes.ReserveConfigurationMap memory self, - uint256 unbackedMintCap - ) internal pure { - require(unbackedMintCap <= MAX_VALID_UNBACKED_MINT_CAP, Errors.INVALID_UNBACKED_MINT_CAP); - - self.data = - (self.data & UNBACKED_MINT_CAP_MASK) | - (unbackedMintCap << UNBACKED_MINT_CAP_START_BIT_POSITION); - } - - /** - * @dev Gets the unbacked mint cap of the reserve - * @param self The reserve configuration - * @return The unbacked mint cap - */ - function getUnbackedMintCap( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (uint256) { - return (self.data & ~UNBACKED_MINT_CAP_MASK) >> UNBACKED_MINT_CAP_START_BIT_POSITION; - } - - /** - * @notice Sets the eMode asset category - * @param self The reserve configuration - * @param category The asset category when the user selects the eMode - */ - function setEModeCategory( - DataTypes.ReserveConfigurationMap memory self, - uint256 category - ) internal pure { - require(category <= MAX_VALID_EMODE_CATEGORY, Errors.INVALID_EMODE_CATEGORY); - - self.data = (self.data & EMODE_CATEGORY_MASK) | (category << EMODE_CATEGORY_START_BIT_POSITION); - } - - /** - * @dev Gets the eMode asset category - * @param self The reserve configuration - * @return The eMode category for the asset - */ - function getEModeCategory( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (uint256) { - return (self.data & ~EMODE_CATEGORY_MASK) >> EMODE_CATEGORY_START_BIT_POSITION; - } - - /** - * @notice Sets the flashloanable flag for the reserve - * @param self The reserve configuration - * @param flashLoanEnabled True if the asset is flashloanable, false otherwise - */ - function setFlashLoanEnabled( - DataTypes.ReserveConfigurationMap memory self, - bool flashLoanEnabled - ) internal pure { - self.data = - (self.data & FLASHLOAN_ENABLED_MASK) | - (uint256(flashLoanEnabled ? 1 : 0) << FLASHLOAN_ENABLED_START_BIT_POSITION); - } - - /** - * @notice Gets the flashloanable flag for the reserve - * @param self The reserve configuration - * @return The flashloanable flag - */ - function getFlashLoanEnabled( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (bool) { - return (self.data & ~FLASHLOAN_ENABLED_MASK) != 0; - } - - /** - * @notice Gets the configuration flags of the reserve - * @param self The reserve configuration - * @return The state flag representing active - * @return The state flag representing frozen - * @return The state flag representing borrowing enabled - * @return The state flag representing stableRateBorrowing enabled - * @return The state flag representing paused - */ - function getFlags( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (bool, bool, bool, bool, bool) { - uint256 dataLocal = self.data; - - return ( - (dataLocal & ~ACTIVE_MASK) != 0, - (dataLocal & ~FROZEN_MASK) != 0, - (dataLocal & ~BORROWING_MASK) != 0, - (dataLocal & ~STABLE_BORROWING_MASK) != 0, - (dataLocal & ~PAUSED_MASK) != 0 - ); - } - - /** - * @notice Gets the configuration parameters of the reserve from storage - * @param self The reserve configuration - * @return The state param representing ltv - * @return The state param representing liquidation threshold - * @return The state param representing liquidation bonus - * @return The state param representing reserve decimals - * @return The state param representing reserve factor - * @return The state param representing eMode category - */ - function getParams( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (uint256, uint256, uint256, uint256, uint256, uint256) { - uint256 dataLocal = self.data; - - return ( - dataLocal & ~LTV_MASK, - (dataLocal & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION, - (dataLocal & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION, - (dataLocal & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION, - (dataLocal & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION, - (dataLocal & ~EMODE_CATEGORY_MASK) >> EMODE_CATEGORY_START_BIT_POSITION - ); - } - - /** - * @notice Gets the caps parameters of the reserve from storage - * @param self The reserve configuration - * @return The state param representing borrow cap - * @return The state param representing supply cap. - */ - function getCaps( - DataTypes.ReserveConfigurationMap memory self - ) internal pure returns (uint256, uint256) { - uint256 dataLocal = self.data; - - return ( - (dataLocal & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION, - (dataLocal & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION - ); - } -} \ No newline at end of file + uint256 internal constant LTV_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000; // prettier-ignore + uint256 internal constant LIQUIDATION_THRESHOLD_MASK = + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF; // prettier-ignore + uint256 internal constant LIQUIDATION_BONUS_MASK = + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF; // prettier-ignore + uint256 internal constant DECIMALS_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFF; // prettier-ignore + uint256 internal constant ACTIVE_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFF; // prettier-ignore + uint256 internal constant FROZEN_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFF; // prettier-ignore + uint256 internal constant BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFF; // prettier-ignore + uint256 internal constant STABLE_BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFF; // prettier-ignore + uint256 internal constant PAUSED_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFF; // prettier-ignore + uint256 internal constant BORROWABLE_IN_ISOLATION_MASK = + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFFF; // prettier-ignore + uint256 internal constant SILOED_BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFFF; // prettier-ignore + uint256 internal constant FLASHLOAN_ENABLED_MASK = + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF; // prettier-ignore + uint256 internal constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF; // prettier-ignore + uint256 internal constant BORROW_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFF; // prettier-ignore + uint256 internal constant SUPPLY_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore + uint256 internal constant LIQUIDATION_PROTOCOL_FEE_MASK = + 0xFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore + uint256 internal constant EMODE_CATEGORY_MASK = 0xFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore + uint256 internal constant UNBACKED_MINT_CAP_MASK = + 0xFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore + uint256 internal constant DEBT_CEILING_MASK = 0xF0000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore + + /// @dev For the LTV, the start bit is 0 (up to 15), hence no bitshifting is needed + uint256 internal constant LIQUIDATION_THRESHOLD_START_BIT_POSITION = 16; + uint256 internal constant LIQUIDATION_BONUS_START_BIT_POSITION = 32; + uint256 internal constant RESERVE_DECIMALS_START_BIT_POSITION = 48; + uint256 internal constant IS_ACTIVE_START_BIT_POSITION = 56; + uint256 internal constant IS_FROZEN_START_BIT_POSITION = 57; + uint256 internal constant BORROWING_ENABLED_START_BIT_POSITION = 58; + uint256 internal constant STABLE_BORROWING_ENABLED_START_BIT_POSITION = 59; + uint256 internal constant IS_PAUSED_START_BIT_POSITION = 60; + uint256 internal constant BORROWABLE_IN_ISOLATION_START_BIT_POSITION = 61; + uint256 internal constant SILOED_BORROWING_START_BIT_POSITION = 62; + uint256 internal constant FLASHLOAN_ENABLED_START_BIT_POSITION = 63; + uint256 internal constant RESERVE_FACTOR_START_BIT_POSITION = 64; + uint256 internal constant BORROW_CAP_START_BIT_POSITION = 80; + uint256 internal constant SUPPLY_CAP_START_BIT_POSITION = 116; + uint256 internal constant LIQUIDATION_PROTOCOL_FEE_START_BIT_POSITION = 152; + uint256 internal constant EMODE_CATEGORY_START_BIT_POSITION = 168; + uint256 internal constant UNBACKED_MINT_CAP_START_BIT_POSITION = 176; + uint256 internal constant DEBT_CEILING_START_BIT_POSITION = 212; + + uint256 internal constant MAX_VALID_LTV = 65_535; + uint256 internal constant MAX_VALID_LIQUIDATION_THRESHOLD = 65_535; + uint256 internal constant MAX_VALID_LIQUIDATION_BONUS = 65_535; + uint256 internal constant MAX_VALID_DECIMALS = 255; + uint256 internal constant MAX_VALID_RESERVE_FACTOR = 65_535; + uint256 internal constant MAX_VALID_BORROW_CAP = 68_719_476_735; + uint256 internal constant MAX_VALID_SUPPLY_CAP = 68_719_476_735; + uint256 internal constant MAX_VALID_LIQUIDATION_PROTOCOL_FEE = 65_535; + uint256 internal constant MAX_VALID_EMODE_CATEGORY = 255; + uint256 internal constant MAX_VALID_UNBACKED_MINT_CAP = 68_719_476_735; + uint256 internal constant MAX_VALID_DEBT_CEILING = 1_099_511_627_775; + + uint256 public constant DEBT_CEILING_DECIMALS = 2; + uint16 public constant MAX_RESERVES_COUNT = 128; + + /** + * @notice Sets the Loan to Value of the reserve + * @param self The reserve configuration + * @param ltv The new ltv + */ + function setLtv(DataTypes.ReserveConfigurationMap memory self, uint256 ltv) internal pure { + require(ltv <= MAX_VALID_LTV, Errors.INVALID_LTV); + + self.data = (self.data & LTV_MASK) | ltv; + } + + /** + * @notice Gets the Loan to Value of the reserve + * @param self The reserve configuration + * @return The loan to value + */ + function getLtv(DataTypes.ReserveConfigurationMap memory self) internal pure returns (uint256) { + return self.data & ~LTV_MASK; + } + + /** + * @notice Sets the liquidation threshold of the reserve + * @param self The reserve configuration + * @param threshold The new liquidation threshold + */ + function setLiquidationThreshold(DataTypes.ReserveConfigurationMap memory self, uint256 threshold) internal pure { + require(threshold <= MAX_VALID_LIQUIDATION_THRESHOLD, Errors.INVALID_LIQ_THRESHOLD); + + self.data = (self.data & LIQUIDATION_THRESHOLD_MASK) | (threshold << LIQUIDATION_THRESHOLD_START_BIT_POSITION); + } + + /** + * @notice Gets the liquidation threshold of the reserve + * @param self The reserve configuration + * @return The liquidation threshold + */ + function getLiquidationThreshold(DataTypes.ReserveConfigurationMap memory self) internal pure returns (uint256) { + return (self.data & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION; + } + + /** + * @notice Sets the liquidation bonus of the reserve + * @param self The reserve configuration + * @param bonus The new liquidation bonus + */ + function setLiquidationBonus(DataTypes.ReserveConfigurationMap memory self, uint256 bonus) internal pure { + require(bonus <= MAX_VALID_LIQUIDATION_BONUS, Errors.INVALID_LIQ_BONUS); + + self.data = (self.data & LIQUIDATION_BONUS_MASK) | (bonus << LIQUIDATION_BONUS_START_BIT_POSITION); + } + + /** + * @notice Gets the liquidation bonus of the reserve + * @param self The reserve configuration + * @return The liquidation bonus + */ + function getLiquidationBonus(DataTypes.ReserveConfigurationMap memory self) internal pure returns (uint256) { + return (self.data & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION; + } + + /** + * @notice Sets the decimals of the underlying asset of the reserve + * @param self The reserve configuration + * @param decimals The decimals + */ + function setDecimals(DataTypes.ReserveConfigurationMap memory self, uint256 decimals) internal pure { + require(decimals <= MAX_VALID_DECIMALS, Errors.INVALID_DECIMALS); + + self.data = (self.data & DECIMALS_MASK) | (decimals << RESERVE_DECIMALS_START_BIT_POSITION); + } + + /** + * @notice Gets the decimals of the underlying asset of the reserve + * @param self The reserve configuration + * @return The decimals of the asset + */ + function getDecimals(DataTypes.ReserveConfigurationMap memory self) internal pure returns (uint256) { + return (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION; + } + + /** + * @notice Sets the active state of the reserve + * @param self The reserve configuration + * @param active The active state + */ + function setActive(DataTypes.ReserveConfigurationMap memory self, bool active) internal pure { + self.data = (self.data & ACTIVE_MASK) | (uint256(active ? 1 : 0) << IS_ACTIVE_START_BIT_POSITION); + } + + /** + * @notice Gets the active state of the reserve + * @param self The reserve configuration + * @return The active state + */ + function getActive(DataTypes.ReserveConfigurationMap memory self) internal pure returns (bool) { + return (self.data & ~ACTIVE_MASK) != 0; + } + + /** + * @notice Sets the frozen state of the reserve + * @param self The reserve configuration + * @param frozen The frozen state + */ + function setFrozen(DataTypes.ReserveConfigurationMap memory self, bool frozen) internal pure { + self.data = (self.data & FROZEN_MASK) | (uint256(frozen ? 1 : 0) << IS_FROZEN_START_BIT_POSITION); + } + + /** + * @notice Gets the frozen state of the reserve + * @param self The reserve configuration + * @return The frozen state + */ + function getFrozen(DataTypes.ReserveConfigurationMap memory self) internal pure returns (bool) { + return (self.data & ~FROZEN_MASK) != 0; + } + + /** + * @notice Sets the paused state of the reserve + * @param self The reserve configuration + * @param paused The paused state + */ + function setPaused(DataTypes.ReserveConfigurationMap memory self, bool paused) internal pure { + self.data = (self.data & PAUSED_MASK) | (uint256(paused ? 1 : 0) << IS_PAUSED_START_BIT_POSITION); + } + + /** + * @notice Gets the paused state of the reserve + * @param self The reserve configuration + * @return The paused state + */ + function getPaused(DataTypes.ReserveConfigurationMap memory self) internal pure returns (bool) { + return (self.data & ~PAUSED_MASK) != 0; + } + + /** + * @notice Sets the borrowable in isolation flag for the reserve. + * @dev When this flag is set to true, the asset will be borrowable against isolated collaterals and the borrowed + * amount will be accumulated in the isolated collateral's total debt exposure. + * @dev Only assets of the same family (eg USD stablecoins) should be borrowable in isolation mode to keep + * consistency in the debt ceiling calculations. + * @param self The reserve configuration + * @param borrowable True if the asset is borrowable + */ + function setBorrowableInIsolation(DataTypes.ReserveConfigurationMap memory self, bool borrowable) internal pure { + self.data = (self.data & BORROWABLE_IN_ISOLATION_MASK) + | (uint256(borrowable ? 1 : 0) << BORROWABLE_IN_ISOLATION_START_BIT_POSITION); + } + + /** + * @notice Gets the borrowable in isolation flag for the reserve. + * @dev If the returned flag is true, the asset is borrowable against isolated collateral. Assets borrowed with + * isolated collateral is accounted for in the isolated collateral's total debt exposure. + * @dev Only assets of the same family (eg USD stablecoins) should be borrowable in isolation mode to keep + * consistency in the debt ceiling calculations. + * @param self The reserve configuration + * @return The borrowable in isolation flag + */ + function getBorrowableInIsolation(DataTypes.ReserveConfigurationMap memory self) internal pure returns (bool) { + return (self.data & ~BORROWABLE_IN_ISOLATION_MASK) != 0; + } + + /** + * @notice Sets the siloed borrowing flag for the reserve. + * @dev When this flag is set to true, users borrowing this asset will not be allowed to borrow any other asset. + * @param self The reserve configuration + * @param siloed True if the asset is siloed + */ + function setSiloedBorrowing(DataTypes.ReserveConfigurationMap memory self, bool siloed) internal pure { + self.data = + (self.data & SILOED_BORROWING_MASK) | (uint256(siloed ? 1 : 0) << SILOED_BORROWING_START_BIT_POSITION); + } + + /** + * @notice Gets the siloed borrowing flag for the reserve. + * @dev When this flag is set to true, users borrowing this asset will not be allowed to borrow any other asset. + * @param self The reserve configuration + * @return The siloed borrowing flag + */ + function getSiloedBorrowing(DataTypes.ReserveConfigurationMap memory self) internal pure returns (bool) { + return (self.data & ~SILOED_BORROWING_MASK) != 0; + } + + /** + * @notice Enables or disables borrowing on the reserve + * @param self The reserve configuration + * @param enabled True if the borrowing needs to be enabled, false otherwise + */ + function setBorrowingEnabled(DataTypes.ReserveConfigurationMap memory self, bool enabled) internal pure { + self.data = (self.data & BORROWING_MASK) | (uint256(enabled ? 1 : 0) << BORROWING_ENABLED_START_BIT_POSITION); + } + + /** + * @notice Gets the borrowing state of the reserve + * @param self The reserve configuration + * @return The borrowing state + */ + function getBorrowingEnabled(DataTypes.ReserveConfigurationMap memory self) internal pure returns (bool) { + return (self.data & ~BORROWING_MASK) != 0; + } + + /** + * @notice Enables or disables stable rate borrowing on the reserve + * @param self The reserve configuration + * @param enabled True if the stable rate borrowing needs to be enabled, false otherwise + */ + function setStableRateBorrowingEnabled(DataTypes.ReserveConfigurationMap memory self, bool enabled) internal pure { + self.data = (self.data & STABLE_BORROWING_MASK) + | (uint256(enabled ? 1 : 0) << STABLE_BORROWING_ENABLED_START_BIT_POSITION); + } + + /** + * @notice Gets the stable rate borrowing state of the reserve + * @param self The reserve configuration + * @return The stable rate borrowing state + */ + function getStableRateBorrowingEnabled(DataTypes.ReserveConfigurationMap memory self) + internal + pure + returns (bool) + { + return (self.data & ~STABLE_BORROWING_MASK) != 0; + } + + /** + * @notice Sets the reserve factor of the reserve + * @param self The reserve configuration + * @param reserveFactor The reserve factor + */ + function setReserveFactor(DataTypes.ReserveConfigurationMap memory self, uint256 reserveFactor) internal pure { + require(reserveFactor <= MAX_VALID_RESERVE_FACTOR, Errors.INVALID_RESERVE_FACTOR); + + self.data = (self.data & RESERVE_FACTOR_MASK) | (reserveFactor << RESERVE_FACTOR_START_BIT_POSITION); + } + + /** + * @notice Gets the reserve factor of the reserve + * @param self The reserve configuration + * @return The reserve factor + */ + function getReserveFactor(DataTypes.ReserveConfigurationMap memory self) internal pure returns (uint256) { + return (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION; + } + + /** + * @notice Sets the borrow cap of the reserve + * @param self The reserve configuration + * @param borrowCap The borrow cap + */ + function setBorrowCap(DataTypes.ReserveConfigurationMap memory self, uint256 borrowCap) internal pure { + require(borrowCap <= MAX_VALID_BORROW_CAP, Errors.INVALID_BORROW_CAP); + + self.data = (self.data & BORROW_CAP_MASK) | (borrowCap << BORROW_CAP_START_BIT_POSITION); + } + + /** + * @notice Gets the borrow cap of the reserve + * @param self The reserve configuration + * @return The borrow cap + */ + function getBorrowCap(DataTypes.ReserveConfigurationMap memory self) internal pure returns (uint256) { + return (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION; + } + + /** + * @notice Sets the supply cap of the reserve + * @param self The reserve configuration + * @param supplyCap The supply cap + */ + function setSupplyCap(DataTypes.ReserveConfigurationMap memory self, uint256 supplyCap) internal pure { + require(supplyCap <= MAX_VALID_SUPPLY_CAP, Errors.INVALID_SUPPLY_CAP); + + self.data = (self.data & SUPPLY_CAP_MASK) | (supplyCap << SUPPLY_CAP_START_BIT_POSITION); + } + + /** + * @notice Gets the supply cap of the reserve + * @param self The reserve configuration + * @return The supply cap + */ + function getSupplyCap(DataTypes.ReserveConfigurationMap memory self) internal pure returns (uint256) { + return (self.data & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION; + } + + /** + * @notice Sets the debt ceiling in isolation mode for the asset + * @param self The reserve configuration + * @param ceiling The maximum debt ceiling for the asset + */ + function setDebtCeiling(DataTypes.ReserveConfigurationMap memory self, uint256 ceiling) internal pure { + require(ceiling <= MAX_VALID_DEBT_CEILING, Errors.INVALID_DEBT_CEILING); + + self.data = (self.data & DEBT_CEILING_MASK) | (ceiling << DEBT_CEILING_START_BIT_POSITION); + } + + /** + * @notice Gets the debt ceiling for the asset if the asset is in isolation mode + * @param self The reserve configuration + * @return The debt ceiling (0 = isolation mode disabled) + */ + function getDebtCeiling(DataTypes.ReserveConfigurationMap memory self) internal pure returns (uint256) { + return (self.data & ~DEBT_CEILING_MASK) >> DEBT_CEILING_START_BIT_POSITION; + } + + /** + * @notice Sets the liquidation protocol fee of the reserve + * @param self The reserve configuration + * @param liquidationProtocolFee The liquidation protocol fee + */ + function setLiquidationProtocolFee( + DataTypes.ReserveConfigurationMap memory self, + uint256 liquidationProtocolFee + ) + internal + pure + { + require(liquidationProtocolFee <= MAX_VALID_LIQUIDATION_PROTOCOL_FEE, Errors.INVALID_LIQUIDATION_PROTOCOL_FEE); + + self.data = (self.data & LIQUIDATION_PROTOCOL_FEE_MASK) + | (liquidationProtocolFee << LIQUIDATION_PROTOCOL_FEE_START_BIT_POSITION); + } + + /** + * @dev Gets the liquidation protocol fee + * @param self The reserve configuration + * @return The liquidation protocol fee + */ + function getLiquidationProtocolFee(DataTypes.ReserveConfigurationMap memory self) internal pure returns (uint256) { + return (self.data & ~LIQUIDATION_PROTOCOL_FEE_MASK) >> LIQUIDATION_PROTOCOL_FEE_START_BIT_POSITION; + } + + /** + * @notice Sets the unbacked mint cap of the reserve + * @param self The reserve configuration + * @param unbackedMintCap The unbacked mint cap + */ + function setUnbackedMintCap(DataTypes.ReserveConfigurationMap memory self, uint256 unbackedMintCap) internal pure { + require(unbackedMintCap <= MAX_VALID_UNBACKED_MINT_CAP, Errors.INVALID_UNBACKED_MINT_CAP); + + self.data = (self.data & UNBACKED_MINT_CAP_MASK) | (unbackedMintCap << UNBACKED_MINT_CAP_START_BIT_POSITION); + } + + /** + * @dev Gets the unbacked mint cap of the reserve + * @param self The reserve configuration + * @return The unbacked mint cap + */ + function getUnbackedMintCap(DataTypes.ReserveConfigurationMap memory self) internal pure returns (uint256) { + return (self.data & ~UNBACKED_MINT_CAP_MASK) >> UNBACKED_MINT_CAP_START_BIT_POSITION; + } + + /** + * @notice Sets the eMode asset category + * @param self The reserve configuration + * @param category The asset category when the user selects the eMode + */ + function setEModeCategory(DataTypes.ReserveConfigurationMap memory self, uint256 category) internal pure { + require(category <= MAX_VALID_EMODE_CATEGORY, Errors.INVALID_EMODE_CATEGORY); + + self.data = (self.data & EMODE_CATEGORY_MASK) | (category << EMODE_CATEGORY_START_BIT_POSITION); + } + + /** + * @dev Gets the eMode asset category + * @param self The reserve configuration + * @return The eMode category for the asset + */ + function getEModeCategory(DataTypes.ReserveConfigurationMap memory self) internal pure returns (uint256) { + return (self.data & ~EMODE_CATEGORY_MASK) >> EMODE_CATEGORY_START_BIT_POSITION; + } + + /** + * @notice Sets the flashloanable flag for the reserve + * @param self The reserve configuration + * @param flashLoanEnabled True if the asset is flashloanable, false otherwise + */ + function setFlashLoanEnabled(DataTypes.ReserveConfigurationMap memory self, bool flashLoanEnabled) internal pure { + self.data = (self.data & FLASHLOAN_ENABLED_MASK) + | (uint256(flashLoanEnabled ? 1 : 0) << FLASHLOAN_ENABLED_START_BIT_POSITION); + } + + /** + * @notice Gets the flashloanable flag for the reserve + * @param self The reserve configuration + * @return The flashloanable flag + */ + function getFlashLoanEnabled(DataTypes.ReserveConfigurationMap memory self) internal pure returns (bool) { + return (self.data & ~FLASHLOAN_ENABLED_MASK) != 0; + } + + /** + * @notice Gets the configuration flags of the reserve + * @param self The reserve configuration + * @return The state flag representing active + * @return The state flag representing frozen + * @return The state flag representing borrowing enabled + * @return The state flag representing stableRateBorrowing enabled + * @return The state flag representing paused + */ + function getFlags(DataTypes.ReserveConfigurationMap memory self) + internal + pure + returns (bool, bool, bool, bool, bool) + { + uint256 dataLocal = self.data; + + return ( + (dataLocal & ~ACTIVE_MASK) != 0, + (dataLocal & ~FROZEN_MASK) != 0, + (dataLocal & ~BORROWING_MASK) != 0, + (dataLocal & ~STABLE_BORROWING_MASK) != 0, + (dataLocal & ~PAUSED_MASK) != 0 + ); + } + + /** + * @notice Gets the configuration parameters of the reserve from storage + * @param self The reserve configuration + * @return The state param representing ltv + * @return The state param representing liquidation threshold + * @return The state param representing liquidation bonus + * @return The state param representing reserve decimals + * @return The state param representing reserve factor + * @return The state param representing eMode category + */ + function getParams(DataTypes.ReserveConfigurationMap memory self) + internal + pure + returns (uint256, uint256, uint256, uint256, uint256, uint256) + { + uint256 dataLocal = self.data; + + return ( + dataLocal & ~LTV_MASK, + (dataLocal & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION, + (dataLocal & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION, + (dataLocal & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION, + (dataLocal & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION, + (dataLocal & ~EMODE_CATEGORY_MASK) >> EMODE_CATEGORY_START_BIT_POSITION + ); + } + + /** + * @notice Gets the caps parameters of the reserve from storage + * @param self The reserve configuration + * @return The state param representing borrow cap + * @return The state param representing supply cap. + */ + function getCaps(DataTypes.ReserveConfigurationMap memory self) internal pure returns (uint256, uint256) { + uint256 dataLocal = self.data; + + return ( + (dataLocal & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION, + (dataLocal & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION + ); + } +} diff --git a/src/balancer/BalancerWrapper.sol b/src/balancer/BalancerWrapper.sol index 3f8780b..ade1410 100644 --- a/src/balancer/BalancerWrapper.sol +++ b/src/balancer/BalancerWrapper.sol @@ -14,10 +14,11 @@ import { IERC3156PPFlashLender } from "lib/erc3156pp/src/interfaces/IERC3156PPFl import { FixedPointMathLib } from "lib/solmate/src/utils/FixedPointMathLib.sol"; import { IERC20 } from "lib/erc3156pp/src/interfaces/IERC20.sol"; - contract BalancerWrapper is IFlashLoanRecipient, IERC3156PPFlashLender { using TransferHelper for IERC20; - using FunctionCodec for function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory); + using + FunctionCodec + for function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory); using FunctionCodec for bytes24; using Arrays for uint256; using Arrays for address; @@ -32,17 +33,14 @@ contract BalancerWrapper is IFlashLoanRecipient, IERC3156PPFlashLender { balancer = _balancer; } - function flashFee(IERC20 asset, uint256 amount) - external - view - returns (uint256 fee) - { + function flashFee(IERC20 asset, uint256 amount) external view returns (uint256 fee) { if (amount >= asset.balanceOf(address(balancer))) fee = type(uint256).max; else fee = amount.mulWadUp(balancer.getProtocolFeesCollector().getFlashLoanFeePercentage()); } /// @dev Use the aggregator to serve an ERC3156++ flash loan. - /// @dev Forward the callback to the callback receiver. The borrower only needs to trust the aggregator and its governance, instead of the underlying lenders. + /// @dev Forward the callback to the callback receiver. The borrower only needs to trust the aggregator and its + /// governance, instead of the underlying lenders. /// @param loanReceiver The address receiving the flash loan /// @param asset The asset to be loaned /// @param amount The amount to loaned @@ -55,7 +53,8 @@ contract BalancerWrapper is IFlashLoanRecipient, IERC3156PPFlashLender { uint256 amount, bytes calldata initiatorData, /// @dev callback. - /// This is a concatenation of (address, bytes4), where the address is the callback receiver, and the bytes4 is the signature of callback function. + /// This is a concatenation of (address, bytes4), where the address is the callback receiver, and the bytes4 is + /// the signature of callback function. /// The arguments in the callback function are fixed. /// If the callback receiver needs to know the loan receiver, it should be encoded by the initiator in `data`. /// @param initiator The address that called this function @@ -66,8 +65,12 @@ contract BalancerWrapper is IFlashLoanRecipient, IERC3156PPFlashLender { /// @param data The ABI encoded data to be passed to the callback /// @return result ABI encoded result of the callback function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) callback - ) external returns (bytes memory) { - bytes memory data = abi.encode(msg.sender, loanReceiver, asset, amount, callback.encodeFunction(), initiatorData); + ) + external + returns (bytes memory) + { + bytes memory data = + abi.encode(msg.sender, loanReceiver, asset, amount, callback.encodeFunction(), initiatorData); flashLoanDataHash = keccak256(data); balancer.flashLoan(this, address(asset).toArray(), amount.toArray(), data); @@ -82,22 +85,33 @@ contract BalancerWrapper is IFlashLoanRecipient, IERC3156PPFlashLender { uint256[] memory amounts, uint256[] memory fees, bytes memory data - ) external override { + ) + external + override + { require(msg.sender == address(balancer), "not balancer"); require(keccak256(data) == flashLoanDataHash, "params hash mismatch"); delete flashLoanDataHash; // decode data - (address initiator, address loanReceiver, IERC20 asset, uint256 amount, bytes24 encodedCallback, bytes memory initiatorData) = abi - .decode(data, (address, address, IERC20, uint256, bytes24, bytes)); - - function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) callback = encodedCallback.decodeFunction(); + ( + address initiator, + address loanReceiver, + IERC20 asset, + uint256 amount, + bytes24 encodedCallback, + bytes memory initiatorData + ) = abi.decode(data, (address, address, IERC20, uint256, bytes24, bytes)); + + function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) callback = + encodedCallback.decodeFunction(); // send the borrowed amount to the loan receiver asset.safeTransfer(address(loanReceiver), amount); // call the callback and tell the calback receiver to pay to the balancer contract // the callback result is kept in a storage variable to be retrieved later in this tx - _callbackResult = callback(initiator, msg.sender, IERC20(assets[0]), amounts[0], fees[0], initiatorData); // TODO: Skip the storage write if result.length == 0 + _callbackResult = callback(initiator, msg.sender, IERC20(assets[0]), amounts[0], fees[0], initiatorData); // TODO: + // Skip the storage write if result.length == 0 } -} \ No newline at end of file +} diff --git a/src/balancer/interfaces/IFlashLoanRecipient.sol b/src/balancer/interfaces/IFlashLoanRecipient.sol index a2d28bb..cd76c78 100644 --- a/src/balancer/interfaces/IFlashLoanRecipient.sol +++ b/src/balancer/interfaces/IFlashLoanRecipient.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; - interface IFlashLoanRecipient { /** * @dev When `flashLoan` is called on the Vault, it invokes the `receiveFlashLoan` hook on the recipient. @@ -17,5 +16,6 @@ interface IFlashLoanRecipient { uint256[] memory amounts, uint256[] memory feeAmounts, bytes memory userData - ) external; + ) + external; } diff --git a/src/balancer/interfaces/IFlashLoaner.sol b/src/balancer/interfaces/IFlashLoaner.sol index 367d25d..f571c9d 100644 --- a/src/balancer/interfaces/IFlashLoaner.sol +++ b/src/balancer/interfaces/IFlashLoaner.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; + import { IFlashLoanRecipient } from "./IFlashLoanRecipient.sol"; import { IProtocolFeesCollector } from "./IProtocolFeesCollector.sol"; @@ -9,7 +10,8 @@ interface IFlashLoaner { address[] memory tokens, uint256[] memory amounts, bytes memory userData - ) external; + ) + external; function getProtocolFeesCollector() external view returns (IProtocolFeesCollector); } diff --git a/src/balancer/interfaces/IProtocolFeesCollector.sol b/src/balancer/interfaces/IProtocolFeesCollector.sol index 4036d83..704a86a 100644 --- a/src/balancer/interfaces/IProtocolFeesCollector.sol +++ b/src/balancer/interfaces/IProtocolFeesCollector.sol @@ -3,4 +3,4 @@ pragma solidity ^0.8.0; interface IProtocolFeesCollector { function getFlashLoanFeePercentage() external view returns (uint256); -} \ No newline at end of file +} diff --git a/src/dydx/DYDXWrapper.sol b/src/dydx/DYDXWrapper.sol index 8fce692..46197dc 100644 --- a/src/dydx/DYDXWrapper.sol +++ b/src/dydx/DYDXWrapper.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later -// Derived from https://github.com/kollateral/kollateral/blob/master/protocol/contracts/liquidity/kollateral/KollateralLiquidityProxy.sol +// Derived from +// https://github.com/kollateral/kollateral/blob/master/protocol/contracts/liquidity/kollateral/KollateralLiquidityProxy.sol pragma solidity ^0.8.0; import { SoloMarginLike } from "./interfaces/SoloMarginLike.sol"; @@ -11,10 +12,11 @@ import { FunctionCodec } from "../utils/FunctionCodec.sol"; import { IERC20 } from "lib/erc3156pp/src/interfaces/IERC20.sol"; import { IERC3156PPFlashLender } from "lib/erc3156pp/src/interfaces/IERC3156PPFlashLender.sol"; - contract DYDXWrapper is IERC3156PPFlashLender, DYDXFlashBorrowerLike { using TransferHelper for IERC20; - using FunctionCodec for function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory); + using + FunctionCodec + for function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory); using FunctionCodec for bytes24; uint256 internal NULL_ACCOUNT_ID = 0; @@ -33,7 +35,7 @@ contract DYDXWrapper is IERC3156PPFlashLender, DYDXFlashBorrowerLike { mapping(IERC20 => bool) public assetsRegistered; /// @param soloMargin_ DYDX SoloMargin address - constructor (SoloMarginLike soloMargin_) { + constructor(SoloMarginLike soloMargin_) { soloMargin = soloMargin_; for (uint256 marketId = 0; marketId <= 3; marketId++) { @@ -55,7 +57,8 @@ contract DYDXWrapper is IERC3156PPFlashLender, DYDXFlashBorrowerLike { } /// @dev Use the aggregator to serve an ERC3156++ flash loan. - /// @dev Forward the callback to the callback receiver. The borrower only needs to trust the aggregator and its governance, instead of the underlying lenders. + /// @dev Forward the callback to the callback receiver. The borrower only needs to trust the aggregator and its + /// governance, instead of the underlying lenders. /// @param loanReceiver The address receiving the flash loan /// @param asset The asset to be loaned /// @param amount The amount to loaned @@ -68,7 +71,8 @@ contract DYDXWrapper is IERC3156PPFlashLender, DYDXFlashBorrowerLike { uint256 amount, bytes calldata initiatorData, /// @dev callback. - /// This is a concatenation of (address, bytes4), where the address is the callback receiver, and the bytes4 is the signature of callback function. + /// This is a concatenation of (address, bytes4), where the address is the callback receiver, and the bytes4 is + /// the signature of callback function. /// The arguments in the callback function are fixed. /// If the callback receiver needs to know the loan receiver, it should be encoded by the initiator in `data`. /// @param initiator The address that called this function @@ -79,7 +83,10 @@ contract DYDXWrapper is IERC3156PPFlashLender, DYDXFlashBorrowerLike { /// @param data The ABI encoded data to be passed to the callback /// @return result ABI encoded result of the callback function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) callback - ) external returns (bytes memory) { + ) + external + returns (bytes memory) + { DYDXDataTypes.ActionArgs[] memory operations = new DYDXDataTypes.ActionArgs[](3); operations[0] = getWithdrawAction(loanReceiver, asset, amount); operations[1] = getCallAction(abi.encode(msg.sender, asset, amount, callback.encodeFunction(), initiatorData)); @@ -94,48 +101,45 @@ contract DYDXWrapper is IERC3156PPFlashLender, DYDXFlashBorrowerLike { return result; } - /// @dev DYDX flash loan callback. It sends the value borrowed to `receiver`, and takes it back plus a `flashFee` after the ERC3156 callback. - function callFunction( - address sender, - DYDXDataTypes.AccountInfo memory, - bytes memory data - ) - public override - { + /// @dev DYDX flash loan callback. It sends the value borrowed to `receiver`, and takes it back plus a `flashFee` + /// after the ERC3156 callback. + function callFunction(address sender, DYDXDataTypes.AccountInfo memory, bytes memory data) public override { require(msg.sender == address(soloMargin), "Callback only from SoloMargin"); require(sender == address(this), "FlashLoan only from this contract"); - // We pass the loan to the loan receiver and we store the callback result in storage for the the ERC3156++ flashLoan function to recover it. + // We pass the loan to the loan receiver and we store the callback result in storage for the the ERC3156++ + // flashLoan function to recover it. _callbackResult = _callFromData(data); } - /// @dev Internal function to transfer to the loan receiver and the callback. It is used to avoid stack too deep. - function _callFromData(bytes memory data) internal returns(bytes memory) { - (address initiator, IERC20 asset, uint256 amount, bytes24 encodedCallback, bytes memory initiatorData) = + function _callFromData(bytes memory data) internal returns (bytes memory) { + (address initiator, IERC20 asset, uint256 amount, bytes24 encodedCallback, bytes memory initiatorData) = abi.decode(data, (address, IERC20, uint256, bytes24, bytes)); uint256 fee = flashFee(asset, amount); - function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) callback = encodedCallback.decodeFunction(); - + function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) callback = + encodedCallback.decodeFunction(); + // Approve the SoloMargin contract allowance to *pull* the owed amount - IERC20(asset).approve(address(soloMargin), amount + fee); + IERC20(asset).approve(address(soloMargin), amount + fee); return callback(initiator, address(this), asset, amount, fee, initiatorData); } function getAccountInfo() internal view returns (DYDXDataTypes.AccountInfo memory) { - return DYDXDataTypes.AccountInfo({ - owner: address(this), - number: 1 - }); + return DYDXDataTypes.AccountInfo({ owner: address(this), number: 1 }); } - function getWithdrawAction(address loanReceiver, IERC20 asset,uint256 amount) - internal - view - returns (DYDXDataTypes.ActionArgs memory) + function getWithdrawAction( + address loanReceiver, + IERC20 asset, + uint256 amount + ) + internal + view + returns (DYDXDataTypes.ActionArgs memory) { return DYDXDataTypes.ActionArgs({ actionType: DYDXDataTypes.ActionType.Withdraw, @@ -154,10 +158,13 @@ contract DYDXWrapper is IERC3156PPFlashLender, DYDXFlashBorrowerLike { }); } - function getDepositAction(IERC20 asset, uint256 repaymentAmount) - internal - view - returns (DYDXDataTypes.ActionArgs memory) + function getDepositAction( + IERC20 asset, + uint256 repaymentAmount + ) + internal + view + returns (DYDXDataTypes.ActionArgs memory) { return DYDXDataTypes.ActionArgs({ actionType: DYDXDataTypes.ActionType.Deposit, @@ -176,11 +183,7 @@ contract DYDXWrapper is IERC3156PPFlashLender, DYDXFlashBorrowerLike { }); } - function getCallAction(bytes memory data_) - internal - view - returns (DYDXDataTypes.ActionArgs memory) - { + function getCallAction(bytes memory data_) internal view returns (DYDXDataTypes.ActionArgs memory) { return DYDXDataTypes.ActionArgs({ actionType: DYDXDataTypes.ActionType.Call, accountId: 0, @@ -192,4 +195,4 @@ contract DYDXWrapper is IERC3156PPFlashLender, DYDXFlashBorrowerLike { data: data_ }); } -} \ No newline at end of file +} diff --git a/src/dydx/interfaces/DYDXFlashBorrowerLike.sol b/src/dydx/interfaces/DYDXFlashBorrowerLike.sol index 5dd66c8..747f5fc 100644 --- a/src/dydx/interfaces/DYDXFlashBorrowerLike.sol +++ b/src/dydx/interfaces/DYDXFlashBorrowerLike.sol @@ -10,7 +10,6 @@ import "../libraries/DYDXDataTypes.sol"; * Interface that Callees for Solo must implement in order to ingest data. */ interface DYDXFlashBorrowerLike { - // ============ Public Functions ============ /** @@ -20,10 +19,5 @@ interface DYDXFlashBorrowerLike { * @param accountInfo The account from which the data is being sent * @param data Arbitrary data given by the sender */ - function callFunction( - address sender, - DYDXDataTypes.AccountInfo memory accountInfo, - bytes memory data - ) - external; -} \ No newline at end of file + function callFunction(address sender, DYDXDataTypes.AccountInfo memory accountInfo, bytes memory data) external; +} diff --git a/src/dydx/libraries/DYDXDataTypes.sol b/src/dydx/libraries/DYDXDataTypes.sol index 24f7c60..8fdb484 100644 --- a/src/dydx/libraries/DYDXDataTypes.sol +++ b/src/dydx/libraries/DYDXDataTypes.sol @@ -4,20 +4,20 @@ pragma solidity ^0.8.0; library DYDXDataTypes { enum ActionType { - Deposit, // supply tokens - Withdraw, // flashLoan tokens - Transfer, // transfer balance between accounts - Buy, // buy an amount of some token (externally) - Sell, // sell an amount of some token (externally) - Trade, // trade tokens against another account + Deposit, // supply tokens + Withdraw, // flashLoan tokens + Transfer, // transfer balance between accounts + Buy, // buy an amount of some token (externally) + Sell, // sell an amount of some token (externally) + Trade, // trade tokens against another account Liquidate, // liquidate an undercollateralized or expiring account - Vaporize, // use excess tokens to zero-out a completely negative account - Call // send arbitrary data to an address + Vaporize, // use excess tokens to zero-out a completely negative account + Call // send arbitrary data to an address } enum AssetDenomination { Wei, // the amount is denominated in wei - Par // the amount is denominated in par + Par // the amount is denominated in par } enum AssetReference { @@ -49,7 +49,7 @@ library DYDXDataTypes { } struct AccountInfo { - address owner; // The address that owns the account + address owner; // The address that owns the account uint256 number; // A nonce that allows a single address to control many accounts } } diff --git a/src/dydx/mocks/SoloMarginMock.sol b/src/dydx/mocks/SoloMarginMock.sol index b945b60..b4b29de 100644 --- a/src/dydx/mocks/SoloMarginMock.sol +++ b/src/dydx/mocks/SoloMarginMock.sol @@ -7,7 +7,6 @@ import "../interfaces/SoloMarginLike.sol"; import "../interfaces/DYDXFlashBorrowerLike.sol"; contract SoloMarginMock is SoloMarginLike { - mapping(uint256 => address) internal _markets; constructor(uint256[] memory marketIds, address[] memory tokenAddresses) { @@ -16,7 +15,13 @@ contract SoloMarginMock is SoloMarginLike { } } - function operate(DYDXDataTypes.AccountInfo[] memory accounts, DYDXDataTypes.ActionArgs[] memory actions) public override { + function operate( + DYDXDataTypes.AccountInfo[] memory accounts, + DYDXDataTypes.ActionArgs[] memory actions + ) + public + override + { /* data */ require(accounts.length == 1, "SoloMarginMock: incorrect accounts length"); require(actions.length == 3, "SoloMarginMock: incorrect actions length"); @@ -25,10 +30,17 @@ contract SoloMarginMock is SoloMarginLike { DYDXDataTypes.ActionArgs memory withdraw = actions[0]; require(withdraw.amount.sign == false, "SoloMarginMock: incorrect withdraw sign"); - require(withdraw.amount.denomination == DYDXDataTypes.AssetDenomination.Wei, "SoloMarginMock: incorrect withdraw denomination"); - require(withdraw.amount.ref == DYDXDataTypes.AssetReference.Delta, "SoloMarginMock: incorrect withdraw reference"); - - require(withdraw.actionType == DYDXDataTypes.ActionType.Withdraw, "SoloMarginMock: incorrect withdraw action type"); + require( + withdraw.amount.denomination == DYDXDataTypes.AssetDenomination.Wei, + "SoloMarginMock: incorrect withdraw denomination" + ); + require( + withdraw.amount.ref == DYDXDataTypes.AssetReference.Delta, "SoloMarginMock: incorrect withdraw reference" + ); + + require( + withdraw.actionType == DYDXDataTypes.ActionType.Withdraw, "SoloMarginMock: incorrect withdraw action type" + ); /* call */ DYDXDataTypes.ActionArgs memory call = actions[1]; @@ -41,7 +53,10 @@ contract SoloMarginMock is SoloMarginLike { uint256 depositValue = withdraw.amount.value + repaymentFee(withdraw.primaryMarketId); require(deposit.amount.value == depositValue, "SoloMarginMock: incorrect deposit value"); require(deposit.amount.sign == true, "SoloMarginMock: incorrect deposit sign"); - require(deposit.amount.denomination == DYDXDataTypes.AssetDenomination.Wei, "SoloMarginMock: incorrect deposit denomination"); + require( + deposit.amount.denomination == DYDXDataTypes.AssetDenomination.Wei, + "SoloMarginMock: incorrect deposit denomination" + ); require(deposit.amount.ref == DYDXDataTypes.AssetReference.Delta, "SoloMarginMock: incorrect deposit reference"); require(deposit.actionType == DYDXDataTypes.ActionType.Deposit, "SoloMarginMock: incorrect deposit action type"); @@ -50,15 +65,17 @@ contract SoloMarginMock is SoloMarginLike { transfer(withdraw.primaryMarketId, msg.sender, withdraw.amount.value); - DYDXFlashBorrowerLike(msg.sender).callFunction(msg.sender, DYDXDataTypes.AccountInfo({ - owner: accounts[0].owner, - number: accounts[0].number - }), call.data); + DYDXFlashBorrowerLike(msg.sender).callFunction( + msg.sender, DYDXDataTypes.AccountInfo({ owner: accounts[0].owner, number: accounts[0].number }), call.data + ); transferFrom(deposit.primaryMarketId, msg.sender, address(this), deposit.amount.value); uint256 balanceAfter = balanceOf(withdraw.primaryMarketId); - require(balanceAfter == balanceBefore + repaymentFee(withdraw.primaryMarketId), "SoloMarginMock: Incorrect ending balance"); + require( + balanceAfter == balanceBefore + repaymentFee(withdraw.primaryMarketId), + "SoloMarginMock: Incorrect ending balance" + ); } function getMarketTokenAddress(uint256 marketId) public view override returns (address) { @@ -78,6 +95,6 @@ contract SoloMarginMock is SoloMarginLike { } function balanceOf(uint256 marketId) internal view returns (uint256) { - return IERC20(_markets[marketId]).balanceOf(address(this)); + return IERC20(_markets[marketId]).balanceOf(address(this)); } } diff --git a/src/erc3156/ERC3156Wrapper.sol b/src/erc3156/ERC3156Wrapper.sol index 1483da2..5a1f8cc 100644 --- a/src/erc3156/ERC3156Wrapper.sol +++ b/src/erc3156/ERC3156Wrapper.sol @@ -9,14 +9,15 @@ import { FunctionCodec } from "../utils/FunctionCodec.sol"; import { IERC3156PPFlashLender } from "lib/erc3156pp/src/interfaces/IERC3156PPFlashLender.sol"; import { IERC20 } from "lib/erc3156pp/src/interfaces/IERC20.sol"; - /** * @author Alberto Cuesta CaƱada * @dev ERC3156++ Flash Lender that uses ERC3156 Flash Lenders as source of liquidity. */ contract ERC3156Wrapper is IERC3156PPFlashLender, IERC3156FlashBorrower { using TransferHelper for IERC20; - using FunctionCodec for function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory); + using + FunctionCodec + for function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory); using FunctionCodec for bytes24; bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan"); @@ -28,11 +29,8 @@ contract ERC3156Wrapper is IERC3156PPFlashLender, IERC3156FlashBorrower { * @param assets_ Asset contracts supported for flash lending. * @param lenders_ The flash lenders that will be used for each asset. */ - constructor( - IERC20[] memory assets_, - IERC3156FlashLender[] memory lenders_ - ) { - require (assets_.length == lenders_.length, "Arrays must be the same length"); + constructor(IERC20[] memory assets_, IERC3156FlashLender[] memory lenders_) { + require(assets_.length == lenders_.length, "Arrays must be the same length"); for (uint256 i = 0; i < assets_.length; i++) { lenders[assets_[i]] = IERC3156FlashLender(address(lenders_[i])); } @@ -41,19 +39,18 @@ contract ERC3156Wrapper is IERC3156PPFlashLender, IERC3156FlashBorrower { /// @dev The fee to be charged for a given loan. /// @param asset The loan currency. /// @param amount The amount of assets lent. - /// @return The amount of `asset` to be charged for the loan, on top of the returned principal. Returns type(uint256).max if the loan is not possible. - function flashFee( - IERC20 asset, - uint256 amount - ) external view returns (uint256) { + /// @return The amount of `asset` to be charged for the loan, on top of the returned principal. Returns + /// type(uint256).max if the loan is not possible. + function flashFee(IERC20 asset, uint256 amount) external view returns (uint256) { IERC3156FlashLender lender = lenders[asset]; - require (address(lender) != address(0), "Unsupported currency"); - if (lender.maxFlashLoan(address(asset)) < amount) return type(uint256).max; + require(address(lender) != address(0), "Unsupported currency"); + if (lender.maxFlashLoan(address(asset)) < amount) return type(uint256).max; else return lender.flashFee(address(asset), amount); } /// @dev Use the aggregator to serve an ERC3156++ flash loan. - /// @dev Forward the callback to the callback receiver. The borrower only needs to trust the aggregator and its governance, instead of the underlying lenders. + /// @dev Forward the callback to the callback receiver. The borrower only needs to trust the aggregator and its + /// governance, instead of the underlying lenders. /// @param loanReceiver The address receiving the flash loan /// @param asset The asset to be loaned /// @param amount The amount to loaned @@ -66,7 +63,8 @@ contract ERC3156Wrapper is IERC3156PPFlashLender, IERC3156FlashBorrower { uint256 amount, bytes calldata initiatorData, /// @dev callback. - /// This is a concatenation of (address, bytes4), where the address is the callback receiver, and the bytes4 is the signature of callback function. + /// This is a concatenation of (address, bytes4), where the address is the callback receiver, and the bytes4 is + /// the signature of callback function. /// The arguments in the callback function are fixed. /// If the callback receiver needs to know the loan receiver, it should be encoded by the initiator in `data`. /// @param initiator The address that called this function @@ -77,9 +75,12 @@ contract ERC3156Wrapper is IERC3156PPFlashLender, IERC3156FlashBorrower { /// @param data The ABI encoded data to be passed to the callback /// @return result ABI encoded result of the callback function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) callback - ) external returns (bytes memory) { + ) + external + returns (bytes memory) + { IERC3156FlashLender lender = lenders[asset]; - require (address(lender) != address(0), "Unsupported currency"); + require(address(lender) != address(0), "Unsupported currency"); bytes memory data = abi.encode(msg.sender, loanReceiver, callback.encodeFunction(), initiatorData); @@ -106,7 +107,10 @@ contract ERC3156Wrapper is IERC3156PPFlashLender, IERC3156FlashBorrower { uint256 amount, uint256 fee, bytes calldata data - ) external returns (bytes32) { + ) + external + returns (bytes32) + { require(erc3156initiator == address(this), "External loan initiator"); require(msg.sender == address(lenders[IERC20(asset)]), "Unknown lender"); IERC3156FlashLender lender = IERC3156FlashLender(msg.sender); @@ -119,18 +123,20 @@ contract ERC3156Wrapper is IERC3156PPFlashLender, IERC3156FlashBorrower { address loanReceiver; bytes24 encodedCallback; - (initiator, loanReceiver, encodedCallback, initiatorData) = abi.decode(data, (address, address, bytes24, bytes)); + (initiator, loanReceiver, encodedCallback, initiatorData) = + abi.decode(data, (address, address, bytes24, bytes)); callback = encodedCallback.decodeFunction(); // We pass the loan to the loan receiver IERC20(asset).safeTransfer(loanReceiver, amount); } // We release loanReceiver and encodedCallback from the stack - // We pass the loan to the loan receiver and we store the callback result in storage for the the ERC3156++ flashLoan function to recover it. + // We pass the loan to the loan receiver and we store the callback result in storage for the the ERC3156++ + // flashLoan function to recover it. _callbackResult = callback(initiator, address(this), IERC20(asset), amount, fee, initiatorData); IERC20(asset).approve(address(lender), amount + fee); return CALLBACK_SUCCESS; } -} \ No newline at end of file +} diff --git a/src/test/FlashBorrower.sol b/src/test/FlashBorrower.sol index 2dc60f2..8e6a078 100644 --- a/src/test/FlashBorrower.sol +++ b/src/test/FlashBorrower.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.0; import { IERC3156PPFlashLender } from "lib/erc3156pp/src/interfaces/IERC3156PPFlashLender.sol"; import { IERC20 } from "lib/erc3156pp/src/interfaces/IERC20.sol"; - contract LoanReceiver { function retrieve(IERC20 asset) external { asset.transfer(msg.sender, asset.balanceOf(address(this))); @@ -22,13 +21,23 @@ contract FlashBorrower { uint256 public flashAmount; uint256 public flashFee; - constructor (IERC3156PPFlashLender lender_) { + constructor(IERC3156PPFlashLender lender_) { lender = lender_; loanReceiver = new LoanReceiver(); } /// @dev ERC-3156++ Flash loan callback - function onFlashLoan(address initiator, address paymentReceiver, IERC20 asset, uint256 amount, uint256 fee, bytes calldata) external returns(bytes memory) { + function onFlashLoan( + address initiator, + address paymentReceiver, + IERC20 asset, + uint256 amount, + uint256 fee, + bytes calldata + ) + external + returns (bytes memory) + { require(msg.sender == address(lender), "FlashBorrower: Untrusted lender"); require(initiator == address(this), "FlashBorrower: External loan initiator"); @@ -43,26 +52,46 @@ contract FlashBorrower { return abi.encode(ERC3156PP_CALLBACK_SUCCESS); } - function onSteal(address initiator, address, IERC20 asset, uint256 amount, uint256 fee, bytes calldata) external returns(bytes memory) { + function onSteal( + address initiator, + address, + IERC20 asset, + uint256 amount, + uint256 fee, + bytes calldata + ) + external + returns (bytes memory) + { require(msg.sender == address(lender), "FlashBorrower: Untrusted lender"); require(initiator == address(this), "FlashBorrower: External loan initiator"); flashInitiator = initiator; flashAsset = asset; flashAmount = amount; flashFee = fee; - + // do nothing return abi.encode(ERC3156PP_CALLBACK_SUCCESS); } - function onReenter(address initiator, address paymentReceiver, IERC20 asset, uint256 amount, uint256 fee, bytes calldata) external returns(bytes memory) { + function onReenter( + address initiator, + address paymentReceiver, + IERC20 asset, + uint256 amount, + uint256 fee, + bytes calldata + ) + external + returns (bytes memory) + { require(msg.sender == address(lender), "FlashBorrower: Untrusted lender"); require(initiator == address(this), "FlashBorrower: External loan initiator"); flashInitiator = initiator; flashAsset = asset; loanReceiver.retrieve(asset); - + flashBorrow(asset, amount * 2); asset.transfer(paymentReceiver, amount + fee); @@ -74,7 +103,17 @@ contract FlashBorrower { return abi.encode(ERC3156PP_CALLBACK_SUCCESS); } - function onFlashLoanVoid(address initiator, address paymentReceiver, IERC20 asset, uint256 amount, uint256 fee, bytes calldata) external returns(bytes memory) { + function onFlashLoanVoid( + address initiator, + address paymentReceiver, + IERC20 asset, + uint256 amount, + uint256 fee, + bytes calldata + ) + external + returns (bytes memory) + { require(msg.sender == address(lender), "FlashBorrower: Untrusted lender"); require(initiator == address(this), "FlashBorrower: External loan initiator"); @@ -89,19 +128,19 @@ contract FlashBorrower { return ""; } - function flashBorrow(IERC20 asset, uint256 amount) public returns(bytes memory) { + function flashBorrow(IERC20 asset, uint256 amount) public returns (bytes memory) { return lender.flashLoan(address(loanReceiver), asset, amount, "", this.onFlashLoan); } - function flashBorrowAndSteal(IERC20 asset, uint256 amount) public returns(bytes memory) { + function flashBorrowAndSteal(IERC20 asset, uint256 amount) public returns (bytes memory) { return lender.flashLoan(address(loanReceiver), asset, amount, "", this.onSteal); } - function flashBorrowAndReenter(IERC20 asset, uint256 amount) public returns(bytes memory) { + function flashBorrowAndReenter(IERC20 asset, uint256 amount) public returns (bytes memory) { return lender.flashLoan(address(loanReceiver), asset, amount, "", this.onReenter); } - function flashBorrowVoid(IERC20 asset, uint256 amount) public returns(bytes memory) { + function flashBorrowVoid(IERC20 asset, uint256 amount) public returns (bytes memory) { return lender.flashLoan(address(loanReceiver), asset, amount, "", this.onFlashLoanVoid); } } diff --git a/src/uniswapV3/UniswapV3Wrapper.sol b/src/uniswapV3/UniswapV3Wrapper.sol index ec727a9..26cbb1f 100644 --- a/src/uniswapV3/UniswapV3Wrapper.sol +++ b/src/uniswapV3/UniswapV3Wrapper.sol @@ -14,7 +14,9 @@ import { IERC3156PPFlashLender } from "lib/erc3156pp/src/interfaces/IERC3156PPFl contract UniswapV3Wrapper is IERC3156PPFlashLender, IUniswapV3FlashCallback { using TransferHelper for IERC20; - using FunctionCodec for function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory); + using + FunctionCodec + for function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory); using FunctionCodec for bytes24; // CONSTANTS @@ -31,18 +33,15 @@ contract UniswapV3Wrapper is IERC3156PPFlashLender, IUniswapV3FlashCallback { /// @param factory_ Uniswap v3 UniswapV3Factory address /// @param weth_ Weth contract used in Uniswap v3 Pairs /// @param dai_ dai contract used in Uniswap v3 Pairs - constructor( - IUniswapV3Factory factory_, - IERC20 weth_, - IERC20 dai_ - ) { + constructor(IUniswapV3Factory factory_, IERC20 weth_, IERC20 dai_) { factory = factory_; weth = weth_; dai = dai_; } /** - * @dev Get the Uniswap Pool that will be used as the source of a loan. The opposite asset will be Weth, except for Weth that will be Dai. + * @dev Get the Uniswap Pool that will be used as the source of a loan. The opposite asset will be Weth, except for + * Weth that will be Dai. * @param asset The loan currency. * @return The Uniswap V3 Pool that will be used as the source of the flash loan. */ @@ -68,7 +67,8 @@ contract UniswapV3Wrapper is IERC3156PPFlashLender, IUniswapV3FlashCallback { } /// @dev Use the aggregator to serve an ERC3156++ flash loan. - /// @dev Forward the callback to the callback receiver. The borrower only needs to trust the aggregator and its governance, instead of the underlying lenders. + /// @dev Forward the callback to the callback receiver. The borrower only needs to trust the aggregator and its + /// governance, instead of the underlying lenders. /// @param loanReceiver The address receiving the flash loan /// @param asset The asset to be loaned /// @param amount The amount to loaned @@ -81,7 +81,8 @@ contract UniswapV3Wrapper is IERC3156PPFlashLender, IUniswapV3FlashCallback { uint256 amount, bytes calldata initiatorData, /// @dev callback. - /// This is a concatenation of (address, bytes4), where the address is the callback receiver, and the bytes4 is the signature of callback function. + /// This is a concatenation of (address, bytes4), where the address is the callback receiver, and the bytes4 is + /// the signature of callback function. /// The arguments in the callback function are fixed. /// If the callback receiver needs to know the loan receiver, it should be encoded by the initiator in `data`. /// @param initiator The address that called this function @@ -92,16 +93,20 @@ contract UniswapV3Wrapper is IERC3156PPFlashLender, IUniswapV3FlashCallback { /// @param data The ABI encoded data to be passed to the callback /// @return result ABI encoded result of the callback function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) callback - ) external returns (bytes memory) { + ) + external + returns (bytes memory) + { IUniswapV3Pool pool = getPool(asset); require(address(pool) != address(0), "Unsupported currency"); - + IERC20 asset0 = IERC20(pool.token0()); IERC20 asset1 = IERC20(pool.token1()); - uint amount0 = asset == asset0 ? amount : 0; - uint amount1 = asset == asset1 ? amount : 0; + uint256 amount0 = asset == asset0 ? amount : 0; + uint256 amount1 = asset == asset1 ? amount : 0; - bytes memory data = abi.encode(msg.sender, loanReceiver, asset, amount, callback.encodeFunction(), initiatorData); + bytes memory data = + abi.encode(msg.sender, loanReceiver, asset, amount, callback.encodeFunction(), initiatorData); _activePool = pool; pool.flash(address(this), amount0, amount1, data); @@ -117,14 +122,24 @@ contract UniswapV3Wrapper is IERC3156PPFlashLender, IUniswapV3FlashCallback { uint256, // Fee on Asset0 uint256, // Fee on Asset1 bytes calldata data - ) external override { + ) + external + override + { require(msg.sender == address(_activePool), "Only active pool"); // decode data - (address initiator, address loanReceiver, IERC20 asset, uint256 amount, bytes24 encodedCallback, bytes memory initiatorData) = abi - .decode(data, (address, address, IERC20, uint256, bytes24, bytes)); - - function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) callback = encodedCallback.decodeFunction(); + ( + address initiator, + address loanReceiver, + IERC20 asset, + uint256 amount, + bytes24 encodedCallback, + bytes memory initiatorData + ) = abi.decode(data, (address, address, IERC20, uint256, bytes24, bytes)); + + function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) callback = + encodedCallback.decodeFunction(); uint256 fee = flashFee(asset, amount); @@ -135,4 +150,4 @@ contract UniswapV3Wrapper is IERC3156PPFlashLender, IUniswapV3FlashCallback { // the callback result is kept in a storage variable to be retrieved later in this tx _callbackResult = callback(initiator, msg.sender, asset, amount, fee, initiatorData); } -} \ No newline at end of file +} diff --git a/src/uniswapV3/interfaces/IUniswapV3Factory.sol b/src/uniswapV3/interfaces/IUniswapV3Factory.sol index 540cfdc..4142d72 100644 --- a/src/uniswapV3/interfaces/IUniswapV3Factory.sol +++ b/src/uniswapV3/interfaces/IUniswapV3Factory.sol @@ -16,11 +16,7 @@ interface IUniswapV3Factory { /// @param tickSpacing The minimum number of ticks between initialized ticks /// @param pool The address of the created pool event PoolCreated( - address indexed token0, - address indexed token1, - uint24 indexed fee, - int24 tickSpacing, - address pool + address indexed token0, address indexed token1, uint24 indexed fee, int24 tickSpacing, address pool ); /// @notice Emitted when a new fee amount is enabled for pool creation via the factory @@ -45,11 +41,7 @@ interface IUniswapV3Factory { /// @param tokenB The contract address of the other token /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip /// @return pool The pool address - function getPool( - address tokenA, - address tokenB, - uint24 fee - ) external view returns (address pool); + function getPool(address tokenA, address tokenB, uint24 fee) external view returns (address pool); /// @notice Creates a pool for the given two tokens and fee /// @param tokenA One of the two tokens in the desired pool @@ -59,11 +51,7 @@ interface IUniswapV3Factory { /// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments /// are invalid. /// @return pool The address of the newly created pool - function createPool( - address tokenA, - address tokenB, - uint24 fee - ) external returns (address pool); + function createPool(address tokenA, address tokenB, uint24 fee) external returns (address pool); /// @notice Updates the owner of the factory /// @dev Must be called by the current owner diff --git a/src/uniswapV3/interfaces/IUniswapV3Pool.sol b/src/uniswapV3/interfaces/IUniswapV3Pool.sol index 56df050..186cd6a 100644 --- a/src/uniswapV3/interfaces/IUniswapV3Pool.sol +++ b/src/uniswapV3/interfaces/IUniswapV3Pool.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; -import './pool/IUniswapV3PoolImmutables.sol'; -import './pool/IUniswapV3PoolState.sol'; -import './pool/IUniswapV3PoolDerivedState.sol'; -import './pool/IUniswapV3PoolActions.sol'; -import './pool/IUniswapV3PoolOwnerActions.sol'; -import './pool/IUniswapV3PoolEvents.sol'; +import "./pool/IUniswapV3PoolImmutables.sol"; +import "./pool/IUniswapV3PoolState.sol"; +import "./pool/IUniswapV3PoolDerivedState.sol"; +import "./pool/IUniswapV3PoolActions.sol"; +import "./pool/IUniswapV3PoolOwnerActions.sol"; +import "./pool/IUniswapV3PoolEvents.sol"; /// @title The interface for a Uniswap V3 Pool /// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform @@ -19,6 +19,4 @@ interface IUniswapV3Pool is IUniswapV3PoolActions, IUniswapV3PoolOwnerActions, IUniswapV3PoolEvents -{ - -} +{ } diff --git a/src/uniswapV3/interfaces/callback/IUniswapV3FlashCallback.sol b/src/uniswapV3/interfaces/callback/IUniswapV3FlashCallback.sol index 18e54c4..a416559 100644 --- a/src/uniswapV3/interfaces/callback/IUniswapV3FlashCallback.sol +++ b/src/uniswapV3/interfaces/callback/IUniswapV3FlashCallback.sol @@ -10,9 +10,5 @@ interface IUniswapV3FlashCallback { /// @param fee0 The fee amount in token0 due to the pool by the end of the flash /// @param fee1 The fee amount in token1 due to the pool by the end of the flash /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call - function uniswapV3FlashCallback( - uint256 fee0, - uint256 fee1, - bytes calldata data - ) external; + function uniswapV3FlashCallback(uint256 fee0, uint256 fee1, bytes calldata data) external; } diff --git a/src/uniswapV3/interfaces/pool/IUniswapV3PoolActions.sol b/src/uniswapV3/interfaces/pool/IUniswapV3PoolActions.sol index 44fb61c..620948c 100644 --- a/src/uniswapV3/interfaces/pool/IUniswapV3PoolActions.sol +++ b/src/uniswapV3/interfaces/pool/IUniswapV3PoolActions.sol @@ -18,15 +18,19 @@ interface IUniswapV3PoolActions { /// @param tickUpper The upper tick of the position in which to add liquidity /// @param amount The amount of liquidity to mint /// @param data Any data that should be passed through to the callback - /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback - /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback + /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in + /// the callback + /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in + /// the callback function mint( address recipient, int24 tickLower, int24 tickUpper, uint128 amount, bytes calldata data - ) external returns (uint256 amount0, uint256 amount1); + ) + external + returns (uint256 amount0, uint256 amount1); /// @notice Collects tokens owed to a position /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity. @@ -46,7 +50,9 @@ interface IUniswapV3PoolActions { int24 tickUpper, uint128 amount0Requested, uint128 amount1Requested - ) external returns (uint128 amount0, uint128 amount1); + ) + external + returns (uint128 amount0, uint128 amount1); /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0 @@ -60,13 +66,16 @@ interface IUniswapV3PoolActions { int24 tickLower, int24 tickUpper, uint128 amount - ) external returns (uint256 amount0, uint256 amount1); + ) + external + returns (uint256 amount0, uint256 amount1); /// @notice Swap token0 for token1, or token1 for token0 /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback /// @param recipient The address to receive the output of the swap /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0 - /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative) + /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), + /// or exact output (negative) /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this /// value after the swap. If one for zero, the price cannot be greater than this value after the swap /// @param data Any data to be passed through to the callback @@ -78,7 +87,9 @@ interface IUniswapV3PoolActions { int256 amountSpecified, uint160 sqrtPriceLimitX96, bytes calldata data - ) external returns (int256 amount0, int256 amount1); + ) + external + returns (int256 amount0, int256 amount1); /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback @@ -88,12 +99,7 @@ interface IUniswapV3PoolActions { /// @param amount0 The amount of token0 to send /// @param amount1 The amount of token1 to send /// @param data Any data to be passed through to the callback - function flash( - address recipient, - uint256 amount0, - uint256 amount1, - bytes calldata data - ) external; + function flash(address recipient, uint256 amount0, uint256 amount1, bytes calldata data) external; /// @notice Increase the maximum number of price and liquidity observations that this pool will store /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to diff --git a/src/uniswapV3/interfaces/pool/IUniswapV3PoolDerivedState.sol b/src/uniswapV3/interfaces/pool/IUniswapV3PoolDerivedState.sol index eda3a00..ddaea17 100644 --- a/src/uniswapV3/interfaces/pool/IUniswapV3PoolDerivedState.sol +++ b/src/uniswapV3/interfaces/pool/IUniswapV3PoolDerivedState.sol @@ -5,15 +5,19 @@ pragma solidity >=0.5.0; /// @notice Contains view functions to provide information about the pool that is computed rather than stored on the /// blockchain. The functions here may have variable gas costs. interface IUniswapV3PoolDerivedState { - /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp - /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing - /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick, + /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block + /// timestamp + /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one + /// representing + /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted + /// average tick, /// you must call it with secondsAgos = [3600, 0]. /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio. /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp - /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block + /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each + /// `secondsAgos` from the current block /// timestamp function observe(uint32[] calldata secondsAgos) external @@ -29,12 +33,11 @@ interface IUniswapV3PoolDerivedState { /// @return tickCumulativeInside The snapshot of the tick accumulator for the range /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range /// @return secondsInside The snapshot of seconds per liquidity for the range - function snapshotCumulativesInside(int24 tickLower, int24 tickUpper) + function snapshotCumulativesInside( + int24 tickLower, + int24 tickUpper + ) external view - returns ( - int56 tickCumulativeInside, - uint160 secondsPerLiquidityInsideX128, - uint32 secondsInside - ); + returns (int56 tickCumulativeInside, uint160 secondsPerLiquidityInsideX128, uint32 secondsInside); } diff --git a/src/uniswapV3/interfaces/pool/IUniswapV3PoolEvents.sol b/src/uniswapV3/interfaces/pool/IUniswapV3PoolEvents.sol index 9d915dd..bc3b7bd 100644 --- a/src/uniswapV3/interfaces/pool/IUniswapV3PoolEvents.sol +++ b/src/uniswapV3/interfaces/pool/IUniswapV3PoolEvents.sol @@ -101,8 +101,7 @@ interface IUniswapV3PoolEvents { /// @param observationCardinalityNextOld The previous value of the next observation cardinality /// @param observationCardinalityNextNew The updated value of the next observation cardinality event IncreaseObservationCardinalityNext( - uint16 observationCardinalityNextOld, - uint16 observationCardinalityNextNew + uint16 observationCardinalityNextOld, uint16 observationCardinalityNextNew ); /// @notice Emitted when the protocol fee is changed by the pool diff --git a/src/uniswapV3/interfaces/pool/IUniswapV3PoolOwnerActions.sol b/src/uniswapV3/interfaces/pool/IUniswapV3PoolOwnerActions.sol index 2395ed3..4a84b81 100644 --- a/src/uniswapV3/interfaces/pool/IUniswapV3PoolOwnerActions.sol +++ b/src/uniswapV3/interfaces/pool/IUniswapV3PoolOwnerActions.sol @@ -19,5 +19,7 @@ interface IUniswapV3PoolOwnerActions { address recipient, uint128 amount0Requested, uint128 amount1Requested - ) external returns (uint128 amount0, uint128 amount1); + ) + external + returns (uint128 amount0, uint128 amount1); } diff --git a/src/uniswapV3/interfaces/pool/IUniswapV3PoolState.sol b/src/uniswapV3/interfaces/pool/IUniswapV3PoolState.sol index 620256c..e7cb5f5 100644 --- a/src/uniswapV3/interfaces/pool/IUniswapV3PoolState.sol +++ b/src/uniswapV3/interfaces/pool/IUniswapV3PoolState.sol @@ -31,11 +31,13 @@ interface IUniswapV3PoolState { bool unlocked ); - /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool + /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the + /// pool /// @dev This value can overflow the uint256 function feeGrowthGlobal0X128() external view returns (uint256); - /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool + /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the + /// pool /// @dev This value can overflow the uint256 function feeGrowthGlobal1X128() external view returns (uint256); @@ -55,9 +57,11 @@ interface IUniswapV3PoolState { /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0, /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1, /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick - /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick, + /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current + /// tick, /// secondsOutside the seconds spent on the other side of the tick from the current tick, - /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false. + /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to + /// false. /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0. /// In addition, these values are only relative and must be used only in comparison to previous snapshots for /// a specific position. @@ -98,11 +102,14 @@ interface IUniswapV3PoolState { /// @notice Returns data about a specific observation index /// @param index The element of the observations array to fetch - /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time + /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of + /// time /// ago, rather than at a specific index in the array. /// @return blockTimestamp The timestamp of the observation, - /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp, - /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp, + /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation + /// timestamp, + /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the + /// observation timestamp, /// Returns initialized whether the observation has been initialized and the values are safe to use function observations(uint256 index) external diff --git a/src/utils/Arrays.sol b/src/utils/Arrays.sol index b5d48fd..a1a1305 100644 --- a/src/utils/Arrays.sol +++ b/src/utils/Arrays.sol @@ -2,7 +2,6 @@ // Thanks to ultrasecr.eth pragma solidity ^0.8.0; - library Arrays { function toArray(uint256 n) external pure returns (uint256[] memory arr) { arr = new uint[](1); @@ -13,4 +12,4 @@ library Arrays { arr = new address[](1); arr[0] = a; } -} \ No newline at end of file +} diff --git a/src/utils/FunctionCodec.sol b/src/utils/FunctionCodec.sol index 0c0bfab..9202204 100644 --- a/src/utils/FunctionCodec.sol +++ b/src/utils/FunctionCodec.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; + import { IERC20 } from "lib/erc3156pp/src/interfaces/IERC20.sol"; library FunctionCodec { @@ -12,7 +13,13 @@ library FunctionCodec { selector = bytes4(encoded << 160); } - function encodeFunction(function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) f) internal pure returns (bytes24) { + function encodeFunction( + function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) f + ) + internal + pure + returns (bytes24) + { return encodeParams(f.address, f.selector); } @@ -31,7 +38,11 @@ library FunctionCodec { } } - function decodeFunction(bytes24 encoded) internal pure returns (function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) f) { + function decodeFunction(bytes24 encoded) + internal + pure + returns (function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) f) + { (address contractAddr, bytes4 selector) = decodeParams(encoded); return decodeFunction(contractAddr, selector); } diff --git a/src/utils/RevertMsgExtractor.sol b/src/utils/RevertMsgExtractor.sol index 0447e8b..7e190a1 100644 --- a/src/utils/RevertMsgExtractor.sol +++ b/src/utils/RevertMsgExtractor.sol @@ -1,16 +1,13 @@ // SPDX-License-Identifier: MIT -// Taken from https://github.com/sushiswap/BoringSolidity/blob/441e51c0544cf2451e6116fe00515e71d7c42e2c/src/BoringBatchable.sol +// Taken from +// https://github.com/sushiswap/BoringSolidity/blob/441e51c0544cf2451e6116fe00515e71d7c42e2c/src/BoringBatchable.sol pragma solidity >=0.6.0; - library RevertMsgExtractor { /// @dev Helper function to extract a useful revert message from a failed call. /// If the returned data is malformed or not correctly abi encoded then this call can fail itself. - function getRevertMsg(bytes memory returnData) - internal pure - returns (string memory) - { + function getRevertMsg(bytes memory returnData) internal pure returns (string memory) { // If the _res length is less than 68, then the transaction failed silently (without a revert message) if (returnData.length < 68) return "Transaction reverted silently"; @@ -20,4 +17,4 @@ library RevertMsgExtractor { } return abi.decode(returnData, (string)); // All that remains is the revert string } -} \ No newline at end of file +} diff --git a/src/utils/TransferHelper.sol b/src/utils/TransferHelper.sol index 7604038..95c6084 100644 --- a/src/utils/TransferHelper.sol +++ b/src/utils/TransferHelper.sol @@ -14,12 +14,9 @@ library TransferHelper { /// @param asset The contract address of the asset which will be transferred /// @param to The recipient of the transfer /// @param value The value of the transfer - function safeTransfer( - IERC20 asset, - address to, - uint256 value - ) internal { - (bool success, bytes memory data) = address(asset).call(abi.encodeWithSelector(IERC20.transfer.selector, to, value)); + function safeTransfer(IERC20 asset, address to, uint256 value) internal { + (bool success, bytes memory data) = + address(asset).call(abi.encodeWithSelector(IERC20.transfer.selector, to, value)); if (!(success && (data.length == 0 || abi.decode(data, (bool))))) revert(RevertMsgExtractor.getRevertMsg(data)); } } diff --git a/test/BalancerWrapper.t.sol b/test/BalancerWrapper.t.sol index 027e3cb..01a76ef 100644 --- a/test/BalancerWrapper.t.sol +++ b/test/BalancerWrapper.t.sol @@ -9,7 +9,6 @@ import { IFlashLoaner } from "../src/balancer/interfaces/IFlashLoaner.sol"; import { FlashBorrower } from "../src/test/FlashBorrower.sol"; import { IERC20, BalancerWrapper } from "../src/balancer/BalancerWrapper.sol"; - /// @dev If this is your first time with Forge, read this tutorial in the Foundry Book: /// https://book.getfoundry.sh/forge/writing-tests contract BalancerWrapperTest is PRBTest, StdCheats { @@ -48,7 +47,7 @@ contract BalancerWrapperTest is PRBTest, StdCheats { uint256 fee = wrapper.flashFee(dai, loan); dai.transfer(address(borrower), fee); bytes memory result = borrower.flashBorrow(dai, loan); - + // Test the return values (bytes32 callbackReturn) = abi.decode(result, (bytes32)); assertEq(uint256(callbackReturn), uint256(borrower.ERC3156PP_CALLBACK_SUCCESS()), "Callback failed"); @@ -57,7 +56,8 @@ contract BalancerWrapperTest is PRBTest, StdCheats { assertEq(borrower.flashInitiator(), address(borrower)); assertEq(address(borrower.flashAsset()), address(dai)); assertEq(borrower.flashAmount(), loan); - assertEq(borrower.flashBalance(), loan + fee); // The amount we transferred to pay for fees, plus the amount we borrowed + assertEq(borrower.flashBalance(), loan + fee); // The amount we transferred to pay for fees, plus the amount we + // borrowed assertEq(borrower.flashFee(), fee); } } diff --git a/test/DYDXWrapper.t.sol b/test/DYDXWrapper.t.sol index c6d2bd4..809d24e 100644 --- a/test/DYDXWrapper.t.sol +++ b/test/DYDXWrapper.t.sol @@ -9,7 +9,6 @@ import { FlashBorrower } from "../src/test/FlashBorrower.sol"; import { IERC20, DYDXWrapper } from "../src/dydx/DYDXWrapper.sol"; import { SoloMarginLike } from "../src/dydx/interfaces/SoloMarginLike.sol"; - /// @dev If this is your first time with Forge, read this tutorial in the Foundry Book: /// https://book.getfoundry.sh/forge/writing-tests contract ERC3156WrapperTest is PRBTest, StdCheats { @@ -48,7 +47,7 @@ contract ERC3156WrapperTest is PRBTest, StdCheats { uint256 fee = wrapper.flashFee(dai, loan); dai.transfer(address(borrower), fee); bytes memory result = borrower.flashBorrow(dai, loan); - + // Test the return values (bytes32 callbackReturn) = abi.decode(result, (bytes32)); assertEq(uint256(callbackReturn), uint256(borrower.ERC3156PP_CALLBACK_SUCCESS()), "Callback failed"); @@ -57,7 +56,8 @@ contract ERC3156WrapperTest is PRBTest, StdCheats { assertEq(borrower.flashInitiator(), address(borrower)); assertEq(address(borrower.flashAsset()), address(dai)); assertEq(borrower.flashAmount(), loan); - assertEq(borrower.flashBalance(), loan + fee); // The amount we transferred to pay for fees, plus the amount we borrowed + assertEq(borrower.flashBalance(), loan + fee); // The amount we transferred to pay for fees, plus the amount we + // borrowed assertEq(borrower.flashFee(), fee); } } diff --git a/test/ERC3156Wrapper.t.sol b/test/ERC3156Wrapper.t.sol index 5e1012f..c847808 100644 --- a/test/ERC3156Wrapper.t.sol +++ b/test/ERC3156Wrapper.t.sol @@ -9,7 +9,6 @@ import { IERC3156FlashLender } from "lib/erc3156/contracts/interfaces/IERC3156Fl import { FlashBorrower } from "../src/test/FlashBorrower.sol"; import { IERC20, ERC3156Wrapper } from "../src/erc3156/ERC3156Wrapper.sol"; - /// @dev If this is your first time with Forge, read this tutorial in the Foundry Book: /// https://book.getfoundry.sh/forge/writing-tests contract ERC3156WrapperTest is PRBTest, StdCheats { @@ -52,7 +51,7 @@ contract ERC3156WrapperTest is PRBTest, StdCheats { uint256 fee = wrapper.flashFee(dai, loan); dai.transfer(address(borrower), fee); bytes memory result = borrower.flashBorrow(dai, loan); - + // Test the return values (bytes32 callbackReturn) = abi.decode(result, (bytes32)); assertEq(uint256(callbackReturn), uint256(borrower.ERC3156PP_CALLBACK_SUCCESS()), "Callback failed"); @@ -61,7 +60,8 @@ contract ERC3156WrapperTest is PRBTest, StdCheats { assertEq(borrower.flashInitiator(), address(borrower)); assertEq(address(borrower.flashAsset()), address(dai)); assertEq(borrower.flashAmount(), loan); - assertEq(borrower.flashBalance(), loan + fee); // The amount we transferred to pay for fees, plus the amount we borrowed + assertEq(borrower.flashBalance(), loan + fee); // The amount we transferred to pay for fees, plus the amount we + // borrowed assertEq(borrower.flashFee(), fee); } } diff --git a/test/UniswapV3Wrapper.t.sol b/test/UniswapV3Wrapper.t.sol index 853add7..8824ab7 100644 --- a/test/UniswapV3Wrapper.t.sol +++ b/test/UniswapV3Wrapper.t.sol @@ -9,7 +9,6 @@ import { FlashBorrower } from "../src/test/FlashBorrower.sol"; import { IERC20, UniswapV3Wrapper } from "../src/uniswapV3/UniswapV3Wrapper.sol"; import { IUniswapV3Factory } from "../src/uniswapV3/interfaces/IUniswapV3Factory.sol"; - /// @dev If this is your first time with Forge, read this tutorial in the Foundry Book: /// https://book.getfoundry.sh/forge/writing-tests contract UniswapV3WrapperTest is PRBTest, StdCheats { @@ -40,7 +39,7 @@ contract UniswapV3WrapperTest is PRBTest, StdCheats { /// @dev Basic test. Run it with `forge test -vvv` to see the console log. function test_flashFee() external { console2.log("test_flashFee"); - assertEq(wrapper.flashFee(dai, 1e18), 3018081325219389, "Fee not exact"); + assertEq(wrapper.flashFee(dai, 1e18), 3_018_081_325_219_389, "Fee not exact"); assertEq(wrapper.flashFee(dai, type(uint256).max), type(uint256).max, "Fee not max"); } @@ -50,7 +49,7 @@ contract UniswapV3WrapperTest is PRBTest, StdCheats { uint256 fee = wrapper.flashFee(dai, loan); dai.transfer(address(borrower), fee); bytes memory result = borrower.flashBorrow(dai, loan); - + // Test the return values (bytes32 callbackReturn) = abi.decode(result, (bytes32)); assertEq(uint256(callbackReturn), uint256(borrower.ERC3156PP_CALLBACK_SUCCESS()), "Callback failed"); @@ -59,7 +58,8 @@ contract UniswapV3WrapperTest is PRBTest, StdCheats { assertEq(borrower.flashInitiator(), address(borrower)); assertEq(address(borrower.flashAsset()), address(dai)); assertEq(borrower.flashAmount(), loan); - assertEq(borrower.flashBalance(), loan + fee); // The amount we transferred to pay for fees, plus the amount we borrowed + assertEq(borrower.flashBalance(), loan + fee); // The amount we transferred to pay for fees, plus the amount we + // borrowed assertEq(borrower.flashFee(), fee); } } diff --git a/test/utils/FunctionCodec.t.sol b/test/utils/FunctionCodec.t.sol index b751992..01278b8 100644 --- a/test/utils/FunctionCodec.t.sol +++ b/test/utils/FunctionCodec.t.sol @@ -8,9 +8,20 @@ import { StdCheats } from "forge-std/StdCheats.sol"; import "src/utils/FunctionCodec.sol"; contract FunctionCodecTest is PRBTest, StdCheats { - function mockCallback(address, address, IERC20, uint256, uint256, bytes memory) external pure returns(bytes memory) { + function mockCallback( + address, + address, + IERC20, + uint256, + uint256, + bytes memory + ) + external + pure + returns (bytes memory) + { return "Hello, world!"; - } + } function test_encodeParams() public { assertEq( @@ -32,7 +43,8 @@ contract FunctionCodecTest is PRBTest, StdCheats { } function test_decodeFunction() public { - function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) f = FunctionCodec.decodeFunction(address(this), this.mockCallback.selector); + function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) f = + FunctionCodec.decodeFunction(address(this), this.mockCallback.selector); address a = address(1); IERC20 i = IERC20(a); @@ -43,7 +55,8 @@ contract FunctionCodecTest is PRBTest, StdCheats { function test_decodeFunction2() public { bytes24 encoded = FunctionCodec.encodeFunction(this.mockCallback); - function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) f = FunctionCodec.decodeFunction(encoded); + function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) f = + FunctionCodec.decodeFunction(encoded); address a = address(1); IERC20 i = IERC20(a); @@ -51,4 +64,4 @@ contract FunctionCodecTest is PRBTest, StdCheats { bytes memory b = "1"; assertEq(f(a, a, i, u, u, b), this.mockCallback(a, a, i, u, u, b)); } -} \ No newline at end of file +}