-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replace type-flag by zx, move to tsx, move the script in a .ts file
- Loading branch information
Showing
4 changed files
with
406 additions
and
196 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,192 +1,8 @@ | ||
#!/usr/bin/env -S npx ts-node --transpile-only | ||
#!/usr/bin/env -S npx tsx | ||
|
||
const HELP = ` | ||
deploy - deploy the Liquity contracts. | ||
|
||
Usage: | ||
./deploy <NETWORK_PRESET> [OPTIONS] | ||
|
||
Arguments: | ||
NETWORK_PRESET The network preset to use, which can be one of: | ||
- local: Deploy to a local network | ||
- mainnet: Deploy to the Ethereum mainnet | ||
- tenderly-devnet: Deploy to a Tenderly devnet | ||
|
||
Options: | ||
--chain-id <CHAIN_ID> Chain ID to deploy to | ||
--deployer <DEPLOYER> Address or private key to deploy with. Will | ||
require a Ledger if an address is provided. | ||
--ledger-path <LEDGER_PATH> HD path to use with the Ledger (only used when | ||
DEPLOYER is an address) | ||
--etherscan-api-key <ETHERSCAN_API_KEY> Etherscan API key for contracts verification | ||
(mainnet only) | ||
--help, -h Show this help message | ||
--open-demo-troves Open demo troves after deployment (local only) | ||
--rpc-url <RPC_URL> RPC URL to use | ||
--verify Verify contracts on Etherscan after deployment | ||
(requires ETHERSCAN_API_KEY to be set). | ||
|
||
Note: options can also be set via corresponding environment variables, | ||
e.g. --chain-id can be set via CHAIN_ID instead. Parameters take precedence over variables. | ||
`; | ||
|
||
const ANVIL_FIRST_ACCOUNT = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; | ||
|
||
async function parseArgs() { | ||
const { typeFlag } = await import("type-flag"); | ||
|
||
const { | ||
_: [networkPreset], | ||
flags: options, | ||
} = typeFlag({ | ||
chainId: { type: Number }, | ||
deployer: { type: String }, | ||
etherscanApiKey: { type: String }, | ||
help: { type: Boolean, alias: "h" }, | ||
ledgerPath: { type: String }, | ||
openDemoTroves: { type: Boolean }, | ||
rpcUrl: { type: String }, | ||
verify: { type: Boolean }, | ||
}); | ||
|
||
options.chainId ??= process.env.CHAIN_ID; | ||
options.deployer ??= process.env.DEPLOYER; | ||
options.etherscanApiKey ??= process.env.ETHERSCAN_API_KEY; | ||
options.ledgerPath ??= process.env.LEDGER_PATH; | ||
options.openDemoTroves ??= Boolean( | ||
process.env.OPEN_DEMO_TROVES && process.env.OPEN_DEMO_TROVES !== "false", | ||
); | ||
options.rpcUrl ??= process.env.RPC_URL; | ||
options.verify ??= Boolean( | ||
process.env.VERIFY && process.env.VERIFY !== "false", | ||
); | ||
|
||
return { networkPreset, options }; | ||
} | ||
|
||
async function main() { | ||
const { $, echo, fs } = await import("zx"); | ||
|
||
const { networkPreset, options } = await parseArgs(); | ||
|
||
if (options.help) { | ||
echo`${HELP}`; | ||
process.exit(0); | ||
} | ||
|
||
// network preset: local | ||
if (networkPreset === "local") { | ||
options.chainId ??= 31337; | ||
options.deployer ??= ANVIL_FIRST_ACCOUNT; | ||
options.rpcUrl ??= "http://localhost:8545"; | ||
} | ||
|
||
// network preset: tenderly-devnet | ||
if (networkPreset === "tenderly-devnet") { | ||
options.chainId ??= 1; | ||
options.rpcUrl ??= ( | ||
await $`tenderly devnet spawn-rpc ${[ | ||
"--project", | ||
"project", | ||
"--template", | ||
"liquity2", | ||
]} 2>&1`.quiet() | ||
).stdout.trim(); | ||
} | ||
|
||
// network preset: mainnet | ||
if (networkPreset === "mainnet") { | ||
options.chainId ??= 1; | ||
} | ||
|
||
// handle missing options | ||
if (!options.chainId) { | ||
throw new Error("--chain-id <CHAIN_ID> is required"); | ||
} | ||
if (!options.rpcUrl) { | ||
throw new Error("--rpc-url <RPC_URL> is required"); | ||
} | ||
if (!options.deployer) { | ||
throw new Error("--deployer <DEPLOYER> is required"); | ||
} | ||
if (options.verify && !options.etherscanApiKey) { | ||
throw new Error( | ||
"--verify requires --etherscan-api-key <ETHERSCAN_API_KEY>", | ||
); | ||
} | ||
|
||
const forgeArgs = [ | ||
"script", | ||
"scripts/DeployLiquity2.s.sol:DeployLiquity2Script", | ||
"--chain-id", | ||
options.chainId, | ||
"--rpc-url", | ||
options.rpcUrl, | ||
"--broadcast", | ||
]; | ||
|
||
// verify | ||
if (options.verify) { | ||
forgeArgs.push("--verify"); | ||
forgeArgs.push("--etherscan-api-key"); | ||
forgeArgs.push(options.etherscanApiKey); | ||
} | ||
|
||
// Ledger signing | ||
if (options.deployer.startsWith("0x") && options.deployer.length === 42) { | ||
forgeArgs.push("--ledger"); | ||
if (options.ledgerPath) { | ||
forgeArgs.push("--hd-paths"); | ||
forgeArgs.push(options.ledgerPath); | ||
} | ||
} | ||
|
||
echo` | ||
Environment: | ||
|
||
CHAIN_ID: ${options.chainId} | ||
DEPLOYER: ${options.deployer} | ||
LEDGER_PATH: ${options.ledgerPath} | ||
ETHERSCAN_API_KEY: ${options.etherscanApiKey && "(secret)"} | ||
OPEN_DEMO_TROVES: ${options.openDemoTroves ? "yes" : "no"} | ||
RPC_URL: ${options.rpcUrl} | ||
VERIFY: ${options.verify ? "yes" : "no"} | ||
`; | ||
|
||
const envVars = [ | ||
`DEPLOYER=${options.deployer}`, | ||
]; | ||
|
||
if (options.openDemoTroves) { | ||
envVars.push("OPEN_DEMO_TROVES=true"); | ||
} | ||
|
||
// deploy | ||
await $`${envVars} forge ${forgeArgs}`; | ||
|
||
// get deployed contracts | ||
const latestRun = await fs.readJson( | ||
`broadcast/DeployLiquity2.s.sol/${options.chainId}/run-latest.json`, | ||
); | ||
const deployedContracts = latestRun.transactions | ||
.filter((tx) => tx.transactionType === "CREATE") | ||
.map((tx) => [tx.contractName, tx.contractAddress]); | ||
|
||
// format deployed contracts | ||
const longestContractName = Math.max( | ||
...deployedContracts.map(([name]) => name.length), | ||
); | ||
const deployedContractsFormatted = deployedContracts | ||
.map(([name, address]) => `${name.padEnd(longestContractName)} ${address}`) | ||
.join("\n"); | ||
|
||
echo("Contract deployment complete."); | ||
echo(""); | ||
echo(deployedContractsFormatted); | ||
echo(""); | ||
} | ||
|
||
main().catch((error) => { | ||
console.error(error); | ||
require("./utils/deploy-cli").main().catch(({ message }) => { | ||
console.error(""); | ||
console.error(` Error: ${message}`); | ||
console.error(""); | ||
process.exit(1); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.