Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
SparkEthereum_20250501
Compiler Version
v0.8.25+commit.b61c2a91
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.25;
import { Ethereum } from 'spark-address-registry/Ethereum.sol';
import { ICapAutomator } from "sparklend-cap-automator/interfaces/ICapAutomator.sol";
import { SparkPayloadEthereum } from "../../SparkPayloadEthereum.sol";
/**
* @title May 1, 2025 Spark Ethereum Proposal
* @notice Spark Liquidity Layer:
* - Onboard SparkLend USDT
* - Onboard AAVE Core USDT
* SparkLend:
* - Update DAI IRM
* - Update USDS IRM
* - Update USDC IRM
* - Update USDT IRM
* - Adjust USDT Cap Automator Parameters
* @author Phoenix Labs
* Forum: https://forum.sky.money/t/may-1-2025-proposed-changes-to-spark-for-upcoming-spell/26288
* Vote: https://vote.makerdao.com/polling/QmfJ5yDF
* https://vote.makerdao.com/polling/QmQM99z5
* https://vote.makerdao.com/polling/Qmdc28Ag
* https://vote.makerdao.com/polling/QmeNB8S1
* https://vote.makerdao.com/polling/Qmee2jez
* https://vote.makerdao.com/polling/QmfBmrxq
* https://vote.makerdao.com/polling/QmZ2vydY
*/
contract SparkEthereum_20250501 is SparkPayloadEthereum {
address constant DAI_USDS_IRM = 0x7729E1CE24d7c4A82e76b4A2c118E328C35E6566; // DAI and USDS use the same params, same IRM
address constant USDC_USDT_IRM = 0x7F2fc6A7E3b3c658A84999b26ad2013C4Dc87061; // USDC and USDT use the same params, same IRM
address constant AAVE_CORE_AUSDT = 0x23878914EFE38d27C4D67Ab83ed1b93A74D4086a;
function _postExecute() internal override {
LISTING_ENGINE.POOL_CONFIGURATOR().setReserveInterestRateStrategyAddress(Ethereum.DAI, DAI_USDS_IRM);
LISTING_ENGINE.POOL_CONFIGURATOR().setReserveInterestRateStrategyAddress(Ethereum.USDS, DAI_USDS_IRM);
LISTING_ENGINE.POOL_CONFIGURATOR().setReserveInterestRateStrategyAddress(Ethereum.USDC, USDC_USDT_IRM);
LISTING_ENGINE.POOL_CONFIGURATOR().setReserveInterestRateStrategyAddress(Ethereum.USDT, USDC_USDT_IRM);
_onboardAaveToken(Ethereum.USDT_ATOKEN, 100_000_000e6, uint256(50_000_000e6) / 1 days);
_onboardAaveToken(AAVE_CORE_AUSDT, 50_000_000e6, uint256(25_000_000e6) / 1 days);
ICapAutomator capAutomator = ICapAutomator(Ethereum.CAP_AUTOMATOR);
capAutomator.setSupplyCapConfig({ asset: Ethereum.USDT, max: 500_000_000, gap: 100_000_000, increaseCooldown: 12 hours });
capAutomator.setBorrowCapConfig({ asset: Ethereum.USDT, max: 450_000_000, gap: 50_000_000, increaseCooldown: 12 hours });
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity >=0.8.0;
library Ethereum {
/******************************************************************************************************************/
/*** Token Addresses ***/
/******************************************************************************************************************/
address internal constant CBBTC = 0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf;
address internal constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address internal constant EZETH = 0xbf5495Efe5DB9ce00f80364C8B423567e58d2110;
address internal constant GNO = 0x6810e776880C02933D47DB1b9fc05908e5386b96;
address internal constant LBTC = 0x8236a87084f8B84306f72007F36F2618A5634494;
address internal constant MKR = 0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2;
address internal constant RETH = 0xae78736Cd615f374D3085123A210448E74Fc6393;
address internal constant RSETH = 0xA1290d69c65A6Fe4DF752f95823fae25cB99e5A7;
address internal constant SDAI = 0x83F20F44975D03b1b09e64809B757c47f942BEeA;
address internal constant SUSDC = 0xBc65ad17c5C0a2A4D159fa5a503f4992c7B545FE;
address internal constant SUSDE = 0x9D39A5DE30e57443BfF2A8307A4256c8797A3497;
address internal constant SUSDS = 0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD;
address internal constant TBTC = 0x18084fbA666a33d37592fA2633fD49a74DD93a88;
address internal constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
address internal constant USDE = 0x4c9EDD5852cd905f086C759E8383e09bff1E68B3;
address internal constant USDS = 0xdC035D45d973E3EC169d2276DDab16f1e407384F;
address internal constant USCC = 0x14d60E7FDC0D71d8611742720E4C50E7a974020c;
address internal constant USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
address internal constant USTB = 0x43415eB6ff9DB7E26A15b704e7A3eDCe97d31C4e;
address internal constant WBTC = 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599;
address internal constant WEETH = 0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee;
address internal constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address internal constant WSTETH = 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0;
/******************************************************************************************************************/
/*** MakerDAO Addresses ***/
/******************************************************************************************************************/
address internal constant CHIEF = 0x0a3f6849f78076aefaDf113F5BED87720274dDC0;
address internal constant DAI_USDS = 0x3225737a9Bbb6473CB4a45b7244ACa2BeFdB276A;
address internal constant PAUSE_PROXY = 0xBE8E3e3618f7474F8cB1d074A26afFef007E98FB;
address internal constant POT = 0x197E90f9FAD81970bA7976f33CbD77088E5D7cf7;
address internal constant PSM = 0xf6e72Db5454dd049d0788e411b06CfAF16853042; // Lite PSM
address internal constant VAT = 0x35D1b3F3D7966A1DFe207aa4514C12a259A0492B;
/******************************************************************************************************************/
/*** SparkDAO Addresses ***/
/******************************************************************************************************************/
address internal constant SPARK_PROXY = 0x3300f198988e4C9C63F75dF86De36421f06af8c4;
address internal constant SPARK_REWARDS = 0xbaf21A27622Db71041Bd336a573DDEdC8eB65122;
/******************************************************************************************************************/
/*** Allocation System Addresses ***/
/******************************************************************************************************************/
address internal constant ALLOCATOR_BUFFER = 0xc395D150e71378B47A1b8E9de0c1a83b75a08324;
address internal constant ALLOCATOR_ORACLE = 0xc7B91C401C02B73CBdF424dFaaa60950d5040dB7;
address internal constant ALLOCATOR_REGISTRY = 0xCdCFA95343DA7821fdD01dc4d0AeDA958051bB3B;
address internal constant ALLOCATOR_ROLES = 0x9A865A710399cea85dbD9144b7a09C889e94E803;
address internal constant ALLOCATOR_VAULT = 0x691a6c29e9e96dd897718305427Ad5D534db16BA;
/******************************************************************************************************************/
/*** Spark Liquidity Layer Addresses ***/
/******************************************************************************************************************/
address internal constant ALM_CONTROLLER = 0xF8Dff673b555a225e149218C5005FC88f4a13870;
address internal constant ALM_PROXY = 0x1601843c5E9bC251A3272907010AFa41Fa18347E;
address internal constant ALM_RATE_LIMITS = 0x7A5FD5cf045e010e62147F065cEAe59e5344b188;
address internal constant ALM_FREEZER = 0x90D8c80C028B4C09C0d8dcAab9bbB057F0513431;
address internal constant ALM_RELAYER = 0x8a25A24EDE9482C4Fc0738F99611BE58F1c839AB;
address internal constant ALM_RELAYER2 = 0x8Cc0Cb0cfB6B7e548cfd395B833c05C346534795;
/******************************************************************************************************************/
/*** Ethena Addresses ***/
/******************************************************************************************************************/
address internal constant ETHENA_MINTER = 0xe3490297a08d6fC8Da46Edb7B6142E4F461b62D3;
/******************************************************************************************************************/
/*** Aave Addresses ***/
/******************************************************************************************************************/
address internal constant ATOKEN_CORE_USDS = 0x32a6268f9Ba3642Dda7892aDd74f1D34469A4259;
address internal constant ATOKEN_CORE_USDC = 0x98C23E9d8f34FEFb1B7BD6a91B7FF122F4e16F5c;
/******************************************************************************************************************/
/*** Blackrock BUIDL Addresses ***/
/******************************************************************************************************************/
address internal constant BUIDL = 0x7712c34205737192402172409a8F7ccef8aA2AEc;
address internal constant BUIDL_REDEEM = 0x31D3F59Ad4aAC0eeE2247c65EBE8Bf6E9E470a53; // Circle redeem
address internal constant BUIDLI = 0x6a9DA2D710BB9B700acde7Cb81F10F1fF8C89041;
address internal constant BUIDLI_DEPOSIT = 0xD1917664bE3FdAea377f6E8D5BF043ab5C3b1312;
address internal constant BUIDLI_REDEEM = 0x8780Dd016171B91E4Df47075dA0a947959C34200; // Offchain redeem
/******************************************************************************************************************/
/*** Centrifuge Addresses ***/
/******************************************************************************************************************/
address internal constant JTRSY = 0x8c213ee79581Ff4984583C6a801e5263418C4b86;
address internal constant JTRSY_VAULT = 0x36036fFd9B1C6966ab23209E073c68Eb9A992f50;
/******************************************************************************************************************/
/*** Curve Addresses ***/
/******************************************************************************************************************/
address internal constant CURVE_SUSDSUSDT = 0x00836Fe54625BE242BcFA286207795405ca4fD10;
address internal constant CURVE_USDCUSDT = 0x4f493B7dE8aAC7d55F71853688b1F7C8F0243C85;
/******************************************************************************************************************/
/*** Fluid Addresses ***/
/******************************************************************************************************************/
address internal constant FLUID_SUSDS = 0x2BBE31d63E6813E3AC858C04dae43FB2a72B0D11;
/******************************************************************************************************************/
/*** Maple Addresses ***/
/******************************************************************************************************************/
address internal constant SYRUP_USDC = 0x80ac24aA929eaF5013f6436cdA2a7ba190f5Cc0b;
/******************************************************************************************************************/
/*** Morpho Addresses ***/
/******************************************************************************************************************/
address internal constant MORPHO = 0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb;
address internal constant MORPHO_DEFAULT_IRM = 0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC;
address internal constant MORPHO_SUSDE_ORACLE = 0x5D916980D5Ae1737a8330Bf24dF812b2911Aae25;
address internal constant MORPHO_USDE_ORACLE = 0xaE4750d0813B5E37A51f7629beedd72AF1f9cA35;
address internal constant MORPHO_VAULT_DAI_1 = 0x73e65DBD630f90604062f6E02fAb9138e713edD9;
/******************************************************************************************************************/
/*** Superstate Addresses ***/
/******************************************************************************************************************/
address internal constant SUPERSTATE_REDEMPTION = 0x4c21B7577C8FE8b0B0669165ee7C8f67fa1454Cf;
/******************************************************************************************************************/
/*** SparkLend - Core Protocol Addresses ***/
/******************************************************************************************************************/
address internal constant AAVE_ORACLE = 0x8105f69D9C41644c6A0803fDA7D03Aa70996cFD9;
address internal constant ACL_MANAGER = 0xdA135Cd78A086025BcdC87B038a1C462032b510C;
address internal constant DAI_TREASURY = 0x856900aa78e856a5df1a2665eE3a66b2487cD68f;
address internal constant EMISSION_MANAGER = 0xf09e48dd4CA8e76F63a57ADd428bB06fee7932a4;
address internal constant INCENTIVES = 0x4370D3b6C9588E02ce9D22e684387859c7Ff5b34;
address internal constant POOL = 0xC13e21B648A5Ee794902342038FF3aDAB66BE987;
address internal constant POOL_ADDRESSES_PROVIDER = 0x02C3eA4e34C0cBd694D2adFa2c690EECbC1793eE;
address internal constant POOL_ADDRESSES_PROVIDER_REGISTRY = 0x03cFa0C4622FF84E50E75062683F44c9587e6Cc1;
address internal constant POOL_CONFIGURATOR = 0x542DBa469bdE58FAeE189ffB60C6b49CE60E0738;
address internal constant TREASURY = 0xb137E7d16564c81ae2b0C8ee6B55De81dd46ECe5;
address internal constant TREASURY_CONTROLLER = 0x92eF091C5a1E01b3CE1ba0D0150C84412d818F7a;
address internal constant WETH_GATEWAY = 0xBD7D6a9ad7865463DE44B05F04559f65e3B11704;
/******************************************************************************************************************/
/*** SparkLend - Reserve Token Addresses ***/
/******************************************************************************************************************/
address internal constant CBBTC_ATOKEN = 0xb3973D459df38ae57797811F2A1fd061DA1BC123;
address internal constant CBBTC_STABLE_DEBT_TOKEN = 0x26a76E2fa1EaDbe7C30f0c333059Bcc3642c28d2;
address internal constant CBBTC_DEBT_TOKEN = 0x661fE667D2103eb52d3632a3eB2cAbd123F27938;
address internal constant DAI_ATOKEN = 0x4DEDf26112B3Ec8eC46e7E31EA5e123490B05B8B;
address internal constant DAI_STABLE_DEBT_TOKEN = 0xfe2B7a7F4cC0Fb76f7Fc1C6518D586F1e4559176;
address internal constant DAI_DEBT_TOKEN = 0xf705d2B7e92B3F38e6ae7afaDAA2fEE110fE5914;
address internal constant GNO_ATOKEN = 0x7b481aCC9fDADDc9af2cBEA1Ff2342CB1733E50F;
address internal constant GNO_STABLE_DEBT_TOKEN = 0xbf13910620722D4D4F8A03962894EB3335Bf4FaE;
address internal constant GNO_DEBT_TOKEN = 0x57a2957651DA467fCD4104D749f2F3684784c25a;
address internal constant RETH_ATOKEN = 0x9985dF20D7e9103ECBCeb16a84956434B6f06ae8;
address internal constant RETH_STABLE_DEBT_TOKEN = 0xa9a4037295Ea3a168DC3F65fE69FdA524d52b3e1;
address internal constant RETH_DEBT_TOKEN = 0xBa2C8F2eA5B56690bFb8b709438F049e5Dd76B96;
address internal constant SDAI_ATOKEN = 0x78f897F0fE2d3B5690EbAe7f19862DEacedF10a7;
address internal constant SDAI_STABLE_DEBT_TOKEN = 0xEc6C6aBEd4DC03299EFf82Ac8A0A83643d3cB335;
address internal constant SDAI_DEBT_TOKEN = 0xaBc57081C04D921388240393ec4088Aa47c6832B;
address internal constant USDC_ATOKEN = 0x377C3bd93f2a2984E1E7bE6A5C22c525eD4A4815;
address internal constant USDC_STABLE_DEBT_TOKEN = 0x887Ac022983Ff083AEb623923789052A955C6798;
address internal constant USDC_DEBT_TOKEN = 0x7B70D04099CB9cfb1Db7B6820baDAfB4C5C70A67;
address internal constant USDT_ATOKEN = 0xe7dF13b8e3d6740fe17CBE928C7334243d86c92f;
address internal constant USDT_STABLE_DEBT_TOKEN = 0x0Dae62F953Ceb2E969fB4dE85f3F9074fa920776;
address internal constant USDT_DEBT_TOKEN = 0x529b6158d1D2992E3129F7C69E81a7c677dc3B12;
address internal constant WBTC_ATOKEN = 0x4197ba364AE6698015AE5c1468f54087602715b2;
address internal constant WBTC_STABLE_DEBT_TOKEN = 0x4b29e6cBeE62935CfC92efcB3839eD2c2F35C1d9;
address internal constant WBTC_DEBT_TOKEN = 0xf6fEe3A8aC8040C3d6d81d9A4a168516Ec9B51D2;
address internal constant WEETH_ATOKEN = 0x3CFd5C0D4acAA8Faee335842e4f31159fc76B008;
address internal constant WEETH_STABLE_DEBT_TOKEN = 0x5B1F8aF3E6C0BF4d20e8e5220a4e4A3A8fA6Dc0A;
address internal constant WEETH_DEBT_TOKEN = 0xc2bD6d2fEe70A0A73a33795BdbeE0368AeF5c766;
address internal constant WETH_ATOKEN = 0x59cD1C87501baa753d0B5B5Ab5D8416A45cD71DB;
address internal constant WETH_STABLE_DEBT_TOKEN = 0x3c6b93D38ffA15ea995D1BC950d5D0Fa6b22bD05;
address internal constant WETH_DEBT_TOKEN = 0x2e7576042566f8D6990e07A1B61Ad1efd86Ae70d;
address internal constant WSTETH_ATOKEN = 0x12B54025C112Aa61fAce2CDB7118740875A566E9;
address internal constant WSTETH_STABLE_DEBT_TOKEN = 0x9832D969a0c8662D98fFf334A4ba7FeE62b109C2;
address internal constant WSTETH_DEBT_TOKEN = 0xd5c3E3B566a42A6110513Ac7670C1a86D76E13E6;
/******************************************************************************************************************/
/*** SparkLend - Auxiliary Protocol Addresses ***/
/******************************************************************************************************************/
address internal constant CAP_AUTOMATOR = 0x2276f52afba7Cf2525fd0a050DF464AC8532d0ef;
address internal constant FREEZER_MOM = 0x237e3985dD7E373F2ec878EC1Ac48A228Cf2e7a3;
address internal constant KILL_SWITCH_ORACLE = 0x909A86f78e1cdEd68F9c2Fe2c9CD922c401abe82;
/******************************************************************************************************************/
/*** SparkLend - Emergency Spells ***/
/******************************************************************************************************************/
address internal constant SPELL_FREEZE_ALL = 0x9e2890BF7f8D5568Cc9e5092E67Ba00C8dA3E97f;
address internal constant SPELL_FREEZE_DAI = 0xa2039bef2c5803d66E4e68F9E23a942E350b938c;
address internal constant SPELL_PAUSE_ALL = 0x425b0de240b4c2DC45979DB782A355D090Dc4d37;
address internal constant SPELL_PAUSE_DAI = 0xCacB88e39112B56278db25b423441248cfF94241;
address internal constant SPELL_REMOVE_MULTISIG = 0xE47AB4919F6F5459Dcbbfbe4264BD4630c0169A9;
/******************************************************************************************************************/
/*** SparkLend - Implementation Addresses ***/
/******************************************************************************************************************/
address internal constant A_TOKEN_IMPL = 0x6175ddEc3B9b38c88157C10A01ed4A3fa8639cC6;
address internal constant DAI_TREASURY_IMPL = 0xF1E57711Eb5F897b415de1aEFCB64d9BAe58D312;
address internal constant INCENTIVES_IMPL = 0x0ee554F6A1f7a4Cb4f82D4C124DdC2AD3E37fde1;
address internal constant POOL_CONFIGURATOR_IMPL = 0xF7b656C95420194b79687fc86D965FB51DA4799F;
address internal constant POOL_IMPL = 0x5aE329203E00f76891094DcfedD5Aca082a50e1b;
address internal constant STABLE_DEBT_TOKEN_IMPL = 0x026a5B6114431d8F3eF2fA0E1B2EDdDccA9c540E;
address internal constant TREASURY_IMPL = 0xF1E57711Eb5F897b415de1aEFCB64d9BAe58D312;
address internal constant VARIABLE_DEBT_TOKEN_IMPL = 0x86C71796CcDB31c3997F8Ec5C2E3dB3e9e40b985;
/******************************************************************************************************************/
/*** SparkLend - Config Engine Addresses ***/
/******************************************************************************************************************/
address internal constant CONFIG_ENGINE = 0x3254F7cd0565aA67eEdC86c2fB608BE48d5cCd78;
address internal constant PROXY_ADMIN = 0x883A82BDd3d07ae6ACfD151020faD350df25087e;
address internal constant RATES_FACTORY = 0xfE57e187EF6285e90d7049e6a21571aa47cF11a2;
address internal constant TRANSPARENT_PROXY_FACTORY = 0x777803CbDD89D5D5Bc1DdD2151B51b0B07F6bf37;
/******************************************************************************************************************/
/*** SparkLend - Data Provider Addresses ***/
/******************************************************************************************************************/
address internal constant PROTOCOL_DATA_PROVIDER = 0xFc21d6d146E6086B8359705C8b28512a983db0cb;
address internal constant UI_INCENTIVE_DATA_PROVIDER = 0xA7F8A757C4f7696c015B595F51B2901AC0121B18;
address internal constant UI_POOL_DATA_PROVIDER = 0xF028c2F4b19898718fD0F77b9b881CbfdAa5e8Bb;
address internal constant WALLET_BALANCE_PROVIDER = 0xd2AeF86F51F92E8e49F42454c287AE4879D1BeDc;
/******************************************************************************************************************/
/*** SparkLend - Library Addresses ***/
/******************************************************************************************************************/
address internal constant BORROW_LOGIC = 0x4662C88C542F0954F8CccCDE4542eEc32d7E7e9a;
address internal constant BRIDGE_LOGIC = 0x2C54924711E479E639032704146b865E12f0C6D1;
address internal constant EMODE_LOGIC = 0x2Ad00613A66D71Ff2B0607fB3C4632C47a50DADe;
address internal constant FLASH_LOAN_LOGIC = 0x7f44e1c1dE70059D7cc483378BEFeE2a030CE247;
address internal constant LIQUIDATION_LOGIC = 0x6aEa92693C527bC2c7B3171C6f2598d67d619088;
address internal constant POOL_LOGIC = 0x1761a0f74032963B6Ad0774C5EBF4586c0bD7604;
address internal constant SUPPLY_LOGIC = 0x46256841e36b7557BB8e4c706beD38b17A9EB2c1;
/******************************************************************************************************************/
/*** Cross-Domain Addresses ***/
/******************************************************************************************************************/
address internal constant CCTP_TOKEN_MESSENGER = 0xBd3fa81B58Ba92a82136038B25aDec7066af3155;
address internal constant OPTIMISM_DSR_FORWARDER = 0x4042127DecC0cF7cc0966791abebf7F76294DeF3;
address internal constant WORLD_CHAIN_DSR_FORWARDER = 0xA34437dAAE56A7CC6DC757048933D7777b3e547B;
/******************************************************************************************************************/
/*** Arbitrum Addresses ***/
/******************************************************************************************************************/
address internal constant ARBITRUM_DSR_FORWARDER = 0x7F36E7F562Ee3f320644F6031e03E12a02B85799;
address internal constant ARBITRUM_SSR_FORWARDER = 0x1A229AdbAC83A948226783F2A3257B52006247D5;
address internal constant ARBITRUM_ESCROW = 0xA10c7CE4b876998858b1a9E12b10092229539400;
address internal constant ARBITRUM_SKY_GOV_RELAY = 0x9ba25c289e351779E0D481Ba37489317c34A899d;
address internal constant ARBITRUM_TOKEN_BRIDGE = 0x84b9700E28B23F873b82c1BEb23d86C091b6079E;
/******************************************************************************************************************/
/*** Base Addresses ***/
/******************************************************************************************************************/
address internal constant BASE_DSR_FORWARDER = 0x8Ed551D485701fe489c215E13E42F6fc59563e0e;
address internal constant BASE_SSR_FORWARDER = 0xB2833392527f41262eB0E3C7b47AFbe030ef188E;
address internal constant BASE_ESCROW = 0x7F311a4D48377030bD810395f4CCfC03bdbe9Ef3;
address internal constant BASE_SKY_GOV_RELAY = 0x1Ee0AE8A993F2f5abDB51EAF4AC2876202b65c3b;
address internal constant BASE_TOKEN_BRIDGE = 0xA5874756416Fa632257eEA380CAbd2E87cED352A;
/******************************************************************************************************************/
/*** Multisigs ***/
/******************************************************************************************************************/
address internal constant FREEZER_MULTISIG = 0x44efFc473e81632B12486866AA1678edbb7BEeC3;
address internal constant SPARKLEND_REWARDS_MULTISIG = 0x8076807464DaC94Ac8Aa1f7aF31b58F73bD88A27;
address internal constant SPARK_REWARDS_MULTISIG = 0xF649956f43825d4d7295a50EDdBe1EDC814A3a83;
/******************************************************************************************************************/
/*** User Action Addresses ***/
/******************************************************************************************************************/
address internal constant USER_ACTIONS_PSM_VARIANT1 = 0x52d298Ff9e77E71C2EB1992260520E7b15257d99;
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.13;
import { IPool } from "aave-v3-core/contracts/interfaces/IPool.sol";
import { IPoolConfigurator } from "aave-v3-core/contracts/interfaces/IPoolConfigurator.sol";
interface ICapAutomator {
/**********************************************************************************************/
/*** Events ***/
/**********************************************************************************************/
/**
* @dev Event to log the setting of a new supply cap config.
* @param asset The address of the asset for which the config was set.
* @param max Maximum allowed supply cap.
* @param gap A gap between the supply and the supply cap that is being maintained.
* @param increaseCooldown A minimum period of time that needs to elapse between consequent cap increases.
*/
event SetSupplyCapConfig(address indexed asset, uint256 max, uint256 gap, uint256 increaseCooldown);
/**
* @dev Event to log the setting of a new borrow cap config.
* @param asset The address of the asset for which the config was set.
* @param max Maximum allowed borrow cap.
* @param gap A gap between the borrows and the borrow cap that is being maintained.
* @param increaseCooldown A minimum period of time that needs to elapse between consequent cap increases.
*/
event SetBorrowCapConfig(address indexed asset, uint256 max, uint256 gap, uint256 increaseCooldown);
/**
* @dev Event to log the removing of a supply cap config.
* @param asset The address of the asset for which supply config was removed.
*/
event RemoveSupplyCapConfig(address indexed asset);
/**
* @dev Event to log the removing of a borrow cap config.
* @param asset The address of the asset for which borrow config was removed.
*/
event RemoveBorrowCapConfig(address indexed asset);
/**
* @dev Event to log the update of the supply cap.
* @param asset The address of the asset which supply cap was updated.
* @param oldSupplyCap The old supply cap.
* @param newSupplyCap The newly set supply cap.
*/
event UpdateSupplyCap(address indexed asset, uint256 oldSupplyCap, uint256 newSupplyCap);
/**
* @dev Event to log the update of the borrow cap.
* @param asset The address of the asset which borrow cap was updated.
* @param oldBorrowCap The old borrow cap.
* @param newBorrowCap The newly set borrow cap.
*/
event UpdateBorrowCap(address indexed asset, uint256 oldBorrowCap, uint256 newBorrowCap);
/**********************************************************************************************/
/*** Storage Variables ***/
/**********************************************************************************************/
/**
* @dev Returns the address of the pool configurator.
* @return poolConfigurator The address of the pool configurator.
*/
function poolConfigurator() external view returns (IPoolConfigurator poolConfigurator);
/**
* @dev Returns the address of the data provider.
* @return pool The address of the data provider.
*/
function pool() external view returns (IPool pool);
/**
* @dev Returns current configuration for automatic supply cap management.
* @param asset The address of the asset which config is going to be returned.
* @return max Maximum allowed supply cap.
* @return gap A gap between the supply and the supply cap that is being maintained.
* @return increaseCooldown A minimum period of time that needs to elapse between consequent cap increases.
* @return lastUpdateBlock The block of the last cap update.
* @return lastIncreaseTime The timestamp of the last cap increase.
*/
function supplyCapConfigs(address asset) external view returns (
uint48 max,
uint48 gap,
uint48 increaseCooldown,
uint48 lastUpdateBlock,
uint48 lastIncreaseTime
);
/**
* @dev Returns current configuration for automatic borrow cap management.
* @param asset The address of the asset which config is going to be returned.
* @return max Maximum allowed borrow cap.
* @return gap A gap between the borrows and the borrow cap that is being maintained.
* @return increaseCooldown A minimum period of time that needs to elapse between consequent cap increases.
* @return lastUpdateBlock The block of the last cap update.
* @return lastIncreaseTime The timestamp of the last cap increase.
*/
function borrowCapConfigs(address asset) external view returns (
uint48 max,
uint48 gap,
uint48 increaseCooldown,
uint48 lastUpdateBlock,
uint48 lastIncreaseTime
);
/**********************************************************************************************/
/*** Owner Functions ***/
/**********************************************************************************************/
/**
* @dev Function creating (or re-setting) a configuration for automatic supply cap management.
* @param asset The address of the asset that is going to be managed.
* @param max Maximum allowed supply cap.
* @param gap A gap between the supply and the supply cap that is being maintained.
* @param increaseCooldown A minimum period of time that needs to elapse between consequent cap increases.
*/
function setSupplyCapConfig(
address asset,
uint256 max,
uint256 gap,
uint256 increaseCooldown
) external;
/**
* @dev Function creating (or re-setting) a configuration for automatic borrow cap management.
* @param asset The address of the asset that is going to be managed.
* @param max Maximum allowed borrow cap.
* @param gap A gap between the borrows and the borrow cap that is being maintained.
* @param increaseCooldown A minimum period of time that needs to elapse between consequent cap increases.
*/
function setBorrowCapConfig(
address asset,
uint256 max,
uint256 gap,
uint256 increaseCooldown
) external;
/**
* @dev Function removing a configuration for automatic supply cap management.
* @param asset The address of the asset for which the configuration is going to be removed.
*/
function removeSupplyCapConfig(address asset) external;
/**
* @dev Function removing a configuration for automatic borrow cap management.
* @param asset The address of the asset for which the configuration is going to be removed.
*/
function removeBorrowCapConfig(address asset) external;
/**********************************************************************************************/
/*** Public Functions ***/
/**********************************************************************************************/
/**
* @dev A public function that updates supply cap on market of a given asset.
* The supply cap is going to be set to the value equal
* to the sum of current supply and the supply cap gap.
* The cap is only going to be increased if the required cooldown time has passed.
* Calling this function more than once per block will not have any additional effect.
* @param asset The address of the asset which cap is going to be updated.
* @return newSupplyCap A newly set supply cap, or the old one if it was not updated.
*/
function execSupply(address asset) external returns (uint256 newSupplyCap);
/**
* @dev A public function that updates borrow cap on market of a given asset.
* The borrow cap is going to be set to the values equal
* to the sum of current borrows and the borrow cap gap.
* The caps is only going to be increased if the required cooldown time has passed.
* Calling this function more than once per block will not have any additional effect.
* @param asset The address of the asset which cap is going to be updated.
* @return newBorrowCap A newly set borrow cap, or the old one if it was not updated.
*/
function execBorrow(address asset) external returns (uint256 newBorrowCap);
/**
* @dev A public function that updates supply and borrow caps on market of a given asset.
* The supply and borrow caps are going to be set to, respectively, the values equal
* to the sum of current supply and the supply cap gap and the sum of current borrows and the borrow cap gap.
* The caps are only going to be increased if the required cooldown time has passed.
* Calling this function more than once per block will not have any additional effect.
* @param asset The address of the asset which caps are going to be updated.
* @return newSupplyCap A newly set supply cap, or the old one if it was not updated.
* @return newBorrowCap A newly set borrow cap, or the old one if it was not updated.
*/
function exec(address asset) external returns (uint256 newSupplyCap, uint256 newBorrowCap);
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import './AaveV3PayloadBase.sol';
import { Arbitrum } from 'spark-address-registry/Arbitrum.sol';
import { Base } from 'spark-address-registry/Base.sol';
import { Ethereum } from 'spark-address-registry/Ethereum.sol';
import { Gnosis } from 'spark-address-registry/Gnosis.sol';
import { IExecutor } from 'spark-gov-relay/src/interfaces/IExecutor.sol';
import { AMBForwarder } from "xchain-helpers/forwarders/AMBForwarder.sol";
import { ArbitrumForwarder } from "xchain-helpers/forwarders/ArbitrumForwarder.sol";
import { OptimismForwarder } from "xchain-helpers/forwarders/OptimismForwarder.sol";
import { SLLHelpers } from './libraries/SLLHelpers.sol';
/**
* @dev Base smart contract for Ethereum.
* @author Phoenix Labs
*/
abstract contract SparkPayloadEthereum is
AaveV3PayloadBase(IEngine(Ethereum.CONFIG_ENGINE))
{
// These need to be immutable (delegatecall) and can only be set in constructor
address public immutable PAYLOAD_ARBITRUM;
address public immutable PAYLOAD_BASE;
address public immutable PAYLOAD_GNOSIS;
function execute() public override {
super.execute();
if (PAYLOAD_ARBITRUM != address(0)) {
ArbitrumForwarder.sendMessageL1toL2({
l1CrossDomain: ArbitrumForwarder.L1_CROSS_DOMAIN_ARBITRUM_ONE,
target: Arbitrum.SPARK_RECEIVER,
message: _encodePayloadQueue(PAYLOAD_ARBITRUM),
gasLimit: 1_000_000,
maxFeePerGas: 50e9,
baseFee: block.basefee
});
}
if (PAYLOAD_BASE != address(0)) {
OptimismForwarder.sendMessageL1toL2({
l1CrossDomain: OptimismForwarder.L1_CROSS_DOMAIN_BASE,
target: Base.SPARK_RECEIVER,
message: _encodePayloadQueue(PAYLOAD_BASE),
gasLimit: 1_000_000
});
}
if (PAYLOAD_GNOSIS != address(0)) {
AMBForwarder.sendMessageEthereumToGnosisChain({
target: Gnosis.AMB_EXECUTOR,
message: _encodePayloadQueue(PAYLOAD_GNOSIS),
gasLimit: 1_000_000
});
}
}
function getPoolContext() public pure override returns (IEngine.PoolContext memory) {
return IEngine.PoolContext({networkName: 'Ethereum', networkAbbreviation: 'Eth'});
}
function _encodePayloadQueue(address _payload) internal pure returns (bytes memory) {
address[] memory targets = new address[](1);
uint256[] memory values = new uint256[](1);
string[] memory signatures = new string[](1);
bytes[] memory calldatas = new bytes[](1);
bool[] memory withDelegatecalls = new bool[](1);
targets[0] = _payload;
values[0] = 0;
signatures[0] = 'execute()';
calldatas[0] = '';
withDelegatecalls[0] = true;
return abi.encodeCall(IExecutor.queue, (
targets,
values,
signatures,
calldatas,
withDelegatecalls
));
}
function _upgradeController(address oldController, address newController) internal {
SLLHelpers.upgradeMainnetController(
oldController,
newController
);
}
function _onboardAaveToken(address token, uint256 depositMax, uint256 depositSlope) internal {
SLLHelpers.onboardAaveToken(
Ethereum.ALM_RATE_LIMITS,
token,
depositMax,
depositSlope
);
}
function _onboardERC4626Vault(address vault, uint256 depositMax, uint256 depositSlope) internal {
SLLHelpers.onboardERC4626Vault(
Ethereum.ALM_RATE_LIMITS,
vault,
depositMax,
depositSlope
);
}
function _onboardCurvePool(
address controller,
address pool,
uint256 maxSlippage,
uint256 swapMax,
uint256 swapSlope,
uint256 depositMax,
uint256 depositSlope,
uint256 withdrawMax,
uint256 withdrawSlope
) internal {
SLLHelpers.onboardCurvePool(
controller,
Ethereum.ALM_RATE_LIMITS,
pool,
maxSlippage,
swapMax,
swapSlope,
depositMax,
depositSlope,
withdrawMax,
withdrawSlope
);
}
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import {IPoolAddressesProvider} from './IPoolAddressesProvider.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
/**
* @title IPool
* @author Aave
* @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
);
/**
* @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;
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import {ConfiguratorInputTypes} from '../protocol/libraries/types/ConfiguratorInputTypes.sol';
/**
* @title IPoolConfigurator
* @author Aave
* @notice Defines the basic interface for a Pool configurator.
*/
interface IPoolConfigurator {
/**
* @dev Emitted when a reserve is initialized.
* @param asset The address of the underlying asset of the reserve
* @param aToken The address of the associated aToken contract
* @param stableDebtToken The address of the associated stable rate debt token
* @param variableDebtToken The address of the associated variable rate debt token
* @param interestRateStrategyAddress The address of the interest rate strategy for the reserve
*/
event ReserveInitialized(
address indexed asset,
address indexed aToken,
address stableDebtToken,
address variableDebtToken,
address interestRateStrategyAddress
);
/**
* @dev Emitted when borrowing is enabled or disabled on a reserve.
* @param asset The address of the underlying asset of the reserve
* @param enabled True if borrowing is enabled, false otherwise
*/
event ReserveBorrowing(address indexed asset, bool enabled);
/**
* @dev Emitted when flashloans are enabled or disabled on a reserve.
* @param asset The address of the underlying asset of the reserve
* @param enabled True if flashloans are enabled, false otherwise
*/
event ReserveFlashLoaning(address indexed asset, bool enabled);
/**
* @dev Emitted when the collateralization risk parameters for the specified asset are updated.
* @param asset The address of the underlying asset of the reserve
* @param ltv The loan to value of the asset when used as collateral
* @param liquidationThreshold The threshold at which loans using this asset as collateral will be considered undercollateralized
* @param liquidationBonus The bonus liquidators receive to liquidate this asset
*/
event CollateralConfigurationChanged(
address indexed asset,
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus
);
/**
* @dev Emitted when stable rate borrowing is enabled or disabled on a reserve
* @param asset The address of the underlying asset of the reserve
* @param enabled True if stable rate borrowing is enabled, false otherwise
*/
event ReserveStableRateBorrowing(address indexed asset, bool enabled);
/**
* @dev Emitted when a reserve is activated or deactivated
* @param asset The address of the underlying asset of the reserve
* @param active True if reserve is active, false otherwise
*/
event ReserveActive(address indexed asset, bool active);
/**
* @dev Emitted when a reserve is frozen or unfrozen
* @param asset The address of the underlying asset of the reserve
* @param frozen True if reserve is frozen, false otherwise
*/
event ReserveFrozen(address indexed asset, bool frozen);
/**
* @dev Emitted when a reserve is paused or unpaused
* @param asset The address of the underlying asset of the reserve
* @param paused True if reserve is paused, false otherwise
*/
event ReservePaused(address indexed asset, bool paused);
/**
* @dev Emitted when a reserve is dropped.
* @param asset The address of the underlying asset of the reserve
*/
event ReserveDropped(address indexed asset);
/**
* @dev Emitted when a reserve factor is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldReserveFactor The old reserve factor, expressed in bps
* @param newReserveFactor The new reserve factor, expressed in bps
*/
event ReserveFactorChanged(
address indexed asset,
uint256 oldReserveFactor,
uint256 newReserveFactor
);
/**
* @dev Emitted when the borrow cap of a reserve is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldBorrowCap The old borrow cap
* @param newBorrowCap The new borrow cap
*/
event BorrowCapChanged(address indexed asset, uint256 oldBorrowCap, uint256 newBorrowCap);
/**
* @dev Emitted when the supply cap of a reserve is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldSupplyCap The old supply cap
* @param newSupplyCap The new supply cap
*/
event SupplyCapChanged(address indexed asset, uint256 oldSupplyCap, uint256 newSupplyCap);
/**
* @dev Emitted when the liquidation protocol fee of a reserve is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldFee The old liquidation protocol fee, expressed in bps
* @param newFee The new liquidation protocol fee, expressed in bps
*/
event LiquidationProtocolFeeChanged(address indexed asset, uint256 oldFee, uint256 newFee);
/**
* @dev Emitted when the unbacked mint cap of a reserve is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldUnbackedMintCap The old unbacked mint cap
* @param newUnbackedMintCap The new unbacked mint cap
*/
event UnbackedMintCapChanged(
address indexed asset,
uint256 oldUnbackedMintCap,
uint256 newUnbackedMintCap
);
/**
* @dev Emitted when the category of an asset in eMode is changed.
* @param asset The address of the underlying asset of the reserve
* @param oldCategoryId The old eMode asset category
* @param newCategoryId The new eMode asset category
*/
event EModeAssetCategoryChanged(address indexed asset, uint8 oldCategoryId, uint8 newCategoryId);
/**
* @dev Emitted when a new eMode category is added.
* @param categoryId The new eMode category id
* @param ltv The ltv for the asset category in eMode
* @param liquidationThreshold The liquidationThreshold for the asset category in eMode
* @param liquidationBonus The liquidationBonus for the asset category in eMode
* @param oracle The optional address of the price oracle specific for this category
* @param label A human readable identifier for the category
*/
event EModeCategoryAdded(
uint8 indexed categoryId,
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus,
address oracle,
string label
);
/**
* @dev Emitted when a reserve interest strategy contract is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldStrategy The address of the old interest strategy contract
* @param newStrategy The address of the new interest strategy contract
*/
event ReserveInterestRateStrategyChanged(
address indexed asset,
address oldStrategy,
address newStrategy
);
/**
* @dev Emitted when an aToken implementation is upgraded.
* @param asset The address of the underlying asset of the reserve
* @param proxy The aToken proxy address
* @param implementation The new aToken implementation
*/
event ATokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/**
* @dev Emitted when the implementation of a stable debt token is upgraded.
* @param asset The address of the underlying asset of the reserve
* @param proxy The stable debt token proxy address
* @param implementation The new aToken implementation
*/
event StableDebtTokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/**
* @dev Emitted when the implementation of a variable debt token is upgraded.
* @param asset The address of the underlying asset of the reserve
* @param proxy The variable debt token proxy address
* @param implementation The new aToken implementation
*/
event VariableDebtTokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/**
* @dev Emitted when the debt ceiling of an asset is set.
* @param asset The address of the underlying asset of the reserve
* @param oldDebtCeiling The old debt ceiling
* @param newDebtCeiling The new debt ceiling
*/
event DebtCeilingChanged(address indexed asset, uint256 oldDebtCeiling, uint256 newDebtCeiling);
/**
* @dev Emitted when the the siloed borrowing state for an asset is changed.
* @param asset The address of the underlying asset of the reserve
* @param oldState The old siloed borrowing state
* @param newState The new siloed borrowing state
*/
event SiloedBorrowingChanged(address indexed asset, bool oldState, bool newState);
/**
* @dev Emitted when the bridge protocol fee is updated.
* @param oldBridgeProtocolFee The old protocol fee, expressed in bps
* @param newBridgeProtocolFee The new protocol fee, expressed in bps
*/
event BridgeProtocolFeeUpdated(uint256 oldBridgeProtocolFee, uint256 newBridgeProtocolFee);
/**
* @dev Emitted when the total premium on flashloans is updated.
* @param oldFlashloanPremiumTotal The old premium, expressed in bps
* @param newFlashloanPremiumTotal The new premium, expressed in bps
*/
event FlashloanPremiumTotalUpdated(
uint128 oldFlashloanPremiumTotal,
uint128 newFlashloanPremiumTotal
);
/**
* @dev Emitted when the part of the premium that goes to protocol is updated.
* @param oldFlashloanPremiumToProtocol The old premium, expressed in bps
* @param newFlashloanPremiumToProtocol The new premium, expressed in bps
*/
event FlashloanPremiumToProtocolUpdated(
uint128 oldFlashloanPremiumToProtocol,
uint128 newFlashloanPremiumToProtocol
);
/**
* @dev Emitted when the reserve is set as borrowable/non borrowable in isolation mode.
* @param asset The address of the underlying asset of the reserve
* @param borrowable True if the reserve is borrowable in isolation, false otherwise
*/
event BorrowableInIsolationChanged(address asset, bool borrowable);
/**
* @notice Initializes multiple reserves.
* @param input The array of initialization parameters
*/
function initReserves(ConfiguratorInputTypes.InitReserveInput[] calldata input) external;
/**
* @dev Updates the aToken implementation for the reserve.
* @param input The aToken update parameters
*/
function updateAToken(ConfiguratorInputTypes.UpdateATokenInput calldata input) external;
/**
* @notice Updates the stable debt token implementation for the reserve.
* @param input The stableDebtToken update parameters
*/
function updateStableDebtToken(
ConfiguratorInputTypes.UpdateDebtTokenInput calldata input
) external;
/**
* @notice Updates the variable debt token implementation for the asset.
* @param input The variableDebtToken update parameters
*/
function updateVariableDebtToken(
ConfiguratorInputTypes.UpdateDebtTokenInput calldata input
) external;
/**
* @notice Configures borrowing on a reserve.
* @dev Can only be disabled (set to false) if stable borrowing is disabled
* @param asset The address of the underlying asset of the reserve
* @param enabled True if borrowing needs to be enabled, false otherwise
*/
function setReserveBorrowing(address asset, bool enabled) external;
/**
* @notice Configures the reserve collateralization parameters.
* @dev All the values are expressed in bps. A value of 10000, results in 100.00%
* @dev The `liquidationBonus` is always above 100%. A value of 105% means the liquidator will receive a 5% bonus
* @param asset The address of the underlying asset of the reserve
* @param ltv The loan to value of the asset when used as collateral
* @param liquidationThreshold The threshold at which loans using this asset as collateral will be considered undercollateralized
* @param liquidationBonus The bonus liquidators receive to liquidate this asset
*/
function configureReserveAsCollateral(
address asset,
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus
) external;
/**
* @notice Enable or disable stable rate borrowing on a reserve.
* @dev Can only be enabled (set to true) if borrowing is enabled
* @param asset The address of the underlying asset of the reserve
* @param enabled True if stable rate borrowing needs to be enabled, false otherwise
*/
function setReserveStableRateBorrowing(address asset, bool enabled) external;
/**
* @notice Enable or disable flashloans on a reserve
* @param asset The address of the underlying asset of the reserve
* @param enabled True if flashloans need to be enabled, false otherwise
*/
function setReserveFlashLoaning(address asset, bool enabled) external;
/**
* @notice Activate or deactivate a reserve
* @param asset The address of the underlying asset of the reserve
* @param active True if the reserve needs to be active, false otherwise
*/
function setReserveActive(address asset, bool active) external;
/**
* @notice Freeze or unfreeze a reserve. A frozen reserve doesn't allow any new supply, borrow
* or rate swap but allows repayments, liquidations, rate rebalances and withdrawals.
* @param asset The address of the underlying asset of the reserve
* @param freeze True if the reserve needs to be frozen, false otherwise
*/
function setReserveFreeze(address asset, bool freeze) external;
/**
* @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 (e.g. USD stablecoins) should be borrowable in isolation mode to keep
* consistency in the debt ceiling calculations
* @param asset The address of the underlying asset of the reserve
* @param borrowable True if the asset should be borrowable in isolation, false otherwise
*/
function setBorrowableInIsolation(address asset, bool borrowable) external;
/**
* @notice Pauses a reserve. A paused reserve does not allow any interaction (supply, borrow, repay,
* swap interest rate, liquidate, atoken transfers).
* @param asset The address of the underlying asset of the reserve
* @param paused True if pausing the reserve, false if unpausing
*/
function setReservePause(address asset, bool paused) external;
/**
* @notice Updates the reserve factor of a reserve.
* @param asset The address of the underlying asset of the reserve
* @param newReserveFactor The new reserve factor of the reserve
*/
function setReserveFactor(address asset, uint256 newReserveFactor) external;
/**
* @notice Sets the interest rate strategy of a reserve.
* @param asset The address of the underlying asset of the reserve
* @param newRateStrategyAddress The address of the new interest strategy contract
*/
function setReserveInterestRateStrategyAddress(
address asset,
address newRateStrategyAddress
) external;
/**
* @notice Pauses or unpauses all the protocol reserves. In the paused state all the protocol interactions
* are suspended.
* @param paused True if protocol needs to be paused, false otherwise
*/
function setPoolPause(bool paused) external;
/**
* @notice Updates the borrow cap of a reserve.
* @param asset The address of the underlying asset of the reserve
* @param newBorrowCap The new borrow cap of the reserve
*/
function setBorrowCap(address asset, uint256 newBorrowCap) external;
/**
* @notice Updates the supply cap of a reserve.
* @param asset The address of the underlying asset of the reserve
* @param newSupplyCap The new supply cap of the reserve
*/
function setSupplyCap(address asset, uint256 newSupplyCap) external;
/**
* @notice Updates the liquidation protocol fee of reserve.
* @param asset The address of the underlying asset of the reserve
* @param newFee The new liquidation protocol fee of the reserve, expressed in bps
*/
function setLiquidationProtocolFee(address asset, uint256 newFee) external;
/**
* @notice Updates the unbacked mint cap of reserve.
* @param asset The address of the underlying asset of the reserve
* @param newUnbackedMintCap The new unbacked mint cap of the reserve
*/
function setUnbackedMintCap(address asset, uint256 newUnbackedMintCap) external;
/**
* @notice Assign an efficiency mode (eMode) category to asset.
* @param asset The address of the underlying asset of the reserve
* @param newCategoryId The new category id of the asset
*/
function setAssetEModeCategory(address asset, uint8 newCategoryId) external;
/**
* @notice Adds a new efficiency mode (eMode) category.
* @dev If zero is provided as oracle address, the default asset oracles will be used to compute the overall debt and
* overcollateralization of the users using this category.
* @dev The new ltv and liquidation threshold must be greater than the base
* ltvs and liquidation thresholds of all assets within the eMode category
* @param categoryId The id of the category to be configured
* @param ltv The ltv associated with the category
* @param liquidationThreshold The liquidation threshold associated with the category
* @param liquidationBonus The liquidation bonus associated with the category
* @param oracle The oracle associated with the category
* @param label A label identifying the category
*/
function setEModeCategory(
uint8 categoryId,
uint16 ltv,
uint16 liquidationThreshold,
uint16 liquidationBonus,
address oracle,
string calldata label
) external;
/**
* @notice Drops a reserve entirely.
* @param asset The address of the reserve to drop
*/
function dropReserve(address asset) external;
/**
* @notice Updates the bridge fee collected by the protocol reserves.
* @param newBridgeProtocolFee The part of the fee sent to the protocol treasury, expressed in bps
*/
function updateBridgeProtocolFee(uint256 newBridgeProtocolFee) external;
/**
* @notice Updates the total flash loan premium.
* Total flash loan premium consists of two parts:
* - A part is sent to aToken holders as extra balance
* - A part is collected by the protocol reserves
* @dev Expressed in bps
* @dev The premium is calculated on the total amount borrowed
* @param newFlashloanPremiumTotal The total flashloan premium
*/
function updateFlashloanPremiumTotal(uint128 newFlashloanPremiumTotal) external;
/**
* @notice Updates the flash loan premium collected by protocol reserves
* @dev Expressed in bps
* @dev The premium to protocol is calculated on the total flashloan premium
* @param newFlashloanPremiumToProtocol The part of the flashloan premium sent to the protocol treasury
*/
function updateFlashloanPremiumToProtocol(uint128 newFlashloanPremiumToProtocol) external;
/**
* @notice Sets the debt ceiling for an asset.
* @param newDebtCeiling The new debt ceiling
*/
function setDebtCeiling(address asset, uint256 newDebtCeiling) external;
/**
* @notice Sets siloed borrowing for an asset
* @param siloed The new siloed borrowing state
*/
function setSiloedBorrowing(address asset, bool siloed) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Address} from './libraries/Address.sol';
import {IAaveV3ConfigEngine as IEngine} from './interfaces/IAaveV3ConfigEngine.sol';
import {IV3RateStrategyFactory as Rates} from './interfaces/IV3RateStrategyFactory.sol';
library EngineFlags {
/// @dev magic value to be used as flag to keep unchanged any current configuration
/// Strongly assumes that the value `type(uint256).max - 42` will never be used, which seems reasonable
uint256 internal constant KEEP_CURRENT = type(uint256).max - 42;
/// @dev value to be used as flag for bool value true
uint256 internal constant ENABLED = 1;
/// @dev value to be used as flag for bool value false
uint256 internal constant DISABLED = 0;
/// @dev converts flag ENABLED DISABLED to bool
function toBool(uint256 flag) internal pure returns (bool) {
require(flag == 0 || flag == 1, 'INVALID_CONVERSION_TO_BOOL');
return flag == 1;
}
/// @dev converts bool to ENABLED DISABLED flags
function fromBool(bool isTrue) internal pure returns (uint256) {
return isTrue ? ENABLED : DISABLED;
}
}
/**
* @dev Base smart contract for an Aave v3.0.1 configs update.
* - Assumes this contract has the right permissions
* - Connected to a IAaveV3ConfigEngine engine contact, which abstract the complexities of
* interaction with the Aave protocol.
* - At the moment covering:
* - Listings of new assets on the pool.
* - Updates of caps (supply cap, borrow cap).
* - Updates of price feeds
* - Updates of interest rate strategies.
* - Updates of borrow parameters (flashloanable, stableRateModeEnabled, borrowableInIsolation, withSiloedBorrowing, reserveFactor)
* - Updates of collateral parameters (ltv, liq threshold, liq bonus, liq protocol fee, debt ceiling)
* @author BGD Labs
*/
abstract contract AaveV3PayloadBase {
using Address for address;
IEngine public immutable LISTING_ENGINE;
constructor(IEngine engine) {
LISTING_ENGINE = engine;
}
/// @dev to be overriden on the child if any extra logic is needed pre-listing
function _preExecute() internal virtual {}
/// @dev to be overriden on the child if any extra logic is needed post-listing
function _postExecute() internal virtual {}
function execute() public virtual {
_preExecute();
IEngine.Listing[] memory listings = newListings();
IEngine.ListingWithCustomImpl[] memory listingsCustom = newListingsCustom();
IEngine.CapsUpdate[] memory caps = capsUpdates();
IEngine.CollateralUpdate[] memory collaterals = collateralsUpdates();
IEngine.BorrowUpdate[] memory borrows = borrowsUpdates();
IEngine.PriceFeedUpdate[] memory priceFeeds = priceFeedsUpdates();
IEngine.RateStrategyUpdate[] memory rates = rateStrategiesUpdates();
if (listings.length != 0) {
address(LISTING_ENGINE).functionDelegateCall(
abi.encodeWithSelector(LISTING_ENGINE.listAssets.selector, getPoolContext(), listings)
);
}
if (listingsCustom.length != 0) {
address(LISTING_ENGINE).functionDelegateCall(
abi.encodeWithSelector(
LISTING_ENGINE.listAssetsCustom.selector,
getPoolContext(),
listingsCustom
)
);
}
if (borrows.length != 0) {
address(LISTING_ENGINE).functionDelegateCall(
abi.encodeWithSelector(LISTING_ENGINE.updateBorrowSide.selector, borrows)
);
}
if (collaterals.length != 0) {
address(LISTING_ENGINE).functionDelegateCall(
abi.encodeWithSelector(LISTING_ENGINE.updateCollateralSide.selector, collaterals)
);
}
if (rates.length != 0) {
address(LISTING_ENGINE).functionDelegateCall(
abi.encodeWithSelector(LISTING_ENGINE.updateRateStrategies.selector, rates)
);
}
if (priceFeeds.length != 0) {
address(LISTING_ENGINE).functionDelegateCall(
abi.encodeWithSelector(LISTING_ENGINE.updatePriceFeeds.selector, priceFeeds)
);
}
if (caps.length != 0) {
address(LISTING_ENGINE).functionDelegateCall(
abi.encodeWithSelector(LISTING_ENGINE.updateCaps.selector, caps)
);
}
_postExecute();
}
/** @dev Converts basis points to RAY units
* e.g. 10_00 (10.00%) will return 100000000000000000000000000
*/
function _bpsToRay(uint256 amount) internal pure returns (uint256) {
return (amount * 1e27) / 10_000;
}
/// @dev to be defined in the child with a list of new assets to list
function newListings() public view virtual returns (IEngine.Listing[] memory) {}
/// @dev to be defined in the child with a list of new assets to list (with custom a/v/s tokens implementations)
function newListingsCustom()
public
view
virtual
returns (IEngine.ListingWithCustomImpl[] memory)
{}
/// @dev to be defined in the child with a list of caps to update
function capsUpdates() public view virtual returns (IEngine.CapsUpdate[] memory) {}
/// @dev to be defined in the child with a list of collaterals' params to update
function collateralsUpdates() public view virtual returns (IEngine.CollateralUpdate[] memory) {}
/// @dev to be defined in the child with a list of borrows' params to update
function borrowsUpdates() public view virtual returns (IEngine.BorrowUpdate[] memory) {}
/// @dev to be defined in the child with a list of priceFeeds to update
function priceFeedsUpdates() public view virtual returns (IEngine.PriceFeedUpdate[] memory) {}
/// @dev to be defined in the child with a list of set of parameters of rate strategies
function rateStrategiesUpdates()
public
view
virtual
returns (IEngine.RateStrategyUpdate[] memory)
{}
/// @dev the lack of support for immutable strings kinds of forces for this
/// Besides that, it can actually be useful being able to change the naming, but remote
function getPoolContext() public view virtual returns (IEngine.PoolContext memory);
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity >=0.8.0;
library Arbitrum {
/******************************************************************************************************************/
/*** Token Addresses ***/
/******************************************************************************************************************/
address internal constant SUSDC = 0x940098b108fB7D0a7E374f6eDED7760787464609;
address internal constant SUSDS = 0xdDb46999F8891663a8F2828d25298f70416d7610;
address internal constant USDC = 0xaf88d065e77c8cC2239327C5EDb3A432268e5831;
address internal constant USDS = 0x6491c05A82219b8D1479057361ff1654749b876b;
/******************************************************************************************************************/
/*** Bridging Addresses ***/
/******************************************************************************************************************/
address internal constant CCTP_TOKEN_MESSENGER = 0x19330d10D9Cc8751218eaf51E8885D058642E08A;
address internal constant SKY_GOV_RELAY = 0x10E6593CDda8c58a1d0f14C5164B376352a55f2F;
address internal constant TOKEN_BRIDGE = 0x13F7F24CA959359a4D710D32c715D4bce273C793;
/******************************************************************************************************************/
/*** PSM Addresses ***/
/******************************************************************************************************************/
address internal constant PSM3 = 0x2B05F8e1cACC6974fD79A673a341Fe1f58d27266;
/******************************************************************************************************************/
/*** Spark Liquidity Layer Addresses ***/
/******************************************************************************************************************/
address internal constant ALM_CONTROLLER = 0x98f567464e91e9B4831d3509024b7868f9F79ee1;
address internal constant ALM_PROXY = 0x92afd6F2385a90e44da3a8B60fe36f6cBe1D8709;
address internal constant ALM_RATE_LIMITS = 0x19D08879851FB54C2dCc4bb32b5a1EA5E9Ad6838;
address internal constant ALM_FREEZER = 0x90D8c80C028B4C09C0d8dcAab9bbB057F0513431;
address internal constant ALM_RELAYER = 0x8a25A24EDE9482C4Fc0738F99611BE58F1c839AB;
address internal constant ALM_RELAYER2 = 0x8Cc0Cb0cfB6B7e548cfd395B833c05C346534795;
/******************************************************************************************************************/
/*** Aave Addresses ***/
/******************************************************************************************************************/
address internal constant ATOKEN_USDC = 0x724dc807b04555b71ed48a6896b6F41593b8C637;
/******************************************************************************************************************/
/*** Governance Relay Addresses ***/
/******************************************************************************************************************/
address internal constant SPARK_EXECUTOR = 0x65d946e533748A998B1f0E430803e39A6388f7a1;
address internal constant SPARK_RECEIVER = 0x212871A1C235892F86cAB30E937e18c94AEd8474;
/******************************************************************************************************************/
/*** SSR Oracle Addresses ***/
/******************************************************************************************************************/
address internal constant SSR_AUTH_ORACLE = 0xEE2816c1E1eed14d444552654Ed3027abC033A36;
address internal constant SSR_BALANCER_RATE_PROVIDER = 0xc0737f29b964e6fC8025F16B30f2eA4C2e2d6f22;
address internal constant SSR_CHAINLINK_RATE_PROVIDER = 0x84AB0c8C158A1cD0d215BE2746cCa668B79cc287;
address internal constant SSR_RECEIVER = 0x567214Dc57a2385Abc4a756f523ddF0275305Cbc;
/******************************************************************************************************************/
/*** DSR Oracle Addresses ***/
/******************************************************************************************************************/
address internal constant DSR_AUTH_ORACLE = 0xE206AEbca7B28e3E8d6787df00B010D4a77c32F3;
address internal constant DSR_RECEIVER = 0xcA61540eC2AC74E6954FA558B4aF836d95eCb91b;
address internal constant DSR_BALANCER_RATE_PROVIDER = 0x73750DbD85753074e452B2C27fB9e3B0E75Ff3B8;
/******************************************************************************************************************/
/*** Multisigs ***/
/******************************************************************************************************************/
address internal constant SPARK_REWARDS_MULTISIG = 0xF649956f43825d4d7295a50EDdBe1EDC814A3a83;
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity >=0.8.0;
library Base {
/******************************************************************************************************************/
/*** Token Addresses ***/
/******************************************************************************************************************/
address internal constant CBBTC = 0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf;
address internal constant SKY = 0x60e3c701e65DEE30c23c9Fb78c3866479cc0944a;
address internal constant SUSDC = 0x3128a0F7f0ea68E7B7c9B00AFa7E41045828e858;
address internal constant SUSDS = 0x5875eEE11Cf8398102FdAd704C9E96607675467a;
address internal constant USDC = 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913;
address internal constant USDS = 0x820C137fa70C8691f0e44Dc420a5e53c168921Dc;
/******************************************************************************************************************/
/*** Bridging Addresses ***/
/******************************************************************************************************************/
address internal constant CCTP_TOKEN_MESSENGER = 0x1682Ae6375C4E4A97e4B583BC394c861A46D8962;
address internal constant SKY_GOV_RELAY = 0xdD0BCc201C9E47c6F6eE68E4dB05b652Bb6aC255;
address internal constant TOKEN_BRIDGE = 0xee44cdb68D618d58F75d9fe0818B640BD7B8A7B7;
/******************************************************************************************************************/
/*** PSM Addresses ***/
/******************************************************************************************************************/
address internal constant PSM3 = 0x1601843c5E9bC251A3272907010AFa41Fa18347E;
/******************************************************************************************************************/
/*** Spark Liquidity Layer Addresses ***/
/******************************************************************************************************************/
address internal constant ALM_CONTROLLER = 0xB94378b5347a3E199AF3575719F67A708a5D8b9B;
address internal constant ALM_PROXY = 0x2917956eFF0B5eaF030abDB4EF4296DF775009cA;
address internal constant ALM_RATE_LIMITS = 0x983eC82E45C61a42FDDA7B3c43B8C767004c8A74;
address internal constant ALM_FREEZER = 0x90D8c80C028B4C09C0d8dcAab9bbB057F0513431;
address internal constant ALM_RELAYER = 0x8a25A24EDE9482C4Fc0738F99611BE58F1c839AB;
address internal constant ALM_RELAYER2 = 0x8Cc0Cb0cfB6B7e548cfd395B833c05C346534795;
/******************************************************************************************************************/
/*** Aave Addresses ***/
/******************************************************************************************************************/
address internal constant ATOKEN_USDC = 0x4e65fE4DbA92790696d040ac24Aa414708F5c0AB;
/******************************************************************************************************************/
/*** Fluid Addresses ***/
/******************************************************************************************************************/
address internal constant FLUID_SUSDS = 0xf62e339f21d8018940f188F6987Bcdf02A849619;
/******************************************************************************************************************/
/*** Morpho Addresses ***/
/******************************************************************************************************************/
address internal constant MORPHO = 0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb;
address internal constant MORPHO_DEFAULT_IRM = 0x46415998764C29aB2a25CbeA6254146D50D22687;
address internal constant MORPHO_VAULT_SUSDC = 0x7BfA7C4f149E7415b73bdeDfe609237e29CBF34A;
/******************************************************************************************************************/
/*** Governance Relay Addresses ***/
/******************************************************************************************************************/
address internal constant SPARK_EXECUTOR = 0xF93B7122450A50AF3e5A76E1d546e95Ac1d0F579;
address internal constant SPARK_RECEIVER = 0xfda082e00EF89185d9DB7E5DcD8c5505070F5A3B;
/******************************************************************************************************************/
/*** SSR Oracle Addresses ***/
/******************************************************************************************************************/
address internal constant SSR_AUTH_ORACLE = 0x65d946e533748A998B1f0E430803e39A6388f7a1;
address internal constant SSR_BALANCER_RATE_PROVIDER = 0x49aF4eE75Ae62C2229bb2486a59Aa1a999f050f0;
address internal constant SSR_CHAINLINK_RATE_PROVIDER = 0x026a5B6114431d8F3eF2fA0E1B2EDdDccA9c540E;
address internal constant SSR_RECEIVER = 0x212871A1C235892F86cAB30E937e18c94AEd8474;
/******************************************************************************************************************/
/*** DSR Oracle Addresses (Legacy) ***/
/******************************************************************************************************************/
address internal constant DSR_AUTH_ORACLE = 0x2Dd2a2Fe346B5704380EfbF6Bd522042eC3E8FAe;
address internal constant DSR_RECEIVER = 0xaDEAf02Ddb5Bed574045050B8096307bE66E0676;
address internal constant DSR_BALANCER_RATE_PROVIDER = 0xeC0C14Ea7fF20F104496d960FDEBF5a0a0cC14D0;
/******************************************************************************************************************/
/*** Multisigs ***/
/******************************************************************************************************************/
address internal constant SPARK_REWARDS_MULTISIG = 0xF649956f43825d4d7295a50EDdBe1EDC814A3a83;
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity >=0.8.0;
library Gnosis {
/******************************************************************************************************************/
/*** Token Addresses ***/
/******************************************************************************************************************/
address internal constant GNO = 0x9C58BAcC331c9aa871AFD802DB6379a98e80CEdb;
address internal constant WETH = 0x6A023CCd1ff6F2045C3309768eAd9E68F978f6e1;
address internal constant WSTETH = 0x6C76971f98945AE98dD7d4DFcA8711ebea946eA6;
address internal constant WXDAI = 0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d;
address internal constant SXDAI = 0xaf204776c7245bF4147c2612BF6e5972Ee483701;
address internal constant USDC = 0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83;
address internal constant USDCE = 0x2a22f9c3b484c3629090FeED35F17Ff8F88f76F0;
address internal constant USDT = 0x4ECaBa5870353805a9F068101A40E0f32ed605C6;
address internal constant EURE = 0xcB444e90D8198415266c6a2724b7900fb12FC56E;
/******************************************************************************************************************/
/*** SparkLend - Core Protocol Addresses ***/
/******************************************************************************************************************/
address internal constant AAVE_ORACLE = 0x8105f69D9C41644c6A0803fDA7D03Aa70996cFD9;
address internal constant ACL_MANAGER = 0x86C71796CcDB31c3997F8Ec5C2E3dB3e9e40b985;
address internal constant EMISSION_MANAGER = 0x4d988568b5f0462B08d1F40bA1F5f17ad2D24F76;
address internal constant INCENTIVES = 0x98e6BcBA7d5daFbfa4a92dAF08d3d7512820c30C;
address internal constant POOL = 0x2Dae5307c5E3FD1CF5A72Cb6F698f915860607e0;
address internal constant POOL_ADDRESSES_PROVIDER = 0xA98DaCB3fC964A6A0d2ce3B77294241585EAbA6d;
address internal constant POOL_ADDRESSES_PROVIDER_REGISTRY = 0x49d24798d3b84965F0d1fc8684EF6565115e70c1;
address internal constant POOL_CONFIGURATOR = 0x2Fc8823E1b967D474b47Ae0aD041c2ED562ab588;
address internal constant TREASURY = 0xb9E6DBFa4De19CCed908BcbFe1d015190678AB5f;
address internal constant TREASURY_CONTROLLER = 0x8220096398c3Dc2644026E8864f5D80Ef613B437;
address internal constant WETH_GATEWAY = 0xBD7D6a9ad7865463DE44B05F04559f65e3B11704;
/******************************************************************************************************************/
/*** SparkLend - Reserve Token Addresses ***/
/******************************************************************************************************************/
address internal constant GNO_ATOKEN = 0x5671b0B8aC13DC7813D36B99C21c53F6cd376a14;
address internal constant GNO_STABLE_DEBT_TOKEN = 0x2f589BADbE2024a94f144ef24344aF91dE21a33c;
address internal constant GNO_DEBT_TOKEN = 0xd4bAbF714964E399f95A7bb94B3DeaF22d9F575d;
address internal constant WETH_ATOKEN = 0x629D562E92fED431122e865Cc650Bc6bdE6B96b0;
address internal constant WETH_STABLE_DEBT_TOKEN = 0xe21Bf3FB5A2b5Bf7BAE8c6F1696c4B097F5D2f93;
address internal constant WETH_DEBT_TOKEN = 0x0aD6cCf9a2e81d4d48aB7db791e9da492967eb84;
address internal constant WSTETH_ATOKEN = 0x9Ee4271E17E3a427678344fd2eE64663Cb78B4be;
address internal constant WSTETH_STABLE_DEBT_TOKEN = 0x0F0e336Ab69D9516A9acF448bC59eA0CE79E4a42;
address internal constant WSTETH_DEBT_TOKEN = 0x3294dA2E28b29D1c08D556e2B86879d221256d31;
address internal constant WXDAI_ATOKEN = 0xC9Fe2D32E96Bb364c7d29f3663ed3b27E30767bB;
address internal constant WXDAI_STABLE_DEBT_TOKEN = 0xab1B62A1346Acf534b581684940E2FD781F2EA22;
address internal constant WXDAI_DEBT_TOKEN = 0x868ADfDf12A86422524EaB6978beAE08A0008F37;
address internal constant SXDAI_ATOKEN = 0xE877b96caf9f180916bF2B5Ce7Ea8069e0123182;
address internal constant SXDAI_STABLE_DEBT_TOKEN = 0x2cF710377b3576287Be7cf352FF75D4472902789;
address internal constant SXDAI_DEBT_TOKEN = 0x1022E390E2457A78E18AEEE0bBf0E96E482EeE19;
address internal constant USDC_ATOKEN = 0x5850D127a04ed0B4F1FCDFb051b3409FB9Fe6B90;
address internal constant USDC_STABLE_DEBT_TOKEN = 0x40BF0Bf6AECeE50eCE10C74E81a52C654A467ae4;
address internal constant USDC_DEBT_TOKEN = 0xBC4f20DAf4E05c17E93676D2CeC39769506b8219;
address internal constant USDCE_ATOKEN = 0xA34DB0ee8F84C4B90ed268dF5aBbe7Dcd3c277ec;
address internal constant USDCE_STABLE_DEBT_TOKEN = 0xC5dfde524371F9424c81F453260B2CCd24936c15;
address internal constant USDCE_DEBT_TOKEN = 0x397b97b572281d0b3e3513BD4A7B38050a75962b;
address internal constant USDT_ATOKEN = 0x08B0cAebE352c3613302774Cd9B82D08afd7bDC4;
address internal constant USDT_STABLE_DEBT_TOKEN = 0x4cB3F681B5e393947BD1e5cAE84764f5892923C2;
address internal constant USDT_DEBT_TOKEN = 0x3A98aBC6F46CA2Fc6c7d06eD02184D63C55e19B2;
address internal constant EURE_ATOKEN = 0x6dc304337BF3EB397241d1889cAE7da638e6e782;
address internal constant EURE_STABLE_DEBT_TOKEN = 0x80F87B8F9c1199e468923D8EE87cEE311690FDA6;
address internal constant EURE_DEBT_TOKEN = 0x0b33480d3FbD1E2dBE88c82aAbe191D7473759D5;
/******************************************************************************************************************/
/*** SparkLend - Implementation Addresses ***/
/******************************************************************************************************************/
address internal constant A_TOKEN_IMPL = 0x856900aa78e856a5df1a2665eE3a66b2487cD68f;
address internal constant INCENTIVES_IMPL = 0x764b4AB9bCA18eB633d92368F725765Ebb8f047C;
address internal constant POOL_CONFIGURATOR_IMPL = 0x6175ddEc3B9b38c88157C10A01ed4A3fa8639cC6;
address internal constant POOL_IMPL = 0xCF86A65779e88bedfF0319FE13aE2B47358EB1bF;
address internal constant STABLE_DEBT_TOKEN_IMPL = 0x4370D3b6C9588E02ce9D22e684387859c7Ff5b34;
address internal constant TREASURY_IMPL = 0x571501be53711c372cE69De51865dD34B87698D5;
address internal constant VARIABLE_DEBT_TOKEN_IMPL = 0x0ee554F6A1f7a4Cb4f82D4C124DdC2AD3E37fde1;
/******************************************************************************************************************/
/*** SparkLend - Config Engine Addresses ***/
/******************************************************************************************************************/
address internal constant PROXY_ADMIN = 0xf76B8262dfd60fb7432C6b55E91f42b6da953647;
address internal constant CONFIG_ENGINE = 0x36eddc380C7f370e5f05Da5Bd7F970a27f063e39;
address internal constant RATES_FACTORY = 0xe04ba71E46fCd7DBB9334D8FBa13d476f38EB0f8;
address internal constant TRANSPARENT_PROXY_FACTORY = 0x91277b74a9d1Cc30fA0ff4927C287fe55E307D78;
/******************************************************************************************************************/
/*** SparkLend - Data Provider Addresses ***/
/******************************************************************************************************************/
address internal constant PROTOCOL_DATA_PROVIDER = 0x2a002054A06546bB5a264D57A81347e23Af91D18;
address internal constant UI_INCENTIVE_DATA_PROVIDER = 0xA7F8A757C4f7696c015B595F51B2901AC0121B18;
address internal constant UI_POOL_DATA_PROVIDER = 0xF028c2F4b19898718fD0F77b9b881CbfdAa5e8Bb;
address internal constant WALLET_BALANCE_PROVIDER = 0xd2AeF86F51F92E8e49F42454c287AE4879D1BeDc;
/******************************************************************************************************************/
/*** Governance Addresses ***/
/******************************************************************************************************************/
address constant AMB_EXECUTOR = 0xc4218C1127cB24a0D6c1e7D25dc34e10f2625f5A;
/******************************************************************************************************************/
/*** Multisigs ***/
/******************************************************************************************************************/
address internal constant SPARK_REWARDS_MULTISIG = 0xF649956f43825d4d7295a50EDdBe1EDC814A3a83;
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.0;
import { IAccessControl } from 'openzeppelin-contracts/contracts/access/IAccessControl.sol';
/**
* @title IExecutor
* @author Aave
* @notice Defines the interface for the Executor
*/
interface IExecutor is IAccessControl {
/******************************************************************************************************************/
/*** Errors ***/
/******************************************************************************************************************/
error GracePeriodTooShort();
error OnlyQueuedActions();
error TimelockNotFinished();
error InvalidActionsSetId();
error EmptyTargets();
error InconsistentParamsLength();
error InsufficientBalance();
/******************************************************************************************************************/
/*** Enums ***/
/******************************************************************************************************************/
/**
* @notice This enum contains all possible actions set states
*/
enum ActionsSetState {
Queued,
Executed,
Canceled,
Expired
}
/******************************************************************************************************************/
/*** Events ***/
/******************************************************************************************************************/
/**
* @notice This struct contains the data needed to execute a specified set of actions.
* @param targets Array of targets to call.
* @param values Array of values to pass in each call.
* @param signatures Array of function signatures to encode in each call by the actions which can be empty strings.
* @param calldatas Array of calldatas to pass in each call, appended to the signature at the same array index if not empty.
* @param withDelegateCalls Array of whether to delegatecall for each call.
* @param executionTime Timestamp starting from which the actions set can be executed.
* @param executed True if the actions set has been executed, false otherwise.
* @param canceled True if the actions set has been canceled, false otherwise.
*/
struct ActionsSet {
address[] targets;
uint256[] values;
string[] signatures;
bytes[] calldatas;
bool[] withDelegatecalls;
uint256 executionTime;
bool executed;
bool canceled;
}
/**
* @dev Emitted when an ActionsSet is queued.
* @param id Id of the ActionsSet.
* @param targets Array of targets to be called by the actions set.
* @param values Array of values to pass in each call by the actions set.
* @param signatures Array of function signatures to encode in each call by the actions set.
* @param calldatas Array of calldata to pass in each call by the actions set.
* @param withDelegatecalls Array of whether to delegatecall for each call of the actions set.
* @param executionTime The timestamp at which this actions set can be executed.
**/
event ActionsSetQueued(
uint256 indexed id,
address[] targets,
uint256[] values,
string[] signatures,
bytes[] calldatas,
bool[] withDelegatecalls,
uint256 executionTime
);
/**
* @dev Emitted when an ActionsSet is successfully executed.
* @param id Id of the ActionsSet.
* @param initiatorExecution The address that triggered the ActionsSet execution.
* @param returnedData The returned data from the ActionsSet execution.
**/
event ActionsSetExecuted(
uint256 indexed id,
address indexed initiatorExecution,
bytes[] returnedData
);
/**
* @dev Emitted when an ActionsSet is cancelled by the guardian.
* @param id Id of the ActionsSet.
**/
event ActionsSetCanceled(uint256 indexed id);
/**
* @dev Emitted when the delay (between queueing and execution) is updated.
* @param oldDelay The value of the old delay.
* @param newDelay The value of the new delay.
**/
event DelayUpdate(uint256 oldDelay, uint256 newDelay);
/**
* @dev Emitted when the grace period (between executionTime and expiration) is updated.
* @param oldGracePeriod The value of the old grace period.
* @param newGracePeriod The value of the new grace period.
**/
event GracePeriodUpdate(uint256 oldGracePeriod, uint256 newGracePeriod);
/******************************************************************************************************************/
/*** State variables ***/
/******************************************************************************************************************/
/**
* @notice The role that allows submission of a queued action.
**/
function SUBMISSION_ROLE() external view returns (bytes32);
/**
* @notice The role that allows a guardian to cancel a pending action.
**/
function GUARDIAN_ROLE() external view returns (bytes32);
/**
* @notice Returns the minimum grace period that can be set, 10 minutes.
*/
function MINIMUM_GRACE_PERIOD() external view returns (uint256);
/**
* @notice Returns the total number of actions sets of the executor.
* @return The number of actions sets.
**/
function actionsSetCount() external view returns (uint256);
/**
* @notice Returns the delay (between queuing and execution)
* @return The value of the delay (in seconds)
**/
function delay() external view returns (uint256);
/**
* @notice Time after the execution time during which the actions set can be executed.
* @return The value of the grace period (in seconds)
**/
function gracePeriod() external view returns (uint256);
/******************************************************************************************************************/
/*** ActionSet functions ***/
/******************************************************************************************************************/
/**
* @notice Queue an ActionsSet.
* @dev If a signature is empty, calldata is used for the execution, calldata is appended to signature otherwise.
* @param targets Array of targets to be called by the actions set.
* @param values Array of values to pass in each call by the actions set.
* @param signatures Array of function signatures to encode in each call by the actions which can be empty strings.
* @param calldatas Array of calldata to pass in each call by the actions set.
* @param withDelegatecalls Array of whether to delegatecall for each call of the actions set.
**/
function queue(
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas,
bool[] memory withDelegatecalls
) external;
/**
* @notice Execute the ActionsSet
* @param actionsSetId The id of the ActionsSet to execute
**/
function execute(uint256 actionsSetId) external payable;
/**
* @notice Cancel the ActionsSet.
* @param actionsSetId The id of the ActionsSet to cancel.
**/
function cancel(uint256 actionsSetId) external;
/******************************************************************************************************************/
/*** Admin functions ***/
/******************************************************************************************************************/
/**
* @notice Update the delay, time between queueing and execution of ActionsSet.
* @dev It does not affect to actions set that are already queued.
* @param delay The value of the delay (in seconds).
**/
function updateDelay(uint256 delay) external;
/**
* @notice Update the grace period, the period after the execution time during which an actions set can be executed
* @param gracePeriod The value of the grace period (in seconds).
**/
function updateGracePeriod(uint256 gracePeriod) external;
/******************************************************************************************************************/
/*** Misc functions ***/
/******************************************************************************************************************/
/**
* @notice Allows to delegatecall a given target with an specific amount of value.
* @dev This function is external so it allows to specify a defined msg.value for the delegate call, reducing
* the risk that a delegatecall gets executed with more value than intended.
* @return The bytes returned by the delegate call.
**/
function executeDelegateCall(address target, bytes calldata data)
external
payable
returns (bytes memory);
/**
* @notice Allows to receive funds into the executor.
* @dev Useful for actionsSet that needs funds to gets executed.
*/
function receiveFunds() external payable;
/******************************************************************************************************************/
/*** View functions ***/
/******************************************************************************************************************/
/**
* @notice Returns the data of an actions set.
* @param actionsSetId The id of the ActionsSet.
* @return The data of the ActionsSet.
**/
function getActionsSetById(uint256 actionsSetId) external view returns (ActionsSet memory);
/**
* @notice Returns the current state of an actions set.
* @param actionsSetId The id of the ActionsSet.
* @return The current state of theI ActionsSet.
**/
function getCurrentState(uint256 actionsSetId) external view returns (ActionsSetState);
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.0;
interface IArbitraryMessagingBridge {
function requireToPassMessage(address _contract, bytes memory _data, uint256 _gas) external returns (bytes32);
}
library AMBForwarder {
address constant internal GNOSIS_AMB_ETHEREUM = 0x4C36d2919e407f0Cc2Ee3c993ccF8ac26d9CE64e;
address constant internal GNOSIS_AMB_GNOSIS_CHAIN = 0x75Df5AF045d91108662D8080fD1FEFAd6aA0bb59;
function sendMessage(
address amb,
address target,
bytes memory message,
uint256 gasLimit
) internal {
IArbitraryMessagingBridge(amb).requireToPassMessage(
target,
message,
gasLimit
);
}
function sendMessageEthereumToGnosisChain(
address target,
bytes memory message,
uint256 gasLimit
) internal {
sendMessage(
GNOSIS_AMB_ETHEREUM,
target,
message,
gasLimit
);
}
function sendMessageGnosisChainToEthereum(
address target,
bytes memory message,
uint256 gasLimit
) internal {
sendMessage(
GNOSIS_AMB_GNOSIS_CHAIN,
target,
message,
gasLimit
);
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.0;
interface ICrossDomainArbitrum {
function createRetryableTicket(
address to,
uint256 l2CallValue,
uint256 maxSubmissionCost,
address excessFeeRefundAddress,
address callValueRefundAddress,
uint256 gasLimit,
uint256 maxFeePerGas,
bytes calldata data
) external payable returns (uint256);
function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee) external view returns (uint256);
}
interface IArbSys {
function sendTxToL1(address target, bytes calldata message) external;
}
library ArbitrumForwarder {
address constant internal L1_CROSS_DOMAIN_ARBITRUM_ONE = 0x4Dbd4fc535Ac27206064B68FfCf827b0A60BAB3f;
address constant internal L1_CROSS_DOMAIN_ARBITRUM_NOVA = 0xc4448b71118c9071Bcb9734A0EAc55D18A153949;
address constant internal L2_CROSS_DOMAIN = 0x0000000000000000000000000000000000000064;
function sendMessageL1toL2(
address l1CrossDomain,
address target,
bytes memory message,
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 baseFee
) internal {
uint256 maxSubmission = ICrossDomainArbitrum(l1CrossDomain).calculateRetryableSubmissionFee(message.length, baseFee);
uint256 maxRedemption = gasLimit * maxFeePerGas;
ICrossDomainArbitrum(l1CrossDomain).createRetryableTicket{value: maxSubmission + maxRedemption}(
target,
0, // we always assume that l2CallValue = 0
maxSubmission,
address(0), // burn the excess gas
address(0), // burn the excess gas
gasLimit,
maxFeePerGas,
message
);
}
function sendMessageL2toL1(
address target,
bytes memory message
) internal {
IArbSys(L2_CROSS_DOMAIN).sendTxToL1(
target,
message
);
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.0;
interface ICrossDomainOptimism {
function sendMessage(address _target, bytes calldata _message, uint32 _gasLimit) external;
}
library OptimismForwarder {
address constant internal L1_CROSS_DOMAIN_OPTIMISM = 0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1;
address constant internal L1_CROSS_DOMAIN_BASE = 0x866E82a600A1414e583f7F13623F1aC5d58b0Afa;
address constant internal L1_CROSS_DOMAIN_WORLD_CHAIN = 0xf931a81D18B1766d15695ffc7c1920a62b7e710a;
address constant internal L2_CROSS_DOMAIN = 0x4200000000000000000000000000000000000007;
function sendMessageL1toL2(
address l1CrossDomain,
address target,
bytes memory message,
uint32 gasLimit
) internal {
ICrossDomainOptimism(l1CrossDomain).sendMessage(
target,
message,
gasLimit
);
}
function sendMessageL2toL1(
address target,
bytes memory message,
uint32 gasLimit
) internal {
ICrossDomainOptimism(L2_CROSS_DOMAIN).sendMessage(
target,
message,
gasLimit
);
}
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import { IAToken } from "aave-v3-origin/src/core/contracts/interfaces/IAToken.sol";
import { IERC20 } from 'forge-std/interfaces/IERC20.sol';
import { IERC4626 } from 'forge-std/interfaces/IERC4626.sol';
import { IMetaMorpho } from "metamorpho/interfaces/IMetaMorpho.sol";
import { MarketParams, Id } from "morpho-blue/src/interfaces/IMorpho.sol";
import { MarketParamsLib } from "morpho-blue/src/libraries/MarketParamsLib.sol";
import { Arbitrum } from 'spark-address-registry/Arbitrum.sol';
import { Base } from 'spark-address-registry/Base.sol';
import { Ethereum } from 'spark-address-registry/Ethereum.sol';
import { ControllerInstance } from "spark-alm-controller/deploy/ControllerInstance.sol";
import { MainnetControllerInit } from "spark-alm-controller/deploy/MainnetControllerInit.sol";
import { ForeignControllerInit } from "spark-alm-controller/deploy/ForeignControllerInit.sol";
import { MainnetController } from "spark-alm-controller/src/MainnetController.sol";
import { ForeignController } from "spark-alm-controller/src/ForeignController.sol";
import { RateLimitHelpers, RateLimitData } from "spark-alm-controller/src/RateLimitHelpers.sol";
import { CCTPForwarder }from "xchain-helpers/forwarders/CCTPForwarder.sol";
/**
* @notice Helper functions for Spark Liquidity Layer
*/
library SLLHelpers {
// This is the same on all chains
address private constant MORPHO = 0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb;
// This is the same on all chains
address private constant ALM_RELAYER_BACKUP = 0x8Cc0Cb0cfB6B7e548cfd395B833c05C346534795;
bytes32 private constant LIMIT_4626_DEPOSIT = keccak256("LIMIT_4626_DEPOSIT");
bytes32 private constant LIMIT_4626_WITHDRAW = keccak256("LIMIT_4626_WITHDRAW");
bytes32 private constant LIMIT_AAVE_DEPOSIT = keccak256("LIMIT_AAVE_DEPOSIT");
bytes32 private constant LIMIT_AAVE_WITHDRAW = keccak256("LIMIT_AAVE_WITHDRAW");
bytes32 private constant LIMIT_USDS_MINT = keccak256("LIMIT_USDS_MINT");
bytes32 private constant LIMIT_USDS_TO_USDC = keccak256("LIMIT_USDS_TO_USDC");
bytes32 private constant LIMIT_USDC_TO_CCTP = keccak256("LIMIT_USDC_TO_CCTP");
bytes32 private constant LIMIT_USDC_TO_DOMAIN = keccak256("LIMIT_USDC_TO_DOMAIN");
bytes32 private constant LIMIT_PSM_DEPOSIT = keccak256("LIMIT_PSM_DEPOSIT");
bytes32 private constant LIMIT_PSM_WITHDRAW = keccak256("LIMIT_PSM_WITHDRAW");
bytes32 private constant LIMIT_CURVE_DEPOSIT = keccak256("LIMIT_CURVE_DEPOSIT");
bytes32 private constant LIMIT_CURVE_SWAP = keccak256("LIMIT_CURVE_SWAP");
bytes32 private constant LIMIT_CURVE_WITHDRAW = keccak256("LIMIT_CURVE_WITHDRAW");
/**
* @notice Activate the bare minimum for Spark Liquidity Layer
* @dev Sets PSM and CCTP rate limits.
*/
function activateSparkLiquidityLayer(
address rateLimits,
address usdc,
address usds,
address susds,
RateLimitData memory usdcDeposit,
RateLimitData memory usdcWithdraw,
RateLimitData memory cctpEthereumDeposit
) internal {
// PSM USDC
RateLimitHelpers.setRateLimitData(
RateLimitHelpers.makeAssetKey(
LIMIT_PSM_DEPOSIT,
usdc
),
rateLimits,
usdcDeposit,
"psmUsdcDepositLimit",
6
);
RateLimitHelpers.setRateLimitData(
RateLimitHelpers.makeAssetKey(
LIMIT_PSM_WITHDRAW,
usdc
),
rateLimits,
usdcWithdraw,
"psmUsdcWithdrawLimit",
6
);
// PSM USDS
RateLimitHelpers.setRateLimitData(
RateLimitHelpers.makeAssetKey(
LIMIT_PSM_DEPOSIT,
usds
),
rateLimits,
RateLimitHelpers.unlimitedRateLimit(),
"psmUsdsDepositLimit",
18
);
RateLimitHelpers.setRateLimitData(
RateLimitHelpers.makeAssetKey(
LIMIT_PSM_WITHDRAW,
usds
),
rateLimits,
RateLimitHelpers.unlimitedRateLimit(),
"psmUsdsWithdrawLimit",
18
);
// PSM sUSDS
RateLimitHelpers.setRateLimitData(
RateLimitHelpers.makeAssetKey(
LIMIT_PSM_DEPOSIT,
susds
),
rateLimits,
RateLimitHelpers.unlimitedRateLimit(),
"psmSusdsDepositLimit",
18
);
RateLimitHelpers.setRateLimitData(
RateLimitHelpers.makeAssetKey(
LIMIT_PSM_WITHDRAW,
susds
),
rateLimits,
RateLimitHelpers.unlimitedRateLimit(),
"psmSusdsWithdrawLimit",
18
);
// CCTP
RateLimitHelpers.setRateLimitData(
LIMIT_USDC_TO_CCTP,
rateLimits,
RateLimitHelpers.unlimitedRateLimit(),
"usdcToCctpLimit",
6
);
RateLimitHelpers.setRateLimitData(
RateLimitHelpers.makeDomainKey(
LIMIT_USDC_TO_DOMAIN,
0 // Ethereum domain id (https://developers.circle.com/stablecoins/evm-smart-contracts)
),
rateLimits,
cctpEthereumDeposit,
"usdcToCctpEthereumLimit",
6
);
}
/**
* @notice Onboard an Aave token
* @dev This will set the deposit to the given numbers with
* the withdraw limit set to unlimited.
*/
function onboardAaveToken(
address rateLimits,
address token,
uint256 depositMax,
uint256 depositSlope
) internal {
IERC20 underlying = IERC20(IAToken(token).UNDERLYING_ASSET_ADDRESS());
RateLimitHelpers.setRateLimitData(
RateLimitHelpers.makeAssetKey(
LIMIT_AAVE_DEPOSIT,
token
),
rateLimits,
RateLimitData({
maxAmount : depositMax,
slope : depositSlope
}),
"atokenDepositLimit",
underlying.decimals()
);
RateLimitHelpers.setRateLimitData(
RateLimitHelpers.makeAssetKey(
LIMIT_AAVE_WITHDRAW,
token
),
rateLimits,
RateLimitHelpers.unlimitedRateLimit(),
"atokenWithdrawLimit",
underlying.decimals()
);
}
/**
* @notice Onboard an ERC4626 vault
* @dev This will set the deposit to the given numbers with
* the withdraw limit set to unlimited.
*/
function onboardERC4626Vault(
address rateLimits,
address vault,
uint256 depositMax,
uint256 depositSlope
) internal {
IERC20 asset = IERC20(IERC4626(vault).asset());
RateLimitHelpers.setRateLimitData(
RateLimitHelpers.makeAssetKey(
LIMIT_4626_DEPOSIT,
vault
),
rateLimits,
RateLimitData({
maxAmount : depositMax,
slope : depositSlope
}),
"vaultDepositLimit",
asset.decimals()
);
RateLimitHelpers.setRateLimitData(
RateLimitHelpers.makeAssetKey(
LIMIT_4626_WITHDRAW,
vault
),
rateLimits,
RateLimitHelpers.unlimitedRateLimit(),
"vaultWithdrawLimit",
asset.decimals()
);
}
/**
* @notice Onboard a Curve pool
*/
function onboardCurvePool(
address controller,
address rateLimits,
address pool,
uint256 maxSlippage,
uint256 swapMax,
uint256 swapSlope,
uint256 depositMax,
uint256 depositSlope,
uint256 withdrawMax,
uint256 withdrawSlope
) internal {
MainnetController(controller).setMaxSlippage(pool, maxSlippage);
if (swapMax != 0) {
RateLimitHelpers.setRateLimitData(
RateLimitHelpers.makeAssetKey(
LIMIT_CURVE_SWAP,
pool
),
rateLimits,
RateLimitData({
maxAmount : swapMax,
slope : swapSlope
}),
"poolSwapLimit",
18
);
}
if (depositMax != 0) {
RateLimitHelpers.setRateLimitData(
RateLimitHelpers.makeAssetKey(
LIMIT_CURVE_DEPOSIT,
pool
),
rateLimits,
RateLimitData({
maxAmount : depositMax,
slope : depositSlope
}),
"poolDepositLimit",
18
);
}
if (withdrawMax != 0) {
RateLimitHelpers.setRateLimitData(
RateLimitHelpers.makeAssetKey(
LIMIT_CURVE_WITHDRAW,
pool
),
rateLimits,
RateLimitData({
maxAmount : withdrawMax,
slope : withdrawSlope
}),
"poolWithdrawLimit",
18
);
}
}
function morphoIdleMarket(
address asset
) internal pure returns (MarketParams memory) {
return MarketParams({
loanToken: asset,
collateralToken: address(0),
oracle: address(0),
irm: address(0),
lltv: 0
});
}
/**
* @notice Activate a Morpho Vault
* @dev This will do the following:
* - Add the relayer as an allocator
* - Add the idle market for the underlying asset with unlimited size
* - Set the supply queue to the idle market
*/
function activateMorphoVault(
address vault,
address relayer
) internal {
IERC20 asset = IERC20(IERC4626(vault).asset());
MarketParams memory idleMarket = morphoIdleMarket(address(asset));
IMetaMorpho(vault).setIsAllocator(
relayer,
true
);
IMetaMorpho(vault).submitCap(
idleMarket,
type(uint184).max
);
IMetaMorpho(vault).acceptCap(
idleMarket
);
Id[] memory supplyQueue = new Id[](1);
supplyQueue[0] = MarketParamsLib.id(idleMarket);
IMetaMorpho(vault).setSupplyQueue(supplyQueue);
}
function setUSDSMintRateLimit(
address rateLimits,
uint256 maxAmount,
uint256 slope
) internal {
RateLimitHelpers.setRateLimitData(
LIMIT_USDS_MINT,
rateLimits,
RateLimitData({
maxAmount : maxAmount,
slope : slope
}),
"USDS mint limit",
18
);
}
function setUSDSToUSDCRateLimit(
address rateLimits,
uint256 maxUsdcAmount,
uint256 slope
) internal {
RateLimitHelpers.setRateLimitData(
LIMIT_USDS_TO_USDC,
rateLimits,
RateLimitData({
maxAmount : maxUsdcAmount,
slope : slope
}),
"Swap USDS to USDC limit",
6
);
}
function setUSDCToCCTPRateLimit(
address rateLimits,
uint256 maxUsdcAmount,
uint256 slope
) internal {
RateLimitHelpers.setRateLimitData(
LIMIT_USDC_TO_CCTP,
rateLimits,
RateLimitData({
maxAmount : maxUsdcAmount,
slope : slope
}),
"Send USDC to CCTP general limit",
6
);
}
function setUSDCToDomainRateLimit(
address rateLimits,
uint32 destinationDomain,
uint256 maxUsdcAmount,
uint256 slope
) internal {
RateLimitHelpers.setRateLimitData(
RateLimitHelpers.makeDomainKey(LIMIT_USDC_TO_DOMAIN, destinationDomain),
rateLimits,
RateLimitData({
maxAmount : maxUsdcAmount,
slope : slope
}),
"Send USDC via CCTP to a specific domain limit",
6
);
}
function addrToBytes32(address addr) internal pure returns (bytes32) {
return bytes32(uint256(uint160(addr)));
}
function upgradeMainnetController(address oldController, address newController) internal {
MainnetControllerInit.MintRecipient[] memory mintRecipients = new MainnetControllerInit.MintRecipient[](2);
mintRecipients[0] = MainnetControllerInit.MintRecipient({
domain : CCTPForwarder.DOMAIN_ID_CIRCLE_BASE,
mintRecipient : addrToBytes32(Base.ALM_PROXY)
});
mintRecipients[1] = MainnetControllerInit.MintRecipient({
domain : CCTPForwarder.DOMAIN_ID_CIRCLE_ARBITRUM_ONE,
mintRecipient : addrToBytes32(Arbitrum.ALM_PROXY)
});
MainnetControllerInit.upgradeController({
controllerInst: ControllerInstance({
almProxy : Ethereum.ALM_PROXY,
controller : newController,
rateLimits : Ethereum.ALM_RATE_LIMITS
}),
configAddresses: MainnetControllerInit.ConfigAddressParams({
freezer : Ethereum.ALM_FREEZER,
relayer : Ethereum.ALM_RELAYER,
oldController : oldController
}),
checkAddresses: MainnetControllerInit.CheckAddressParams({
admin : Ethereum.SPARK_PROXY,
proxy : Ethereum.ALM_PROXY,
rateLimits : Ethereum.ALM_RATE_LIMITS,
vault : Ethereum.ALLOCATOR_VAULT,
psm : Ethereum.PSM,
daiUsds : Ethereum.DAI_USDS,
cctp : Ethereum.CCTP_TOKEN_MESSENGER
}),
mintRecipients: mintRecipients
});
MainnetController(newController).grantRole(MainnetController(newController).RELAYER(), ALM_RELAYER_BACKUP);
}
function upgradeForeignController(
ControllerInstance memory controllerInst,
ForeignControllerInit.ConfigAddressParams memory configAddresses,
ForeignControllerInit.CheckAddressParams memory checkAddresses
) internal {
ForeignControllerInit.MintRecipient[] memory mintRecipients = new ForeignControllerInit.MintRecipient[](1);
mintRecipients[0] = ForeignControllerInit.MintRecipient({
domain : CCTPForwarder.DOMAIN_ID_CIRCLE_ETHEREUM,
mintRecipient : addrToBytes32(Ethereum.ALM_PROXY)
});
ForeignControllerInit.upgradeController({
controllerInst: controllerInst,
configAddresses: configAddresses,
checkAddresses: checkAddresses,
mintRecipients: mintRecipients
});
ForeignController(controllerInst.controller).grantRole(ForeignController(controllerInst.controller).RELAYER(), ALM_RELAYER_BACKUP);
}
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
/**
* @title IPoolAddressesProvider
* @author Aave
* @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;
}// SPDX-License-Identifier: BUSL-1.1
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 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;
}
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;
}
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 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 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 ExecuteWithdrawParams {
address asset;
uint256 amount;
address to;
uint256 reservesCount;
address oracle;
uint8 userEModeCategory;
}
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 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 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 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 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;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
library ConfiguratorInputTypes {
struct InitReserveInput {
address aTokenImpl;
address stableDebtTokenImpl;
address variableDebtTokenImpl;
uint8 underlyingAssetDecimals;
address interestRateStrategyAddress;
address underlyingAsset;
address treasury;
address incentivesController;
string aTokenName;
string aTokenSymbol;
string variableDebtTokenName;
string variableDebtTokenSymbol;
string stableDebtTokenName;
string stableDebtTokenSymbol;
bytes params;
}
struct UpdateATokenInput {
address asset;
address treasury;
address incentivesController;
string name;
string symbol;
address implementation;
bytes params;
}
struct UpdateDebtTokenInput {
address asset;
address incentivesController;
string name;
string symbol;
address implementation;
bytes params;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
// From commit https://github.com/OpenZeppelin/openzeppelin-contracts/commit/8b778fa20d6d76340c5fac1ed66c80273f05b95a
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, 'Address: insufficient balance');
(bool success, ) = recipient.call{value: amount}('');
require(success, 'Address: unable to send value, recipient may have reverted');
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, 'Address: low-level call failed');
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, 'Address: low-level call with value failed');
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, 'Address: insufficient balance for call');
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data)
internal
view
returns (bytes memory)
{
return functionStaticCall(target, data, 'Address: low-level static call failed');
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, 'Address: low-level delegate call failed');
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), 'Address: call to non-contract');
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IPool} from 'sparklend-v1-core/contracts/interfaces/IPool.sol';
import {IPoolConfigurator} from 'sparklend-v1-core/contracts/interfaces/IPoolConfigurator.sol';
import {IAaveOracle} from 'sparklend-v1-core/contracts/interfaces/IAaveOracle.sol';
import {IV3RateStrategyFactory} from './IV3RateStrategyFactory.sol';
/// @dev Examples here assume the usage of the `AaveV3PayloadBase` base contracts
/// contained in this same repository
interface IAaveV3ConfigEngine {
/**
* @dev Required for naming of a/v/s tokens
* Example (mock):
* PoolContext({
* networkName: 'Polygon',
* networkAbbreviation: 'Pol'
* })
*/
struct PoolContext {
string networkName;
string networkAbbreviation;
}
/**
* @dev Example (mock):
* Listing({
* asset: 0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9,
* assetSymbol: 'AAVE',
* priceFeed: 0x547a514d5e3769680Ce22B2361c10Ea13619e8a9,
* rateStrategyParams: Rates.RateStrategyParams({
* optimalUsageRatio: _bpsToRay(80_00),
* baseVariableBorrowRate: _bpsToRay(25), // 0.25%
* variableRateSlope1: _bpsToRay(3_00),
* variableRateSlope2: _bpsToRay(75_00),
* stableRateSlope1: _bpsToRay(3_00),
* stableRateSlope2: _bpsToRay(75_00),
* baseStableRateOffset: _bpsToRay(2_00),
* stableRateExcessOffset: _bpsToRay(3_00),
* optimalStableToTotalDebtRatio: _bpsToRay(30_00)
* }),
* enabledToBorrow: EngineFlags.ENABLED,
* flashloanable: EngineFlags.ENABLED,
* stableRateModeEnabled: EngineFlags.DISABLED,
* borrowableInIsolation: EngineFlags.ENABLED,
* withSiloedBorrowing:, EngineFlags.DISABLED,
* ltv: 70_50, // 70.5%
* liqThreshold: 76_00, // 76%
* liqBonus: 5_00, // 5%
* reserveFactor: 10_00, // 10%
* supplyCap: 100_000, // 100k AAVE
* borrowCap: 60_000, // 60k AAVE
* debtCeiling: 100_000, // 100k USD
* liqProtocolFee: 10_00, // 10%
* eModeCategory: 0, // No category
* }
*/
struct Listing {
address asset;
string assetSymbol;
address priceFeed;
IV3RateStrategyFactory.RateStrategyParams rateStrategyParams; // Mandatory, no matter if enabled for borrowing or not
uint256 enabledToBorrow;
uint256 stableRateModeEnabled; // Only considered is enabledToBorrow == EngineFlags.ENABLED (true)
uint256 borrowableInIsolation; // Only considered is enabledToBorrow == EngineFlags.ENABLED (true)
uint256 withSiloedBorrowing; // Only considered if enabledToBorrow == EngineFlags.ENABLED (true)
uint256 flashloanable; // Independent from enabled to borrow: an asset can be flashloanble and not enabled to borrow
uint256 ltv; // Only considered if liqThreshold > 0
uint256 liqThreshold; // If `0`, the asset will not be enabled as collateral
uint256 liqBonus; // Only considered if liqThreshold > 0
uint256 reserveFactor; // Only considered if enabledToBorrow == EngineFlags.ENABLED (true)
uint256 supplyCap; // If passing any value distinct to EngineFlags.KEEP_CURRENT, always configured
uint256 borrowCap; // If passing any value distinct to EngineFlags.KEEP_CURRENT, always configured
uint256 debtCeiling; // Only considered if liqThreshold > 0
uint256 liqProtocolFee; // Only considered if liqThreshold > 0
uint8 eModeCategory; // If `O`, no eMode category will be set
}
struct TokenImplementations {
address aToken;
address vToken;
address sToken;
}
struct ListingWithCustomImpl {
Listing base;
TokenImplementations implementations;
}
/**
* @dev Example (mock):
* CapsUpdate({
* asset: AaveV3EthereumAssets.AAVE_UNDERLYING,
* supplyCap: 1_000_000,
* borrowCap: EngineFlags.KEEP_CURRENT
* }
*/
struct CapsUpdate {
address asset;
uint256 supplyCap; // Pass any value, of EngineFlags.KEEP_CURRENT to keep it as it is
uint256 borrowCap; // Pass any value, of EngineFlags.KEEP_CURRENT to keep it as it is
}
/**
* @dev Example (mock):
* PriceFeedUpdate({
* asset: AaveV3EthereumAssets.AAVE_UNDERLYING,
* priceFeed: 0x547a514d5e3769680Ce22B2361c10Ea13619e8a9
* })
*/
struct PriceFeedUpdate {
address asset;
address priceFeed;
}
/**
* @dev Example (mock):
* CollateralUpdate({
* asset: AaveV3EthereumAssets.AAVE_UNDERLYING,
* ltv: 60_00,
* liqThreshold: 70_00,
* liqBonus: EngineFlags.KEEP_CURRENT,
* debtCeiling: EngineFlags.KEEP_CURRENT,
* liqProtocolFee: 7_00,
* eModeCategory: EngineFlags.KEEP_CURRENT
* })
*/
struct CollateralUpdate {
address asset;
uint256 ltv;
uint256 liqThreshold;
uint256 liqBonus;
uint256 debtCeiling;
uint256 liqProtocolFee;
uint256 eModeCategory;
}
/**
* @dev Example (mock):
* BorrowUpdate({
* asset: AaveV3EthereumAssets.AAVE_UNDERLYING,
* enabledToBorrow: EngineFlags.ENABLED,
* flashloanable: EngineFlags.KEEP_CURRENT,
* stableRateModeEnabled: EngineFlags.KEEP_CURRENT,
* borrowableInIsolation: EngineFlags.KEEP_CURRENT,
* withSiloedBorrowing: EngineFlags.KEEP_CURRENT,
* reserveFactor: 15_00, // 15%
* })
*/
struct BorrowUpdate {
address asset;
uint256 enabledToBorrow;
uint256 flashloanable;
uint256 stableRateModeEnabled;
uint256 borrowableInIsolation;
uint256 withSiloedBorrowing;
uint256 reserveFactor;
}
/**
* @dev Example (mock):
* RateStrategyUpdate({
* asset: AaveV3OptimismAssets.USDT_UNDERLYING,
* params: Rates.RateStrategyParams({
* optimalUsageRatio: _bpsToRay(80_00),
* baseVariableBorrowRate: EngineFlags.KEEP_CURRENT,
* variableRateSlope1: EngineFlags.KEEP_CURRENT,
* variableRateSlope2: _bpsToRay(75_00),
* stableRateSlope1: EngineFlags.KEEP_CURRENT,
* stableRateSlope2: _bpsToRay(75_00),
* baseStableRateOffset: EngineFlags.KEEP_CURRENT,
* stableRateExcessOffset: EngineFlags.KEEP_CURRENT,
* optimalStableToTotalDebtRatio: EngineFlags.KEEP_CURRENT
* })
* })
*/
struct RateStrategyUpdate {
address asset;
IV3RateStrategyFactory.RateStrategyParams params;
}
/**
* @notice Performs full listing of the assets, in the Aave pool configured in this engine instance
* @param context `PoolContext` struct, effectively meta-data for naming of a/v/s tokens.
* More information on the documentation of the struct.
* @param listings `Listing[]` list of declarative configs for every aspect of the asset listings.
* More information on the documentation of the struct.
*/
function listAssets(PoolContext memory context, Listing[] memory listings) external;
/**
* @notice Performs full listings of assets, in the Aave pool configured in this engine instance
* @dev This function allows more customization, especifically enables to set custom implementations
* for a/v/s tokens.
* IMPORTANT. Use it only if understanding the internals of the Aave v3 protocol
* @param context `PoolContext` struct, effectively meta-data for naming of a/v/s tokens.
* More information on the documentation of the struct.
* @param listings `ListingWithCustomImpl[]` list of declarative configs for every aspect of the asset listings.
*/
function listAssetsCustom(
PoolContext memory context,
ListingWithCustomImpl[] memory listings
) external;
/**
* @notice Performs an update of the caps (supply, borrow) of the assets, in the Aave pool configured in this engine instance
* @param updates `CapsUpdate[]` list of declarative updates containing the new caps
* More information on the documentation of the struct.
*/
function updateCaps(CapsUpdate[] memory updates) external;
/**
* @notice Performs an update on the rate strategy params of the assets, in the Aave pool configured in this engine instance
* @dev The engine itself manages if a new rate strategy needs to be deployed or if an existing one can be re-used
* @param updates `RateStrategyUpdate[]` list of declarative updates containing the new rate strategy params
* More information on the documentation of the struct.
*/
function updateRateStrategies(RateStrategyUpdate[] memory updates) external;
/**
* @notice Performs an update of the collateral-related params of the assets, in the Aave pool configured in this engine instance
* @param updates `CollateralUpdate[]` list of declarative updates containing the new parameters
* More information on the documentation of the struct.
*/
function updateCollateralSide(CollateralUpdate[] memory updates) external;
/**
* @notice Performs an update of the price feed of the assets, in the Aave pool configured in this engine instance
* @param updates `PriceFeedUpdate[]` list of declarative updates containing the new parameters
* More information on the documentation of the struct.
*/
function updatePriceFeeds(PriceFeedUpdate[] memory updates) external;
/**
* @notice Performs an update of the borrow-related params of the assets, in the Aave pool configured in this engine instance
* @param updates `BorrowUpdate[]` list of declarative updates containing the new parameters
* More information on the documentation of the struct.
*/
function updateBorrowSide(BorrowUpdate[] memory updates) external;
function RATE_STRATEGIES_FACTORY() external view returns (IV3RateStrategyFactory);
function POOL() external view returns (IPool);
function POOL_CONFIGURATOR() external view returns (IPoolConfigurator);
function ORACLE() external view returns (IAaveOracle);
function ATOKEN_IMPL() external view returns (address);
function VTOKEN_IMPL() external view returns (address);
function STOKEN_IMPL() external view returns (address);
function REWARDS_CONTROLLER() external view returns (address);
function COLLECTOR() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IPoolAddressesProvider} from 'sparklend-v1-core/contracts/interfaces/IPoolAddressesProvider.sol';
import {IDefaultInterestRateStrategy} from 'sparklend-v1-core/contracts/interfaces/IDefaultInterestRateStrategy.sol';
interface IV3RateStrategyFactory {
event RateStrategyCreated(
address indexed strategy,
bytes32 indexed hashedParam,
RateStrategyParams params
);
/// @dev same parameters and the ones received on the constructor of DefaultReserveInterestRateStrategy
/// in practise defining the strategy itself
struct RateStrategyParams {
uint256 optimalUsageRatio;
uint256 baseVariableBorrowRate;
uint256 variableRateSlope1;
uint256 variableRateSlope2;
uint256 stableRateSlope1;
uint256 stableRateSlope2;
uint256 baseStableRateOffset;
uint256 stableRateExcessOffset;
uint256 optimalStableToTotalDebtRatio;
}
/**
* @notice Create new rate strategies from a list of parameters
* @dev If a strategy with exactly the same `RateStrategyParams` already exists, no creation happens but
* its address is returned
* @param params `RateStrategyParams[]` list of parameters for multiple strategies
* @return address[] list of strategies
*/
function createStrategies(RateStrategyParams[] memory params) external returns (address[] memory);
/**
* @notice Returns the identifier of a rate strategy from its parameters
* @param params `RateStrategyParams` the parameters of the rate strategy
* @return bytes32 the keccak256 hash generated from the `RateStrategyParams` parameters
* to be used as identifier of the rate strategy on the factory
*/
function strategyHashFromParams(RateStrategyParams memory params) external pure returns (bytes32);
/**
* @notice Returns all the strategies registered in the factory
* @return address[] list of strategies
*/
function getAllStrategies() external view returns (address[] memory);
/**
* @notice Returns the a strategy added, given its parameters.
* @dev Only if the strategy is registered in the factory.
* @param params `RateStrategyParams` the parameters of the rate strategy
* @return address the address of the strategy
*/
function getStrategyByParams(RateStrategyParams memory params) external view returns (address);
/**
* @notice From an asset in the Aave v3 pool, returns exclusively its parameters
* @param asset The address of the asset
* @return RateStrategyParams The parameters or the strategy, or empty RateStrategyParams struct
*/
function getStrategyDataOfAsset(address asset) external view returns (RateStrategyParams memory);
/**
* @notice From a rate strategy address, returns its parameters
* @param strategy The address of the rate strategy
* @return RateStrategyParams Struct with the parameters of the strategy
*/
function getStrategyData(
IDefaultInterestRateStrategy strategy
) external view returns (RateStrategyParams memory);
function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)
pragma solidity ^0.8.20;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev The `account` is missing a role.
*/
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
/**
* @dev The caller of a function is not the expected one.
*
* NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
*/
error AccessControlBadConfirmation();
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*/
function renounceRole(bytes32 role, address callerConfirmation) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
import {IScaledBalanceToken} from './IScaledBalanceToken.sol';
import {IInitializableAToken} from './IInitializableAToken.sol';
/**
* @title IAToken
* @author Aave
* @notice Defines the basic interface for an AToken.
*/
interface IAToken is IERC20, IScaledBalanceToken, IInitializableAToken {
/**
* @dev Emitted during the transfer action
* @param from The user whose tokens are being transferred
* @param to The recipient
* @param value The scaled amount being transferred
* @param index The next liquidity index of the reserve
*/
event BalanceTransfer(address indexed from, address indexed to, uint256 value, uint256 index);
/**
* @notice Mints `amount` aTokens to `user`
* @param caller The address performing the mint
* @param onBehalfOf The address of the user that will receive the minted aTokens
* @param amount The amount of tokens getting minted
* @param index The next liquidity index of the reserve
* @return `true` if the the previous balance of the user was 0
*/
function mint(
address caller,
address onBehalfOf,
uint256 amount,
uint256 index
) external returns (bool);
/**
* @notice Burns aTokens from `user` and sends the equivalent amount of underlying to `receiverOfUnderlying`
* @dev In some instances, the mint event could be emitted from a burn transaction
* if the amount to burn is less than the interest that the user accrued
* @param from The address from which the aTokens will be burned
* @param receiverOfUnderlying The address that will receive the underlying
* @param amount The amount being burned
* @param index The next liquidity index of the reserve
*/
function burn(address from, address receiverOfUnderlying, uint256 amount, uint256 index) external;
/**
* @notice Mints aTokens to the reserve treasury
* @param amount The amount of tokens getting minted
* @param index The next liquidity index of the reserve
*/
function mintToTreasury(uint256 amount, uint256 index) external;
/**
* @notice Transfers aTokens in the event of a borrow being liquidated, in case the liquidators reclaims the aToken
* @param from The address getting liquidated, current owner of the aTokens
* @param to The recipient
* @param value The amount of tokens getting transferred
*/
function transferOnLiquidation(address from, address to, uint256 value) external;
/**
* @notice Transfers the underlying asset to `target`.
* @dev Used by the Pool to transfer assets in borrow(), withdraw() and flashLoan()
* @param target The recipient of the underlying
* @param amount The amount getting transferred
*/
function transferUnderlyingTo(address target, uint256 amount) external;
/**
* @notice Handles the underlying received by the aToken after the transfer has been completed.
* @dev The default implementation is empty as with standard ERC20 tokens, nothing needs to be done after the
* transfer is concluded. However in the future there may be aTokens that allow for example to stake the underlying
* to receive LM rewards. In that case, `handleRepayment()` would perform the staking of the underlying asset.
* @param user The user executing the repayment
* @param onBehalfOf The address of the user who will get his debt reduced/removed
* @param amount The amount getting repaid
*/
function handleRepayment(address user, address onBehalfOf, uint256 amount) external;
/**
* @notice Allow passing a signed message to approve spending
* @dev implements the permit function as for
* https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md
* @param owner The owner of the funds
* @param spender The spender
* @param value The amount
* @param deadline The deadline timestamp, type(uint256).max for max deadline
* @param v Signature param
* @param s Signature param
* @param r Signature param
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @notice Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH)
* @return The address of the underlying asset
*/
function UNDERLYING_ASSET_ADDRESS() external view returns (address);
/**
* @notice Returns the address of the Aave treasury, receiving the fees on this aToken.
* @return Address of the Aave treasury
*/
function RESERVE_TREASURY_ADDRESS() external view returns (address);
/**
* @notice Get the domain separator for the token
* @dev Return cached value if chainId matches cache, otherwise recomputes separator
* @return The domain separator of the token at current chain
*/
function DOMAIN_SEPARATOR() external view returns (bytes32);
/**
* @notice Returns the nonce for owner.
* @param owner The address of the owner
* @return The nonce of the owner
*/
function nonces(address owner) external view returns (uint256);
/**
* @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;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2;
/// @dev Interface of the ERC20 standard as defined in the EIP.
/// @dev This includes the optional name, symbol, and decimals metadata.
interface IERC20 {
/// @dev Emitted when `value` tokens are moved from one account (`from`) to another (`to`).
event Transfer(address indexed from, address indexed to, uint256 value);
/// @dev Emitted when the allowance of a `spender` for an `owner` is set, where `value`
/// is the new allowance.
event Approval(address indexed owner, address indexed spender, uint256 value);
/// @notice Returns the amount of tokens in existence.
function totalSupply() external view returns (uint256);
/// @notice Returns the amount of tokens owned by `account`.
function balanceOf(address account) external view returns (uint256);
/// @notice Moves `amount` tokens from the caller's account to `to`.
function transfer(address to, uint256 amount) external returns (bool);
/// @notice Returns the remaining number of tokens that `spender` is allowed
/// to spend on behalf of `owner`
function allowance(address owner, address spender) external view returns (uint256);
/// @notice Sets `amount` as the allowance of `spender` over the caller's tokens.
/// @dev Be aware of front-running risks: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
function approve(address spender, uint256 amount) external returns (bool);
/// @notice Moves `amount` tokens from `from` to `to` using the allowance mechanism.
/// `amount` is then deducted from the caller's allowance.
function transferFrom(address from, address to, uint256 amount) external returns (bool);
/// @notice Returns the name of the token.
function name() external view returns (string memory);
/// @notice Returns the symbol of the token.
function symbol() external view returns (string memory);
/// @notice Returns the decimals places of the token.
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2;
import {IERC20} from "./IERC20.sol";
/// @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in
/// https://eips.ethereum.org/EIPS/eip-4626
interface IERC4626 is IERC20 {
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares
);
/// @notice Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
/// @dev
/// - MUST be an ERC-20 token contract.
/// - MUST NOT revert.
function asset() external view returns (address assetTokenAddress);
/// @notice Returns the total amount of the underlying asset that is “managed” by Vault.
/// @dev
/// - SHOULD include any compounding that occurs from yield.
/// - MUST be inclusive of any fees that are charged against assets in the Vault.
/// - MUST NOT revert.
function totalAssets() external view returns (uint256 totalManagedAssets);
/// @notice Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
/// scenario where all the conditions are met.
/// @dev
/// - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
/// - MUST NOT show any variations depending on the caller.
/// - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
/// - MUST NOT revert.
///
/// NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
/// “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
/// from.
function convertToShares(uint256 assets) external view returns (uint256 shares);
/// @notice Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
/// scenario where all the conditions are met.
/// @dev
/// - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
/// - MUST NOT show any variations depending on the caller.
/// - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
/// - MUST NOT revert.
///
/// NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
/// “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
/// from.
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/// @notice Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
/// through a deposit call.
/// @dev
/// - MUST return a limited value if receiver is subject to some deposit limit.
/// - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
/// - MUST NOT revert.
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
/// @notice Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
/// current on-chain conditions.
/// @dev
/// - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
/// call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
/// in the same transaction.
/// - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
/// deposit would be accepted, regardless if the user has enough tokens approved, etc.
/// - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
/// - MUST NOT revert.
///
/// NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
/// share price or some other type of condition, meaning the depositor will lose assets by depositing.
function previewDeposit(uint256 assets) external view returns (uint256 shares);
/// @notice Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
/// @dev
/// - MUST emit the Deposit event.
/// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
/// deposit execution, and are accounted for during deposit.
/// - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
/// approving enough underlying tokens to the Vault contract, etc).
///
/// NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/// @notice Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
/// @dev
/// - MUST return a limited value if receiver is subject to some mint limit.
/// - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
/// - MUST NOT revert.
function maxMint(address receiver) external view returns (uint256 maxShares);
/// @notice Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
/// current on-chain conditions.
/// @dev
/// - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
/// in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
/// same transaction.
/// - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
/// would be accepted, regardless if the user has enough tokens approved, etc.
/// - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
/// - MUST NOT revert.
///
/// NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
/// share price or some other type of condition, meaning the depositor will lose assets by minting.
function previewMint(uint256 shares) external view returns (uint256 assets);
/// @notice Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
/// @dev
/// - MUST emit the Deposit event.
/// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
/// execution, and are accounted for during mint.
/// - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
/// approving enough underlying tokens to the Vault contract, etc).
///
/// NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/// @notice Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
/// Vault, through a withdrawal call.
/// @dev
/// - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
/// - MUST NOT revert.
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
/// @notice Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
/// given current on-chain conditions.
/// @dev
/// - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
/// call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
/// called
/// in the same transaction.
/// - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
/// the withdrawal would be accepted, regardless if the user has enough shares, etc.
/// - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
/// - MUST NOT revert.
///
/// NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
/// share price or some other type of condition, meaning the depositor will lose assets by depositing.
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
/// @notice Burns shares from owner and sends exactly assets of underlying tokens to receiver.
/// @dev
/// - MUST emit the Withdraw event.
/// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
/// withdraw execution, and are accounted for during withdrawal.
/// - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
/// not having enough shares, etc).
///
/// Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
/// Those methods should be performed separately.
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
/// @notice Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
/// through a redeem call.
/// @dev
/// - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
/// - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
/// - MUST NOT revert.
function maxRedeem(address owner) external view returns (uint256 maxShares);
/// @notice Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
/// given current on-chain conditions.
/// @dev
/// - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
/// in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
/// same transaction.
/// - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
/// redemption would be accepted, regardless if the user has enough shares, etc.
/// - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
/// - MUST NOT revert.
///
/// NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
/// share price or some other type of condition, meaning the depositor will lose assets by redeeming.
function previewRedeem(uint256 shares) external view returns (uint256 assets);
/// @notice Burns exactly shares from owner and sends assets of underlying tokens to receiver.
/// @dev
/// - MUST emit the Withdraw event.
/// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
/// redeem execution, and are accounted for during redeem.
/// - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
/// not having enough shares, etc).
///
/// NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
/// Those methods should be performed separately.
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
import {IMorpho, Id, MarketParams} from "../../lib/morpho-blue/src/interfaces/IMorpho.sol";
import {IERC4626} from "../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol";
import {IERC20Permit} from "../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol";
import {MarketConfig, PendingUint192, PendingAddress} from "../libraries/PendingLib.sol";
struct MarketAllocation {
/// @notice The market to allocate.
MarketParams marketParams;
/// @notice The amount of assets to allocate.
uint256 assets;
}
interface IMulticall {
function multicall(bytes[] calldata) external returns (bytes[] memory);
}
interface IOwnable {
function owner() external view returns (address);
function transferOwnership(address) external;
function renounceOwnership() external;
function acceptOwnership() external;
function pendingOwner() external view returns (address);
}
/// @dev This interface is used for factorizing IMetaMorphoStaticTyping and IMetaMorpho.
/// @dev Consider using the IMetaMorpho interface instead of this one.
interface IMetaMorphoBase {
/// @notice The address of the Morpho contract.
function MORPHO() external view returns (IMorpho);
function DECIMALS_OFFSET() external view returns (uint8);
/// @notice The address of the curator.
function curator() external view returns (address);
/// @notice Stores whether an address is an allocator or not.
function isAllocator(address target) external view returns (bool);
/// @notice The current guardian. Can be set even without the timelock set.
function guardian() external view returns (address);
/// @notice The current fee.
function fee() external view returns (uint96);
/// @notice The fee recipient.
function feeRecipient() external view returns (address);
/// @notice The skim recipient.
function skimRecipient() external view returns (address);
/// @notice The current timelock.
function timelock() external view returns (uint256);
/// @dev Stores the order of markets on which liquidity is supplied upon deposit.
/// @dev Can contain any market. A market is skipped as soon as its supply cap is reached.
function supplyQueue(uint256) external view returns (Id);
/// @notice Returns the length of the supply queue.
function supplyQueueLength() external view returns (uint256);
/// @dev Stores the order of markets from which liquidity is withdrawn upon withdrawal.
/// @dev Always contain all non-zero cap markets as well as all markets on which the vault supplies liquidity,
/// without duplicate.
function withdrawQueue(uint256) external view returns (Id);
/// @notice Returns the length of the withdraw queue.
function withdrawQueueLength() external view returns (uint256);
/// @notice Stores the total assets managed by this vault when the fee was last accrued.
/// @dev May be greater than `totalAssets()` due to removal of markets with non-zero supply or socialized bad debt.
/// This difference will decrease the fee accrued until one of the functions updating `lastTotalAssets` is
/// triggered (deposit/mint/withdraw/redeem/setFee/setFeeRecipient).
function lastTotalAssets() external view returns (uint256);
/// @notice Submits a `newTimelock`.
/// @dev Warning: Reverts if a timelock is already pending. Revoke the pending timelock to overwrite it.
/// @dev In case the new timelock is higher than the current one, the timelock is set immediately.
function submitTimelock(uint256 newTimelock) external;
/// @notice Accepts the pending timelock.
function acceptTimelock() external;
/// @notice Revokes the pending timelock.
/// @dev Does not revert if there is no pending timelock.
function revokePendingTimelock() external;
/// @notice Submits a `newSupplyCap` for the market defined by `marketParams`.
/// @dev Warning: Reverts if a cap is already pending. Revoke the pending cap to overwrite it.
/// @dev Warning: Reverts if a market removal is pending.
/// @dev In case the new cap is lower than the current one, the cap is set immediately.
function submitCap(MarketParams memory marketParams, uint256 newSupplyCap) external;
/// @notice Accepts the pending cap of the market defined by `marketParams`.
function acceptCap(MarketParams memory marketParams) external;
/// @notice Revokes the pending cap of the market defined by `id`.
/// @dev Does not revert if there is no pending cap.
function revokePendingCap(Id id) external;
/// @notice Submits a forced market removal from the vault, eventually losing all funds supplied to the market.
/// @notice Funds can be recovered by enabling this market again and withdrawing from it (using `reallocate`),
/// but funds will be distributed pro-rata to the shares at the time of withdrawal, not at the time of removal.
/// @notice This forced removal is expected to be used as an emergency process in case a market constantly reverts.
/// To softly remove a sane market, the curator role is expected to bundle a reallocation that empties the market
/// first (using `reallocate`), followed by the removal of the market (using `updateWithdrawQueue`).
/// @dev Warning: Removing a market with non-zero supply will instantly impact the vault's price per share.
/// @dev Warning: Reverts for non-zero cap or if there is a pending cap. Successfully submitting a zero cap will
/// prevent such reverts.
function submitMarketRemoval(MarketParams memory marketParams) external;
/// @notice Revokes the pending removal of the market defined by `id`.
/// @dev Does not revert if there is no pending market removal.
function revokePendingMarketRemoval(Id id) external;
/// @notice Submits a `newGuardian`.
/// @notice Warning: a malicious guardian could disrupt the vault's operation, and would have the power to revoke
/// any pending guardian.
/// @dev In case there is no guardian, the gardian is set immediately.
/// @dev Warning: Submitting a gardian will overwrite the current pending gardian.
function submitGuardian(address newGuardian) external;
/// @notice Accepts the pending guardian.
function acceptGuardian() external;
/// @notice Revokes the pending guardian.
function revokePendingGuardian() external;
/// @notice Skims the vault `token` balance to `skimRecipient`.
function skim(address) external;
/// @notice Sets `newAllocator` as an allocator or not (`newIsAllocator`).
function setIsAllocator(address newAllocator, bool newIsAllocator) external;
/// @notice Sets `curator` to `newCurator`.
function setCurator(address newCurator) external;
/// @notice Sets the `fee` to `newFee`.
function setFee(uint256 newFee) external;
/// @notice Sets `feeRecipient` to `newFeeRecipient`.
function setFeeRecipient(address newFeeRecipient) external;
/// @notice Sets `skimRecipient` to `newSkimRecipient`.
function setSkimRecipient(address newSkimRecipient) external;
/// @notice Sets `supplyQueue` to `newSupplyQueue`.
/// @param newSupplyQueue is an array of enabled markets, and can contain duplicate markets, but it would only
/// increase the cost of depositing to the vault.
function setSupplyQueue(Id[] calldata newSupplyQueue) external;
/// @notice Updates the withdraw queue. Some markets can be removed, but no market can be added.
/// @notice Removing a market requires the vault to have 0 supply on it, or to have previously submitted a removal
/// for this market (with the function `submitMarketRemoval`).
/// @notice Warning: Anyone can supply on behalf of the vault so the call to `updateWithdrawQueue` that expects a
/// market to be empty can be griefed by a front-run. To circumvent this, the allocator can simply bundle a
/// reallocation that withdraws max from this market with a call to `updateWithdrawQueue`.
/// @dev Warning: Removing a market with supply will decrease the fee accrued until one of the functions updating
/// `lastTotalAssets` is triggered (deposit/mint/withdraw/redeem/setFee/setFeeRecipient).
/// @dev Warning: `updateWithdrawQueue` is not idempotent. Submitting twice the same tx will change the queue twice.
/// @param indexes The indexes of each market in the previous withdraw queue, in the new withdraw queue's order.
function updateWithdrawQueue(uint256[] calldata indexes) external;
/// @notice Reallocates the vault's liquidity so as to reach a given allocation of assets on each given market.
/// @notice The allocator can withdraw from any market, even if it's not in the withdraw queue, as long as the loan
/// token of the market is the same as the vault's asset.
/// @dev The behavior of the reallocation can be altered by state changes, including:
/// - Deposits on the vault that supplies to markets that are expected to be supplied to during reallocation.
/// - Withdrawals from the vault that withdraws from markets that are expected to be withdrawn from during
/// reallocation.
/// - Donations to the vault on markets that are expected to be supplied to during reallocation.
/// - Withdrawals from markets that are expected to be withdrawn from during reallocation.
/// @dev Sender is expected to pass `assets = type(uint256).max` with the last MarketAllocation of `allocations` to
/// supply all the remaining withdrawn liquidity, which would ensure that `totalWithdrawn` = `totalSupplied`.
function reallocate(MarketAllocation[] calldata allocations) external;
}
/// @dev This interface is inherited by MetaMorpho so that function signatures are checked by the compiler.
/// @dev Consider using the IMetaMorpho interface instead of this one.
interface IMetaMorphoStaticTyping is IMetaMorphoBase {
/// @notice Returns the current configuration of each market.
function config(Id) external view returns (uint184 cap, bool enabled, uint64 removableAt);
/// @notice Returns the pending guardian.
function pendingGuardian() external view returns (address guardian, uint64 validAt);
/// @notice Returns the pending cap for each market.
function pendingCap(Id) external view returns (uint192 value, uint64 validAt);
/// @notice Returns the pending timelock.
function pendingTimelock() external view returns (uint192 value, uint64 validAt);
}
/// @title IMetaMorpho
/// @author Morpho Labs
/// @custom:contact [email protected]
/// @dev Use this interface for MetaMorpho to have access to all the functions with the appropriate function signatures.
interface IMetaMorpho is IMetaMorphoBase, IERC4626, IERC20Permit, IOwnable, IMulticall {
/// @notice Returns the current configuration of each market.
function config(Id) external view returns (MarketConfig memory);
/// @notice Returns the pending guardian.
function pendingGuardian() external view returns (PendingAddress memory);
/// @notice Returns the pending cap for each market.
function pendingCap(Id) external view returns (PendingUint192 memory);
/// @notice Returns the pending timelock.
function pendingTimelock() external view returns (PendingUint192 memory);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
type Id is bytes32;
struct MarketParams {
address loanToken;
address collateralToken;
address oracle;
address irm;
uint256 lltv;
}
/// @dev Warning: For `feeRecipient`, `supplyShares` does not contain the accrued shares since the last interest
/// accrual.
struct Position {
uint256 supplyShares;
uint128 borrowShares;
uint128 collateral;
}
/// @dev Warning: `totalSupplyAssets` does not contain the accrued interest since the last interest accrual.
/// @dev Warning: `totalBorrowAssets` does not contain the accrued interest since the last interest accrual.
/// @dev Warning: `totalSupplyShares` does not contain the additional shares accrued by `feeRecipient` since the last
/// interest accrual.
struct Market {
uint128 totalSupplyAssets;
uint128 totalSupplyShares;
uint128 totalBorrowAssets;
uint128 totalBorrowShares;
uint128 lastUpdate;
uint128 fee;
}
struct Authorization {
address authorizer;
address authorized;
bool isAuthorized;
uint256 nonce;
uint256 deadline;
}
struct Signature {
uint8 v;
bytes32 r;
bytes32 s;
}
/// @dev This interface is used for factorizing IMorphoStaticTyping and IMorpho.
/// @dev Consider using the IMorpho interface instead of this one.
interface IMorphoBase {
/// @notice The EIP-712 domain separator.
/// @dev Warning: Every EIP-712 signed message based on this domain separator can be reused on another chain sharing
/// the same chain id because the domain separator would be the same.
function DOMAIN_SEPARATOR() external view returns (bytes32);
/// @notice The owner of the contract.
/// @dev It has the power to change the owner.
/// @dev It has the power to set fees on markets and set the fee recipient.
/// @dev It has the power to enable but not disable IRMs and LLTVs.
function owner() external view returns (address);
/// @notice The fee recipient of all markets.
/// @dev The recipient receives the fees of a given market through a supply position on that market.
function feeRecipient() external view returns (address);
/// @notice Whether the `irm` is enabled.
function isIrmEnabled(address irm) external view returns (bool);
/// @notice Whether the `lltv` is enabled.
function isLltvEnabled(uint256 lltv) external view returns (bool);
/// @notice Whether `authorized` is authorized to modify `authorizer`'s position on all markets.
/// @dev Anyone is authorized to modify their own positions, regardless of this variable.
function isAuthorized(address authorizer, address authorized) external view returns (bool);
/// @notice The `authorizer`'s current nonce. Used to prevent replay attacks with EIP-712 signatures.
function nonce(address authorizer) external view returns (uint256);
/// @notice Sets `newOwner` as `owner` of the contract.
/// @dev Warning: No two-step transfer ownership.
/// @dev Warning: The owner can be set to the zero address.
function setOwner(address newOwner) external;
/// @notice Enables `irm` as a possible IRM for market creation.
/// @dev Warning: It is not possible to disable an IRM.
function enableIrm(address irm) external;
/// @notice Enables `lltv` as a possible LLTV for market creation.
/// @dev Warning: It is not possible to disable a LLTV.
function enableLltv(uint256 lltv) external;
/// @notice Sets the `newFee` for the given market `marketParams`.
/// @param newFee The new fee, scaled by WAD.
/// @dev Warning: The recipient can be the zero address.
function setFee(MarketParams memory marketParams, uint256 newFee) external;
/// @notice Sets `newFeeRecipient` as `feeRecipient` of the fee.
/// @dev Warning: If the fee recipient is set to the zero address, fees will accrue there and will be lost.
/// @dev Modifying the fee recipient will allow the new recipient to claim any pending fees not yet accrued. To
/// ensure that the current recipient receives all due fees, accrue interest manually prior to making any changes.
function setFeeRecipient(address newFeeRecipient) external;
/// @notice Creates the market `marketParams`.
/// @dev Here is the list of assumptions on the market's dependencies (tokens, IRM and oracle) that guarantees
/// Morpho behaves as expected:
/// - The token should be ERC-20 compliant, except that it can omit return values on `transfer` and `transferFrom`.
/// - The token balance of Morpho should only decrease on `transfer` and `transferFrom`. In particular, tokens with
/// burn functions are not supported.
/// - The token should not re-enter Morpho on `transfer` nor `transferFrom`.
/// - The token balance of the sender (resp. receiver) should decrease (resp. increase) by exactly the given amount
/// on `transfer` and `transferFrom`. In particular, tokens with fees on transfer are not supported.
/// - The IRM should not re-enter Morpho.
/// - The oracle should return a price with the correct scaling.
/// @dev Here is a list of properties on the market's dependencies that could break Morpho's liveness properties
/// (funds could get stuck):
/// - The token can revert on `transfer` and `transferFrom` for a reason other than an approval or balance issue.
/// - A very high amount of assets (~1e35) supplied or borrowed can make the computation of `toSharesUp` and
/// `toSharesDown` overflow.
/// - The IRM can revert on `borrowRate`.
/// - A very high borrow rate returned by the IRM can make the computation of `interest` in `_accrueInterest`
/// overflow.
/// - The oracle can revert on `price`. Note that this can be used to prevent `borrow`, `withdrawCollateral` and
/// `liquidate` from being used under certain market conditions.
/// - A very high price returned by the oracle can make the computation of `maxBorrow` in `_isHealthy` overflow, or
/// the computation of `assetsRepaid` in `liquidate` overflow.
/// @dev The borrow share price of a market with less than 1e4 assets borrowed can be decreased by manipulations, to
/// the point where `totalBorrowShares` is very large and borrowing overflows.
function createMarket(MarketParams memory marketParams) external;
/// @notice Supplies `assets` or `shares` on behalf of `onBehalf`, optionally calling back the caller's
/// `onMorphoSupply` function with the given `data`.
/// @dev Either `assets` or `shares` should be zero. Most use cases should rely on `assets` as an input so the
/// caller is guaranteed to have `assets` tokens pulled from their balance, but the possibility to mint a specific
/// amount of shares is given for full compatibility and precision.
/// @dev Supplying a large amount can revert for overflow.
/// @dev Supplying an amount of shares may lead to supply more or fewer assets than expected due to slippage.
/// Consider using the `assets` parameter to avoid this.
/// @param marketParams The market to supply assets to.
/// @param assets The amount of assets to supply.
/// @param shares The amount of shares to mint.
/// @param onBehalf The address that will own the increased supply position.
/// @param data Arbitrary data to pass to the `onMorphoSupply` callback. Pass empty data if not needed.
/// @return assetsSupplied The amount of assets supplied.
/// @return sharesSupplied The amount of shares minted.
function supply(
MarketParams memory marketParams,
uint256 assets,
uint256 shares,
address onBehalf,
bytes memory data
) external returns (uint256 assetsSupplied, uint256 sharesSupplied);
/// @notice Withdraws `assets` or `shares` on behalf of `onBehalf` and sends the assets to `receiver`.
/// @dev Either `assets` or `shares` should be zero. To withdraw max, pass the `shares`'s balance of `onBehalf`.
/// @dev `msg.sender` must be authorized to manage `onBehalf`'s positions.
/// @dev Withdrawing an amount corresponding to more shares than supplied will revert for underflow.
/// @dev It is advised to use the `shares` input when withdrawing the full position to avoid reverts due to
/// conversion roundings between shares and assets.
/// @param marketParams The market to withdraw assets from.
/// @param assets The amount of assets to withdraw.
/// @param shares The amount of shares to burn.
/// @param onBehalf The address of the owner of the supply position.
/// @param receiver The address that will receive the withdrawn assets.
/// @return assetsWithdrawn The amount of assets withdrawn.
/// @return sharesWithdrawn The amount of shares burned.
function withdraw(
MarketParams memory marketParams,
uint256 assets,
uint256 shares,
address onBehalf,
address receiver
) external returns (uint256 assetsWithdrawn, uint256 sharesWithdrawn);
/// @notice Borrows `assets` or `shares` on behalf of `onBehalf` and sends the assets to `receiver`.
/// @dev Either `assets` or `shares` should be zero. Most use cases should rely on `assets` as an input so the
/// caller is guaranteed to borrow `assets` of tokens, but the possibility to mint a specific amount of shares is
/// given for full compatibility and precision.
/// @dev `msg.sender` must be authorized to manage `onBehalf`'s positions.
/// @dev Borrowing a large amount can revert for overflow.
/// @dev Borrowing an amount of shares may lead to borrow fewer assets than expected due to slippage.
/// Consider using the `assets` parameter to avoid this.
/// @param marketParams The market to borrow assets from.
/// @param assets The amount of assets to borrow.
/// @param shares The amount of shares to mint.
/// @param onBehalf The address that will own the increased borrow position.
/// @param receiver The address that will receive the borrowed assets.
/// @return assetsBorrowed The amount of assets borrowed.
/// @return sharesBorrowed The amount of shares minted.
function borrow(
MarketParams memory marketParams,
uint256 assets,
uint256 shares,
address onBehalf,
address receiver
) external returns (uint256 assetsBorrowed, uint256 sharesBorrowed);
/// @notice Repays `assets` or `shares` on behalf of `onBehalf`, optionally calling back the caller's
/// `onMorphoReplay` function with the given `data`.
/// @dev Either `assets` or `shares` should be zero. To repay max, pass the `shares`'s balance of `onBehalf`.
/// @dev Repaying an amount corresponding to more shares than borrowed will revert for underflow.
/// @dev It is advised to use the `shares` input when repaying the full position to avoid reverts due to conversion
/// roundings between shares and assets.
/// @dev An attacker can front-run a repay with a small repay making the transaction revert for underflow.
/// @param marketParams The market to repay assets to.
/// @param assets The amount of assets to repay.
/// @param shares The amount of shares to burn.
/// @param onBehalf The address of the owner of the debt position.
/// @param data Arbitrary data to pass to the `onMorphoRepay` callback. Pass empty data if not needed.
/// @return assetsRepaid The amount of assets repaid.
/// @return sharesRepaid The amount of shares burned.
function repay(
MarketParams memory marketParams,
uint256 assets,
uint256 shares,
address onBehalf,
bytes memory data
) external returns (uint256 assetsRepaid, uint256 sharesRepaid);
/// @notice Supplies `assets` of collateral on behalf of `onBehalf`, optionally calling back the caller's
/// `onMorphoSupplyCollateral` function with the given `data`.
/// @dev Interest are not accrued since it's not required and it saves gas.
/// @dev Supplying a large amount can revert for overflow.
/// @param marketParams The market to supply collateral to.
/// @param assets The amount of collateral to supply.
/// @param onBehalf The address that will own the increased collateral position.
/// @param data Arbitrary data to pass to the `onMorphoSupplyCollateral` callback. Pass empty data if not needed.
function supplyCollateral(MarketParams memory marketParams, uint256 assets, address onBehalf, bytes memory data)
external;
/// @notice Withdraws `assets` of collateral on behalf of `onBehalf` and sends the assets to `receiver`.
/// @dev `msg.sender` must be authorized to manage `onBehalf`'s positions.
/// @dev Withdrawing an amount corresponding to more collateral than supplied will revert for underflow.
/// @param marketParams The market to withdraw collateral from.
/// @param assets The amount of collateral to withdraw.
/// @param onBehalf The address of the owner of the collateral position.
/// @param receiver The address that will receive the collateral assets.
function withdrawCollateral(MarketParams memory marketParams, uint256 assets, address onBehalf, address receiver)
external;
/// @notice Liquidates the given `repaidShares` of debt asset or seize the given `seizedAssets` of collateral on the
/// given market `marketParams` of the given `borrower`'s position, optionally calling back the caller's
/// `onMorphoLiquidate` function with the given `data`.
/// @dev Either `seizedAssets` or `repaidShares` should be zero.
/// @dev Seizing more than the collateral balance will underflow and revert without any error message.
/// @dev Repaying more than the borrow balance will underflow and revert without any error message.
/// @dev An attacker can front-run a liquidation with a small repay making the transaction revert for underflow.
/// @param marketParams The market of the position.
/// @param borrower The owner of the position.
/// @param seizedAssets The amount of collateral to seize.
/// @param repaidShares The amount of shares to repay.
/// @param data Arbitrary data to pass to the `onMorphoLiquidate` callback. Pass empty data if not needed.
/// @return The amount of assets seized.
/// @return The amount of assets repaid.
function liquidate(
MarketParams memory marketParams,
address borrower,
uint256 seizedAssets,
uint256 repaidShares,
bytes memory data
) external returns (uint256, uint256);
/// @notice Executes a flash loan.
/// @dev Flash loans have access to the whole balance of the contract (the liquidity and deposited collateral of all
/// markets combined, plus donations).
/// @dev Warning: Not ERC-3156 compliant but compatibility is easily reached:
/// - `flashFee` is zero.
/// - `maxFlashLoan` is the token's balance of this contract.
/// - The receiver of `assets` is the caller.
/// @param token The token to flash loan.
/// @param assets The amount of assets to flash loan.
/// @param data Arbitrary data to pass to the `onMorphoFlashLoan` callback.
function flashLoan(address token, uint256 assets, bytes calldata data) external;
/// @notice Sets the authorization for `authorized` to manage `msg.sender`'s positions.
/// @param authorized The authorized address.
/// @param newIsAuthorized The new authorization status.
function setAuthorization(address authorized, bool newIsAuthorized) external;
/// @notice Sets the authorization for `authorization.authorized` to manage `authorization.authorizer`'s positions.
/// @dev Warning: Reverts if the signature has already been submitted.
/// @dev The signature is malleable, but it has no impact on the security here.
/// @dev The nonce is passed as argument to be able to revert with a different error message.
/// @param authorization The `Authorization` struct.
/// @param signature The signature.
function setAuthorizationWithSig(Authorization calldata authorization, Signature calldata signature) external;
/// @notice Accrues interest for the given market `marketParams`.
function accrueInterest(MarketParams memory marketParams) external;
/// @notice Returns the data stored on the different `slots`.
function extSloads(bytes32[] memory slots) external view returns (bytes32[] memory);
}
/// @dev This interface is inherited by Morpho so that function signatures are checked by the compiler.
/// @dev Consider using the IMorpho interface instead of this one.
interface IMorphoStaticTyping is IMorphoBase {
/// @notice The state of the position of `user` on the market corresponding to `id`.
/// @dev Warning: For `feeRecipient`, `supplyShares` does not contain the accrued shares since the last interest
/// accrual.
function position(Id id, address user)
external
view
returns (uint256 supplyShares, uint128 borrowShares, uint128 collateral);
/// @notice The state of the market corresponding to `id`.
/// @dev Warning: `totalSupplyAssets` does not contain the accrued interest since the last interest accrual.
/// @dev Warning: `totalBorrowAssets` does not contain the accrued interest since the last interest accrual.
/// @dev Warning: `totalSupplyShares` does not contain the accrued shares by `feeRecipient` since the last interest
/// accrual.
function market(Id id)
external
view
returns (
uint128 totalSupplyAssets,
uint128 totalSupplyShares,
uint128 totalBorrowAssets,
uint128 totalBorrowShares,
uint128 lastUpdate,
uint128 fee
);
/// @notice The market params corresponding to `id`.
/// @dev This mapping is not used in Morpho. It is there to enable reducing the cost associated to calldata on layer
/// 2s by creating a wrapper contract with functions that take `id` as input instead of `marketParams`.
function idToMarketParams(Id id)
external
view
returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv);
}
/// @title IMorpho
/// @author Morpho Labs
/// @custom:contact [email protected]
/// @dev Use this interface for Morpho to have access to all the functions with the appropriate function signatures.
interface IMorpho is IMorphoBase {
/// @notice The state of the position of `user` on the market corresponding to `id`.
/// @dev Warning: For `feeRecipient`, `p.supplyShares` does not contain the accrued shares since the last interest
/// accrual.
function position(Id id, address user) external view returns (Position memory p);
/// @notice The state of the market corresponding to `id`.
/// @dev Warning: `m.totalSupplyAssets` does not contain the accrued interest since the last interest accrual.
/// @dev Warning: `m.totalBorrowAssets` does not contain the accrued interest since the last interest accrual.
/// @dev Warning: `m.totalSupplyShares` does not contain the accrued shares by `feeRecipient` since the last
/// interest accrual.
function market(Id id) external view returns (Market memory m);
/// @notice The market params corresponding to `id`.
/// @dev This mapping is not used in Morpho. It is there to enable reducing the cost associated to calldata on layer
/// 2s by creating a wrapper contract with functions that take `id` as input instead of `marketParams`.
function idToMarketParams(Id id) external view returns (MarketParams memory);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import {Id, MarketParams} from "../interfaces/IMorpho.sol";
/// @title MarketParamsLib
/// @author Morpho Labs
/// @custom:contact [email protected]
/// @notice Library to convert a market to its id.
library MarketParamsLib {
/// @notice The length of the data used to compute the id of a market.
/// @dev The length is 5 * 32 because `MarketParams` has 5 variables of 32 bytes each.
uint256 internal constant MARKET_PARAMS_BYTES_LENGTH = 5 * 32;
/// @notice Returns the id of the market `marketParams`.
function id(MarketParams memory marketParams) internal pure returns (Id marketParamsId) {
assembly ("memory-safe") {
marketParamsId := keccak256(marketParams, MARKET_PARAMS_BYTES_LENGTH)
}
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity >=0.8.0;
struct ControllerInstance {
address almProxy;
address controller;
address rateLimits;
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity >=0.8.0;
import { MainnetController } from "../src/MainnetController.sol";
import { IALMProxy } from "../src/interfaces/IALMProxy.sol";
import { IRateLimits } from "../src/interfaces/IRateLimits.sol";
import { ControllerInstance } from "./ControllerInstance.sol";
interface IBufferLike {
function approve(address, address, uint256) external;
}
interface IPSMLike {
function kiss(address) external;
}
interface IVaultLike {
function buffer() external view returns (address);
function rely(address) external;
}
library MainnetControllerInit {
/**********************************************************************************************/
/*** Structs and constants ***/
/**********************************************************************************************/
struct CheckAddressParams {
address admin;
address proxy;
address rateLimits;
address vault;
address psm;
address daiUsds;
address cctp;
}
struct ConfigAddressParams {
address freezer;
address relayer;
address oldController;
}
struct MintRecipient {
uint32 domain;
bytes32 mintRecipient;
}
bytes32 constant DEFAULT_ADMIN_ROLE = 0x00;
/**********************************************************************************************/
/*** Internal library functions ***/
/**********************************************************************************************/
function initAlmSystem(
address vault,
address usds,
ControllerInstance memory controllerInst,
ConfigAddressParams memory configAddresses,
CheckAddressParams memory checkAddresses,
MintRecipient[] memory mintRecipients
)
internal
{
// Step 1: Do sanity checks outside of the controller
require(IALMProxy(controllerInst.almProxy).hasRole(DEFAULT_ADMIN_ROLE, checkAddresses.admin), "MainnetControllerInit/incorrect-admin-almProxy");
require(IRateLimits(controllerInst.rateLimits).hasRole(DEFAULT_ADMIN_ROLE, checkAddresses.admin), "MainnetControllerInit/incorrect-admin-rateLimits");
// Step 2: Initialize the controller
_initController(controllerInst, configAddresses, checkAddresses, mintRecipients);
// Step 3: Configure almProxy within the allocation system
require(vault == checkAddresses.vault, "MainnetControllerInit/incorrect-vault");
IVaultLike(vault).rely(controllerInst.almProxy);
IBufferLike(IVaultLike(vault).buffer()).approve(usds, controllerInst.almProxy, type(uint256).max);
}
function upgradeController(
ControllerInstance memory controllerInst,
ConfigAddressParams memory configAddresses,
CheckAddressParams memory checkAddresses,
MintRecipient[] memory mintRecipients
)
internal
{
_initController(controllerInst, configAddresses, checkAddresses, mintRecipients);
IALMProxy almProxy = IALMProxy(controllerInst.almProxy);
IRateLimits rateLimits = IRateLimits(controllerInst.rateLimits);
require(configAddresses.oldController != address(0), "MainnetControllerInit/old-controller-zero-address");
require(almProxy.hasRole(almProxy.CONTROLLER(), configAddresses.oldController), "MainnetControllerInit/old-controller-not-almProxy-controller");
require(rateLimits.hasRole(rateLimits.CONTROLLER(), configAddresses.oldController), "MainnetControllerInit/old-controller-not-rateLimits-controller");
almProxy.revokeRole(almProxy.CONTROLLER(), configAddresses.oldController);
rateLimits.revokeRole(rateLimits.CONTROLLER(), configAddresses.oldController);
}
function pauseProxyInitAlmSystem(address psm, address almProxy) internal {
IPSMLike(psm).kiss(almProxy); // To allow using no fee functionality
}
/**********************************************************************************************/
/*** Private helper functions ***/
/**********************************************************************************************/
function _initController(
ControllerInstance memory controllerInst,
ConfigAddressParams memory configAddresses,
CheckAddressParams memory checkAddresses,
MintRecipient[] memory mintRecipients
)
private
{
// Step 1: Perform controller sanity checks
MainnetController newController = MainnetController(controllerInst.controller);
require(newController.hasRole(DEFAULT_ADMIN_ROLE, checkAddresses.admin), "MainnetControllerInit/incorrect-admin-controller");
require(address(newController.proxy()) == controllerInst.almProxy, "MainnetControllerInit/incorrect-almProxy");
require(address(newController.rateLimits()) == controllerInst.rateLimits, "MainnetControllerInit/incorrect-rateLimits");
require(address(newController.vault()) == checkAddresses.vault, "MainnetControllerInit/incorrect-vault");
require(address(newController.psm()) == checkAddresses.psm, "MainnetControllerInit/incorrect-psm");
require(address(newController.daiUsds()) == checkAddresses.daiUsds, "MainnetControllerInit/incorrect-daiUsds");
require(address(newController.cctp()) == checkAddresses.cctp, "MainnetControllerInit/incorrect-cctp");
require(newController.psmTo18ConversionFactor() == 1e12, "MainnetControllerInit/incorrect-psmTo18ConversionFactor");
require(configAddresses.oldController != address(newController), "MainnetControllerInit/old-controller-is-new-controller");
// Step 2: Configure ACL permissions controller, almProxy, and rateLimits
IALMProxy almProxy = IALMProxy(controllerInst.almProxy);
IRateLimits rateLimits = IRateLimits(controllerInst.rateLimits);
newController.grantRole(newController.FREEZER(), configAddresses.freezer);
newController.grantRole(newController.RELAYER(), configAddresses.relayer);
almProxy.grantRole(almProxy.CONTROLLER(), address(newController));
rateLimits.grantRole(rateLimits.CONTROLLER(), address(newController));
// Step 3: Configure the mint recipients on other domains
for (uint256 i = 0; i < mintRecipients.length; i++) {
newController.setMintRecipient(mintRecipients[i].domain, mintRecipients[i].mintRecipient);
}
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity >=0.8.0;
import { ForeignController } from "../src/ForeignController.sol";
import { IALMProxy } from "../src/interfaces/IALMProxy.sol";
import { IRateLimits } from "../src/interfaces/IRateLimits.sol";
import { ControllerInstance } from "./ControllerInstance.sol";
interface IPSM3Like {
function susds() external view returns (address);
function totalAssets() external view returns (uint256);
function totalShares() external view returns (uint256);
function usdc() external view returns (address);
function usds() external view returns (address);
}
library ForeignControllerInit {
/**********************************************************************************************/
/*** Structs and constants ***/
/**********************************************************************************************/
struct CheckAddressParams {
address admin;
address psm;
address cctp;
address usdc;
address susds;
address usds;
}
struct ConfigAddressParams {
address freezer;
address relayer;
address oldController;
}
struct MintRecipient {
uint32 domain;
bytes32 mintRecipient;
}
bytes32 constant DEFAULT_ADMIN_ROLE = 0x00;
/**********************************************************************************************/
/*** Internal library functions ***/
/**********************************************************************************************/
function initAlmSystem(
ControllerInstance memory controllerInst,
ConfigAddressParams memory configAddresses,
CheckAddressParams memory checkAddresses,
MintRecipient[] memory mintRecipients
)
internal
{
// Step 1: Do sanity checks outside of the controller
require(IALMProxy(controllerInst.almProxy).hasRole(DEFAULT_ADMIN_ROLE, checkAddresses.admin), "ForeignControllerInit/incorrect-admin-almProxy");
require(IRateLimits(controllerInst.rateLimits).hasRole(DEFAULT_ADMIN_ROLE, checkAddresses.admin), "ForeignControllerInit/incorrect-admin-rateLimits");
// Step 2: Initialize the controller
_initController(controllerInst, configAddresses, checkAddresses, mintRecipients);
}
function upgradeController(
ControllerInstance memory controllerInst,
ConfigAddressParams memory configAddresses,
CheckAddressParams memory checkAddresses,
MintRecipient[] memory mintRecipients
)
internal
{
_initController(controllerInst, configAddresses, checkAddresses, mintRecipients);
IALMProxy almProxy = IALMProxy(controllerInst.almProxy);
IRateLimits rateLimits = IRateLimits(controllerInst.rateLimits);
require(configAddresses.oldController != address(0), "ForeignControllerInit/old-controller-zero-address");
require(almProxy.hasRole(almProxy.CONTROLLER(), configAddresses.oldController), "ForeignControllerInit/old-controller-not-almProxy-controller");
require(rateLimits.hasRole(rateLimits.CONTROLLER(), configAddresses.oldController), "ForeignControllerInit/old-controller-not-rateLimits-controller");
almProxy.revokeRole(almProxy.CONTROLLER(), configAddresses.oldController);
rateLimits.revokeRole(rateLimits.CONTROLLER(), configAddresses.oldController);
}
/**********************************************************************************************/
/*** Private helper functions ***/
/**********************************************************************************************/
function _initController(
ControllerInstance memory controllerInst,
ConfigAddressParams memory configAddresses,
CheckAddressParams memory checkAddresses,
MintRecipient[] memory mintRecipients
)
private
{
// Step 1: Perform controller sanity checks
ForeignController newController = ForeignController(controllerInst.controller);
require(newController.hasRole(DEFAULT_ADMIN_ROLE, checkAddresses.admin), "ForeignControllerInit/incorrect-admin-controller");
require(address(newController.proxy()) == controllerInst.almProxy, "ForeignControllerInit/incorrect-almProxy");
require(address(newController.rateLimits()) == controllerInst.rateLimits, "ForeignControllerInit/incorrect-rateLimits");
require(address(newController.psm()) == checkAddresses.psm, "ForeignControllerInit/incorrect-psm");
require(address(newController.usdc()) == checkAddresses.usdc, "ForeignControllerInit/incorrect-usdc");
require(address(newController.cctp()) == checkAddresses.cctp, "ForeignControllerInit/incorrect-cctp");
require(configAddresses.oldController != address(newController), "ForeignControllerInit/old-controller-is-new-controller");
// Step 2: Perform PSM sanity checks
IPSM3Like psm = IPSM3Like(checkAddresses.psm);
require(psm.totalAssets() >= 1e18, "ForeignControllerInit/psm-totalAssets-not-seeded");
require(psm.totalShares() >= 1e18, "ForeignControllerInit/psm-totalShares-not-seeded");
require(psm.usdc() == checkAddresses.usdc, "ForeignControllerInit/psm-incorrect-usdc");
require(psm.usds() == checkAddresses.usds, "ForeignControllerInit/psm-incorrect-usds");
require(psm.susds() == checkAddresses.susds, "ForeignControllerInit/psm-incorrect-susds");
// Step 3: Configure ACL permissions controller, almProxy, and rateLimits
IALMProxy almProxy = IALMProxy(controllerInst.almProxy);
IRateLimits rateLimits = IRateLimits(controllerInst.rateLimits);
newController.grantRole(newController.FREEZER(), configAddresses.freezer);
newController.grantRole(newController.RELAYER(), configAddresses.relayer);
almProxy.grantRole(almProxy.CONTROLLER(), address(newController));
rateLimits.grantRole(rateLimits.CONTROLLER(), address(newController));
// Step 4: Configure the mint recipients on other domains
for (uint256 i = 0; i < mintRecipients.length; i++) {
newController.setMintRecipient(mintRecipients[i].domain, mintRecipients[i].mintRecipient);
}
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.21;
import { IAToken } from "aave-v3-origin/src/core/contracts/interfaces/IAToken.sol";
import { IPool as IAavePool } from "aave-v3-origin/src/core/contracts/interfaces/IPool.sol";
import { IERC20 } from "forge-std/interfaces/IERC20.sol";
import { IERC4626 } from "forge-std/interfaces/IERC4626.sol";
import { IERC7540 } from "forge-std/interfaces/IERC7540.sol";
import { IMetaMorpho, Id, MarketAllocation } from "metamorpho/interfaces/IMetaMorpho.sol";
import { AccessControl } from "openzeppelin-contracts/contracts/access/AccessControl.sol";
import { Ethereum } from "spark-address-registry/Ethereum.sol";
import { IALMProxy } from "./interfaces/IALMProxy.sol";
import { ICCTPLike } from "./interfaces/CCTPInterfaces.sol";
import { IRateLimits } from "./interfaces/IRateLimits.sol";
import { RateLimitHelpers } from "./RateLimitHelpers.sol";
interface IATokenWithPool is IAToken {
function POOL() external view returns(address);
}
interface IBuidlRedeemLike {
function asset() external view returns(address);
function redeem(uint256 usdcAmount) external;
}
interface ICurvePoolLike is IERC20 {
function add_liquidity(
uint256[] memory amounts,
uint256 minMintAmount,
address receiver
) external;
function balances(uint256 index) external view returns (uint256);
function coins(uint256 index) external returns (address);
function exchange(
int128 inputIndex,
int128 outputIndex,
uint256 amountIn,
uint256 minAmountOut,
address receiver
) external returns (uint256 tokensOut);
function get_virtual_price() external view returns (uint256);
function N_COINS() external view returns (uint256);
function remove_liquidity(
uint256 burnAmount,
uint256[] memory minAmounts,
address receiver
) external;
function stored_rates() external view returns (uint256[] memory);
}
interface IDaiUsdsLike {
function dai() external view returns (address);
function daiToUsds(address usr, uint256 wad) external;
function usdsToDai(address usr, uint256 wad) external;
}
interface IEthenaMinterLike {
function setDelegatedSigner(address delegateSigner) external;
function removeDelegatedSigner(address delegateSigner) external;
}
interface ICentrifugeToken is IERC7540 {
function cancelDepositRequest(uint256 requestId, address controller) external;
function cancelRedeemRequest(uint256 requestId, address controller) external;
function claimCancelDepositRequest(uint256 requestId, address receiver, address controller)
external returns (uint256 assets);
function claimCancelRedeemRequest(uint256 requestId, address receiver, address controller)
external returns (uint256 shares);
}
interface IMapleTokenLike is IERC4626 {
function requestRedeem(uint256 shares, address receiver) external;
function removeShares(uint256 shares, address receiver) external;
}
interface IPSMLike {
function buyGemNoFee(address usr, uint256 usdcAmount) external returns (uint256 usdsAmount);
function fill() external returns (uint256 wad);
function gem() external view returns (address);
function sellGemNoFee(address usr, uint256 usdcAmount) external returns (uint256 usdsAmount);
function to18ConversionFactor() external view returns (uint256);
}
interface ISSRedemptionLike is IERC20 {
function calculateUsdcOut(uint256 ustbAmount)
external view returns (uint256 usdcOutAmount, uint256 usdPerUstbChainlinkRaw);
function redeem(uint256 ustbAmout) external;
}
interface ISUSDELike is IERC4626 {
function cooldownAssets(uint256 usdeAmount) external;
function cooldownShares(uint256 susdeAmount) external;
function unstake(address receiver) external;
}
interface IUSTBLike is IERC20 {
function subscribe(uint256 inAmount, address stablecoin) external;
}
interface IVaultLike {
function buffer() external view returns (address);
function draw(uint256 usdsAmount) external;
function wipe(uint256 usdsAmount) external;
}
contract MainnetController is AccessControl {
/**********************************************************************************************/
/*** Events ***/
/**********************************************************************************************/
// NOTE: This is used to track individual transfers for offchain processing of CCTP transactions
event CCTPTransferInitiated(
uint64 indexed nonce,
uint32 indexed destinationDomain,
bytes32 indexed mintRecipient,
uint256 usdcAmount
);
event MaxSlippageSet(address indexed pool, uint256 maxSlippage);
event MintRecipientSet(uint32 indexed destinationDomain, bytes32 mintRecipient);
event RelayerRemoved(address indexed relayer);
/**********************************************************************************************/
/*** State variables ***/
/**********************************************************************************************/
bytes32 public constant FREEZER = keccak256("FREEZER");
bytes32 public constant RELAYER = keccak256("RELAYER");
bytes32 public constant LIMIT_4626_DEPOSIT = keccak256("LIMIT_4626_DEPOSIT");
bytes32 public constant LIMIT_4626_WITHDRAW = keccak256("LIMIT_4626_WITHDRAW");
bytes32 public constant LIMIT_7540_DEPOSIT = keccak256("LIMIT_7540_DEPOSIT");
bytes32 public constant LIMIT_7540_REDEEM = keccak256("LIMIT_7540_REDEEM");
bytes32 public constant LIMIT_AAVE_DEPOSIT = keccak256("LIMIT_AAVE_DEPOSIT");
bytes32 public constant LIMIT_AAVE_WITHDRAW = keccak256("LIMIT_AAVE_WITHDRAW");
bytes32 public constant LIMIT_ASSET_TRANSFER = keccak256("LIMIT_ASSET_TRANSFER");
bytes32 public constant LIMIT_BUIDL_REDEEM_CIRCLE = keccak256("LIMIT_BUIDL_REDEEM_CIRCLE");
bytes32 public constant LIMIT_CURVE_DEPOSIT = keccak256("LIMIT_CURVE_DEPOSIT");
bytes32 public constant LIMIT_CURVE_SWAP = keccak256("LIMIT_CURVE_SWAP");
bytes32 public constant LIMIT_CURVE_WITHDRAW = keccak256("LIMIT_CURVE_WITHDRAW");
bytes32 public constant LIMIT_MAPLE_REDEEM = keccak256("LIMIT_MAPLE_REDEEM");
bytes32 public constant LIMIT_SUPERSTATE_REDEEM = keccak256("LIMIT_SUPERSTATE_REDEEM");
bytes32 public constant LIMIT_SUPERSTATE_SUBSCRIBE = keccak256("LIMIT_SUPERSTATE_SUBSCRIBE");
bytes32 public constant LIMIT_SUSDE_COOLDOWN = keccak256("LIMIT_SUSDE_COOLDOWN");
bytes32 public constant LIMIT_USDC_TO_CCTP = keccak256("LIMIT_USDC_TO_CCTP");
bytes32 public constant LIMIT_USDC_TO_DOMAIN = keccak256("LIMIT_USDC_TO_DOMAIN");
bytes32 public constant LIMIT_USDE_BURN = keccak256("LIMIT_USDE_BURN");
bytes32 public constant LIMIT_USDE_MINT = keccak256("LIMIT_USDE_MINT");
bytes32 public constant LIMIT_USDS_MINT = keccak256("LIMIT_USDS_MINT");
bytes32 public constant LIMIT_USDS_TO_USDC = keccak256("LIMIT_USDS_TO_USDC");
address public immutable buffer;
IALMProxy public immutable proxy;
IBuidlRedeemLike public immutable buidlRedeem;
ICCTPLike public immutable cctp;
IDaiUsdsLike public immutable daiUsds;
IEthenaMinterLike public immutable ethenaMinter;
IPSMLike public immutable psm;
IRateLimits public immutable rateLimits;
ISSRedemptionLike public immutable superstateRedemption;
IVaultLike public immutable vault;
IERC20 public immutable dai;
IERC20 public immutable usds;
IERC20 public immutable usde;
IERC20 public immutable usdc;
IUSTBLike public immutable ustb;
ISUSDELike public immutable susde;
uint256 public immutable psmTo18ConversionFactor;
mapping(address pool => uint256 maxSlippage) public maxSlippages; // 1e18 precision
mapping(uint32 destinationDomain => bytes32 mintRecipient) public mintRecipients;
/**********************************************************************************************/
/*** Initialization ***/
/**********************************************************************************************/
constructor(
address admin_,
address proxy_,
address rateLimits_,
address vault_,
address psm_,
address daiUsds_,
address cctp_
) {
_grantRole(DEFAULT_ADMIN_ROLE, admin_);
proxy = IALMProxy(proxy_);
rateLimits = IRateLimits(rateLimits_);
vault = IVaultLike(vault_);
buffer = IVaultLike(vault_).buffer();
psm = IPSMLike(psm_);
daiUsds = IDaiUsdsLike(daiUsds_);
cctp = ICCTPLike(cctp_);
buidlRedeem = IBuidlRedeemLike(Ethereum.BUIDL_REDEEM);
ethenaMinter = IEthenaMinterLike(Ethereum.ETHENA_MINTER);
superstateRedemption = ISSRedemptionLike(Ethereum.SUPERSTATE_REDEMPTION);
susde = ISUSDELike(Ethereum.SUSDE);
ustb = IUSTBLike(Ethereum.USTB);
dai = IERC20(daiUsds.dai());
usdc = IERC20(psm.gem());
usds = IERC20(Ethereum.USDS);
usde = IERC20(Ethereum.USDE);
psmTo18ConversionFactor = psm.to18ConversionFactor();
}
/**********************************************************************************************/
/*** Admin functions ***/
/**********************************************************************************************/
function setMintRecipient(uint32 destinationDomain, bytes32 mintRecipient) external {
_checkRole(DEFAULT_ADMIN_ROLE);
mintRecipients[destinationDomain] = mintRecipient;
emit MintRecipientSet(destinationDomain, mintRecipient);
}
function setMaxSlippage(address pool, uint256 maxSlippage) external {
_checkRole(DEFAULT_ADMIN_ROLE);
maxSlippages[pool] = maxSlippage;
emit MaxSlippageSet(pool, maxSlippage);
}
/**********************************************************************************************/
/*** Freezer functions ***/
/**********************************************************************************************/
function removeRelayer(address relayer) external {
_checkRole(FREEZER);
_revokeRole(RELAYER, relayer);
emit RelayerRemoved(relayer);
}
/**********************************************************************************************/
/*** Relayer vault functions ***/
/**********************************************************************************************/
function mintUSDS(uint256 usdsAmount) external {
_checkRole(RELAYER);
_rateLimited(LIMIT_USDS_MINT, usdsAmount);
// Mint USDS into the buffer
proxy.doCall(
address(vault),
abi.encodeCall(vault.draw, (usdsAmount))
);
// Transfer USDS from the buffer to the proxy
proxy.doCall(
address(usds),
abi.encodeCall(usds.transferFrom, (buffer, address(proxy), usdsAmount))
);
}
function burnUSDS(uint256 usdsAmount) external {
_checkRole(RELAYER);
_cancelRateLimit(LIMIT_USDS_MINT, usdsAmount);
// Transfer USDS from the proxy to the buffer
proxy.doCall(
address(usds),
abi.encodeCall(usds.transfer, (buffer, usdsAmount))
);
// Burn USDS from the buffer
proxy.doCall(
address(vault),
abi.encodeCall(vault.wipe, (usdsAmount))
);
}
/**********************************************************************************************/
/*** Relayer ERC20 functions ***/
/**********************************************************************************************/
function transferAsset(address asset, address destination, uint256 amount) external {
_checkRole(RELAYER);
_rateLimited(
RateLimitHelpers.makeAssetDestinationKey(LIMIT_ASSET_TRANSFER, asset, destination),
amount
);
proxy.doCall(
asset,
abi.encodeCall(IERC20(asset).transfer, (destination, amount))
);
}
/**********************************************************************************************/
/*** Relayer ERC4626 functions ***/
/**********************************************************************************************/
function depositERC4626(address token, uint256 amount) external returns (uint256 shares) {
_checkRole(RELAYER);
_rateLimitedAsset(LIMIT_4626_DEPOSIT, token, amount);
// Note that whitelist is done by rate limits
IERC20 asset = IERC20(IERC4626(token).asset());
// Approve asset to token from the proxy (assumes the proxy has enough of the asset).
_approve(address(asset), token, amount);
// Deposit asset into the token, proxy receives token shares, decode the resulting shares
shares = abi.decode(
proxy.doCall(
token,
abi.encodeCall(IERC4626(token).deposit, (amount, address(proxy)))
),
(uint256)
);
}
function withdrawERC4626(address token, uint256 amount) external returns (uint256 shares) {
_checkRole(RELAYER);
_rateLimitedAsset(LIMIT_4626_WITHDRAW, token, amount);
// Withdraw asset from a token, decode resulting shares.
// Assumes proxy has adequate token shares.
shares = abi.decode(
proxy.doCall(
token,
abi.encodeCall(IERC4626(token).withdraw, (amount, address(proxy), address(proxy)))
),
(uint256)
);
}
// NOTE: !!! Rate limited at end of function !!!
function redeemERC4626(address token, uint256 shares) external returns (uint256 assets) {
_checkRole(RELAYER);
// Redeem shares for assets from the token, decode the resulting assets.
// Assumes proxy has adequate token shares.
assets = abi.decode(
proxy.doCall(
token,
abi.encodeCall(IERC4626(token).redeem, (shares, address(proxy), address(proxy)))
),
(uint256)
);
rateLimits.triggerRateLimitDecrease(
RateLimitHelpers.makeAssetKey(LIMIT_4626_WITHDRAW, token),
assets
);
}
/**********************************************************************************************/
/*** Relayer ERC7540 functions ***/
/**********************************************************************************************/
function requestDepositERC7540(address token, uint256 amount) external {
_checkRole(RELAYER);
_rateLimitedAsset(LIMIT_7540_DEPOSIT, token, amount);
// Note that whitelist is done by rate limits
IERC20 asset = IERC20(IERC7540(token).asset());
// Approve asset to vault from the proxy (assumes the proxy has enough of the asset).
_approve(address(asset), token, amount);
// Submit deposit request by transferring assets
proxy.doCall(
token,
abi.encodeCall(IERC7540(token).requestDeposit, (amount, address(proxy), address(proxy)))
);
}
function claimDepositERC7540(address token) external {
_checkRole(RELAYER);
_rateLimitExists(RateLimitHelpers.makeAssetKey(LIMIT_7540_DEPOSIT, token));
uint256 shares = IERC7540(token).maxMint(address(proxy));
// Claim shares from the vault to the proxy
proxy.doCall(
token,
abi.encodeCall(IERC4626(token).mint, (shares, address(proxy)))
);
}
function requestRedeemERC7540(address token, uint256 shares) external {
_checkRole(RELAYER);
_rateLimitedAsset(
LIMIT_7540_REDEEM,
token,
IERC7540(token).convertToAssets(shares)
);
// Submit redeem request by transferring shares
proxy.doCall(
token,
abi.encodeCall(IERC7540(token).requestRedeem, (shares, address(proxy), address(proxy)))
);
}
function claimRedeemERC7540(address token) external {
_checkRole(RELAYER);
_rateLimitExists(RateLimitHelpers.makeAssetKey(LIMIT_7540_REDEEM, token));
uint256 assets = IERC7540(token).maxWithdraw(address(proxy));
// Claim assets from the vault to the proxy
proxy.doCall(
token,
abi.encodeCall(IERC7540(token).withdraw, (assets, address(proxy), address(proxy)))
);
}
/**********************************************************************************************/
/*** Relayer Centrifuge functions ***/
/**********************************************************************************************/
// NOTE: These cancelation methods are compatible with ERC-7887
uint256 CENTRIFUGE_REQUEST_ID = 0;
function cancelCentrifugeDepositRequest(address token) external {
_checkRole(RELAYER);
_rateLimitExists(RateLimitHelpers.makeAssetKey(LIMIT_7540_DEPOSIT, token));
// NOTE: While the cancelation is pending, no new deposit request can be submitted
proxy.doCall(
token,
abi.encodeCall(
ICentrifugeToken(token).cancelDepositRequest,
(CENTRIFUGE_REQUEST_ID, address(proxy))
)
);
}
function claimCentrifugeCancelDepositRequest(address token) external {
_checkRole(RELAYER);
_rateLimitExists(RateLimitHelpers.makeAssetKey(LIMIT_7540_DEPOSIT, token));
proxy.doCall(
token,
abi.encodeCall(
ICentrifugeToken(token).claimCancelDepositRequest,
(CENTRIFUGE_REQUEST_ID, address(proxy), address(proxy))
)
);
}
function cancelCentrifugeRedeemRequest(address token) external {
_checkRole(RELAYER);
_rateLimitExists(RateLimitHelpers.makeAssetKey(LIMIT_7540_REDEEM, token));
// NOTE: While the cancelation is pending, no new redeem request can be submitted
proxy.doCall(
token,
abi.encodeCall(
ICentrifugeToken(token).cancelRedeemRequest,
(CENTRIFUGE_REQUEST_ID, address(proxy))
)
);
}
function claimCentrifugeCancelRedeemRequest(address token) external {
_checkRole(RELAYER);
_rateLimitExists(RateLimitHelpers.makeAssetKey(LIMIT_7540_REDEEM, token));
proxy.doCall(
token,
abi.encodeCall(
ICentrifugeToken(token).claimCancelRedeemRequest,
(CENTRIFUGE_REQUEST_ID, address(proxy), address(proxy))
)
);
}
/**********************************************************************************************/
/*** Relayer Aave functions ***/
/**********************************************************************************************/
function depositAave(address aToken, uint256 amount) external {
_checkRole(RELAYER);
_rateLimitedAsset(LIMIT_AAVE_DEPOSIT, aToken, amount);
IERC20 underlying = IERC20(IATokenWithPool(aToken).UNDERLYING_ASSET_ADDRESS());
IAavePool pool = IAavePool(IATokenWithPool(aToken).POOL());
// Approve underlying to Aave pool from the proxy (assumes the proxy has enough underlying).
_approve(address(underlying), address(pool), amount);
// Deposit underlying into Aave pool, proxy receives aTokens
proxy.doCall(
address(pool),
abi.encodeCall(pool.supply, (address(underlying), amount, address(proxy), 0))
);
}
// NOTE: !!! Rate limited at end of function !!!
function withdrawAave(address aToken, uint256 amount)
external
returns (uint256 amountWithdrawn)
{
_checkRole(RELAYER);
IAavePool pool = IAavePool(IATokenWithPool(aToken).POOL());
// Withdraw underlying from Aave pool, decode resulting amount withdrawn.
// Assumes proxy has adequate aTokens.
amountWithdrawn = abi.decode(
proxy.doCall(
address(pool),
abi.encodeCall(
pool.withdraw,
(IATokenWithPool(aToken).UNDERLYING_ASSET_ADDRESS(), amount, address(proxy))
)
),
(uint256)
);
rateLimits.triggerRateLimitDecrease(
RateLimitHelpers.makeAssetKey(LIMIT_AAVE_WITHDRAW, aToken),
amountWithdrawn
);
}
/**********************************************************************************************/
/*** Relayer BlackRock BUIDL functions ***/
/**********************************************************************************************/
function redeemBUIDLCircleFacility(uint256 usdcAmount) external {
_checkRole(RELAYER);
_rateLimited(LIMIT_BUIDL_REDEEM_CIRCLE, usdcAmount);
_approve(address(buidlRedeem.asset()), address(buidlRedeem), usdcAmount);
proxy.doCall(
address(buidlRedeem),
abi.encodeCall(buidlRedeem.redeem, (usdcAmount))
);
}
/**********************************************************************************************/
/*** Relayer Curve StableSwap functions ***/
/**********************************************************************************************/
function swapCurve(
address pool,
uint256 inputIndex,
uint256 outputIndex,
uint256 amountIn,
uint256 minAmountOut
)
external returns (uint256 amountOut)
{
_checkRole(RELAYER);
require(inputIndex != outputIndex, "MainnetController/invalid-indices");
uint256 maxSlippage = maxSlippages[pool];
require(maxSlippage != 0, "MainnetController/max-slippage-not-set");
ICurvePoolLike curvePool = ICurvePoolLike(pool);
uint256 numCoins = curvePool.N_COINS();
require(
inputIndex < numCoins && outputIndex < numCoins,
"MainnetController/index-too-high"
);
// Normalized to provide 36 decimal precision when multiplied by asset amount
uint256[] memory rates = curvePool.stored_rates();
// Below code is simplified from the following logic.
// `maxSlippage` was multipled first to avoid precision loss.
// valueIn = amountIn * rates[inputIndex] / 1e18 // 18 decimal precision, USD
// tokensOut = valueIn * 1e18 / rates[outputIndex] // Token precision, token amount
// result = tokensOut * maxSlippage / 1e18
uint256 minimumMinAmountOut = amountIn
* rates[inputIndex]
* maxSlippage
/ rates[outputIndex]
/ 1e18;
require(
minAmountOut >= minimumMinAmountOut,
"MainnetController/min-amount-not-met"
);
rateLimits.triggerRateLimitDecrease(
RateLimitHelpers.makeAssetKey(LIMIT_CURVE_SWAP, pool),
amountIn * rates[inputIndex] / 1e18
);
_approve(curvePool.coins(inputIndex), pool, amountIn);
amountOut = abi.decode(
proxy.doCall(
pool,
abi.encodeCall(
curvePool.exchange,
(
int128(int256(inputIndex)), // safe cast because of 8 token max
int128(int256(outputIndex)), // safe cast because of 8 token max
amountIn,
minAmountOut,
address(proxy)
)
)
),
(uint256)
);
}
function addLiquidityCurve(
address pool,
uint256[] memory depositAmounts,
uint256 minLpAmount
)
external returns (uint256 shares)
{
_checkRole(RELAYER);
uint256 maxSlippage = maxSlippages[pool];
require(maxSlippage != 0, "MainnetController/max-slippage-not-set");
ICurvePoolLike curvePool = ICurvePoolLike(pool);
require(
depositAmounts.length == curvePool.N_COINS(),
"MainnetController/invalid-deposit-amounts"
);
// Normalized to provide 36 decimal precision when multiplied by asset amount
uint256[] memory rates = curvePool.stored_rates();
// Aggregate the value of the deposited assets (e.g. USD)
uint256 valueDeposited;
for (uint256 i = 0; i < depositAmounts.length; i++) {
_approve(curvePool.coins(i), pool, depositAmounts[i]);
valueDeposited += depositAmounts[i] * rates[i];
}
valueDeposited /= 1e18;
// Ensure minimum LP amount expected is greater than max slippage amount.
require(
minLpAmount >= valueDeposited * maxSlippage / curvePool.get_virtual_price(),
"MainnetController/min-amount-not-met"
);
// Reduce the rate limit by the aggregated underlying asset value of the deposit (e.g. USD)
rateLimits.triggerRateLimitDecrease(
RateLimitHelpers.makeAssetKey(LIMIT_CURVE_DEPOSIT, pool),
valueDeposited
);
shares = abi.decode(
proxy.doCall(
pool,
abi.encodeCall(
curvePool.add_liquidity,
(depositAmounts, minLpAmount, address(proxy))
)
),
(uint256)
);
// Compute the swap value by taking the difference of the current underlying
// asset values from minted shares vs the deposited funds, converting this into an
// aggregated swap "amount in" by dividing the total value moved by two and decrease the
// swap rate limit by this amount.
uint256 totalSwapped;
for (uint256 i; i < depositAmounts.length; i++) {
totalSwapped += _absSubtraction(
curvePool.balances(i) * rates[i] * shares / curvePool.totalSupply(),
depositAmounts[i] * rates[i]
);
}
uint256 averageSwap = totalSwapped / 2 / 1e18;
rateLimits.triggerRateLimitDecrease(
RateLimitHelpers.makeAssetKey(LIMIT_CURVE_SWAP, pool),
averageSwap
);
}
function removeLiquidityCurve(
address pool,
uint256 lpBurnAmount,
uint256[] memory minWithdrawAmounts
)
external returns (uint256[] memory withdrawnTokens)
{
_checkRole(RELAYER);
uint256 maxSlippage = maxSlippages[pool];
require(maxSlippage != 0, "MainnetController/max-slippage-not-set");
ICurvePoolLike curvePool = ICurvePoolLike(pool);
require(
minWithdrawAmounts.length == curvePool.N_COINS(),
"MainnetController/invalid-min-withdraw-amounts"
);
// Normalized to provide 36 decimal precision when multiplied by asset amount
uint256[] memory rates = curvePool.stored_rates();
// Aggregate the minimum values of the withdrawn assets (e.g. USD)
uint256 valueMinWithdrawn;
for (uint256 i = 0; i < minWithdrawAmounts.length; i++) {
valueMinWithdrawn += minWithdrawAmounts[i] * rates[i];
}
valueMinWithdrawn /= 1e18;
// Check that the aggregated minimums are greater than the max slippage amount
require(
valueMinWithdrawn >= lpBurnAmount * curvePool.get_virtual_price() * maxSlippage / 1e36,
"MainnetController/min-amount-not-met"
);
withdrawnTokens = abi.decode(
proxy.doCall(
pool,
abi.encodeCall(
curvePool.remove_liquidity,
(lpBurnAmount, minWithdrawAmounts, address(proxy))
)
),
(uint256[])
);
// Aggregate value withdrawn to reduce the rate limit
uint256 valueWithdrawn;
for (uint256 i = 0; i < withdrawnTokens.length; i++) {
valueWithdrawn += withdrawnTokens[i] * rates[i];
}
valueWithdrawn /= 1e18;
rateLimits.triggerRateLimitDecrease(
RateLimitHelpers.makeAssetKey(LIMIT_CURVE_WITHDRAW, pool),
valueWithdrawn
);
}
/**********************************************************************************************/
/*** Relayer Ethena functions ***/
/**********************************************************************************************/
function setDelegatedSigner(address delegatedSigner) external {
_checkRole(RELAYER);
proxy.doCall(
address(ethenaMinter),
abi.encodeCall(ethenaMinter.setDelegatedSigner, (address(delegatedSigner)))
);
}
function removeDelegatedSigner(address delegatedSigner) external {
_checkRole(RELAYER);
proxy.doCall(
address(ethenaMinter),
abi.encodeCall(ethenaMinter.removeDelegatedSigner, (address(delegatedSigner)))
);
}
// Note that Ethena's mint/redeem per-block limits include other users
function prepareUSDeMint(uint256 usdcAmount) external {
_checkRole(RELAYER);
_rateLimited(LIMIT_USDE_MINT, usdcAmount);
_approve(address(usdc), address(ethenaMinter), usdcAmount);
}
function prepareUSDeBurn(uint256 usdeAmount) external {
_checkRole(RELAYER);
_rateLimited(LIMIT_USDE_BURN, usdeAmount);
_approve(address(usde), address(ethenaMinter), usdeAmount);
}
function cooldownAssetsSUSDe(uint256 usdeAmount) external {
_checkRole(RELAYER);
_rateLimited(LIMIT_SUSDE_COOLDOWN, usdeAmount);
proxy.doCall(
address(susde),
abi.encodeCall(susde.cooldownAssets, (usdeAmount))
);
}
// NOTE: !!! Rate limited at end of function !!!
function cooldownSharesSUSDe(uint256 susdeAmount)
external
returns (uint256 cooldownAmount)
{
_checkRole(RELAYER);
cooldownAmount = abi.decode(
proxy.doCall(
address(susde),
abi.encodeCall(susde.cooldownShares, (susdeAmount))
),
(uint256)
);
rateLimits.triggerRateLimitDecrease(LIMIT_SUSDE_COOLDOWN, cooldownAmount);
}
function unstakeSUSDe() external {
_checkRole(RELAYER);
proxy.doCall(
address(susde),
abi.encodeCall(susde.unstake, (address(proxy)))
);
}
/**********************************************************************************************/
/*** Relayer Maple functions ***/
/**********************************************************************************************/
function requestMapleRedemption(address mapleToken, uint256 shares) external {
_checkRole(RELAYER);
_rateLimitedAsset(
LIMIT_MAPLE_REDEEM,
mapleToken,
IMapleTokenLike(mapleToken).convertToAssets(shares)
);
proxy.doCall(
mapleToken,
abi.encodeCall(IMapleTokenLike(mapleToken).requestRedeem, (shares, address(proxy)))
);
}
function cancelMapleRedemption(address mapleToken, uint256 shares) external {
_checkRole(RELAYER);
_rateLimitExists(RateLimitHelpers.makeAssetKey(LIMIT_MAPLE_REDEEM, mapleToken));
proxy.doCall(
mapleToken,
abi.encodeCall(IMapleTokenLike(mapleToken).removeShares, (shares, address(proxy)))
);
}
/**********************************************************************************************/
/*** Relayer Superstate functions ***/
/**********************************************************************************************/
function subscribeSuperstate(uint256 usdcAmount) external {
_checkRole(RELAYER);
_rateLimited(LIMIT_SUPERSTATE_SUBSCRIBE, usdcAmount);
_approve(address(usdc), address(ustb), usdcAmount);
proxy.doCall(
address(ustb),
abi.encodeCall(ustb.subscribe, (usdcAmount, address(usdc)))
);
}
// NOTE: Rate limited outside of modifier because of tuple return
function redeemSuperstate(uint256 ustbAmount) external {
_checkRole(RELAYER);
( uint256 usdcAmount, ) = superstateRedemption.calculateUsdcOut(ustbAmount);
rateLimits.triggerRateLimitDecrease(LIMIT_SUPERSTATE_REDEEM, usdcAmount);
_approve(address(ustb), address(superstateRedemption), ustbAmount);
proxy.doCall(
address(superstateRedemption),
abi.encodeCall(superstateRedemption.redeem, (ustbAmount))
);
}
/**********************************************************************************************/
/*** Relayer DaiUsds functions ***/
/**********************************************************************************************/
function swapUSDSToDAI(uint256 usdsAmount)
external
onlyRole(RELAYER)
{
// Approve USDS to DaiUsds migrator from the proxy (assumes the proxy has enough USDS)
_approve(address(usds), address(daiUsds), usdsAmount);
// Swap USDS to DAI 1:1
proxy.doCall(
address(daiUsds),
abi.encodeCall(daiUsds.usdsToDai, (address(proxy), usdsAmount))
);
}
function swapDAIToUSDS(uint256 daiAmount)
external
onlyRole(RELAYER)
{
// Approve DAI to DaiUsds migrator from the proxy (assumes the proxy has enough DAI)
_approve(address(dai), address(daiUsds), daiAmount);
// Swap DAI to USDS 1:1
proxy.doCall(
address(daiUsds),
abi.encodeCall(daiUsds.daiToUsds, (address(proxy), daiAmount))
);
}
/**********************************************************************************************/
/*** Relayer PSM functions ***/
/**********************************************************************************************/
// NOTE: The param `usdcAmount` is denominated in 1e6 precision to match how PSM uses
// USDC precision for both `buyGemNoFee` and `sellGemNoFee`
function swapUSDSToUSDC(uint256 usdcAmount) external {
_checkRole(RELAYER);
_rateLimited(LIMIT_USDS_TO_USDC, usdcAmount);
uint256 usdsAmount = usdcAmount * psmTo18ConversionFactor;
// Approve USDS to DaiUsds migrator from the proxy (assumes the proxy has enough USDS)
_approve(address(usds), address(daiUsds), usdsAmount);
// Swap USDS to DAI 1:1
proxy.doCall(
address(daiUsds),
abi.encodeCall(daiUsds.usdsToDai, (address(proxy), usdsAmount))
);
// Approve DAI to PSM from the proxy because conversion from USDS to DAI was 1:1
_approve(address(dai), address(psm), usdsAmount);
// Swap DAI to USDC through the PSM
proxy.doCall(
address(psm),
abi.encodeCall(psm.buyGemNoFee, (address(proxy), usdcAmount))
);
}
function swapUSDCToUSDS(uint256 usdcAmount) external {
_checkRole(RELAYER);
_cancelRateLimit(LIMIT_USDS_TO_USDC, usdcAmount);
// Approve USDC to PSM from the proxy (assumes the proxy has enough USDC)
_approve(address(usdc), address(psm), usdcAmount);
// Max USDC that can be swapped to DAI in one call
uint256 limit = dai.balanceOf(address(psm)) / psmTo18ConversionFactor;
if (usdcAmount <= limit) {
_swapUSDCToDAI(usdcAmount);
} else {
uint256 remainingUsdcToSwap = usdcAmount;
// Refill the PSM with DAI as many times as needed to get to the full `usdcAmount`.
// If the PSM cannot be filled with the full amount, psm.fill() will revert
// with `DssLitePsm/nothing-to-fill` since rush() will return 0.
// This is desired behavior because this function should only succeed if the full
// `usdcAmount` can be swapped.
while (remainingUsdcToSwap > 0) {
psm.fill();
limit = dai.balanceOf(address(psm)) / psmTo18ConversionFactor;
uint256 swapAmount = remainingUsdcToSwap < limit ? remainingUsdcToSwap : limit;
_swapUSDCToDAI(swapAmount);
remainingUsdcToSwap -= swapAmount;
}
}
uint256 daiAmount = usdcAmount * psmTo18ConversionFactor;
// Approve DAI to DaiUsds migrator from the proxy (assumes the proxy has enough DAI)
_approve(address(dai), address(daiUsds), daiAmount);
// Swap DAI to USDS 1:1
proxy.doCall(
address(daiUsds),
abi.encodeCall(daiUsds.daiToUsds, (address(proxy), daiAmount))
);
}
/**********************************************************************************************/
/*** Relayer bridging functions ***/
/**********************************************************************************************/
function transferUSDCToCCTP(uint256 usdcAmount, uint32 destinationDomain) external {
_checkRole(RELAYER);
_rateLimited(LIMIT_USDC_TO_CCTP, usdcAmount);
_rateLimited(
RateLimitHelpers.makeDomainKey(LIMIT_USDC_TO_DOMAIN, destinationDomain),
usdcAmount
);
bytes32 mintRecipient = mintRecipients[destinationDomain];
require(mintRecipient != 0, "MainnetController/domain-not-configured");
// Approve USDC to CCTP from the proxy (assumes the proxy has enough USDC)
_approve(address(usdc), address(cctp), usdcAmount);
// If amount is larger than limit it must be split into multiple calls
uint256 burnLimit = cctp.localMinter().burnLimitsPerMessage(address(usdc));
while (usdcAmount > burnLimit) {
_initiateCCTPTransfer(burnLimit, destinationDomain, mintRecipient);
usdcAmount -= burnLimit;
}
// Send remaining amount (if any)
if (usdcAmount > 0) {
_initiateCCTPTransfer(usdcAmount, destinationDomain, mintRecipient);
}
}
/**********************************************************************************************/
/*** Relayer helper functions ***/
/**********************************************************************************************/
function _absSubtraction(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a - b : b - a;
}
function _approve(address token, address spender, uint256 amount) internal {
proxy.doCall(token, abi.encodeCall(IERC20.approve, (spender, amount)));
}
function _initiateCCTPTransfer(
uint256 usdcAmount,
uint32 destinationDomain,
bytes32 mintRecipient
)
internal
{
uint64 nonce = abi.decode(
proxy.doCall(
address(cctp),
abi.encodeCall(
cctp.depositForBurn,
(
usdcAmount,
destinationDomain,
mintRecipient,
address(usdc)
)
)
),
(uint64)
);
emit CCTPTransferInitiated(nonce, destinationDomain, mintRecipient, usdcAmount);
}
function _swapUSDCToDAI(uint256 usdcAmount) internal {
// Swap USDC to DAI through the PSM (1:1 since sellGemNoFee is used)
proxy.doCall(
address(psm),
abi.encodeCall(psm.sellGemNoFee, (address(proxy), usdcAmount))
);
}
/**********************************************************************************************/
/*** Rate Limit helper functions ***/
/**********************************************************************************************/
function _rateLimited(bytes32 key, uint256 amount) internal {
rateLimits.triggerRateLimitDecrease(key, amount);
}
function _rateLimitedAsset(bytes32 key, address asset, uint256 amount) internal {
rateLimits.triggerRateLimitDecrease(RateLimitHelpers.makeAssetKey(key, asset), amount);
}
function _cancelRateLimit(bytes32 key, uint256 amount) internal {
rateLimits.triggerRateLimitIncrease(key, amount);
}
function _rateLimitExists(bytes32 key) internal view {
require(
rateLimits.getRateLimitData(key).maxAmount > 0,
"MainnetController/invalid-action"
);
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.21;
import { IAToken } from "aave-v3-origin/src/core/contracts/interfaces/IAToken.sol";
import { IPool as IAavePool } from "aave-v3-origin/src/core/contracts/interfaces/IPool.sol";
import { IERC20 } from "forge-std/interfaces/IERC20.sol";
import { IERC4626 } from "forge-std/interfaces/IERC4626.sol";
import { IMetaMorpho, Id, MarketAllocation } from "metamorpho/interfaces/IMetaMorpho.sol";
import { AccessControl } from "openzeppelin-contracts/contracts/access/AccessControl.sol";
import { IPSM3 } from "spark-psm/src/interfaces/IPSM3.sol";
import { IALMProxy } from "./interfaces/IALMProxy.sol";
import { ICCTPLike } from "./interfaces/CCTPInterfaces.sol";
import { IRateLimits } from "./interfaces/IRateLimits.sol";
import { RateLimitHelpers } from "./RateLimitHelpers.sol";
interface IATokenWithPool is IAToken {
function POOL() external view returns(address);
}
contract ForeignController is AccessControl {
/**********************************************************************************************/
/*** Events ***/
/**********************************************************************************************/
// NOTE: This is used to track individual transfers for offchain processing of CCTP transactions
event CCTPTransferInitiated(
uint64 indexed nonce,
uint32 indexed destinationDomain,
bytes32 indexed mintRecipient,
uint256 usdcAmount
);
event MintRecipientSet(uint32 indexed destinationDomain, bytes32 mintRecipient);
event RelayerRemoved(address indexed relayer);
/**********************************************************************************************/
/*** State variables ***/
/**********************************************************************************************/
bytes32 public constant FREEZER = keccak256("FREEZER");
bytes32 public constant RELAYER = keccak256("RELAYER");
bytes32 public constant LIMIT_4626_DEPOSIT = keccak256("LIMIT_4626_DEPOSIT");
bytes32 public constant LIMIT_4626_WITHDRAW = keccak256("LIMIT_4626_WITHDRAW");
bytes32 public constant LIMIT_AAVE_DEPOSIT = keccak256("LIMIT_AAVE_DEPOSIT");
bytes32 public constant LIMIT_AAVE_WITHDRAW = keccak256("LIMIT_AAVE_WITHDRAW");
bytes32 public constant LIMIT_PSM_DEPOSIT = keccak256("LIMIT_PSM_DEPOSIT");
bytes32 public constant LIMIT_PSM_WITHDRAW = keccak256("LIMIT_PSM_WITHDRAW");
bytes32 public constant LIMIT_USDC_TO_CCTP = keccak256("LIMIT_USDC_TO_CCTP");
bytes32 public constant LIMIT_USDC_TO_DOMAIN = keccak256("LIMIT_USDC_TO_DOMAIN");
IALMProxy public immutable proxy;
ICCTPLike public immutable cctp;
IPSM3 public immutable psm;
IRateLimits public immutable rateLimits;
IERC20 public immutable usdc;
mapping(uint32 destinationDomain => bytes32 mintRecipient) public mintRecipients;
/**********************************************************************************************/
/*** Initialization ***/
/**********************************************************************************************/
constructor(
address admin_,
address proxy_,
address rateLimits_,
address psm_,
address usdc_,
address cctp_
) {
_grantRole(DEFAULT_ADMIN_ROLE, admin_);
proxy = IALMProxy(proxy_);
rateLimits = IRateLimits(rateLimits_);
psm = IPSM3(psm_);
usdc = IERC20(usdc_);
cctp = ICCTPLike(cctp_);
}
/**********************************************************************************************/
/*** Modifiers ***/
/**********************************************************************************************/
modifier rateLimited(bytes32 key, uint256 amount) {
rateLimits.triggerRateLimitDecrease(key, amount);
_;
}
modifier rateLimitedAsset(bytes32 key, address asset, uint256 amount) {
rateLimits.triggerRateLimitDecrease(RateLimitHelpers.makeAssetKey(key, asset), amount);
_;
}
modifier rateLimitExists(bytes32 key) {
require(
rateLimits.getRateLimitData(key).maxAmount > 0,
"ForeignController/invalid-action"
);
_;
}
/**********************************************************************************************/
/*** Admin functions ***/
/**********************************************************************************************/
function setMintRecipient(uint32 destinationDomain, bytes32 mintRecipient)
external
onlyRole(DEFAULT_ADMIN_ROLE)
{
mintRecipients[destinationDomain] = mintRecipient;
emit MintRecipientSet(destinationDomain, mintRecipient);
}
/**********************************************************************************************/
/*** Freezer functions ***/
/**********************************************************************************************/
function removeRelayer(address relayer) external onlyRole(FREEZER) {
_revokeRole(RELAYER, relayer);
emit RelayerRemoved(relayer);
}
/**********************************************************************************************/
/*** Relayer PSM functions ***/
/**********************************************************************************************/
function depositPSM(address asset, uint256 amount)
external
onlyRole(RELAYER)
rateLimitedAsset(LIMIT_PSM_DEPOSIT, asset, amount)
returns (uint256 shares)
{
// Approve `asset` to PSM from the proxy (assumes the proxy has enough `asset`).
_approve(asset, address(psm), amount);
// Deposit `amount` of `asset` in the PSM, decode the result to get `shares`.
shares = abi.decode(
proxy.doCall(
address(psm),
abi.encodeCall(
psm.deposit,
(asset, address(proxy), amount)
)
),
(uint256)
);
}
// NOTE: !!! Rate limited at end of function !!!
function withdrawPSM(address asset, uint256 maxAmount)
external
onlyRole(RELAYER)
returns (uint256 assetsWithdrawn)
{
// Withdraw up to `maxAmount` of `asset` in the PSM, decode the result
// to get `assetsWithdrawn` (assumes the proxy has enough PSM shares).
assetsWithdrawn = abi.decode(
proxy.doCall(
address(psm),
abi.encodeCall(
psm.withdraw,
(asset, address(proxy), maxAmount)
)
),
(uint256)
);
rateLimits.triggerRateLimitDecrease(
RateLimitHelpers.makeAssetKey(LIMIT_PSM_WITHDRAW, asset),
assetsWithdrawn
);
}
/**********************************************************************************************/
/*** Relayer bridging functions ***/
/**********************************************************************************************/
function transferUSDCToCCTP(uint256 usdcAmount, uint32 destinationDomain)
external
onlyRole(RELAYER)
rateLimited(LIMIT_USDC_TO_CCTP, usdcAmount)
rateLimited(
RateLimitHelpers.makeDomainKey(LIMIT_USDC_TO_DOMAIN, destinationDomain),
usdcAmount
)
{
bytes32 mintRecipient = mintRecipients[destinationDomain];
require(mintRecipient != 0, "ForeignController/domain-not-configured");
// Approve USDC to CCTP from the proxy (assumes the proxy has enough USDC).
_approve(address(usdc), address(cctp), usdcAmount);
// If amount is larger than limit it must be split into multiple calls.
uint256 burnLimit = cctp.localMinter().burnLimitsPerMessage(address(usdc));
while (usdcAmount > burnLimit) {
_initiateCCTPTransfer(burnLimit, destinationDomain, mintRecipient);
usdcAmount -= burnLimit;
}
// Send remaining amount (if any)
if (usdcAmount > 0) {
_initiateCCTPTransfer(usdcAmount, destinationDomain, mintRecipient);
}
}
/**********************************************************************************************/
/*** Relayer ERC4626 functions ***/
/**********************************************************************************************/
function depositERC4626(address token, uint256 amount)
external
onlyRole(RELAYER)
rateLimitedAsset(LIMIT_4626_DEPOSIT, token, amount)
returns (uint256 shares)
{
// Note that whitelist is done by rate limits.
IERC20 asset = IERC20(IERC4626(token).asset());
// Approve asset to token from the proxy (assumes the proxy has enough of the asset).
_approve(address(asset), token, amount);
// Deposit asset into the token, proxy receives token shares, decode the resulting shares.
shares = abi.decode(
proxy.doCall(
token,
abi.encodeCall(IERC4626(token).deposit, (amount, address(proxy)))
),
(uint256)
);
}
function withdrawERC4626(address token, uint256 amount)
external
onlyRole(RELAYER)
rateLimitedAsset(LIMIT_4626_WITHDRAW, token, amount)
returns (uint256 shares)
{
// Withdraw asset from a token, decode resulting shares.
// Assumes proxy has adequate token shares.
shares = abi.decode(
proxy.doCall(
token,
abi.encodeCall(IERC4626(token).withdraw, (amount, address(proxy), address(proxy)))
),
(uint256)
);
}
// NOTE: !!! Rate limited at end of function !!!
function redeemERC4626(address token, uint256 shares)
external
onlyRole(RELAYER)
returns (uint256 assets)
{
// Redeem shares for assets from the token, decode the resulting assets.
// Assumes proxy has adequate token shares.
assets = abi.decode(
proxy.doCall(
token,
abi.encodeCall(IERC4626(token).redeem, (shares, address(proxy), address(proxy)))
),
(uint256)
);
rateLimits.triggerRateLimitDecrease(
RateLimitHelpers.makeAssetKey(LIMIT_4626_WITHDRAW, token),
assets
);
}
/**********************************************************************************************/
/*** Relayer Aave functions ***/
/**********************************************************************************************/
function depositAave(address aToken, uint256 amount)
external
onlyRole(RELAYER)
rateLimitedAsset(LIMIT_AAVE_DEPOSIT, aToken, amount)
{
IERC20 underlying = IERC20(IATokenWithPool(aToken).UNDERLYING_ASSET_ADDRESS());
IAavePool pool = IAavePool(IATokenWithPool(aToken).POOL());
// Approve underlying to Aave pool from the proxy (assumes the proxy has enough underlying).
_approve(address(underlying), address(pool), amount);
// Deposit underlying into Aave pool, proxy receives aTokens.
proxy.doCall(
address(pool),
abi.encodeCall(pool.supply, (address(underlying), amount, address(proxy), 0))
);
}
// NOTE: !!! Rate limited at end of function !!!
function withdrawAave(address aToken, uint256 amount)
external
onlyRole(RELAYER)
returns (uint256 amountWithdrawn)
{
IAavePool pool = IAavePool(IATokenWithPool(aToken).POOL());
// Withdraw underlying from Aave pool, decode resulting amount withdrawn.
// Assumes proxy has adequate aTokens.
amountWithdrawn = abi.decode(
proxy.doCall(
address(pool),
abi.encodeCall(
pool.withdraw,
(IATokenWithPool(aToken).UNDERLYING_ASSET_ADDRESS(), amount, address(proxy))
)
),
(uint256)
);
rateLimits.triggerRateLimitDecrease(
RateLimitHelpers.makeAssetKey(LIMIT_AAVE_WITHDRAW, aToken),
amountWithdrawn
);
}
/**********************************************************************************************/
/*** Relayer Morpho functions ***/
/**********************************************************************************************/
function setSupplyQueueMorpho(address morphoVault, Id[] memory newSupplyQueue)
external
onlyRole(RELAYER)
rateLimitExists(RateLimitHelpers.makeAssetKey(LIMIT_4626_DEPOSIT, morphoVault))
{
proxy.doCall(
morphoVault,
abi.encodeCall(IMetaMorpho(morphoVault).setSupplyQueue, (newSupplyQueue))
);
}
function updateWithdrawQueueMorpho(address morphoVault, uint256[] calldata indexes)
external
onlyRole(RELAYER)
rateLimitExists(RateLimitHelpers.makeAssetKey(LIMIT_4626_DEPOSIT, morphoVault))
{
proxy.doCall(
morphoVault,
abi.encodeCall(IMetaMorpho(morphoVault).updateWithdrawQueue, (indexes))
);
}
function reallocateMorpho(address morphoVault, MarketAllocation[] calldata allocations)
external
onlyRole(RELAYER)
rateLimitExists(RateLimitHelpers.makeAssetKey(LIMIT_4626_DEPOSIT, morphoVault))
{
proxy.doCall(
morphoVault,
abi.encodeCall(IMetaMorpho(morphoVault).reallocate, (allocations))
);
}
/**********************************************************************************************/
/*** Internal helper functions ***/
/**********************************************************************************************/
function _approve(address token, address spender, uint256 amount) internal {
proxy.doCall(token, abi.encodeCall(IERC20.approve, (spender, amount)));
}
function _initiateCCTPTransfer(
uint256 usdcAmount,
uint32 destinationDomain,
bytes32 mintRecipient
)
internal
{
uint64 nonce = abi.decode(
proxy.doCall(
address(cctp),
abi.encodeCall(
cctp.depositForBurn,
(
usdcAmount,
destinationDomain,
mintRecipient,
address(usdc)
)
)
),
(uint64)
);
emit CCTPTransferInitiated(nonce, destinationDomain, mintRecipient, usdcAmount);
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.21;
import { IRateLimits } from "../src/interfaces/IRateLimits.sol";
struct RateLimitData {
uint256 maxAmount;
uint256 slope;
}
library RateLimitHelpers {
error InvalidUnlimitedRateLimitSlope(string name);
error InvalidMaxAmountPrecision(string name);
error InvalidSlopePrecision(string name);
function makeAssetKey(bytes32 key, address asset) internal pure returns (bytes32) {
return keccak256(abi.encode(key, asset));
}
function makeAssetDestinationKey(bytes32 key, address asset, address destination) internal pure returns (bytes32) {
return keccak256(abi.encode(key, asset, destination));
}
function makeDomainKey(bytes32 key, uint32 domain) internal pure returns (bytes32) {
return keccak256(abi.encode(key, domain));
}
function unlimitedRateLimit() internal pure returns (RateLimitData memory) {
return RateLimitData({
maxAmount : type(uint256).max,
slope : 0
});
}
function setRateLimitData(
bytes32 key,
address rateLimits,
RateLimitData memory data,
string memory name,
uint256 decimals
)
internal
{
// Handle setting an unlimited rate limit
if (data.maxAmount == type(uint256).max) {
if (data.slope != 0) {
revert InvalidUnlimitedRateLimitSlope(name);
}
} else {
uint256 upperBound = 1e12 * (10 ** decimals);
uint256 lowerBound = 10 ** decimals;
if (data.maxAmount > upperBound || data.maxAmount < lowerBound) {
revert InvalidMaxAmountPrecision(name);
}
if (
data.slope != 0 &&
(data.slope > upperBound / 1 hours || data.slope < lowerBound / 1 hours)
) {
revert InvalidSlopePrecision(name);
}
}
IRateLimits(rateLimits).setRateLimitData(key, data.maxAmount, data.slope);
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.0;
interface IMessageTransmitter {
function sendMessage(
uint32 destinationDomain,
bytes32 recipient,
bytes calldata messageBody
) external;
}
library CCTPForwarder {
address constant internal MESSAGE_TRANSMITTER_CIRCLE_ETHEREUM = 0x0a992d191DEeC32aFe36203Ad87D7d289a738F81;
address constant internal MESSAGE_TRANSMITTER_CIRCLE_AVALANCHE = 0x8186359aF5F57FbB40c6b14A588d2A59C0C29880;
address constant internal MESSAGE_TRANSMITTER_CIRCLE_OPTIMISM = 0x4D41f22c5a0e5c74090899E5a8Fb597a8842b3e8;
address constant internal MESSAGE_TRANSMITTER_CIRCLE_ARBITRUM_ONE = 0xC30362313FBBA5cf9163F0bb16a0e01f01A896ca;
address constant internal MESSAGE_TRANSMITTER_CIRCLE_BASE = 0xAD09780d193884d503182aD4588450C416D6F9D4;
address constant internal MESSAGE_TRANSMITTER_CIRCLE_POLYGON_POS = 0xF3be9355363857F3e001be68856A2f96b4C39Ba9;
uint32 constant internal DOMAIN_ID_CIRCLE_ETHEREUM = 0;
uint32 constant internal DOMAIN_ID_CIRCLE_AVALANCHE = 1;
uint32 constant internal DOMAIN_ID_CIRCLE_OPTIMISM = 2;
uint32 constant internal DOMAIN_ID_CIRCLE_ARBITRUM_ONE = 3;
uint32 constant internal DOMAIN_ID_CIRCLE_NOBLE = 4;
uint32 constant internal DOMAIN_ID_CIRCLE_SOLANA = 5;
uint32 constant internal DOMAIN_ID_CIRCLE_BASE = 6;
uint32 constant internal DOMAIN_ID_CIRCLE_POLYGON_POS = 7;
function sendMessage(
address messageTransmitter,
uint32 destinationDomainId,
bytes32 recipient,
bytes memory messageBody
) internal {
IMessageTransmitter(messageTransmitter).sendMessage(
destinationDomainId,
recipient,
messageBody
);
}
function sendMessage(
address messageTransmitter,
uint32 destinationDomainId,
address recipient,
bytes memory messageBody
) internal {
sendMessage(
messageTransmitter,
destinationDomainId,
bytes32(uint256(uint160(recipient))),
messageBody
);
}
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import {IPoolAddressesProvider} from './IPoolAddressesProvider.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
/**
* @title IPool
* @author Aave
* @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
);
/**
* @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 number of initialized reserves
* @dev It includes dropped reserves
* @return The count
*/
function getReservesCount() external view returns (uint256);
/**
* @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;
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import {ConfiguratorInputTypes} from '../protocol/libraries/types/ConfiguratorInputTypes.sol';
/**
* @title IPoolConfigurator
* @author Aave
* @notice Defines the basic interface for a Pool configurator.
*/
interface IPoolConfigurator {
/**
* @dev Emitted when a reserve is initialized.
* @param asset The address of the underlying asset of the reserve
* @param aToken The address of the associated aToken contract
* @param stableDebtToken The address of the associated stable rate debt token
* @param variableDebtToken The address of the associated variable rate debt token
* @param interestRateStrategyAddress The address of the interest rate strategy for the reserve
*/
event ReserveInitialized(
address indexed asset,
address indexed aToken,
address stableDebtToken,
address variableDebtToken,
address interestRateStrategyAddress
);
/**
* @dev Emitted when borrowing is enabled or disabled on a reserve.
* @param asset The address of the underlying asset of the reserve
* @param enabled True if borrowing is enabled, false otherwise
*/
event ReserveBorrowing(address indexed asset, bool enabled);
/**
* @dev Emitted when flashloans are enabled or disabled on a reserve.
* @param asset The address of the underlying asset of the reserve
* @param enabled True if flashloans are enabled, false otherwise
*/
event ReserveFlashLoaning(address indexed asset, bool enabled);
/**
* @dev Emitted when the collateralization risk parameters for the specified asset are updated.
* @param asset The address of the underlying asset of the reserve
* @param ltv The loan to value of the asset when used as collateral
* @param liquidationThreshold The threshold at which loans using this asset as collateral will be considered undercollateralized
* @param liquidationBonus The bonus liquidators receive to liquidate this asset
*/
event CollateralConfigurationChanged(
address indexed asset,
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus
);
/**
* @dev Emitted when stable rate borrowing is enabled or disabled on a reserve
* @param asset The address of the underlying asset of the reserve
* @param enabled True if stable rate borrowing is enabled, false otherwise
*/
event ReserveStableRateBorrowing(address indexed asset, bool enabled);
/**
* @dev Emitted when a reserve is activated or deactivated
* @param asset The address of the underlying asset of the reserve
* @param active True if reserve is active, false otherwise
*/
event ReserveActive(address indexed asset, bool active);
/**
* @dev Emitted when a reserve is frozen or unfrozen
* @param asset The address of the underlying asset of the reserve
* @param frozen True if reserve is frozen, false otherwise
*/
event ReserveFrozen(address indexed asset, bool frozen);
/**
* @dev Emitted when a reserve is paused or unpaused
* @param asset The address of the underlying asset of the reserve
* @param paused True if reserve is paused, false otherwise
*/
event ReservePaused(address indexed asset, bool paused);
/**
* @dev Emitted when a reserve is dropped.
* @param asset The address of the underlying asset of the reserve
*/
event ReserveDropped(address indexed asset);
/**
* @dev Emitted when a reserve factor is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldReserveFactor The old reserve factor, expressed in bps
* @param newReserveFactor The new reserve factor, expressed in bps
*/
event ReserveFactorChanged(
address indexed asset,
uint256 oldReserveFactor,
uint256 newReserveFactor
);
/**
* @dev Emitted when the borrow cap of a reserve is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldBorrowCap The old borrow cap
* @param newBorrowCap The new borrow cap
*/
event BorrowCapChanged(address indexed asset, uint256 oldBorrowCap, uint256 newBorrowCap);
/**
* @dev Emitted when the supply cap of a reserve is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldSupplyCap The old supply cap
* @param newSupplyCap The new supply cap
*/
event SupplyCapChanged(address indexed asset, uint256 oldSupplyCap, uint256 newSupplyCap);
/**
* @dev Emitted when the liquidation protocol fee of a reserve is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldFee The old liquidation protocol fee, expressed in bps
* @param newFee The new liquidation protocol fee, expressed in bps
*/
event LiquidationProtocolFeeChanged(address indexed asset, uint256 oldFee, uint256 newFee);
/**
* @dev Emitted when the unbacked mint cap of a reserve is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldUnbackedMintCap The old unbacked mint cap
* @param newUnbackedMintCap The new unbacked mint cap
*/
event UnbackedMintCapChanged(
address indexed asset,
uint256 oldUnbackedMintCap,
uint256 newUnbackedMintCap
);
/**
* @dev Emitted when the category of an asset in eMode is changed.
* @param asset The address of the underlying asset of the reserve
* @param oldCategoryId The old eMode asset category
* @param newCategoryId The new eMode asset category
*/
event EModeAssetCategoryChanged(address indexed asset, uint8 oldCategoryId, uint8 newCategoryId);
/**
* @dev Emitted when a new eMode category is added.
* @param categoryId The new eMode category id
* @param ltv The ltv for the asset category in eMode
* @param liquidationThreshold The liquidationThreshold for the asset category in eMode
* @param liquidationBonus The liquidationBonus for the asset category in eMode
* @param oracle The optional address of the price oracle specific for this category
* @param label A human readable identifier for the category
*/
event EModeCategoryAdded(
uint8 indexed categoryId,
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus,
address oracle,
string label
);
/**
* @dev Emitted when a reserve interest strategy contract is updated.
* @param asset The address of the underlying asset of the reserve
* @param oldStrategy The address of the old interest strategy contract
* @param newStrategy The address of the new interest strategy contract
*/
event ReserveInterestRateStrategyChanged(
address indexed asset,
address oldStrategy,
address newStrategy
);
/**
* @dev Emitted when an aToken implementation is upgraded.
* @param asset The address of the underlying asset of the reserve
* @param proxy The aToken proxy address
* @param implementation The new aToken implementation
*/
event ATokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/**
* @dev Emitted when the implementation of a stable debt token is upgraded.
* @param asset The address of the underlying asset of the reserve
* @param proxy The stable debt token proxy address
* @param implementation The new aToken implementation
*/
event StableDebtTokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/**
* @dev Emitted when the implementation of a variable debt token is upgraded.
* @param asset The address of the underlying asset of the reserve
* @param proxy The variable debt token proxy address
* @param implementation The new aToken implementation
*/
event VariableDebtTokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/**
* @dev Emitted when the debt ceiling of an asset is set.
* @param asset The address of the underlying asset of the reserve
* @param oldDebtCeiling The old debt ceiling
* @param newDebtCeiling The new debt ceiling
*/
event DebtCeilingChanged(address indexed asset, uint256 oldDebtCeiling, uint256 newDebtCeiling);
/**
* @dev Emitted when the the siloed borrowing state for an asset is changed.
* @param asset The address of the underlying asset of the reserve
* @param oldState The old siloed borrowing state
* @param newState The new siloed borrowing state
*/
event SiloedBorrowingChanged(address indexed asset, bool oldState, bool newState);
/**
* @dev Emitted when the bridge protocol fee is updated.
* @param oldBridgeProtocolFee The old protocol fee, expressed in bps
* @param newBridgeProtocolFee The new protocol fee, expressed in bps
*/
event BridgeProtocolFeeUpdated(uint256 oldBridgeProtocolFee, uint256 newBridgeProtocolFee);
/**
* @dev Emitted when the total premium on flashloans is updated.
* @param oldFlashloanPremiumTotal The old premium, expressed in bps
* @param newFlashloanPremiumTotal The new premium, expressed in bps
*/
event FlashloanPremiumTotalUpdated(
uint128 oldFlashloanPremiumTotal,
uint128 newFlashloanPremiumTotal
);
/**
* @dev Emitted when the part of the premium that goes to protocol is updated.
* @param oldFlashloanPremiumToProtocol The old premium, expressed in bps
* @param newFlashloanPremiumToProtocol The new premium, expressed in bps
*/
event FlashloanPremiumToProtocolUpdated(
uint128 oldFlashloanPremiumToProtocol,
uint128 newFlashloanPremiumToProtocol
);
/**
* @dev Emitted when the reserve is set as borrowable/non borrowable in isolation mode.
* @param asset The address of the underlying asset of the reserve
* @param borrowable True if the reserve is borrowable in isolation, false otherwise
*/
event BorrowableInIsolationChanged(address asset, bool borrowable);
/**
* @notice Initializes multiple reserves.
* @param input The array of initialization parameters
*/
function initReserves(ConfiguratorInputTypes.InitReserveInput[] calldata input) external;
/**
* @dev Updates the aToken implementation for the reserve.
* @param input The aToken update parameters
*/
function updateAToken(ConfiguratorInputTypes.UpdateATokenInput calldata input) external;
/**
* @notice Updates the stable debt token implementation for the reserve.
* @param input The stableDebtToken update parameters
*/
function updateStableDebtToken(
ConfiguratorInputTypes.UpdateDebtTokenInput calldata input
) external;
/**
* @notice Updates the variable debt token implementation for the asset.
* @param input The variableDebtToken update parameters
*/
function updateVariableDebtToken(
ConfiguratorInputTypes.UpdateDebtTokenInput calldata input
) external;
/**
* @notice Configures borrowing on a reserve.
* @dev Can only be disabled (set to false) if stable borrowing is disabled
* @param asset The address of the underlying asset of the reserve
* @param enabled True if borrowing needs to be enabled, false otherwise
*/
function setReserveBorrowing(address asset, bool enabled) external;
/**
* @notice Configures the reserve collateralization parameters.
* @dev All the values are expressed in bps. A value of 10000, results in 100.00%
* @dev The `liquidationBonus` is always above 100%. A value of 105% means the liquidator will receive a 5% bonus
* @param asset The address of the underlying asset of the reserve
* @param ltv The loan to value of the asset when used as collateral
* @param liquidationThreshold The threshold at which loans using this asset as collateral will be considered undercollateralized
* @param liquidationBonus The bonus liquidators receive to liquidate this asset
*/
function configureReserveAsCollateral(
address asset,
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus
) external;
/**
* @notice Enable or disable stable rate borrowing on a reserve.
* @dev Can only be enabled (set to true) if borrowing is enabled
* @param asset The address of the underlying asset of the reserve
* @param enabled True if stable rate borrowing needs to be enabled, false otherwise
*/
function setReserveStableRateBorrowing(address asset, bool enabled) external;
/**
* @notice Enable or disable flashloans on a reserve
* @param asset The address of the underlying asset of the reserve
* @param enabled True if flashloans need to be enabled, false otherwise
*/
function setReserveFlashLoaning(address asset, bool enabled) external;
/**
* @notice Activate or deactivate a reserve
* @param asset The address of the underlying asset of the reserve
* @param active True if the reserve needs to be active, false otherwise
*/
function setReserveActive(address asset, bool active) external;
/**
* @notice Freeze or unfreeze a reserve. A frozen reserve doesn't allow any new supply, borrow
* or rate swap but allows repayments, liquidations, rate rebalances and withdrawals.
* @param asset The address of the underlying asset of the reserve
* @param freeze True if the reserve needs to be frozen, false otherwise
*/
function setReserveFreeze(address asset, bool freeze) external;
/**
* @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 (e.g. USD stablecoins) should be borrowable in isolation mode to keep
* consistency in the debt ceiling calculations
* @param asset The address of the underlying asset of the reserve
* @param borrowable True if the asset should be borrowable in isolation, false otherwise
*/
function setBorrowableInIsolation(address asset, bool borrowable) external;
/**
* @notice Pauses a reserve. A paused reserve does not allow any interaction (supply, borrow, repay,
* swap interest rate, liquidate, atoken transfers).
* @param asset The address of the underlying asset of the reserve
* @param paused True if pausing the reserve, false if unpausing
*/
function setReservePause(address asset, bool paused) external;
/**
* @notice Updates the reserve factor of a reserve.
* @param asset The address of the underlying asset of the reserve
* @param newReserveFactor The new reserve factor of the reserve
*/
function setReserveFactor(address asset, uint256 newReserveFactor) external;
/**
* @notice Sets the interest rate strategy of a reserve.
* @param asset The address of the underlying asset of the reserve
* @param newRateStrategyAddress The address of the new interest strategy contract
*/
function setReserveInterestRateStrategyAddress(
address asset,
address newRateStrategyAddress
) external;
/**
* @notice Pauses or unpauses all the protocol reserves. In the paused state all the protocol interactions
* are suspended.
* @param paused True if protocol needs to be paused, false otherwise
*/
function setPoolPause(bool paused) external;
/**
* @notice Updates the borrow cap of a reserve.
* @param asset The address of the underlying asset of the reserve
* @param newBorrowCap The new borrow cap of the reserve
*/
function setBorrowCap(address asset, uint256 newBorrowCap) external;
/**
* @notice Updates the supply cap of a reserve.
* @param asset The address of the underlying asset of the reserve
* @param newSupplyCap The new supply cap of the reserve
*/
function setSupplyCap(address asset, uint256 newSupplyCap) external;
/**
* @notice Updates the liquidation protocol fee of reserve.
* @param asset The address of the underlying asset of the reserve
* @param newFee The new liquidation protocol fee of the reserve, expressed in bps
*/
function setLiquidationProtocolFee(address asset, uint256 newFee) external;
/**
* @notice Updates the unbacked mint cap of reserve.
* @param asset The address of the underlying asset of the reserve
* @param newUnbackedMintCap The new unbacked mint cap of the reserve
*/
function setUnbackedMintCap(address asset, uint256 newUnbackedMintCap) external;
/**
* @notice Assign an efficiency mode (eMode) category to asset.
* @param asset The address of the underlying asset of the reserve
* @param newCategoryId The new category id of the asset
*/
function setAssetEModeCategory(address asset, uint8 newCategoryId) external;
/**
* @notice Adds a new efficiency mode (eMode) category.
* @dev If zero is provided as oracle address, the default asset oracles will be used to compute the overall debt and
* overcollateralization of the users using this category.
* @dev The new ltv and liquidation threshold must be greater than the base
* ltvs and liquidation thresholds of all assets within the eMode category
* @param categoryId The id of the category to be configured
* @param ltv The ltv associated with the category
* @param liquidationThreshold The liquidation threshold associated with the category
* @param liquidationBonus The liquidation bonus associated with the category
* @param oracle The oracle associated with the category
* @param label A label identifying the category
*/
function setEModeCategory(
uint8 categoryId,
uint16 ltv,
uint16 liquidationThreshold,
uint16 liquidationBonus,
address oracle,
string calldata label
) external;
/**
* @notice Drops a reserve entirely.
* @param asset The address of the reserve to drop
*/
function dropReserve(address asset) external;
/**
* @notice Updates the bridge fee collected by the protocol reserves.
* @param newBridgeProtocolFee The part of the fee sent to the protocol treasury, expressed in bps
*/
function updateBridgeProtocolFee(uint256 newBridgeProtocolFee) external;
/**
* @notice Updates the total flash loan premium.
* Total flash loan premium consists of two parts:
* - A part is sent to aToken holders as extra balance
* - A part is collected by the protocol reserves
* @dev Expressed in bps
* @dev The premium is calculated on the total amount borrowed
* @param newFlashloanPremiumTotal The total flashloan premium
*/
function updateFlashloanPremiumTotal(uint128 newFlashloanPremiumTotal) external;
/**
* @notice Updates the flash loan premium collected by protocol reserves
* @dev Expressed in bps
* @dev The premium to protocol is calculated on the total flashloan premium
* @param newFlashloanPremiumToProtocol The part of the flashloan premium sent to the protocol treasury
*/
function updateFlashloanPremiumToProtocol(uint128 newFlashloanPremiumToProtocol) external;
/**
* @notice Sets the debt ceiling for an asset.
* @param newDebtCeiling The new debt ceiling
*/
function setDebtCeiling(address asset, uint256 newDebtCeiling) external;
/**
* @notice Sets siloed borrowing for an asset
* @param siloed The new siloed borrowing state
*/
function setSiloedBorrowing(address asset, bool siloed) external;
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import {IPriceOracleGetter} from './IPriceOracleGetter.sol';
import {IPoolAddressesProvider} from './IPoolAddressesProvider.sol';
/**
* @title IAaveOracle
* @author Aave
* @notice Defines the basic interface for the Aave Oracle
*/
interface IAaveOracle is IPriceOracleGetter {
/**
* @dev Emitted after the base currency is set
* @param baseCurrency The base currency of used for price quotes
* @param baseCurrencyUnit The unit of the base currency
*/
event BaseCurrencySet(address indexed baseCurrency, uint256 baseCurrencyUnit);
/**
* @dev Emitted after the price source of an asset is updated
* @param asset The address of the asset
* @param source The price source of the asset
*/
event AssetSourceUpdated(address indexed asset, address indexed source);
/**
* @dev Emitted after the address of fallback oracle is updated
* @param fallbackOracle The address of the fallback oracle
*/
event FallbackOracleUpdated(address indexed fallbackOracle);
/**
* @notice Returns the PoolAddressesProvider
* @return The address of the PoolAddressesProvider contract
*/
function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider);
/**
* @notice Sets or replaces price sources of assets
* @param assets The addresses of the assets
* @param sources The addresses of the price sources
*/
function setAssetSources(address[] calldata assets, address[] calldata sources) external;
/**
* @notice Sets the fallback oracle
* @param fallbackOracle The address of the fallback oracle
*/
function setFallbackOracle(address fallbackOracle) external;
/**
* @notice Returns a list of prices from a list of assets addresses
* @param assets The list of assets addresses
* @return The prices of the given assets
*/
function getAssetsPrices(address[] calldata assets) external view returns (uint256[] memory);
/**
* @notice Returns the address of the source for an asset address
* @param asset The address of the asset
* @return The address of the source
*/
function getSourceOfAsset(address asset) external view returns (address);
/**
* @notice Returns the address of the fallback oracle
* @return The address of the fallback oracle
*/
function getFallbackOracle() external view returns (address);
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
/**
* @title IPoolAddressesProvider
* @author Aave
* @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;
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import {IReserveInterestRateStrategy} from './IReserveInterestRateStrategy.sol';
import {IPoolAddressesProvider} from './IPoolAddressesProvider.sol';
/**
* @title IDefaultInterestRateStrategy
* @author Aave
* @notice Defines the basic interface of the DefaultReserveInterestRateStrategy
*/
interface IDefaultInterestRateStrategy is IReserveInterestRateStrategy {
/**
* @notice Returns the usage ratio at which the pool aims to obtain most competitive borrow rates.
* @return The optimal usage ratio, expressed in ray.
*/
function OPTIMAL_USAGE_RATIO() external view returns (uint256);
/**
* @notice Returns the optimal stable to total debt ratio of the reserve.
* @return The optimal stable to total debt ratio, expressed in ray.
*/
function OPTIMAL_STABLE_TO_TOTAL_DEBT_RATIO() external view returns (uint256);
/**
* @notice Returns the excess usage ratio above the optimal.
* @dev It's always equal to 1-optimal usage ratio (added as constant for gas optimizations)
* @return The max excess usage ratio, expressed in ray.
*/
function MAX_EXCESS_USAGE_RATIO() external view returns (uint256);
/**
* @notice Returns the excess stable debt ratio above the optimal.
* @dev It's always equal to 1-optimal stable to total debt ratio (added as constant for gas optimizations)
* @return The max excess stable to total debt ratio, expressed in ray.
*/
function MAX_EXCESS_STABLE_TO_TOTAL_DEBT_RATIO() external view returns (uint256);
/**
* @notice Returns the address of the PoolAddressesProvider
* @return The address of the PoolAddressesProvider contract
*/
function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider);
/**
* @notice Returns the variable rate slope below optimal usage ratio
* @dev It's the variable rate when usage ratio > 0 and <= OPTIMAL_USAGE_RATIO
* @return The variable rate slope, expressed in ray
*/
function getVariableRateSlope1() external view returns (uint256);
/**
* @notice Returns the variable rate slope above optimal usage ratio
* @dev It's the variable rate when usage ratio > OPTIMAL_USAGE_RATIO
* @return The variable rate slope, expressed in ray
*/
function getVariableRateSlope2() external view returns (uint256);
/**
* @notice Returns the stable rate slope below optimal usage ratio
* @dev It's the stable rate when usage ratio > 0 and <= OPTIMAL_USAGE_RATIO
* @return The stable rate slope, expressed in ray
*/
function getStableRateSlope1() external view returns (uint256);
/**
* @notice Returns the stable rate slope above optimal usage ratio
* @dev It's the variable rate when usage ratio > OPTIMAL_USAGE_RATIO
* @return The stable rate slope, expressed in ray
*/
function getStableRateSlope2() external view returns (uint256);
/**
* @notice Returns the stable rate excess offset
* @dev It's an additional premium applied to the stable when stable debt > OPTIMAL_STABLE_TO_TOTAL_DEBT_RATIO
* @return The stable rate excess offset, expressed in ray
*/
function getStableRateExcessOffset() external view returns (uint256);
/**
* @notice Returns the base stable borrow rate
* @return The base stable borrow rate, expressed in ray
*/
function getBaseStableBorrowRate() external view returns (uint256);
/**
* @notice Returns the base variable borrow rate
* @return The base variable borrow rate, expressed in ray
*/
function getBaseVariableBorrowRate() external view returns (uint256);
/**
* @notice Returns the maximum variable borrow rate
* @return The maximum variable borrow rate, expressed in ray
*/
function getMaxVariableBorrowRate() external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title IScaledBalanceToken
* @author Aave
* @notice Defines the basic interface for a scaled-balance token.
*/
interface IScaledBalanceToken {
/**
* @dev Emitted after the mint action
* @param caller The address performing the mint
* @param onBehalfOf The address of the user that will receive the minted tokens
* @param value The scaled-up amount being minted (based on user entered amount and balance increase from interest)
* @param balanceIncrease The increase in scaled-up balance since the last action of 'onBehalfOf'
* @param index The next liquidity index of the reserve
*/
event Mint(
address indexed caller,
address indexed onBehalfOf,
uint256 value,
uint256 balanceIncrease,
uint256 index
);
/**
* @dev Emitted after the burn action
* @dev If the burn function does not involve a transfer of the underlying asset, the target defaults to zero address
* @param from The address from which the tokens will be burned
* @param target The address that will receive the underlying, if any
* @param value The scaled-up amount being burned (user entered amount - balance increase from interest)
* @param balanceIncrease The increase in scaled-up balance since the last action of 'from'
* @param index The next liquidity index of the reserve
*/
event Burn(
address indexed from,
address indexed target,
uint256 value,
uint256 balanceIncrease,
uint256 index
);
/**
* @notice Returns the scaled balance of the user.
* @dev The scaled balance is the sum of all the updated stored balance divided by the reserve's liquidity index
* at the moment of the update
* @param user The user whose balance is calculated
* @return The scaled balance of the user
*/
function scaledBalanceOf(address user) external view returns (uint256);
/**
* @notice Returns the scaled balance of the user and the scaled total supply.
* @param user The address of the user
* @return The scaled balance of the user
* @return The scaled total supply
*/
function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256);
/**
* @notice Returns the scaled total supply of the scaled balance token. Represents sum(debt/index)
* @return The scaled total supply
*/
function scaledTotalSupply() external view returns (uint256);
/**
* @notice Returns last index interest was accrued to the user's balance
* @param user The address of the user
* @return The last index interest was accrued to the user's balance, expressed in ray
*/
function getPreviousIndex(address user) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IAaveIncentivesController} from './IAaveIncentivesController.sol';
import {IPool} from './IPool.sol';
/**
* @title IInitializableAToken
* @author Aave
* @notice Interface for the initialize function on AToken
*/
interface IInitializableAToken {
/**
* @dev Emitted when an aToken is initialized
* @param underlyingAsset The address of the underlying asset
* @param pool The address of the associated pool
* @param treasury The address of the treasury
* @param incentivesController The address of the incentives controller for this aToken
* @param aTokenDecimals The decimals of the underlying
* @param aTokenName The name of the aToken
* @param aTokenSymbol The symbol of the aToken
* @param params A set of encoded parameters for additional initialization
*/
event Initialized(
address indexed underlyingAsset,
address indexed pool,
address treasury,
address incentivesController,
uint8 aTokenDecimals,
string aTokenName,
string aTokenSymbol,
bytes params
);
/**
* @notice Initializes the aToken
* @param pool The pool contract that is initializing this contract
* @param treasury The address of the Aave treasury, receiving the fees on this aToken
* @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH)
* @param incentivesController The smart contract managing potential incentives distribution
* @param aTokenDecimals The decimals of the aToken, same as the underlying asset's
* @param aTokenName The name of the aToken
* @param aTokenSymbol The symbol of the aToken
* @param params A set of encoded parameters for additional initialization
*/
function initialize(
IPool pool,
address treasury,
address underlyingAsset,
IAaveIncentivesController incentivesController,
uint8 aTokenDecimals,
string calldata aTokenName,
string calldata aTokenSymbol,
bytes calldata params
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC4626.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";
import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";
/**
* @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in
* https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
*/
interface IERC4626 is IERC20, IERC20Metadata {
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed sender,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
/**
* @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
*
* - MUST be an ERC-20 token contract.
* - MUST NOT revert.
*/
function asset() external view returns (address assetTokenAddress);
/**
* @dev Returns the total amount of the underlying asset that is “managed” by Vault.
*
* - SHOULD include any compounding that occurs from yield.
* - MUST be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT revert.
*/
function totalAssets() external view returns (uint256 totalManagedAssets);
/**
* @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToShares(uint256 assets) external view returns (uint256 shares);
/**
* @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
* through a deposit call.
*
* - MUST return a limited value if receiver is subject to some deposit limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
* - MUST NOT revert.
*/
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
* call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
* in the same transaction.
* - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
* deposit would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewDeposit(uint256 assets) external view returns (uint256 shares);
/**
* @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* deposit execution, and are accounted for during deposit.
* - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
* - MUST return a limited value if receiver is subject to some mint limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
* - MUST NOT revert.
*/
function maxMint(address receiver) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
* in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
* same transaction.
* - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
* would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by minting.
*/
function previewMint(uint256 shares) external view returns (uint256 assets);
/**
* @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
* execution, and are accounted for during mint.
* - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
* Vault, through a withdraw call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
* call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
* called
* in the same transaction.
* - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
* the withdrawal would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
/**
* @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* withdraw execution, and are accounted for during withdraw.
* - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
* through a redeem call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxRedeem(address owner) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
* in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
* same transaction.
* - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
* redemption would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by redeeming.
*/
function previewRedeem(uint256 shares) external view returns (uint256 assets);
/**
* @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* redeem execution, and are accounted for during redeem.
* - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
struct MarketConfig {
/// @notice The maximum amount of assets that can be allocated to the market.
uint184 cap;
/// @notice Whether the market is in the withdraw queue.
bool enabled;
/// @notice The timestamp at which the market can be instantly removed from the withdraw queue.
uint64 removableAt;
}
struct PendingUint192 {
/// @notice The pending value to set.
uint192 value;
/// @notice The timestamp at which the pending value becomes valid.
uint64 validAt;
}
struct PendingAddress {
/// @notice The pending value to set.
address value;
/// @notice The timestamp at which the pending value becomes valid.
uint64 validAt;
}
/// @title PendingLib
/// @author Morpho Labs
/// @custom:contact [email protected]
/// @notice Library to manage pending values and their validity timestamp.
library PendingLib {
/// @dev Updates `pending`'s value to `newValue` and its corresponding `validAt` timestamp.
/// @dev Assumes `timelock` <= `MAX_TIMELOCK`.
function update(PendingUint192 storage pending, uint184 newValue, uint256 timelock) internal {
pending.value = newValue;
// Safe "unchecked" cast because timelock <= MAX_TIMELOCK.
pending.validAt = uint64(block.timestamp + timelock);
}
/// @dev Updates `pending`'s value to `newValue` and its corresponding `validAt` timestamp.
/// @dev Assumes `timelock` <= `MAX_TIMELOCK`.
function update(PendingAddress storage pending, address newValue, uint256 timelock) internal {
pending.value = newValue;
// Safe "unchecked" cast because timelock <= MAX_TIMELOCK.
pending.validAt = uint64(block.timestamp + timelock);
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity >=0.8.0;
import { IAccessControl } from "openzeppelin-contracts/contracts/access/IAccessControl.sol";
interface IALMProxy is IAccessControl {
/**
* @dev This function retrieves a constant `bytes32` value that represents the controller.
* @return The `bytes32` identifier of the controller.
*/
function CONTROLLER() external view returns (bytes32);
/**
* @dev Performs a standard call to the specified `target` with the given `data`.
* Reverts if the call fails.
* @param target The address of the target contract to call.
* @param data The calldata that will be sent to the target contract.
* @return result The returned data from the call.
*/
function doCall(address target, bytes calldata data)
external returns (bytes memory result);
/**
* @dev This function allows for transferring `value` (ether) along with the call to the target contract.
* Reverts if the call fails.
* @param target The address of the target contract to call.
* @param data The calldata that will be sent to the target contract.
* @param value The amount of Ether (in wei) to send with the call.
* @return result The returned data from the call.
*/
function doCallWithValue(address target, bytes memory data, uint256 value)
external payable returns (bytes memory result);
/**
* @dev This function performs a delegate call to the specified `target`
* with the given `data`. Reverts if the call fails.
* @param target The address of the target contract to delegate call.
* @param data The calldata that will be sent to the target contract.
* @return result The returned data from the delegate call.
*/
function doDelegateCall(address target, bytes calldata data)
external returns (bytes memory result);
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity >=0.8.0;
import { IAccessControl } from "openzeppelin-contracts/contracts/access/IAccessControl.sol";
interface IRateLimits is IAccessControl {
/**********************************************************************************************/
/*** Structs ***/
/**********************************************************************************************/
/**
* @dev Struct representing a rate limit.
* The current rate limit is calculated using the formula:
* `currentRateLimit = min(slope * (block.timestamp - lastUpdated) + lastAmount, maxAmount)`.
* @param maxAmount Maximum allowed amount at any time.
* @param slope The slope of the rate limit, used to calculate the new
* limit based on time passed. [tokens / second]
* @param lastAmount The amount left available at the last update.
* @param lastUpdated The timestamp when the rate limit was last updated.
*/
struct RateLimitData {
uint256 maxAmount;
uint256 slope;
uint256 lastAmount;
uint256 lastUpdated;
}
/**********************************************************************************************/
/*** Events ***/
/**********************************************************************************************/
/**
* @dev Emitted when the rate limit data is set.
* @param key The identifier for the rate limit.
* @param maxAmount The maximum allowed amount for the rate limit.
* @param slope The slope value used in the rate limit calculation.
* @param lastAmount The amount left available at the last update.
* @param lastUpdated The timestamp when the rate limit was last updated.
*/
event RateLimitDataSet(
bytes32 indexed key,
uint256 maxAmount,
uint256 slope,
uint256 lastAmount,
uint256 lastUpdated
);
/**
* @dev Emitted when a rate limit decrease is triggered.
* @param key The identifier for the rate limit.
* @param amountToDecrease The amount to decrease from the current rate limit.
* @param oldRateLimit The previous rate limit value before triggering.
* @param newRateLimit The new rate limit value after triggering.
*/
event RateLimitDecreaseTriggered(
bytes32 indexed key,
uint256 amountToDecrease,
uint256 oldRateLimit,
uint256 newRateLimit
);
/**
* @dev Emitted when a rate limit increase is triggered.
* @param key The identifier for the rate limit.
* @param amountToIncrease The amount to increase from the current rate limit.
* @param oldRateLimit The previous rate limit value before triggering.
* @param newRateLimit The new rate limit value after triggering.
*/
event RateLimitIncreaseTriggered(
bytes32 indexed key,
uint256 amountToIncrease,
uint256 oldRateLimit,
uint256 newRateLimit
);
/**********************************************************************************************/
/*** State variables ***/
/**********************************************************************************************/
/**
* @dev Returns the controller identifier as a bytes32 value.
* @return The controller identifier.
*/
function CONTROLLER() external view returns (bytes32);
/**********************************************************************************************/
/*** Admin functions ***/
/**********************************************************************************************/
/**
* @dev Sets rate limit data for a specific key.
* @param key The identifier for the rate limit.
* @param maxAmount The maximum allowed amount for the rate limit.
* @param slope The slope value used in the rate limit calculation.
* @param lastAmount The amount left available at the last update.
* @param lastUpdated The timestamp when the rate limit was last updated.
*/
function setRateLimitData(
bytes32 key,
uint256 maxAmount,
uint256 slope,
uint256 lastAmount,
uint256 lastUpdated
) external;
/**
* @dev Sets rate limit data for a specific key with
* `lastAmount == maxAmount` and `lastUpdated == block.timestamp`.
* @param key The identifier for the rate limit.
* @param maxAmount The maximum allowed amount for the rate limit.
* @param slope The slope value used in the rate limit calculation.
*/
function setRateLimitData(bytes32 key, uint256 maxAmount, uint256 slope) external;
/**
* @dev Sets an unlimited rate limit.
* @param key The identifier for the rate limit.
*/
function setUnlimitedRateLimitData(bytes32 key) external;
/**********************************************************************************************/
/*** Getter Functions ***/
/**********************************************************************************************/
/**
* @dev Retrieves the RateLimitData struct associated with a specific key.
* @param key The identifier for the rate limit.
* @return The data associated with the rate limit.
*/
function getRateLimitData(bytes32 key) external view returns (RateLimitData memory);
/**
* @dev Retrieves the current rate limit for a specific key.
* @param key The identifier for the rate limit.
* @return The current rate limit value for the given key.
*/
function getCurrentRateLimit(bytes32 key) external view returns (uint256);
/**********************************************************************************************/
/*** Controller functions ***/
/**********************************************************************************************/
/**
* @dev Triggers the rate limit for a specific key and reduces the available
* amount by the provided value.
* @param key The identifier for the rate limit.
* @param amountToDecrease The amount to decrease from the current rate limit.
* @return newLimit The updated rate limit after the deduction.
*/
function triggerRateLimitDecrease(bytes32 key, uint256 amountToDecrease)
external returns (uint256 newLimit);
/**
* @dev Increases the rate limit for a given key up to the maxAmount. Does not revert if
* the new rate limit exceeds the maxAmount.
* @param key The identifier for the rate limit.
* @param amountToIncrease The amount to increase from the current rate limit.
* @return newLimit The updated rate limit after the addition.
*/
function triggerRateLimitIncrease(bytes32 key, uint256 amountToIncrease)
external returns (uint256 newLimit);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IPoolAddressesProvider} from './IPoolAddressesProvider.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
/**
* @title IPool
* @author Aave
* @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 Permissionless method which allows anyone to swap a users stable debt to variable debt
* @dev Introduced in favor of stable rate deprecation
* @param asset The address of the underlying asset borrowed
* @param user The address of the user whose debt will be swapped from stable to variable
*/
function swapToVariable(address asset, address user) 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 Accumulates interest to all indexes of the reserve
* @dev Only callable by the PoolConfigurator contract
* @dev To be used when required by the configurator, for example when updating interest rates strategy data
* @param asset The address of the underlying asset of the reserve
*/
function syncIndexesState(address asset) external;
/**
* @notice Updates interest rates on the reserve data
* @dev Only callable by the PoolConfigurator contract
* @dev To be used when required by the configurator, for example when updating interest rates strategy data
* @param asset The address of the underlying asset of the reserve
*/
function syncRatesState(address asset) 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.ReserveDataLegacy memory);
/**
* @notice Returns the state and configuration of the reserve, including extra data included with Aave v3.1
* @param asset The address of the underlying asset of the reserve
* @return The state and configuration data of the reserve with virtual accounting
*/
function getReserveDataExtended(
address asset
) external view returns (DataTypes.ReserveData memory);
/**
* @notice Returns the virtual underlying balance of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The reserve virtual underlying balance
*/
function getVirtualUnderlyingBalance(address asset) external view returns (uint128);
/**
* @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 number of initialized reserves
* @dev It includes dropped reserves
* @return The count
*/
function getReservesCount() external view returns (uint256);
/**
* @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 Sets the liquidation grace period of the given asset
* @dev To enable a liquidation grace period, a timestamp in the future should be set,
* To disable a liquidation grace period, any timestamp in the past works, like 0
* @param asset The address of the underlying asset to set the liquidationGracePeriod
* @param until Timestamp when the liquidation grace period will end
**/
function setLiquidationGracePeriod(address asset, uint40 until) external;
/**
* @notice Returns the liquidation grace period of the given asset
* @param asset The address of the underlying asset
* @return Timestamp when the liquidation grace period will end
**/
function getLiquidationGracePeriod(address asset) external returns (uint40);
/**
* @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;
/**
* @notice Gets the address of the external FlashLoanLogic
*/
function getFlashLoanLogic() external returns (address);
/**
* @notice Gets the address of the external BorrowLogic
*/
function getBorrowLogic() external returns (address);
/**
* @notice Gets the address of the external BridgeLogic
*/
function getBridgeLogic() external returns (address);
/**
* @notice Gets the address of the external EModeLogic
*/
function getEModeLogic() external returns (address);
/**
* @notice Gets the address of the external LiquidationLogic
*/
function getLiquidationLogic() external returns (address);
/**
* @notice Gets the address of the external PoolLogic
*/
function getPoolLogic() external returns (address);
/**
* @notice Gets the address of the external SupplyLogic
*/
function getSupplyLogic() external returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2;
import {IERC7575} from "./IERC7575.sol";
/// @dev Interface of the base operator logic of ERC7540, as defined in
/// https://eips.ethereum.org/EIPS/eip-7540
interface IERC7540Operator {
/**
* @dev The event emitted when an operator is set.
*
* @param controller The address of the controller.
* @param operator The address of the operator.
* @param approved The approval status.
*/
event OperatorSet(address indexed controller, address indexed operator, bool approved);
/**
* @dev Sets or removes an operator for the caller.
*
* @param operator The address of the operator.
* @param approved The approval status.
* @return Whether the call was executed successfully or not
*/
function setOperator(address operator, bool approved) external returns (bool);
/**
* @dev Returns `true` if the `operator` is approved as an operator for an `controller`.
*
* @param controller The address of the controller.
* @param operator The address of the operator.
* @return status The approval status
*/
function isOperator(address controller, address operator) external view returns (bool status);
}
/// @dev Interface of the asynchronous deposit Vault interface of ERC7540, as defined in
/// https://eips.ethereum.org/EIPS/eip-7540
interface IERC7540Deposit is IERC7540Operator {
event DepositRequest(
address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
);
/**
* @dev Transfers assets from sender into the Vault and submits a Request for asynchronous deposit.
*
* - MUST support ERC-20 approve / transferFrom on asset as a deposit Request flow.
* - MUST revert if all of assets cannot be requested for deposit.
* - owner MUST be msg.sender unless some unspecified explicit approval is given by the caller,
* approval of ERC-20 tokens from owner to sender is NOT enough.
*
* @param assets the amount of deposit assets to transfer from owner
* @param controller the controller of the request who will be able to operate the request
* @param owner the source of the deposit assets
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault's underlying asset token.
*/
function requestDeposit(uint256 assets, address controller, address owner) external returns (uint256 requestId);
/**
* @dev Returns the amount of requested assets in Pending state.
*
* - MUST NOT include any assets in Claimable state for deposit or mint.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
*/
function pendingDepositRequest(uint256 requestId, address controller)
external
view
returns (uint256 pendingAssets);
/**
* @dev Returns the amount of requested assets in Claimable state for the controller to deposit or mint.
*
* - MUST NOT include any assets in Pending state.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
*/
function claimableDepositRequest(uint256 requestId, address controller)
external
view
returns (uint256 claimableAssets);
/**
* @dev Mints shares Vault shares to receiver by claiming the Request of the controller.
*
* - MUST emit the Deposit event.
* - controller MUST equal msg.sender unless the controller has approved the msg.sender as an operator.
*/
function deposit(uint256 assets, address receiver, address controller) external returns (uint256 shares);
/**
* @dev Mints exactly shares Vault shares to receiver by claiming the Request of the controller.
*
* - MUST emit the Deposit event.
* - controller MUST equal msg.sender unless the controller has approved the msg.sender as an operator.
*/
function mint(uint256 shares, address receiver, address controller) external returns (uint256 assets);
}
/// @dev Interface of the asynchronous deposit Vault interface of ERC7540, as defined in
/// https://eips.ethereum.org/EIPS/eip-7540
interface IERC7540Redeem is IERC7540Operator {
event RedeemRequest(
address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
);
/**
* @dev Assumes control of shares from sender into the Vault and submits a Request for asynchronous redeem.
*
* - MUST support a redeem Request flow where the control of shares is taken from sender directly
* where msg.sender has ERC-20 approval over the shares of owner.
* - MUST revert if all of shares cannot be requested for redeem.
*
* @param shares the amount of shares to be redeemed to transfer from owner
* @param controller the controller of the request who will be able to operate the request
* @param owner the source of the shares to be redeemed
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault's share token.
*/
function requestRedeem(uint256 shares, address controller, address owner) external returns (uint256 requestId);
/**
* @dev Returns the amount of requested shares in Pending state.
*
* - MUST NOT include any shares in Claimable state for redeem or withdraw.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
*/
function pendingRedeemRequest(uint256 requestId, address controller)
external
view
returns (uint256 pendingShares);
/**
* @dev Returns the amount of requested shares in Claimable state for the controller to redeem or withdraw.
*
* - MUST NOT include any shares in Pending state for redeem or withdraw.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
*/
function claimableRedeemRequest(uint256 requestId, address controller)
external
view
returns (uint256 claimableShares);
}
/// @dev Interface of the fully asynchronous Vault interface of ERC7540, as defined in
/// https://eips.ethereum.org/EIPS/eip-7540
interface IERC7540 is IERC7540Deposit, IERC7540Redeem, IERC7575 {}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)
pragma solidity ^0.8.20;
import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {ERC165} from "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
mapping(bytes32 role => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with an {AccessControlUnauthorizedAccount} error including the required role.
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
return _roles[role].hasRole[account];
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
* is missing `role`.
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
if (!hasRole(role, account)) {
_roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
/**
* @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
if (hasRole(role, account)) {
_roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity >=0.8.0;
interface ICCTPLike {
function depositForBurn(
uint256 amount,
uint32 destinationDomain,
bytes32 mintRecipient,
address burnToken
) external returns (uint64 nonce);
function localMinter() external view returns (ICCTPTokenMinterLike);
}
interface ICCTPTokenMinterLike {
function burnLimitsPerMessage(address) external view returns (uint256);
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.13;
import { IERC20 } from "erc20-helpers/interfaces/IERC20.sol";
interface IPSM3 {
/**********************************************************************************************/
/*** Events ***/
/**********************************************************************************************/
/**
* @dev Emitted when a new pocket is set in the PSM, transferring the balance of USDC.
* of the old pocket to the new pocket.
* @param oldPocket Address of the old `pocket`.
* @param newPocket Address of the new `pocket`.
* @param amountTransferred Amount of USDC transferred from the old pocket to the new pocket.
*/
event PocketSet(
address indexed oldPocket,
address indexed newPocket,
uint256 amountTransferred
);
/**
* @dev Emitted when an asset is swapped in the PSM.
* @param assetIn Address of the asset swapped in.
* @param assetOut Address of the asset swapped out.
* @param sender Address of the sender of the swap.
* @param receiver Address of the receiver of the swap.
* @param amountIn Amount of the asset swapped in.
* @param amountOut Amount of the asset swapped out.
* @param referralCode Referral code for the swap.
*/
event Swap(
address indexed assetIn,
address indexed assetOut,
address sender,
address indexed receiver,
uint256 amountIn,
uint256 amountOut,
uint256 referralCode
);
/**
* @dev Emitted when an asset is deposited into the PSM.
* @param asset Address of the asset deposited.
* @param user Address of the user that deposited the asset.
* @param receiver Address of the receiver of the resulting shares from the deposit.
* @param assetsDeposited Amount of the asset deposited.
* @param sharesMinted Number of shares minted to the user.
*/
event Deposit(
address indexed asset,
address indexed user,
address indexed receiver,
uint256 assetsDeposited,
uint256 sharesMinted
);
/**
* @dev Emitted when an asset is withdrawn from the PSM.
* @param asset Address of the asset withdrawn.
* @param user Address of the user that withdrew the asset.
* @param receiver Address of the receiver of the withdrawn assets.
* @param assetsWithdrawn Amount of the asset withdrawn.
* @param sharesBurned Number of shares burned from the user.
*/
event Withdraw(
address indexed asset,
address indexed user,
address indexed receiver,
uint256 assetsWithdrawn,
uint256 sharesBurned
);
/**********************************************************************************************/
/*** State variables and immutables ***/
/**********************************************************************************************/
/**
* @dev Returns the IERC20 interface representing USDC.
* @return The IERC20 interface of USDC.
*/
function usdc() external view returns (IERC20);
/**
* @dev Returns the IERC20 interface representing USDS.
* @return The IERC20 interface of USDS.
*/
function usds() external view returns (IERC20);
/**
* @dev Returns the IERC20 interface representing sUSDS. This asset is the yield-bearing
* asset in the PSM. The value of this asset is queried from the rate provider.
* @return The IERC20 interface of sUSDS.
*/
function susds() external view returns (IERC20);
/**
* @dev Returns the address of the pocket, an address that holds custody of USDC in the
* PSM and can deploy it to yield-bearing strategies. Settable by the owner.
* @return The address of the pocket.
*/
function pocket() external view returns (address);
/**
* @dev Returns the address of the rate provider, a contract that provides the conversion
* rate between sUSDS and the other two assets in the PSM (e.g., sUSDS to USD).
* @return The address of the rate provider.
*/
function rateProvider() external view returns (address);
/**
* @dev Returns the total number of shares in the PSM. Shares represent ownership of the
* assets in the PSM and can be converted to assets at any time.
* @return The total number of shares.
*/
function totalShares() external view returns (uint256);
/**
* @dev Returns the number of shares held by a specific user.
* @param user The address of the user.
* @return The number of shares held by the user.
*/
function shares(address user) external view returns (uint256);
/**********************************************************************************************/
/*** Owner functions ***/
/**********************************************************************************************/
/**
* @dev Sets the address of the pocket, an address that holds custody of USDC in the PSM
* and can deploy it to yield-bearing strategies. This function will transfer the
* balance of USDC in the PSM to the new pocket. Callable only by the owner.
* @param newPocket Address of the new pocket.
*/
function setPocket(address newPocket) external;
/**********************************************************************************************/
/*** Swap functions ***/
/**********************************************************************************************/
/**
* @dev Swaps a specified amount of assetIn for assetOut in the PSM. The amount swapped is
* converted based on the current value of the two assets used in the swap. This
* function will revert if there is not enough balance in the PSM to facilitate the
* swap. Both assets must be supported in the PSM in order to succeed.
* @param assetIn Address of the ERC-20 asset to swap in.
* @param assetOut Address of the ERC-20 asset to swap out.
* @param amountIn Amount of the asset to swap in.
* @param minAmountOut Minimum amount of the asset to receive.
* @param receiver Address of the receiver of the swapped assets.
* @param referralCode Referral code for the swap.
* @return amountOut Resulting amount of the asset that will be received in the swap.
*/
function swapExactIn(
address assetIn,
address assetOut,
uint256 amountIn,
uint256 minAmountOut,
address receiver,
uint256 referralCode
) external returns (uint256 amountOut);
/**
* @dev Swaps a derived amount of assetIn for a specific amount of assetOut in the PSM. The
* amount swapped is converted based on the current value of the two assets used in
* the swap. This function will revert if there is not enough balance in the PSM to
* facilitate the swap. Both assets must be supported in the PSM in order to succeed.
* @param assetIn Address of the ERC-20 asset to swap in.
* @param assetOut Address of the ERC-20 asset to swap out.
* @param amountOut Amount of the asset to receive from the swap.
* @param maxAmountIn Max amount of the asset to use for the swap.
* @param receiver Address of the receiver of the swapped assets.
* @param referralCode Referral code for the swap.
* @return amountIn Resulting amount of the asset swapped in.
*/
function swapExactOut(
address assetIn,
address assetOut,
uint256 amountOut,
uint256 maxAmountIn,
address receiver,
uint256 referralCode
) external returns (uint256 amountIn);
/**********************************************************************************************/
/*** Liquidity provision functions ***/
/**********************************************************************************************/
/**
* @dev Deposits an amount of a given asset into the PSM. Must be one of the supported
* assets in order to succeed. The amount deposited is converted to shares based on
* the current exchange rate.
* @param asset Address of the ERC-20 asset to deposit.
* @param receiver Address of the receiver of the resulting shares from the deposit.
* @param assetsToDeposit Amount of the asset to deposit into the PSM.
* @return newShares Number of shares minted to the user.
*/
function deposit(address asset, address receiver, uint256 assetsToDeposit)
external returns (uint256 newShares);
/**
* @dev Withdraws an amount of a given asset from the PSM up to `maxAssetsToWithdraw`.
* Must be one of the supported assets in order to succeed. The amount withdrawn is
* the minimum of the balance of the PSM, the max amount, and the max amount of assets
* that the user's shares can be converted to.
* @param asset Address of the ERC-20 asset to withdraw.
* @param receiver Address of the receiver of the withdrawn assets.
* @param maxAssetsToWithdraw Max amount that the user is willing to withdraw.
* @return assetsWithdrawn Resulting amount of the asset withdrawn from the PSM.
*/
function withdraw(
address asset,
address receiver,
uint256 maxAssetsToWithdraw
) external returns (uint256 assetsWithdrawn);
/**********************************************************************************************/
/*** Deposit/withdraw preview functions ***/
/**********************************************************************************************/
/**
* @dev View function that returns the exact number of shares that would be minted for a
* given asset and amount to deposit.
* @param asset Address of the ERC-20 asset to deposit.
* @param assets Amount of the asset to deposit into the PSM.
* @return shares Number of shares to be minted to the user.
*/
function previewDeposit(address asset, uint256 assets) external view returns (uint256 shares);
/**
* @dev View function that returns the exact number of assets that would be withdrawn and
* corresponding shares that would be burned in a withdrawal for a given asset and max
* withdraw amount. The amount returned is the minimum of the balance of the PSM,
* the max amount, and the max amount of assets that the user's shares
* can be converted to.
* @param asset Address of the ERC-20 asset to withdraw.
* @param maxAssetsToWithdraw Max amount that the user is willing to withdraw.
* @return sharesToBurn Number of shares that would be burned in the withdrawal.
* @return assetsWithdrawn Resulting amount of the asset withdrawn from the PSM.
*/
function previewWithdraw(address asset, uint256 maxAssetsToWithdraw)
external view returns (uint256 sharesToBurn, uint256 assetsWithdrawn);
/**********************************************************************************************/
/*** Swap preview functions ***/
/**********************************************************************************************/
/**
* @dev View function that returns the exact amount of assetOut that would be received for a
* given amount of assetIn in a swap. The amount returned is converted based on the
* current value of the two assets used in the swap.
* @param assetIn Address of the ERC-20 asset to swap in.
* @param assetOut Address of the ERC-20 asset to swap out.
* @param amountIn Amount of the asset to swap in.
* @return amountOut Amount of the asset that will be received in the swap.
*/
function previewSwapExactIn(address assetIn, address assetOut, uint256 amountIn)
external view returns (uint256 amountOut);
/**
* @dev View function that returns the exact amount of assetIn that would be required to
* receive a given amount of assetOut in a swap. The amount returned is
* converted based on the current value of the two assets used in the swap.
* @param assetIn Address of the ERC-20 asset to swap in.
* @param assetOut Address of the ERC-20 asset to swap out.
* @param amountOut Amount of the asset to receive from the swap.
* @return amountIn Amount of the asset that is required to receive amountOut.
*/
function previewSwapExactOut(address assetIn, address assetOut, uint256 amountOut)
external view returns (uint256 amountIn);
/**********************************************************************************************/
/*** Conversion functions ***/
/**********************************************************************************************/
/**
* @dev View function that converts an amount of a given shares to the equivalent amount of
* assets for a specified asset.
* @param asset Address of the asset to use to convert.
* @param numShares Number of shares to convert to assets.
* @return assets Value of assets in asset-native units.
*/
function convertToAssets(address asset, uint256 numShares) external view returns (uint256);
/**
* @dev View function that converts an amount of a given shares to the equivalent
* amount of assetValue.
* @param numShares Number of shares to convert to assetValue.
* @return assetValue Value of assets in USDC denominated in 18 decimals.
*/
function convertToAssetValue(uint256 numShares) external view returns (uint256);
/**
* @dev View function that converts an amount of assetValue (18 decimal value denominated in
* USDC and USDS) to shares in the PSM based on the current exchange rate.
* Note that this rounds down on calculation so is intended to be used for quoting the
* current exchange rate.
* @param assetValue 18 decimal value denominated in USDC (e.g., 1e6 USDC = 1e18)
* @return shares Number of shares that the assetValue is equivalent to.
*/
function convertToShares(uint256 assetValue) external view returns (uint256);
/**
* @dev View function that converts an amount of a given asset to shares in the PSM based
* on the current exchange rate. Note that this rounds down on calculation so is
* intended to be used for quoting the current exchange rate.
* @param asset Address of the ERC-20 asset to convert to shares.
* @param assets Amount of assets in asset-native units.
* @return shares Number of shares that the assetValue is equivalent to.
*/
function convertToShares(address asset, uint256 assets) external view returns (uint256);
/**********************************************************************************************/
/*** Asset value functions ***/
/**********************************************************************************************/
/**
* @dev View function that returns the total value of the balance of all assets in the PSM
* converted to USDC/USDS terms denominated in 18 decimal precision.
*/
function totalAssets() external view returns (uint256);
}// SPDX-License-Identifier: BUSL-1.1
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 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;
}
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;
}
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 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 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 ExecuteWithdrawParams {
address asset;
uint256 amount;
address to;
uint256 reservesCount;
address oracle;
uint8 userEModeCategory;
}
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 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;
address pool;
uint8 userEModeCategory;
bool isAuthorizedFlashBorrower;
}
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 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 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 InitReserveParams {
address asset;
address aTokenAddress;
address stableDebtAddress;
address variableDebtAddress;
address interestRateStrategyAddress;
uint16 reservesCount;
uint16 maxNumberReserves;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
library ConfiguratorInputTypes {
struct InitReserveInput {
address aTokenImpl;
address stableDebtTokenImpl;
address variableDebtTokenImpl;
uint8 underlyingAssetDecimals;
address interestRateStrategyAddress;
address underlyingAsset;
address treasury;
address incentivesController;
string aTokenName;
string aTokenSymbol;
string variableDebtTokenName;
string variableDebtTokenSymbol;
string stableDebtTokenName;
string stableDebtTokenSymbol;
bytes params;
}
struct UpdateATokenInput {
address asset;
address treasury;
address incentivesController;
string name;
string symbol;
address implementation;
bytes params;
}
struct UpdateDebtTokenInput {
address asset;
address incentivesController;
string name;
string symbol;
address implementation;
bytes params;
}
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
/**
* @title IPriceOracleGetter
* @author Aave
* @notice Interface for the Aave price oracle.
*/
interface IPriceOracleGetter {
/**
* @notice Returns the base currency address
* @dev Address 0x0 is reserved for USD as base currency.
* @return Returns the base currency address.
*/
function BASE_CURRENCY() external view returns (address);
/**
* @notice Returns the base currency unit
* @dev 1 ether for ETH, 1e8 for USD.
* @return Returns the base currency unit.
*/
function BASE_CURRENCY_UNIT() external view returns (uint256);
/**
* @notice Returns the asset price in the base currency
* @param asset The address of the asset
* @return The price of the asset
*/
function getAssetPrice(address asset) external view returns (uint256);
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
/**
* @title IReserveInterestRateStrategy
* @author Aave
* @notice Interface for the calculation of the interest rates
*/
interface IReserveInterestRateStrategy {
/**
* @notice Calculates the interest rates depending on the reserve's state and configurations
* @param params The parameters needed to calculate interest rates
* @return liquidityRate The liquidity rate expressed in rays
* @return stableBorrowRate The stable borrow rate expressed in rays
* @return variableBorrowRate The variable borrow rate expressed in rays
*/
function calculateInterestRates(
DataTypes.CalculateInterestRatesParams memory params
) external view returns (uint256, uint256, uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title IAaveIncentivesController
* @author Aave
* @notice Defines the basic interface for an Aave Incentives Controller.
* @dev It only contains one single function, needed as a hook on aToken and debtToken transfers.
*/
interface IAaveIncentivesController {
/**
* @dev Called by the corresponding asset on transfer hook in order to update the rewards distribution.
* @dev The units of `totalSupply` and `userBalance` should be the same.
* @param user The address of the user whose asset balance has changed
* @param totalSupply The total supply of the asset prior to user balance change
* @param userBalance The previous user balance prior to balance change
*/
function handleAction(address user, uint256 totalSupply, uint256 userBalance) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title IPoolAddressesProvider
* @author Aave
* @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;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library DataTypes {
/**
* This exists specifically to maintain the `getReserveData()` interface, since the new, internal
* `ReserveData` struct includes the reserve's `virtualUnderlyingBalance`.
*/
struct ReserveDataLegacy {
//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;
//timestamp until when liquidations are not allowed on the reserve, if set to past liquidations will be allowed
uint40 liquidationGracePeriodUntil;
//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;
//the amount of underlying accounted for by the protocol
uint128 virtualUnderlyingBalance;
}
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: virtual accounting is enabled for the reserve
//bit 253-255 unused
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;
}
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 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 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 ExecuteWithdrawParams {
address asset;
uint256 amount;
address to;
uint256 reservesCount;
address oracle;
uint8 userEModeCategory;
}
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 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;
address pool;
uint8 userEModeCategory;
bool isAuthorizedFlashBorrower;
}
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 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 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;
bool usingVirtualBalance;
uint256 virtualUnderlyingBalance;
}
struct InitReserveParams {
address asset;
address aTokenAddress;
address stableDebtAddress;
address variableDebtAddress;
address interestRateStrategyAddress;
uint16 reservesCount;
uint16 maxNumberReserves;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2;
import {IERC165} from "./IERC165.sol";
/// @dev Interface of the ERC7575 "Multi-Asset ERC-4626 Vaults", as defined in
/// https://eips.ethereum.org/EIPS/eip-7575
interface IERC7575 is IERC165 {
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares
);
/**
* @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
*
* - MUST be an ERC-20 token contract.
* - MUST NOT revert.
*/
function asset() external view returns (address assetTokenAddress);
/**
* @dev Returns the address of the share token
*
* - MUST be an ERC-20 token contract.
* - MUST NOT revert.
*/
function share() external view returns (address shareTokenAddress);
/**
* @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToShares(uint256 assets) external view returns (uint256 shares);
/**
* @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/**
* @dev Returns the total amount of the underlying asset that is “managed” by Vault.
*
* - SHOULD include any compounding that occurs from yield.
* - MUST be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT revert.
*/
function totalAssets() external view returns (uint256 totalManagedAssets);
/**
* @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
* through a deposit call.
*
* - MUST return a limited value if receiver is subject to some deposit limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
* - MUST NOT revert.
*/
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
* call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
* in the same transaction.
* - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
* deposit would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewDeposit(uint256 assets) external view returns (uint256 shares);
/**
* @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* deposit execution, and are accounted for during deposit.
* - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
* - MUST return a limited value if receiver is subject to some mint limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
* - MUST NOT revert.
*/
function maxMint(address receiver) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
* in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
* same transaction.
* - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
* would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by minting.
*/
function previewMint(uint256 shares) external view returns (uint256 assets);
/**
* @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
* execution, and are accounted for during mint.
* - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
* Vault, through a withdraw call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
* call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
* called
* in the same transaction.
* - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
* the withdrawal would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
/**
* @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* withdraw execution, and are accounted for during withdraw.
* - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
* through a redeem call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxRedeem(address owner) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
* in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
* same transaction.
* - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
* redemption would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by redeeming.
*/
function previewRedeem(uint256 shares) external view returns (uint256 assets);
/**
* @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* redeem execution, and are accounted for during redeem.
* - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}
/// @dev Interface of the ERC20 share token, as defined in
/// https://eips.ethereum.org/EIPS/eip-7575
interface IERC7575Share is IERC165 {
event VaultUpdate(address indexed asset, address vault);
/**
* @dev Returns the address of the Vault for the given asset.
*
* @param asset the ERC-20 token to deposit with into the Vault
*/
function vault(address asset) external view returns (address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/*
* @title Interface of the ERC20 standard as defined in the EIP,
* including EIP-2612 permit functionality.
*/
interface IERC20 {
/**********************************************************************************************/
/*** Events ***/
/**********************************************************************************************/
/**
* @dev Emitted when one account has set the allowance of another account over their tokens.
* @param owner Account that tokens are approved from.
* @param spender Account that tokens are approved for.
* @param amount Amount of tokens that have been approved.
*/
event Approval(address indexed owner, address indexed spender, uint256 amount);
/**
* @dev Emitted when tokens have moved from one account to another.
* @param owner Account that tokens have moved from.
* @param recipient Account that tokens have moved to.
* @param amount Amount of tokens that have been transferred.
*/
event Transfer(address indexed owner, address indexed recipient, uint256 amount);
/**********************************************************************************************/
/*** External Functions ***/
/**********************************************************************************************/
/**
* @dev Function that allows one account to set the allowance of another account
* over their tokens.
* Emits an {Approval} event.
* @param spender Account that tokens are approved for.
* @param amount Amount of tokens that have been approved.
* @return success Boolean indicating whether the operation succeeded.
*/
function approve(address spender, uint256 amount) external returns (bool success);
/**
* @dev Function that allows one account to decrease the allowance of another
* account over their tokens.
* Emits an {Approval} event.
* @param spender Account that tokens are approved for.
* @param subtractedAmount Amount to decrease approval by.
* @return success Boolean indicating whether the operation succeeded.
*/
function decreaseAllowance(address spender, uint256 subtractedAmount)
external returns (bool success);
/**
* @dev Function that allows one account to increase the allowance of another
* account over their tokens.
* Emits an {Approval} event.
* @param spender Account that tokens are approved for.
* @param addedAmount Amount to increase approval by.
* @return success Boolean indicating whether the operation succeeded.
*/
function increaseAllowance(address spender, uint256 addedAmount)
external returns (bool success);
/**
* @dev Approve by signature.
* @param owner Owner address that signed the permit.
* @param spender Spender of the permit.
* @param amount Permit approval spend limit.
* @param deadline Deadline after which the permit is invalid.
* @param v ECDSA signature v component.
* @param r ECDSA signature r component.
* @param s ECDSA signature s component.
*/
function permit(
address owner,
address spender,
uint256 amount,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Moves an amount of tokens from `msg.sender` to a specified account.
* Emits a {Transfer} event.
* @param recipient Account that receives tokens.
* @param amount Amount of tokens that are transferred.
* @return success Boolean indicating whether the operation succeeded.
*/
function transfer(address recipient, uint256 amount) external returns (bool success);
/**
* @dev Moves a pre-approved amount of tokens from a sender to a specified account.
* Emits a {Transfer} event.
* Emits an {Approval} event.
* @param owner Account that tokens are moving from.
* @param recipient Account that receives tokens.
* @param amount Amount of tokens that are transferred.
* @return success Boolean indicating whether the operation succeeded.
*/
function transferFrom(address owner, address recipient, uint256 amount)
external returns (bool success);
/**********************************************************************************************/
/*** View Functions ***/
/**********************************************************************************************/
/**
* @dev Returns the allowance that one account has given another over their tokens.
* @param owner Account that tokens are approved from.
* @param spender Account that tokens are approved for.
* @return allowance Allowance that one account has given another over their tokens.
*/
function allowance(address owner, address spender) external view returns (uint256 allowance);
/**
* @dev Returns the amount of tokens owned by a given account.
* @param account Account that owns the tokens.
* @return balance Amount of tokens owned by a given account.
*/
function balanceOf(address account) external view returns (uint256 balance);
/**
* @dev Returns the decimal precision used by the token.
* @return decimals The decimal precision used by the token.
*/
function decimals() external view returns (uint8 decimals);
/**
* @dev Returns the signature domain separator.
* @return domainSeparator The signature domain separator.
*/
function DOMAIN_SEPARATOR() external view returns (bytes32 domainSeparator);
/**
* @dev Returns the name of the token.
* @return name The name of the token.
*/
function name() external view returns (string memory name);
/**
* @dev Returns the nonce for the given owner.
* @param owner The address of the owner account.
* @return nonce The nonce for the given owner.
*/
function nonces(address owner) external view returns (uint256 nonce);
/**
* @dev Returns the permit type hash.
* @return permitTypehash The permit type hash.
*/
function PERMIT_TYPEHASH() external view returns (bytes32 permitTypehash);
/**
* @dev Returns the symbol of the token.
* @return symbol The symbol of the token.
*/
function symbol() external view returns (string memory symbol);
/**
* @dev Returns the total amount of tokens in existence.
* @return totalSupply The total amount of tokens in existence.
*/
function totalSupply() external view returns (uint256 totalSupply);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2;
interface IERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceID The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}{
"remappings": [
"morpho-blue/=lib/metamorpho/lib/morpho-blue/",
"@openzeppelin/contracts-upgradeable/=lib/spark-alm-controller/lib/sdai/lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/contracts/=lib/metamorpho/lib/openzeppelin-contracts/contracts/",
"aave-v3-core/=lib/sparklend-kill-switch/lib/aave-v3-core/",
"aave-v3-origin/=lib/spark-alm-controller/lib/aave-v3-origin/",
"aave-v3-periphery/=lib/aave-v3-periphery/contracts/",
"ds-test/=lib/metamorpho/lib/forge-std/lib/ds-test/src/",
"dss-allocator/=lib/spark-alm-controller/lib/dss-allocator/",
"dss-interfaces/=lib/spark-alm-controller/lib/dss-test/lib/dss-interfaces/src/",
"dss-test/=lib/spark-alm-controller/lib/dss-test/src/",
"erc20-helpers/=lib/erc20-helpers/src/",
"erc4626-tests/=lib/metamorpho/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"metamorpho/=lib/metamorpho/src/",
"morpho-blue-oracles/=lib/morpho-blue-oracles/src/",
"murky/=lib/metamorpho/lib/universal-rewards-distributor/lib/murky/src/",
"openzeppelin-contracts-upgradeable/=lib/spark-alm-controller/lib/sdai/lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/metamorpho/lib/openzeppelin-contracts/",
"openzeppelin-foundry-upgrades/=lib/spark-alm-controller/lib/sdai/lib/openzeppelin-foundry-upgrades/src/",
"openzeppelin/=lib/metamorpho/lib/universal-rewards-distributor/lib/openzeppelin-contracts/contracts/",
"sdai/=lib/spark-alm-controller/lib/sdai/",
"solidity-stringutils/=lib/spark-alm-controller/lib/sdai/lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/",
"solidity-utils/=lib/spark-alm-controller/lib/aave-v3-origin/lib/solidity-utils/",
"spark-address-registry/=lib/spark-address-registry/src/",
"spark-alm-controller/=lib/spark-alm-controller/",
"spark-gov-relay/=lib/spark-gov-relay/",
"spark-psm/=lib/spark-alm-controller/lib/spark-psm/",
"sparklend-address-registry/=lib/spark-alm-controller/lib/spark-psm/lib/xchain-ssr-oracle/lib/sparklend-address-registry/",
"sparklend-cap-automator/=lib/sparklend-cap-automator/src/",
"sparklend-freezer/=lib/sparklend-freezer/src/",
"sparklend-kill-switch/=lib/sparklend-kill-switch/src/",
"sparklend-v1-core/=lib/sparklend-v1-core/",
"token-tests/=lib/spark-alm-controller/lib/sdai/lib/token-tests/src/",
"universal-rewards-distributor/=lib/metamorpho/lib/universal-rewards-distributor/src/",
"usds/=lib/spark-alm-controller/lib/usds/",
"xchain-helpers/=lib/xchain-helpers/src/",
"xchain-ssr-oracle/=lib/spark-alm-controller/lib/spark-psm/lib/xchain-ssr-oracle/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"name","type":"string"}],"name":"InvalidMaxAmountPrecision","type":"error"},{"inputs":[{"internalType":"string","name":"name","type":"string"}],"name":"InvalidSlopePrecision","type":"error"},{"inputs":[{"internalType":"string","name":"name","type":"string"}],"name":"InvalidUnlimitedRateLimitSlope","type":"error"},{"inputs":[],"name":"LISTING_ENGINE","outputs":[{"internalType":"contract IAaveV3ConfigEngine","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAYLOAD_ARBITRUM","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAYLOAD_BASE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAYLOAD_GNOSIS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowsUpdates","outputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"enabledToBorrow","type":"uint256"},{"internalType":"uint256","name":"flashloanable","type":"uint256"},{"internalType":"uint256","name":"stableRateModeEnabled","type":"uint256"},{"internalType":"uint256","name":"borrowableInIsolation","type":"uint256"},{"internalType":"uint256","name":"withSiloedBorrowing","type":"uint256"},{"internalType":"uint256","name":"reserveFactor","type":"uint256"}],"internalType":"struct IAaveV3ConfigEngine.BorrowUpdate[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"capsUpdates","outputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"supplyCap","type":"uint256"},{"internalType":"uint256","name":"borrowCap","type":"uint256"}],"internalType":"struct IAaveV3ConfigEngine.CapsUpdate[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateralsUpdates","outputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"ltv","type":"uint256"},{"internalType":"uint256","name":"liqThreshold","type":"uint256"},{"internalType":"uint256","name":"liqBonus","type":"uint256"},{"internalType":"uint256","name":"debtCeiling","type":"uint256"},{"internalType":"uint256","name":"liqProtocolFee","type":"uint256"},{"internalType":"uint256","name":"eModeCategory","type":"uint256"}],"internalType":"struct IAaveV3ConfigEngine.CollateralUpdate[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getPoolContext","outputs":[{"components":[{"internalType":"string","name":"networkName","type":"string"},{"internalType":"string","name":"networkAbbreviation","type":"string"}],"internalType":"struct IAaveV3ConfigEngine.PoolContext","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"newListings","outputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"string","name":"assetSymbol","type":"string"},{"internalType":"address","name":"priceFeed","type":"address"},{"components":[{"internalType":"uint256","name":"optimalUsageRatio","type":"uint256"},{"internalType":"uint256","name":"baseVariableBorrowRate","type":"uint256"},{"internalType":"uint256","name":"variableRateSlope1","type":"uint256"},{"internalType":"uint256","name":"variableRateSlope2","type":"uint256"},{"internalType":"uint256","name":"stableRateSlope1","type":"uint256"},{"internalType":"uint256","name":"stableRateSlope2","type":"uint256"},{"internalType":"uint256","name":"baseStableRateOffset","type":"uint256"},{"internalType":"uint256","name":"stableRateExcessOffset","type":"uint256"},{"internalType":"uint256","name":"optimalStableToTotalDebtRatio","type":"uint256"}],"internalType":"struct IV3RateStrategyFactory.RateStrategyParams","name":"rateStrategyParams","type":"tuple"},{"internalType":"uint256","name":"enabledToBorrow","type":"uint256"},{"internalType":"uint256","name":"stableRateModeEnabled","type":"uint256"},{"internalType":"uint256","name":"borrowableInIsolation","type":"uint256"},{"internalType":"uint256","name":"withSiloedBorrowing","type":"uint256"},{"internalType":"uint256","name":"flashloanable","type":"uint256"},{"internalType":"uint256","name":"ltv","type":"uint256"},{"internalType":"uint256","name":"liqThreshold","type":"uint256"},{"internalType":"uint256","name":"liqBonus","type":"uint256"},{"internalType":"uint256","name":"reserveFactor","type":"uint256"},{"internalType":"uint256","name":"supplyCap","type":"uint256"},{"internalType":"uint256","name":"borrowCap","type":"uint256"},{"internalType":"uint256","name":"debtCeiling","type":"uint256"},{"internalType":"uint256","name":"liqProtocolFee","type":"uint256"},{"internalType":"uint8","name":"eModeCategory","type":"uint8"}],"internalType":"struct IAaveV3ConfigEngine.Listing[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"newListingsCustom","outputs":[{"components":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"string","name":"assetSymbol","type":"string"},{"internalType":"address","name":"priceFeed","type":"address"},{"components":[{"internalType":"uint256","name":"optimalUsageRatio","type":"uint256"},{"internalType":"uint256","name":"baseVariableBorrowRate","type":"uint256"},{"internalType":"uint256","name":"variableRateSlope1","type":"uint256"},{"internalType":"uint256","name":"variableRateSlope2","type":"uint256"},{"internalType":"uint256","name":"stableRateSlope1","type":"uint256"},{"internalType":"uint256","name":"stableRateSlope2","type":"uint256"},{"internalType":"uint256","name":"baseStableRateOffset","type":"uint256"},{"internalType":"uint256","name":"stableRateExcessOffset","type":"uint256"},{"internalType":"uint256","name":"optimalStableToTotalDebtRatio","type":"uint256"}],"internalType":"struct IV3RateStrategyFactory.RateStrategyParams","name":"rateStrategyParams","type":"tuple"},{"internalType":"uint256","name":"enabledToBorrow","type":"uint256"},{"internalType":"uint256","name":"stableRateModeEnabled","type":"uint256"},{"internalType":"uint256","name":"borrowableInIsolation","type":"uint256"},{"internalType":"uint256","name":"withSiloedBorrowing","type":"uint256"},{"internalType":"uint256","name":"flashloanable","type":"uint256"},{"internalType":"uint256","name":"ltv","type":"uint256"},{"internalType":"uint256","name":"liqThreshold","type":"uint256"},{"internalType":"uint256","name":"liqBonus","type":"uint256"},{"internalType":"uint256","name":"reserveFactor","type":"uint256"},{"internalType":"uint256","name":"supplyCap","type":"uint256"},{"internalType":"uint256","name":"borrowCap","type":"uint256"},{"internalType":"uint256","name":"debtCeiling","type":"uint256"},{"internalType":"uint256","name":"liqProtocolFee","type":"uint256"},{"internalType":"uint8","name":"eModeCategory","type":"uint8"}],"internalType":"struct IAaveV3ConfigEngine.Listing","name":"base","type":"tuple"},{"components":[{"internalType":"address","name":"aToken","type":"address"},{"internalType":"address","name":"vToken","type":"address"},{"internalType":"address","name":"sToken","type":"address"}],"internalType":"struct IAaveV3ConfigEngine.TokenImplementations","name":"implementations","type":"tuple"}],"internalType":"struct IAaveV3ConfigEngine.ListingWithCustomImpl[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeedsUpdates","outputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"priceFeed","type":"address"}],"internalType":"struct IAaveV3ConfigEngine.PriceFeedUpdate[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rateStrategiesUpdates","outputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"components":[{"internalType":"uint256","name":"optimalUsageRatio","type":"uint256"},{"internalType":"uint256","name":"baseVariableBorrowRate","type":"uint256"},{"internalType":"uint256","name":"variableRateSlope1","type":"uint256"},{"internalType":"uint256","name":"variableRateSlope2","type":"uint256"},{"internalType":"uint256","name":"stableRateSlope1","type":"uint256"},{"internalType":"uint256","name":"stableRateSlope2","type":"uint256"},{"internalType":"uint256","name":"baseStableRateOffset","type":"uint256"},{"internalType":"uint256","name":"stableRateExcessOffset","type":"uint256"},{"internalType":"uint256","name":"optimalStableToTotalDebtRatio","type":"uint256"}],"internalType":"struct IV3RateStrategyFactory.RateStrategyParams","name":"params","type":"tuple"}],"internalType":"struct IAaveV3ConfigEngine.RateStrategyUpdate[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"}]Contract Creation Code
610100604052348015600f575f80fd5b50733254f7cd0565aa67eedc86c2fb608be48d5ccd7860805260805160a05160c05160e051611dbf6100a75f395f81816101670152818161033d015261038701525f8181610136015281816102af015261030e01525f818161019d0152818161021a015261027901525f818160d40152818161048b0152818161097801528181610a7c01528181610b800152610c840152611dbf5ff3fe608060405234801561000f575f80fd5b50600436106100cb575f3560e01c806395a93cb111610088578063c0a2558011610063578063c0a25580146101ce578063d0c38c27146101dd578063fabe3463146101ec578063fbb256f6146101fb575f80fd5b806395a93cb114610189578063b14e012714610198578063b1af0d0d146101bf575f80fd5b80630a4aa3fa146100cf5780631850edd8146101135780632b179434146101225780634c8031251461013157806361461954146101585780636256d8ad14610162575b5f80fd5b6100f67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b606060405161010a9190611494565b606060405161010a91906114e1565b6100f67f000000000000000000000000000000000000000000000000000000000000000081565b610160610210565b005b6100f67f000000000000000000000000000000000000000000000000000000000000000081565b606060405161010a9190611522565b6100f67f000000000000000000000000000000000000000000000000000000000000000081565b606060405161010a9190611583565b606060405161010a91906117c3565b606060405161010a91906117d5565b606060405161010a91906118b1565b6102036103b6565b60405161010a91906118f9565b610218610415565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316156102ad576102ad734dbd4fc535ac27206064b68ffcf827b0a60bab3f73212871a1c235892f86cab30e937e18c94aed847461029d7f00000000000000000000000000000000000000000000000000000000000000006105b5565b620f4240640ba43b7400486107a9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161561033b5761033b73866e82a600a1414e583f7f13623f1ac5d58b0afa73fda082e00ef89185d9db7e5dcd8c5505070f5a3b6103327f00000000000000000000000000000000000000000000000000000000000000006105b5565b620f42406108c0565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316156103b4576103b473c4218c1127cb24a0d6c1e7d25dc34e10f2625f5a6103ab7f00000000000000000000000000000000000000000000000000000000000000006105b5565b620f4240610923565b565b60408051808201909152606080825260208201525060408051608081018252600881830190815267457468657265756d60c01b606083015281528151808301909252600382526208ae8d60eb1b60208381019190915281019190915290565b60608051819081908190819081908190156104b3576104b1633cb6502d60e01b61043d6103b6565b8960405160240161044f92919061190b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690610948565b505b8551156104e1576104df6314d8093760e21b6104cd6103b6565b8860405160240161044f92919061192f565b505b825115610508576040516105069063bb06653560e01b9061044f908690602401611494565b505b83511561052f5760405161052d90636e17618760e11b9061044f9087906024016114e1565b505b80511561055657604051610554906324f4c44560e01b9061044f9084906024016117d5565b505b81511561057d5760405161057b9063927c400360e01b9061044f908590602401611583565b505b8451156105a4576040516105a2906355caa16360e01b9061044f908890602401611522565b505b6105ac610976565b50505050505050565b6040805160018082528183019092526060915f91906020808301908036833750506040805160018082528183019092529293505f9291506020808301908036833750506040805160018082528183019092529293505f929150602082015b60608152602001906001900390816106135750506040805160018082528183019092529192505f9190602082015b60608152602001906001900390816106415750506040805160018082528183019092529192505f91906020808301908036833701905050905086855f8151811061068d5761068d611953565b60200260200101906001600160a01b031690816001600160a01b0316815250505f845f815181106106c0576106c0611953565b6020026020010181815250506040518060400160405280600981526020016865786563757465282960b81b815250835f8151811061070057610700611953565b602002602001018190525060405180602001604052805f815250825f8151811061072c5761072c611953565b60200260200101819052506001815f8151811061074b5761074b611953565b911515602092830291909101909101526040516107749086908690869086908690602401611a1d565b60408051601f198184030181529190526020810180516001600160e01b031663d9a4cbdf60e01b179052979650505050505050565b835160405163a66b327d60e01b81525f916001600160a01b0389169163a66b327d916107e2918690600401918252602082015260400190565b602060405180830381865afa1580156107fd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108219190611abc565b90505f61082e8486611ae7565b90506001600160a01b03881663679b6ded6108498385611afe565b895f865f808c8c8f6040518a63ffffffff1660e01b8152600401610874989796959493929190611b11565b60206040518083038185885af1158015610890573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906108b59190611abc565b505050505050505050565b604051633dbb202b60e01b81526001600160a01b03851690633dbb202b906108f090869086908690600401611b6b565b5f604051808303815f87803b158015610907575f80fd5b505af1158015610919573d5f803e3d5ffd5b5050505050505050565b610943734c36d2919e407f0cc2ee3c993ccf8ac26d9ce64e848484610f09565b505050565b606061096d8383604051806060016040528060278152602001611d6360279139610f79565b90505b92915050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663587250846040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109f69190611bbb565b604051631d2118f960e01b8152736b175474e89094c44da98b954eedeac495271d0f6004820152737729e1ce24d7c4a82e76b4a2c118e328c35e656660248201526001600160a01b039190911690631d2118f9906044015f604051808303815f87803b158015610a64575f80fd5b505af1158015610a76573d5f803e3d5ffd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663587250846040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ad6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610afa9190611bbb565b604051631d2118f960e01b815273dc035d45d973e3ec169d2276ddab16f1e407384f6004820152737729e1ce24d7c4a82e76b4a2c118e328c35e656660248201526001600160a01b039190911690631d2118f9906044015f604051808303815f87803b158015610b68575f80fd5b505af1158015610b7a573d5f803e3d5ffd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663587250846040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bda573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bfe9190611bbb565b604051631d2118f960e01b815273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486004820152737f2fc6a7e3b3c658a84999b26ad2013c4dc8706160248201526001600160a01b039190911690631d2118f9906044015f604051808303815f87803b158015610c6c575f80fd5b505af1158015610c7e573d5f803e3d5ffd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663587250846040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cde573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d029190611bbb565b604051631d2118f960e01b815273dac17f958d2ee523a2206206994597c13d831ec76004820152737f2fc6a7e3b3c658a84999b26ad2013c4dc8706160248201526001600160a01b039190911690631d2118f9906044015f604051808303815f87803b158015610d70575f80fd5b505af1158015610d82573d5f803e3d5ffd5b50505050610dbf73e7df13b8e3d6740fe17cbe928c7334243d86c92f655af3107a400062015180652d79883d2000610dba9190611bdd565b610fed565b610df17323878914efe38d27c4d67ab83ed1b93a74d4086a652d79883d2000610dba620151806516bcc41e9000611bdd565b60405163b28c909f60e01b815273dac17f958d2ee523a2206206994597c13d831ec76004820152631dcd650060248201526305f5e100604482015261a8c06064820152732276f52afba7cf2525fd0a050df464ac8532d0ef90819063b28c909f906084015f604051808303815f87803b158015610e6c575f80fd5b505af1158015610e7e573d5f803e3d5ffd5b50506040516328e7733d60e01b815273dac17f958d2ee523a2206206994597c13d831ec76004820152631ad2748060248201526302faf080604482015261a8c060648201526001600160a01b03841692506328e7733d91506084015f604051808303815f87803b158015610ef0575f80fd5b505af1158015610f02573d5f803e3d5ffd5b5050505050565b60405163dc8601b360e01b81526001600160a01b0385169063dc8601b390610f3990869086908690600401611bfc565b6020604051808303815f875af1158015610f55573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f029190611abc565b60605f80856001600160a01b031685604051610f959190611c2f565b5f60405180830381855af49150503d805f8114610fcd576040519150601f19603f3d011682016040523d82523d5f602084013e610fd2565b606091505b5091509150610fe38683838761100d565b9695505050505050565b610943737a5fd5cf045e010e62147f065ceae59e5344b188848484611092565b606083156110805782515f03611079576001600160a01b0385163b6110795760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161108a565b61108a838361128c565b949350505050565b5f836001600160a01b031663b16a19de6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110f39190611bbb565b90506111cb6111227f8e6d782dd232ba18cda332ab87226668a41414f4096db2b33575872cd6fca16a866112b6565b8660405180604001604052808781526020018681525060405180604001604052806012815260200171185d1bdad95b91195c1bdcda5d131a5b5a5d60721b815250856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561119f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111c39190611c45565b60ff166112fa565b610f026111f87f519fa96e0bcf84b705fc396cd38f7f5e661413cb0fe321a78e8a29091b5bf262866112b6565b866112246040805180820182525f808252602091820181905282518084019093525f1983529082015290565b60405180604001604052806013815260200172185d1bdad95b95da5d1a191c985dd31a5b5a5d606a1b815250856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561119f573d5f803e3d5ffd5b81511561129c5781518083602001fd5b8060405162461bcd60e51b81526004016110709190611c65565b5f82826040516020016112dc9291909182526001600160a01b0316602082015260400190565b60405160208183030381529060405280519060200120905092915050565b825160010161132d57602083015115611328578160405163f6d4892760e01b81526004016110709190611c65565b6113e5565b5f61133982600a611d57565b6113489064e8d4a51000611ae7565b90505f61135683600a611d57565b905081855f015111806113695750845181115b156113895783604051631ba7ee4d60e01b81526004016110709190611c65565b6020850151158015906113c257506113a3610e1083611bdd565b856020015111806113c257506113bb610e1082611bdd565b8560200151105b156113e2578360405163a1ac05b360e01b81526004016110709190611c65565b50505b82516020840151604051631a191fdd60e11b815260048101889052602481019290925260448201526001600160a01b038516906334323fba906064015f604051808303815f87803b158015611438575f80fd5b505af11580156108b5573d5f803e3d5ffd5b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a0818101519083015260c090810151910152565b602080825282518282018190525f9190848201906040850190845b818110156114d5576114c283855161144a565b9284019260e092909201916001016114af565b50909695505050505050565b602080825282518282018190525f9190848201906040850190845b818110156114d55761150f83855161144a565b9284019260e092909201916001016114fc565b602080825282518282018190525f919060409081850190868401855b8281101561157657815180516001600160a01b031685528681015187860152850151858501526060909301929085019060010161153e565b5091979650505050505050565b602080825282518282018190525f919060409081850190868401855b8281101561157657815180516001600160a01b039081168652908701511686850152928401929085019060010161159f565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e08301526101008082015181840152505050565b80516001600160a01b031682525f6103406020830151816020860152611681828601826115d1565b915050604083015161169e60408601826001600160a01b03169052565b5060608301516116b160608601826115ff565b5060808301516101808581019190915260a08401516101a08087019190915260c08501516101c08088019190915260e08601516101e080890191909152610100870151610200808a0191909152610120880151610220808b01919091526101408901516102408b01526101608901516102608b0152948801516102808a0152928701516102a0890152908601516102c08801528501516102e087015284015161030086015283015160ff8116610320860152509392505050565b5f8282518085526020808601955060208260051b840101602086015f5b848110156117b657601f198684030189526117a4838351611659565b98840198925090830190600101611788565b5090979650505050505050565b602081525f61096d602083018461176b565b602080825282518282018190525f9190848201906040850190845b818110156114d557835180516001600160a01b03168452850151611816868501826115ff565b509284019261014092909201916001016117f0565b5f82825180855260208086019550808260051b8401018186015f5b848110156117b657601f1986840301895281516080815181865261186c82870182611659565b9287015180516001600160a01b03908116888a01528189015181166040808a019190915290910151166060909601959095525098840198925090830190600101611846565b602081525f61096d602083018461182b565b5f8151604084526118d760408501826115d1565b9050602083015184820360208601526118f082826115d1565b95945050505050565b602081525f61096d60208301846118c3565b604081525f61191d60408301856118c3565b82810360208401526118f0818561176b565b604081525f61194160408301856118c3565b82810360208401526118f0818561182b565b634e487b7160e01b5f52603260045260245ffd5b5f815180845260208085019450602084015f5b838110156119965781518752958201959082019060010161197a565b509495945050505050565b5f8282518085526020808601955060208260051b840101602086015f5b848110156117b657601f198684030189526119da8383516115d1565b988401989250908301906001016119be565b5f815180845260208085019450602084015f5b838110156119965781511515875295820195908201906001016119ff565b60a080825286519082018190525f9060209060c0840190828a01845b82811015611a5e5781516001600160a01b031684529284019290840190600101611a39565b5050508381036020850152611a738189611967565b9150508281036040840152611a8881876119a1565b90508281036060840152611a9c81866119a1565b90508281036080840152611ab081856119ec565b98975050505050505050565b5f60208284031215611acc575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761097057610970611ad3565b8082018082111561097057610970611ad3565b5f61010060018060a01b03808c1684528a602085015289604085015280891660608501528088166080850152508560a08401528460c08401528060e0840152611b5c818401856115d1565b9b9a5050505050505050505050565b6001600160a01b03841681526060602082018190525f90611b8e908301856115d1565b905063ffffffff83166040830152949350505050565b6001600160a01b0381168114611bb8575f80fd5b50565b5f60208284031215611bcb575f80fd5b8151611bd681611ba4565b9392505050565b5f82611bf757634e487b7160e01b5f52601260045260245ffd5b500490565b6001600160a01b03841681526060602082018190525f90611c1f908301856115d1565b9050826040830152949350505050565b5f82518060208501845e5f920191825250919050565b5f60208284031215611c55575f80fd5b815160ff81168114611bd6575f80fd5b602081525f61096d60208301846115d1565b600181815b80851115611cb157815f1904821115611c9757611c97611ad3565b80851615611ca457918102915b93841c9390800290611c7c565b509250929050565b5f82611cc757506001610970565b81611cd357505f610970565b8160018114611ce95760028114611cf357611d0f565b6001915050610970565b60ff841115611d0457611d04611ad3565b50506001821b610970565b5060208310610133831016604e8410600b8410161715611d32575081810a610970565b611d3c8383611c77565b805f1904821115611d4f57611d4f611ad3565b029392505050565b5f61096d8383611cb956fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220da16b171d52d88f9a8348bcf20f68d4a39bafbb1479f9549f3c4dc54a8686f8b64736f6c63430008190033
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106100cb575f3560e01c806395a93cb111610088578063c0a2558011610063578063c0a25580146101ce578063d0c38c27146101dd578063fabe3463146101ec578063fbb256f6146101fb575f80fd5b806395a93cb114610189578063b14e012714610198578063b1af0d0d146101bf575f80fd5b80630a4aa3fa146100cf5780631850edd8146101135780632b179434146101225780634c8031251461013157806361461954146101585780636256d8ad14610162575b5f80fd5b6100f67f0000000000000000000000003254f7cd0565aa67eedc86c2fb608be48d5ccd7881565b6040516001600160a01b0390911681526020015b60405180910390f35b606060405161010a9190611494565b606060405161010a91906114e1565b6100f67f000000000000000000000000000000000000000000000000000000000000000081565b610160610210565b005b6100f67f000000000000000000000000000000000000000000000000000000000000000081565b606060405161010a9190611522565b6100f67f000000000000000000000000000000000000000000000000000000000000000081565b606060405161010a9190611583565b606060405161010a91906117c3565b606060405161010a91906117d5565b606060405161010a91906118b1565b6102036103b6565b60405161010a91906118f9565b610218610415565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316156102ad576102ad734dbd4fc535ac27206064b68ffcf827b0a60bab3f73212871a1c235892f86cab30e937e18c94aed847461029d7f00000000000000000000000000000000000000000000000000000000000000006105b5565b620f4240640ba43b7400486107a9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161561033b5761033b73866e82a600a1414e583f7f13623f1ac5d58b0afa73fda082e00ef89185d9db7e5dcd8c5505070f5a3b6103327f00000000000000000000000000000000000000000000000000000000000000006105b5565b620f42406108c0565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316156103b4576103b473c4218c1127cb24a0d6c1e7d25dc34e10f2625f5a6103ab7f00000000000000000000000000000000000000000000000000000000000000006105b5565b620f4240610923565b565b60408051808201909152606080825260208201525060408051608081018252600881830190815267457468657265756d60c01b606083015281528151808301909252600382526208ae8d60eb1b60208381019190915281019190915290565b60608051819081908190819081908190156104b3576104b1633cb6502d60e01b61043d6103b6565b8960405160240161044f92919061190b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526001600160a01b037f0000000000000000000000003254f7cd0565aa67eedc86c2fb608be48d5ccd781690610948565b505b8551156104e1576104df6314d8093760e21b6104cd6103b6565b8860405160240161044f92919061192f565b505b825115610508576040516105069063bb06653560e01b9061044f908690602401611494565b505b83511561052f5760405161052d90636e17618760e11b9061044f9087906024016114e1565b505b80511561055657604051610554906324f4c44560e01b9061044f9084906024016117d5565b505b81511561057d5760405161057b9063927c400360e01b9061044f908590602401611583565b505b8451156105a4576040516105a2906355caa16360e01b9061044f908890602401611522565b505b6105ac610976565b50505050505050565b6040805160018082528183019092526060915f91906020808301908036833750506040805160018082528183019092529293505f9291506020808301908036833750506040805160018082528183019092529293505f929150602082015b60608152602001906001900390816106135750506040805160018082528183019092529192505f9190602082015b60608152602001906001900390816106415750506040805160018082528183019092529192505f91906020808301908036833701905050905086855f8151811061068d5761068d611953565b60200260200101906001600160a01b031690816001600160a01b0316815250505f845f815181106106c0576106c0611953565b6020026020010181815250506040518060400160405280600981526020016865786563757465282960b81b815250835f8151811061070057610700611953565b602002602001018190525060405180602001604052805f815250825f8151811061072c5761072c611953565b60200260200101819052506001815f8151811061074b5761074b611953565b911515602092830291909101909101526040516107749086908690869086908690602401611a1d565b60408051601f198184030181529190526020810180516001600160e01b031663d9a4cbdf60e01b179052979650505050505050565b835160405163a66b327d60e01b81525f916001600160a01b0389169163a66b327d916107e2918690600401918252602082015260400190565b602060405180830381865afa1580156107fd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108219190611abc565b90505f61082e8486611ae7565b90506001600160a01b03881663679b6ded6108498385611afe565b895f865f808c8c8f6040518a63ffffffff1660e01b8152600401610874989796959493929190611b11565b60206040518083038185885af1158015610890573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906108b59190611abc565b505050505050505050565b604051633dbb202b60e01b81526001600160a01b03851690633dbb202b906108f090869086908690600401611b6b565b5f604051808303815f87803b158015610907575f80fd5b505af1158015610919573d5f803e3d5ffd5b5050505050505050565b610943734c36d2919e407f0cc2ee3c993ccf8ac26d9ce64e848484610f09565b505050565b606061096d8383604051806060016040528060278152602001611d6360279139610f79565b90505b92915050565b7f0000000000000000000000003254f7cd0565aa67eedc86c2fb608be48d5ccd786001600160a01b031663587250846040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109f69190611bbb565b604051631d2118f960e01b8152736b175474e89094c44da98b954eedeac495271d0f6004820152737729e1ce24d7c4a82e76b4a2c118e328c35e656660248201526001600160a01b039190911690631d2118f9906044015f604051808303815f87803b158015610a64575f80fd5b505af1158015610a76573d5f803e3d5ffd5b505050507f0000000000000000000000003254f7cd0565aa67eedc86c2fb608be48d5ccd786001600160a01b031663587250846040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ad6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610afa9190611bbb565b604051631d2118f960e01b815273dc035d45d973e3ec169d2276ddab16f1e407384f6004820152737729e1ce24d7c4a82e76b4a2c118e328c35e656660248201526001600160a01b039190911690631d2118f9906044015f604051808303815f87803b158015610b68575f80fd5b505af1158015610b7a573d5f803e3d5ffd5b505050507f0000000000000000000000003254f7cd0565aa67eedc86c2fb608be48d5ccd786001600160a01b031663587250846040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bda573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bfe9190611bbb565b604051631d2118f960e01b815273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486004820152737f2fc6a7e3b3c658a84999b26ad2013c4dc8706160248201526001600160a01b039190911690631d2118f9906044015f604051808303815f87803b158015610c6c575f80fd5b505af1158015610c7e573d5f803e3d5ffd5b505050507f0000000000000000000000003254f7cd0565aa67eedc86c2fb608be48d5ccd786001600160a01b031663587250846040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cde573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d029190611bbb565b604051631d2118f960e01b815273dac17f958d2ee523a2206206994597c13d831ec76004820152737f2fc6a7e3b3c658a84999b26ad2013c4dc8706160248201526001600160a01b039190911690631d2118f9906044015f604051808303815f87803b158015610d70575f80fd5b505af1158015610d82573d5f803e3d5ffd5b50505050610dbf73e7df13b8e3d6740fe17cbe928c7334243d86c92f655af3107a400062015180652d79883d2000610dba9190611bdd565b610fed565b610df17323878914efe38d27c4d67ab83ed1b93a74d4086a652d79883d2000610dba620151806516bcc41e9000611bdd565b60405163b28c909f60e01b815273dac17f958d2ee523a2206206994597c13d831ec76004820152631dcd650060248201526305f5e100604482015261a8c06064820152732276f52afba7cf2525fd0a050df464ac8532d0ef90819063b28c909f906084015f604051808303815f87803b158015610e6c575f80fd5b505af1158015610e7e573d5f803e3d5ffd5b50506040516328e7733d60e01b815273dac17f958d2ee523a2206206994597c13d831ec76004820152631ad2748060248201526302faf080604482015261a8c060648201526001600160a01b03841692506328e7733d91506084015f604051808303815f87803b158015610ef0575f80fd5b505af1158015610f02573d5f803e3d5ffd5b5050505050565b60405163dc8601b360e01b81526001600160a01b0385169063dc8601b390610f3990869086908690600401611bfc565b6020604051808303815f875af1158015610f55573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f029190611abc565b60605f80856001600160a01b031685604051610f959190611c2f565b5f60405180830381855af49150503d805f8114610fcd576040519150601f19603f3d011682016040523d82523d5f602084013e610fd2565b606091505b5091509150610fe38683838761100d565b9695505050505050565b610943737a5fd5cf045e010e62147f065ceae59e5344b188848484611092565b606083156110805782515f03611079576001600160a01b0385163b6110795760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161108a565b61108a838361128c565b949350505050565b5f836001600160a01b031663b16a19de6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110f39190611bbb565b90506111cb6111227f8e6d782dd232ba18cda332ab87226668a41414f4096db2b33575872cd6fca16a866112b6565b8660405180604001604052808781526020018681525060405180604001604052806012815260200171185d1bdad95b91195c1bdcda5d131a5b5a5d60721b815250856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561119f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111c39190611c45565b60ff166112fa565b610f026111f87f519fa96e0bcf84b705fc396cd38f7f5e661413cb0fe321a78e8a29091b5bf262866112b6565b866112246040805180820182525f808252602091820181905282518084019093525f1983529082015290565b60405180604001604052806013815260200172185d1bdad95b95da5d1a191c985dd31a5b5a5d606a1b815250856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561119f573d5f803e3d5ffd5b81511561129c5781518083602001fd5b8060405162461bcd60e51b81526004016110709190611c65565b5f82826040516020016112dc9291909182526001600160a01b0316602082015260400190565b60405160208183030381529060405280519060200120905092915050565b825160010161132d57602083015115611328578160405163f6d4892760e01b81526004016110709190611c65565b6113e5565b5f61133982600a611d57565b6113489064e8d4a51000611ae7565b90505f61135683600a611d57565b905081855f015111806113695750845181115b156113895783604051631ba7ee4d60e01b81526004016110709190611c65565b6020850151158015906113c257506113a3610e1083611bdd565b856020015111806113c257506113bb610e1082611bdd565b8560200151105b156113e2578360405163a1ac05b360e01b81526004016110709190611c65565b50505b82516020840151604051631a191fdd60e11b815260048101889052602481019290925260448201526001600160a01b038516906334323fba906064015f604051808303815f87803b158015611438575f80fd5b505af11580156108b5573d5f803e3d5ffd5b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a0818101519083015260c090810151910152565b602080825282518282018190525f9190848201906040850190845b818110156114d5576114c283855161144a565b9284019260e092909201916001016114af565b50909695505050505050565b602080825282518282018190525f9190848201906040850190845b818110156114d55761150f83855161144a565b9284019260e092909201916001016114fc565b602080825282518282018190525f919060409081850190868401855b8281101561157657815180516001600160a01b031685528681015187860152850151858501526060909301929085019060010161153e565b5091979650505050505050565b602080825282518282018190525f919060409081850190868401855b8281101561157657815180516001600160a01b039081168652908701511686850152928401929085019060010161159f565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e08301526101008082015181840152505050565b80516001600160a01b031682525f6103406020830151816020860152611681828601826115d1565b915050604083015161169e60408601826001600160a01b03169052565b5060608301516116b160608601826115ff565b5060808301516101808581019190915260a08401516101a08087019190915260c08501516101c08088019190915260e08601516101e080890191909152610100870151610200808a0191909152610120880151610220808b01919091526101408901516102408b01526101608901516102608b0152948801516102808a0152928701516102a0890152908601516102c08801528501516102e087015284015161030086015283015160ff8116610320860152509392505050565b5f8282518085526020808601955060208260051b840101602086015f5b848110156117b657601f198684030189526117a4838351611659565b98840198925090830190600101611788565b5090979650505050505050565b602081525f61096d602083018461176b565b602080825282518282018190525f9190848201906040850190845b818110156114d557835180516001600160a01b03168452850151611816868501826115ff565b509284019261014092909201916001016117f0565b5f82825180855260208086019550808260051b8401018186015f5b848110156117b657601f1986840301895281516080815181865261186c82870182611659565b9287015180516001600160a01b03908116888a01528189015181166040808a019190915290910151166060909601959095525098840198925090830190600101611846565b602081525f61096d602083018461182b565b5f8151604084526118d760408501826115d1565b9050602083015184820360208601526118f082826115d1565b95945050505050565b602081525f61096d60208301846118c3565b604081525f61191d60408301856118c3565b82810360208401526118f0818561176b565b604081525f61194160408301856118c3565b82810360208401526118f0818561182b565b634e487b7160e01b5f52603260045260245ffd5b5f815180845260208085019450602084015f5b838110156119965781518752958201959082019060010161197a565b509495945050505050565b5f8282518085526020808601955060208260051b840101602086015f5b848110156117b657601f198684030189526119da8383516115d1565b988401989250908301906001016119be565b5f815180845260208085019450602084015f5b838110156119965781511515875295820195908201906001016119ff565b60a080825286519082018190525f9060209060c0840190828a01845b82811015611a5e5781516001600160a01b031684529284019290840190600101611a39565b5050508381036020850152611a738189611967565b9150508281036040840152611a8881876119a1565b90508281036060840152611a9c81866119a1565b90508281036080840152611ab081856119ec565b98975050505050505050565b5f60208284031215611acc575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761097057610970611ad3565b8082018082111561097057610970611ad3565b5f61010060018060a01b03808c1684528a602085015289604085015280891660608501528088166080850152508560a08401528460c08401528060e0840152611b5c818401856115d1565b9b9a5050505050505050505050565b6001600160a01b03841681526060602082018190525f90611b8e908301856115d1565b905063ffffffff83166040830152949350505050565b6001600160a01b0381168114611bb8575f80fd5b50565b5f60208284031215611bcb575f80fd5b8151611bd681611ba4565b9392505050565b5f82611bf757634e487b7160e01b5f52601260045260245ffd5b500490565b6001600160a01b03841681526060602082018190525f90611c1f908301856115d1565b9050826040830152949350505050565b5f82518060208501845e5f920191825250919050565b5f60208284031215611c55575f80fd5b815160ff81168114611bd6575f80fd5b602081525f61096d60208301846115d1565b600181815b80851115611cb157815f1904821115611c9757611c97611ad3565b80851615611ca457918102915b93841c9390800290611c7c565b509250929050565b5f82611cc757506001610970565b81611cd357505f610970565b8160018114611ce95760028114611cf357611d0f565b6001915050610970565b60ff841115611d0457611d04611ad3565b50506001821b610970565b5060208310610133831016604e8410600b8410161715611d32575081810a610970565b611d3c8383611c77565b805f1904821115611d4f57611d4f611ad3565b029392505050565b5f61096d8383611cb956fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220da16b171d52d88f9a8348bcf20f68d4a39bafbb1479f9549f3c4dc54a8686f8b64736f6c63430008190033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.