UNPKG

@nodeset/contracts

Version:

Protocol for accessing NodeSet's Constellation Ethereum staking network

230 lines (200 loc) 11.4 kB
import { expect } from "chai"; import { ethers, upgrades, hardhatArguments } from "hardhat"; import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { Protocol, protocolFixture, RocketPool, SetupData, Signers } from "../test"; import { generateDepositData } from ".././rocketpool/_helpers/minipool"; import { approvedSalt, approveHasSignedExitMessageSig, assertAddOperator } from ".././utils/utils"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { BigNumber } from "ethers"; import { Contract } from "@openzeppelin/upgrades"; import { IMinipool } from "../../typechain-types"; const ethMintAmount = ethers.utils.parseEther("8"); const rplMintAmount = ethers.utils.parseEther("720"); const salt = 3; describe("SuperNodeAccount close", function () { let setupData: SetupData; let protocol: Protocol; let signers: Signers; let rocketPool: RocketPool; let nodeOperator: SignerWithAddress; let salts: any; let rawSalt: BigNumber; let pepperedSalt: BigNumber; let config: any; let sig: string; let timestamp: number; let minipoolContract: IMinipool; beforeEach(async function () { setupData = await loadFixture(protocolFixture); protocol = setupData.protocol; signers = setupData.signers; rocketPool = setupData.rocketPool; // Set liquidity reserve to 0% await protocol.vCRPL.connect(signers.admin).setLiquidityReservePercent(0); await protocol.vCWETH.connect(signers.admin).setLiquidityReservePercent(0); // set fee to 0% await protocol.vCWETH.connect(signers.admin).setMintFee(0); // Deposit 8 ETH for 1 minipool const ethBalance = await ethers.provider.getBalance(signers.ethWhale.address) await protocol.wETH.connect(signers.ethWhale).deposit({ value: ethers.utils.parseEther("1000") }); await protocol.wETH.connect(signers.ethWhale).approve(protocol.vCWETH.address, ethBalance); await protocol.vCWETH.connect(signers.ethWhale).deposit(ethMintAmount, signers.ethWhale.address); // Deposit 720 RPL await rocketPool.rplContract.connect(signers.rplWhale).transfer(signers.ethWhale.address, rplMintAmount); await rocketPool.rplContract.connect(signers.ethWhale).approve(protocol.vCRPL.address, rplMintAmount); await protocol.vCRPL.connect(signers.ethWhale).deposit(rplMintAmount, signers.ethWhale.address); nodeOperator = signers.hyperdriver; await assertAddOperator(setupData, nodeOperator); salts = await approvedSalt(salt, nodeOperator.address); rawSalt = salts.rawSalt; pepperedSalt = salts.pepperedSalt; const depositData = await generateDepositData(protocol.superNode.address, pepperedSalt) const bond = await setupData.protocol.superNode.bond(); config = { timezoneLocation: 'Australia/Brisbane', bondAmount: bond, minimumNodeFee: 0, validatorPubkey: depositData.depositData.pubkey, validatorSignature: depositData.depositData.signature, depositDataRoot: depositData.depositDataRoot, salt: pepperedSalt, expectedMinipoolAddress: depositData.minipoolAddress, }; const message = await approveHasSignedExitMessageSig( setupData, nodeOperator.address, '0x' + config.expectedMinipoolAddress, config.salt, ); sig = message.sig; timestamp = message.timestamp; minipoolContract = (await ethers.getContractAt( 'IMinipool', config.expectedMinipoolAddress )); }); describe("when minipool is not dissolved", function () { it("should revert", async function () { await expect( protocol.superNode .connect(nodeOperator) .createMinipool({ validatorPubkey: config.validatorPubkey, validatorSignature: config.validatorSignature, depositDataRoot: config.depositDataRoot, salt: rawSalt, expectedMinipoolAddress: config.expectedMinipoolAddress, sig: sig }, { value: ethers.utils.parseEther('1') })) .to.not.be.reverted; // Deposit minipool to set to prelaunch state await expect(minipoolContract.connect(nodeOperator).deposit({ value: ethMintAmount })).to.not.be.reverted; // Increase the time by 10 days await ethers.provider.send("evm_increaseTime", [10*24*3600]); await ethers.provider.send("evm_mine", []); // Assert validator count prior to closing minipool expect(await protocol.whitelist.getActiveValidatorCountForOperator(nodeOperator.address)).to.be.equal(1); expect(await protocol.superNode.connect(nodeOperator).getNumMinipools()).to.be.equal(1); // Only close minipool await expect(protocol.superNode.connect(nodeOperator).closeDissolvedMinipool(nodeOperator.address, config.expectedMinipoolAddress)).to.be.revertedWith("The minipool can only be closed while dissolved"); }); }); describe("when minipool is dissolved", function () { describe("when subNodeOperator address is valid", function () { describe("when minipool address is valid", function () { it("removes the validator", async function () { await expect( protocol.superNode .connect(nodeOperator) .createMinipool({ validatorPubkey: config.validatorPubkey, validatorSignature: config.validatorSignature, depositDataRoot: config.depositDataRoot, salt: rawSalt, expectedMinipoolAddress: config.expectedMinipoolAddress, sig: sig }, { value: ethers.utils.parseEther('1') })) .to.not.be.reverted; // Deposit minipool to set to prelaunch state await expect(minipoolContract.connect(nodeOperator).deposit({ value: ethMintAmount })).to.not.be.reverted; // Increase the time by 10 days await ethers.provider.send("evm_increaseTime", [10*24*3600]); await ethers.provider.send("evm_mine", []); // Assert validator count prior to closing minipool expect(await protocol.whitelist.getActiveValidatorCountForOperator(nodeOperator.address)).to.be.equal(1); expect(await protocol.superNode.connect(nodeOperator).getNumMinipools()).to.be.equal(1); // Dissolve and close minipool await expect(minipoolContract.connect(nodeOperator).dissolve()).to.not.be.reverted; await protocol.superNode.connect(nodeOperator).closeDissolvedMinipool(nodeOperator.address, config.expectedMinipoolAddress); // Assert validator count prior after closing minipool expect(await protocol.whitelist.getActiveValidatorCountForOperator(nodeOperator.address)).to.be.equal(0); expect(await protocol.superNode.connect(nodeOperator).getNumMinipools()).to.be.equal(0); }); }); describe("when minipool address is invalid", function () { it("should revert", async function () { await expect( protocol.superNode .connect(nodeOperator) .createMinipool({ validatorPubkey: config.validatorPubkey, validatorSignature: config.validatorSignature, depositDataRoot: config.depositDataRoot, salt: rawSalt, expectedMinipoolAddress: config.expectedMinipoolAddress, sig: sig }, { value: ethers.utils.parseEther('1') })) .to.not.be.reverted; // Deposit minipool to set to prelaunch state await expect(minipoolContract.connect(nodeOperator).deposit({ value: ethMintAmount })).to.not.be.reverted; // Increase the time by 10 days await ethers.provider.send("evm_increaseTime", [10*24*3600]); await ethers.provider.send("evm_mine", []); // Assert validator count prior to closing minipool expect(await protocol.whitelist.getActiveValidatorCountForOperator(nodeOperator.address)).to.be.equal(1); expect(await protocol.superNode.connect(nodeOperator).getNumMinipools()).to.be.equal(1); // Dissolve and close minipool await expect(minipoolContract.connect(nodeOperator).dissolve()).to.not.be.reverted; // Invalid minipool address await expect(protocol.superNode.connect(nodeOperator).closeDissolvedMinipool(nodeOperator.address, nodeOperator.address)).to.be.revertedWith("minipool not recognized"); }); }); }); describe("when subNodeOperator address is invalid", function () { it("should revert", async function () { await expect( protocol.superNode .connect(nodeOperator) .createMinipool({ validatorPubkey: config.validatorPubkey, validatorSignature: config.validatorSignature, depositDataRoot: config.depositDataRoot, salt: rawSalt, expectedMinipoolAddress: config.expectedMinipoolAddress, sig: sig }, { value: ethers.utils.parseEther('1') })) .to.not.be.reverted; // Deposit minipool to set to prelaunch state await expect(minipoolContract.connect(nodeOperator).deposit({ value: ethMintAmount })).to.not.be.reverted; // Increase the time by 10 days await ethers.provider.send("evm_increaseTime", [10*24*3600]); await ethers.provider.send("evm_mine", []); // Assert validator count prior to closing minipool expect(await protocol.whitelist.getActiveValidatorCountForOperator(nodeOperator.address)).to.be.equal(1); expect(await protocol.superNode.connect(nodeOperator).getNumMinipools()).to.be.equal(1); // Dissolve and close minipool await expect(minipoolContract.connect(nodeOperator).dissolve()).to.not.be.reverted; // Close with invalid address await expect(protocol.superNode.connect(nodeOperator).closeDissolvedMinipool(config.expectedMinipoolAddress, config.expectedMinipoolAddress)).to.be.revertedWith("operator does not own the specified minipool"); }); }); }); });