-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #42 from yieldnest/chad/sc-193/yneth-spec-test-reb…
…ased ynETH Scenario Testing
- Loading branch information
Showing
4 changed files
with
486 additions
and
4 deletions.
There are no files selected for viewing
This file contains 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 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,36 @@ | ||
// SPDX-License-Identifier: BSD 3-Clause License | ||
pragma solidity ^0.8.24; | ||
|
||
library Invariants { | ||
|
||
/// Share and Assets Invariants | ||
function shareMintIntegrity (uint256 totalSupply, uint256 previousTotal, uint256 newShares) public pure { | ||
require(totalSupply == previousTotal + newShares, | ||
"Invariant: Total supply should be equal to previous total plus new shares" | ||
); | ||
} | ||
|
||
function totalDepositIntegrity (uint256 totalDeposited, uint256 previousTotal, uint256 newDeposited) public pure { | ||
require(totalDeposited == previousTotal + newDeposited, | ||
"Invariant: Total deposited should be equal to previous total plus new deposited" | ||
); | ||
} | ||
|
||
function userSharesIntegrity (uint256 userShares, uint256 previousShares, uint256 newShares) public pure { | ||
require(userShares == previousShares + newShares, | ||
"Invariant: User shares should be equal to previous shares plus new shares" | ||
); | ||
} | ||
|
||
function totalAssetsIntegrity (uint256 totalAssets, uint256 previousAssets, uint256 newAssets) public pure { | ||
require(totalAssets == previousAssets + newAssets, | ||
"Invariant: Total assets should be equal to previous assets plus new assets" | ||
); | ||
} | ||
|
||
function totalBalanceIntegrity (uint256 balance, uint256 previousBalance, uint256 newBalance) public pure { | ||
require(balance == previousBalance + newBalance, | ||
"Invariant: Total balance should be equal to previous balance plus new balance" | ||
); | ||
} | ||
} |
This file contains 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 @@ | ||
|
||
## Usage Scenario Tests | ||
|
||
These tests are designed to verify the correct behavior of the ynETH contract in various usage scenarios. | ||
|
||
**Scenario 1:** Successful ETH Deposit and Share Minting | ||
|
||
Objective: Test that a user can deposit ETH and receive the correct amount of shares in return. | ||
|
||
**Scenario 2:** Deposit Paused | ||
|
||
Objective: Ensure that deposits are correctly paused and resumed, preventing or allowing ETH deposits accordingly. | ||
|
||
**Scenario 3:** Deposit and Withdraw ETH to Staking Nodes Manager | ||
|
||
Objective: Test the end-to-end flow of depositing ETH to an eigenpod, and withdrawing ETH to the staking nodes manager. | ||
|
||
**Scenario 4:** Share Accouting and Yield Accrual | ||
|
||
Objective: Verify that the share price correctly increases after the contract earns yield from consensus and execution rewards. | ||
|
||
**Scenario 5:** Emergency Withdrawal of ETH | ||
|
||
Objective: Test ability to withdraw all assets from eigenpods. | ||
|
||
**Scenario 6:** Validator and Staking Node Administration | ||
|
||
Objective: Test the ynETH's ability to update the address of the Staking Nodes Manager. | ||
|
||
**Scenario 7:** Accrual and Distribution of Fees | ||
|
||
Objective: Ensure that ynETH correctly accrues and distributes fees from yield earnings from execution and consensus rewards. | ||
|
||
**Scenario 8:** Staking Rewards Distribution | ||
|
||
Objective: Test the distribution of staking rewards to a multisig. | ||
|
||
**Scenario 9:** EigenLayer Accounting and Distribution | ||
|
||
Objective: Verify that ynETH correctly accounts for fund balances and withdrawals from EigenLayer. | ||
|
||
## Invariant Scenarios | ||
|
||
The following invariant scenarios are designed to verify the correct behavior of the ynETH contract in various usage scenarios. These scenarios should never fail, and if they do, it indicates there is an implementation issue somewhere in the protocol. | ||
|
||
**Total Assets Consistency** | ||
|
||
```solidity | ||
assert(totalDepositedInPool + totalDepositedInValidators() == totalAssets()); | ||
``` | ||
|
||
**Exchange Rate Integrity** | ||
|
||
```solidity | ||
assert(exchangeAdjustmentRate >= 0 && exchangeAdjustmentRate <= BASIS_POINTS_DENOMINATOR); | ||
``` | ||
**Share Minting Consistency** | ||
|
||
```solidity | ||
assert(totalSupply() == previousTotalSupply + mintedShares) | ||
``` | ||
|
||
**User Shares Integrity** | ||
|
||
```solidity | ||
assert(balanceOf(user) == previousUserSharesBalance + newUserSharesBalance); | ||
``` | ||
|
||
**Total Deposited Integrity** | ||
|
||
```solidity | ||
assert(totalDepositedInValidators() == previousTotalDeposited + newDeposit); | ||
``` | ||
|
||
**Total Assets Integrity** | ||
|
||
```solidity | ||
assert(totalAssets() == previousTotalAssets + newDeposit); | ||
``` | ||
|
||
**Total Balance Integrity** | ||
|
||
```solidity | ||
assert(address(yneth).balance() == previousBalance + newBalance); | ||
``` | ||
|
||
**Deposit and Withdrawal Symmetry** | ||
|
||
```solidity | ||
uint256 sharesMinted = depositETH(amount); | ||
assert(sharesMinted == previewDeposit(amount)); | ||
``` | ||
|
||
**Rewards Increase Total Assets** | ||
|
||
```solidity | ||
uint256 previousTotalAssets = totalAssets(); | ||
// Simulate receiving rewards | ||
receiveRewards{value: rewardAmount}(); | ||
assert(totalAssets() == previousTotalAssets + rewardAmount); | ||
``` | ||
|
||
**Authorized Access Control** | ||
|
||
```solidity | ||
// For any role-restricted operation | ||
assert(msg.sender == authorizedRoleAddress); | ||
``` |
Oops, something went wrong.