Skip to content

Commit

Permalink
Replace type-flag by zx, move to tsx, move the script in a .ts file
Browse files Browse the repository at this point in the history
  • Loading branch information
bpierre committed Mar 29, 2024
1 parent 9473e03 commit 99c9511
Show file tree
Hide file tree
Showing 4 changed files with 406 additions and 196 deletions.
194 changes: 5 additions & 189 deletions contracts/deploy
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);
});
2 changes: 1 addition & 1 deletion contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"hardhat-gas-reporter": "^1.0.8",
"solidity-coverage": "^0.8.8",
"ts-node": ">=8.0.0",
"type-flag": "^3.0.0",
"tsx": "^4.7.1",
"typechain": "^8.1.0",
"typescript": ">=4.5.0",
"zx": "^7.2.3"
Expand Down
Loading

0 comments on commit 99c9511

Please sign in to comment.