Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion contracts/DelegateBorrowers/MoveDebtDelegate.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import { ResilientOracleInterface } from "@venusprotocol/oracle/contracts/interf
import { ensureNonzeroAddress } from "@venusprotocol/solidity-utilities/contracts/validators.sol";

import { approveOrRevert } from "../lib/approveOrRevert.sol";
import { IVBep20, IComptroller } from "../InterfacesV8.sol";
import { IComptroller } from "../Comptroller/interfaces/IComptroller.sol";
import { IVBep20 } from "../Tokens/VTokens/interfaces/IVBep20.sol";

contract MoveDebtDelegate is Ownable2StepUpgradeable, ReentrancyGuardUpgradeable {
/// @dev VToken return value signalling about successful execution
Expand Down
3 changes: 2 additions & 1 deletion contracts/DelegateBorrowers/SwapDebtDelegate.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC
import { ResilientOracleInterface } from "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol";

import { approveOrRevert } from "../lib/approveOrRevert.sol";
import { IVBep20, IComptroller } from "../InterfacesV8.sol";
import { IComptroller } from "../Comptroller/interfaces/IComptroller.sol";
import { IVBep20 } from "../Tokens/VTokens/interfaces/IVBep20.sol";

contract SwapDebtDelegate is Ownable2StepUpgradeable, ReentrancyGuardUpgradeable {
/// @dev VToken return value signalling about successful execution
Expand Down
7 changes: 5 additions & 2 deletions contracts/Governance/TokenRedeemer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuar
import { Ownable2Step } from "@openzeppelin/contracts/access/Ownable2Step.sol";
import { ensureNonzeroAddress } from "@venusprotocol/solidity-utilities/contracts/validators.sol";

import { IVAIController, IVToken, IVBep20, IVBNB } from "../InterfacesV8.sol";
import { IVToken } from "../Tokens/VTokens/interfaces/IVToken.sol";
import { IVBep20 } from "../Tokens/VTokens/interfaces/IVBep20.sol";
import { IVBNB } from "../Tokens/VTokens/interfaces/IVBNB.sol";
import { IVAIController } from "../Tokens/VAI/interfaces/IVAIController.sol";
import { Currency, CurrencyLibrary } from "../lib/Currency.sol";

contract TokenRedeemer is ReentrancyGuard, Ownable2Step {
Expand Down Expand Up @@ -162,7 +165,7 @@ contract TokenRedeemer is ReentrancyGuard, Ownable2Step {
return;
}
if (_isVBNB(vToken)) {
IVBNB(address(vToken)).repayBorrowBehalf{ value: amount }(borrower);
IVBNB(payable(address(vToken))).repayBorrowBehalf{ value: amount }(borrower);
} else {
uint256 err = IVBep20(address(vToken)).repayBorrowBehalf(borrower, amount);
if (err != 0) {
Expand Down
108 changes: 0 additions & 108 deletions contracts/InterfacesV8.sol

This file was deleted.

24 changes: 14 additions & 10 deletions contracts/Liquidator/BUSDLiquidator.sol
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import { SafeERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import { Ownable2StepUpgradeable } from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
import { MANTISSA_ONE } from "@venusprotocol/solidity-utilities/contracts/constants.sol";
import { ensureNonzeroAddress } from "@venusprotocol/solidity-utilities/contracts/validators.sol";

import { approveOrRevert } from "../lib/approveOrRevert.sol";
import { ILiquidator, IComptroller, IVToken, IVBep20, IVBNB, IVAIController } from "../InterfacesV8.sol";
import { Action } from "../Comptroller/Diamond/interfaces/IFacetBase.sol";
import { ILiquidator } from "./interfaces/ILiquidator.sol";
import { IComptroller } from "../Comptroller/interfaces/IComptroller.sol";
import { IVToken } from "../Tokens/VTokens/interfaces/IVToken.sol";
import { IVBep20 } from "../Tokens/VTokens/interfaces/IVBep20.sol";

/**
* @title BUSDLiquidator
* @author Venus
* @notice A custom contract for force-liquidating BUSD debts
*/
contract BUSDLiquidator is Ownable2StepUpgradeable, ReentrancyGuardUpgradeable {
using SafeERC20Upgradeable for IERC20Upgradeable;
using SafeERC20Upgradeable for IVToken;
using SafeERC20 for IERC20;
using SafeERC20 for IVToken;

/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
IVBep20 public immutable vBUSD;
Expand Down Expand Up @@ -95,7 +99,7 @@ contract BUSDLiquidator is Ownable2StepUpgradeable, ReentrancyGuardUpgradeable {
/// @notice Allows to recover token accidentally sent to this contract by sending the entire balance to Governance
/// @param token The address of the token to recover
/// @custom:access Only Governance
function sweepToken(IERC20Upgradeable token) external onlyOwner {
function sweepToken(IERC20 token) external onlyOwner {
token.safeTransfer(msg.sender, token.balanceOf(address(this)));
}

Expand All @@ -107,8 +111,8 @@ contract BUSDLiquidator is Ownable2StepUpgradeable, ReentrancyGuardUpgradeable {
function _unpauseAndLiquidate(address borrower, uint256 repayAmount, IVToken vTokenCollateral) internal {
address[] memory vTokens = new address[](1);
vTokens[0] = address(vBUSD);
IComptroller.Action[] memory actions = new IComptroller.Action[](1);
actions[0] = IComptroller.Action.LIQUIDATE;
Action[] memory actions = new Action[](1);
actions[0] = Action.LIQUIDATE;

comptroller._setActionsPaused(vTokens, actions, false);
_liquidateBorrow(borrower, repayAmount, vTokenCollateral);
Expand All @@ -122,7 +126,7 @@ contract BUSDLiquidator is Ownable2StepUpgradeable, ReentrancyGuardUpgradeable {
/// @param vTokenCollateral The collateral to seize from the borrower
function _liquidateBorrow(address borrower, uint256 repayAmount, IVToken vTokenCollateral) internal {
ILiquidator liquidatorContract = ILiquidator(comptroller.liquidatorContract());
IERC20Upgradeable busd = IERC20Upgradeable(vBUSD.underlying());
IERC20 busd = IERC20(vBUSD.underlying());

uint256 actualRepayAmount = _transferIn(busd, msg.sender, repayAmount);
approveOrRevert(busd, address(liquidatorContract), actualRepayAmount);
Expand All @@ -141,7 +145,7 @@ contract BUSDLiquidator is Ownable2StepUpgradeable, ReentrancyGuardUpgradeable {
/// @param from The account to transfer from
/// @param amount The amount to transfer
/// @return The actual amount transferred
function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {
function _transferIn(IERC20 token, address from, uint256 amount) internal returns (uint256) {
uint256 prevBalance = token.balanceOf(address(this));
token.safeTransferFrom(from, address(this), amount);
return token.balanceOf(address(this)) - prevBalance;
Expand Down
24 changes: 18 additions & 6 deletions contracts/Liquidator/Liquidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,25 @@ import { Ownable2StepUpgradeable } from "@openzeppelin/contracts-upgradeable/acc
import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import { SafeERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import { ensureNonzeroAddress } from "@venusprotocol/solidity-utilities/contracts/validators.sol";
import "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol";
import { AccessControlledV8 } from "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol";
import { IProtocolShareReserve } from "../external/IProtocolShareReserve.sol";
import { IWBNB } from "../external/IWBNB.sol";
import "./LiquidatorStorage.sol";
import { IComptroller, IVToken, IVBep20, IVBNB, IVAIController } from "../InterfacesV8.sol";

contract Liquidator is Ownable2StepUpgradeable, ReentrancyGuardUpgradeable, LiquidatorStorage, AccessControlledV8 {
import { Action } from "../Comptroller/Diamond/interfaces/IFacetBase.sol";
import { IComptroller } from "../Comptroller/interfaces/IComptroller.sol";
import { IVToken } from "../Tokens/VTokens/interfaces/IVToken.sol";
import { IVBep20 } from "../Tokens/VTokens/interfaces/IVBep20.sol";
import { IVBNB } from "../Tokens/VTokens/interfaces/IVBNB.sol";
import { IVAIController } from "../Tokens/VAI/interfaces/IVAIController.sol";
import { ILiquidator } from "./interfaces/ILiquidator.sol";
import { LiquidatorStorage } from "./LiquidatorStorage.sol";

contract Liquidator is
ILiquidator,
Ownable2StepUpgradeable,
ReentrancyGuardUpgradeable,
LiquidatorStorage,
AccessControlledV8
{
/// @notice Address of vBNB contract.
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
IVBNB public immutable vBnb;
Expand Down Expand Up @@ -468,7 +480,7 @@ contract Liquidator is Ownable2StepUpgradeable, ReentrancyGuardUpgradeable, Liqu
/// @dev Checks liquidation action in comptroller and vaiDebt with minLiquidatableVAI threshold
function _checkForceVAILiquidate(address vToken_, address borrower_) private view {
uint256 _vaiDebt = vaiController.getVAIRepayAmount(borrower_);
bool _isVAILiquidationPaused = comptroller.actionPaused(address(vaiController), IComptroller.Action.LIQUIDATE);
bool _isVAILiquidationPaused = comptroller.actionPaused(address(vaiController), Action.LIQUIDATE);
bool _isForcedLiquidationEnabled = comptroller.isForcedLiquidationEnabled(vToken_);
if (
_isForcedLiquidationEnabled ||
Expand Down
8 changes: 5 additions & 3 deletions contracts/Liquidator/LiquidatorStorage.sol
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.25;

contract LiquidatorStorage {
import { ILiquidatorStorage } from "./interfaces/ILiquidatorStorage.sol";

contract LiquidatorStorage is ILiquidatorStorage {
/* State */

/// @notice Percent of seized amount that goes to treasury.
uint256 public treasuryPercentMantissa;

/// @notice Mapping of addresses allowed to liquidate an account if liquidationRestricted[borrower] == true
mapping(address => mapping(address => bool)) public allowedLiquidatorsByAccount;
mapping(address borrower => mapping(address liquidator => bool)) public allowedLiquidatorsByAccount;

/// @notice Whether the liquidations are restricted to enabled allowedLiquidatorsByAccount addresses only
mapping(address => bool) public liquidationRestricted;
mapping(address borrower => bool) public liquidationRestricted;

/// @notice minimum amount of VAI liquidation threshold
uint256 public minLiquidatableVAI;
Expand Down
58 changes: 58 additions & 0 deletions contracts/Liquidator/interfaces/ILiquidator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.25;

import { IVToken } from "../../Tokens/VTokens/interfaces/IVToken.sol";
import { ILiquidatorStorage } from "./ILiquidatorStorage.sol";

interface ILiquidator is ILiquidatorStorage {
/**
* @notice An admin function to restrict liquidations to allowed addresses only.
* @dev Use {addTo,removeFrom}AllowList to configure the allowed addresses.
* @param borrower The address of the borrower
*/
function restrictLiquidation(address borrower) external;

/**
* @notice An admin function to remove restrictions for liquidations.
* @dev Does not impact the allowedLiquidatorsByAccount mapping for the borrower, just turns off the check.
* @param borrower The address of the borrower
*/
function unrestrictLiquidation(address borrower) external;

/**
* @notice An admin function to add the liquidator to the allowedLiquidatorsByAccount mapping for a certain
* borrower. If the liquidations are restricted, only liquidators from the
* allowedLiquidatorsByAccount mapping can participate in liquidating the positions of this borrower.
* @param borrower The address of the borrower
* @param borrower The address of the liquidator
*/
function addToAllowlist(address borrower, address liquidator) external;

/**
* @notice An admin function to remove the liquidator from the allowedLiquidatorsByAccount mapping for a certain
* borrower.
* @param borrower The address of the borrower
* @param liquidator The address of the liquidator
*/
function removeFromAllowlist(address borrower, address liquidator) external;

/**
* @notice Liquidates a borrowers position.
* @param vToken The address of the vToken to liquidate
* @param borrower The address of the borrower
* @param repayAmount The amount of the underlying asset to repay
* @param vTokenCollateral The address of the vToken collateral
*/
function liquidateBorrow(
address vToken,
address borrower,
uint256 repayAmount,
IVToken vTokenCollateral
) external payable;

/**
* @notice Sets the percentage of the liquidation reward that is sent to the treasury.
* @param newTreasuryPercentMantissa The new treasury percent, scaled by 1e18 (e.g. 0.2 * 1e18 for 20%)
*/
function setTreasuryPercent(uint256 newTreasuryPercentMantissa) external;
}
50 changes: 50 additions & 0 deletions contracts/Liquidator/interfaces/ILiquidatorStorage.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.25;

interface ILiquidatorStorage {
/**
* @notice Percent of seized amount that goes to treasury.
* @return The treasury percent, scaled by 1e18 (e.g. 0.2 * 1e18 for 20%)
*/
function treasuryPercentMantissa() external view returns (uint256);

/**
* @notice Mapping of addresses allowed to liquidate an account if liquidationRestricted[borrower] == true
* @param liquidator The address of the liquidator
* @param borrower The address of the borrower
* @return True if the liquidator is allowed to liquidate the borrower, false otherwise
*/
function allowedLiquidatorsByAccount(address liquidator, address borrower) external view returns (bool);

/**
* @notice Whether the liquidations are restricted to enabled allowedLiquidatorsByAccount addresses only
* @param borrower The address of the borrower
* @return True if the liquidations are restricted to enabled allowedLiquidatorsByAccount addresses only, false otherwise
*/
function liquidationRestricted(address borrower) external view returns (bool);

/**
* @notice minimum amount of VAI liquidation threshold
* @return The minimum amount of VAI liquidation threshold
*/
function minLiquidatableVAI() external view returns (uint256);

/**
* @notice check for liquidation of VAI
* @return True if the liquidation of VAI is enabled, false otherwise
*/
function forceVAILiquidate() external view returns (bool);

/**
* @notice assests whose redeem is pending to reduce reserves
* @param index The index of the pending redeem
* @return The address of the pending redeem
*/
function pendingRedeem(uint256 index) external view returns (address);

/**
* @notice protocol share reserve contract address
* @return The address of the protocol share reserve contract
*/
function protocolShareReserve() external view returns (address);
}
Loading