-
Notifications
You must be signed in to change notification settings - Fork 66
feat: Add NexusViewer #1172
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
Merged
rackstar
merged 14 commits into
feat/staking-viewer-dashboard-updates
from
feat/contract-viewer-get-total-nxm
Jul 12, 2024
Merged
feat: Add NexusViewer #1172
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
ac064a2
Add NexusViewer and INexusViewer
rackstar fb9bbc2
Add NexusViewer mocks
rackstar 4e3c854
Add stakingPool test utils
rackstar 55907bc
Update StakingViewer unit tests
rackstar 87ce454
Add NexusViewer unit tests
rackstar c3371a3
Move calculatePremium to cover integration utils
rackstar e15124a
Add viewer contracts to integration test setup
rackstar 006008b
Add NexusViewer integration tests
rackstar 6349a5b
Update getStakedNXM unit tests and NVMockStakingViewer
rackstar 2f70afd
Fix linting issue + clean up
rackstar 6454661
Move getManagerTotalRewards to stakingViewer
rackstar 42f0fdf
Fix natspec comments
rackstar 8970723
Fix natspec comments + linting issue
rackstar c58f1a6
Rename method to getManagerTokenRewardsByAddr
rackstar File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// SPDX-License-Identifier: GPL-3.0-only | ||
|
||
pragma solidity ^0.8.18; | ||
|
||
import {IAssessmentViewer} from "./IAssessmentViewer.sol"; | ||
import {IStakingViewer} from "./IStakingViewer.sol"; | ||
|
||
interface INexusViewer { | ||
|
||
struct ClaimableNXM { | ||
uint governanceRewards; // Governance rewards in NXM | ||
uint assessmentRewards; // Claimable assessment reward in NXM | ||
uint assessmentStake; // Claimable assessment stake in NXM | ||
uint stakingPoolTotalRewards; // Total staking pool rewards in NXM | ||
uint stakingPoolTotalExpiredStake; // Total staking pool expired stake in NXM | ||
uint managerTotalRewards; // Pool manager total staking rewards in NXM | ||
uint legacyPooledStakeRewards; // Legacy pooled staking rewards in NXM | ||
uint legacyPooledStakeDeposits; // Legacy pooled staking deposits in NXM | ||
uint legacyCoverNoteDeposits; // Legacy cover note deposits in NXM | ||
uint legacyClaimAssessmentTokens; // Legacy claim assessment tokens in NXM | ||
} | ||
|
||
struct StakedNXM { | ||
uint stakingPoolTotalActiveStake; // Total amount of active stake in staking pools in NXM | ||
uint assessmentStake; // Locked assessment stake in NXM | ||
uint assessmentRewards; // Locked assessment rewards in NXM | ||
} | ||
|
||
function getClaimableNXM(address member, uint[] calldata tokenIds) external view returns (ClaimableNXM memory); | ||
|
||
function getStakedNXM(address member, uint[] calldata tokenIds) external view returns (StakedNXM memory); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
contracts/mocks/modules/NexusViewer/NVMockAssessmentViewer.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// SPDX-License-Identifier: GPL-3.0-only | ||
|
||
pragma solidity ^0.8.18; | ||
|
||
import {IAssessment} from "../../../interfaces/IAssessment.sol"; | ||
import {IAssessmentViewer} from "../../../interfaces/IAssessmentViewer.sol"; | ||
import {INXMMaster} from "../../../interfaces/INXMMaster.sol"; | ||
import {INXMToken} from "../../../interfaces/INXMToken.sol"; | ||
|
||
contract NVMockAssessmentViewer is IAssessmentViewer { | ||
|
||
bool stakeLocked; | ||
AssessmentRewards assessmentRewards; | ||
|
||
/* ========== SETTERS ========== */ | ||
|
||
function setStakeLocked(bool _stakeLocked) external { | ||
stakeLocked = _stakeLocked; | ||
} | ||
|
||
function setRewards( | ||
uint _totalPendingAmountInNXM, | ||
uint _withdrawableAmountInNXM, | ||
uint _withdrawableUntilIndex | ||
) external { | ||
assessmentRewards = AssessmentRewards({ | ||
totalPendingAmountInNXM: _totalPendingAmountInNXM, | ||
withdrawableAmountInNXM: _withdrawableAmountInNXM, | ||
withdrawableUntilIndex: _withdrawableUntilIndex | ||
}); | ||
} | ||
|
||
/* ========== VIEWS ========== */ | ||
|
||
function isStakeLocked(address) external view returns (bool) { | ||
return stakeLocked; | ||
} | ||
|
||
function getRewards(address) external view returns (AssessmentRewards memory) { | ||
return assessmentRewards; | ||
} | ||
|
||
/* ========== NOT YET IMPLEMENTED ========== */ | ||
|
||
function assessment() public pure returns (IAssessment) { | ||
revert("assessment not yet implemented"); | ||
} | ||
} |
126 changes: 126 additions & 0 deletions
126
contracts/mocks/modules/NexusViewer/NVMockStakingViewer.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
// SPDX-License-Identifier: GPL-3.0-only | ||
|
||
pragma solidity ^0.8.18; | ||
|
||
import {ICover} from "../../../interfaces/ICover.sol"; | ||
import {INXMMaster} from "../../../interfaces/INXMMaster.sol"; | ||
import {IStakingNFT} from "../../../interfaces/IStakingNFT.sol"; | ||
import {IStakingPool} from "../../../interfaces/IStakingPool.sol"; | ||
import {IStakingProducts} from "../../../interfaces/IStakingProducts.sol"; | ||
import {IStakingPoolFactory} from "../../../interfaces/IStakingPoolFactory.sol"; | ||
import {IStakingViewer} from "../../../interfaces/IStakingViewer.sol"; | ||
import {StakingPoolLibrary} from "../../../libraries/StakingPoolLibrary.sol"; | ||
|
||
contract NVMockStakingViewer is IStakingViewer { | ||
|
||
uint public constant TRANCHE_DURATION = 91 days; | ||
uint public constant MAX_ACTIVE_TRANCHES = 8; | ||
uint public constant ONE_NXM = 1 ether; | ||
uint public constant TRANCHE_ID_AT_DEPLOY = 213; | ||
uint public constant MAX_UINT = type(uint).max; | ||
AggregatedTokens aggregatedTokens; | ||
|
||
/* ========== SETTERS ========== */ | ||
|
||
function setAggregatedTokens(uint _totalActiveStake, uint _totalExpiredStake, uint _totalRewards) public { | ||
aggregatedTokens = AggregatedTokens({ | ||
totalActiveStake: _totalActiveStake, | ||
totalExpiredStake: _totalExpiredStake, | ||
totalRewards: _totalRewards | ||
}); | ||
} | ||
|
||
/* ========== VIEWS ========== */ | ||
|
||
function getAggregatedTokens(uint[] calldata) public view returns (AggregatedTokens memory) { | ||
return aggregatedTokens; | ||
} | ||
|
||
/* ========== NOT YET IMPLEMENTED ========== */ | ||
|
||
function _cover() internal pure returns (ICover) { | ||
revert("_cover not yet implemented"); | ||
} | ||
|
||
function _stakingProducts() internal pure returns (IStakingProducts) { | ||
revert("_stakingProducts not yet implemented"); | ||
} | ||
|
||
function stakingPool(uint) public pure returns (IStakingPool) { | ||
revert("stakingPool not yet implemented"); | ||
} | ||
|
||
/* ========== STAKING POOL ========== */ | ||
|
||
function getPool(uint) public pure returns (Pool memory) { | ||
revert("getPool not yet implemented"); | ||
} | ||
|
||
function getPools(uint[] memory) public pure returns (Pool[] memory) { | ||
revert("getPools not yet implemented"); | ||
} | ||
|
||
function getAllPools() public pure returns (Pool[] memory) { | ||
revert("getAllPools not yet implemented"); | ||
} | ||
|
||
function getProductPools(uint) public pure returns (Pool[] memory) { | ||
revert("getProductPools not yet implemented"); | ||
} | ||
|
||
/* ========== PRODUCTS ========== */ | ||
|
||
function getPoolProducts(uint) public pure returns (StakingProduct[] memory) { | ||
revert("getPoolProducts not yet implemented"); | ||
} | ||
|
||
/* ========== TOKENS AND DEPOSITS ========== */ | ||
|
||
function getStakingPoolsOf(uint[] memory) public pure returns (TokenPoolMap[] memory) { | ||
revert("getStakingPoolsOf not yet implemented"); | ||
} | ||
|
||
function _getToken(uint, uint) internal pure returns (Token memory) { | ||
revert("_getToken not yet implemented"); | ||
} | ||
|
||
function getToken(uint) public pure returns (Token memory) { | ||
revert("getToken not yet implemented"); | ||
} | ||
|
||
function getTokens(uint[] memory) public pure returns (Token[] memory) { | ||
revert("getTokens not yet implemented"); | ||
} | ||
|
||
function getManagedStakingPools(address) public pure returns (Pool[] memory) { | ||
revert("getManagedStakingPools not yet implemented"); | ||
} | ||
|
||
function getManagerTokenRewardsByAddr(address) public pure returns (Token[] memory) { | ||
revert("getManagerTokenRewardsByAddr not yet implemented"); | ||
} | ||
|
||
function getManagerTotalRewards(address) public pure returns (uint) { | ||
revert("getManagerTotalRewards not yet implemented"); | ||
} | ||
|
||
function getManagerPoolsAndRewards(address) external pure returns (ManagerPoolsAndRewards memory) { | ||
revert("getManagerPoolsAndRewards not yet implemented"); | ||
} | ||
|
||
function getManagerRewards(uint[] memory) external pure returns (Token[] memory) { | ||
revert("getManagerRewards not yet implemented"); | ||
} | ||
|
||
function processExpirationsFor(uint[] memory) external pure { | ||
revert("processExpirationsFor not yet implemented"); | ||
} | ||
|
||
function processExpirations(uint[] memory) public pure { | ||
revert("processExpirations not yet implemented"); | ||
} | ||
|
||
function _getMatchingPools(address) internal pure returns (Pool[] memory, uint) { | ||
revert("_getMatchingPools not yet implemented"); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
// SPDX-License-Identifier: GPL-3.0-only | ||
|
||
pragma solidity ^0.8.18; | ||
|
||
import {Multicall} from "../../abstract/Multicall.sol"; | ||
import {IAssessment} from "../../interfaces/IAssessment.sol"; | ||
import {IAssessmentViewer} from "../../interfaces/IAssessmentViewer.sol"; | ||
import {IGovernance} from "../../interfaces/IGovernance.sol"; | ||
import {INexusViewer} from "../../interfaces/INexusViewer.sol"; | ||
import {INXMMaster} from "../../interfaces/INXMMaster.sol"; | ||
import {IPooledStaking} from "../../interfaces/IPooledStaking.sol"; | ||
import {IStakingViewer} from "../../interfaces/IStakingViewer.sol"; | ||
import {ITokenController} from "../../interfaces/ITokenController.sol"; | ||
|
||
/// @title NexusViewer Contract | ||
/// @notice This contract provides a unified view of system-wide data from various contracts within the Nexus Mutual protocol. | ||
contract NexusViewer is INexusViewer, Multicall { | ||
|
||
INXMMaster public immutable master; | ||
IStakingViewer public immutable stakingViewer; | ||
IAssessmentViewer public immutable assessmentViewer; | ||
|
||
constructor(INXMMaster _master, IStakingViewer _stakingViewer, IAssessmentViewer _assessmentViewer) { | ||
master = _master; | ||
stakingViewer = _stakingViewer; | ||
assessmentViewer = _assessmentViewer; | ||
} | ||
|
||
/// @notice Retrieves the claimable NXM tokens across the protocol for a given member. | ||
/// @dev Ensure the tokenIds passed belongs to the member address. | ||
/// @param member The address of the member to query. | ||
/// @param tokenIds An array of staking NFT token IDs associated with the member. | ||
/// @return A ClaimableNxm struct containing details of the claimable NXM tokens. | ||
function getClaimableNXM(address member, uint[] calldata tokenIds) external view returns (ClaimableNXM memory) { | ||
|
||
// Governance | ||
uint governanceRewards = _governance().getPendingReward(member); | ||
|
||
// Assessment | ||
IAssessmentViewer.AssessmentRewards memory assessmentRewards = assessmentViewer.getRewards(member); | ||
(uint assessmentStake, bool isStakeLocked) = _getAssessmentStake(member); | ||
|
||
// Staking Pool | ||
IStakingViewer.AggregatedTokens memory aggregatedTokens = stakingViewer.getAggregatedTokens(tokenIds); | ||
uint managerTotalRewards = stakingViewer.getManagerTotalRewards(member); | ||
|
||
// V1 | ||
uint legacyPooledStakeDeposits = _legacyPooledStaking().stakerDeposit(member); | ||
uint legacyPooledStakeRewards = _legacyPooledStaking().stakerReward(member); | ||
uint legacyClaimAssessmentTokens = _tokenController().tokensLocked(member, "CLA"); | ||
(, , uint legacyCoverNoteDeposits) = _tokenController().getWithdrawableCoverNotes(member); | ||
|
||
return ClaimableNXM({ | ||
governanceRewards: governanceRewards, | ||
assessmentRewards: assessmentRewards.withdrawableAmountInNXM, | ||
assessmentStake: isStakeLocked ? 0 : assessmentStake, | ||
stakingPoolTotalRewards: aggregatedTokens.totalRewards, | ||
stakingPoolTotalExpiredStake: aggregatedTokens.totalExpiredStake, | ||
managerTotalRewards: managerTotalRewards, | ||
legacyPooledStakeRewards: legacyPooledStakeRewards, | ||
legacyPooledStakeDeposits: legacyPooledStakeDeposits, | ||
legacyCoverNoteDeposits: legacyCoverNoteDeposits, | ||
legacyClaimAssessmentTokens: legacyClaimAssessmentTokens | ||
}); | ||
} | ||
|
||
/// @notice Retrieves the locked NXM tokens across the protocol for a given member. | ||
/// @dev Ensure the tokenIds passed belongs to the member address. | ||
/// @param member The address of the member to query. | ||
/// @param tokenIds An array of staking NFT token IDs associated with the member. | ||
/// @return A StakedNXM struct containing details of the locked NXM tokens. | ||
function getStakedNXM(address member, uint[] calldata tokenIds) external view returns (StakedNXM memory) { | ||
|
||
IStakingViewer.AggregatedTokens memory aggregatedTokens = stakingViewer.getAggregatedTokens(tokenIds); | ||
|
||
IAssessmentViewer.AssessmentRewards memory assessmentRewards = assessmentViewer.getRewards(member); | ||
(uint assessmentStake, bool isStakeLocked) = _getAssessmentStake(member); | ||
|
||
return StakedNXM({ | ||
stakingPoolTotalActiveStake: aggregatedTokens.totalActiveStake, | ||
assessmentStake: isStakeLocked ? assessmentStake : 0, | ||
assessmentRewards: assessmentRewards.totalPendingAmountInNXM - assessmentRewards.withdrawableAmountInNXM | ||
}); | ||
} | ||
|
||
function _getAssessmentStake(address member) internal view returns (uint assessmentStake, bool isStakeLocked) { | ||
(assessmentStake, , ) = _assessment().stakeOf(member); | ||
isStakeLocked = assessmentViewer.isStakeLocked(member); | ||
} | ||
|
||
/* ========== DEPENDENCIES ========== */ | ||
|
||
function _assessment() internal view returns (IAssessment) { | ||
return IAssessment(master.getLatestAddress("AS")); | ||
} | ||
|
||
function _legacyPooledStaking() internal view returns (IPooledStaking) { | ||
return IPooledStaking(master.getLatestAddress("PS")); | ||
} | ||
|
||
function _governance() internal view returns (IGovernance) { | ||
return IGovernance(master.getLatestAddress("GV")); | ||
} | ||
|
||
function _tokenController() internal view returns (ITokenController) { | ||
return ITokenController(master.contractAddresses("TC")); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.