Vinium

Smart Contract Audit Report

Audit Summary

Vinium is a new decentralized liquidity markets protocol where users are in control of their funds while participating in the market.

For this audit, we reviewed the project team's contracts folder at commit 78e147a367a6fc6b22dc790fe57b11f13a6a9005 on the team's private GitHub repository.

Audit Findings

All findings have been resolved, though some centralized aspects are present.
Date: August 30th, 2022.
Updated: October 12th, 2022 with changes from commit bc410432209ffb0ca6b4be424043f81a20959a3f to commit 78e147a367a6fc6b22dc790fe57b11f13a6a9005.

Finding #1 - FlashLiquidationAdapter - Informational (Resolved)

Description: The FlashLiquidationAdapter contract's only functionality is in conjunction with a flashloan which the team has elected to not implement.
Recommendation: This can be removed from the repository and should not be deployed.
Resolution: The team has chosen to implement the flashloan functionality.

Finding #2 - UniswapRepayAdapter, UniswapLiquiditySwapAdapter, & ParaSwapLiquiditySwapAdapter - Informational (Resolved)

Description: These contracts contain an executeOperation() function used to support flashloans which the team has elected to not implement.
Recommendation: This function can be removed to lower contract size and deployment cost.
Resolution: The team has chosen to implement the flashloan functionality.

Finding #3 - Vinium Lending - Informational (Resolved)

Description: The protocol contains several hardcoded addresses on the Ethereum Mainnet.
Recommendation: The team should ensure these addresses are updated and/or accurate before deployment.
Resolution: The team has updated the necessary addresses.

Contracts Overview

  • The contracts utilize ReentrancyGuard to protect against reentrancy attacks in applicable functions.
AToken Contract:
  • aTokens are interest-bearing tokens that correspond to an underlying asset. For example, an aWETH 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.
  • This contract complies with the ERC-20 standard.
  • The contract also implements EIP2612 functionality allowing for gasless transfers for users through the use of permits.
  • Only the LendingPool may call all non-ERC20 and non-ERC2612 public functions that affect state
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.
  • The IncentivesController contract's handleAction() function will be called if the contract's address is defined.
  • 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, only the LendingPool may call all non-ERC20 public functions that affect state.
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.
  • The IncentivesController contract's handleAction() function will be called if the contract's address is defined.
  • 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, only the LendingPool may call all non-ERC20 public functions that affect state.
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.
  • 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.
  • 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.
  • 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.
AaveOracle Contract:
  • This contract is used to fetch prices using specified oracles.
  • A specified Chainlink Aggregator is used as the primary source for an asset's price.
  • If a Chainlink Aggregator for an asset has not been set or returns 0, the contract's fallback oracle is used.
  • If asset is the specified "base currency", the "base currency unit" constant is returned as the price.
  • The owner can update the Chainlink Aggregator for any asset at any time.
  • The owner can update the fallback oracle 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, and LendingRateOracle 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.
UniswapRepayAdapter Contract:
  • This contract serves as a wrapper for swapping and repaying debt using Uniswap.
  • Users specify whether they are repaying a specific amount of debt or their entire debt and whether they are repaying a stable rate debt or variable rate debt.
  • The specified amount of aTokens are transferred from the user where they are subsequently exchanged for the underlying asset.
  • The received tokens are swapped for the needed collateral tokens if they are not the same token.
  • The received tokens are then used to repay the user's debt in the LendingPool.
UniswapLiquiditySwapAdapter Contract:
  • This contract serves as a wrapper for swapping between assets on Uniswap and depositing into the LendingPool.
  • Users provide a list of assets to swap from and a list of assets to swap to.
  • The user may specify that their entire token balance is swapped or just a specified amount.
  • The specified amount of the asset's corresponding aTokens are transferred from the user where they are subsequently exchanged for the underlying asset.
  • The received tokens are then swapped on Uniswap and subsequently deposited into the LendingPool on behalf of the user.
ParaSwapLiquiditySwapAdapter Contract:
  • This contract serves as a wrapper for swapping between assets on ParaSwap and depositing into the LendingPool.
  • Users provide an asset to swap from and an asset to swap to.
  • The user may specify that their entire token balance is swapped or just a specified amount.
  • The specified amount of the asset's corresponding aTokens are transferred from the user where they are subsequently exchanged for the underlying asset.
  • The underlying asset is then swapped for the specified token using ParaSwap.
  • The received tokens are deposited into the LendingPool on the behalf of the user.

Audit Results

Vulnerability Category Notes Result
Arbitrary Jump/Storage Write N/A PASS
Centralization of Control
  • The Pool Admin can freeze and update attributes of a Lending Pool at any time.
  • The LendingPoolAddressProvider's owner can update the LendingPool contract implementation at any time.
  • The AaveOracle's owner can update the fallback oracle and Chainlink Aggregator for any asset.
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
Unbounded Loops N/A PASS
Unused Code N/A PASS
Overall Contract Safety   PASS

Contract Source Summary and Visualizations

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 1300+ 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 across 1500 projects!.
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.