Lendle

Smart Contract Audit Report

Audit Summary

Lendle Audit Report Lendle is releasing a new decentralized lending platform where users can borrow assets after depositing collateral. Users can additionally earn rewards by staking $LEND tokens.

For this audit, we reviewed the following contracts on the Mantle Mainnet:

Audit Findings

No findings were identified, though some centralized aspects are present.
Date: September 8th, 2023.
Updated: September 25th, 2023 to reflect deployment on Mantle Mainnet.

Contracts Overview

AToken Contract:
  • aTokens are interest bearing tokens that correspond to an underlying asset. For example an lvWETH aToken would correspond to WETH.
  • aTokens are minted to the user when they deposit the underlying asset into a Lending Pool.
  • When withdrawing from the Lending Pool, the tokens are burned and the corresponding asset is returned to the user.
  • When tokens are minted, burned, or transferred, rewards are minted as Staking Tokens in a MultiFeeDistribution contract. The amount of rewards earned is dependent on the amount of tokens and the time since rewards were last earned.
  • The Lending Pool uses this contract to mint tokens as interest to the Treasury and Second Treasury addresses; 80% of the interest is sent to the Treasury and the remaining 20% is sent to the Second Treasury.
  • This contract complies with the ERC-20 standard.
  • Other than the ERC20 and EIP2612 functions, all functions that affect the state of the token can only be called by the Lending Pool.
StableDebtToken Contract:
  • StableDebtTokens are created when a user borrows from the Lending Pool.
  • As the name suggests, StableDebtTokens represent a borrowing position that has a stable interest rate.
  • Tokens are minted when the borrower takes the position, and burned when they repay their position.
  • When tokens are minted or burned, rewards are minted as Staking Tokens in a MultiFeeDistribution contract. The amount of rewards earned is dependent on the amount of tokens and the time since rewards were last earned.
  • These tokens are modeled after the ERC20 standard, but do not fully implement the standard. As debt is non-transferable, there are no transfer functions for StableDebtTokens.
  • Similar to the aToken, all non-ERC20 public functions that affect state are only able to be called by the Lending Pool.
VariableDebtToken Contract:
  • VariableDebtTokens are created when a user borrows from the Lending Pool.
  • As the name suggests, VariableDebtTokens represent a borrowing position that has a variable interest rate.
  • The variable interest rate is constantly changing based on the Utilization rate. The utilization rate is a measure of the liquidity of the corresponding asset existing in the Lending Pool.
  • Tokens are minted when the borrower takes the position, and burned when they repay their position.
  • When tokens are minted or burned, rewards are minted as Staking Tokens in a MultiFeeDistribution contract. The amount of rewards earned is dependent on the amount of tokens and the time since rewards were last earned.
  • These tokens are modeled after the ERC20 standard, but do not fully implement the standard.
  • As debt is non-transferable, there are no transfer functions for VariableDebtTokens.
  • Similar to the aToken, all non-ERC20 public functions that affect state are only able to be called by the Lending Pool.
ChefIncentivesController Contract:
  • This contract is used to provide rewards for IncentivizedERC20 token holders.
  • It is configured in the LendingPoolConfigurator contract.
  • Users are able to claim rewards which are minted in the MultiFeeDistribution contract and locked for a specified time; these earned rewards can be withdrawn before the lock time with a penalty.
  • The claimable rewards are only minted upon claiming. Since there is a mint cap, it is possible that if the user has not claimed for a while, some claimable rewards will not be able to be minted if the mint cap is reached.
  • Reward rates are variable and set by the owner on deployment. Each reward period may have a different rewards emission rate.
  • Rewards are determined based on the time elapsed, how many allocation points are given to the pool, and the user's token balance.
  • The owner can start the rewards and set the start time only once on deployment.
  • The owner can change the allocation points for the token pools at any time.
  • The owner can change the receiver of rewards for any user at any time.
  • The team must exercise caution when adding tokens to avoid fee-on-transfer and ERC777-compliant tokens.
LendleToken Contract:
  • The total supply of the token is set on deployment.
  • The minter address, which can be set only once, has the ability to mint tokens to any address as long as it does not result in the total supply exceeding the max total supply.
  • There are no burning functionalities present, however a user can send their tokens to any burn address to reduce circulating supply, if desired.
  • The contract complies with the ERC-20 token standard.
TokenVesting Contract:
  • This contract takes a list of recipients and amounts and unlocks these amounts in a MultiFeeDistribution contract over time.
  • User amounts vest linearly over the span of a custom duration specified by the owner. For example, if 10% of the duration has passed, 10% of funds will be available to claim.
  • When funds are claimed in this contract, they are minted as unlocked tokens for the user in the MultiFeeDistribution contract.
  • The owner must execute the start function in order for the vesting time to begin.
MultiFeeDistribution Contract:
  • This contract allows users to stake tokens to earn rewards in various tokens.
  • Users must deposit staking tokens with a lock in order to earn rewards in the same staking tokens. Tokens that are locked may not be withdrawn until the locked period is over. Unlocked tokens do not earn rewards in staking tokens, but will still accrue other rewards.
  • The lock duration is 13 weeks and cannot be changed.
  • Earned rewards are able to be withdrawn with a penalty before the lock duration is over.
  • Users are able to withdraw unlocked tokens and rewards at anytime.
  • The owner can disable reward claiming at any time, which will
  • The owner can set valid addresses for minters only once.
  • The owner can to add a token as a reward at anytime.
  • The owner can withdraw any non-staking and non-rewards token in the contract at any time.
  • The team must exercise caution that the Staking Token used is not fee-on-transfer.
MasterChef Contract:
  • Users can stake designated tokens in the contract to earn rewards.
  • Rewards are determined based on the time elapsed, how many allocation points are given to the pool, and how much the user has staked.
  • Reward rates are variable and set by the owner on deployment. Each reward period may have a different rewards emission rate.
  • Users are able to designate where their rewards are sent.
  • Staking tokens are minted as rewards in an external MultiFeeDistribution contract as long as they do not exceed the max total amount that can be minted.
  • Minted rewards are locked at a time set in the MultiFeeDistribution contract. They can be withdrawn before the lock time at a penalty.
  • Rewards are claimed when both depositing and withdrawing, but they are not minted until claimed. Users can call the claim function to mint any pending rewards.
  • The claimable rewards are only minted upon claiming. Since there is a mint cap, it is possible that if the user has not claimed for a while, some claimable rewards will not be able to be minted if the mint cap is reached.
  • There is also the option to emergency withdraw which will send the user all of their deposited tokens without claiming any rewards.
  • The owner can choose to start the rewards only once after the contract is deployed.
  • The owner can add a new pool to the contract at any time. The team must exercise caution when adding tokens to avoid fee-on-transfer and ERC777-compliant tokens.
  • The owner can change the allocation points for the token pools at any time.
  • The owner can change the receiver of rewards for any user at any time.
MerkleDistributor Contract:
  • The owner of this contract has the ability to create Claim Records with custom durations and amounts. A recipient is not specified.
  • The duration must be at least 1 week, and cannot be modified after the Claim Record is created.
  • Any user can redeem a Claim Record until its specified duration has passed.
  • When a user makes a claim, the amount claimed is minted and locked in the MultiFeeDistribution contract.
  • The total amount of claimable tokens cannot exceed the maximum claimable amount, which decreases over the course of a year to a base amount.
  • Claim Record data is secured and verified through the implementation of a Merkle Tree.
StakingConfigurator Contract:
  • This contract is used to maintain a list of various addresses used throughout the protocol.
  • The owner may use this contract to update the implementation of a registered Proxy address at any time.
  • The owner may update the MultiFeeDistribution, ChefIncentivesController, MasterChef, and ProtocolRevenueDistribution addresses at any time.
PythPriceFeed Contract:
  • This contract uses Pyth to determine the current price of an asset.
  • The oracle is considered to have failed to fetch an accurate price if there is a failed response, or the timeout period has passed since the last price fetch.
  • In the event that Pyth is failing to return an accurate price, the contract defaults to the last good price that the contract received.
AaveOracle Contract:
  • This contract is used to track the price of various assets determined by Sources.
  • The current asset price is determined by the price reported by the asset's Source.
  • The Owner may set the Source for any asset at any time.
LendingPoolAddressesProvider Contract:
  • This contract is used to maintain a list of various addresses used throughout the protocol.
  • The owner may use this contract to update the implementation of a registered Proxy address at any time.
  • The owner may update the address corresponding to a market ID at any time.
  • The owner may update the LendingPool, LendingPoolConfigurator, LendingPoolCollateralManager, PriceOracle, LendingRateOracle, and StakingConfigurator addresses at any time.
  • The owner may update a specified Pool's Pool Admin and Emergency Admin at any time.
LendingPoolAddressesProviderRegistry Contract:
  • This contract is used to maintain a list of LendingPoolAddressesProvider contracts.
  • The owner may register and unregister an address as an AddressProvider at any time.
LendingRateOracle Contract:
  • This contract is used to track the borrow rate and liquidity rate for various assets.
  • The owner may set the borrow rate for any asset at any time.
  • The owner may set the liquidity rate for any asset at any time.
LendingPool Contract:
  • Users are able to deposit various supported tokens into this contract.
  • Upon depositing, aTokens corresponding to the token are minted to the user. When withdrawing, these aTokens are burned.
  • Users can also deposit and withdraw on behalf of another address, if desired. This means that aTokens can be minted to a different address upon deposit, and a different address can receive withdrawn funds.
  • A user can borrow an amount of an asset from its reserve, provided that the user has deposited enough funds to be used as collateral.
  • Users must manually set their funds to be used as collateral before borrowing. The collateralized loans are then locked and cannot be withdrawn.
  • When borrowing, users either choose to use a stable or variable interest rate model, where corresponding StableDebtTokens or VariableDebtTokens will be minted to the borrower to track debt.
  • Users can swap between interest rate models at any time.
  • Funds have no deadline to be paid back, however more interest will be accrued as time passes. This can lead to a decrease in the loan's health factor, which is based on the liquidation threshold and the value of the borrowed assets.
  • If the health factor drops below a certain threshold, another user can pay a portion of the funds borrowed and receive a portion of the collateral plus an additional percentage of the collateral as a bonus.
  • The user performing the liquidation can select to receive the collateral aTokens or the actual underlying asset back.
  • The health factor can be increased by either repaying borrowed funds or by depositing futher collateral.
  • Users can specify a different address to receive debt, provided they have been given a credit delegation allowance. StableDebtTokens/VariableDebtTokens are then minted and burned to or from this different address.
  • The owner of the LendingPoolAddressProvider contract can update this contract's LendingPoolCollateralManager address at any time.
  • This contract also implements flashloan functionality, where anyone can borrow the all of the assets in any liquidity pool, as long as they are returned within the transaction. A premium of up to .09% of each pool used in the flash loan is charged as a fee.
  • When depositing, borrowing, or taking out a flashloan, users are able to specify a referral address.
  • A Price Oracle contract is used to calculate price data, and can be changed at any time by the Pool Admin of the LendingPoolAddressProvider address.
  • The Lending Pool Configurator of the LendingPoolAddressesProvider contract has the ability to add new assets at any time, as long as the number of assets does not exceed 128.
  • The owner of the LendingPoolAddressProvider contract has the ability to update the LendingPool contract implementation at any time.
WETHGateway Contract:
  • This contract allows users to wrap and unwrap the blockchain's native token to facilitate standard LendingPool functionality.
  • The blockchain's native token will be wrapped when depositing and repaying, and unwrapped when withdrawing and borrowing from LendingPools.
  • When repaying, any excess tokens will be returned to the user.
  • The owner can withdraw any tokens or ETH from this contract at any time.
LendingPoolConfigurator Contract:
  • A Pool Admin, defined in the LendingPoolAddressesProvider contract, has power to make various configuration updates to the lending pools through this contract.
  • An Emergency Admin, also defined in the LendingPoolAddressesProvider contract, has the ability to pause all transactions through this contract.
  • The Pool Admin and Emergency Admin roles can be changed at any time by the owner of the LendingPoolAddressesProvider contract.
  • A Pool Admin has the ability to make any of the following changes at any time:
    • Update the implementation of any aToken.
    • Update the implementation of the StableDebtToken or VariableDebtToken.
    • Allow or disallow any kind of borrowing on any reserve.
    • Configure the loan to value ratio of an asset used as collateral.
    • Update the bonus percentage earned when liquidating an asset.
    • Update an asset's health factor threshold to enable liquidations.
    • Activate or deactivate any reserve.
    • Freeze or unfreeze any reserve, disallowing/allowing deposits, borrows, and rate swaps.
    • Change a reserve's strategy contract used to generate interest.
    • Update the reserve factor of an asset, which is the factor of how much of an asset is stored in a separate contract as reserve.

Audit Results

Vulnerability Category Notes Result
Arbitrary Jump/Storage Write N/A PASS
Centralization of Control
  • The owner and defined roles have the permissions described above.
  • The LendingPoolConfigurator Pool Admin can add any asset to the LendingPool.
  • The LendingPoolConfigurator Pool Admin can freeze any asset in the LendingPool.
  • The AaveOracle owner can set the source for any asset.
  • The contracts in the platform are upgradable and their implementations can be swapped out at any time.
WARNING
Compiler Issues N/A PASS
Delegate Call to Untrusted Contract N/A PASS
Dependence on Predictable Variables N/A PASS
Ether/Token Theft N/A PASS
Flash Loans N/A PASS
Front Running N/A PASS
Improper Events N/A PASS
Improper Authorization Scheme N/A PASS
Integer Over/Underflow N/A PASS
Logical Issues N/A PASS
Oracle Issues N/A PASS
Outdated Compiler Version N/A PASS
Race Conditions N/A PASS
Reentrancy N/A PASS
Signature Issues N/A PASS
Sybil Attack N/A PASS
Unbounded Loops N/A PASS
Unused Code N/A PASS
Overall Contract Safety   PASS

Contract Source Summary and Visualizations

Name

Address/Source Code

Visualized
(Hover-Zoom Recommended)

AToken

Mantle Mainnet

Inheritance Chart.  Function Graph.

StableDebtToken

Mantle Mainnet

Inheritance Chart.  Function Graph.

VariableDebtToken

Mantle Mainnet

Inheritance Chart.  Function Graph.

LendleToken

Mantle Mainnet

Inheritance Chart.  Function Graph.

ChefIncentivesController

Mantle Mainnet

Inheritance Chart.  Function Graph.

TokenVesting

Mantle Mainnet

Inheritance Chart.  Function Graph.

MultiFeeDistribution

Mantle Mainnet

Inheritance Chart.  Function Graph.

MasterChef

Mantle Mainnet

Inheritance Chart.  Function Graph.

MerkleDistributor

Mantle Mainnet

Inheritance Chart.  Function Graph.

StakingConfigurator

Mantle Mainnet

Inheritance Chart.  Function Graph.

LendingPool

Mantle Mainnet

Inheritance Chart.  Function Graph.

WETHGateway

Mantle Mainnet

Inheritance Chart.  Function Graph.

LendingPoolCollateralManager

Mantle Mainnet

Inheritance Chart.  Function Graph.

LendingPoolConfigurator

Mantle Mainnet

Inheritance Chart.  Function Graph.

PythPriceFeed

Mantle Mainnet

Inheritance Chart.  Function Graph.

AaveOracle

Mantle Mainnet

Inheritance Chart.  Function Graph.

LendingPoolAddressesProvider

Mantle Mainnet

Inheritance Chart.  Function Graph.

LendingPoolAddressesProviderRegistry

Mantle Mainnet

Inheritance Chart.  Function Graph.

LendingRateOracle

Mantle Mainnet

Inheritance Chart.  Function Graph.

About SourceHat

SourceHat has quickly grown to have one of the most experienced and well-equipped smart contract auditing teams in the industry. Our team has conducted 1800+ solidity smart contract audits covering all major project types and protocols, securing a total of over $50 billion U.S. dollars in on-chain value!
Our firm is well-reputed in the community and is trusted as a top smart contract auditing company for the review of solidity code, no matter how complex. Our team of experienced solidity smart contract auditors performs audits for tokens, NFTs, crowdsales, marketplaces, gambling games, financial protocols, and more!

Contact us today to get a free quote for a smart contract audit of your project!

What is a SourceHat Audit?

Typically, a smart contract audit is a comprehensive review process designed to discover logical errors, security vulnerabilities, and optimization opportunities within code. A SourceHat Audit takes this a step further by verifying economic logic to ensure the stability of smart contracts and highlighting privileged functionality to create a report that is easy to understand for developers and community members alike.

How Do I Interpret the Findings?

Each of our Findings will be labeled with a Severity level. We always recommend the team resolve High, Medium, and Low severity findings prior to deploying the code to the mainnet. Here is a breakdown on what each Severity level means for the project:

  • High severity indicates that the issue puts a large number of users' funds at risk and has a high probability of exploitation, or the smart contract contains serious logical issues which can prevent the code from operating as intended.
  • Medium severity issues are those which place at least some users' funds at risk and has a medium to high probability of exploitation.
  • Low severity issues have a relatively minor risk association; these issues have a low probability of occurring or may have a minimal impact.
  • Informational issues pose no immediate risk, but inform the project team of opportunities for gas optimizations and following smart contract security best practices.