Prime Staked ETH is liquid restaking built on top of EigenLayer.
| Contract Name | Address |
|---|---|
| PrimeZapper | 0x3cf4Db4c59dCB082d1A9719C54dF3c04Db93C6b7 |
The following are Open Zeppelin contracts.
| Contract Name | Address |
|---|---|
| ProxyFactory | 0x279b272E8266D2fd87e64739A8ecD4A5c94F953D |
| ProxyAdmin | 0xF83cacA1bC89e4C7f93bd17c193cD98fEcc6d758 |
The protocol is currently managed by a Gnosis Safe, 3 of 7 multi-signature wallet.
| Contract Name | Address |
|---|---|
| ProxyAdmin Owner | 0xEc574b7faCEE6932014EbfB1508538f6015DCBb0 |
| Admin | 0xEc574b7faCEE6932014EbfB1508538f6015DCBb0 |
| Manager | 0xEc574b7faCEE6932014EbfB1508538f6015DCBb0 |
| Operator | 0xEc574b7faCEE6932014EbfB1508538f6015DCBb0 |
| Contract Name | Address |
|---|---|
| Origin (OETH) | 0x856c4Efb76C1D1AE02e20CEB03A2A6a08b0b8dC3 |
| Mantle (mETH) | 0xd5f7838f5c461feff7fe49ea5ebaf7728bb0adfa |
| Stader (ETHx) | 0xA35b1B31Ce002FBF2058D22F30f95D405200A15b |
| Lido (stETH) | 0xae7ab96520de3a18e5e111b5eaab095312d7fe84 |
| Staked Frax (sfrxETH) | 0xac3E018457B222d93114458476f3E3416Abbe38F |
| Rocket Pool (rETH) | 0xae78736cd615f374d3085123a210448e74fc6393 |
| Swell (swETH) | 0xf951E335afb289353dc249e82926178EaC7DEd78 |
| LST | Price Provider | Price Source |
|---|---|---|
| Origin (OETH) | fixed 1 ETH | |
| Mantle (mETH) | mETHToETH on Mantle Staking |
0xe3cBd06D7dadB3F4e6557bAb7EdD924CD1489E8f |
| Stader (ETHx) | getExchangeRate on Stake Pools Manager |
0xcf5EA1b38380f6aF39068375516Daf40Ed70D299 |
| Lido (stETH) | ChainLink | 0x86392dC19c0b719886221c78AB11eb8Cf5c52812 |
| Staked Frax (sfrxETH) | Frax Dual Oracle | 0x584902BCe4282003E420Cf5b7ae5063D6C1c182a |
| Rocket Pool (rETH) | ChainLink | 0xf397bF97280B488cA19ee3093E81C0a77F02e9a5 |
| Swell (swETH) | RedStone | 0x061bB36F8b67bB922937C102092498dcF4619F86 |
EigenLayer's mainnet contract addresses
- Install dependencies
npm install
forge install- copy .env.example to .env and fill in the values
cp .env.example .envThis is a list of the most frequently needed commands.
Delete the build artifacts and cache directories:
forge cleanCompile the contracts:
forge buildFormat the contracts:
forge fmtLint the contracts:
$ npm lintmake unit-testRun the fork tests against mainnet or a local. The FORK_RPC_URL env var controls whether the fork tests run against
mainnet or a local forked node.
make fork-testGenerate test coverage and output result to the terminal:
$ npm test:coverageGenerate test coverage with lcov report (you'll have to open the ./coverage/index.html file in your browser, to do so
simply copy paste the path):
$ npm test:coverage:reportGet a gas report:
$ forge test --gas-reportThe runs the Goerli deployment in a fork and does not broadcast the transactions to the local Anvil node. The contracts will NOT be deployed to the local Anvil node.
Set GOERLI_DEPLOYER_PRIVATE_KEY and FORK_RPC_URL environment variables in the .env file.
In one terminal run
make node-test-forkIn another terminal run
make deploy-testnet-forkSet GOERLI_DEPLOYER_PRIVATE_KEY, GOERLI_RPC_URL and GOERLI_ETHERSCAN_API_KEY environment variables in the .env
file.
make deploy-testnetUpdate the address in Addresses.sol if this new deployment is going to be used for more Goerli testing.
In one terminal run the Anvil node forking the mainnet
make node-forkIn another terminal apply the deploys that are not yet on mainnet.
make pool-deleg-oracle-fork
make add-assets-forkmake deploy-lrt-local-testCreate a new ordered deploy script in script/foundry-scripts/mainnet. For example, 10_deployNativeETH.s.sol
To run the script as a dry-run against a local forked node, start an Anvil node in one terminal:
make node-forkAnd run the following in a new terminal:
IS_FORK=true forge script script/foundry-scripts/mainnet/10_deployNativeETH.s.sol:DeployNativeETH --rpc-url localhost --broadcast -vvvTo run the script against mainnet, set DEPLOYER_PRIVATE_KEY in your .env file and following command:
forge script script/foundry-scripts/mainnet/10_deployNativeETH.s.sol:DeployNativeETH --rpc-url ${MAINNET_RPC_URL} --broadcast --etherscan-api-key ${ETHERSCAN_API_KEY} --verify -vvvFor instructions on how to deploy to a testnet or mainnet, check out the Solidity Scripting tutorial.
Follow this pattern contractAddress=<contractAddress> contractPath=<contract-path> make verify-contract-testnet
Example:
contractAddress=0x0000000000000000000000000000000000000000 contractPath=contracts/LRTConfig.sol:LRTConfig make verify-contract-testnetOpen Zeppelin Defender v2 is used to manage the Operations account and automate AMM operational jobs like updating the primeETH exchange rate.
The Prime Staked operator account is a Defender v2 Relayer
account with address
0x5De069482Ac1DB318082477B7B87D59dfB313f91.
To create an API key for the Relayer account go to the Manage tab on the top right of the Defender UI.
Click Relayers on the left menu and select the
Prime Staked
Relayer.
Click the Create new API Key to get the new API key and secret.
Add the API key and secret to the .env file.
# Open Zeppelin Defender Relayer account API key
DEFENDER_RELAYER_KEY=
DEFENDER_RELAYER_SECRET=
⚠️ Remember to delete the API key when you are done using it.
Actions are used to run operational jobs are specific times or intervals.
rollup is used to bundle Actions source code in /script/defender-actions into a single file that can be uploaded to Defender. The implementation was based off. Defender Actions example using Rollup. The rollup config is in /script/defender-actions/rollup.config.cjs. The outputs are written to folders under /script/defender-actions/dist.
The defender-autotask CLI is used to upload the
Action code to Defender. For this to work, a Defender Team API key with Manage Actions capabilities is needed. This
can be generated by a Defender team admin under the Manage tab on the top right of the UI and then API Keys on the
left menu. Best to unselect all capabilities except Manage Actions.
Save the Defender Team API key and secret to your .env file.
# Open Zeppelin Defender Team API key
DEFENDER_TEAM_KEY=
DEFENDER_TEAM_SECRET=
The following will bundle the Actions code ready for upload.
cd ./script/defender-actions
npx rollup -c
The following will upload the different Action bundles to Defender.
# change to the defender-actions folder
cd ./script/defender-actions
npx rollup -c
# Export the DEFENDER_TEAM_KEY and DEFENDER_TEAM_SECRET environment variables
export DEFENDER_TEAM_KEY=
export DEFENDER_TEAM_SECRET=
# Alternatively, the following can be used but it will export all env var including DEPLOYER_PRIVATE_KEY
# set -o allexport && source ../../.env && set +o allexport
# Set the DEBUG environment variable to prime* for the Defender Action
npx hardhat setActionVars --id 184e6533-9413-48be-ac01-4a63f87c3035
npx hardhat setActionVars --id 7dda695d-56b1-48ba-9e9a-3307c4a2f7bb
npx hardhat setActionVars --id 0cfd91ac-1248-4470-ba1f-e58cd8514b3d
npx hardhat setActionVars --id d990c176-897d-4739-8f20-563fbacf11b0
# Upload Deposit to EigenLayer code
# The Defender autotask client uses generic env var names so we'll set them first from the values in the .env file
export API_KEY=${DEFENDER_TEAM_KEY}
export API_SECRET=${DEFENDER_TEAM_SECRET}
# Goerli
npx defender-autotask update-code 7dda695d-56b1-48ba-9e9a-3307c4a2f7bb ./dist/operateValidators
# Mainnet
npx defender-autotask update-code 184e6533-9413-48be-ac01-4a63f87c3035 ./dist/depositAllEL
npx defender-autotask update-code d990c176-897d-4739-8f20-563fbacf11b0 ./dist/transferWETH
npx defender-autotask update-code 0cfd91ac-1248-4470-ba1f-e58cd8514b3d ./dist/operateValidatorsrollup and defender-autotask-client can be installed globally to avoid the npx prefix.
| Name | ID | Source Code |
|---|---|---|
| Prime - Deposit LSTs to EigenLayer | 184e6533-9413-48be-ac01-4a63f87c3035 | /script/defender-actions/depositAllEL.js |
| Prime - transfer WETH to Native Staking NodeDelegatorETH | d990c176-897d-4739-8f20-563fbacf11b0 | /script/defender-actions/transferWETH.js |
| Prime - primeETH Price Updater | e5ab3a21-ed4d-4b0a-b07a-c3127a59895c | |
| Prime - Add validator | 0cfd91ac-1248-4470-ba1f-e58cd8514b3d | /script/defender-actions/operateValidators.js |
Make sure the HOLESKY_RPC_URL environment variable is set in the .env file.
Generate an API key for the Holesky Defender Relayer and set the DEFENDER_RELAYER_KEY and DEFENDER_RELAYER_SECRET
environment variables in the .env file.
export DEBUG=prime*
npx hardhat depositWETH --amount 32 --network holesky
npx hardhat depositPrime --symbol WETH --amount 32 --network holesky
npx hardhat depositEL --symbol WETH --index 1 --network holesky
npx hardhat operateValidators --network holesky
This section contains the required steps and dependencies to create validator keys and splitting them.
First, download the "staking-deposit-cli" tool from the ethereum release page which is a CLI tool for generating keystore files. Extract the file and move it somewhere on the $PATH (e.g. /usr/local/bin)
Create a new mnemonic in offline mode:
deposit new-mnemonicFollow the wizard and create a required number of validator keys - the wizard asks what number of keys are required -
along with the validator deposit data. Example validator keys for mnemonic "daughter topple square amount rich elder
regret blade crisp auto burden shoe enrich weasel apart case space zebra require oyster stadium icon truly result" is
located in validator_key_data/validator_keys
After that create shares data that can be used by the DVT to deploy distributed validators. See example command:
npx hardhat splitValidatorKey --network goerli --operatorids 60.79.220.349 --operatorkeys LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMHZPbHNpTzVCV0dDTEM1TUxDQW8KYkN0ZDI5NmNvaFN0MGhhMmtpRjMwNi9NR2Y5OVRORCs0TmpRWXNEQVlFYVJjZFhNUjY1bjdHTk4yUkkxdTg0aQpTZm04NElKTTdIRGsxeUpVTGdGcnRmQ00yWG03ZzFYODZ3ZkZGT2JrWUJSQmNIZnZSZUxHcDdzdjFpSFh1M2s3CkszVzJvUnZhV2U4V3k3MGdXS25jeWROakZpWDJIQ2psQnIyRjhJT0Z0SHI3cGpyWnZqa0ROcDFkMnprK2V6YncKdCticUMySnFSaVF4MGI5d0d4d3h0UERERjY0amVtWDRpMkJPWXNvUkx6dkN6dWtaeHB3UlNJOW1wTHE1UktOaApIY1pEcWg3RUV5VFloUG1BTTcvT2luMWROZCtNUi9VRU5mTkJqMGZMVURhZWJWSUVVMEhzRzMzdHV3MmR5RksxCnRRSURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K.LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBbzRtb2hUcVdKRGhyYkp5MlhXeXUKQjZIOFU3OXpxS2VhdGdweGRIcS9iWkxrTHpNcE10SVNNOEd3ckUxVlhmMUZ1RWhqcXhTQko0V1hnb0RxWGZTNQp4Q0RIeUdwSld1STF5Q3V5Z3NLRE96QkU4OWZaZEZlY1BsQTZpbzYxR0ROWkJPOWNEOGY2VnFiblN1TDRIMEZjCnkwdk5SdmdROWhEUFJZcHhMVER6N1gyU1RYZWk5eGcyVVdBYm01QUZVbm9WR01yZ2R4YkY5ZjlaNDZDZVk0TFgKL3pqQW1DNFl5YVlYZk9TL2lzQkZkYTN3RlFZZmVhcVVWb2huOCt6ZFg3Y2p4SVZrdDVtQ2FqVFo2bXJzWEFBNApzTDQxaEM4Z0NKYmdESDhIcEZaVXViYUFFUEswV1dZOENCUEhMY1dtWWxLeEJhVEdaU25SM2ZBN3hRcU5lK3VvCkl3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K.LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBeUtiUGc2SXRnTGJSTHpHK0VhMUcKSGdSQm45a3J2N2pXN09ocGxqQWg3MUtCVnFNVldtZi9LRVlBUis1Qnp2bGdwV3ptc3pxZ3MyeDN6UzB5MHd0Zgp6WkVLZ2NrMDJIcXVTMzIwTUJ2QTBLN3B0OFc4Qm9ZM3ozS3d4bUpwUnNwZ3p5dm80TGIyU3RsL1FBNFE4cjZsCjVOWjdrRVNHVktFTFA3R3JrQTlYajBOS0wxZU5uYTRocnpEcnpJS1FwMGZkcjBpWWFxRnhNWUZBZ0FUcVp2b1kKbGxDWG16TmdaUDdtaERRWTdWSk9kenJkSTBrOEdISTZpWUFlWUExRVR1Y01mckpzMmd0a0FPRlR6TjhYYW5VWgpkQis1c0g2V0UwSGhvVGFCeGYwcHpnTFpvenROdTdpUzFmRlZOTUNnR3BCc3MxMDcxMEZFNE1aYW1uWFMxeWt5ClN3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K.LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBd1l0MEdGdmRORTA3L1NuNGdSSnUKNkhlWHU0S3RkL1k1ZGkweGFFNUNyYXZyenU3ZXNIZzg0SXRmcURVbTQrVTNJQm9LelFkdUNKdkw5L1FwTG5LaApTanRzcEpid0gxd2liYXppcVFuM08zbVljb0tYWjAvWDVJamoyUG9hVG13cUkrTFlLbUNXNWFQR3psWklpYUF2ClNGQ2V6M3BFTllQOFNlMFRObm1UaWNuMGRkVkIwMU9uRzJxZEZIMXhBRGNxckFwTE52NmVhMzF6eUdRTG9FbHoKTzFMK2VjZzB3SHRON0hqYnZGUDczcDF5TTA4UU1LRzV6ellKUTVJWmEwL3lWK213blJpSjZTcTZEUkgxd1JwYQpHeXpYQWNqYTBJSER0ckJPdCtOQ2grZS8vVU1Gd3B3OS8zMG5rN2JBRVBOcDY3Qks3Q0tnU0FHLzhxcmt4bHRVCi93SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K --keystorelocation validator_key_data/validator_keys/keystore-m_12381_3600_1_0_0-1708952408.json --keystorepass testtestThanks to the incentive program from SSV, Openzeppelin Defender Relayer can claim SSV tokens each month. Follow these steps to claim them:
- Go on https://ssvscan.io/claim/
- Using RabbyWallet (or equivalent), impersonate Relayer address
- Click "Claiming Rewards" (green button)
- Open the RabbyWallet pop-up
- Click on "View Raw", it should open the transaction data by default.
- Copy the
datasection, it should be something like 0x1a4e41c2... This is the PAYLOAD. - In a terminal, on the root of the repo, run:
npx hardhat --network mainnet claimSSV --payload PAYLOADto claim the SSV token and transfer them to the relayer.npx hardhat --network mainnet balance --symbol SSVto check how many SSV token hold the relayer.npx hardhat --network mainnet transfer --amount AMOUNT --symbol SSV --to MULTI_SIGto transfer SSV token to multisig. The amount should be in ether. For example, if you want to transfer48927251356344789668tokens, write48.927. This is important to remove some decimals otherwise the transaction may fail.
This repo was originally forked from Kelp DAO. It's been further developed by Origin Protocol since January 2024.



