Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we don't need to run the mainnet fork tests too frequently. Maybe on PR merges into dev?

      if: github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged && github.ref == 'refs/heads/dev'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good flag if we run into more issues, but i think this should be fine for now

env:
FOUNDRY_PROFILE: "forktest"
RPC_MAINNET: ${{ secrets.RPC_MAINNET }}
RPC_HOLESKY: ${{ secrets.RPC_HOLESKY }}
CHAIN_ID: ${{ secrets.CHAIN_ID }}
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
68 changes: 37 additions & 31 deletions src/test/integration/IntegrationDeployer.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ abstract contract IntegrationDeployer is ExistingDeploymentParser {
// be returned from `_randUser`.
bytes assetTypes;
bytes userTypes;
bytes forkTypes;
// Set only once in configRand
// Set only once in setUp, if FORK_MAINNET env is set
uint forkType;

// Constants
Expand Down Expand Up @@ -183,10 +182,31 @@ abstract contract IntegrationDeployer is ExistingDeploymentParser {
*/
function setUp() public virtual {
isUpgraded = false;
// create mainnet fork that can be used later
mainnetForkId = cheats.createFork(cheats.rpcUrl("mainnet"), mainnetForkBlock);
// create holesky fork that can be used later
holeskyForkId = cheats.createFork(cheats.rpcUrl("holesky"), holeskyForkBLock);

/**
* env FOUNDRY_PROFILE=forktest forge t --mc Integration
*
* Running foundry like this will trigger the fork test profile,
* lowering fuzz runs and using a remote RPC to test against mainnet state
*/
bool forkMainnet =
_hash("forktest") ==
_hash(cheats.envOr(string("FOUNDRY_PROFILE"), string("default")));

if (forkMainnet) {
emit log("setUp: running tests against mainnet fork");
emit log_named_string("- using RPC url", cheats.rpcUrl("mainnet"));
emit log_named_uint("- forking at block", mainnetForkBlock);

cheats.createSelectFork(cheats.rpcUrl("mainnet"), mainnetForkBlock);
forkType = MAINNET;
} else {
emit log("setUp: running tests locally");

forkType = LOCAL;
}

_deployOrFetchContracts();
}

function _setUpLocal() public virtual {
Expand Down Expand Up @@ -608,8 +628,7 @@ abstract contract IntegrationDeployer is ExistingDeploymentParser {
function _configRand(
uint24 _randomSeed,
uint _assetTypes,
uint _userTypes,
uint _forkTypes
uint _userTypes
) internal {
// Using uint24 for the seed type so that if a test fails, it's easier
// to manually use the seed to replay the same test.
Expand All @@ -619,7 +638,6 @@ abstract contract IntegrationDeployer is ExistingDeploymentParser {
// Convert flag bitmaps to bytes of set bits for easy use with _randUint
assetTypes = _bitmapToBytes(_assetTypes);
userTypes = _bitmapToBytes(_userTypes);
forkTypes = _bitmapToBytes(_forkTypes);

emit log("_configRand: Users will be initialized with these asset types:");
for (uint i = 0; i < assetTypes.length; i++) {
Expand All @@ -631,17 +649,8 @@ abstract contract IntegrationDeployer is ExistingDeploymentParser {
emit log(userTypeToStr[uint(uint8(userTypes[i]))]);
}

emit log("_configRand: Tests will be shadow forked based on these fork types");
for (uint i = 0; i < forkTypes.length; i++) {
emit log(forkTypeToStr[uint(uint8(forkTypes[i]))]);
}

assertTrue(assetTypes.length != 0, "_configRand: no asset types selected");
assertTrue(userTypes.length != 0, "_configRand: no user types selected");
assertTrue(forkTypes.length != 0, "_configRand: no fork types selected");

// Use forkType to deploy contracts locally or fetch from mainnet
_deployOrFetchContracts();
}

/**
Expand All @@ -651,16 +660,14 @@ abstract contract IntegrationDeployer is ExistingDeploymentParser {
* Note: for non-LOCAL forktypes, upgrade of contracts will be peformed after user initialization.
*/
function _deployOrFetchContracts() internal {
forkType = _randForkType();

emit log_named_string("_deployOrFetchContracts selected fork for test", forkTypeToStr[forkType]);
emit log_named_string("_deployOrFetchContracts using fork for test", forkTypeToStr[forkType]);

if (forkType == LOCAL) {
_setUpLocal();
// Set Upgraded as local setup deploys most up to date contracts
isUpgraded = true;
} else if (forkType == MAINNET) {
cheats.selectFork(mainnetForkId);
// cheats.selectFork(mainnetForkId);
string memory deploymentInfoPath = "script/configs/mainnet/Mainnet_current_deployment.config.json";
_parseDeployedContracts(deploymentInfoPath);

Expand Down Expand Up @@ -688,7 +695,8 @@ abstract contract IntegrationDeployer is ExistingDeploymentParser {
// Create mock beacon chain / proof gen interface
beaconChain = new BeaconChainMock(timeMachine, beaconChainOracle, eigenPodManager);
} else if (forkType == HOLESKY) {
cheats.selectFork(holeskyForkId);
revert("_deployOrFetchContracts - holesky tests currently broken sorry");
// cheats.selectFork(holeskyForkId);
string memory deploymentInfoPath = "script/configs/holesky/Holesky_current_deployment.config.json";
_parseDeployedContracts(deploymentInfoPath);

Expand Down Expand Up @@ -727,7 +735,7 @@ abstract contract IntegrationDeployer is ExistingDeploymentParser {
cheats.stopPrank();

} else {
revert("_configEigenlayerContracts: unimplemented forkType");
revert("_deployOrFetchContracts: unimplemented forkType");
}
}

Expand Down Expand Up @@ -970,13 +978,6 @@ abstract contract IntegrationDeployer is ExistingDeploymentParser {
return userType;
}

function _randForkType() internal returns (uint) {
uint idx = _randUint({ min: 0, max: forkTypes.length - 1 });
uint randForkType = uint(uint8(forkTypes[idx]));

return randForkType;
}

/**
* @dev Converts a bitmap into an array of bytes
* @dev Each byte in the input is processed as indicating a single bit to flip in the bitmap
Expand Down Expand Up @@ -1028,4 +1029,9 @@ abstract contract IntegrationDeployer is ExistingDeploymentParser {

emit log("==================");
}

/// @dev Helper because solidity syntax is exhausting
function _hash(string memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(s));
}
}
21 changes: 20 additions & 1 deletion src/test/integration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ Good question.

This folder contains the integration framework and tests for Eigenlayer core, which orchestrates the deployment of all EigenLayer core contracts to fuzz high-level user flows across multiple user and asset types, and supports time-travelling state lookups to quickly compare past and present states (please try to avoid preventing your own birth).

**If you want to know how to run the tests**:

* Local: `forge t --mc Integration`
* Mainnet fork tests: `env FOUNDRY_PROFILE=forktest forge t --mc Integration`

Note that for mainnet fork tests, you'll need to set the `RPC_MAINNET` environment variable to your RPC provider of choice!

**If you want to know where the tests are**, take a look at `/tests`. We're doing one test contract per top-level flow, and defining multiple test functions for variants on that flow.

e.g. if you're testing the flow "deposit into strategies -> delegate to operator -> queue withdrawal -> complete withdrawal", that's it's own test contract. For variants where withdrawals are completed "as tokens" vs "as shares," those are their own functions inside that contract.
Expand Down Expand Up @@ -93,4 +100,16 @@ function testFuzz_deposit_delegate_EXAMPLE(uint24 _random) public {
### What needs to be done?

* Suggest or PR cleanup if you have ideas. Currently, the `IntegrationDeployer` contract is pretty messy.
* Coordinate in Slack to pick out some user flows to write tests for!
* Coordinate in Slack to pick out some user flows to write tests for!

#### Reduce RPC spam for fork tests

Currently our mainnet fork tests spam whatever RPC we use. We can improve this in the future - apparently the meta is:

> Use an anvil node to fork the network, you can write a script to make some changes to the forked network for setup etc, then fork your local node in your test.
> Effectively you just setup an anvil node with the command
`anvil -f RPC_URL `
You can use `anvil -h` for more info on what it can do.

> Then in your test you use the vm.createSelectFork command in your setup with the argument to point to your local anvil node which is basically a copy of the rpc you set it up as.
> If you want to do some setup before running your tests you can write a script file and broadcast the setup transactions to your local anvil node (make sure to use one of the private keys anvil gives you)
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ import "src/test/integration/IntegrationChecks.t.sol";
import "src/test/integration/users/User.t.sol";

contract Integration_Delegate_Deposit_Queue_Complete is IntegrationCheckUtils {

function testFuzz_delegate_deposit_queue_completeAsShares(uint24 _random) public {
// Configure the random parameters for the test
_configRand({
_randomSeed: _random,
_assetTypes: HOLDS_LST | HOLDS_ETH | HOLDS_ALL,
_userTypes: DEFAULT | ALT_METHODS,
_forkTypes: LOCAL | MAINNET
_userTypes: DEFAULT | ALT_METHODS
});
// Create a staker and an operator with a nonzero balance and corresponding strategies
(User staker, IStrategy[] memory strategies, uint[] memory tokenBalances) = _newRandomStaker();
Expand Down Expand Up @@ -50,8 +49,7 @@ contract Integration_Delegate_Deposit_Queue_Complete is IntegrationCheckUtils {
_configRand({
_randomSeed: _random,
_assetTypes: HOLDS_LST | HOLDS_ETH | HOLDS_ALL,
_userTypes: DEFAULT | ALT_METHODS,
_forkTypes: LOCAL | MAINNET
_userTypes: DEFAULT | ALT_METHODS
});

// Create a staker and an operator with a nonzero balance and corresponding strategies
Expand Down
15 changes: 5 additions & 10 deletions src/test/integration/tests/Deposit_Delegate_Queue_Complete.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ contract Integration_Deposit_Delegate_Queue_Complete is IntegrationCheckUtils {
_configRand({
_randomSeed: _random,
_assetTypes: HOLDS_LST | HOLDS_ETH | HOLDS_ALL,
_userTypes: DEFAULT | ALT_METHODS,
_forkTypes: LOCAL | MAINNET
_userTypes: DEFAULT | ALT_METHODS
});

/// 0. Create an operator and a staker with:
Expand Down Expand Up @@ -83,8 +82,7 @@ contract Integration_Deposit_Delegate_Queue_Complete is IntegrationCheckUtils {
_configRand({
_randomSeed: _random,
_assetTypes: HOLDS_LST | HOLDS_ETH | HOLDS_ALL,
_userTypes: DEFAULT | ALT_METHODS,
_forkTypes: LOCAL | MAINNET
_userTypes: DEFAULT | ALT_METHODS
});

/// 0. Create an operator and a staker with:
Expand Down Expand Up @@ -149,8 +147,7 @@ contract Integration_Deposit_Delegate_Queue_Complete is IntegrationCheckUtils {
_configRand({
_randomSeed: _random,
_assetTypes: HOLDS_LST | HOLDS_ETH | HOLDS_ALL,
_userTypes: DEFAULT | ALT_METHODS,
_forkTypes: LOCAL | MAINNET
_userTypes: DEFAULT | ALT_METHODS
});

/// 0. Create an operator and a staker with:
Expand Down Expand Up @@ -215,8 +212,7 @@ contract Integration_Deposit_Delegate_Queue_Complete is IntegrationCheckUtils {
_configRand({
_randomSeed: _random,
_assetTypes: HOLDS_LST | HOLDS_ETH | HOLDS_ALL,
_userTypes: DEFAULT | ALT_METHODS,
_forkTypes: LOCAL | MAINNET
_userTypes: DEFAULT | ALT_METHODS
});

/// 0. Create an operator and a staker with:
Expand Down Expand Up @@ -287,8 +283,7 @@ contract Integration_Deposit_Delegate_Queue_Complete is IntegrationCheckUtils {
_configRand({
_randomSeed: _random,
_assetTypes: NO_ASSETS | HOLDS_LST | HOLDS_ETH | HOLDS_ALL,
_userTypes: DEFAULT | ALT_METHODS,
_forkTypes: LOCAL | MAINNET
_userTypes: DEFAULT | ALT_METHODS
});

/// 0. Create a staker and operator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ contract Integration_Deposit_Delegate_Redelegate_Complete is IntegrationCheckUti
_configRand({
_randomSeed: _random,
_assetTypes: HOLDS_LST | HOLDS_ETH | HOLDS_ALL,
_userTypes: DEFAULT | ALT_METHODS,
_forkTypes: LOCAL | MAINNET
_userTypes: DEFAULT | ALT_METHODS
});

/// 0. Create an operator and a staker with:
Expand Down Expand Up @@ -91,8 +90,7 @@ contract Integration_Deposit_Delegate_Redelegate_Complete is IntegrationCheckUti
_configRand({
_randomSeed: _random,
_assetTypes: HOLDS_LST | HOLDS_ETH | HOLDS_ALL,
_userTypes: DEFAULT | ALT_METHODS,
_forkTypes: LOCAL | MAINNET
_userTypes: DEFAULT | ALT_METHODS
});

/// 0. Create an operator and a staker with:
Expand Down Expand Up @@ -177,8 +175,7 @@ contract Integration_Deposit_Delegate_Redelegate_Complete is IntegrationCheckUti
_configRand({
_randomSeed: _random,
_assetTypes: HOLDS_LST, // not holding ETH since we can only deposit 32 ETH multiples
_userTypes: DEFAULT | ALT_METHODS,
_forkTypes: LOCAL | MAINNET
_userTypes: DEFAULT | ALT_METHODS
});

/// 0. Create an operator and a staker with:
Expand Down Expand Up @@ -270,8 +267,7 @@ contract Integration_Deposit_Delegate_Redelegate_Complete is IntegrationCheckUti
_configRand({
_randomSeed: _random,
_assetTypes: HOLDS_LST, // not holding ETH since we can only deposit 32 ETH multiples
_userTypes: DEFAULT | ALT_METHODS,
_forkTypes: LOCAL | MAINNET
_userTypes: DEFAULT | ALT_METHODS
});

/// 0. Create an operator and a staker with:
Expand Down Expand Up @@ -363,8 +359,7 @@ contract Integration_Deposit_Delegate_Redelegate_Complete is IntegrationCheckUti
_configRand({
_randomSeed: _random,
_assetTypes: HOLDS_LST | HOLDS_ETH | HOLDS_ALL,
_userTypes: DEFAULT | ALT_METHODS,
_forkTypes: LOCAL | MAINNET
_userTypes: DEFAULT | ALT_METHODS
});

/// 0. Create operators and a staker
Expand Down Expand Up @@ -438,8 +433,7 @@ contract Integration_Deposit_Delegate_Redelegate_Complete is IntegrationCheckUti
_configRand({
_randomSeed: _random,
_assetTypes: HOLDS_LST | HOLDS_ETH | HOLDS_ALL,
_userTypes: DEFAULT | ALT_METHODS,
_forkTypes: LOCAL | MAINNET
_userTypes: DEFAULT | ALT_METHODS
});

/// 0. Create operators and a staker
Expand Down
Loading