Initial commit
This commit is contained in:
176
contracts/core/CollateralToggleManager.sol
Normal file
176
contracts/core/CollateralToggleManager.sol
Normal file
@@ -0,0 +1,176 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.24;
|
||||
|
||||
import "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import "@openzeppelin/contracts/access/AccessControl.sol";
|
||||
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
|
||||
|
||||
/**
|
||||
* @title CollateralToggleManager
|
||||
* @notice Manages Aave v3 collateral enable/disable and sub-vault operations
|
||||
* @dev Enables efficient batch operations for collateral management
|
||||
*/
|
||||
contract CollateralToggleManager is Ownable, AccessControl, ReentrancyGuard {
|
||||
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
|
||||
bytes32 public constant KERNEL_ROLE = keccak256("KERNEL_ROLE");
|
||||
|
||||
// Aave v3 Pool interface
|
||||
interface IPoolV3 {
|
||||
function setUserUseReserveAsCollateral(
|
||||
address asset,
|
||||
bool useAsCollateral
|
||||
) external;
|
||||
|
||||
function getUserAccountData(address user)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
uint256 totalCollateralBase,
|
||||
uint256 totalDebtBase,
|
||||
uint256 availableBorrowsBase,
|
||||
uint256 currentLiquidationThreshold,
|
||||
uint256 ltv,
|
||||
uint256 healthFactor
|
||||
);
|
||||
}
|
||||
|
||||
IPoolV3 public aavePool;
|
||||
address public aaveUserAccount;
|
||||
|
||||
// Collateral status tracking
|
||||
mapping(address => bool) public collateralEnabled;
|
||||
address[] public managedAssets;
|
||||
|
||||
event CollateralToggled(address indexed asset, bool enabled);
|
||||
event BatchCollateralToggled(address[] assets, bool[] enabled);
|
||||
event AavePoolUpdated(address oldPool, address newPool);
|
||||
event AaveUserAccountUpdated(address oldAccount, address newAccount);
|
||||
|
||||
constructor(
|
||||
address _aavePool,
|
||||
address _aaveUserAccount,
|
||||
address initialOwner
|
||||
) Ownable(initialOwner) {
|
||||
require(_aavePool != address(0), "Invalid Aave pool");
|
||||
require(_aaveUserAccount != address(0), "Invalid Aave account");
|
||||
|
||||
aavePool = IPoolV3(_aavePool);
|
||||
aaveUserAccount = _aaveUserAccount;
|
||||
|
||||
_grantRole(DEFAULT_ADMIN_ROLE, initialOwner);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Enable or disable collateral for an asset
|
||||
*/
|
||||
function toggleCollateral(
|
||||
address asset,
|
||||
bool useAsCollateral
|
||||
) external onlyRole(KERNEL_ROLE) nonReentrant {
|
||||
require(asset != address(0), "Invalid asset");
|
||||
|
||||
// Update Aave
|
||||
aavePool.setUserUseReserveAsCollateral(asset, useAsCollateral);
|
||||
|
||||
// Track status
|
||||
if (!collateralEnabled[asset] && managedAssets.length > 0) {
|
||||
bool alreadyTracked = false;
|
||||
for (uint256 i = 0; i < managedAssets.length; i++) {
|
||||
if (managedAssets[i] == asset) {
|
||||
alreadyTracked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!alreadyTracked) {
|
||||
managedAssets.push(asset);
|
||||
}
|
||||
}
|
||||
|
||||
collateralEnabled[asset] = useAsCollateral;
|
||||
emit CollateralToggled(asset, useAsCollateral);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Batch toggle collateral for multiple assets
|
||||
*/
|
||||
function batchToggleCollateral(
|
||||
address[] calldata assets,
|
||||
bool[] calldata useAsCollateral
|
||||
) external onlyRole(KERNEL_ROLE) nonReentrant {
|
||||
require(assets.length == useAsCollateral.length, "Array length mismatch");
|
||||
require(assets.length > 0 && assets.length <= 20, "Invalid array length"); // Reasonable limit
|
||||
|
||||
for (uint256 i = 0; i < assets.length; i++) {
|
||||
toggleCollateral(assets[i], useAsCollateral[i]);
|
||||
}
|
||||
|
||||
emit BatchCollateralToggled(assets, useAsCollateral);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Get collateral status for an asset
|
||||
*/
|
||||
function isCollateralEnabled(address asset) external view returns (bool) {
|
||||
return collateralEnabled[asset];
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Get all managed assets
|
||||
*/
|
||||
function getManagedAssets() external view returns (address[] memory) {
|
||||
return managedAssets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Get Aave position health factor
|
||||
*/
|
||||
function getHealthFactor() external view returns (uint256) {
|
||||
try aavePool.getUserAccountData(aaveUserAccount) returns (
|
||||
uint256,
|
||||
uint256,
|
||||
uint256,
|
||||
uint256,
|
||||
uint256,
|
||||
uint256 healthFactor
|
||||
) {
|
||||
return healthFactor;
|
||||
} catch {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Update Aave pool
|
||||
*/
|
||||
function setAavePool(address newPool) external onlyOwner {
|
||||
require(newPool != address(0), "Invalid pool");
|
||||
address oldPool = address(aavePool);
|
||||
aavePool = IPoolV3(newPool);
|
||||
emit AavePoolUpdated(oldPool, newPool);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Update Aave user account
|
||||
*/
|
||||
function setAaveUserAccount(address newAccount) external onlyOwner {
|
||||
require(newAccount != address(0), "Invalid account");
|
||||
address oldAccount = aaveUserAccount;
|
||||
aaveUserAccount = newAccount;
|
||||
emit AaveUserAccountUpdated(oldAccount, newAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Grant kernel role
|
||||
*/
|
||||
function grantKernel(address kernel) external onlyOwner {
|
||||
_grantRole(KERNEL_ROLE, kernel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Revoke kernel role
|
||||
*/
|
||||
function revokeKernel(address kernel) external onlyOwner {
|
||||
_revokeRole(KERNEL_ROLE, kernel);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user