Developers

Hamburger

What is Aave

Aave is a decentralized non-custodial money market protocol where users can participate as depositors or borrowers. Depositors provide liquidity to the market to earn a passive income, while borrowers are able to borrow in an overcollateralized (perpetually) or undercollateralized (one-block liquidity) fashion.

The following documentation describes the fundamentals of the protocol and how to interact with it. Please join the #development room in the Aave community Discord server; our team and members of the community look forward to help you building an application on top of Aave. Your questions help us improve, so please don't hesitate to ask if you can't find what you are looking for here.



How it works

The protocol is implemented as a set of smart contracts on top of the Ethereum blockchain. Smart contracts guarantee safety, and avoid the need of a middleman.

The Aave protocol is developed with security as reference: the protocol has been audited by multiple auditors. Please find more details about the security of the Aave protocol in the Audits section.



Smart Contracts

The LendingPoolAddressesProvider

The smart contracts in the Aave protocol are upgradeable through governance. The protocol keeps a global register of addresses that holds all the addresses of the components deployed on the particular network. Therefore, whenever it's required to access the LendingPool contract (description below), it is recommended to fetch the correct address from the LendingPoolAddressesProvider smart contract.

Retrieve contract instances

The following table sums up all the addresses of the protocol, grouped by network.

Contracts ABI Atoken Address Underlying Asset Address
LendingPoolAddressesProvider JSON 0x24a42fD28C976A61Df5D00D0599C34c4f90748c8 N/A
LendingPool JSON 0x398eC7346DcD622eDc5ae82352F02bE94C62d119 N/A
LendingPoolCore JSON 0x3dfd23A6c5E8BbcFc9581d2E864a68feb6a076d3 N/A
aETH JSON 0x3a3a65aab0dd2a17e3f1947ba16138cd37d08c04 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
aDAI JSON 0xfC1E690f61EFd961294b3e1Ce3313fBD8aa4f85d 0x6b175474e89094c44da98b954eedeac495271d0f
aUSDC JSON 0x9ba00d6856a4edf4665bca2c2309936572473b7e 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
aSUSD JSON 0x625ae63000f46200499120b906716420bd059240 0x57ab1e02fee23774580c119740129eac7081e9d3
aTUSD JSON 0x4da9b813057d04baef4e5800e36083717b4a0341 0x0000000000085d4780B73119b644AE5ecd22b376
aUSDT JSON 0x71fc860F7D3A592A4a98740e39dB31d25db65ae8 0xdac17f958d2ee523a2206206994597c13d831ec7
aBAT JSON 0xe1ba0fb44ccb0d11b80f92f4f8ed94ca3ff51d00 0x0d8775f648430679a709e98d2b0cb6250d2887ef
aKNC JSON 0x9d91be44c06d373a8a226e1f3b146956083803eb 0xdd974d5c2e2928dea5f71b9825b8b646686bd200
aLEND JSON 0x7D2D3688Df45Ce7C552E19c27e007673da9204B8 0x80fB784B7eD66730e8b1DBd9820aFD29931aab03
aLINK JSON 0xA64BD6C70Cb9051F6A9ba1F163Fdc07E0DfB5F84 0x514910771af9ca656af840dff83e8264ecf986ca
aMANA JSON 0x6FCE4A401B6B80ACe52baAefE4421Bd188e76F6f 0x0f5d2fb29fb7d3cfee444a200298f468908cc942
aMKR JSON 0x7deb5e830be29f91e298ba5ff1356bb7f8146998 0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2
aREP JSON 0x71010a9d003445ac60c4e6a7017c1e89a477b438 0x1985365e9f78359a9B6AD760e32412f4a445E862
aSNX JSON 0x328c4c80bc7aca0834db37e6600a6c49e12da4de 0xc011a72400e58ecd99ee497cf89e3775d4bd732f
aWBTC JSON 0xfc4b8ed459e00e5400be803a9bb3954234fd50e3 0x2260fac5e5542a773aa44fbcfedf7c193bc2c599
aZRX JSON 0x6Fb0855c404E09c47C3fBCA25f08d4E41f9F062f 0xe41d2489571d322189246dafa5ebde1f4699f498
Contracts ABI Address Underlying Asset Address
LendingPoolAddressesProvider JSON 0x1c8756FD2B28e9426CDBDcC7E3c4d64fa9A54728 N/A
LendingPool JSON 0x9E5C7835E4b13368fd628196C4f1c6cEc89673Fa N/A
LendingPoolCore JSON 0x4295Ee704716950A4dE7438086d6f0FBC0BA9472 N/A
aETH JSON 0x2433A1b6FcF156956599280C3Eb1863247CFE675 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
aDAI JSON 0xcB1Fe6F440c49E9290c3eb7f158534c2dC374201 0xf80A32A835F79D7787E8a8ee5721D0fEaFd78108
aUSDC JSON 0x2dB6a31f973Ec26F5e17895f0741BB5965d5Ae15 0x851dEf71f0e6A903375C1e536Bd9ff1684BAD802
aSUSD JSON 0x5D17e0ea2d886F865E40176D71dbc0b59a54d8c1 0xc374eB17f665914c714Ac4cdC8AF3a3474228cc5
aTUSD JSON 0x82F01c5694f36690a985F01dC0aD46e1B20E7a1a 0xa51EE1845C13Cb03FcA998304b00EcC407fc1F92
aUSDT JSON 0x790744bC4257B4a0519a3C5649Ac1d16DDaFAE0D 0xB404c51BBC10dcBE948077F18a4B8E553D160084
aBAT JSON 0x0D0Ff1C81F2Fbc8cbafA8Df4bF668f5ba963Dab4 0x85B24b3517E3aC7bf72a14516160541A60cFF19d
aKNC JSON 0xcf6efd4528d27df440fdd585a116d3c1fc5addee 0xCe4aA1dE3091033Ba74FA2Ad951f6adc5E5cF361
aLEND JSON 0x383261d0e287f0A641322AEB15E3da50147Dd36b 0x217b896620AfF6518B9862160606695607A63442
aLINK JSON 0x52fd99c15e6FFf8D4CF1B83b2263a501FDd78973 0x1a906E71FF9e28d8E01460639EB8CF0a6f0e2486
aMANA JSON 0x8e96a4068da80F66ef1CFc7987f0F834c26106fa 0x78b1F763857C8645E46eAdD9540882905ff32Db7
aMKR JSON 0xEd6A5d671f7c55aa029cbAEa2e5E9A18E9d6a1CE 0x78b1F763857C8645E46eAdD9540882905ff32Db7
aREP JSON 0xE4B92BcDB2f972e1ccc069D4dB33d5f6363738dE 0xBeb13523503d35F9b3708ca577CdCCAdbFB236bD
aWBTC JSON 0xA1c4dB01F8344eCb11219714706C82f0c0c64841 0xa0E54Ab6AA5f0bf1D62EC3526436F3c05b3348A0
aZRX JSON 0x5BDC773c9D3515a5e3Dd415428F92a90E8e63Ae4 0x02d7055704EfF050323A2E5ee4ba05DB2A588959
Contracts ABI Address Underlying Asset Address
LendingPoolAddressesProvider JSON 0x506B0B2CF20FAA8f38a4E2B524EE43e1f4458Cc5 N/A
LendingPool JSON 0x580D4Fdc4BF8f9b5ae2fb9225D584fED4AD5375c N/A
LendingPoolCore JSON 0x95D1189Ed88B380E319dF73fF00E479fcc4CFa45 N/A
aETH JSON 0xD483B49F2d55D2c53D32bE6efF735cB001880F79 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
aDAI JSON 0x58AD4cB396411B691A9AAb6F74545b2C5217FE6a 0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD
aUSDC JSON 0x02F626c6ccb6D2ebC071c068DC1f02Bf5693416a 0xe22da380ee6B445bb8273C81944ADEB6E8450422
aSUSD JSON 0xb9c1434ab6d5811d1d0e92e8266a37ae8328e901 0xD868790F57B39C9B2B51b12de046975f986675f9
aTUSD JSON 0xA79383e0d2925527ba5Ec1c1bcaA13c28EE00314 0x1c4a937d171752e1313D70fb16Ae2ea02f86303e
aUSDT JSON 0xA01bA9fB493b851F4Ac5093A324CB081A909C34B 0x13512979ADE267AB5100878E2e0f485B568328a4
aBAT JSON 0x5ad67de6Fb697e92a7dE99d991F7CdB77EdF5F74 0x2d12186Fbb9f9a8C28B3FfdD4c42920f8539D738
aKNC JSON 0xB08EC9EdB6BD7971220FEa04644174f3EbfbDe96 0x3F80c39c0b96A0945f9F0E9f55d8A8891c5671A8
aLEND JSON 0xa2facD0F9Ef0Bb75cFc64Ad692F79378b5C3673a 0x1BCe8A0757B7315b74bA1C7A731197295ca4747a
aLINK JSON 0xEC23855Ff01012E1823807CE19a790CeBc4A64dA 0xAD5ce863aE3E4E9394Ab43d4ba0D80f419F61789
aMANA JSON 0xe68204D69Cbfaf6124190EFa65ad9C591C0D48e4 0x738Dc6380157429e957d223e6333Dc385c85Fec7
aMKR JSON 0xfB762B5BAb463f7F35610Ba65e2534993a1c09C6 0x61e4CAE3DA7FD189e52a4879C7B8067D7C2Cc0FA
aREP JSON 0x0578469469Db1129271f4eb3EB9D97426506c44c 0x260071C8D61DAf730758f8BD0d6370353956AE0E
aWBTC JSON 0xCD5C52C7B30468D16771193C47eAFF43EFc47f5C 0x3b92f58feD223E2cB1bCe4c286BD97e42f2A12EA
aZRX JSON 0x0F456900c6bdFddfA27E1E4E4c84EB823a2eE13c 0xD0d76886cF8D952ca26177EB7CfDf83bad08C00C
aSNX JSON 0xb4D480f963f4F685F1D51d2B6159D126658B1dA8 0x7FDb81B0b8a010dd4FFc57C3fecbf145BA8Bd947

A description of the main contracts of the protocol follows.



LendingPoolAddressesProvider

/// Retrieve LendingPool address

LendingPoolAddressesProvider provider = LendingPoolAddressesProvider(
    /*contract_address*/
    );
LendingPool lendingPool = LendingPool(provider.getLendingPool());
// wrap our code into an async function to handle promises

async function Launcher() {

    const Web3 = require('web3')

    // plug your provider here
    const provider = require('./provider.js')['provider']

    const web3 = new Web3(provider)
    // import the provider ABI

    const LPproviderABI = require('./lendingpoolProvider.js')['LPproviderABI']
    const LPprovideradress = '0x9C6C63aA0cD4557d7aE6D9306C06C093A2e35408'

    // retriving the LendingPool address
    const contactLPprovider = new web3.eth.Contract(LPproviderABI, LPprovideradress)

    // getLendingPool() method call
    const getLPAddress = await contactLPprovider.methods.getLendingPool().call()
}
Launcher()

Global addresses register of the protocol. This contract is immutable and his address will never change. Needs to be used whenever it is needed to fetch the address of the latest implementation of the LendingPool contract.

LendingPool

The LendingPool contract is the main contract of the protocol. It exposes all the user-oriented actions that can be invoked using either Solidity or web3 libraries. Web3 code samples are excluding the imports and transactions related parts to focus on methods interactions, if you need any support feel free to join the #developers channel on our Aave community Discord server; and ask us anything.



deposit()

/**
* Deposit of 1000 DAI
*/

/// Retrieve LendingPool address
LendingPoolAddressesProvider provider = LendingPoolAddressesProvider(
    /*contract_address*/
    );
LendingPool lendingPool = LendingPool(provider.getLendingPool());

/// Input variables

address daiAddress = "0x6b175474e89094c44da98b954eedeac495271d0f";
uint256 amount = 1000 * 1e18;
uint16 referral = 0;

/// Deposit method call
lendingPool.deposit(daiAddress, amount, referral);
// Depositing 1000 DAI

// input variables
const DAIAmountinWei = web3.utils.toWei("1000", "ether").toString()
const DAIAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'
const referralCode = '0'

// adding the data field for the transaction
rawTransaction.data = await contractLendingpool.methods.deposit(
    DAIAddress,
    DAIAmountinWei,
    referralCode
    ).encodeABI()

function deposit( address _reserve, uint256 _amount, uint16 _referralCode)

Deposits a certain _amount of an asset specified by the _reserve parameter.

The caller receives a certain amount of corresponding aTokens in exchange. The amount of aTokens received depends on the corresponding aToken exchange rate.

for _referralCode input explanations, please refer to the referral program section of this documentation

Parameter Name Type Description
_reserve address address of the underlying asset
_amount uint256 amount deposited, expressed in decimals units
_referralCode uint256 Referral code for affiliation programs

ETH deposits

Our protocol doesn't use any EIP-20 wrapper such as wETH for ETH deposits, _amount parameter of deposit() method must match the value parameter of the transaction.

ETH reserve address is provided by LendingPoolAddressesProvider getEthereumAddress() method

ERC20 deposits

The _reserve parameter correponds to the ERC20 contract address of the underlying asset




setUserUseReserveAsCollateral()

/**
* Enable usage of the DAI reserve as collateral for the user
*/

/// Retrieve LendingPoolAddress

LendingPoolAddressesProvider provider = LendingPoolAddressesProvider(
    /*contract_address*/
    );
LendingPool lendingPool = LendingPool(provider.getLendingPool());

/// Input variables

address daiAddress = "0x6b175474e89094c44da98b954eedeac495271d0f";
bool useAsCollateral = true;

/// setUserUseReserveAsCollateral method call
lendingPool.setUserUseReserveAsCollateral(daiAddress, useAsCollateral);

// Enable usage of the DAI reserve as collateral for the user

// input variables
const DAIAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'
const allowBool = true

// adding the data field for the transaction
rawTransaction.data = await contractLendingpool.methods
.setUserUseReserveAsCollateral(
    DAIAddress,
    allowBool,
    ).encodeABI()

function setUserUseReserveAsCollateral(address _reserve, bool _useAsCollateral)

Using this function users can decide whether or not use a specific deposit as collateral. Users will only be able to disable deposits that are not being used as collateral yet.

Parameter Name Type Description
_reserve address address of the asset _reserve
_useAsCollateral bool if true, the asset is allowed as a collateral for borrow




borrow()

/**
* borrowing 1000 DAI
*/

/// Retrieve LendingPool address

LendingPoolAddressesProvider provider = LendingPoolAddressesProvider(
    /*contract_address*/
    );
LendingPool lendingPool = LendingPool(provider.getLendingPool());

/// Input variables

address daiAddress = "0x6b175474e89094c44da98b954eedeac495271d0f";
uint256 amount = 1000 * 1e18;
/// 1 is stable rate, 2 is variable rate
uint256 variableRate = 2;
uint256 referral = 0;

/// Borrow method call
lendingPool.borrow(daiAddress, amount, variableRate, referral);
// borrowing 1000 DAI with variable rate

//input variables

const daiAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'
const DAIAmountinWei = web3.utils.toWei("1000", "gwei")
const interestRateMode = 2
const referralCode = '0'
// adding the data field for the transaction
rawTransaction.data = await contractLendingpool.methods.borrow(
    daiAddress,
    DAIAmountinWei,
    interestRateMode,
    referralCode,
    ).encodeABI()

function borrow( address _reserve, uint256 _amount, uint256 _interestRateMode, uint16 _referralCode)

The borrow() function transfer a specific amount of the asset identified by the _reserve parameter to the msg.sender, provided that the caller has preemptively deposited enough collateral to cover the borrow.

Every borrow can be opened with a stable or variable rate mode. Borrows have infinite duration and there is no repayment schedule. In case of price fluctuations, a borrow position is liquidated if if the price of the collateral drops below a certain threshold. Please refer to the White Paper to understand how the stable rate economy works.

for _referralCode input explanations please refer to the referral program section of this documentation

NOTE:

stable terminology is replacing the deprecated fixed terminology. As the Aave contracts ecosystem is audited, fixed term remains in the code.

Parameter Name Type Description
_reserve address address of the asset _reserve
_amount uint256 amount of to borrow, expressed in decimal units
_interestRateMode uint256 Stable or Variable rates borrow mode selection. take note that variable rate int is 2, stable rate is 1.
_referralCode uint256 Referral code for affiliation programs




repay()

/// Retrieve the LendingPool address

LendingPoolAddressesProvider provider = LendingPoolAddressesProvider(
    /*contract_address*/
    );
LendingPool lendingPool = LendingPool(provider.getLendingPool());

/// Input variables

address daiAddress = "0x6b175474e89094c44da98b954eedeac495271d0f";
uint256 amount = 1000 * 1e18;
address myAddress = /*repayer_address*/;

/// Repay method call
lendingPool.repay(daiAddress, amount, myAddress);

// repay 1000 DAI

// input variables

    const daiAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'
    const DAIAmountinWei = web3.utils.toWei("1000", "ether")
    const myAddress = '[YOUR_ADDRESS]'

    // adding the data field for the transaction
    rawTransaction.data = await contractLendingpool.methods.repay(
        daiAddress,
        DAIAmountinWei,
        myAddress,
        ).encodeABI()

function repay( address _reserve, uint256 _amount, address payable _onBehalfOf)

This function allows the user to fully or partially repay a borrowed asset. The _onBehalfOf parameter can be used to repay the debt of a different user. NOTE: When the user sending the transaction is repaying his own debt, _onBehalfOf needs to be equal to msg.sender.

Parameter Name Type Description
_reserve address address of the asset _reserve
_amount uint256 amount to repay, expressed in decimal units. To repay the whole borrowed amount, the function accepts uint(-1) as value for _amount, ONLY when the repayment is not executed on behalf of a 3rd party. In case of repayments on behalf of another user, it's recommended to send an _amount slightly higher than the current borrowed amount.
_onBehalfOf address payable address to repay on behalf of. Needs to be equal to msg.sender when the caller is repaying for himself.




rebalanceFixedBorrowRate()

/// Retrieve the LendingPool address

LendingPoolAddressesProvider provider = LendingPoolAddressesProvider(
    /*contract_address*/
    );
LendingPool lendingPool = LendingPool(provider.getLendingPool());

/// Input variables

address daiAddress = "0x6b175474e89094c44da98b954eedeac495271d0f";
address rebalancedUser = /*address_to_rebalance*/;

/// rebalanceFixedBorrowRate method call
lendingPool.rebalanceFixedBorrowRate(daiAddress, rebalancedUser);

// Rebalance a DAI stable rate loan

// input variables

    const daiAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'
    const myAddress = [INPUT_YOUR_ADDRESS]

    // adding the data field for the transaction
    rawTransaction.data = await contractLendingpool.methods.rebalanceFixedBorrowRate(
        daiAddress,
        myAddress,
        ).encodeABI()

function rebalanceFixedBorrowRate(address _reserve, address _user)

This function rebalances the Stable rate of _user. If the user is not borrowing at a Stable rate or the conditions for the rebalance are not satisfied, the transaction gets reverted. Please refer to the White Paper for details on how and when an user position can be rebalanced.

Parameter Name Type Description
_reserve address address of the asset _reserve
_user address address of the user to rebalance




liquidationCall()

/// Retrieve the LendingPool address

LendingPoolAddressesProvider provider = LendingPoolAddressesProvider(
    /*contract_address*/
    );
LendingPool lendingPool = LendingPool(provider.getLendingPool());

/// Input variables

address collateralAddress = /*collateral_address*/;
address linkAddress = "0x514910771AF9Ca656af840dff83E8264EcF986CA";
address userliquidated = /*user_address_being_liquidated*/;
uint256 purchaseAmount = 12 * 1e18;
bool getATokens = true;


/// liquidationCall method call
lendingPool.liquidationCall(
    collateralAddress,
    linkAddress,
    userliquidated,
    purchaseAmount,
    getATokens
    );
//liquidation of a LINK debt position

//input variables
const collateralAddress = [COLLATERAL_ADDRESS]
const linkAdress =
"0x514910771af9ca656af840dff83e8264ecf986ca"
const userLiquidated = [USER_BEING_LIQUIDATED]
const purchaseAmount =
web3.utils.toWei("12", "ether")
const getATokens = true

/// adding the data field for the transaction

rawTransaction.data = await contractLendingpool.methods.repay(
    collateralAddress,
    linkAdress,
    userLiquidated,
    purchaseAmount,
    getATokens
    ).encodeABI()

function liquidationCall(address _collateral, address _reserve, address _user, uint256 _purchaseAmount, bool _receiveAToken)

The liquidationCall() function allows everybody to liquidate positions that present a health factor below 1. Whenever this happens, liquidators will repay part or all of the outstanding borrowed amount on behalf of the borrower, while receiving a discounted amount of collateral in return. Liquidators can decide if they want to receive an equivalent amount of collateral aTokens, or the underlying asset directly. When the liquidation happens, the health factor of the position is increased, bringing it above 1 again.

Liquidators can only close a certain amount of collateral defined by a close factor. Across all the protocol, the close factor is 0.5 (liquidators can liquidate 50% of every position at once).

Parameter Name Type Description
_collateral address address of the liquidated collateral reserve
_reserve address address of the asset reserve of the loan principal
_user address address of the user borrowing
_purchaseAmount uint256 amount of the discounted purchase
_receiveAToken bool if true, the user receives the aTokens equivalent of the purchased collateral. If false, the user receives the underlying asset directly




flashLoan()


/**
* Flash Loan of 1000 DAI
*/

/// Retrieve the LendingPool address

LendingPoolAddressesProvider provider = LendingPoolAddressesProvider(
    /*contract_address*/
    );
LendingPool lendingPool = LendingPool(provider.getLendingPool());

/// Input variables

/* the receiver is a contract that implements the IFLashLoanReceiver interface */
address receiver = /*contract_address*/;
address daiAddress = "0x6b175474e89094c44da98b954eedeac495271d0f";
uint256 amount = 1000 * 1e18;
params = ""

/// flashLoan method call
lendingPool.flashLoan(receiver, daiAddress, amount, params);

function flashLoan( address payable _receiver, address _reserve, uint _amount, bytes memory _params) external

Allows contracts to borrow in an undercollateralized fashion from the reserve specified by the parameter _reserve a certain _amount of liquidity, that must be returned within the same transaction. Please refer to the Tutorials section on how to create and implement on top of the Flash Loan functionality.

Parameter Name Type Description
_receiver address, payable address of the receiver of the borrowed assets
_reserve address address of deposit asset _reserve
_amount uint256 amount to be received
_params bytes bytes-encoded extra parameters to use inside the executeOperation() function




getReserveConfigurationData()

function getReserveConfigurationData(address _reserve)

Returns specific reserve's configuration parameters.

return name Type Description
ltv uint256 Loan-to-value. Value in percentage
liquidationThreshold uint256 liquidation threshold. Value in percentage
liquidationDiscount uint256 liquidation Bonus. Value in percentage
interestRateStrategyAddress address address of the contract defining the interest rate strategy
usageasCollateralEnabled bool if true, reserve asset can be used as collateral for borrowing
borrowingEnabled bool if true, reserve asset can be borrowed
fixedBorrowRateEnabled bool if true, reserve asset can be borrowed with stable rate mode
isActive bool if true, users can interact with reserve asset




getReserveData()

function getReserveData(address _reserve)

Returns global information on any asset reserve pool

return name Type Description
totalLiquidity uint256 reserve total liquidity
availableLiquidity uint256 reserve available liquidity for borrowing
totalBorrowsFixed uint256 total amount of outstanding borrows at Stable rate
totalBorrowsVariable uint256 total amount of outstanding borrows at Variable rate
liquidityRate uint256 current yearly interest earned by the depositors. In Ray units.
variableBorrowRate uint256 current Variable rate APR of the reserve pool
fixedBorrowRate uint256 current stable rate APR of the reserve pool
averageFixedBorrowRate uint256 current average stable borrow rate
utilizationRate uint256 Espressed as total borrows/total liquidity.
liquidityIndexRate uint256 cumulative liquidity index
variableBorrowIndex uint256 cumulative variable borrow index
aTokenAddress address aTokens contract address for the specific _reserve
lastUpdateTimestamp uint40 timestamp of the last update of reserve data




getUserAccountData()

function getUserAccountData(address _user)

Returns information of a reserve exclusively related with a particular user address

return name Type Description
totalLiquidityETH uint256 user aggregated deposits across all the reserves. In Wei
totalCollateralETH uint256 user aggregated collateral across all the reserves. In Wei
totalBorrowsETH uint256 user aggregated outstanding borrows across all the reserves. In Wei
totalFeesETH uint256 user aggregated current outstanding fees in ETH. In Wei
availableBorrowsETH uint256 user available amount to borrow in ETH
currentLiquidationThreshold uint256 user current average liquidation threshold across all the collaterals deposited
ltv uint256 user average Loan-to-Value between all the collaterals
healthFactor uint256 user current Health Factor




getUserReserveData()

function getUserReserveData(address _reserve, address _user)

Returns information related to the user data on a specific reserve

return name Type Description
currentATokenBalance uint256 user current reserve AToken balance
currentUnderlyingBalance uint256 user current reserve deposit amount
currentBorrowBalance uint256 user current reserve outstanding borrow balance
principalBorrowBalance uint256 user balance of borrowed asset
borrowRateMode uint256 user borrow rate mode either Stable or Variable
borrowRate uint256 user current borrow rate APR
liquidityRate uint256 user current earn rate on _reserve
originationFee uint256 user outstanding loan origination fee
variableBorrowIndex uint256 user variable cumulative index
lastUpdateTimestamp uint256 Timestamp of the last data update




getReserves()

function getReserves()

Returns an array of all the active reserves addresses.




aTokens

The aTokens are interest-bearing derivative tokens that are minted and burned upon deposit and redeem. The aTokens value are pegged to the value of the corresponding deposited asset at a 1:1 ratio, and can be safely stored, transferred or traded. All Interests collected by the aTokens reserves are distributed to aTokens holders directly by continiously increasing their wallet balance. Users can decide to redirect at any time their stream of interest to any ethereum public address.



redeem()

/// Instantiation of the AToken address
AToken aTokenInstance = AToken("/*aToken_address*/");

/// Input variables
uint256 amount = 1000 * 1e18;

/// redeem method call
aTokenInstance.redeem(amount)
// redeem 1000 DAI

// input variables

const aDAIToken = '0x6b175474e89094c44da98b954eedeac495271d0f'
const aDAIABI = require('./aDAIABI.js')['aDAIABI']
const contractADAI = new web3.eth.Contract(aDAIABI, aDAIToken)

const DAIAmountinWei = web3.utils.toWei("1000", "ether")
const getExchangeRate = await contractADAI.methods
.getExchangeRate().call() / 10 ** 27

const aTokenAmount = new BigNumber(DAIAmountinWei * getExchangeRate)
const strATokenAmount = aTokenAmount.toFixed(0)

rawTransaction.data = await contractADAI.methods.redeem(
strATokenAmount)
.send(rawTransaction)

function redeem(uint256 _amount)

Non-standard ERC20 function to redeem an _amount of aTokens for the underlying asset, burning the aTokens during the process. NOTE: redeem() will fail if the aTokens to be redeemed are being used as collateral. Please refer to the transferAllowed() function to understand how to check if a specific redeem/transfer action can be performed.

Parameter Name Type Description
_amount uint256 amount of ATokens to redeem




transfer()

/// Instantiation of the AToken address
AToken aTokenInstance = AToken("/*aToken_address*/");

/// Input variables
address recipient = /*transfer_recipient_address*/;
uint256 amount = 1000 * 1e18;

/// transfer method call
aTokenInstance.transfer(recipient, amount)

function transfer(address recipient, uint256 amount) public

Standard ERC20 function to transfer tokens from msg.sender to a specified recipient. NOTE: transfer() will fail if the aTokens to be redeemed are being used as collateral. Please refer to the transferAllowed() function to understand how to check if a specific redeem/transfer action can be performed.




transferFrom()

/// Instantiation of the AToken address
AToken aTokenInstance = AToken("/*aToken_address*/");

/// Input variables 
address from = /*transfer_source_address*/
address to = /*transfer_recipient_address*/;
uint256 amount = 1000 * 1e18;

/// transferFrom method call
aTokenInstance.transferFrom(from, to, amount)
// send 1000 DAI

// input variables

const aDAIToken = '0x6b175474e89094c44da98b954eedeac495271d0f'
const aDAIABI = require('./aDAIABI.js')['aDAIABI']
const contractADAI = new web3.eth.Contract(aDAIABI, aDAIToken)

const user = /*user_public_address*/
const receiver = /*receiver_public_address*/
const DAIAmountInWei = web3.utils.toWei("1000", "ether")

rawTransaction.data = await contractADAI.methods.
transferFrom(user, receiver, DAIAmountInWei)
.encodeABI(rawTransaction)

function transferFrom(address from, address to, uint256 amount) public

Standard ERC20 function to transfer tokens from an address to another. NOTE: transferFrom() will fail if the aTokens to be redeemed are being used as collateral. Please refer to the transferAllowed() function to understand how to check if a specific redeem/transfer action can be performed.




transferAllowed()

function transferAllowed(address from, uint256 amount)

Non-standard ERC20 function that allows to check beforehand if a transfer or a redeem will fail. Specifically, a transfer/redeem will fail if the resulting Health Factor of the user performing the action will end up being below 1.

return name Type Description
transferAllowed bool true if the transfer is allowed, otherwise false




function redirectInterestStream()

/// Instantiation of the AToken address
AToken aTokenInstance = AToken("/*aToken_address*/");

/// Input variables
address receiver = /*receiver_public_address*/;

/// transfer method call
aTokenInstance.redirectInterestStream(receiver)
// interest stream redirection

// input variables

const aDAIToken = '0x6b175474e89094c44da98b954eedeac495271d0f'
const aDAIABI = require('./aDAIABI.js')['aDAIABI']
const contractADAI = new web3.eth.Contract(aDAIABI, aDAIToken)

const receiver = /*receiver_public_address*/

rawTransaction.data = await contractADAI.methods.
redirectInterestStream(receiver)
.encodeABI(rawTransaction)

function redirectInterestStream(address _to)

Redirects the interest generated to a target address. When the interest is redirected, the user balance is added to the receiver balance.

Parameter Name Type Description
_to address Address of the receiver of the interest stream




function redirectInterestStreamOf()

/// Instantiation of the AToken address
AToken aTokenInstance = AToken("/*aToken_address*/");

/// Input variables
address depositor = /*depositor_public_address*/;
address receiver = /*receiver_public_address*/;

/// transfer method call
aTokenInstance.redirectInterestStreamOf(depositor, receiver)
// interest stream redirection

// input variables

const aDAIToken = '0x6b175474e89094c44da98b954eedeac495271d0f'
const aDAIABI = require('./aDAIABI.js')['aDAIABI']
const contractADAI = new web3.eth.Contract(aDAIABI, aDAIToken)

const depositor = /*depositor_public_address*/
const receiver = /*receiver_public_address*/

rawTransaction.data = await contractADAI.methods.
redirectInterestStreamOf(depositor, receiver)
.encodeABI(rawTransaction)

function redirectInterestStreamOf(address _from, address _to)

Allows a allowed third-party to redirects the interest generated by a depositor to a target address. When the interest is redirected, the depositor balance is added to the receiver balance. The caller needs to have allowance on the interest redirection to be able to execute the function.

Parameter Name Type Description
_from address Address of the depositor
_to address Address of the receiver of the interest stream




function allowInterestRedirectionTo()

/// Instantiation of the AToken address
AToken aTokenInstance = AToken("/*aToken_address*/");

/// Input variables
address receiver = /*receiver_public_address*/;

/// transfer method call
aTokenInstance.allowInterestRedirectionTo(receiver)
// Allowing interest redirection

// input variables

const aDAIToken = '0x6b175474e89094c44da98b954eedeac495271d0f'
const aDAIABI = require('./aDAIABI.js')['aDAIABI']
const contractADAI = new web3.eth.Contract(aDAIABI, aDAIToken)

const receiver = /*receiver_public_address*/

rawTransaction.data = await contractADAI.methods.
redirectInterestStreamOf(receiver)
.encodeABI(rawTransaction)

function allowInterestRedirectionTo(address _to)

Gives allowance to an address to execute the interest redirection on behalf of the caller. This method allows third parties to setup interest stream redirections on behalf of the depositors.

Parameter Name Type Description
_to address depositor Ethereum public address




balanceOf()

function balanceOf(address _user)

returns the current total aToken balance of _user all interest collected included. To obtain the user asset principal balance with interests excluded , ERC20 non-standard method principalBalanceOf() can be used.

return name Type Description
balance uint256 aToken balance of the user, in wei units.




Non-standard ERC20 aTokens view methods

ATokens contracts has a set of methods designed to help monitoring the Aave protocol activity for third-parties. Methods and their output are described in this section.

principalBalanceOf()

function principalBalanceOf(address _user)

Returns user current balance deposited to the Aave protocol reserve contract, with interest collected amount removed. To obtain the user asset total current balance with interests included, ERC20 standard method balanceOf() can be used.

return name Type Description
amount uint256 user balance, in wei units.




getInterestRedirectionAddress()

function getInterestRedirectionAddress(address _user)

Returns user current interest stream recipient address, if the user doesn't have set any receiver the method return 0x00....

return name Type Description
receiver address receiver public address.




Tutorials

The following section provides simple code examples on how to implement some specific functionalities of the protocol as well as the basic interactions.



Implementing a FlashLoanReceiver contract



pragma solidity ^0.5.0;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";

import "../tokens/MintableERC20.sol";
import "../../flashloan/base/FlashLoanReceiverBase.sol";
import "../../configuration/LendingPoolAddressesProvider.sol";
import "../../configuration/NetworkMetadataProvider.sol";

contract FlashLoanReceiverExample is FlashLoanReceiverBase {

    using SafeMath for uint256;


    constructor(LendingPoolAddressesProvider _provider)
        FlashLoanReceiverBase(_provider)
        public {}


    function executeOperation(
        address _reserve,
        uint256 _amount,
        uint256 _fee,
        memory bytes _params) external {

        //check the contract has the specified balance
        require(_amount <= getBalanceInternal(address(this), _reserve), 
            "Invalid balance for the contract");

        /**

        CUSTOM ACTION TO PERFORM WITH THE BORROWED LIQUIDITY

        */

        transferFundsBackToPoolInternal(_reserve, _amount.add(_fee));
    }
}

To interact with the Flash Loan functionality of the Aave protocol, a basic understanding of Solidity and its inheritance techniques are needed. Specifically, in order to be able to access the protocol's liquidity in an undercollateralized way, it's necessary to implement a separate smart contract inheriting from the FlashLoanReceiverBase contract which can be found here.

A basic implementation of the Flash Loan feature would need to keep into account the following conditions:

executeOperation() function can also use any bytes encoded parameters defined in the flashLoan() input params_ for more flexibility as an exemple an Ethereum public address or any extra data necessary in the context of executeOperation().

Security & Audits

Aave has been implemented with security as priority. The system has been designed to be safe and secure, and we have spent all the necessary resources in order to ensure that the protocol matches the highest security standards.

Currently, the code has already been audited by Trail of Bits And a second audit by OpenZeppelin.

This section will be updated with the corresponding audit reports once all the code verification procedures are completed. As soon as the audit process is completed, the smart contracts code will be also open sourced and a bounty campaign will start.



Audits

Trail of Bits

The first audit by Trail of Bits can be found here.




Open Zeppelin

The first audit by Open Zeppelin can be found here




Referral Program

Aave has a 20% fee-share referral program. Aave loans have a 0.25% origination fee on the loan amount. 80% of this fee is used to buy on the markets the token LEND and burn it to reduce monetary supply of the LEND token. 20% is reserved and directly redistributed to referees, in order to participate in the Referral Program, a referralCode to be used as an input of either deposit() or redeem() calls is needed.

If you wish to participate in our Referral Program, we invite you to fill our Referral program form we will provide you a referralCode in 1-2 business days.

Misc

Gas consumption

The gas consumption of the protocol depends on the specific action executed and the user. Specifically, it might be higher whenever an user executes an action for the first time, or depending on how many currencies the user has deposited/borrowed. Every currency added to the Aave protocol slightly increases the gas cost of all the operations that involve checking the account global liquidity. Gas cost of the flashLoan() function also depends on the specific flash loan implementation.

Function Typical gas cost
Deposit < 180K
Redeem < 300K
Borrow < 500K
Redeem < 150K
liquidationCall < 500K




Ray Math

For internal calculations and to reduce the impact of rounding errors, the protocol uses the concept of Ray Math. A Ray is a unit with 27 decimals of precision. All the rates (liquidity/borrow/utilization rates) as well as the cumulative indexes and the aTokens exchange rates are expressed in Ray. Please refer to the following article for further details about this concept.




Glossary

Term Description
Loan To Value Expressed in percentage, represents the maximum borrowing power expressed by a specific collateral. If a collateral has a Loan to Value of 75%, for every 1 ETH worth of collateral the user will be able to borrow 0.75 ETH worth of principal currency. The Loan To Value is specified per collateral.
Liquidation Threshold Expressed in percentage, represents the threshold at which a borrow position will be considered undercollateralized and subjected to liquidation. If a collateral has a liquidation threshold of 80%, it means that the loan will be liquidated when the collateral is worth 80% of the principal amount. The liquidation threshold is specified per collateral.
Liquidation Bonus Expressed in percentage, is the bonus acting as liquidators incentive to purchase a specific collateral. The Liquidation Bonus is specified per collateral.
Health factor Represents the ratio between total collateral multiplied by the liquidation threshold, and the borrowed principal. When the Health Factor goes below 1, the loan is undercollateralized and can be liquidated.
Stable rate A loan with a stable rate behaves like a fixed rate loan in the short term, but the rates can be rebalanced following sudden market changes in the medium/long term.

Risk parameters Matrix

Name Symbol Currency Collateral Loan To Value Liquidation Threshold Liquidation Bonus
DAI DAI yes yes 75% 80% 5%
USDC USDC yes yes 75% 80% 5%
True USD TUSD yes Yes 75% 80% 5%
Tether USDT yes No - - -
Synthetix USD SUSD yes No - - -
Synthetix SNX yes No - - -
Augur REP yes yes 35% 65% 10%
0x ZRX yes yes 60% 65% 10%
Basic Attention Token BAT yes yes 60% 65% 10%
Wrapped BTC WBTC yes yes 60% 65% 15%
Maker MKR yes yes 60% 65% 10%
Chainlink LINK yes yes 65% 70% 10%
Kyber Network KNC yes yes 60% 65% 10%
Decentraland MANA yes yes 60% 65% 10%
Ethereum ETH yes yes 75% 80% 5%
Aave LEND yes yes 40% 65% 15%