Contracts
The goal of getContracts
is to return all the contracts defined by a protocol. For instance:
- staking contracts
- governance contracts
- lending / borrowing pools
- DEX pairs
- ...
info
For performance reasons (ex: fetching 1 million pools), getContracts
is called on a regular basis by a background task, but not when updating someone's balances.
Lending Pool
The lending pool contract is used to get lending/borrowing assets:
- aTokens
- stable debt tokens
- variable debt tokens
On Ethereum mainnet, the lending pool contract is deployed at 0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9
.
To get reserves info, let's iterate on all reserve contracts (using getReservesList
) and call getReserveData
.
Get ABI from Etherscan
/src/adapters/aave-v2/ethereum.ts
const abi = {
getReservesList: {
inputs: [],
name: "getReservesList",
outputs: [{ internalType: "address[]", name: "", type: "address[]" }],
stateMutability: "view",
type: "function",
},
getReserveData: {
inputs: [{ internalType: "address", name: "asset", type: "address" }],
name: "getReserveData",
outputs: [
{
components: [
{
components: [
{ internalType: "uint256", name: "data", type: "uint256" },
],
internalType: "struct DataTypes.ReserveConfigurationMap",
name: "configuration",
type: "tuple",
},
{
internalType: "uint128",
name: "liquidityIndex",
type: "uint128",
},
{
internalType: "uint128",
name: "variableBorrowIndex",
type: "uint128",
},
{
internalType: "uint128",
name: "currentLiquidityRate",
type: "uint128",
},
{
internalType: "uint128",
name: "currentVariableBorrowRate",
type: "uint128",
},
{
internalType: "uint128",
name: "currentStableBorrowRate",
type: "uint128",
},
{
internalType: "uint40",
name: "lastUpdateTimestamp",
type: "uint40",
},
{
internalType: "address",
name: "aTokenAddress",
type: "address",
},
{
internalType: "address",
name: "stableDebtTokenAddress",
type: "address",
},
{
internalType: "address",
name: "variableDebtTokenAddress",
type: "address",
},
{
internalType: "address",
name: "interestRateStrategyAddress",
type: "address",
},
{ internalType: "uint8", name: "id", type: "uint8" },
],
internalType: "struct DataTypes.ReserveData",
name: "",
type: "tuple",
},
],
stateMutability: "view",
type: "function",
},
} as const;
Create a function to fetch contracts:
- address: address of the contract the user "interacted" with, either by making a transaction to it or by receiving it. In this example, the user receives aTokens when lending / borrowing on the platform.
- underlyings: actual underlying token. aDAI -> DAI
- category: 'lending' for aTokens, 'borrow' for debt tokens
async function getLendingPoolContracts(ctx: BaseContext, lendingPool: Contract) {
const contracts: Contract[] = []
const reservesList = await call({
ctx,
target: lendingPool.address,
abi: abi.getReservesList,
})
const reservesDataRes = await multicall({
ctx,
calls: reservesList.map(
(reserveTokenAddress) => ({ target: lendingPool.address, params: [reserveTokenAddress] } as const),
),
abi: abi.getReserveData,
})
for (let i = 0; i < reservesDataRes.length; i++) {
const reserveDataRes = reservesDataRes[i]
if (!reserveDataRes.success) {
continue
}
const underlyingToken = reserveDataRes.input.params[0]
const aToken = reserveDataRes.output.aTokenAddress
const stableDebtToken = reserveDataRes.output.stableDebtTokenAddress
const variableDebtToken = reserveDataRes.output.variableDebtTokenAddress
contracts.push(
{
chain: ctx.chain,
address: aToken,
underlyings: [underlyingToken],
category: 'lend',
},
{
chain: ctx.chain,
address: stableDebtToken,
underlyings: [underlyingToken],
category: 'borrow',
stable: true,
},
{
chain: ctx.chain,
address: variableDebtToken,
underlyings: [underlyingToken],
category: 'borrow',
stable: false,
},
)
}
return contracts
}
Return contracts in getContracts
:
/src/adapters/aave-v2/ethereum.ts
const lendingPool: Contract = {
name: "Lending Pool",
address: "0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9",
chain: "ethereum",
};
export const getContracts = async (ctx: BaseContext) => {
const pools = await getLendingPoolContracts(ctx, lendingPool);
return {
contracts: {
pools,
},
};
};