Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hardhat tasks for Native Staking #2085

Merged
merged 6 commits into from
Jun 3, 2024
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
7 changes: 4 additions & 3 deletions contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -343,15 +343,16 @@ export DEFENDER_TEAM_SECRET=
# Set the DEBUG environment variable to oeth* for the Defender Action
npx hardhat setActionVars --id 38e44420-f38b-4d4a-86b0-6012a8897ad9
npx hardhat setActionVars --id f4b5b8d4-82ff-483f-bfae-9fef015790ca
npx hardhat setActionVars --id 191d9631-70b9-43c5-9db4-1dd985fde05c

# 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}
# Holesky
npx defender-autotask update-code 38e44420-f38b-4d4a-86b0-6012a8897ad9 ./dist/operateValidators
npx defender-autotask update-code 38e44420-f38b-4d4a-86b0-6012a8897ad9 ./dist/registerValidators
npx defender-autotask update-code 191d9631-70b9-43c5-9db4-1dd985fde05c ./dist/doAccounting
# Mainnet
npx defender-autotask update-code f4b5b8d4-82ff-483f-bfae-9fef015790ca ./dist/operateValidators
npx defender-autotask update-code f4b5b8d4-82ff-483f-bfae-9fef015790ca ./dist/registerValidators
```

`rollup` and `defender-autotask-client` can be installed globally to avoid the `npx` prefix.
Expand Down
12 changes: 11 additions & 1 deletion contracts/dev.env
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,14 @@ ACCOUNTS_TO_FUND=

#P2P API KEYS
P2P_MAINNET_API_KEY=[SET API Key]
P2P_HOLESKY_API_KEY=[SET API Key]
P2P_HOLESKY_API_KEY=[SET API Key]

# Defender Team Key needed to upload code to Actions
# DEFENDER_TEAM_KEY=
# DEFENDER_TEAM_SECRET=

# Defender Relayer API key
# HOLESKY_DEFENDER_API_KEY=
# HOLESKY_DEFENDER_API_SECRET=
# DEFENDER_API_KEY=
# DEFENDER_API_SECRET=
1 change: 1 addition & 0 deletions contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"papaparse": "^5.3.1",
"prettier": "^2.3.2",
"prettier-plugin-solidity": "1.0.0-beta.17",
"rollup": "^4.18.0",
"solc": "0.8.6",
"solhint": "^3.4.1",
"solidifier": "^2.2.3",
Expand Down
42 changes: 42 additions & 0 deletions contracts/scripts/defender-actions/doAccounting.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const { ethers } = require("ethers");
const {
DefenderRelaySigner,
DefenderRelayProvider,
} = require("@openzeppelin/defender-relay-client/lib/ethers");
const addresses = require("../../utils/addresses");
const { logTxDetails } = require("../../utils/txLogger");

const nativeStakingStrategyAbi = require("../../abi/native_staking_SSV_strategy.json");

const log = require("../../utils/logger")("action:doAccounting");

// Entrypoint for the Defender Action
const handler = async (event) => {
console.log(
`DEBUG env var in handler before being set: "${process.env.DEBUG}"`
);

// Initialize defender relayer provider and signer
const provider = new DefenderRelayProvider(event);
const signer = new DefenderRelaySigner(event, provider, { speed: "fastest" });

const network = await provider.getNetwork();
const networkName = network.chainId === 1 ? "mainnet" : "holesky";
log(`Network: ${networkName} with chain id (${network.chainId})`);

const nativeStakingProxyAddress =
addresses[networkName].NativeStakingSSVStrategyProxy;
log(
`Resolved Native Staking Strategy address to ${nativeStakingProxyAddress}`
);
const nativeStakingStrategy = new ethers.Contract(
nativeStakingProxyAddress,
nativeStakingStrategyAbi,
signer
);

const tx = await nativeStakingStrategy.connect(signer).doAccounting();
await logTxDetails(tx, "doAccounting");
};

module.exports = { handler };
34 changes: 9 additions & 25 deletions contracts/scripts/defender-actions/registerValidators.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,29 @@ const addresses = require("../../utils/addresses");
const nativeStakingStrategyAbi = require("../../abi/native_staking_SSV_strategy.json");
const IWETH9Abi = require("../../abi/IWETH9.json");

const log = require("../../utils/logger")("action:operateValidators");
const log = require("../../utils/logger")("action:registerValidators");

// Entrypoint for the Defender Action
const handler = async (event) => {
const store = new KeyValueStoreClient(event);
// Initialize defender relayer provider and signer
console.log(
`DEBUG env var in handler before being set: "${process.env.DEBUG}"`
);

const store = new KeyValueStoreClient(event);

// Initialize defender relayer provider and signer
const provider = new DefenderRelayProvider(event);
const signer = new DefenderRelaySigner(event, provider, { speed: "fastest" });

const network = await provider.getNetwork();
const networkName = network.chainId === 1 ? "mainnet" : "holesky";
log(`Network: ${networkName} with chain id (${network.chainId})`);
console.log(`Network: ${networkName} with chain id (${network.chainId})`);

const nativeStakingProxyAddress =
addresses[networkName].NativeStakingSSVStrategyProxy;
log(
`Resolved Native Staking Strategy address to ${nativeStakingProxyAddress}`
);
console.log(
`Resolved Native Staking Strategy address to ${nativeStakingProxyAddress}`
);
const nativeStakingStrategy = new ethers.Contract(
nativeStakingProxyAddress,
nativeStakingStrategyAbi,
Expand All @@ -46,17 +43,11 @@ const handler = async (event) => {

const wethAddress = addresses[networkName].WETH;
log(`Resolved WETH address to ${wethAddress}`);
console.log(`Resolved WETH address to ${wethAddress}`);
const WETH = new ethers.Contract(wethAddress, IWETH9Abi, signer);

const feeAccumulatorAddress =
await nativeStakingStrategy.FEE_ACCUMULATOR_ADDRESS();

const contracts = {
nativeStakingStrategy,
WETH,
};

const p2p_api_key =
network.chainId === 1
? event.secrets.P2P_MAINNET_API_KEY
Expand All @@ -69,25 +60,18 @@ const handler = async (event) => {
const p2p_base_url =
network.chainId === 1 ? "api.p2p.org" : "api-test-holesky.p2p.org";

const config = {
await registerValidators({
signer,
store,
nativeStakingStrategy,
WETH,
feeAccumulatorAddress,
p2p_api_key,
p2p_base_url,
// how much SSV (expressed in days of runway) gets deposited into the
// SSV Network contract on validator registration. This is calculated
// at a Cluster level rather than a single validator.
validatorSpawnOperationalPeriodInDays: 1,
// Stake the 32 ETH into the validator
stake: true,
// Clear the local state of the Defender Action
clear: true,
};

await registerValidators({
signer,
contracts,
store,
config,
});
};

Expand Down
11 changes: 11 additions & 0 deletions contracts/scripts/defender-actions/rollup.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ module.exports = [
input: "registerValidators.js",
output: {
file: "dist/registerValidators/index.js",
inlineDynamicImports: true,
format: "cjs",
},
},
Expand All @@ -40,6 +41,16 @@ module.exports = [
input: "stakeValidators.js",
output: {
file: "dist/stakeValidators/index.js",
inlineDynamicImports: true,
format: "cjs",
},
},
{
...commonConfig,
input: "doAccounting.js",
output: {
file: "dist/doAccounting/index.js",
inlineDynamicImports: true,
format: "cjs",
},
},
Expand Down
70 changes: 70 additions & 0 deletions contracts/scripts/defender-actions/stakeValidators.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const { ethers } = require("ethers");
const {
DefenderRelaySigner,
DefenderRelayProvider,
} = require("@openzeppelin/defender-relay-client/lib/ethers");
const {
KeyValueStoreClient,
} = require("@openzeppelin/defender-kvstore-client");
const { stakeValidators } = require("../../tasks/validator");
const addresses = require("../../utils/addresses");

const nativeStakingStrategyAbi = require("../../abi/native_staking_SSV_strategy.json");
const IWETH9Abi = require("../../abi/IWETH9.json");

const log = require("../../utils/logger")("action:stakeValidators");

// Entrypoint for the Defender Action
const handler = async (event) => {
console.log(
`DEBUG env var in handler before being set: "${process.env.DEBUG}"`
);

const store = new KeyValueStoreClient(event);

// Initialize defender relayer provider and signer
const provider = new DefenderRelayProvider(event);
const signer = new DefenderRelaySigner(event, provider, { speed: "fastest" });

const network = await provider.getNetwork();
const networkName = network.chainId === 1 ? "mainnet" : "holesky";
log(`Network: ${networkName} with chain id (${network.chainId})`);

const nativeStakingProxyAddress =
addresses[networkName].NativeStakingSSVStrategyProxy;
log(
`Resolved Native Staking Strategy address to ${nativeStakingProxyAddress}`
);
const nativeStakingStrategy = new ethers.Contract(
nativeStakingProxyAddress,
nativeStakingStrategyAbi,
signer
);

const wethAddress = addresses[networkName].WETH;
log(`Resolved WETH address to ${wethAddress}`);
const WETH = new ethers.Contract(wethAddress, IWETH9Abi, signer);

const p2p_api_key =
network.chainId === 1
? event.secrets.P2P_MAINNET_API_KEY
: event.secrets.P2P_HOLESKY_API_KEY;
if (!p2p_api_key) {
throw new Error(
"Secret with P2P API key not set. Add the P2P_MAINNET_API_KEY or P2P_HOLESKY_API_KEY secret"
);
}
const p2p_base_url =
network.chainId === 1 ? "api.p2p.org" : "api-test-holesky.p2p.org";

await stakeValidators({
signer,
store,
nativeStakingStrategy,
WETH,
p2p_api_key,
p2p_base_url,
});
};

module.exports = { handler };
21 changes: 21 additions & 0 deletions contracts/tasks/harvest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const { resolveContract } = require("../utils/resolvers");
const { getSigner } = require("../utils/signers");
const { logTxDetails } = require("../utils/txLogger");

const log = require("../utils/logger")("task:harvest");

async function harvestAndSwap({ strategy, harvester }) {
const signer = await getSigner();

const harvesterContract = await resolveContract(harvester, "OETHHarvester");
const strategyContract = await resolveContract(strategy);

log(`Harvesting and swapping for strategy ${strategyContract.address}`);
const tx = await harvesterContract.connect(signer)[
// eslint-disable-next-line no-unexpected-multiline
"harvestAndSwap(address)"
](strategyContract.address);
await logTxDetails(tx, "harvestAndSwap");
}

module.exports = { harvestAndSwap };
2 changes: 1 addition & 1 deletion contracts/tasks/ssv.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const depositSSV = async ({ amount, operatorids }, hre) => {
const clusterInfo = await getClusterInfo({
chainId: hre.network.config.chainId,
ssvNetwork: ssvNetwork.address,
operatorIds: operatorids,
operatorids,
ownerAddress: strategy.address,
});

Expand Down
Loading