Skip to content

Commit

Permalink
Merge pull request #42 from yieldnest/chad/sc-193/yneth-spec-test-reb…
Browse files Browse the repository at this point in the history
…ased

ynETH Scenario Testing
  • Loading branch information
xhad authored Mar 23, 2024
2 parents a95197c + dc7f3e0 commit fdc503a
Show file tree
Hide file tree
Showing 4 changed files with 486 additions and 4 deletions.
4 changes: 0 additions & 4 deletions test/foundry/integration/StakingNodesManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -442,10 +442,6 @@ contract StakingNodesManagerViews is IntegrationBaseTest {
}
}

contract StakingNodesManagerUtils is IntegrationBaseTest {


}

contract StakingNodesManagerValidators is IntegrationBaseTest {

Expand Down
36 changes: 36 additions & 0 deletions test/foundry/scenarios/Invariants.sol
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"
);
}
}
108 changes: 108 additions & 0 deletions test/foundry/scenarios/ynETH-Scenarios.md
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);
```
Loading

0 comments on commit fdc503a

Please sign in to comment.