Skip to content

Commit

Permalink
Merge branch 'payments' into payments-natspec
Browse files Browse the repository at this point in the history
  • Loading branch information
8sunyuan authored Apr 18, 2024
2 parents c4faf63 + 10a3e44 commit 6a2c7f1
Show file tree
Hide file tree
Showing 122 changed files with 477 additions and 301 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/run-deploy-scripts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Run Deploy Scripts
# We run the deploy scripts just to make sure they work

on:
push:
pull_request:
types: [opened, reopened]

jobs:
prepare:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2
with:
submodules: true

# install foundry to run forge script. Should we run forge script in a container instead?
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

- name: Start Anvil chain
# need to start Anvil chain with -d to let the container run in the background
# if we start with 'anvil &' instead, the process stops when the step ends
run: docker run -d --rm -p 8545:8545 --entrypoint anvil ghcr.io/foundry-rs/foundry:nightly-5b7e4cb3c882b28f3c32ba580de27ce7381f415a --host 0.0.0.0

- name: Wait for Anvil chain to start
run: sleep 3

# Run Forge script against the Anvil chain
- name: Run M2_Deploy_From_Scratch
run: |
forge script script/deploy/devnet/M2_Deploy_From_Scratch.s.sol --rpc-url http://localhost:8545 \
--private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 --broadcast \
--sig "run(string memory configFileName)" -- M2_deploy_from_scratch.anvil.config.json
22 changes: 18 additions & 4 deletions .github/workflows/testinparallel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@ jobs:
needs: prepare
runs-on: ubuntu-latest
strategy:
matrix:
file: ${{fromJson(needs.prepare.outputs.matrix)}}
fail-fast: false

steps:
- name: Checkout code
uses: actions/checkout@v2
Expand All @@ -43,9 +42,24 @@ jobs:
forge build --sizes
id: build

- name: Run forge test for the file
run: forge test --match-path src/test/${{ matrix.file }} --no-match-contract FFI
- name: Run unit tests
run: forge test --no-match-contract Integration
env:
RPC_MAINNET: ${{ secrets.RPC_MAINNET }}
RPC_HOLESKY: ${{ secrets.RPC_HOLESKY }}
CHAIN_ID: ${{ secrets.CHAIN_ID }}

- name: Run integration tests
run: forge test --match-contract Integration
env:
RPC_MAINNET: ${{ secrets.RPC_MAINNET }}
RPC_HOLESKY: ${{ secrets.RPC_HOLESKY }}
CHAIN_ID: ${{ secrets.CHAIN_ID }}

- name: Run integration mainnet fork tests
run: forge test --match-contract Integration
env:
FOUNDRY_PROFILE: "forktest"
RPC_MAINNET: ${{ secrets.RPC_MAINNET }}
RPC_HOLESKY: ${{ secrets.RPC_HOLESKY }}
CHAIN_ID: ${{ secrets.CHAIN_ID }}
137 changes: 92 additions & 45 deletions README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions certora/harnesses/DelegationManagerHarness.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.12;
pragma solidity ^0.8.12;

import "../../src/contracts/core/DelegationManager.sol";

Expand All @@ -25,4 +25,4 @@ contract DelegationManagerHarness is DelegationManager {
return strategyManager.stakerStrategyShares(staker, strategy);
}
}
}
}
4 changes: 2 additions & 2 deletions certora/harnesses/EigenPodHarness.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.12;
pragma solidity ^0.8.12;

import "../../src/contracts/pods/EigenPod.sol";

Expand Down Expand Up @@ -37,4 +37,4 @@ contract EigenPodHarness is EigenPod {
function get_ETH_Balance() public view returns (uint256) {
return address(this).balance;
}
}
}
4 changes: 2 additions & 2 deletions certora/harnesses/EigenPodManagerHarness.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.12;
pragma solidity ^0.8.12;

import "../../src/contracts/pods/EigenPodManager.sol";

Expand All @@ -21,4 +21,4 @@ contract EigenPodManagerHarness is EigenPodManager {
function get_podByOwner(address podOwner) public view returns (IEigenPod) {
return ownerToPod[podOwner];
}
}
}
4 changes: 2 additions & 2 deletions certora/harnesses/PausableHarness.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.12;
pragma solidity ^0.8.12;

import "../../src/contracts/permissions/Pausable.sol";

Expand All @@ -21,4 +21,4 @@ contract PausableHarness is Pausable {
function bitwise_and(uint256 input_1, uint256 input_2) external pure returns (uint256) {
return (input_1 & input_2);
}
}
}
4 changes: 2 additions & 2 deletions certora/harnesses/SlasherHarness.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.12;
pragma solidity ^0.8.12;

import "../../src/contracts/core/Slasher.sol";

Expand Down Expand Up @@ -82,4 +82,4 @@ contract SlasherHarness is Slasher {
// get_linked_list_entry(operator, get_previous_node(operator, node), true) == node && get_linked_list_entry(operator, get_next_node(operator, node), false) == node
// );
// }
}
}
4 changes: 2 additions & 2 deletions certora/harnesses/StrategyManagerHarness.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.12;
pragma solidity ^0.8.12;

import "../../src/contracts/core/StrategyManager.sol";

Expand Down Expand Up @@ -55,4 +55,4 @@ contract StrategyManagerHarness is StrategyManager {
function get_stakerStrategyShares(address staker, IStrategy strategy) public view returns (uint256) {
return stakerStrategyShares[staker][strategy];
}
}
}
2 changes: 0 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

## EigenLayer M2 Docs

**EigenLayer M2** extends the functionality of EigenLayer M1 (which is live on mainnet). M2 is currently on the Goerli testnet, and will eventually be released on mainnet.

This repo contains the EigenLayer core contracts, which enable restaking of liquid staking tokens (LSTs) and beacon chain ETH to secure new services, called AVSs (actively validated services). For more info on AVSs, check out the EigenLayer middleware contracts [here][middleware-repo].

This document provides an overview of system components, contracts, and user roles. Further documentation on the major system contracts can be found in [/core](./core/).
Expand Down
2 changes: 1 addition & 1 deletion docs/core/AVSDirectory.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

| File | Type | Proxy |
| -------- | -------- | -------- |
| [`AVSDirectory.sol`](../src/contracts/core/AVSDirectory.sol) | Singleton | Transparent proxy |
| [`AVSDirectory.sol`](../../src/contracts/core/AVSDirectory.sol) | Singleton | Transparent proxy |

The `AVSDirectory` handles interactions between AVSs and the EigenLayer core contracts. Once registered as an Operator in EigenLayer core (via the `DelegationManager`), Operators can register with one or more AVSs (via the AVS's contracts) to begin providing services to them offchain. As a part of registering with an AVS, the AVS will record this registration in the core contracts by calling into the `AVSDirectory`.

Expand Down
4 changes: 2 additions & 2 deletions docs/core/DelegationManager.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Registers the caller as an Operator in EigenLayer. The new Operator provides the
* Sets `OperatorDetails` for the Operator in question
* Delegates the Operator to itself
* If the Operator has shares in the `EigenPodManager`, the `DelegationManager` adds these shares to the Operator's shares for the beacon chain ETH strategy.
* For each of the three strategies in the `StrategyManager`, if the Operator holds shares in that strategy they are added to the Operator's shares under the corresponding strategy.
* For each of the strategies in the `StrategyManager`, if the Operator holds shares in that strategy they are added to the Operator's shares under the corresponding strategy.

*Requirements*:
* Caller MUST NOT already be an Operator
Expand Down Expand Up @@ -132,7 +132,7 @@ Allows the caller (a Staker) to delegate their shares to an Operator. Delegation
*Effects*:
* Records the Staker as being delegated to the Operator
* If the Staker has shares in the `EigenPodManager`, the `DelegationManager` adds these shares to the Operator's shares for the beacon chain ETH strategy.
* For each of the three strategies in the `StrategyManager`, if the Staker holds shares in that strategy they are added to the Operator's shares under the corresponding strategy.
* For each of the strategies in the `StrategyManager`, if the Staker holds shares in that strategy they are added to the Operator's shares under the corresponding strategy.

*Requirements*:
* Pause status MUST NOT be set: `PAUSED_NEW_DELEGATION`
Expand Down
4 changes: 2 additions & 2 deletions docs/core/StrategyManager.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

The primary function of the `StrategyManager` is to handle accounting for individual Stakers as they deposit and withdraw LSTs from their corresponding strategies. It is responsible for (i) allowing Stakers to deposit LSTs into the corresponding strategy, (ii) allowing the `DelegationManager` to remove shares when a Staker queues a withdrawal, and (iii) allowing the `DelegationManager` to complete a withdrawal by either adding shares back to the Staker or withdrawing the shares as tokens via the corresponding strategy.

As of M2, three LSTs are supported and each has its own instance of `StrategyBaseTVLLimits`: cbETH, rETH, and stETH. Each `StrategyBaseTVLLimits` has two main functions (`deposit` and `withdraw`), both of which can only be called by the `StrategyManager`. These `StrategyBaseTVLLimits` contracts are fairly simple deposit/withdraw contracts that hold tokens deposited by Stakers. Because these strategies are essentially extensions of the `StrategyManager`, their functions are documented in this file (see below).
As of M2, several LSTs are supported and each has its own instance of `StrategyBaseTVLLimits`. Each `StrategyBaseTVLLimits` has two main functions (`deposit` and `withdraw`), both of which can only be called by the `StrategyManager`. These `StrategyBaseTVLLimits` contracts are fairly simple deposit/withdraw contracts that hold tokens deposited by Stakers. Because these strategies are essentially extensions of the `StrategyManager`, their functions are documented in this file (see below).

#### High-level Concepts

Expand Down Expand Up @@ -59,7 +59,7 @@ function depositIntoStrategy(
returns (uint256 shares)
```

Allows a Staker to deposit some `amount` of `token` into the specified `strategy` in exchange for shares of that strategy. The underlying `strategy` must be one of the three whitelisted `StrategyBaseTVLLimits` instances, and the `token` being deposited must correspond to that `strategy's` underlying token (cbETH, rETH, or stETH).
Allows a Staker to deposit some `amount` of `token` into the specified `strategy` in exchange for shares of that strategy. The underlying `strategy` must be one of the whitelisted `StrategyBaseTVLLimits` instances, and the `token` being deposited must correspond to that `strategy's` underlying token (cbETH, rETH, or stETH).

The number of shares received is calculated by the `strategy` using an internal exchange rate that depends on the previous number of tokens deposited.

Expand Down
5 changes: 4 additions & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,7 @@ number_underscore = "thousands"
quote_style = "double"
tab_width = 4

# See more config options https://github.com/gakonst/foundry/tree/master/config
# See more config options https://github.com/gakonst/foundry/tree/master/config

[profile.forktest.fuzz]
runs=20
71 changes: 71 additions & 0 deletions script/admin/mainnet/Mainnet_Unpause_Deposits.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.12;

import "../../utils/ExistingDeploymentParser.sol";
import "../../utils/TimelockEncoding.sol";

// forge script script/admin/mainnet/Mainnet_Unpause_Deposits.s.sol:Mainnet_Unpause_Deposits --fork-url $RPC_MAINNET -vvvv
contract Mainnet_Unpause_Deposits is ExistingDeploymentParser, TimelockEncoding {
Vm cheats = Vm(HEVM_ADDRESS);

// Tues Apr 16 2024 12:00:00 GMT-0700 (Pacific Daylight Time)
uint256 timelockEta = 1713250800;

function run() external virtual {
_parseDeployedContracts("script/output/mainnet/M1_deployment_mainnet_2023_6_9.json");

bytes memory final_calldata_to_executor_multisig = encodeForExecutor({
// call to executor will be from the timelock
from: timelock,
// performing single pause operation
to: address(strategyManager),
// value to send in tx
value: 0,
// calldata for the operation
data: abi.encodeWithSelector(Pausable.unpause.selector, 0),
// operation type (for performing single operation)
operation: ISafe.Operation.Call
});

(bytes memory calldata_to_timelock_queuing_action, bytes memory calldata_to_timelock_executing_action) = encodeForTimelock({
// address to be called from the timelock
to: executorMultisig,
// value to send in tx
value: 0,
// calldata for the operation
data: final_calldata_to_executor_multisig,
// time at which the tx will become executable
timelockEta: timelockEta
});

bytes32 expectedTxHash = getTxHash({
target: executorMultisig,
_value: 0,
_data: final_calldata_to_executor_multisig,
eta: timelockEta
});
emit log_named_bytes32("expectedTxHash", expectedTxHash);

cheats.prank(operationsMultisig);
(bool success, ) = timelock.call(calldata_to_timelock_queuing_action);
require(success, "call to timelock queuing action failed");

require(ITimelock(timelock).queuedTransactions(expectedTxHash), "expectedTxHash not queued");

// test performing the upgrade
cheats.warp(timelockEta);
cheats.prank(operationsMultisig);
(success, ) = timelock.call(calldata_to_timelock_executing_action);
require(success, "call to timelock executing action failed");

// Check correctness after upgrade
require(strategyManager.paused() == 0, "unpausing was not completed correctly");
}

function getTxHash(address target, uint256 _value, bytes memory _data, uint256 eta) public pure returns (bytes32) {
// empty bytes
bytes memory signature;
bytes32 txHash = keccak256(abi.encode(target, _value, signature, _data, eta));
return txHash;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR": "32000000000"
},
"eigenPodManager": {
"max_pods": 0,
"init_paused_status": 30
},
"delayedWithdrawalRouter": {
Expand Down
Loading

0 comments on commit 6a2c7f1

Please sign in to comment.