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

feat: add proper upgrade to version 3 in Lido #882

Open
wants to merge 1 commit into
base: feat/vaults
Choose a base branch
from
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
24 changes: 12 additions & 12 deletions contracts/0.4.24/Lido.sol
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
{
_bootstrapInitialHolder();
_initialize_v2(_lidoLocator, _eip712StETH);
Copy link
Member

Choose a reason for hiding this comment

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

Can we remove _initialize_v2 altogether by moving it's logic to v3?

Copy link
Member Author

Choose a reason for hiding this comment

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

We can, but should we?

_initialize_v3();
initialized();
}

Expand All @@ -234,23 +235,22 @@ contract Lido is Versioned, StETHPermit, AragonApp {
}

/**
* @notice A function to finalize upgrade to v2 (from v1). Can be called only once
* @dev Value "1" in CONTRACT_VERSION_POSITION is skipped due to change in numbering
*
* The initial protocol token holder must exist.
* initializer for the Lido version "3"
*/
function _initialize_v3() internal {
_setContractVersion(3);
}

/**
* @notice A function to finalize upgrade to v3 (from v2). Can be called only once
*
* For more details see https://github.com/lidofinance/lido-improvement-proposals/blob/develop/LIPS/lip-10.md
*/
function finalizeUpgrade_v2(address _lidoLocator, address _eip712StETH) external {
_checkContractVersion(0);
function finalizeUpgrade_v3() external {
require(hasInitialized(), "NOT_INITIALIZED");
_checkContractVersion(2);

require(_lidoLocator != address(0), "LIDO_LOCATOR_ZERO_ADDRESS");
require(_eip712StETH != address(0), "EIP712_STETH_ZERO_ADDRESS");

require(_sharesOf(INITIAL_TOKEN_HOLDER) != 0, "INITIAL_HOLDER_EXISTS");

_initialize_v2(_lidoLocator, _eip712StETH);
_initialize_v3();
}

/**
Expand Down
17 changes: 3 additions & 14 deletions test/0.4.24/contracts/Lido__HarnessForFinalizeUpgradeV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,8 @@ pragma solidity 0.4.24;

import {Lido} from "contracts/0.4.24/Lido.sol";

contract Lido__HarnessForFinalizeUpgradeV2 is Lido {
function harness__initialize(uint256 _initialVersion) external payable {
assert(address(this).balance != 0);
_bootstrapInitialHolder();
_setContractVersion(_initialVersion);
initialized();
}

function harness__mintSharesWithoutChecks(address account, uint256 amount) external returns (uint256) {
return super._mintShares(account, amount);
}

function harness__burnInitialHoldersShares() external returns (uint256) {
return super._burnShares(INITIAL_TOKEN_HOLDER, _sharesOf(INITIAL_TOKEN_HOLDER));
contract Lido__HarnessForFinalizeUpgradeV3 is Lido {
function harness_setContractVersion(uint256 _version) external {
_setContractVersion(_version);
}
}
118 changes: 0 additions & 118 deletions test/0.4.24/lido/lido.finalizeUpgrade_v2.test.ts

This file was deleted.

101 changes: 101 additions & 0 deletions test/0.4.24/lido/lido.finalizeUpgrade_v3.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { expect } from "chai";
import { MaxUint256, ZeroAddress } from "ethers";
import { ethers } from "hardhat";

import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
import { time } from "@nomicfoundation/hardhat-network-helpers";

import { Lido__HarnessForFinalizeUpgradeV3, LidoLocator } from "typechain-types";

import { certainAddress, INITIAL_STETH_HOLDER, proxify } from "lib";

import { deployLidoLocator } from "test/deploy";
import { Snapshot } from "test/suite";

describe("Lido.sol:finalizeUpgrade_v3", () => {
let deployer: HardhatEthersSigner;

let impl: Lido__HarnessForFinalizeUpgradeV3;
let lido: Lido__HarnessForFinalizeUpgradeV3;
let locator: LidoLocator;

const initialValue = 1n;
const initialVersion = 2n;
const finalizeVersion = 3n;

let withdrawalQueueAddress: string;
let burnerAddress: string;
const eip712helperAddress = certainAddress("lido:initialize:eip712helper");

let originalState: string;

before(async () => {
[deployer] = await ethers.getSigners();
impl = await ethers.deployContract("Lido__HarnessForFinalizeUpgradeV3");
[lido] = await proxify({ impl, admin: deployer });

locator = await deployLidoLocator();
[withdrawalQueueAddress, burnerAddress] = await Promise.all([locator.withdrawalQueue(), locator.burner()]);
});

beforeEach(async () => (originalState = await Snapshot.take()));

afterEach(async () => await Snapshot.restore(originalState));

it("Reverts if not initialized", async () => {
await expect(lido.harness_setContractVersion(initialVersion))
.and.to.emit(lido, "ContractVersionSet")
.withArgs(initialVersion);

await expect(lido.finalizeUpgrade_v3()).to.be.revertedWith("NOT_INITIALIZED");
});

context("initialized", () => {
before(async () => {
const latestBlock = BigInt(await time.latestBlock());

await expect(lido.initialize(locator, eip712helperAddress, { value: initialValue }))
.to.emit(lido, "Submitted")
.withArgs(INITIAL_STETH_HOLDER, initialValue, ZeroAddress)
.and.to.emit(lido, "Transfer")
.withArgs(ZeroAddress, INITIAL_STETH_HOLDER, initialValue)
.and.to.emit(lido, "TransferShares")
.withArgs(ZeroAddress, INITIAL_STETH_HOLDER, initialValue)
.and.to.emit(lido, "ContractVersionSet")
.withArgs(finalizeVersion)
.and.to.emit(lido, "EIP712StETHInitialized")
.withArgs(eip712helperAddress)
.and.to.emit(lido, "Approval")
.withArgs(withdrawalQueueAddress, burnerAddress, MaxUint256)
.and.to.emit(lido, "LidoLocatorSet")
.withArgs(await locator.getAddress());

expect(await impl.getInitializationBlock()).to.equal(MaxUint256);
expect(await lido.getInitializationBlock()).to.equal(latestBlock + 1n);
});

it("Reverts if initialized from scratch", async () => {
await expect(lido.finalizeUpgrade_v3()).to.be.reverted;
});

it("Reverts if contract version does not equal 2", async () => {
const unexpectedVersion = 1n;

await expect(lido.harness_setContractVersion(unexpectedVersion))
.and.to.emit(lido, "ContractVersionSet")
.withArgs(unexpectedVersion);

await expect(lido.finalizeUpgrade_v3()).to.be.reverted;
});

it("Sets contract version to 3", async () => {
await expect(lido.harness_setContractVersion(initialVersion))
.and.to.emit(lido, "ContractVersionSet")
.withArgs(initialVersion);

await expect(lido.finalizeUpgrade_v3()).and.to.emit(lido, "ContractVersionSet").withArgs(finalizeVersion);

expect(await lido.getContractVersion()).to.equal(finalizeVersion);
});
});
});
Loading