diff --git a/contracts/EpochManager.sol b/contracts/EpochManager.sol index 74e2792c..547a299b 100644 --- a/contracts/EpochManager.sol +++ b/contracts/EpochManager.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import {IPool} from "./interfaces/IPool.sol"; import {PoolConfig, PoolSettings, LPConfig} from "./PoolConfig.sol"; import {PoolConfigCache} from "./PoolConfigCache.sol"; -import {IRedemptionHandler, RedemptionSummary} from "./interfaces/IRedemptionHandler.sol"; +import {IRedemptionHandler, EpochRedemptionSummary} from "./interfaces/IRedemptionHandler.sol"; import {IPoolSafe} from "./interfaces/IPoolSafe.sol"; import {ITranchesPolicy} from "./interfaces/ITranchesPolicy.sol"; import {DEFAULT_DECIMALS_FACTOR, JUNIOR_TRANCHE, SENIOR_TRANCHE} from "./SharedDefs.sol"; @@ -102,8 +102,8 @@ contract EpochManager is PoolConfigCache, IEpochManager { juniorTranche.totalSupply(); // get unprocessed redemption requests - RedemptionSummary memory seniorSummary = seniorTranche.currentRedemptionSummary(); - RedemptionSummary memory juniorSummary = juniorTranche.currentRedemptionSummary(); + EpochRedemptionSummary memory seniorSummary = seniorTranche.currentRedemptionSummary(); + EpochRedemptionSummary memory juniorSummary = juniorTranche.currentRedemptionSummary(); uint256 unprocessedAmount; if (seniorSummary.totalSharesRequested > 0 || juniorSummary.totalSharesRequested > 0) { @@ -136,11 +136,11 @@ contract EpochManager is PoolConfigCache, IEpochManager { function startNewEpoch() external { poolConfig.onlyPool(msg.sender); - RedemptionSummary memory seniorEpoch = seniorTranche.currentRedemptionSummary(); + EpochRedemptionSummary memory seniorEpoch = seniorTranche.currentRedemptionSummary(); if (seniorEpoch.totalSharesRequested > 0) { seniorTranche.executeRedemptionSummary(seniorEpoch); } - RedemptionSummary memory juniorEpoch = juniorTranche.currentRedemptionSummary(); + EpochRedemptionSummary memory juniorEpoch = juniorTranche.currentRedemptionSummary(); if (juniorEpoch.totalSharesRequested > 0) { juniorTranche.executeRedemptionSummary(juniorEpoch); } @@ -187,9 +187,9 @@ contract EpochManager is PoolConfigCache, IEpochManager { */ function _processEpoch( uint96[2] memory tranchesAssets, - RedemptionSummary memory seniorSummary, + EpochRedemptionSummary memory seniorSummary, uint256 seniorPrice, - RedemptionSummary memory juniorSummary, + EpochRedemptionSummary memory juniorSummary, uint256 juniorPrice ) internal view { // get available underlying token amount @@ -228,27 +228,27 @@ contract EpochManager is PoolConfigCache, IEpochManager { * @notice Processes redemption requests for the senior tranche * @param tranchesAssets tranches assets indexed by SENIOR_TRANCHE or JUNIOR_TRANCHE * @param lpTokenPrice the price of the senior LP tokens - * @param epochInfo epoch info for the senior tranche + * @param redemptionSummary epoch info for the senior tranche * @param availableAmount the total amount available for redemption * @dev this function is side-effectual and mutates the following incoming params: * tranchesAssets: will be updated to reflect the remaining amount of assets in the senior tranche - * epochInfo: will be updated to reflect the latest redemption request states for the senior tranche + * redemptionSummary: will be updated to reflect the latest redemption request states for the senior tranche */ function _processSeniorRedemptionRequests( uint96[2] memory tranchesAssets, uint256 lpTokenPrice, - RedemptionSummary memory epochInfo, + EpochRedemptionSummary memory redemptionSummary, uint256 availableAmount ) internal pure returns (uint256 remainingAmount) { - uint256 sharesToRedeem = epochInfo.totalSharesRequested; + uint256 sharesToRedeem = redemptionSummary.totalSharesRequested; uint256 redemptionAmount = (sharesToRedeem * lpTokenPrice) / DEFAULT_DECIMALS_FACTOR; if (availableAmount < redemptionAmount) { redemptionAmount = availableAmount; // TODO rounding error? sharesToRedeem = (redemptionAmount * DEFAULT_DECIMALS_FACTOR) / lpTokenPrice; } - epochInfo.totalSharesProcessed = uint96(sharesToRedeem); - epochInfo.totalAmountProcessed = uint96(redemptionAmount); + redemptionSummary.totalSharesProcessed = uint96(sharesToRedeem); + redemptionSummary.totalAmountProcessed = uint96(redemptionAmount); availableAmount -= redemptionAmount; tranchesAssets[SENIOR_TRANCHE] -= uint96(redemptionAmount); @@ -262,17 +262,17 @@ contract EpochManager is PoolConfigCache, IEpochManager { * @param tranchesAssets tranches assets indexed by SENIOR_ or JUNIOR_TRANCHE, i.e. tranches[0] is the * senior tranche assets and tranches[1] is the junior tranche assets * @param lpTokenPrice the price of the junior LP tokens - * @param epochInfo the list of epoch infos in each epoch for the junior tranche + * @param redemptionSummary the list of epoch infos in each epoch for the junior tranche * @param availableAmount the total amount available for redemption * @dev this function is side-effectual and mutates the following incoming params: * tranchesAssets: will be updated to reflect the remaining amount of assets in the junior tranche - * epochInfo: will be updated to reflect the latest redemption request states for the senior tranche + * redemptionSummary: will be updated to reflect the latest redemption request states for the senior tranche */ function _processJuniorRedemptionRequests( uint96[2] memory tranchesAssets, uint256 lpTokenPrice, uint256 maxSeniorJuniorRatio, - RedemptionSummary memory epochInfo, + EpochRedemptionSummary memory redemptionSummary, uint256 availableAmount ) internal pure returns (uint256 remainingAmount) { // Calculate the minimum amount of junior assets required to maintain the senior : junior ratio. @@ -286,7 +286,7 @@ contract EpochManager is PoolConfigCache, IEpochManager { : 0; if (maxRedeemableAmount <= 0) return availableAmount; - uint256 sharesToRedeem = epochInfo.totalSharesRequested; + uint256 sharesToRedeem = redemptionSummary.totalSharesRequested; uint256 redemptionAmount = (sharesToRedeem * lpTokenPrice) / DEFAULT_DECIMALS_FACTOR; if (availableAmount < redemptionAmount) { redemptionAmount = availableAmount; @@ -298,8 +298,8 @@ contract EpochManager is PoolConfigCache, IEpochManager { sharesToRedeem = (redemptionAmount * DEFAULT_DECIMALS_FACTOR) / lpTokenPrice; } - epochInfo.totalSharesProcessed = uint96(sharesToRedeem); - epochInfo.totalAmountProcessed = uint96(redemptionAmount); + redemptionSummary.totalSharesProcessed = uint96(sharesToRedeem); + redemptionSummary.totalAmountProcessed = uint96(redemptionAmount); availableAmount -= redemptionAmount; tranchesAssets[JUNIOR_TRANCHE] -= uint96(redemptionAmount); diff --git a/contracts/TrancheVault.sol b/contracts/TrancheVault.sol index 50273c8c..34c34d5e 100644 --- a/contracts/TrancheVault.sol +++ b/contracts/TrancheVault.sol @@ -6,7 +6,7 @@ import {PoolConfig, LPConfig} from "./PoolConfig.sol"; import {PoolConfigCache} from "./PoolConfigCache.sol"; import {JUNIOR_TRANCHE, SENIOR_TRANCHE, DEFAULT_DECIMALS_FACTOR, SECONDS_IN_A_DAY} from "./SharedDefs.sol"; import {TrancheVaultStorage, IERC20} from "./TrancheVaultStorage.sol"; -import {IRedemptionHandler, RedemptionSummary} from "./interfaces/IRedemptionHandler.sol"; +import {IRedemptionHandler, EpochRedemptionSummary} from "./interfaces/IRedemptionHandler.sol"; import {IEpochManager} from "./interfaces/IEpochManager.sol"; import {IPool} from "./interfaces/IPool.sol"; import {IPoolSafe} from "./interfaces/IPoolSafe.sol"; @@ -98,7 +98,11 @@ contract TrancheVault is poolConfig.onlyPoolOperator(msg.sender); if (lender == address(0)) revert Errors.zeroAddressProvided(); _grantRole(LENDER_ROLE, lender); - userInfos[lender] = UserInfo({principal: 0, reinvestYield: reinvestYield}); + depositRecords[lender] = DepositRecord({ + principal: 0, + reinvestYield: reinvestYield, + lastDepositTime: 0 + }); } /** @@ -109,7 +113,7 @@ contract TrancheVault is poolConfig.onlyPoolOperator(msg.sender); if (lender == address(0)) revert Errors.zeroAddressProvided(); _revokeRole(LENDER_ROLE, lender); - delete userInfos[lender]; + delete depositRecords[lender]; } /** @@ -117,7 +121,7 @@ contract TrancheVault is */ function setReinvestYield(address lender, bool reinvestYield) external { poolConfig.onlyPoolOperator(msg.sender); - userInfos[lender].reinvestYield = reinvestYield; + depositRecords[lender].reinvestYield = reinvestYield; emit ReinvestYieldConfigSet(lender, reinvestYield, msg.sender); } @@ -126,10 +130,10 @@ contract TrancheVault is external view override - returns (RedemptionSummary memory redemptionSummary) + returns (EpochRedemptionSummary memory redemptionSummary) { uint256 epochId = epochManager.currentEpochId(); - redemptionSummary = redemptionSummaryByEpochId[epochId]; + redemptionSummary = epochRedemptionSummaries[epochId]; } function decimals() public view override returns (uint8) { @@ -141,11 +145,11 @@ contract TrancheVault is } /// @inheritdoc IRedemptionHandler - function executeRedemptionSummary(RedemptionSummary memory summaryProcessed) external { + function executeRedemptionSummary(EpochRedemptionSummary memory summaryProcessed) external { _onlyEpochManager(msg.sender); if (summaryProcessed.totalSharesProcessed > 0) { - redemptionSummaryByEpochId[summaryProcessed.epochId] = summaryProcessed; + epochRedemptionSummaries[summaryProcessed.epochId] = summaryProcessed; // Burn processed shares of LP tokens. ERC20Upgradeable._burn(address(this), summaryProcessed.totalSharesProcessed); // Withdraw underlying tokens from the reserve so that LPs can redeem. @@ -157,13 +161,13 @@ contract TrancheVault is if (unprocessed > 0) { // Move unprocessed redemption to next epoch - RedemptionSummary memory nextRedemptionSummary = RedemptionSummary({ + EpochRedemptionSummary memory nextRedemptionSummary = EpochRedemptionSummary({ epochId: summaryProcessed.epochId + 1, totalSharesRequested: uint96(unprocessed), totalSharesProcessed: 0, totalAmountProcessed: 0 }); - redemptionSummaryByEpochId[nextRedemptionSummary.epochId] = nextRedemptionSummary; + epochRedemptionSummaries[nextRedemptionSummary.epochId] = nextRedemptionSummary; epochIds.push(nextRedemptionSummary.epochId); } @@ -228,15 +232,14 @@ contract TrancheVault is poolSafe.deposit(msg.sender, assets); shares = _convertToShares(assets, trancheAssets); ERC20Upgradeable._mint(receiver, shares); - UserInfo memory userInfo = userInfos[receiver]; - userInfo.principal += uint96(assets); - userInfos[receiver] = userInfo; + DepositRecord memory depositRecord = depositRecords[receiver]; + depositRecord.principal += uint96(assets); + depositRecord.lastDepositTime = uint64(block.timestamp); + depositRecords[receiver] = depositRecord; tranches[trancheIndex] += uint96(assets); pool.updateTranchesAssets(tranches); - lastDepositTime[receiver] = block.timestamp; - emit LiquidityDeposited(msg.sender, receiver, assets, shares); } @@ -248,9 +251,10 @@ contract TrancheVault is if (shares == 0) revert Errors.zeroAmountProvided(); poolConfig.onlyProtocolAndPoolOn(); + DepositRecord memory depositRecord = depositRecords[msg.sender]; if ( block.timestamp < - lastDepositTime[msg.sender] + + depositRecord.lastDepositTime + poolConfig.getLPConfig().withdrawalLockoutPeriodInDays * SECONDS_IN_A_DAY ) revert Errors.withdrawTooSoon(); @@ -267,7 +271,7 @@ contract TrancheVault is ); uint256 currentEpochId = epochManager.currentEpochId(); - RedemptionSummary memory currRedemptionSummary = redemptionSummaryByEpochId[ + EpochRedemptionSummary memory currRedemptionSummary = epochRedemptionSummaries[ currentEpochId ]; if (currRedemptionSummary.totalSharesRequested > 0) { @@ -281,21 +285,22 @@ contract TrancheVault is currRedemptionSummary.epochId = uint64(currentEpochId); currRedemptionSummary.totalSharesRequested = uint96(shares); } - redemptionSummaryByEpochId[currentEpochId] = currRedemptionSummary; + epochRedemptionSummaries[currentEpochId] = currRedemptionSummary; - RedemptionInfo memory lenderRedemptionInfo = _getLatestRedemptionInfo( + LenderRedemptionRecord memory lenderRedemptionRecord = _getLatestLenderRedemptionRecord( msg.sender, currentEpochId ); - lenderRedemptionInfo.numSharesRequested += uint96(shares); + lenderRedemptionRecord.numSharesRequested += uint96(shares); uint256 principalRequested = convertToAssets(shares); - lenderRedemptionInfo.principalRequested += uint96(principalRequested); - redemptionInfoByLender[msg.sender] = lenderRedemptionInfo; - UserInfo memory userInfo = userInfos[msg.sender]; - userInfo.principal = uint96( - userInfo.principal > principalRequested ? userInfo.principal - principalRequested : 0 + lenderRedemptionRecord.principalRequested += uint96(principalRequested); + lenderRedemptionRecords[msg.sender] = lenderRedemptionRecord; + depositRecord.principal = uint96( + depositRecord.principal > principalRequested + ? depositRecord.principal - principalRequested + : 0 ); - userInfos[msg.sender] = userInfo; + depositRecords[msg.sender] = depositRecord; ERC20Upgradeable._transfer(msg.sender, address(this), shares); @@ -311,35 +316,35 @@ contract TrancheVault is poolConfig.onlyProtocolAndPoolOn(); uint256 currentEpochId = epochManager.currentEpochId(); - RedemptionInfo memory lenderRedemptionInfo = _getLatestRedemptionInfo( + LenderRedemptionRecord memory lenderRedemptionRecord = _getLatestLenderRedemptionRecord( msg.sender, currentEpochId ); - if (lenderRedemptionInfo.numSharesRequested < shares) { + if (lenderRedemptionRecord.numSharesRequested < shares) { revert Errors.insufficientSharesForRequest(); } - UserInfo memory userInfo = userInfos[msg.sender]; + DepositRecord memory depositRecord = depositRecords[msg.sender]; // TODO rounding error? - userInfo.principal += - (lenderRedemptionInfo.principalRequested * uint96(shares)) / - lenderRedemptionInfo.numSharesRequested; - userInfos[msg.sender] = userInfo; + depositRecord.principal += + (lenderRedemptionRecord.principalRequested * uint96(shares)) / + lenderRedemptionRecord.numSharesRequested; + depositRecords[msg.sender] = depositRecord; - uint96 newNumSharesRequested = lenderRedemptionInfo.numSharesRequested - uint96(shares); + uint96 newNumSharesRequested = lenderRedemptionRecord.numSharesRequested - uint96(shares); // TODO rounding error? - lenderRedemptionInfo.principalRequested = - (lenderRedemptionInfo.principalRequested * newNumSharesRequested) / - lenderRedemptionInfo.numSharesRequested; - lenderRedemptionInfo.numSharesRequested = newNumSharesRequested; - redemptionInfoByLender[msg.sender] = lenderRedemptionInfo; + lenderRedemptionRecord.principalRequested = + (lenderRedemptionRecord.principalRequested * newNumSharesRequested) / + lenderRedemptionRecord.numSharesRequested; + lenderRedemptionRecord.numSharesRequested = newNumSharesRequested; + lenderRedemptionRecords[msg.sender] = lenderRedemptionRecord; - RedemptionSummary memory currRedemptionSummary = redemptionSummaryByEpochId[ + EpochRedemptionSummary memory currRedemptionSummary = epochRedemptionSummaries[ currentEpochId ]; currRedemptionSummary.totalSharesRequested -= uint96(shares); - redemptionSummaryByEpochId[currentEpochId] = currRedemptionSummary; + epochRedemptionSummaries[currentEpochId] = currRedemptionSummary; ERC20Upgradeable._transfer(address(this), msg.sender, shares); @@ -352,11 +357,11 @@ contract TrancheVault is function disburse() external { poolConfig.onlyProtocolAndPoolOn(); - RedemptionInfo memory info = _getLatestRedemptionInfoFor(msg.sender); - uint256 withdrawable = info.totalAmountProcessed - info.totalAmountWithdrawn; + LenderRedemptionRecord memory record = _getLatestLenderRedemptionRecordFor(msg.sender); + uint256 withdrawable = record.totalAmountProcessed - record.totalAmountWithdrawn; if (withdrawable > 0) { - info.totalAmountWithdrawn += uint96(withdrawable); - redemptionInfoByLender[msg.sender] = info; + record.totalAmountWithdrawn += uint96(withdrawable); + lenderRedemptionRecords[msg.sender] = record; underlyingToken.transfer(msg.sender, withdrawable); emit LenderFundDisbursed(msg.sender, msg.sender, withdrawable); } @@ -374,12 +379,12 @@ contract TrancheVault is address lender = lenders[i]; uint256 shares = ERC20Upgradeable.balanceOf(lender); uint256 assets = (shares * price) / DEFAULT_DECIMALS_FACTOR; - UserInfo memory userInfo = userInfos[lender]; - if (assets > userInfo.principal) { - uint256 yield = assets - userInfo.principal; - if (userInfo.reinvestYield) { - userInfo.principal += uint96(yield); - userInfos[lender] = userInfo; + DepositRecord memory depositRecord = depositRecords[lender]; + if (assets > depositRecord.principal) { + uint256 yield = assets - depositRecord.principal; + if (depositRecord.reinvestYield) { + depositRecord.principal += uint96(yield); + depositRecords[lender] = depositRecord; emit YieldReinvested(lender, yield); } else { // TODO rounding up? @@ -407,10 +412,12 @@ contract TrancheVault is * @notice Returns the withdrawable assets value of the given account */ function withdrawableAssets(address account) external view returns (uint256 assets) { - RedemptionInfo memory lenderRedemptionInfo = _getLatestRedemptionInfoFor(account); + LenderRedemptionRecord memory lenderRedemptionRecord = _getLatestLenderRedemptionRecordFor( + account + ); assets = - lenderRedemptionInfo.totalAmountProcessed - - lenderRedemptionInfo.totalAmountWithdrawn; + lenderRedemptionRecord.totalAmountProcessed - + lenderRedemptionRecord.totalAmountWithdrawn; } /** @@ -418,8 +425,10 @@ contract TrancheVault is * @param account The lender's account */ function cancellableRedemptionShares(address account) external view returns (uint256 shares) { - RedemptionInfo memory lenderRedemptionInfo = _getLatestRedemptionInfoFor(account); - shares = lenderRedemptionInfo.numSharesRequested; + LenderRedemptionRecord memory lenderRedemptionRecord = _getLatestLenderRedemptionRecordFor( + account + ); + shares = lenderRedemptionRecord.numSharesRequested; } function totalAssets() public view returns (uint256) { @@ -457,54 +466,54 @@ contract TrancheVault is function _updateUserWithdrawable(address user) internal returns (uint256 withdrawableAmount) {} - function _getLatestRedemptionInfoFor( + function _getLatestLenderRedemptionRecordFor( address account - ) internal view returns (RedemptionInfo memory lenderRedemptionInfo) { + ) internal view returns (LenderRedemptionRecord memory lenderRedemptionRecord) { uint256 currentEpochId = epochManager.currentEpochId(); - lenderRedemptionInfo = _getLatestRedemptionInfo(account, currentEpochId); + lenderRedemptionRecord = _getLatestLenderRedemptionRecord(account, currentEpochId); } - function _getLatestRedemptionInfo( + function _getLatestLenderRedemptionRecord( address account, uint256 currentEpochId - ) internal view returns (RedemptionInfo memory lenderRedemptionInfo) { - lenderRedemptionInfo = redemptionInfoByLender[account]; - if (lenderRedemptionInfo.lastUpdatedEpochIndex < epochIds.length) { - uint256 epochId = epochIds[lenderRedemptionInfo.lastUpdatedEpochIndex]; + ) internal view returns (LenderRedemptionRecord memory lenderRedemptionRecord) { + lenderRedemptionRecord = lenderRedemptionRecords[account]; + if (lenderRedemptionRecord.lastUpdatedEpochIndex < epochIds.length) { + uint256 epochId = epochIds[lenderRedemptionRecord.lastUpdatedEpochIndex]; if (epochId < currentEpochId) { - lenderRedemptionInfo = _updateRedemptionInfo(lenderRedemptionInfo); + lenderRedemptionRecord = _updateLenderRedemptionRecord(lenderRedemptionRecord); } } } /** - * @notice Brings the redemption information for a lender up-to-date. - * @dev Prior to invoking this function, the lender's redemption info may be outdated, not accurately reflecting + * @notice Brings the redemption record for a lender up-to-date. + * @dev Prior to invoking this function, the lender's redemption record may be outdated, not accurately reflecting * the amount of withdrawable funds. This is due to the potential passage of additional epochs and the * processing of further redemption requests since the lender's last update. This function addresses this - * by iterating through all epochs executed since the last update, ensuring the redemption info is current + * by iterating through all epochs executed since the last update, ensuring the redemption record is current * and accurate. - * @param redemptionInfo The lender's current processed redemption request information. - * @return newRedemptionInfo The lender's updated processed redemption request information. + * @param redemptionRecord The lender's current processed redemption request record. + * @return newRedemptionRecord The lender's updated processed redemption request record. */ - function _updateRedemptionInfo( - RedemptionInfo memory redemptionInfo - ) internal view returns (RedemptionInfo memory newRedemptionInfo) { - newRedemptionInfo = redemptionInfo; + function _updateLenderRedemptionRecord( + LenderRedemptionRecord memory redemptionRecord + ) internal view returns (LenderRedemptionRecord memory newRedemptionRecord) { + newRedemptionRecord = redemptionRecord; uint256 numEpochIds = epochIds.length; - uint256 remainingShares = newRedemptionInfo.numSharesRequested; + uint256 remainingShares = newRedemptionRecord.numSharesRequested; if (remainingShares > 0) { uint256 totalShares = remainingShares; for ( - uint256 i = newRedemptionInfo.lastUpdatedEpochIndex; + uint256 i = newRedemptionRecord.lastUpdatedEpochIndex; i < numEpochIds && remainingShares > 0; i++ ) { uint256 epochId = epochIds[i]; - RedemptionSummary memory summary = redemptionSummaryByEpochId[epochId]; + EpochRedemptionSummary memory summary = epochRedemptionSummaries[epochId]; if (summary.totalSharesProcessed > 0) { // TODO Will there be one decimal unit of rounding error here if it can't be divisible? - newRedemptionInfo.totalAmountProcessed += uint96( + newRedemptionRecord.totalAmountProcessed += uint96( (remainingShares * summary.totalAmountProcessed) / summary.totalSharesRequested ); @@ -514,15 +523,15 @@ contract TrancheVault is summary.totalSharesRequested; } } - newRedemptionInfo.numSharesRequested = uint96(remainingShares); + newRedemptionRecord.numSharesRequested = uint96(remainingShares); if (remainingShares < totalShares) { // Some shares are processed, so the principal requested is reduced proportionally. - newRedemptionInfo.principalRequested = uint96( - (remainingShares * newRedemptionInfo.principalRequested) / totalShares + newRedemptionRecord.principalRequested = uint96( + (remainingShares * newRedemptionRecord.principalRequested) / totalShares ); } } - newRedemptionInfo.lastUpdatedEpochIndex = uint64(numEpochIds - 1); + newRedemptionRecord.lastUpdatedEpochIndex = uint64(numEpochIds - 1); } function _onlyEpochManager(address account) internal view { diff --git a/contracts/TrancheVaultStorage.sol b/contracts/TrancheVaultStorage.sol index c0572acc..8f7f520a 100644 --- a/contracts/TrancheVaultStorage.sol +++ b/contracts/TrancheVaultStorage.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; -import {RedemptionSummary} from "./interfaces/IRedemptionHandler.sol"; +import {EpochRedemptionSummary} from "./interfaces/IRedemptionHandler.sol"; import {IEpochManager} from "./interfaces/IEpochManager.sol"; import {IPool} from "./interfaces/IPool.sol"; import {IPoolSafe} from "./interfaces/IPoolSafe.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract TrancheVaultStorage { - struct RedemptionInfo { + struct LenderRedemptionRecord { // The index of the epoch ID in the epochIds array when the redemption info was last updated. uint64 lastUpdatedEpochIndex; // The number of shares requested for redemption in this epoch @@ -21,11 +21,13 @@ contract TrancheVaultStorage { uint96 totalAmountWithdrawn; } - struct UserInfo { + struct DepositRecord { // The total amount of underlying tokens deposited by the lender uint96 principal; // Whether the lender reinvests the yield bool reinvestYield; + // The last deposit time in this pool + uint64 lastDepositTime; } IERC20 public underlyingToken; @@ -41,15 +43,12 @@ contract TrancheVaultStorage { // Note that the index may not be contiguous: if there is no redemption request, // the ID won't be recorded in this array. uint256[] public epochIds; - mapping(uint256 => RedemptionSummary) public redemptionSummaryByEpochId; + mapping(uint256 => EpochRedemptionSummary) public epochRedemptionSummaries; - mapping(address => RedemptionInfo) public redemptionInfoByLender; + mapping(address => LenderRedemptionRecord) public lenderRedemptionRecords; // This mapping contains the amount of underlying tokens deposited by lenders - mapping(address => UserInfo) public userInfos; - - // Tracks the last deposit time for each lender in this pool - mapping(address => uint256) public lastDepositTime; + mapping(address => DepositRecord) public depositRecords; /** * @dev This empty reserved space is put in place to allow future versions to add new diff --git a/contracts/interfaces/IRedemptionHandler.sol b/contracts/interfaces/IRedemptionHandler.sol index a4ee811d..1fa1bd3e 100644 --- a/contracts/interfaces/IRedemptionHandler.sol +++ b/contracts/interfaces/IRedemptionHandler.sol @@ -2,12 +2,12 @@ pragma solidity ^0.8.0; /** - * @notice RedemptionSummary is a summary of a group of redemption requests. It captures + * @notice EpochRedemptionSummary is a summary of a group of redemption requests. It captures * the total number of shares requested, number of shares actually redeemed and the * associated amount. */ -struct RedemptionSummary { +struct EpochRedemptionSummary { uint64 epochId; // The total number of shares requested for redemption in this epoch uint96 totalSharesRequested; @@ -21,7 +21,7 @@ interface IRedemptionHandler { /** * @notice Returns unprocessed epoch info. */ - function currentRedemptionSummary() external view returns (RedemptionSummary memory); + function currentRedemptionSummary() external view returns (EpochRedemptionSummary memory); /** * @notice Executes the redemption bundle by transferring assets @@ -29,6 +29,6 @@ interface IRedemptionHandler { * have been approved to redeem */ function executeRedemptionSummary( - RedemptionSummary memory processedRedemptionSummary + EpochRedemptionSummary memory processedRedemptionSummary ) external; } diff --git a/test/BaseTest.ts b/test/BaseTest.ts index 73141a23..c2a6bc22 100644 --- a/test/BaseTest.ts +++ b/test/BaseTest.ts @@ -37,7 +37,7 @@ import { CreditConfigStruct, CreditConfigStructOutput, } from "../typechain-types/contracts/credit/CreditManager"; -import { RedemptionSummaryStruct } from "../typechain-types/contracts/interfaces/IRedemptionHandler"; +import { EpochRedemptionSummaryStruct } from "../typechain-types/contracts/interfaces/IRedemptionHandler"; import { getLatestBlock, maxBigNumber, minBigNumber, sumBNArray, toToken } from "./TestUtils"; export type CreditContractType = @@ -980,7 +980,7 @@ export class ProfitAndLossCalculator { } export function checkRedemptionSummary( - redemptionSummary: RedemptionSummaryStruct, + redemptionSummary: EpochRedemptionSummaryStruct, epochId: BN, totalSharesRequested: BN, totalSharesProcessed: BN = BN.from(0), @@ -1082,7 +1082,7 @@ export class EpochChecker { private async checkCurrentEpochEmpty(trancheContract: TrancheVault) { const epochId = await this.epochManagerContract.currentEpochId(); - const epoch = await trancheContract.redemptionSummaryByEpochId(epochId); + const epoch = await trancheContract.epochRedemptionSummaries(epochId); checkRedemptionSummary(epoch, BN.from(0), BN.from(0), BN.from(0), BN.from(0)); return epochId; } @@ -1095,7 +1095,7 @@ export class EpochChecker { delta: number = 0, ) { const epochId = await this.epochManagerContract.currentEpochId(); - const epoch = await trancheContract.redemptionSummaryByEpochId(epochId); + const epoch = await trancheContract.epochRedemptionSummaries(epochId); checkRedemptionSummary( epoch, epochId, @@ -1115,7 +1115,7 @@ export class EpochChecker { amountProcessed: BN = BN.from(0), delta: number = 0, ) { - const epoch = await trancheContract.redemptionSummaryByEpochId(epochId); + const epoch = await trancheContract.epochRedemptionSummaries(epochId); checkRedemptionSummary( epoch, epochId, @@ -1717,7 +1717,7 @@ export function calcPoolFees( return [accruedIncomes, remainingProfit.sub(poolOwnerIncome).sub(eaIncome)]; } -export async function checkRedemptionInfoByLender( +export async function checkRedemptionRecordByLender( trancheVaultContract: TrancheVault, lender: SignerWithAddress, lastUpdatedEpochIndex: BN | number, @@ -1727,9 +1727,9 @@ export async function checkRedemptionInfoByLender( totalAmountWithdrawn: BN = BN.from(0), delta: number = 0, ) { - const redemptionInfo = await trancheVaultContract.redemptionInfoByLender(lender.address); - checkRedemptionInfo( - redemptionInfo, + const redemptionRecord = await trancheVaultContract.lenderRedemptionRecords(lender.address); + checkRedemptionRecord( + redemptionRecord, lastUpdatedEpochIndex, numSharesRequested, principalRequested, @@ -1739,7 +1739,7 @@ export async function checkRedemptionInfoByLender( ); } -type RedemptionInfoStructOutput = [BN, BN, BN, BN, BN] & { +type RedemptionRecordStructOutput = [BN, BN, BN, BN, BN] & { lastUpdatedEpochIndex: BN; numSharesRequested: BN; principalRequested: BN; @@ -1747,8 +1747,8 @@ type RedemptionInfoStructOutput = [BN, BN, BN, BN, BN] & { totalAmountWithdrawn: BN; }; -export function checkRedemptionInfo( - redemptionInfo: RedemptionInfoStructOutput, +export function checkRedemptionRecord( + redemptionRecord: RedemptionRecordStructOutput, lastUpdatedEpochIndex: BN | number, numSharesRequested: BN = BN.from(0), principalRequested: BN = BN.from(0), @@ -1756,9 +1756,9 @@ export function checkRedemptionInfo( totalAmountWithdrawn: BN = BN.from(0), delta: number = 0, ) { - expect(redemptionInfo.lastUpdatedEpochIndex).to.be.closeTo(lastUpdatedEpochIndex, delta); - expect(redemptionInfo.numSharesRequested).to.be.closeTo(numSharesRequested, delta); - expect(redemptionInfo.principalRequested).to.be.closeTo(principalRequested, delta); - expect(redemptionInfo.totalAmountProcessed).to.be.closeTo(totalAmountProcessed, delta); - expect(redemptionInfo.totalAmountWithdrawn).to.be.closeTo(totalAmountWithdrawn, delta); + expect(redemptionRecord.lastUpdatedEpochIndex).to.be.closeTo(lastUpdatedEpochIndex, delta); + expect(redemptionRecord.numSharesRequested).to.be.closeTo(numSharesRequested, delta); + expect(redemptionRecord.principalRequested).to.be.closeTo(principalRequested, delta); + expect(redemptionRecord.totalAmountProcessed).to.be.closeTo(totalAmountProcessed, delta); + expect(redemptionRecord.totalAmountWithdrawn).to.be.closeTo(totalAmountWithdrawn, delta); } diff --git a/test/TrancheVaultTest.ts b/test/TrancheVaultTest.ts index 0939704b..6f6e0c02 100644 --- a/test/TrancheVaultTest.ts +++ b/test/TrancheVaultTest.ts @@ -24,7 +24,7 @@ import { EpochChecker, FeeCalculator, PnLCalculator, - checkRedemptionInfoByLender, + checkRedemptionRecordByLender, deployAndSetupPoolContracts, deployProtocolContracts, } from "./BaseTest"; @@ -70,19 +70,22 @@ let poolConfigContract: PoolConfig, let epochChecker: EpochChecker, feeCalculator: FeeCalculator; -type UserInfoStructOutput = [BN, boolean] & { +type DepositRecordStructOutput = [BN, boolean, BN] & { principal: BN; reinvestYield: boolean; + lastDepositTime: BN; }; -function checkUserInfo( - userInfo: UserInfoStructOutput, +function checkDepositRecord( + depositRecord: DepositRecordStructOutput, principal: BN = BN.from(0), reinvestYield: boolean = false, + lastDepositTime: BN = BN.from(0), delta: number = 0, ) { - expect(userInfo.principal).to.be.closeTo(principal, delta); - expect(userInfo.reinvestYield).to.equal(reinvestYield); + expect(depositRecord.principal).to.be.closeTo(principal, delta); + expect(depositRecord.reinvestYield).to.equal(reinvestYield); + expect(depositRecord.lastDepositTime).to.be.closeTo(lastDepositTime, 0); } async function mockDistributePnL(profit: BN, loss: BN, lossRecovery: BN) { @@ -187,8 +190,10 @@ describe("TrancheVault Test", function () { await juniorTrancheVaultContract.hasRole(role, defaultDeployer.address), ).to.equal(true); - let userInfo = await juniorTrancheVaultContract.userInfos(defaultDeployer.address); - checkUserInfo(userInfo); + let depositRecord = await juniorTrancheVaultContract.depositRecords( + defaultDeployer.address, + ); + checkDepositRecord(depositRecord); }); it("Should not allow non-Operator to remove a lender", async function () { @@ -204,8 +209,10 @@ describe("TrancheVault Test", function () { .connect(defaultDeployer) .addApprovedLender(defaultDeployer.address, true); - let userInfo = await juniorTrancheVaultContract.userInfos(defaultDeployer.address); - checkUserInfo(userInfo, BN.from(0), true); + let depositRecord = await juniorTrancheVaultContract.depositRecords( + defaultDeployer.address, + ); + checkDepositRecord(depositRecord, BN.from(0), true); role = await juniorTrancheVaultContract.LENDER_ROLE(); await expect( @@ -219,8 +226,10 @@ describe("TrancheVault Test", function () { expect( await juniorTrancheVaultContract.hasRole(role, defaultDeployer.address), ).to.equal(false); - userInfo = await juniorTrancheVaultContract.userInfos(defaultDeployer.address); - checkUserInfo(userInfo); + depositRecord = await juniorTrancheVaultContract.depositRecords( + defaultDeployer.address, + ); + checkDepositRecord(depositRecord); }); }); @@ -349,6 +358,10 @@ describe("TrancheVault Test", function () { let lenderBalanceBeforeJuniorDeposit = await mockTokenContract.balanceOf( lender.address, ); + + let block = await getLatestBlock(); + let ts = block.timestamp + 5; + await setNextBlockTimestamp(ts); await expect( juniorTrancheVaultContract.connect(lender).deposit(juniorAmount, lender.address), ) @@ -371,9 +384,9 @@ describe("TrancheVault Test", function () { expect(await mockTokenContract.balanceOf(lender.address)).to.equal( lenderBalanceBeforeJuniorDeposit.sub(juniorAmount), ); - let userInfo = await juniorTrancheVaultContract.userInfos(lender.address); - checkUserInfo(userInfo, juniorAmount, true); - let lenderPrincipal = userInfo.principal; + let depositRecord = await juniorTrancheVaultContract.depositRecords(lender.address); + checkDepositRecord(depositRecord, juniorAmount, true, BN.from(ts)); + let lenderPrincipal = depositRecord.principal; // Let lender makes the deposit, but send the token to lender2. const seniorAmount = toToken(10_000); @@ -381,6 +394,8 @@ describe("TrancheVault Test", function () { lender.address, ); + ts = ts + 5; + await setNextBlockTimestamp(ts); await expect( seniorTrancheVaultContract.connect(lender).deposit(seniorAmount, lender2.address), ) @@ -395,8 +410,8 @@ describe("TrancheVault Test", function () { expect(await mockTokenContract.balanceOf(lender.address)).to.equal( lenderBalanceBeforeSeniorDeposit.sub(seniorAmount), ); - userInfo = await seniorTrancheVaultContract.userInfos(lender2.address); - checkUserInfo(userInfo, seniorAmount, true); + depositRecord = await seniorTrancheVaultContract.depositRecords(lender2.address); + checkDepositRecord(depositRecord, seniorAmount, true, BN.from(ts)); poolAssets = poolAssets.add(seniorAmount); // Lender deposits in junior tranche again. @@ -405,6 +420,8 @@ describe("TrancheVault Test", function () { const juniorTotalAssets = await juniorTrancheVaultContract.totalAssets(); const juniorTotalShares = await juniorTrancheVaultContract.totalSupply(); const lenderJuniorShares = await juniorTrancheVaultContract.balanceOf(lender.address); + ts = ts + 5; + await setNextBlockTimestamp(ts); await expect( juniorTrancheVaultContract.connect(lender).deposit(juniorAmount, lender.address), ) @@ -423,8 +440,13 @@ describe("TrancheVault Test", function () { expect(await mockTokenContract.balanceOf(lender.address)).to.equal( lenderBalanceBeforeJuniorDeposit.sub(juniorAmount), ); - userInfo = await juniorTrancheVaultContract.userInfos(lender.address); - checkUserInfo(userInfo, lenderPrincipal.add(juniorAmount), true); + depositRecord = await juniorTrancheVaultContract.depositRecords(lender.address); + checkDepositRecord( + depositRecord, + lenderPrincipal.add(juniorAmount), + true, + BN.from(ts), + ); }); describe("When there is PnL", function () { @@ -487,6 +509,9 @@ describe("TrancheVault Test", function () { .div(juniorAssets); // Distribute profit, loss and loss recovery in the pool so that LP tokens changes in value. await creditContract.mockDistributePnL(profit, loss, lossRecovery); + let block = await getLatestBlock(); + let ts = block.timestamp + 3; + await setNextBlockTimestamp(ts); await expect( juniorTrancheVaultContract .connect(lender3) @@ -511,14 +536,18 @@ describe("TrancheVault Test", function () { expect(await juniorTrancheVaultContract.balanceOf(lender3.address)).to.equal( expectedNewJuniorShares, ); - let userInfo = await juniorTrancheVaultContract.userInfos(lender3.address); - checkUserInfo(userInfo, juniorAmount, true); + let depositRecord = await juniorTrancheVaultContract.depositRecords( + lender3.address, + ); + checkDepositRecord(depositRecord, juniorAmount, true, BN.from(ts)); // Then check the senior tranche. const expectedSeniorAssets = seniorAssets.add(seniorAmount); const expectedNewSeniorShares = seniorAmount .mul(initialSeniorShares) .div(seniorAssets); + ts = ts + 3; + await setNextBlockTimestamp(ts); await expect( seniorTrancheVaultContract .connect(lender4) @@ -542,8 +571,8 @@ describe("TrancheVault Test", function () { expect(await seniorTrancheVaultContract.balanceOf(lender4.address)).to.equal( expectedNewSeniorShares, ); - userInfo = await seniorTrancheVaultContract.userInfos(lender4.address); - checkUserInfo(userInfo, seniorAmount, true); + depositRecord = await seniorTrancheVaultContract.depositRecords(lender4.address); + checkDepositRecord(depositRecord, seniorAmount, true, BN.from(ts)); } it("Should mint the correct number of LP tokens if there is profit in the pool", async function () { @@ -712,8 +741,9 @@ describe("TrancheVault Test", function () { const shares = toToken(10_000); const currentEpochId = await epochManagerContract.currentEpochId(); let balance = await juniorTrancheVaultContract.balanceOf(lender.address); - let principal = (await juniorTrancheVaultContract.userInfos(lender.address)) - .principal; + let principal = ( + await juniorTrancheVaultContract.depositRecords(lender.address) + ).principal; await expect( juniorTrancheVaultContract.connect(lender).addRedemptionRequest(shares), ) @@ -723,10 +753,11 @@ describe("TrancheVault Test", function () { balance.sub(shares), ); expect( - (await juniorTrancheVaultContract.userInfos(lender.address)).principal, + (await juniorTrancheVaultContract.depositRecords(lender.address)) + .principal, ).to.equal(principal.sub(shares)); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender, 0, @@ -746,7 +777,7 @@ describe("TrancheVault Test", function () { // Lender requests redemption again balance = await juniorTrancheVaultContract.balanceOf(lender.address); - principal = (await juniorTrancheVaultContract.userInfos(lender.address)) + principal = (await juniorTrancheVaultContract.depositRecords(lender.address)) .principal; await expect( juniorTrancheVaultContract.connect(lender).addRedemptionRequest(shares), @@ -757,10 +788,11 @@ describe("TrancheVault Test", function () { balance.sub(shares), ); expect( - (await juniorTrancheVaultContract.userInfos(lender.address)).principal, + (await juniorTrancheVaultContract.depositRecords(lender.address)) + .principal, ).to.equal(principal.sub(shares)); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender, 0, @@ -781,7 +813,7 @@ describe("TrancheVault Test", function () { // Lender2 requests redemption balance = await juniorTrancheVaultContract.balanceOf(lender2.address); - principal = (await juniorTrancheVaultContract.userInfos(lender2.address)) + principal = (await juniorTrancheVaultContract.depositRecords(lender2.address)) .principal; await expect( juniorTrancheVaultContract.connect(lender2).addRedemptionRequest(shares), @@ -792,17 +824,18 @@ describe("TrancheVault Test", function () { balance.sub(shares), ); expect( - (await juniorTrancheVaultContract.userInfos(lender2.address)).principal, + (await juniorTrancheVaultContract.depositRecords(lender2.address)) + .principal, ).to.equal(principal.sub(shares)); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender2, 0, shares, shares, ); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender, 0, @@ -826,8 +859,9 @@ describe("TrancheVault Test", function () { const shares = toToken(10_000); let currentEpochId = await epochManagerContract.currentEpochId(); let balance = await juniorTrancheVaultContract.balanceOf(lender.address); - let principal = (await juniorTrancheVaultContract.userInfos(lender.address)) - .principal; + let principal = ( + await juniorTrancheVaultContract.depositRecords(lender.address) + ).principal; await expect( juniorTrancheVaultContract.connect(lender).addRedemptionRequest(shares), ) @@ -837,10 +871,11 @@ describe("TrancheVault Test", function () { balance.sub(shares), ); expect( - (await juniorTrancheVaultContract.userInfos(lender.address)).principal, + (await juniorTrancheVaultContract.depositRecords(lender.address)) + .principal, ).to.equal(principal.sub(shares)); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender, 0, @@ -878,7 +913,7 @@ describe("TrancheVault Test", function () { // Lender requests redemption in next epoch balance = await juniorTrancheVaultContract.balanceOf(lender.address); - principal = (await juniorTrancheVaultContract.userInfos(lender.address)) + principal = (await juniorTrancheVaultContract.depositRecords(lender.address)) .principal; await expect( juniorTrancheVaultContract.connect(lender).addRedemptionRequest(shares), @@ -889,10 +924,11 @@ describe("TrancheVault Test", function () { balance.sub(shares), ); expect( - (await juniorTrancheVaultContract.userInfos(lender.address)).principal, + (await juniorTrancheVaultContract.depositRecords(lender.address)) + .principal, ).to.equal(principal.sub(shares)); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender, 1, @@ -913,7 +949,7 @@ describe("TrancheVault Test", function () { // Lender2 requests redemption balance = await juniorTrancheVaultContract.balanceOf(lender2.address); - principal = (await juniorTrancheVaultContract.userInfos(lender2.address)) + principal = (await juniorTrancheVaultContract.depositRecords(lender2.address)) .principal; await expect( juniorTrancheVaultContract.connect(lender2).addRedemptionRequest(shares), @@ -924,10 +960,11 @@ describe("TrancheVault Test", function () { balance.sub(shares), ); expect( - (await juniorTrancheVaultContract.userInfos(lender2.address)).principal, + (await juniorTrancheVaultContract.depositRecords(lender2.address)) + .principal, ).to.equal(principal.sub(shares)); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender2, 1, @@ -958,7 +995,7 @@ describe("TrancheVault Test", function () { // Lender2 requests redemption in next epoch balance = await juniorTrancheVaultContract.balanceOf(lender2.address); - principal = (await juniorTrancheVaultContract.userInfos(lender2.address)) + principal = (await juniorTrancheVaultContract.depositRecords(lender2.address)) .principal; await expect( juniorTrancheVaultContract.connect(lender2).addRedemptionRequest(shares), @@ -969,10 +1006,11 @@ describe("TrancheVault Test", function () { balance.sub(shares), ); expect( - (await juniorTrancheVaultContract.userInfos(lender2.address)).principal, + (await juniorTrancheVaultContract.depositRecords(lender2.address)) + .principal, ).to.equal(principal.sub(shares)); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender2, 2, @@ -1005,7 +1043,7 @@ describe("TrancheVault Test", function () { ); const sharesRequested = balance.sub(1); let principal = ( - await seniorTrancheVaultContract.userInfos(poolOwnerTreasury.address) + await seniorTrancheVaultContract.depositRecords(poolOwnerTreasury.address) ).principal; await expect( seniorTrancheVaultContract @@ -1018,11 +1056,14 @@ describe("TrancheVault Test", function () { await seniorTrancheVaultContract.balanceOf(poolOwnerTreasury.address), ).to.equal(balance.sub(sharesRequested)); expect( - (await seniorTrancheVaultContract.userInfos(poolOwnerTreasury.address)) - .principal, + ( + await seniorTrancheVaultContract.depositRecords( + poolOwnerTreasury.address, + ) + ).principal, ).to.equal(principal.sub(sharesRequested)); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( seniorTrancheVaultContract, poolOwnerTreasury, 0, @@ -1043,7 +1084,7 @@ describe("TrancheVault Test", function () { ); const sharesRequested = balance.sub(1); let principal = ( - await seniorTrancheVaultContract.userInfos(evaluationAgent.address) + await seniorTrancheVaultContract.depositRecords(evaluationAgent.address) ).principal; await expect( seniorTrancheVaultContract @@ -1056,11 +1097,11 @@ describe("TrancheVault Test", function () { await seniorTrancheVaultContract.balanceOf(evaluationAgent.address), ).to.equal(balance.sub(sharesRequested)); expect( - (await seniorTrancheVaultContract.userInfos(evaluationAgent.address)) + (await seniorTrancheVaultContract.depositRecords(evaluationAgent.address)) .principal, ).to.equal(principal.sub(sharesRequested)); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( seniorTrancheVaultContract, evaluationAgent, 0, @@ -1135,30 +1176,28 @@ describe("TrancheVault Test", function () { let currentEpochId = await epochManagerContract.currentEpochId(); let balance = await juniorTrancheVaultContract.balanceOf(lender.address); let epochBefore = - await juniorTrancheVaultContract.redemptionSummaryByEpochId( - currentEpochId, - ); + await juniorTrancheVaultContract.epochRedemptionSummaries(currentEpochId); let cancellableRedemptionSharesBefore = await juniorTrancheVaultContract.cancellableRedemptionShares( lender.address, ); - let principal = (await juniorTrancheVaultContract.userInfos(lender.address)) - .principal; + let principal = ( + await juniorTrancheVaultContract.depositRecords(lender.address) + ).principal; await expect( juniorTrancheVaultContract.connect(lender).cancelRedemptionRequest(shares), ) .to.emit(juniorTrancheVaultContract, "RedemptionRequestRemoved") .withArgs(lender.address, shares, currentEpochId); let epochAfter = - await juniorTrancheVaultContract.redemptionSummaryByEpochId( - currentEpochId, - ); + await juniorTrancheVaultContract.epochRedemptionSummaries(currentEpochId); let cancellableRedemptionSharesAfter = await juniorTrancheVaultContract.cancellableRedemptionShares( lender.address, ); expect( - (await juniorTrancheVaultContract.userInfos(lender.address)).principal, + (await juniorTrancheVaultContract.depositRecords(lender.address)) + .principal, ).to.equal(principal.add(shares)); expect(await juniorTrancheVaultContract.balanceOf(lender.address)).to.equal( balance.add(shares), @@ -1170,7 +1209,7 @@ describe("TrancheVault Test", function () { cancellableRedemptionSharesBefore.sub(cancellableRedemptionSharesAfter), ).to.equal(shares); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender, 0, @@ -1194,14 +1233,12 @@ describe("TrancheVault Test", function () { // Lender removes redemption request balance = await juniorTrancheVaultContract.balanceOf(lender.address); epochBefore = - await juniorTrancheVaultContract.redemptionSummaryByEpochId( - currentEpochId, - ); + await juniorTrancheVaultContract.epochRedemptionSummaries(currentEpochId); cancellableRedemptionSharesBefore = await juniorTrancheVaultContract.cancellableRedemptionShares( lender.address, ); - principal = (await juniorTrancheVaultContract.userInfos(lender.address)) + principal = (await juniorTrancheVaultContract.depositRecords(lender.address)) .principal; await expect( juniorTrancheVaultContract.connect(lender).cancelRedemptionRequest(shares), @@ -1209,16 +1246,15 @@ describe("TrancheVault Test", function () { .to.emit(juniorTrancheVaultContract, "RedemptionRequestRemoved") .withArgs(lender.address, shares, currentEpochId); epochAfter = - await juniorTrancheVaultContract.redemptionSummaryByEpochId( - currentEpochId, - ); + await juniorTrancheVaultContract.epochRedemptionSummaries(currentEpochId); cancellableRedemptionSharesAfter = await juniorTrancheVaultContract.cancellableRedemptionShares( lender.address, ); expect( - (await juniorTrancheVaultContract.userInfos(lender.address)).principal, + (await juniorTrancheVaultContract.depositRecords(lender.address)) + .principal, ).to.equal(principal.add(shares)); expect(await juniorTrancheVaultContract.balanceOf(lender.address)).to.equal( balance.add(shares), @@ -1230,7 +1266,7 @@ describe("TrancheVault Test", function () { cancellableRedemptionSharesBefore.sub(cancellableRedemptionSharesAfter), ).to.equal(shares); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender, 1, @@ -1264,7 +1300,7 @@ describe("TrancheVault Test", function () { await juniorTrancheVaultContract.cancellableRedemptionShares( lender2.address, ); - principal = (await juniorTrancheVaultContract.userInfos(lender2.address)) + principal = (await juniorTrancheVaultContract.depositRecords(lender2.address)) .principal; await expect( juniorTrancheVaultContract @@ -1279,7 +1315,8 @@ describe("TrancheVault Test", function () { ); expect( - (await juniorTrancheVaultContract.userInfos(lender2.address)).principal, + (await juniorTrancheVaultContract.depositRecords(lender2.address)) + .principal, ).to.equal(principal.add(allShares)); expect(await juniorTrancheVaultContract.balanceOf(lender2.address)).to.equal( balance.add(allShares), @@ -1289,7 +1326,7 @@ describe("TrancheVault Test", function () { ).to.equal(allShares); await epochChecker.checkJuniorRedemptionSummaryById(currentEpochId); - await checkRedemptionInfoByLender(juniorTrancheVaultContract, lender2, 2); + await checkRedemptionRecordByLender(juniorTrancheVaultContract, lender2, 2); }); }); @@ -1304,8 +1341,9 @@ describe("TrancheVault Test", function () { let principal = await juniorTrancheVaultContract.convertToAssets(shares); let currentEpochId = await epochManagerContract.currentEpochId(); let balance = await juniorTrancheVaultContract.balanceOf(lender.address); - let allPrincipal = (await juniorTrancheVaultContract.userInfos(lender.address)) - .principal; + let allPrincipal = ( + await juniorTrancheVaultContract.depositRecords(lender.address) + ).principal; await expect( juniorTrancheVaultContract.connect(lender).addRedemptionRequest(shares), ) @@ -1315,9 +1353,10 @@ describe("TrancheVault Test", function () { balance.sub(shares), ); expect( - (await juniorTrancheVaultContract.userInfos(lender.address)).principal, + (await juniorTrancheVaultContract.depositRecords(lender.address)) + .principal, ).to.equal(allPrincipal.sub(principal)); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender, 0, @@ -1341,8 +1380,9 @@ describe("TrancheVault Test", function () { shares = toToken(13_000); principal = await juniorTrancheVaultContract.convertToAssets(shares); balance = await juniorTrancheVaultContract.balanceOf(lender.address); - allPrincipal = (await juniorTrancheVaultContract.userInfos(lender.address)) - .principal; + allPrincipal = ( + await juniorTrancheVaultContract.depositRecords(lender.address) + ).principal; await expect( juniorTrancheVaultContract.connect(lender).addRedemptionRequest(shares), ) @@ -1352,9 +1392,10 @@ describe("TrancheVault Test", function () { balance.sub(shares), ); expect( - (await juniorTrancheVaultContract.userInfos(lender.address)).principal, + (await juniorTrancheVaultContract.depositRecords(lender.address)) + .principal, ).to.equal(allPrincipal.sub(principal)); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender, 0, @@ -1401,8 +1442,9 @@ describe("TrancheVault Test", function () { shares = toToken(10_000); principal = principalRequested.mul(shares).div(sharesRequested); balance = await juniorTrancheVaultContract.balanceOf(lender.address); - allPrincipal = (await juniorTrancheVaultContract.userInfos(lender.address)) - .principal; + allPrincipal = ( + await juniorTrancheVaultContract.depositRecords(lender.address) + ).principal; await expect( juniorTrancheVaultContract.connect(lender).cancelRedemptionRequest(shares), ) @@ -1412,9 +1454,10 @@ describe("TrancheVault Test", function () { balance.add(shares), ); expect( - (await juniorTrancheVaultContract.userInfos(lender.address)).principal, + (await juniorTrancheVaultContract.depositRecords(lender.address)) + .principal, ).to.equal(allPrincipal.add(principal)); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender, 1, @@ -1441,8 +1484,9 @@ describe("TrancheVault Test", function () { let principal = await juniorTrancheVaultContract.convertToAssets(shares); let currentEpochId = await epochManagerContract.currentEpochId(); let balance = await juniorTrancheVaultContract.balanceOf(lender.address); - let allPrincipal = (await juniorTrancheVaultContract.userInfos(lender.address)) - .principal; + let allPrincipal = ( + await juniorTrancheVaultContract.depositRecords(lender.address) + ).principal; await expect( juniorTrancheVaultContract.connect(lender).addRedemptionRequest(shares), ) @@ -1452,9 +1496,10 @@ describe("TrancheVault Test", function () { balance.sub(shares), ); expect( - (await juniorTrancheVaultContract.userInfos(lender.address)).principal, + (await juniorTrancheVaultContract.depositRecords(lender.address)) + .principal, ).to.equal(allPrincipal.sub(principal)); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender, 0, @@ -1513,8 +1558,9 @@ describe("TrancheVault Test", function () { principal = await juniorTrancheVaultContract.convertToAssets(shares); currentEpochId = await epochManagerContract.currentEpochId(); balance = await juniorTrancheVaultContract.balanceOf(lender.address); - allPrincipal = (await juniorTrancheVaultContract.userInfos(lender.address)) - .principal; + allPrincipal = ( + await juniorTrancheVaultContract.depositRecords(lender.address) + ).principal; await expect( juniorTrancheVaultContract.connect(lender).addRedemptionRequest(shares), ) @@ -1524,9 +1570,10 @@ describe("TrancheVault Test", function () { balance.sub(shares), ); expect( - (await juniorTrancheVaultContract.userInfos(lender.address)).principal, + (await juniorTrancheVaultContract.depositRecords(lender.address)) + .principal, ).to.equal(allPrincipal.sub(principal)); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender, 1, @@ -1550,8 +1597,9 @@ describe("TrancheVault Test", function () { shares = toToken(10_000); principal = principalRequested.mul(shares).div(sharesRequested); balance = await juniorTrancheVaultContract.balanceOf(lender.address); - allPrincipal = (await juniorTrancheVaultContract.userInfos(lender.address)) - .principal; + allPrincipal = ( + await juniorTrancheVaultContract.depositRecords(lender.address) + ).principal; await expect( juniorTrancheVaultContract.connect(lender).cancelRedemptionRequest(shares), ) @@ -1561,9 +1609,10 @@ describe("TrancheVault Test", function () { balance.add(shares), ); expect( - (await juniorTrancheVaultContract.userInfos(lender.address)).principal, + (await juniorTrancheVaultContract.depositRecords(lender.address)) + .principal, ).to.equal(allPrincipal.add(principal)); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender, 1, @@ -1616,7 +1665,7 @@ describe("TrancheVault Test", function () { ).to.equal(shares); let balanceBefore = await mockTokenContract.balanceOf(lender.address); - let principal = (await seniorTrancheVaultContract.userInfos(lender.address)) + let principal = (await seniorTrancheVaultContract.depositRecords(lender.address)) .principal; await expect(seniorTrancheVaultContract.connect(lender).disburse()) .to.emit(seniorTrancheVaultContract, "LenderFundDisbursed") @@ -1625,9 +1674,9 @@ describe("TrancheVault Test", function () { balanceBefore.add(shares), ); expect( - (await seniorTrancheVaultContract.userInfos(lender.address)).principal, + (await seniorTrancheVaultContract.depositRecords(lender.address)).principal, ).to.equal(principal); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( seniorTrancheVaultContract, lender, 0, @@ -1638,7 +1687,7 @@ describe("TrancheVault Test", function () { ); balanceBefore = await mockTokenContract.balanceOf(lender2.address); - principal = (await seniorTrancheVaultContract.userInfos(lender2.address)) + principal = (await seniorTrancheVaultContract.depositRecords(lender2.address)) .principal; await expect(seniorTrancheVaultContract.connect(lender2).disburse()) .to.emit(seniorTrancheVaultContract, "LenderFundDisbursed") @@ -1647,9 +1696,9 @@ describe("TrancheVault Test", function () { balanceBefore.add(shares), ); expect( - (await seniorTrancheVaultContract.userInfos(lender2.address)).principal, + (await seniorTrancheVaultContract.depositRecords(lender2.address)).principal, ).to.equal(principal); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( seniorTrancheVaultContract, lender2, 0, @@ -1715,7 +1764,7 @@ describe("TrancheVault Test", function () { balanceBefore.add(withdrawable), ); let allWithdrawable = withdrawable; - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( seniorTrancheVaultContract, lender, 1, @@ -1733,7 +1782,7 @@ describe("TrancheVault Test", function () { balanceBefore.add(withdrawable2), ); let allWithdrawable2 = withdrawable2; - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( seniorTrancheVaultContract, lender2, 1, @@ -1766,7 +1815,7 @@ describe("TrancheVault Test", function () { lastEpoch = await epochManagerContract.currentEpoch(); let totalSharesRequested = ( - await seniorTrancheVaultContract.redemptionSummaryByEpochId(lastEpoch.id) + await seniorTrancheVaultContract.epochRedemptionSummaries(lastEpoch.id) ).totalSharesRequested; ts = lastEpoch.endTime.toNumber() + 60 * 5; await setNextBlockTimestamp(ts); @@ -1789,7 +1838,7 @@ describe("TrancheVault Test", function () { balanceBefore.add(withdrawable), ); allWithdrawable = allWithdrawable.add(withdrawable); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( seniorTrancheVaultContract, lender, 2, @@ -1807,7 +1856,7 @@ describe("TrancheVault Test", function () { balanceBefore.add(withdrawable2), ); allWithdrawable2 = allWithdrawable2.add(withdrawable2); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( seniorTrancheVaultContract, lender2, 2, @@ -1849,7 +1898,7 @@ describe("TrancheVault Test", function () { balanceBefore.add(allShares), ); allWithdrawable = allWithdrawable.add(allShares); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( seniorTrancheVaultContract, lender, 2, @@ -1867,7 +1916,7 @@ describe("TrancheVault Test", function () { balanceBefore.add(allShares2), ); allWithdrawable2 = allWithdrawable2.add(allShares2); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( seniorTrancheVaultContract, lender2, 2, @@ -1938,7 +1987,7 @@ describe("TrancheVault Test", function () { expect(await mockTokenContract.balanceOf(lender.address)).to.equal( balance.add(amountProcessed), ); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender, 1, @@ -2002,7 +2051,7 @@ describe("TrancheVault Test", function () { expect(await mockTokenContract.balanceOf(lender.address)).to.equal( balance.add(amountProcessed), ); - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, lender, 1, @@ -2133,7 +2182,7 @@ describe("TrancheVault Test", function () { async syncPrincipal(trancheVaultContract: TrancheVault) { this.principal = ( - await trancheVaultContract.userInfos(this.lender.getAddress()) + await trancheVaultContract.depositRecords(this.lender.getAddress()) )[0]; } } @@ -2364,16 +2413,16 @@ describe("TrancheVault Test", function () { expect(await mockTokenContract.balanceOf(lender2.address)).to.equal(lender2Assets); expect(await mockTokenContract.balanceOf(lender3.address)).to.equal(lender3Assets); expect(await mockTokenContract.balanceOf(lender4.address)).to.equal(lender4Assets); - expect((await juniorTrancheVaultContract.userInfos(lender.address))[0]).to.equal( + expect((await juniorTrancheVaultContract.depositRecords(lender.address))[0]).to.equal( lenders[0].principal, ); - expect((await juniorTrancheVaultContract.userInfos(lender2.address))[0]).to.equal( + expect((await juniorTrancheVaultContract.depositRecords(lender2.address))[0]).to.equal( lenders[1].principal, ); - expect((await juniorTrancheVaultContract.userInfos(lender3.address))[0]).to.equal( + expect((await juniorTrancheVaultContract.depositRecords(lender3.address))[0]).to.equal( lenders[2].principal, ); - expect((await juniorTrancheVaultContract.userInfos(lender4.address))[0]).to.equal( + expect((await juniorTrancheVaultContract.depositRecords(lender4.address))[0]).to.equal( lenders[3].principal, ); diff --git a/test/integration/LenderIntegrationTest.ts b/test/integration/LenderIntegrationTest.ts index a8829144..53a519ec 100644 --- a/test/integration/LenderIntegrationTest.ts +++ b/test/integration/LenderIntegrationTest.ts @@ -33,7 +33,7 @@ import { ProfitAndLossCalculator, SeniorYieldTracker, calcLateFee, - checkRedemptionInfoByLender, + checkRedemptionRecordByLender, checkSeniorYieldTrackersMatch, deployPoolContracts, deployProtocolContracts, @@ -447,13 +447,13 @@ async function testYieldPayout() { oldBalances[i].add(interests[i]), ); jLenderPrincipals[i] = ( - await juniorTrancheVaultContract.userInfos(jActiveLenders[i].address) + await juniorTrancheVaultContract.depositRecords(jActiveLenders[i].address) ).principal; } else { expect(await mockTokenContract.balanceOf(jActiveLenders[i].address)).to.equal( oldBalances[i], ); - let [newPrincipal] = await juniorTrancheVaultContract.userInfos( + let [newPrincipal] = await juniorTrancheVaultContract.depositRecords( jActiveLenders[i].address, ); expect(newPrincipal).greaterThan(jLenderPrincipals[i]); @@ -482,13 +482,13 @@ async function testYieldPayout() { oldBalances[i].add(interests[i]), ); sLenderPrincipals[i] = ( - await seniorTrancheVaultContract.userInfos(sActiveLenders[i].address) + await seniorTrancheVaultContract.depositRecords(sActiveLenders[i].address) ).principal; } else { expect(await mockTokenContract.balanceOf(sActiveLenders[i].address)).to.equal( oldBalances[i], ); - let [newPrincipal] = await seniorTrancheVaultContract.userInfos( + let [newPrincipal] = await seniorTrancheVaultContract.depositRecords( sActiveLenders[i].address, ); expect(newPrincipal).greaterThan(sLenderPrincipals[i]); @@ -512,7 +512,9 @@ async function testRedemptionRequest(jLenderRequests: BN[], sLenderRequests: BN[ expect(await juniorTrancheVaultContract.balanceOf(jLenders[i].address)).to.equal( oldShares.sub(jLenderRequests[i]), ); - let [newPrincipal] = await juniorTrancheVaultContract.userInfos(jLenders[i].address); + let [newPrincipal] = await juniorTrancheVaultContract.depositRecords( + jLenders[i].address, + ); let principalRequested = await juniorTrancheVaultContract.convertToAssets( jLenderRequests[i], ); @@ -521,9 +523,9 @@ async function testRedemptionRequest(jLenderRequests: BN[], sLenderRequests: BN[ jLenderPrincipalRequests[i] = jLenderPrincipalRequests[i].add(principalRequested); jLenderPrincipals[i] = newPrincipal; let lastUpdatedEpochIndex = ( - await juniorTrancheVaultContract.redemptionInfoByLender(jLenders[i].address) + await juniorTrancheVaultContract.lenderRedemptionRecords(jLenders[i].address) ).lastUpdatedEpochIndex; - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( juniorTrancheVaultContract, jLenders[i], lastUpdatedEpochIndex, @@ -559,7 +561,9 @@ async function testRedemptionRequest(jLenderRequests: BN[], sLenderRequests: BN[ expect(await seniorTrancheVaultContract.balanceOf(sLenders[i].address)).to.equal( oldShares.sub(sLenderRequests[i]), ); - let [newPrincipal] = await seniorTrancheVaultContract.userInfos(sLenders[i].address); + let [newPrincipal] = await seniorTrancheVaultContract.depositRecords( + sLenders[i].address, + ); let principalRequested = await seniorTrancheVaultContract.convertToAssets( sLenderRequests[i], ); @@ -568,9 +572,9 @@ async function testRedemptionRequest(jLenderRequests: BN[], sLenderRequests: BN[ sLenderPrincipalRequests[i] = sLenderPrincipalRequests[i].add(principalRequested); sLenderPrincipals[i] = newPrincipal; let lastUpdatedEpochIndex = ( - await seniorTrancheVaultContract.redemptionInfoByLender(sLenders[i].address) + await seniorTrancheVaultContract.lenderRedemptionRecords(sLenders[i].address) ).lastUpdatedEpochIndex; - await checkRedemptionInfoByLender( + await checkRedemptionRecordByLender( seniorTrancheVaultContract, sLenders[i], lastUpdatedEpochIndex,