-
Notifications
You must be signed in to change notification settings - Fork 49
Staking refactor including bug fixes #2021
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
base: dev
Are you sure you want to change the base?
Changes from all commits
a255c1d
c38ecba
70c173b
d27e204
8ca5d46
1611b4b
98c60ec
8fd11dc
1604509
fb35a86
3d4832a
57d5261
9d87373
0cf0ec4
4c8db66
8a5fbbd
799dad1
a050ca6
51d7739
0eb3292
d99def1
cb7d9b4
56b7b34
6c28f88
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,11 +2,11 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; | |
import { DeployFunction } from "hardhat-deploy/types"; | ||
import { getContractAddress } from "./utils/getContractAddress"; | ||
import { deployUpgradable } from "./utils/deployUpgradable"; | ||
import { changeCurrencyRate } from "./utils/klerosCoreHelper"; | ||
import { HomeChains, isSkipped, isDevnet, PNK, ETH } from "./utils"; | ||
import { getContractOrDeploy, getContractOrDeployUpgradable } from "./utils/getContractOrDeploy"; | ||
import { deployERC20AndFaucet } from "./utils/deployTokens"; | ||
import { ChainlinkRNG, DisputeKitClassic, KlerosCore } from "../typechain-types"; | ||
import { changeCurrencyRate } from "./utils/klerosCoreHelper"; | ||
|
||
const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { | ||
const { ethers, deployments, getNamedAccounts, getChainId } = hre; | ||
|
@@ -29,65 +29,104 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) | |
|
||
await getContractOrDeployUpgradable(hre, "EvidenceModule", { from: deployer, args: [deployer], log: true }); | ||
|
||
const disputeKit = await deployUpgradable(deployments, "DisputeKitClassic", { | ||
const disputeKit = await deployUpgradable(deployments, "DisputeKitClassicV2", { | ||
from: deployer, | ||
args: [deployer, ZeroAddress], | ||
contract: "DisputeKitClassic", | ||
args: [ | ||
deployer, | ||
ZeroAddress, // Placeholder for KlerosCore address, configured later | ||
], | ||
log: true, | ||
}); | ||
|
||
let klerosCoreAddress = await deployments.getOrNull("KlerosCore").then((deployment) => deployment?.address); | ||
if (!klerosCoreAddress) { | ||
const nonce = await ethers.provider.getTransactionCount(deployer); | ||
klerosCoreAddress = getContractAddress(deployer, nonce + 3); // deployed on the 4th tx (nonce+3): SortitionModule Impl tx, SortitionModule Proxy tx, KlerosCore Impl tx, KlerosCore Proxy tx | ||
console.log("calculated future KlerosCore address for nonce %d: %s", nonce + 3, klerosCoreAddress); | ||
} | ||
// Calculate future addresses for circular dependencies | ||
const nonce = await ethers.provider.getTransactionCount(deployer); | ||
|
||
const vaultAddress = getContractAddress(deployer, nonce + 1); // deployed on the 2nd tx (nonce+1): Vault Impl tx, Vault Proxy tx | ||
console.log("calculated future Vault address for nonce %d: %s", nonce + 1, vaultAddress); | ||
|
||
const stakeControllerAddress = getContractAddress(deployer, nonce + 5); // deployed on the 6th tx (nonce+5): Vault Impl tx, Vault Proxy tx, SortitionModule Impl tx, SortitionModule Proxy tx,, StakeController Impl tx, StakeController Proxy tx | ||
console.log("calculated future StakeController address for nonce %d: %s", nonce + 5, stakeControllerAddress); | ||
|
||
const klerosCoreAddress = getContractAddress(deployer, nonce + 7); // deployed on the 8th tx (nonce+7): Vault Impl tx, Vault Proxy tx, SortitionModule Impl tx, SortitionModule Proxy tx, StakeController Impl tx, StakeController Proxy tx, KlerosCore Impl tx, KlerosCore Proxy tx | ||
console.log("calculated future KlerosCore address for nonce %d: %s", nonce + 7, klerosCoreAddress); | ||
|
||
const vault = await deployUpgradable(deployments, "Vault", { | ||
from: deployer, | ||
args: [deployer, pnk.target, stakeControllerAddress, klerosCoreAddress], | ||
log: true, | ||
}); // nonce (implementation), nonce + 1 (proxy) | ||
|
||
// Deploy SortitionSumTree | ||
const sortitionModuleV2 = await deployUpgradable(deployments, "SortitionSumTree", { | ||
from: deployer, | ||
args: [deployer, stakeControllerAddress], | ||
log: true, | ||
}); // nonce + 2 (implementation), nonce + 3 (proxy) | ||
Comment on lines
+54
to
+65
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The Vault’s constructor is expected to hold a reference to the tradeable PNK token (proxy). Pass the proxy address instead: -args: [deployer, pnk.target, stakeControllerAddress, klerosCoreAddress],
+const pnkAddress = await pnk.getAddress(); // proxy address
+args: [deployer, pnkAddress, stakeControllerAddress, klerosCoreAddress], Same remark applies later to
🤖 Prompt for AI Agents
|
||
|
||
// Deploy StakeController | ||
const devnet = isDevnet(hre.network); | ||
const minStakingTime = devnet ? 180 : 1800; | ||
const maxFreezingTime = devnet ? 600 : 1800; | ||
const rng = (await ethers.getContract("ChainlinkRNG")) as ChainlinkRNG; | ||
const sortitionModule = await deployUpgradable(deployments, "SortitionModule", { | ||
const maxDrawingTime = devnet ? 600 : 1800; | ||
const rng = await ethers.getContract<ChainlinkRNG>("ChainlinkRNG"); | ||
const stakeController = await deployUpgradable(deployments, "StakeController", { | ||
from: deployer, | ||
args: [deployer, klerosCoreAddress, minStakingTime, maxFreezingTime, rng.target, RNG_LOOKAHEAD], | ||
args: [ | ||
deployer, | ||
klerosCoreAddress, | ||
vault.address, | ||
sortitionModuleV2.address, | ||
rng.target, | ||
minStakingTime, | ||
maxDrawingTime, | ||
RNG_LOOKAHEAD, | ||
], | ||
log: true, | ||
}); // nonce (implementation), nonce+1 (proxy) | ||
}); // nonce + 4 (implementation), nonce + 5 (proxy) | ||
|
||
const minStake = PNK(200); | ||
const alpha = 10000; | ||
const feeForJuror = ETH(0.1); | ||
const jurorsForCourtJump = 256; | ||
const klerosCore = await deployUpgradable(deployments, "KlerosCore", { | ||
|
||
// Deploy KlerosCore | ||
const klerosCoreV2 = await deployUpgradable(deployments, "KlerosCore", { | ||
from: deployer, | ||
args: [ | ||
deployer, | ||
deployer, | ||
pnk.target, | ||
ZeroAddress, // KlerosCore is configured later | ||
ZeroAddress, // JurorProsecutionModule, not implemented yet | ||
disputeKit.address, | ||
false, | ||
[minStake, alpha, feeForJuror, jurorsForCourtJump], | ||
[0, 0, 0, 10], // evidencePeriod, commitPeriod, votePeriod, appealPeriod | ||
ethers.toBeHex(5), // Extra data for sortition module will return the default value of K | ||
sortitionModule.address, | ||
stakeController.address, | ||
vault.address, | ||
], | ||
log: true, | ||
}); // nonce+2 (implementation), nonce+3 (proxy) | ||
}); | ||
|
||
// Configure cross-dependencies | ||
console.log("Configuring cross-dependencies..."); | ||
|
||
// disputeKit.changeCore() only if necessary | ||
const disputeKitContract = (await ethers.getContract("DisputeKitClassic")) as DisputeKitClassic; | ||
const disputeKitContract = await ethers.getContract<DisputeKitClassic>("DisputeKitClassicV2"); | ||
const currentCore = await disputeKitContract.core(); | ||
if (currentCore !== klerosCore.address) { | ||
console.log(`disputeKit.changeCore(${klerosCore.address})`); | ||
await disputeKitContract.changeCore(klerosCore.address); | ||
if (currentCore !== klerosCoreV2.address) { | ||
console.log(`disputeKit.changeCore(${klerosCoreV2.address})`); | ||
await disputeKitContract.changeCore(klerosCoreV2.address); | ||
} | ||
|
||
// rng.changeSortitionModule() only if necessary | ||
// Note: the RNG's `sortitionModule` variable is misleading, it's only for access control and should be renamed to `consumer`. | ||
const rngSortitionModule = await rng.sortitionModule(); | ||
if (rngSortitionModule !== sortitionModule.address) { | ||
console.log(`rng.changeSortitionModule(${sortitionModule.address})`); | ||
await rng.changeSortitionModule(sortitionModule.address); | ||
if (rngSortitionModule !== stakeController.address) { | ||
console.log(`rng.changeSortitionModule(${stakeController.address})`); | ||
await rng.changeSortitionModule(stakeController.address); | ||
} | ||
|
||
const core = (await hre.ethers.getContract("KlerosCore")) as KlerosCore; | ||
const core = await hre.ethers.getContract<KlerosCore>("KlerosCore"); | ||
try { | ||
await changeCurrencyRate(core, await pnk.getAddress(), true, 12225583, 12); | ||
await changeCurrencyRate(core, await dai.getAddress(), true, 60327783, 11); | ||
|
@@ -98,9 +137,16 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) | |
|
||
await deploy("KlerosCoreSnapshotProxy", { | ||
from: deployer, | ||
contract: "KlerosCoreSnapshotProxy", | ||
args: [deployer, core.target], | ||
log: true, | ||
}); | ||
|
||
console.log("✅ V2 Architecture deployment completed successfully!"); | ||
console.log(`📦 Vault: ${vault.address}`); | ||
console.log(`🎯 SortitionSumTree: ${sortitionModuleV2.address}`); | ||
console.log(`🎮 StakeController: ${stakeController.address}`); | ||
console.log(`⚖️ KlerosCore: ${klerosCoreV2.address}`); | ||
}; | ||
|
||
deployArbitration.tags = ["Arbitration"]; | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,8 +1,8 @@ | ||||||
import { KlerosCore, KlerosCoreNeo, KlerosCoreRuler, KlerosCoreUniversity } from "../../typechain-types"; | ||||||
import { KlerosCore, KlerosCoreNeo, KlerosCoreRuler, KlerosCoreUniversity, KlerosCore } from "../../typechain-types"; | ||||||
import { BigNumberish, toBigInt } from "ethers"; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix duplicate import causing syntax error. The import statement contains a duplicate Apply this diff to remove the duplicate: -import { KlerosCore, KlerosCoreNeo, KlerosCoreRuler, KlerosCoreUniversity, KlerosCore } from "../../typechain-types";
+import { KlerosCore, KlerosCoreNeo, KlerosCoreRuler, KlerosCoreUniversity } from "../../typechain-types"; 🧰 Tools🪛 Biome (1.9.4)[error] 1-1: Declarations inside of a a second declaration of
(parse) 🤖 Prompt for AI Agents
|
||||||
|
||||||
export const changeCurrencyRate = async ( | ||||||
core: KlerosCore | KlerosCoreNeo | KlerosCoreRuler | KlerosCoreUniversity, | ||||||
core: KlerosCore | KlerosCoreNeo | KlerosCoreRuler | KlerosCoreUniversity | KlerosCore, | ||||||
erc20: string, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix duplicate type in parameter annotation. The Apply this diff to remove the duplicate: - core: KlerosCore | KlerosCoreNeo | KlerosCoreRuler | KlerosCoreUniversity | KlerosCore,
+ core: KlerosCore | KlerosCoreNeo | KlerosCoreRuler | KlerosCoreUniversity, 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||
accepted: boolean, | ||||||
rateInEth: BigNumberish, | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Manual nonce arithmetic is fragile and will break on the first extra transaction
Hard-coding
nonce + {1‥7}
assumes that no additional tx slips in between the calculated point and the actual deployment (e.g. a library deploy, an implicit OZ admin‐upgrade deploy, or even a gas‐price retry).Once the assumption is violated every pre-computed address is wrong, bricking the whole deployment.
Consider replacing the manual math with:
predictAddress
helpers available in OZ Upgrades, ordeployments.get
and passing that concrete value to the next deploy step.This turns the circular-dependency problem into a deterministic two-phase deploy without relying on fragile nonce bookkeeping.
🤖 Prompt for AI Agents