Skip to content

Commit

Permalink
Merge pull request #91 from Ion-Protocol/jun/PAG-L-07
Browse files Browse the repository at this point in the history
L-07 Fix [PAG]
  • Loading branch information
junkim012 authored May 16, 2024
2 parents 971e8f6 + 5f1fe86 commit 9c94f1a
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 5 deletions.
10 changes: 5 additions & 5 deletions src/IonPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -490,14 +490,14 @@ contract IonPool is PausableUpgradeable, RewardToken {
(uint256 borrowRate, uint256 reserveFactor) =
$.interestRateModule.calculateInterestRate(ilkIndex, totalDebt, totalEthSupply);

if (borrowRate == 0) return (0, 0, 0, 0, 0);

// Calculates borrowRate ^ (time) and returns the result with RAY precision
uint256 borrowRateExpT = _rpow(borrowRate + RAY, block.timestamp - ilk.lastRateUpdate, RAY);

// Unsafe cast OK
timestampIncrease = uint48(block.timestamp) - ilk.lastRateUpdate;

if (borrowRate == 0) return (0, 0, 0, 0, timestampIncrease);

// Calculates borrowRate ^ (time) and returns the result with RAY precision
uint256 borrowRateExpT = _rpow(borrowRate + RAY, timestampIncrease, RAY);

// Debt distribution
// This form of rate accrual is much safer than distributing the new
// debt increase to the total debt since low debt amounts won't cause
Expand Down
5 changes: 5 additions & 0 deletions src/vault/Vault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ contract Vault is ERC4626, Multicall, AccessControlDefaultAdminRules, Reentrancy
error MarketsAndAllocationCapLengthMustBeEqual();
error IonPoolsArrayAndNewCapsArrayMustBeOfEqualLength();
error InvalidFeePercentage();
error MaxSupportedMarketsReached();

event UpdateSupplyQueue(address indexed caller, IIonPool[] newSupplyQueue);
event UpdateWithdrawQueue(address indexed caller, IIonPool[] newWithdrawQueue);
Expand All @@ -69,6 +70,8 @@ contract Vault is ERC4626, Multicall, AccessControlDefaultAdminRules, Reentrancy

IERC20 public immutable BASE_ASSET;

uint8 public constant MAX_SUPPORTED_MARKETS = 32;

EnumerableSet.AddressSet supportedMarkets;

IIonPool[] public supplyQueue;
Expand Down Expand Up @@ -167,6 +170,8 @@ contract Vault is ERC4626, Multicall, AccessControlDefaultAdminRules, Reentrancy
}
}

if (supportedMarkets.length() > MAX_SUPPORTED_MARKETS) revert MaxSupportedMarketsReached();

updateSupplyQueue(newSupplyQueue);
updateWithdrawQueue(newWithdrawQueue);
}
Expand Down
46 changes: 46 additions & 0 deletions test/unit/concrete/IonPool.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -1129,6 +1129,52 @@ contract IonPool_InterestTest is IonPoolSharedSetup, IIonPoolEvents {
}
}

// If zero borrow rate, only the last updated timestamp should update
function test_CalculateRewardAndDebtDistributionZeroBorrowRate() external {
// update interest rate module to have zero rates.
IlkData[] memory ilkConfigs = new IlkData[](3);
uint16[] memory distributionFactors = new uint16[](3);
distributionFactors[0] = 0.2e4;
distributionFactors[1] = 0.4e4;
distributionFactors[2] = 0.4e4;

for (uint8 i; i != 3; ++i) {
IlkData memory ilkConfig = IlkData({
adjustedProfitMargin: 0,
minimumKinkRate: 0,
reserveFactor: 0,
adjustedBaseRate: 0,
minimumBaseRate: 0,
optimalUtilizationRate: 9000,
distributionFactor: distributionFactors[i],
adjustedAboveKinkSlope: 0,
minimumAboveKinkSlope: 0
});
ilkConfigs[i] = ilkConfig;
}

interestRateModule = new InterestRate(ilkConfigs, apyOracle);
ionPool.updateInterestRateModule(interestRateModule);

vm.warp(block.timestamp + 1 days);

(
uint256 totalSupplyFactorIncrease,
,
uint104[] memory rateIncreases,
uint256 totalDebtIncrease,
uint48[] memory timestampIncreases
) = ionPool.calculateRewardAndDebtDistribution();

assertEq(totalSupplyFactorIncrease, 0, "total supply factor");
assertEq(totalDebtIncrease, 0, "total debt increase");

for (uint8 i; i != 3; ++i) {
assertEq(rateIncreases[i], 0, "rate");
assertEq(timestampIncreases[i], 1 days, "timestamp increase");
}
}

function test_AccrueInterest() public {
uint256 collateralDepositAmount = 10e18;
uint256 normalizedBorrowAmount = 5e18;
Expand Down
22 changes: 22 additions & 0 deletions test/unit/concrete/vault/Vault.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,28 @@ contract VaultSetUpTest is VaultSharedSetup {

function test_Revert_AddSupportedMarkets_MarketAlreadySupported() public { }

function test_Revert_AddSupportedMarkets_MaxSupportedMarketsReached() public {
vault = new Vault(BASE_ASSET, FEE_RECIPIENT, ZERO_FEES, "Ion Vault Token", "IVT", INITIAL_DELAY, VAULT_ADMIN);

vm.startPrank(vault.defaultAdmin());
vault.grantRole(vault.OWNER_ROLE(), OWNER);
vault.grantRole(vault.ALLOCATOR_ROLE(), OWNER);
vm.stopPrank();

IIonPool[] memory markets = new IIonPool[](vault.MAX_SUPPORTED_MARKETS() + 1);
uint256[] memory allocationCaps = new uint256[](vault.MAX_SUPPORTED_MARKETS() + 1);

for (uint8 i = 0; i < vault.MAX_SUPPORTED_MARKETS() + 1; i++) {
markets[i] = deployIonPool(BASE_ASSET, WEETH, address(this));
allocationCaps[i] = 1 ether;
}

vm.startPrank(OWNER);
vm.expectRevert(Vault.MaxSupportedMarketsReached.selector);
vault.addSupportedMarkets(markets, allocationCaps, markets, markets);
vm.stopPrank();
}

function test_RemoveSingleSupportedMarket() public {
uint256[] memory allocationCaps = new uint256[](1);
allocationCaps[0] = 1e18;
Expand Down

0 comments on commit 9c94f1a

Please sign in to comment.