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 Simple DVT to scratch deploy #845

Merged
merged 11 commits into from
Oct 9, 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
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ LOCAL_WITHDRAWAL_VAULT_ADDRESS=

# RPC URL for a separate, non Hardhat Network node (Anvil, Infura, Alchemy, etc.)
MAINNET_RPC_URL=http://localhost:8545

# RPC URL for Hardhat Network forking, required for running tests on mainnet fork with tracing (Infura, Alchemy, etc.)
# https://hardhat.org/hardhat-network/docs/guides/forking-other-networks#forking-other-networks
MAINNET_FORKING_URL=
HARDHAT_FORKING_URL=

# https://docs.lido.fi/deployed-contracts
MAINNET_LOCATOR_ADDRESS=0xC1d0b3DE6792Bf6b4b37EccdcC24e45978Cfd2Eb
Expand Down
8 changes: 5 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ the [Lido Research Forum](https://research.lido.fi/).
- [Foundry](https://book.getfoundry.sh/) latest available version

> [!TIP]
> On macOS with Homebrew, it is recommended to install Node.js using [`n`](https://github.com/tj/n) or [ > `nvm`](https://github.com/nvm-sh/nvm) version managers.
> On macOS with Homebrew, it is recommended to install Node.js using [`n`](https://github.com/tj/n) or
> [ >`nvm`](https://github.com/nvm-sh/nvm) version managers.
>
> Example setup process using `n` package manager for zsh users:
>
> ```bash
Expand Down Expand Up @@ -325,8 +327,8 @@ This is the most common method for running integration tests. It uses an instanc
mainnet environment, allowing you to run integration tests with trace logging.

> [!NOTE]
> Ensure that `MAINNET_FORKING_URL` and other `MAINNET_*` environment variables are set in the `.env` file (refer to
> `.env.example` for guidance).
> Ensure that `HARDHAT_FORKING_URL` is set to Ethereum Mainnet RPC and `MAINNET_*` environment variables are set in the
> `.env` file (refer to `.env.example` for guidance).

```bash
# Run all integration tests
Expand Down
120 changes: 46 additions & 74 deletions contracts/0.4.24/template/LidoTemplate.sol
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ contract LidoTemplate is IsContract {
string private constant LIDO_APP_NAME = "lido";
string private constant ORACLE_APP_NAME = "oracle";
string private constant NODE_OPERATORS_REGISTRY_APP_NAME = "node-operators-registry";
string private constant SIMPLE_DVT_APP_NAME = "simple-dvt";

// DAO config constants
bool private constant TOKEN_TRANSFERABLE = true;
Expand All @@ -85,6 +86,7 @@ contract LidoTemplate is IsContract {
Repo lido;
Repo oracle;
Repo nodeOperatorsRegistry;
Repo simpleDVT;
Repo aragonAgent;
Repo aragonFinance;
Repo aragonTokenManager;
Expand All @@ -104,6 +106,7 @@ contract LidoTemplate is IsContract {
Lido lido;
LegacyOracle oracle;
NodeOperatorsRegistry operators;
NodeOperatorsRegistry sdvt;
address stakingRouter;
}

Expand Down Expand Up @@ -261,7 +264,6 @@ contract LidoTemplate is IsContract {
bytes _nodeOperatorsRegistryContentURI,
address _oracleImplAddress,
bytes _oracleContentURI

) external onlyOwner {
require(deployState.lidoRegistry != address(0), ERROR_REGISTRY_NOT_DEPLOYED);

Expand Down Expand Up @@ -293,14 +295,18 @@ contract LidoTemplate is IsContract {
_oracleContentURI
);

apmRepos.simpleDVT = lidoRegistry.newRepoWithVersion(
SIMPLE_DVT_APP_NAME,
this,
_initialSemanticVersion,
_nodeOperatorsRegistryImplAddress,
_nodeOperatorsRegistryContentURI
);

emit TmplReposCreated();
}

function newDAO(
string _tokenName,
string _tokenSymbol,
uint64[4] _votingSettings
) external onlyOwner {
function newDAO(string _tokenName, string _tokenSymbol, uint64[4] _votingSettings) external onlyOwner {
DeployState memory state = deployState;

require(state.lidoRegistry != address(0), ERROR_REGISTRY_NOT_DEPLOYED);
Expand Down Expand Up @@ -328,7 +334,7 @@ contract LidoTemplate is IsContract {
_votingSettings[0], // support
_votingSettings[1], // acceptance
_votingSettings[2], // duration
_votingSettings[3] // objectionPhaseDuration
_votingSettings[3] // objectionPhaseDuration
);

bytes memory noInit = new bytes(0);
Expand All @@ -345,6 +351,14 @@ contract LidoTemplate is IsContract {
)
);

state.sdvt = NodeOperatorsRegistry(
_installNonDefaultApp(
state.dao,
_getAppId(SIMPLE_DVT_APP_NAME, state.lidoRegistryEnsNode),
noInit
)
);

state.oracle = LegacyOracle(
_installNonDefaultApp(state.dao, _getAppId(ORACLE_APP_NAME, state.lidoRegistryEnsNode), noInit)
);
Expand Down Expand Up @@ -387,13 +401,7 @@ contract LidoTemplate is IsContract {
emit TmplTokensIssued(totalAmount);
}

function finalizeDAO(
string _daoName,
uint256 _unvestedTokensAmount,
address _stakingRouter
)
external onlyOwner
{
function finalizeDAO(string _daoName, uint256 _unvestedTokensAmount, address _stakingRouter) external onlyOwner {
require(_stakingRouter != address(0));
DeployState memory state = deployState;
APMRepos memory repos = apmRepos;
Expand Down Expand Up @@ -474,9 +482,7 @@ contract LidoTemplate is IsContract {
uint64 _acceptance,
uint64 _duration,
uint64 _objectionPhaseDuration
)
private returns (Voting)
{
) private returns (Voting) {
bytes32 appId = _getAppId(ARAGON_VOTING_APP_NAME, _lidoRegistryEnsNode);
bytes memory initializeData = abi.encodeWithSelector(
Voting(0).initialize.selector,
Expand Down Expand Up @@ -511,11 +517,7 @@ contract LidoTemplate is IsContract {

/* TOKEN */

function _createToken(
string memory _name,
string memory _symbol,
uint8 _decimals
) internal returns (MiniMeToken) {
function _createToken(string memory _name, string memory _symbol, uint8 _decimals) internal returns (MiniMeToken) {
MiniMeToken token = miniMeFactory.createCloneToken(MiniMeToken(address(0)), 0, _name, _decimals, _symbol, true);
return token;
}
Expand All @@ -530,10 +532,7 @@ contract LidoTemplate is IsContract {
uint64 _vestingEnd,
bool _vestingRevokable,
uint256 _expectedFinalTotalSupply
)
private
returns (uint256 totalAmount)
{
) private returns (uint256 totalAmount) {
totalAmount = 0;
uint256 i;

Expand Down Expand Up @@ -614,6 +613,18 @@ contract LidoTemplate is IsContract {
acl.createPermission(_state.stakingRouter, _state.operators, _state.operators.STAKING_ROUTER_ROLE(), voting);
acl.createPermission(_state.agent, _state.operators, _state.operators.MANAGE_NODE_OPERATOR_ROLE(), voting);

// SimpleDVT
perms[0] = _state.operators.MANAGE_SIGNING_KEYS();
perms[1] = _state.operators.SET_NODE_OPERATOR_LIMIT_ROLE();
perms[2] = _state.operators.MANAGE_NODE_OPERATOR_ROLE();
for (i = 0; i < 3; ++i) {
_createPermissionForVoting(acl, _state.sdvt, perms[i], voting);
}
acl.createPermission(_state.stakingRouter, _state.sdvt, _state.sdvt.STAKING_ROUTER_ROLE(), this);
acl.grantPermission(_state.agent, _state.sdvt, _state.sdvt.STAKING_ROUTER_ROLE());

_transferPermissionFromTemplate(acl, _state.sdvt, voting, _state.sdvt.STAKING_ROUTER_ROLE());

// Lido
perms[0] = _state.lido.PAUSE_ROLE();
perms[1] = _state.lido.RESUME_ROLE();
Expand All @@ -630,38 +641,20 @@ contract LidoTemplate is IsContract {
_createPermissionForTemplate(_acl, _tokenManager, _tokenManager.ASSIGN_ROLE());
}

function _createPermissionForVoting(
ACL _acl,
address _app,
bytes32 perm,
address _voting
) internal {
function _createPermissionForVoting(ACL _acl, address _app, bytes32 perm, address _voting) internal {
_acl.createPermission(_voting, _app, perm, _voting);
}

function _createAgentPermissions(
ACL _acl,
Agent _agent,
address _voting
) internal {
function _createAgentPermissions(ACL _acl, Agent _agent, address _voting) internal {
_createPermissionForVoting(_acl, _agent, _agent.EXECUTE_ROLE(), _voting);
_createPermissionForVoting(_acl, _agent, _agent.RUN_SCRIPT_ROLE(), _voting);
}

function _createVaultPermissions(
ACL _acl,
Vault _vault,
address _finance,
address _voting
) internal {
function _createVaultPermissions(ACL _acl, Vault _vault, address _finance, address _voting) internal {
_acl.createPermission(_finance, _vault, _vault.TRANSFER_ROLE(), _voting);
}

function _createFinancePermissions(
ACL _acl,
Finance _finance,
address _voting
) internal {
function _createFinancePermissions(ACL _acl, Finance _finance, address _voting) internal {
_createPermissionForVoting(_acl, _finance, _finance.EXECUTE_PAYMENTS_ROLE(), _voting);
_createPermissionForVoting(_acl, _finance, _finance.MANAGE_PAYMENTS_ROLE(), _voting);
_createPermissionForVoting(_acl, _finance, _finance.CREATE_PAYMENTS_ROLE(), _voting);
Expand All @@ -673,39 +666,23 @@ contract LidoTemplate is IsContract {
_createPermissionForVoting(_acl, registry, registry.REGISTRY_ADD_EXECUTOR_ROLE(), _voting);
}

function _createVotingPermissions(
ACL _acl,
Voting _voting,
address _tokenManager
) internal {
function _createVotingPermissions(ACL _acl, Voting _voting, address _tokenManager) internal {
_createPermissionForVoting(_acl, _voting, _voting.MODIFY_QUORUM_ROLE(), _voting);
_createPermissionForVoting(_acl, _voting, _voting.MODIFY_SUPPORT_ROLE(), _voting);
_acl.createPermission(_tokenManager, _voting, _voting.CREATE_VOTES_ROLE(), _voting);
}

function _configureTokenManagerPermissions(
ACL _acl,
TokenManager _tokenManager,
address _voting
) internal {
function _configureTokenManagerPermissions(ACL _acl, TokenManager _tokenManager, address _voting) internal {
_removePermissionFromTemplate(_acl, _tokenManager, _tokenManager.ISSUE_ROLE());
_removePermissionFromTemplate(_acl, _tokenManager, _tokenManager.ASSIGN_ROLE());
_createPermissionForVoting(_acl, _tokenManager, _tokenManager.ASSIGN_ROLE(), _voting);
}

function _createPermissionForTemplate(
ACL _acl,
address _app,
bytes32 _permission
) private {
function _createPermissionForTemplate(ACL _acl, address _app, bytes32 _permission) private {
_acl.createPermission(address(this), _app, _permission, address(this));
}

function _removePermissionFromTemplate(
ACL _acl,
address _app,
bytes32 _permission
) private {
function _removePermissionFromTemplate(ACL _acl, address _app, bytes32 _permission) private {
_acl.revokePermission(address(this), _app, _permission);
_acl.removePermissionManager(_app, _permission);
}
Expand All @@ -716,12 +693,7 @@ contract LidoTemplate is IsContract {
_transferPermissionFromTemplate(_acl, _acl, _voting, _acl.CREATE_PERMISSIONS_ROLE(), _voting);
}

function _transferPermissionFromTemplate(
ACL _acl,
address _app,
address _to,
bytes32 _permission
) private {
function _transferPermissionFromTemplate(ACL _acl, address _app, address _to, bytes32 _permission) private {
_transferPermissionFromTemplate(_acl, _app, _to, _permission, _to);
}

Expand Down
16 changes: 9 additions & 7 deletions globals.d.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
declare namespace NodeJS {
export interface ProcessEnv {
/* RPC URL for Hardhat Network forking, required for running tests on mainnet fork with tracing */
MAINNET_FORKING_URL?: string;
/* iternal logging verbosity (used in scratch deploy / integration tests) */
LOG_LEVEL?: "all" | "debug" | "info" | "warn" | "error" | "none"; // default: "info"

/* logging verbosity */
LOG_LEVEL?: "all" | "debug" | "info" | "warn" | "error" | "none";
/**
* Flags for changing the behavior of the Hardhat Network
*/

/* RPC URL for Hardhat Network forking, required for running tests on mainnet fork with tracing */
HARDHAT_FORKING_URL?: string;

/**
* Flags for changing the behavior of the integration tests
*/

/* if "on" the integration tests will deploy the contracts to the empty Hardhat Network node using scratch deploy */
INTEGRATION_SCRATCH_DEPLOY?: "on" | "off";
/* if "on" the integration tests will enable assertions and checks for the simple DVT module */
INTEGRATION_SIMPLE_DVT_MODULE?: "on" | "off";
INTEGRATION_ON_SCRATCH?: "on" | "off"; // default: "off"

/**
* Network configuration for the protocol discovery.
Expand Down
16 changes: 9 additions & 7 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,18 @@ import { mochaRootHooks } from "test/hooks";
import "./tasks";

const RPC_URL: string = process.env.RPC_URL || "";
const MAINNET_FORKING_URL = process.env.MAINNET_FORKING_URL || "";
const INTEGRATION_SCRATCH_DEPLOY = process.env.INTEGRATION_SCRATCH_DEPLOY || "off";
const ACCOUNTS_PATH = "./accounts.json";

/**
* Determines the forking configuration for Hardhat.
* @returns The forking configuration object or undefined.
*/
const HARDHAT_FORKING_URL = process.env.HARDHAT_FORKING_URL || "";

const INTEGRATION_WITH_SCRATCH_DEPLOY = process.env.INTEGRATION_WITH_SCRATCH_DEPLOY || "off";

/* Determines the forking configuration for Hardhat */
function getHardhatForkingConfig() {
return INTEGRATION_SCRATCH_DEPLOY === "on" || !MAINNET_FORKING_URL ? undefined : { url: MAINNET_FORKING_URL };
if (INTEGRATION_WITH_SCRATCH_DEPLOY === "on" || !HARDHAT_FORKING_URL) {
return undefined;
}
return { url: HARDHAT_FORKING_URL };
}

function loadAccounts(networkName: string) {
Expand Down
5 changes: 2 additions & 3 deletions lib/protocol/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@ export const getProtocolContext = async (): Promise<ProtocolContext> => {

// By default, all flags are "on"
const flags = {
isScratchDeploy: process.env.INTEGRATION_SCRATCH_DEPLOY === "on",
withSimpleDvtModule: process.env.INTEGRATION_SIMPLE_DVT_MODULE !== "off",
onScratch: process.env.INTEGRATION_ON_SCRATCH === "on",
} as ProtocolContextFlags;

log.debug("Protocol context flags", {
"With simple DVT module": flags.withSimpleDvtModule,
"On scratch": flags.onScratch,
});

const context = {
Expand Down
5 changes: 2 additions & 3 deletions lib/protocol/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,5 @@ export {
report,
} from "./accounting";

export { sdvtEnsureOperators } from "./sdvt.helper";

export { norEnsureOperators } from "./nor.helper";
export { sdvtEnsureOperators } from "./sdvt";
export { norEnsureOperators } from "./nor";
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { impersonate, log, streccak, trace } from "lib";
import { ether } from "../../units";
import { ProtocolContext } from "../types";

import { getOperatorManagerAddress, getOperatorName, getOperatorRewardAddress } from "./nor.helper";
import { getOperatorManagerAddress, getOperatorName, getOperatorRewardAddress } from "./nor";

const MIN_OPS_COUNT = 3n;
const MIN_OP_KEYS_COUNT = 10n;
Expand Down
3 changes: 1 addition & 2 deletions lib/protocol/networks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ async function getLocalNetworkConfig(network: string, source: string): Promise<P
locator: config["lidoLocator"].proxy.address,
agentAddress: config["app:aragon-agent"].proxy.address,
votingAddress: config["app:aragon-voting"].proxy.address,
easyTrackAddress: config["app:aragon-agent"].proxy.address,
sdvt: config["app:node-operators-registry"].proxy.address,
easyTrackAddress: config["app:aragon-voting"].proxy.address,
};
return new ProtocolNetworkConfig(getPrefixedEnv(network.toUpperCase(), defaultEnv), defaults, `${network}-${source}`);
}
Expand Down
2 changes: 2 additions & 0 deletions lib/protocol/provision.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
ensureOracleCommitteeMembers,
ensureStakeLimit,
norEnsureOperators,
sdvtEnsureOperators,
unpauseStaking,
unpauseWithdrawalQueue,
} from "./helpers";
Expand All @@ -21,6 +22,7 @@ export const provision = async (ctx: ProtocolContext) => {
await unpauseWithdrawalQueue(ctx);

await norEnsureOperators(ctx, 3n, 5n);
await sdvtEnsureOperators(ctx, 3n, 5n);

await ensureStakeLimit(ctx);
};
Loading
Loading