Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add BatchBadDebtRepay steward contract #4

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
34929ef
Added submodule aave-address-book
TepNik Jan 13, 2025
1e92a0f
Added submodule solidity-utils
TepNik Jan 13, 2025
e6e3697
Added Prettier
TepNik Jan 14, 2025
65f4bbb
Added node_modules and VS Code settings into the gitignore file
TepNik Jan 14, 2025
5aa08c3
Added BatchRepayBadDebtSteward contract
TepNik Jan 14, 2025
12693d1
Added tests for the BatchRepayBadDebtSteward contract
TepNik Jan 14, 2025
a186712
Deleted prettier
TepNik Jan 14, 2025
4160fa4
Used Foundry prettier
TepNik Jan 14, 2025
548af0f
Removed aave-address-book and solidity-utils submodules
TepNik Jan 14, 2025
56bbdd2
Made gas improvements in the BatchRepayBadDebtSteward contract
TepNik Jan 14, 2025
c7ad378
Updated aave-helpers
TepNik Jan 14, 2025
b3bd46f
Moved tests to the Avalanche network fork
TepNik Jan 14, 2025
00f66b7
Deleted the UserBadDebtRepaid event
TepNik Jan 14, 2025
1890937
Added gas snapshots
TepNik Jan 15, 2025
6402a01
Removed the UserHasNoDebt error
TepNik Jan 15, 2025
b708e61
Added the batchLiquidate function to the BatchRepayBadDebtSteward con…
TepNik Jan 20, 2025
8f1b538
Added tests for the batchLiquidate and for the getDebtAmount function…
TepNik Jan 20, 2025
cbb9ce1
Added rescue functions into the BatchRepayBadDebtSteward contract
TepNik Jan 20, 2025
3a5bdf0
Added the AccessControl contract and the CLEANUP role into the BatchR…
TepNik Jan 20, 2025
adbe47f
Changed immutable variables to an uppercase
TepNik Jan 21, 2025
17e27ff
Removed to argument from rescue* functions
TepNik Jan 21, 2025
cfba539
Added the batchLiquidateWithMaxCap function to the BatchRepayBadDebtS…
TepNik Jan 21, 2025
8e81a30
Fixed gas snapshots
TepNik Jan 21, 2025
498031e
fix: add working ci
sakulstra Jan 27, 2025
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ docs/

# Dotenv file
.env

.vscode

node_modules
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
[submodule "lib/aave-helpers"]
path = lib/aave-helpers
url = https://github.com/bgd-labs/aave-helpers
[submodule "lib/aave-address-book"]
path = lib/aave-address-book
url = https://github.com/bgd-labs/aave-address-book
[submodule "lib/solidity-utils"]
TepNik marked this conversation as resolved.
Show resolved Hide resolved
path = lib/solidity-utils
url = https://github.com/bgd-labs/solidity-utils
4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
out
lib
cache
node_modules
24 changes: 24 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
TepNik marked this conversation as resolved.
Show resolved Hide resolved
"overrides": [
{
"files": "*.sol",
"options": {
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"bracketSpacing": false
}
},
{
"files": "*.ts",
"options": {
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"bracketSpacing": false
}
}
]
}
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[profile.default]
src = "src"
out = "out"
test = "tests"
libs = ["lib"]

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
Expand Down
1 change: 1 addition & 0 deletions lib/aave-address-book
Submodule aave-address-book added at 712494
1 change: 1 addition & 0 deletions lib/solidity-utils
Submodule solidity-utils added at 7e630a
66 changes: 66 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
TepNik marked this conversation as resolved.
Show resolved Hide resolved
"name": "aave-stewards",
"version": "1.0.0",
"scripts": {
"lint": "prettier . --check",
"lint:fix": "prettier . --write"
},
"repository": {
"type": "git",
"url": "git+https://github.com/bgd-labs/aave-stewards.git"
},
"author": "BGD Labs for Aave",
"license": "BUSL-1.1",
"bugs": {
"url": "https://github.com/bgd-labs/aave-stewards/issues"
},
"homepage": "https://github.com/bgd-labs/aave-stewards#readme",
"type": "module",
"dependencies": {
"prettier": "^3.4.2",
"prettier-plugin-solidity": "^1.4.2"
}
}
85 changes: 85 additions & 0 deletions src/maintenance/BatchRepayBadDebtSteward.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IPool, DataTypes} from 'aave-address-book/AaveV3.sol';
import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol';
import {SafeERC20} from 'solidity-utils/contracts/oz-common/SafeERC20.sol';

import {IBatchRepayBadDebtSteward} from './interfaces/IBatchRepayBadDebtSteward.sol';

/// @title BatchRepayBadDebtSteward
/// @author BGD Labs
/// @notice This contract allows to repay all the bad debt of a list of users
/// @dev Only allowed those users that have some debt and doesn't have any collateral
contract BatchRepayBadDebtSteward is IBatchRepayBadDebtSteward {
using SafeERC20 for IERC20;

/* PUBLIC GLOBAL VARIABLES */

/// @inheritdoc IBatchRepayBadDebtSteward
IPool public immutable override POOL;

/* CONSTRUCTOR */

constructor(address _pool) {
POOL = IPool(_pool);
}

/* EXTERNAL FUNCTIONS */

/// @inheritdoc IBatchRepayBadDebtSteward
function batchRepayBadDebt(address asset, address[] memory users) external override {
(uint256 totalDebtAmount, uint256[] memory debtAmounts) = getBadDebtAmount(asset, users);

IERC20(asset).safeTransferFrom(msg.sender, address(this), totalDebtAmount);
IERC20(asset).forceApprove(address(POOL), totalDebtAmount);

uint256 length = users.length;
for (uint256 i = 0; i < length; i++) {
POOL.repay({asset: asset, amount: debtAmounts[i], interestRateMode: 2, onBehalfOf: users[i]});

emit UserBadDebtRepaid({user: users[i], asset: asset, amount: debtAmounts[i]});
TepNik marked this conversation as resolved.
Show resolved Hide resolved
}
}

/* PUBLIC VIEW FUNCTIONS */

/// @inheritdoc IBatchRepayBadDebtSteward
function getBadDebtAmount(
address asset,
address[] memory users
) public view override returns (uint256, uint256[] memory) {
uint256 length = users.length;

uint256 totalDebtAmount;
uint256[] memory debtAmounts = new uint256[](length);

DataTypes.ReserveDataLegacy memory reserveData = POOL.getReserveData(asset);

for (uint256 i = 0; i < length; i++) {
address user = users[i];

for (uint256 j = i + 1; j < length; j++) {
TepNik marked this conversation as resolved.
Show resolved Hide resolved
if (user == users[j]) {
revert UsersShouldBeDifferent(user);
}
}

(uint256 totalCollateralBase, uint256 totalDebtBase, , , , ) = POOL.getUserAccountData(user);

if (totalCollateralBase > 0) {
revert UserHasSomeCollateral(user);
}

if (totalDebtBase == 0) {
revert UserHasNoDebt(user);
}

totalDebtAmount += debtAmounts[i] = IERC20(reserveData.variableDebtTokenAddress).balanceOf(
user
);
}

return (totalDebtAmount, debtAmounts);
}
}
54 changes: 54 additions & 0 deletions src/maintenance/interfaces/IBatchRepayBadDebtSteward.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IPool} from 'aave-address-book/AaveV3.sol';

interface IBatchRepayBadDebtSteward {
/* EVENTS */

/// @notice Emitted when a user has been repaid his bad debt
/// @param user The address of the user
/// @param asset The address of the asset
/// @param amount The amount repaid
event UserBadDebtRepaid(address indexed user, address indexed asset, uint256 amount);

/* ERRORS */

/// @notice Thrown when a user has some collateral
/// @param user The address of the user
error UserHasSomeCollateral(address user);

/// @notice Thrown when a user has no debt
/// @param user The address of the user
error UserHasNoDebt(address user);

/// @notice Thrown when an array contains two users with the same address
/// @param user The address of the user
error UsersShouldBeDifferent(address user);

/* GLOBAL VARIABLES */

/// @notice The Aave pool
function POOL() external view returns (IPool);

/* EXTERNAL FUNCTIONS */

/// @notice Repays all the bad debt of the users
/// @dev Will fail if the user has some collateral or no debt
/// @param asset The address of the asset to repay
/// @param users The addresses of the users to repay
function batchRepayBadDebt(address asset, address[] calldata users) external;

/* EXTERNAL VIEW FUNCTIONS */

/// @notice Returns the total bad debt amount and the debt amounts of users
/// @dev Will fail if the user has some collateral or no debt
/// @param asset The address of the asset to repay
/// @param users The addresses of the users to repay
/// @return totalDebtAmount The total debt amount
/// @return debtAmounts The debt amounts of the users
function getBadDebtAmount(
address asset,
address[] memory users
) external view returns (uint256 totalDebtAmount, uint256[] memory debtAmounts);
}
Loading
Loading