Skip to content

Commit

Permalink
fix: #12
Browse files Browse the repository at this point in the history
  • Loading branch information
xenide committed Dec 31, 2024
1 parent 3596ae0 commit 7480072
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 38 deletions.
46 changes: 24 additions & 22 deletions src/asset-management/EulerV2Manager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ contract EulerV2Manager is IAssetManager, Owned(msg.sender), RGT {

error OutstandingSharesForVault();
error ReturnAssetZeroAmount();
error InvestmentAttemptDuringWindDown();
error NoVaultForAsset();

/// @dev Mapping from an ERC20 token to an Euler V2 vault.
/// This implies that for a given asset, there can only be one vault at any one time.
Expand Down Expand Up @@ -159,26 +161,12 @@ contract EulerV2Manager is IAssetManager, Owned(msg.sender), RGT {
{
IERC20 lToken0 = aPair.token0();
IERC20 lToken1 = aPair.token1();

IERC4626 lToken0Vault = assetVault[lToken0];
IERC4626 lToken1Vault = assetVault[lToken1];

// do not do anything if there isn't a designated vault for the token
if (address(lToken0Vault) == address(0)) {
aAmount0Change = 0;
}
if (address(lToken1Vault) == address(0)) {
aAmount1Change = 0;
}

if (windDownMode) {
if (aAmount0Change > 0) {
aAmount0Change = 0;
}
if (aAmount1Change > 0) {
aAmount1Change = 0;
}
}
if (address(lToken0Vault) == address(0)) require(aAmount0Change == 0, NoVaultForAsset());
if (address(lToken1Vault) == address(0)) require(aAmount1Change == 0, NoVaultForAsset());
if (windDownMode) require(aAmount0Change <= 0 && aAmount1Change <= 0, InvestmentAttemptDuringWindDown());

// withdraw from the vault
if (aAmount0Change < 0) {
Expand Down Expand Up @@ -234,13 +222,20 @@ contract EulerV2Manager is IAssetManager, Owned(msg.sender), RGT {
IAssetManagedPair lPair = IAssetManagedPair(msg.sender);
IERC20 lToken0 = lPair.token0();
IERC20 lToken1 = lPair.token1();

(uint256 lReserve0, uint256 lReserve1,,) = lPair.getReserves();

uint256 lToken0Managed = _getBalance(lPair, lToken0);
uint256 lToken1Managed = _getBalance(lPair, lToken1);
int256 lAmount0Change;
if (address(assetVault[lToken0]) != address(0)) {
uint256 lToken0Managed = _getBalance(lPair, lToken0);
lAmount0Change = _calculateChangeAmount(lReserve0, lToken0Managed);
}

int256 lAmount0Change = _calculateChangeAmount(lReserve0, lToken0Managed);
int256 lAmount1Change = _calculateChangeAmount(lReserve1, lToken1Managed);
int256 lAmount1Change;
if (address(assetVault[lToken1]) != address(0)) {
uint256 lToken1Managed = _getBalance(lPair, lToken1);
lAmount1Change = _calculateChangeAmount(lReserve1, lToken1Managed);
}

_adjustManagement(lPair, lAmount0Change, lAmount1Change);
}
Expand All @@ -250,11 +245,18 @@ contract EulerV2Manager is IAssetManager, Owned(msg.sender), RGT {
_adjustManagement(IAssetManagedPair(msg.sender), -aToken0Amt.toInt256(), -aToken1Amt.toInt256());
}

// calculates the amount of token to divest or invest based on the thresholds, and if windown mode is activated
function _calculateChangeAmount(uint256 aReserve, uint256 aManaged) internal view returns (int256 rAmountChange) {
if (
aManaged * Constants.WAD < aReserve * lowerThreshold || aManaged * Constants.WAD > aReserve * upperThreshold
) {
rAmountChange = (aReserve.mulWad(uint256(lowerThreshold).avg(upperThreshold)) - aManaged).toInt256();
rAmountChange =
aReserve.mulWad(uint256(lowerThreshold).avg(upperThreshold)).toInt256() - aManaged.toInt256();

// only allow divesting if windDownMode is activated
if (windDownMode && rAmountChange > 0) {
rAmountChange = 0;
}
}
}

Expand Down
37 changes: 21 additions & 16 deletions test/integration/Euler.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -234,15 +234,19 @@ contract EulerIntegrationTest is BaseTest {
assertEq(_manager.windDownMode(), true);
}

function testAdjustManagement_NoMarket(uint256 aAmountToManage) public allNetworks allPairs {
// assume - we want negative numbers too
int256 lAmountToManage = int256(bound(aAmountToManage, 0, type(uint256).max));
function testAdjustManagement_NoVaultForAsset(int256 aAmountToManage) public allNetworks allPairs {
// assume - we want any positive / negative numbers, just not zero
vm.assume(aAmountToManage != 0);

// arrange
IERC20 lToken0 = _pair.token0();

// act
vm.expectRevert(EulerV2Manager.NoVaultForAsset.selector);
_manager.adjustManagement(
_pair,
_pair.token0() == USDC ? int256(0) : lAmountToManage,
_pair.token1() == USDC ? int256(0) : lAmountToManage
lToken0 == USDC ? int256(0) : aAmountToManage,
lToken0 == USDC ? aAmountToManage : int256(0)
);

// assert
Expand Down Expand Up @@ -339,20 +343,20 @@ contract EulerIntegrationTest is BaseTest {

_manager.setWindDownMode(true);
int256 lIncreaseAmt = 50e6;
IERC20 lToken0 = _pair.token0();
IERC20 lOtherPairToken0 = lOtherPair.token0();

// act
// act & assert - manual adjustments to increase management should fail
vm.expectRevert(EulerV2Manager.InvestmentAttemptDuringWindDown.selector);
_manager.adjustManagement(
_pair, _pair.token0() == USDC ? lIncreaseAmt : int256(0), _pair.token1() == USDC ? lIncreaseAmt : int256(0)
_pair, lToken0 == USDC ? lIncreaseAmt : int256(0), lToken0 == USDC ? int256(0) : lIncreaseAmt
);
vm.expectRevert(EulerV2Manager.InvestmentAttemptDuringWindDown.selector);
_manager.adjustManagement(
lOtherPair,
lOtherPair.token0() == USDC ? lIncreaseAmt : int256(0),
lOtherPair.token1() == USDC ? lIncreaseAmt : int256(0)
lOtherPairToken0 == USDC ? lIncreaseAmt : int256(0),
lOtherPairToken0 == USDC ? int256(0) : lIncreaseAmt
);

// assert
assertApproxEqAbs(_manager.getBalance(_pair, USDC), 300e6, 1);
assertEq(_manager.getBalance(lOtherPair, USDC), 0);
}

function testGetBalance(uint256 aAmountToManage) public allNetworks allPairs {
Expand Down Expand Up @@ -561,17 +565,18 @@ contract EulerIntegrationTest is BaseTest {
_pair.burn(address(this));
assertGt(_pair.token0() == USDC ? _pair.token0Managed() : _pair.token1Managed(), 0);
uint256 lAmtManaged = _manager.getBalance(_pair, USDC);
IERC20 lToken0 = _pair.token0();

// act
_manager.setWindDownMode(true);

// assert - burn should still succeed
_pair.burn(address(this));
// this call to increase management should have no effect
vm.expectRevert(EulerV2Manager.InvestmentAttemptDuringWindDown.selector);
_manager.adjustManagement(
_pair,
_pair.token0() == USDC ? int256(100e6) : int256(0),
_pair.token1() == USDC ? int256(100e6) : int256(0)
lToken0 == USDC ? int256(100e6) : int256(0),
lToken0 == USDC ? int256(0) : int256(100e6)
);
assertEq(_manager.getBalance(_pair, USDC), lAmtManaged);
// a call to decrease management should have an effect
Expand Down

0 comments on commit 7480072

Please sign in to comment.