feat: migrate deployment to Hardhat Ignition
Replace the imperative deploy scripts with Hardhat Ignition modules:
- ignition/modules/{MockToken,Reputation,P2PIX}.ts orchestrate the full
deployment graph; P2PIX.ts wires MockToken + Reputation and deploys
P2PIX via its constructor
- ignition/parameters/localhost.json holds per-network values
(defaultBlocks, validSigners, MockToken supply)
- swap hardhat-toolbox for the individual plugins that Ignition needs;
add hardhat-verify (v2) and bump hardhat/hardhat-tracer accordingly
- delete scripts/1-deploy-mockToken.ts and scripts/2-deploy-p2pix.ts
- add deploy:{localhost,goerli,sepolia,mumbai} npm scripts
- include ignition/**/* in tsconfig.json
- gitignore ignition/deployments/chain-31337/ (ephemeral local state)
This branch carries the deployment-tooling migration only — the contract
is still the original constructor-based P2PIX. Proxy / UUPS deploy
support will land alongside the upgradeable contract change.
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -29,3 +29,7 @@ npm-debug.log*
|
|||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
docs/lib/mock/*.md
|
docs/lib/mock/*.md
|
||||||
|
.dagrobin/
|
||||||
|
|
||||||
|
# Hardhat Ignition local/ephemeral deployments
|
||||||
|
ignition/deployments/chain-31337/
|
||||||
|
|||||||
52
README.md
52
README.md
@@ -125,36 +125,52 @@ To grab deployment addresses you can just grab from deploys folder:
|
|||||||
import localhostDeploys from "p2pix-smart-contracts/deploys/localhost.json";
|
import localhostDeploys from "p2pix-smart-contracts/deploys/localhost.json";
|
||||||
```
|
```
|
||||||
|
|
||||||
## Deploying to local environment
|
## Deployment (Hardhat Ignition)
|
||||||
|
|
||||||
On the first teminal, use the following command and import some wallets to your Metamask, then connect to the network pointed:
|
Deployments are orchestrated by
|
||||||
|
[Hardhat Ignition](https://hardhat.org/ignition). Each module declares its
|
||||||
|
contracts; Ignition handles ordering, idempotency, and per-network state
|
||||||
|
under `ignition/deployments/`.
|
||||||
|
|
||||||
|
### Modules
|
||||||
|
|
||||||
|
- `ignition/modules/MockToken.ts` — ERC20 mock used in dev / testnets.
|
||||||
|
- `ignition/modules/Reputation.ts` — Reputation + Multicall.
|
||||||
|
- `ignition/modules/P2PIX.ts` — wires Reputation + MockToken and deploys
|
||||||
|
P2PIX via its constructor, returning the full set of addresses.
|
||||||
|
|
||||||
|
### Per-network parameters
|
||||||
|
|
||||||
|
Network-specific values (e.g. `defaultBlocks`, `validSigners`, MockToken
|
||||||
|
`supply`) live in `ignition/parameters/<network>.json`. Only
|
||||||
|
`localhost.json` is checked in; copy it to e.g. `goerli.json` and set the
|
||||||
|
network values before running the matching `deploy:*` script.
|
||||||
|
|
||||||
|
### Local environment
|
||||||
|
|
||||||
|
On the first terminal:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
yarn hardhat node
|
yarn hardhat node
|
||||||
```
|
```
|
||||||
|
|
||||||
On the second teminal, run the following commands:
|
On the second terminal:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
yarn deploy1:localhost
|
yarn deploy:localhost
|
||||||
yarn deploy2:localhost
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**_NOTE_:** The second script transfers 2M tokens to the first wallet of the node.
|
Addresses for every deployed contract are written to
|
||||||
To use the P2Pix smart contract first transfer some of the tokens to other wallets.
|
`ignition/deployments/chain-31337/deployed_addresses.json` (this path is
|
||||||
|
gitignored — local-only state).
|
||||||
|
|
||||||
## Deploying to testnets
|
### Testnets
|
||||||
|
|
||||||
Deploy to Ethereum's Goerli testnet:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
yarn deploy1:goerli
|
yarn deploy:goerli
|
||||||
yarn deploy2:goerli
|
yarn deploy:sepolia
|
||||||
|
yarn deploy:mumbai
|
||||||
```
|
```
|
||||||
|
|
||||||
Deploy to Polygon's Mumbai testnet:
|
Each command requires the matching `ignition/parameters/<network>.json`
|
||||||
|
and the relevant API keys in `.env`.
|
||||||
```sh
|
|
||||||
yarn deploy1:mumbai
|
|
||||||
yarn deploy2:mumbai
|
|
||||||
```
|
|
||||||
|
|||||||
14
ignition/modules/MockToken.ts
Normal file
14
ignition/modules/MockToken.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
|
||||||
|
import { ethers } from "ethers";
|
||||||
|
|
||||||
|
const DEFAULT_SUPPLY = ethers.utils
|
||||||
|
.parseEther("20000000")
|
||||||
|
.toString();
|
||||||
|
|
||||||
|
export default buildModule("MockToken", m => {
|
||||||
|
const supply = m.getParameter("supply", DEFAULT_SUPPLY);
|
||||||
|
|
||||||
|
const token = m.contract("MockToken", [supply]);
|
||||||
|
|
||||||
|
return { token };
|
||||||
|
});
|
||||||
32
ignition/modules/P2PIX.ts
Normal file
32
ignition/modules/P2PIX.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
|
||||||
|
|
||||||
|
import MockTokenModule from "./MockToken";
|
||||||
|
import ReputationModule from "./Reputation";
|
||||||
|
|
||||||
|
export default buildModule("P2PIX", m => {
|
||||||
|
const { token } = m.useModule(MockTokenModule);
|
||||||
|
const { reputation, multicall } = m.useModule(
|
||||||
|
ReputationModule,
|
||||||
|
);
|
||||||
|
|
||||||
|
const defaultBlocks = m.getParameter("defaultBlocks", 10);
|
||||||
|
const validSigners = m.getParameter<string[]>(
|
||||||
|
"validSigners",
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const p2pix = m.contract("P2PIX", [
|
||||||
|
defaultBlocks,
|
||||||
|
validSigners,
|
||||||
|
reputation,
|
||||||
|
[token],
|
||||||
|
[true],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
p2pix,
|
||||||
|
reputation,
|
||||||
|
multicall,
|
||||||
|
token,
|
||||||
|
};
|
||||||
|
});
|
||||||
8
ignition/modules/Reputation.ts
Normal file
8
ignition/modules/Reputation.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
|
||||||
|
|
||||||
|
export default buildModule("Reputation", m => {
|
||||||
|
const reputation = m.contract("Reputation", []);
|
||||||
|
const multicall = m.contract("Multicall", []);
|
||||||
|
|
||||||
|
return { reputation, multicall };
|
||||||
|
});
|
||||||
9
ignition/parameters/localhost.json
Normal file
9
ignition/parameters/localhost.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"P2PIX": {
|
||||||
|
"defaultBlocks": 10,
|
||||||
|
"validSigners": []
|
||||||
|
},
|
||||||
|
"MockToken": {
|
||||||
|
"supply": "20000000000000000000000000"
|
||||||
|
}
|
||||||
|
}
|
||||||
10
package.json
10
package.json
@@ -13,12 +13,10 @@
|
|||||||
"compile": "hardhat compile",
|
"compile": "hardhat compile",
|
||||||
"typechain": "hardhat typechain",
|
"typechain": "hardhat typechain",
|
||||||
"test": "hardhat test",
|
"test": "hardhat test",
|
||||||
"deploy1:localhost": "hardhat run scripts/1-deploy-mockToken.ts --network localhost",
|
"deploy:localhost": "hardhat ignition deploy ignition/modules/P2PIX.ts --network localhost --parameters ignition/parameters/localhost.json",
|
||||||
"deploy2:localhost": "hardhat run scripts/2-deploy-p2pix.ts --network localhost",
|
"deploy:goerli": "hardhat ignition deploy ignition/modules/P2PIX.ts --network goerli --parameters ignition/parameters/goerli.json",
|
||||||
"deploy1:goerli": "hardhat run scripts/1-deploy-mockToken.ts --network goerli",
|
"deploy:sepolia": "hardhat ignition deploy ignition/modules/P2PIX.ts --network sepolia --parameters ignition/parameters/sepolia.json",
|
||||||
"deploy2:goerli": "hardhat run scripts/2-deploy-p2pix.ts --network goerli",
|
"deploy:mumbai": "hardhat ignition deploy ignition/modules/P2PIX.ts --network polygon-mumbai --parameters ignition/parameters/mumbai.json",
|
||||||
"deploy1:mumbai": "hardhat run scripts/1-deploy-mockToken.ts --network polygon-mumbai",
|
|
||||||
"deploy2:mumbai": "hardhat run scripts/2-deploy-p2pix.ts --network polygon-mumbai",
|
|
||||||
"coverage": "hardhat coverage --solcoverjs ./.solcover.js --temp artifacts --testfiles \"test/**/*.ts\" && yarn typechain",
|
"coverage": "hardhat coverage --solcoverjs ./.solcover.js --temp artifacts --testfiles \"test/**/*.ts\" && yarn typechain",
|
||||||
"lint": "yarn lint:sol && yarn lint:ts && yarn prettier:check",
|
"lint": "yarn lint:sol && yarn lint:ts && yarn prettier:check",
|
||||||
"lint:sol": "solhint --config ./.solhint.json --max-warnings 0 \"contracts/**/*.sol\"",
|
"lint:sol": "solhint --config ./.solhint.json --max-warnings 0 \"contracts/**/*.sol\"",
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
import "@nomicfoundation/hardhat-ethers";
|
|
||||||
import * as fs from "fs";
|
|
||||||
import { ethers, network } from "hardhat";
|
|
||||||
|
|
||||||
import { Deploys } from "../test/utils/interfaces";
|
|
||||||
|
|
||||||
let deploysJson: Deploys;
|
|
||||||
const supply: BigInt = ethers.parseEther("20000000");
|
|
||||||
|
|
||||||
const main = async () => {
|
|
||||||
try {
|
|
||||||
const data = fs.readFileSync(
|
|
||||||
`./deploys/${network.name}.json`,
|
|
||||||
{ encoding: "utf-8" },
|
|
||||||
);
|
|
||||||
deploysJson = JSON.parse(data);
|
|
||||||
} catch (err) {
|
|
||||||
console.log("Error loading Master address: ", err);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const [deployer] = await ethers.getSigners();
|
|
||||||
console.log(`Deploying contracts with ${deployer.address}`);
|
|
||||||
|
|
||||||
let erc20 = await ethers.deployContract("MockToken", [supply]);
|
|
||||||
erc20 = await erc20.waitForDeployment();
|
|
||||||
|
|
||||||
deploysJson.token = await erc20.getAddress();
|
|
||||||
console.log("🚀 Mock Token Deployed:", await erc20.getAddress());
|
|
||||||
|
|
||||||
fs.writeFileSync(
|
|
||||||
`./deploys/${network.name}.json`,
|
|
||||||
JSON.stringify(deploysJson, undefined, 2),
|
|
||||||
);
|
|
||||||
|
|
||||||
/* UNCOMMENT WHEN DEPLOYING TO MAINNET/PUBLIC TESTNETS */
|
|
||||||
// verify
|
|
||||||
// await hre.run("verify:verify", {
|
|
||||||
// address: erc20.address,
|
|
||||||
// constructorArguments: [supply],
|
|
||||||
// });
|
|
||||||
};
|
|
||||||
|
|
||||||
main()
|
|
||||||
.then(() => process.exit(0))
|
|
||||||
.catch(error => {
|
|
||||||
console.log(error);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
import "@nomicfoundation/hardhat-ethers";
|
|
||||||
import * as fs from "fs";
|
|
||||||
import { ethers, network } from "hardhat";
|
|
||||||
|
|
||||||
import { Deploys } from "../test/utils/interfaces";
|
|
||||||
|
|
||||||
let deploysJson: Deploys;
|
|
||||||
|
|
||||||
const main = async () => {
|
|
||||||
try {
|
|
||||||
const data = fs.readFileSync(
|
|
||||||
`./deploys/${network.name}.json`,
|
|
||||||
{ encoding: "utf-8" },
|
|
||||||
);
|
|
||||||
deploysJson = JSON.parse(data);
|
|
||||||
} catch (err) {
|
|
||||||
console.log("Error loading Master address: ", err);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const [deployer] = await ethers.getSigners();
|
|
||||||
console.log(`Deploying contracts with ${deployer.address}`);
|
|
||||||
|
|
||||||
let reputation = await ethers.deployContract("Reputation");
|
|
||||||
let multicall = await ethers.deployContract("Multicall");
|
|
||||||
let p2pix = await ethers.deployContract("P2PIX", [
|
|
||||||
10,
|
|
||||||
deploysJson.signers,
|
|
||||||
reputation.target,
|
|
||||||
[deploysJson.token],
|
|
||||||
[true],
|
|
||||||
]);
|
|
||||||
|
|
||||||
reputation = await reputation.waitForDeployment();
|
|
||||||
multicall = await multicall.waitForDeployment();
|
|
||||||
p2pix = await p2pix.waitForDeployment();
|
|
||||||
|
|
||||||
deploysJson.p2pix = await p2pix.getAddress();
|
|
||||||
console.log("🚀 P2PIX Deployed:", await p2pix.getAddress());
|
|
||||||
console.log("🌠 Reputation Deployed:", await reputation.getAddress());
|
|
||||||
console.log("🛰 Multicall Deployed:", await multicall.getAddress());
|
|
||||||
|
|
||||||
fs.writeFileSync(
|
|
||||||
`./deploys/${network.name}.json`,
|
|
||||||
JSON.stringify(deploysJson, undefined, 2),
|
|
||||||
);
|
|
||||||
|
|
||||||
/* UNCOMMENT WHEN DEPLOYING TO MAINNET/PUBLIC TESTNETS */
|
|
||||||
//verify
|
|
||||||
// await hre.run("verify:verify", {
|
|
||||||
// address: p2pix.address,
|
|
||||||
// constructorArguments: [
|
|
||||||
// 10,
|
|
||||||
// deploysJson.signers,
|
|
||||||
// reputation.address,
|
|
||||||
// [deploysJson.token],
|
|
||||||
// [true],
|
|
||||||
// ],
|
|
||||||
// });
|
|
||||||
// await hre.run("verify:verify", {
|
|
||||||
// address: reputation.address,
|
|
||||||
// constructorArguments: [],
|
|
||||||
// });
|
|
||||||
// await hre.run("verify:verify", {
|
|
||||||
// address: mutlicall.address,
|
|
||||||
// constructorArguments: [],
|
|
||||||
// });
|
|
||||||
};
|
|
||||||
|
|
||||||
main()
|
|
||||||
.then(() => process.exit(0))
|
|
||||||
.catch(error => {
|
|
||||||
console.log(error);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
@@ -18,5 +18,10 @@
|
|||||||
},
|
},
|
||||||
"exclude": ["node_modules"],
|
"exclude": ["node_modules"],
|
||||||
"files": ["./hardhat.config.ts"],
|
"files": ["./hardhat.config.ts"],
|
||||||
"include": ["src/**/*", "test/**/*", "scripts/**/*"]
|
"include": [
|
||||||
|
"src/**/*",
|
||||||
|
"test/**/*",
|
||||||
|
"scripts/**/*",
|
||||||
|
"ignition/**/*"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user