Skip to content
Open
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
11 changes: 4 additions & 7 deletions contracts/contracts/interfaces/ISSVNetwork.sol
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,8 @@ interface ISSVNetwork {
function deposit(
address clusterOwner,
uint64[] memory operatorIds,
uint256 amount,
Cluster memory cluster
) external;
) external payable;

function executeOperatorFee(uint64 operatorId) external;

Expand Down Expand Up @@ -201,11 +200,9 @@ interface ISSVNetwork {

function proxiableUUID() external view returns (bytes32);

function reactivate(
uint64[] memory operatorIds,
uint256 amount,
Cluster memory cluster
) external;
function reactivate(uint64[] memory operatorIds, Cluster memory cluster)
external
payable;

function reduceOperatorFee(uint64 operatorId, uint256 fee) external;

Expand Down
3 changes: 1 addition & 2 deletions contracts/contracts/mocks/MockSSVNetwork.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@ contract MockSSVNetwork {
function deposit(
address clusterOwner,
uint64[] calldata operatorIds,
uint256 amount,
Cluster memory cluster
) external {}
) external payable {}

function setFeeRecipientAddress(address recipient) external {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
const addresses = require("../../utils/addresses");
const { deploymentWithGovernanceProposal } = require("../../utils/deploy");

const strategyConfigs = [
{
proxyName: "NativeStakingSSVStrategy2Proxy",
label: "2nd Native Staking SSV Strategy",
},
{
proxyName: "NativeStakingSSVStrategy3Proxy",
label: "3rd Native Staking SSV Strategy",
},
{
proxyName: "CompoundingStakingSSVStrategyProxy",
label: "Compounding Staking SSV Strategy",
},
];

module.exports = deploymentWithGovernanceProposal(
{
deployName: "195_claim_ssv_from_staking_strategies",
forceDeploy: false,
reduceQueueTime: true,
deployerIsProposer: false,
proposalId: "",
},
async ({ ethers }) => {
const ssv = await ethers.getContractAt("IERC20", addresses.mainnet.SSV);
const recipient = addresses.multichainStrategist;
const actions = [];

let totalSSV = ethers.BigNumber.from(0);

for (const strategyConfig of strategyConfigs) {
const proxy = await ethers.getContract(strategyConfig.proxyName);
const strategy = await ethers.getContractAt("IStrategy", proxy.address);
const balance = await ssv.balanceOf(strategy.address);

console.log(
`${strategyConfig.label} ${
strategy.address
} has ${ethers.utils.formatEther(balance)} SSV`
);

if (balance.isZero()) {
continue;
}

actions.push({
contract: strategy,
signature: "transferToken(address,uint256)",
args: [ssv.address, balance],
});

totalSSV = totalSSV.add(balance);
}

if (totalSSV.isZero()) {
throw new Error("No SSV found on staking strategies");
}

actions.push({
contract: ssv,
signature: "transfer(address,uint256)",
args: [recipient, totalSSV],
});

console.log(
`Transferring ${ethers.utils.formatEther(totalSSV)} SSV to ${recipient}`
);

return {
name: "Claim SSV from staking strategies and transfer to Guardian multisig",
actions,
};
}
);
3 changes: 2 additions & 1 deletion contracts/deployments/mainnet/.migrations.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,5 +78,6 @@
"189_harvesting_eip1271_ogn": 1774552993,
"190_remove_3rd_native_staking_strategy": 1775468903,
"192_migrate_ssv_clusters_to_eth": 1777859891,
"193_permissioned_rebase_module": 1778095857
"193_permissioned_rebase_module": 1778095857,
"195_claim_ssv_from_staking_strategies": 1778480807
}
19 changes: 11 additions & 8 deletions contracts/tasks/ssv.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,11 @@ const printClusterInfo = async (options) => {
console.log(`Cluster: ${JSON.stringify(cluster.cluster, null, " ")}`);
};

const depositSSV = async ({ amount, index, operatorids }) => {
const depositCluster = async ({ amount, index, operatorids }) => {
const amountBN = parseUnits(amount.toString(), 18);
log(`Splitting operator IDs ${operatorids}`);
const operatorIds = await sortOperatorIds(operatorids);
const sortedOperatorIds = await sortOperatorIds(operatorids);
const operatorIds = splitOperatorIds(sortedOperatorIds);

const signer = await getSigner();

Expand All @@ -78,22 +79,24 @@ const depositSSV = async ({ amount, index, operatorids }) => {
const clusterInfo = await getClusterInfo({
chainId,
ssvNetwork: ssvNetwork.address,
operatorids,
operatorids: sortedOperatorIds,
ownerAddress: strategy.address,
});

log(
`About to deposit ${formatUnits(
amountBN
)} SSV tokens to the SSV Network for native staking strategy ${
)} ETH to the SSV Network for native staking strategy ${
strategy.address
} with operator IDs ${operatorIds}`
);
log(`Cluster: ${JSON.stringify(clusterInfo.cluster)}`);
const tx = await strategy
const tx = await ssvNetwork
.connect(signer)
.depositSSV(operatorIds, amountBN, clusterInfo.cluster);
await logTxDetails(tx, "depositSSV");
.deposit(strategy.address, operatorIds, clusterInfo.cluster, {
value: amountBN,
});
await logTxDetails(tx, "depositCluster");
};

const migrateClusterToETH = async ({ type, amount, operatorids, index }) => {
Expand Down Expand Up @@ -136,7 +139,7 @@ const migrateClusterToETH = async ({ type, amount, operatorids, index }) => {

module.exports = {
printClusterInfo,
depositSSV,
depositCluster,
migrateClusterToETH,
removeValidator,
};
91 changes: 9 additions & 82 deletions contracts/tasks/tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const { calculateMaxPricePerVoteTask, manageBribes } = require("./poolBooster");
const { updateVotemarketEpochsTask } = require("./votemarket");
const { manageMerklBribesTask } = require("./merklPoolBooster");
const {
depositSSV,
depositCluster,
migrateClusterToETH,
printClusterInfo,
removeValidator: removeOldValidator,
Expand All @@ -92,7 +92,6 @@ const {
updateWOETHOraclePrice,
} = require("./strategy");
const {
validatorOperationsConfig,
exitValidator,
doAccounting,
manuallyFixAccounting,
Expand Down Expand Up @@ -123,7 +122,6 @@ const {
undelegateValidator,
withdrawFromSFC,
} = require("../utils/sonicActions");
const { registerValidators, stakeValidators } = require("../utils/validator");
const { harvestAndSwap } = require("./harvest");
const { deployForceEtherSender, forceSend } = require("./simulation");
const { sleep } = require("../utils/time");
Expand Down Expand Up @@ -1160,10 +1158,10 @@ task("getClusterInfo").setAction(async (_, __, runSuper) => {
});

subtask(
"depositSSV",
"Deposit SSV tokens from the native staking strategy into an SSV Cluster"
"depositCluster",
"Deposit ETH into an SSV cluster for a native staking strategy"
)
.addParam("amount", "Amount of SSV tokens to deposit", undefined, types.float)
.addParam("amount", "Amount of ETH to deposit", undefined, types.float)
.addOptionalParam(
"index",
"The number of the Native Staking Contract deployed.",
Expand All @@ -1176,8 +1174,8 @@ subtask(
undefined,
types.string
)
.setAction(depositSSV);
task("depositSSV").setAction(async (_, __, runSuper) => {
.setAction(depositCluster);
task("depositCluster").setAction(async (_, __, runSuper) => {
return runSuper();
});

Expand Down Expand Up @@ -1273,77 +1271,6 @@ task("deployStakingProxy").setAction(async (_, __, runSuper) => {
return runSuper();
});

// Validator Operations

subtask(
"registerValidators",
"Creates the required amount of new SSV validators and stakes ETH"
)
.addOptionalParam(
"days",
"SSV Cluster operational time in days",
2,
types.int
)
.addOptionalParam(
"validators",
"The number of validators to register. defaults to the max that can be registered",
undefined,
types.int
)
.addOptionalParam("clear", "Clear storage", false, types.boolean)
.addOptionalParam(
"eth",
"Override the days option and set the amount of ETH to deposit to the cluster.",
undefined,
types.float
)
.addOptionalParam(
"uuid",
"uuid of P2P's request SSV validator API call. Used to reprocess a registration that failed to get the SSV request status.",
undefined,
types.string
)
.addOptionalParam(
"index",
"The number of the Native Staking Contract deployed.",
undefined,
types.int
)
.setAction(async (taskArgs) => {
const config = await validatorOperationsConfig(taskArgs);
const signer = await getSigner();
await registerValidators({ ...config, signer });
});
task("registerValidators").setAction(async (_, __, runSuper) => {
return runSuper();
});

subtask(
"stakeValidators",
"Creates the required amount of new SSV validators and stakes ETH"
)
.addOptionalParam(
"uuid",
"uuid of P2P's request SSV validator API call",
undefined,
types.string
)
.addOptionalParam(
"index",
"The number of the Native Staking Contract deployed.",
undefined,
types.int
)
.setAction(async (taskArgs) => {
const config = await validatorOperationsConfig(taskArgs);
const signer = await getSigner();
await stakeValidators({ ...config, signer });
});
task("stakeValidators").setAction(async (_, __, runSuper) => {
return runSuper();
});

/**
* This function relays the messages between mainnet and base networks.
*
Expand Down Expand Up @@ -2434,10 +2361,10 @@ subtask(
types.string
)
.addOptionalParam(
"ssv",
"Amount of SSV to deposit to the cluster.",
"eth",
"Amount of ETH to deposit to the cluster.",
0,
types.int
types.float
)
.setAction(async (taskArgs) => {
await registerValidator(taskArgs);
Expand Down
Loading
Loading