Skip to content

Commit

Permalink
feat(scratch deploy): mvp of local scratch deployment
Browse files Browse the repository at this point in the history
  • Loading branch information
arwer13 committed Sep 11, 2023
1 parent de6d827 commit e156f08
Show file tree
Hide file tree
Showing 21 changed files with 356 additions and 438 deletions.
87 changes: 19 additions & 68 deletions SCRATCH_DEPLOY.md
Original file line number Diff line number Diff line change
@@ -1,84 +1,35 @@
# Deploy Lido protocol from scratch

**NB**: at the moment the deployment from scratch scripts and manual target Lido V1 version (before Lido V2 upgrade) and is not working

Video guide: [youtube](https://www.youtube.com/watch?v=dCMXcfglJv0)

## Requirements

* shell - bash or zsh
* docker
* node.js v14
* node.js v16
* yarn

## Environment

You will need at least:

* Ethereum node
* IPFS node
* Aragon web client

In case of local deploy this environment is set up with docker.

> Note: Lido protocol is based on Aragon framework, so the entire Aragon framework environment is required for deployment.
## DAO configuration

Dao config is stored in `deployed-{NETWORK_NAME}.json` file, where `{NETWORK_NAME}` is network name of your choice. See the [`deployed-local-defaults.json`](deployed-local-defaults.json) for basic parameters. Please refer to [`deployed-mainnet.json`](deployed-mainnet.json) for currently deployed Mainnet version of DAO.
## Local deployment

Copy `deployed-local-defaults.json` to `deployed-{NETWORK_NAME}.json` (e.g. `deployed-kintsugi.json`) and update it accordingly .
Deploys the DAO to local (http://127.0.0.1:8545) dev node (anvil, hardhat, ganache).
The deployment is done from default test account `0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266`.
The node must be configured with the default test accounts derived from mnemonic `test test test test test test test test test test test junk`.

## Network configuration
1. Run `yarn install` (get sure repo dependencies are installed)
2. Run the node on default port 8545 (for the commands see subsections below)
3. Set test account private key `0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80` to `accounts.json` under `/eth/local` like `"local": ["<private key>"]`
4. Run the deploy script `bash dao-local-deploy.sh` from root repo directory
5. Check out the deploy artifacts in `deployed-local.json`

Add to [`hardhat.config.js`](hardhat.config.js) your network connection parameter (inside the `getNetConfig` function, use `mainnet` or `local` as reference).
### Anvil

## Deploy process
Run the node with command:

> Note: all deploy process is depend of ENS contract. If the target network has one, you can use it. In this case, write it directly to the `deployed-{NETWORK_NAME}.json` file. Otherwise, own ENS contract will be deployed.
> Note: ETH2 Deposit contract is required. If the target network has one, you must use it. In this case, write it directly to the `deployed-{NETWORK_NAME}.json` file. Otherwise, own Deposit contract will be deployed.
Steps for deploy:

* [ ] run environment docker containers
* [ ] set up network config
* [ ] prepare DAO config file
* [ ] deploy Aragon framework environment (including ENS)
* [ ] build and deploy standard Aragon apps (contracts and frontend files)
* [ ] deploy Deposit contract (if necessary)
* [ ] deploy Lido DAO template contract
* [ ] deploy Lido Apps contract implementations
* [ ] register Lido APM name in ENS
* [ ] build Lido Apps frontend files and upload it to IPFS
* [ ] deploy Lido APM contract (via Lido Template)
* [ ] deploy Lido Apps repo contracts (via Lido Template)
* [ ] deploy Lido DAO contract (via Lido Template)
* [ ] issue DAO tokens (via Lido Template)
* [ ] deploy LidoExecutionLayerRewardsVault
* [ ] finalize DAO setup (via Lido Template)
* [ ] deploy CompositePostRebaseBeaconReceiver
* [ ] deploy Burner
* [ ] make final deployed DAO check via script
* [ ] open and check Lido DAO web interface (via Aragon client)

All steps are automated via shell script [`dao-local-deploy.sh`](dao-local-deploy.sh) for local deploy process. The script be modified for any other network:

So, one-click local deploy from scratch command is:

```bash
./dao-local-deploy.sh
```shell
anvil -p 8545 --auto-impersonate --gas-price 0 --base-fee 0 --chain-id 1337 --mnemonic "test test test test test test test test test test test junk"
```

> Note: some steps require manually updating some transaction hashes in the `deployed-{NETWORK_NAME}.json` file. The script will pause the process in this case, please follow the script tips.
### Hardhat node

## Aragon dependency issue
> NB: Hardhat node is configured in `hardhat.config.js` under `hardhat: { `.
`ipfs-http-client` version has been strictly pinned to `43.0.0` in [this commit](https://github.com/lidofinance/lido-dao/commit/38bf0232fbc59ec6d69d27e170e3e75cfbe1ba11) because `/scripts/multisig/04-publish-app-frontends.js` used to crash at
```javascript
const rootCid = await uploadDirToIpfs({ dirPath: distPath, ipfsApiUrl: ipfsAPI })
To run hardhat node execute:
```shell
yarn hardhat node
```

It appeared that `@aragon/buidler-aragon@npm:^0.2.9` uses `ipfs-http-client`.

`ipfs-http-client` has a brittle API. Neither `41.0.0` nor `50.0.0` versions of it will work with `@aragon/buidler-aragon@npm:^0.2.9`.
91 changes: 52 additions & 39 deletions contracts/0.4.24/template/LidoTemplate.sol
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,54 @@ contract LidoTemplate is IsContract {
ens.setOwner(node, _to);
}

function createStdAragonRepos(
address _agentImpl,
address _financeImpl,
address _tokenManagerImpl,
address _votingImpl
) external onlyOwner {
// uint16[3] memory initialSemanticVersion = [1, 0, 0];

uint16[3] memory initialSemanticVersion = [uint16(1), uint16(0), uint16(0)];

bytes memory dummyContentURI = new bytes(0);
// new bytes(0x697066733a516d516b4a4d7476753474794a76577250584a666a4c667954576e393539696179794e6a703759714e7a58377053);

APMRegistry lidoRegistry = deployState.lidoRegistry;

apmRepos.aragonAgent = lidoRegistry.newRepoWithVersion(
ARAGON_AGENT_APP_NAME,
this,
initialSemanticVersion,
_agentImpl,
dummyContentURI
);

apmRepos.aragonFinance = lidoRegistry.newRepoWithVersion(
ARAGON_FINANCE_APP_NAME,
this,
initialSemanticVersion,
_financeImpl,
dummyContentURI
);

apmRepos.aragonTokenManager = lidoRegistry.newRepoWithVersion(
ARAGON_TOKEN_MANAGER_APP_NAME,
this,
initialSemanticVersion,
_tokenManagerImpl,
dummyContentURI
);

apmRepos.aragonVoting = lidoRegistry.newRepoWithVersion(
ARAGON_VOTING_APP_NAME,
this,
initialSemanticVersion,
_votingImpl,
dummyContentURI
);
}

function createRepos(
uint16[3] _initialSemanticVersion,
address _lidoImplAddress,
Expand All @@ -216,6 +264,7 @@ 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 @@ -247,44 +296,6 @@ contract LidoTemplate is IsContract {
_oracleContentURI
);

// create Aragon app repos pointing to latest upstream versions

AppVersion memory latest = _apmResolveLatest(ARAGON_AGENT_APP_ID);
apmRepos.aragonAgent = lidoRegistry.newRepoWithVersion(
ARAGON_AGENT_APP_NAME,
this,
_initialSemanticVersion,
latest.contractAddress,
latest.contentURI
);

latest = _apmResolveLatest(ARAGON_FINANCE_APP_ID);
apmRepos.aragonFinance = lidoRegistry.newRepoWithVersion(
ARAGON_FINANCE_APP_NAME,
this,
_initialSemanticVersion,
latest.contractAddress,
latest.contentURI
);

latest = _apmResolveLatest(ARAGON_TOKEN_MANAGER_APP_ID);
apmRepos.aragonTokenManager = lidoRegistry.newRepoWithVersion(
ARAGON_TOKEN_MANAGER_APP_NAME,
this,
_initialSemanticVersion,
latest.contractAddress,
latest.contentURI
);

latest = _apmResolveLatest(ARAGON_VOTING_APP_ID);
apmRepos.aragonVoting = lidoRegistry.newRepoWithVersion(
ARAGON_VOTING_APP_NAME,
this,
_initialSemanticVersion,
latest.contractAddress,
latest.contentURI
);

emit TmplReposCreated();
}

Expand Down Expand Up @@ -736,7 +747,9 @@ contract LidoTemplate is IsContract {
}

function _resolveRepo(bytes32 _appId) private view returns (Repo) {
return Repo(PublicResolver(ens.resolver(_appId)).addr(_appId));
address resolverAddress = ens.resolver(_appId);
require(resolverAddress != address(0x0), "ZERO_RESOLVER_ADDRESS");
return Repo(PublicResolver(resolverAddress).addr(_appId));
}

/**
Expand Down
81 changes: 26 additions & 55 deletions dao-deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,90 +25,61 @@ function msg() {
fi
}


# yarn install --immutable
yarn compile

rm -f deployed-$NETWORK.json
cp deployed-$NETWORK-defaults.json deployed-$NETWORK.json
rm -f ${NETWORK_STATE_FILE}
cp ${NETWORK_STATE_DEFAULTS_FILE} ${NETWORK_STATE_FILE}


# Fill in deployer, chainId, etc from env to the deploy artifact
yarn hardhat --network $NETWORK run ./scripts/scratch/00-populate-deploy-artifact-from-env.js --no-compile

# It does not deploy DepositContract if it is specified in deployed-${NETWORK}-defaults.json
yarn hardhat --network $NETWORK run --no-compile ./scripts/scratch/deploy-beacon-deposit-contract.js
yarn hardhat --network $NETWORK run ./scripts/scratch/deploy-beacon-deposit-contract.js --no-compile
msg "Deposit contract deployed or is specified."

yarn deploy:$NETWORK:aragon-env
yarn deploy:aragon-env
msg "Aragon ENV deployed."

# NB!
# Need this renaming because during publishing of aragon apps and deploying their frontends
# via it's internal scripts all contracts get parsed. If contracts has custom errors or multiple
# verions declaration the process fails.

MULTI_VERSION_PRAGMA="pragma solidity >=0.4.24 <0.9.0;"
SINGLE_VERSION_PRAGMA="pragma solidity 0.4.24;"

for ff in $(find contracts/0.8.9 -iname '*.sol'); do mv "$ff" "$ff.tmp" ; done
for ff in $(grep -l -R "${MULTI_VERSION_PRAGMA}" contracts/common); do
sed -i '' "s/${MULTI_VERSION_PRAGMA}/${SINGLE_VERSION_PRAGMA}/g" "$ff" ; done

mv contracts/0.4.24/template/LidoTemplate.sol contracts/0.4.24/template/LidoTemplate.sol.bkp
yarn deploy:$NETWORK:aragon-std-apps
yarn deploy:aragon-std-apps-custom
msg "Aragon STD apps deployed."
mv contracts/0.4.24/template/LidoTemplate.sol.bkp contracts/0.4.24/template/LidoTemplate.sol

yarn hardhat --network $NETWORK run ./scripts/scratch/01-deploy-lido-template-and-bases.js

yarn hardhat --network $NETWORK run ./scripts/scratch/02-obtain-deployed-instances.js
yarn hardhat --network $NETWORK run ./scripts/scratch/01-deploy-lido-template-and-bases.js --no-compile
yarn hardhat --network $NETWORK run ./scripts/scratch/02-obtain-deployed-instances.js --no-compile
msg "Apps instances deployed"

yarn hardhat --network $NETWORK run ./scripts/scratch/03-register-ens-domain.js
if [ -f "tx-02-1-commit-ens-registration.json" ]; then
yarn hardhat --network $NETWORK tx --from $DEPLOYER --file tx-02-1-commit-ens-registration.json
fi
yarn hardhat --network $NETWORK tx --from $DEPLOYER --file tx-02-2-make-ens-registration.json
yarn hardhat --network $NETWORK run ./scripts/scratch/03-register-ens-domain.js --no-compile
msg "ENS registered"

yarn hardhat --network $NETWORK run ./scripts/scratch/04-publish-app-frontends.js
msg "Frontend published to IPFS"

# Okay, now we can restore the contracts
for ff in $(find contracts/0.8.9 -iname '*.sol.tmp'); do mv "$ff" "${ff%.*}" ; done
for ff in $(grep -l -R "${SINGLE_VERSION_PRAGMA}" contracts/common); do
sed -i '' "s/${SINGLE_VERSION_PRAGMA}/${MULTI_VERSION_PRAGMA}/g" "$ff" ; done

yarn hardhat --network $NETWORK run ./scripts/scratch/05-deploy-apm.js
yarn hardhat --network $NETWORK tx --from $DEPLOYER --file tx-03-deploy-apm.json
yarn hardhat --network $NETWORK run ./scripts/scratch/06-obtain-deployed-apm.js
yarn hardhat --network $NETWORK run ./scripts/scratch/05-deploy-apm.js --no-compile
yarn hardhat --network $NETWORK run ./scripts/scratch/06-obtain-deployed-apm.js --no-compile
msg "APM deployed"


yarn hardhat --network $NETWORK run ./scripts/scratch/07-create-app-repos.js
yarn hardhat --network $NETWORK tx --from $DEPLOYER --file tx-07-create-app-repos.json
yarn hardhat --network $NETWORK run ./scripts/scratch/07-create-app-repos.js --no-compile
msg "App repos created"

yarn hardhat --network $NETWORK run ./scripts/scratch/08-deploy-dao.js
yarn hardhat --network $NETWORK tx --from $DEPLOYER --file tx-05-deploy-dao.json
yarn hardhat --network $NETWORK run ./scripts/scratch/08-deploy-dao.js --no-compile

yarn hardhat --network $NETWORK run ./scripts/scratch/09-obtain-deployed-dao.js
yarn hardhat --network $NETWORK run ./scripts/scratch/09-obtain-deployed-dao.js --no-compile
msg "DAO deploy started"


# Do it at the end, because might need the contracts initialized
yarn hardhat --network $NETWORK run ./scripts/scratch/10-issue-tokens.js
yarn hardhat --network $NETWORK tx --from $DEPLOYER --file tx-06-1-issue-tokens.json
yarn hardhat --network $NETWORK run ./scripts/scratch/10-issue-tokens.js --no-compile
msg "Tokens issued"


# Deploy the contracts before finalizing DAO, because the template might set permissions on some of them
yarn hardhat --network $NETWORK run ./scripts/scratch/13-deploy-non-aragon-contracts.js
yarn hardhat --network $NETWORK run ./scripts/scratch/13-deploy-non-aragon-contracts.js --no-compile
msg "Non-aragon contracts deployed"

yarn hardhat --network $NETWORK run ./scripts/scratch/11-finalize-dao.js
yarn hardhat --network $NETWORK tx --from $DEPLOYER --file tx-11-finalize-dao.json
yarn hardhat --network $NETWORK run ./scripts/scratch/11-finalize-dao.js --no-compile
msg "DAO deploy finalized"

rm ./tx-*.json

yarn hardhat --network $NETWORK run ./scripts/scratch/14-initialize-non-aragon-contracts.js
yarn hardhat --network $NETWORK run ./scripts/scratch/14-initialize-non-aragon-contracts.js --no-compile
msg "Non-aragon contracts initialized"

yarn hardhat --network $NETWORK run ./scripts/scratch/15-grant-roles.js
yarn hardhat --network $NETWORK run ./scripts/scratch/15-grant-roles.js --no-compile
msg "Roles granted"

# TODO: save commit of the latest deploy
Loading

0 comments on commit e156f08

Please sign in to comment.