Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions contracts/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ The format is based on [Common Changelog](https://common-changelog.org/).
- **Breaking:** Replace `require()` with `revert()` and custom errors outside KlerosCore for consistency and smaller bytecode ([#2084](https://github.com/kleros/kleros-v2/issues/2084))
- **Breaking:** Rename the interface from `RNG` to `IRNG` ([#2054](https://github.com/kleros/kleros-v2/issues/2054))
- **Breaking:** Remove the `_block` parameter from `IRNG.requestRandomness()` and `IRNG.receiveRandomness()`, not needed for the primary VRF-based RNG ([#2054](https://github.com/kleros/kleros-v2/issues/2054))
- **Breaking:** Rename `governor` to `owner` in order to comply with the lightweight ownership standard [ERC-5313](https://eipsinsight.com/ercs/erc-5313) ([#2112](https://github.com/kleros/kleros-v2/issues/2112))
- Make the primary VRF-based RNG fall back to `BlockhashRNG` if the VRF request is not fulfilled within a timeout ([#2054](https://github.com/kleros/kleros-v2/issues/2054))
- Authenticate the calls to the RNGs to prevent 3rd parties from depleting the Chainlink VRF subscription funds ([#2054](https://github.com/kleros/kleros-v2/issues/2054))
- Use `block.timestamp` rather than `block.number` for `BlockhashRNG` for better reliability on Arbitrum as block production is sporadic depending on network conditions. ([#2054](https://github.com/kleros/kleros-v2/issues/2054))
Expand Down
2 changes: 1 addition & 1 deletion contracts/deploy/00-home-chain-arbitration-ruler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
await deployUpgradable(deployments, "KlerosCoreRuler", {
from: deployer,
args: [
deployer, // governor
deployer, // owner
pnk.target,
[minStake, alpha, feeForJuror, jurorsForCourtJump],
],
Expand Down
2 changes: 1 addition & 1 deletion contracts/deploy/00-home-chain-arbitration-university.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
const klerosCore = await deployUpgradable(deployments, "KlerosCoreUniversity", {
from: deployer,
args: [
deployer, // governor
deployer, // owner
deployer, // instructor
pnk.target,
ZeroAddress, // KlerosCore is configured later
Expand Down
2 changes: 1 addition & 1 deletion contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import "hardhat-contract-sizer";
import "hardhat-tracer";
require("./scripts/populatePolicyRegistry");
require("./scripts/populateCourts");
require("./scripts/changeGovernor");
require("./scripts/changeOwner");
require("./scripts/getDisputeTemplate");
require("./scripts/compareStorageLayout");
require("./scripts/storage-layout");
Expand Down
77 changes: 0 additions & 77 deletions contracts/scripts/changeGovernor.ts

This file was deleted.

77 changes: 77 additions & 0 deletions contracts/scripts/changeOwner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { task } from "hardhat/config";
import { prompt, print } from "gluegun";
import { Cores, getContracts } from "./utils/contracts";
import { isAddress } from "viem";

const { bold } = print.colors;

task("change-owner", "Changes the owner for all the contracts")
.addPositionalParam("newOwner", "The address of the new owner")
.addOptionalParam("coreType", "The type of core to use between base, neo, university (default: base)", Cores.BASE)
.setAction(async (taskArgs, hre) => {
const newOwner = taskArgs.newOwner;
if (!isAddress(newOwner)) {
throw new Error("Invalid owner address provided");
}
print.highlight(`💣 Changing owner to ${bold(newOwner)}`);

const { confirm } = await prompt.ask({
type: "confirm",
name: "confirm",
message: "Are you sure you want to proceed?",
});
if (!confirm) {
console.log("Operation cancelled by user.");
return;
}

const coreType = Cores[taskArgs.coreType.toUpperCase() as keyof typeof Cores];
if (coreType === undefined) {
console.error("Invalid core type, must be one of base, neo, university");
return;
}
console.log("Using core type %s", coreType);

const {
core,
disputeKitClassic,
disputeResolver,
disputeTemplateRegistry,
policyRegistry,
chainlinkRng,
randomizerRng,
snapshotProxy,
sortition,
evidence,
} = await getContracts(hre, coreType);

const updateOwner = async (contractName: string, contractInstance: any) => {
print.info(`Changing owner for ${contractName}`);

const spinner = print.spin(`Executing transaction for ${contractName}...`);
try {
const tx = await contractInstance.changeOwner(newOwner);
await tx.wait();
spinner.succeed(`Owner changed for ${contractName}, tx hash: ${tx.hash}`);
} catch (error) {
if (error instanceof Error) {
spinner.fail(`Failed to change owner for ${contractName}: ${error.message}`);
} else {
spinner.fail(`Failed to change owner for ${contractName}: ${String(error)}`);
}
}
};

await updateOwner("KlerosCore", core);
await updateOwner("DisputeKitClassic", disputeKitClassic);
await updateOwner("DisputeResolver", disputeResolver);
await updateOwner("DisputeTemplateRegistry", disputeTemplateRegistry);
await updateOwner("PolicyRegistry", policyRegistry);
await updateOwner("KlerosCoreSnapshotProxy", snapshotProxy);
await updateOwner("SortitionModule", sortition);
await updateOwner("EvidenceModule", evidence);
if (chainlinkRng) await updateOwner("ChainlinkRNG", chainlinkRng);
if (randomizerRng) await updateOwner("RandomizerRNG", randomizerRng);

print.success("Owner changed successfully");
});
Comment on lines +1 to +77
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Repo-wide verification: detect leftover governor APIs.

Run the following to find any stragglers like changeGovernor, onlyByGovernor, or GovernorOnly still referenced by scripts or contracts.


🏁 Script executed:

#!/bin/bash
# Find lingering governor-era identifiers.
rg -nP --type=sol --type=ts --type=js -C2 '\b(changeGovernor|onlyByGovernor|GovernorOnly|governor\(\))\b' contracts | sed -n '1,200p'

Length of output: 161


I’ve updated the search to use file globs instead of unsupported --type=sol. Please run this to catch any leftover governor-era identifiers:


🏁 Script executed:

#!/bin/bash
# Find lingering governor-era identifiers in .sol, .ts, and .js under contracts/
rg -nP -C2 '\b(changeGovernor|onlyByGovernor|GovernorOnly|governor\(\))\b' -g '*.sol' -g '*.ts' -g '*.js' contracts | sed -n '1,200p'

Length of output: 13931


Regenerate or Exclude Stale ABI Definitions
We’ve confirmed dozens of changeGovernor and GovernorOnly occurrences—but all are coming from the auto-generated viem ABI files under

  • contracts/deployments/testnet.viem.ts
  • contracts/deployments/mainnet.viem.ts

These aren’t hand‐written references in your scripts or contracts themselves, but stale ABI definitions. You should either:

  • Regenerate the deployments/ABI files so they no longer include the old governor methods, or
  • Exclude contracts/deployments/** from your grep checks (e.g. add -g '!contracts/deployments/**') and optionally remove them from version control if they’re fully generated at build time.

Please update accordingly to ensure no leftover governor APIs remain in your committed source.

6 changes: 3 additions & 3 deletions contracts/scripts/utils/execution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { type BuilderTransaction, template, transaction, transactionBuilderUrl }
const governableAbi = [
{
inputs: [],
name: "governor",
name: "owner",
outputs: [
{
internalType: "address",
Expand All @@ -25,8 +25,8 @@ export const execute = async (tx: ContractTransaction) => {
const { ethers } = hre;

const contract = await ethers.getContractAt(governableAbi, tx.to);
const governor = await contract.governor();
const isContract = (await ethers.provider.getCode(governor)).length > 2;
const owner = await contract.owner();
const isContract = (await ethers.provider.getCode(owner)).length > 2;
if (isContract) {
// Don't execute, just log the tx. It must be submitted for execution separately.
const { to, value, data } = tx;
Expand Down
6 changes: 3 additions & 3 deletions contracts/scripts/utils/tx-builder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { arbitrum } from "viem/chains";

const governor = "0x66e8DE9B42308c6Ca913D1EE041d6F6fD037A57e";
const owner = "0x66e8DE9B42308c6Ca913D1EE041d6F6fD037A57e";
const deployer = "0xf1C7c037891525E360C59f708739Ac09A7670c59";

// Transaction batch example: https://github.com/safe-global/safe-wallet-monorepo/blob/8bbf3b82edc347b70a038629cd9afd45eb1ed38a/apps/web/cypress/fixtures/test-working-batch.json
Expand All @@ -12,7 +12,7 @@ export const template = ({ name, transactions }: { name: string; transactions: B
name,
description: "", // Not used because the Safe app doesn't show it
txBuilderVersion: "1.18.0",
createdFromSafeAddress: governor,
createdFromSafeAddress: owner,
createdFromOwnerAddress: deployer,
},
transactions,
Expand Down Expand Up @@ -42,4 +42,4 @@ export interface BuilderTransaction {
contractInputsValues: null;
}

export const transactionBuilderUrl = `https://app.safe.global/apps/open?safe=arb1:${governor}&appUrl=https%3A%2F%2Fapps-portal.safe.global%2Ftx-builder`;
export const transactionBuilderUrl = `https://app.safe.global/apps/open?safe=arb1:${owner}&appUrl=https%3A%2F%2Fapps-portal.safe.global%2Ftx-builder`;
2 changes: 1 addition & 1 deletion contracts/scripts/viemTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const main = async () => {
client: client,
});

await disputeKit.read.governor().then(console.log);
await disputeKit.read.owner().then(console.log);

// --------------------------------------------------

Expand Down
28 changes: 14 additions & 14 deletions contracts/src/arbitration/DisputeTemplateRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ contract DisputeTemplateRegistry is IDisputeTemplateRegistry, UUPSProxiable, Ini
// * Storage * //
// ************************************* //

/// @dev The governor of the contract.
address public governor;
/// @dev The owner of the contract.
address public owner;

/// @dev The number of templates.
uint256 public templates;
Expand All @@ -24,8 +24,8 @@ contract DisputeTemplateRegistry is IDisputeTemplateRegistry, UUPSProxiable, Ini
// * Function Modifiers * //
// ************************************* //

modifier onlyByGovernor() {
if (governor != msg.sender) revert GovernorOnly();
modifier onlyByOwner() {
if (owner != msg.sender) revert OwnerOnly();
_;
}

Expand All @@ -39,9 +39,9 @@ contract DisputeTemplateRegistry is IDisputeTemplateRegistry, UUPSProxiable, Ini
}

/// @dev Initializer
/// @param _governor Governor of the contract.
function initialize(address _governor) external reinitializer(1) {
governor = _governor;
/// @param _owner Owner of the contract.
function initialize(address _owner) external reinitializer(1) {
owner = _owner;
}

function initialize2() external reinitializer(2) {
Expand All @@ -53,15 +53,15 @@ contract DisputeTemplateRegistry is IDisputeTemplateRegistry, UUPSProxiable, Ini
// ************************ //

/// @dev Access Control to perform implementation upgrades (UUPS Proxiable)
/// Only the governor can perform upgrades (`onlyByGovernor`)
function _authorizeUpgrade(address) internal view override onlyByGovernor {
/// Only the owner can perform upgrades (`onlyByOwner`)
function _authorizeUpgrade(address) internal view override onlyByOwner {
// NOP
}

/// @dev Changes the governor of the contract.
/// @param _governor The new governor.
function changeGovernor(address _governor) external onlyByGovernor {
governor = _governor;
/// @dev Changes the owner of the contract.
/// @param _owner The new owner.
function changeOwner(address _owner) external onlyByOwner {
owner = _owner;
}

// ************************************* //
Expand All @@ -85,5 +85,5 @@ contract DisputeTemplateRegistry is IDisputeTemplateRegistry, UUPSProxiable, Ini
// * Errors * //
// ************************************* //

error GovernorOnly();
error OwnerOnly();
}
10 changes: 5 additions & 5 deletions contracts/src/arbitration/KlerosCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ contract KlerosCore is KlerosCoreBase {
}

/// @dev Initializer (constructor equivalent for upgradable contracts).
/// @param _governor The governor's address.
/// @param _owner The owner's address.
/// @param _guardian The guardian's address.
/// @param _pinakion The address of the token contract.
/// @param _jurorProsecutionModule The address of the juror prosecution module.
Expand All @@ -32,7 +32,7 @@ contract KlerosCore is KlerosCoreBase {
/// @param _sortitionModuleAddress The sortition module responsible for sortition of the jurors.
/// @param _wNative The wrapped native token address, typically wETH.
function initialize(
address _governor,
address _owner,
address _guardian,
IERC20 _pinakion,
address _jurorProsecutionModule,
Expand All @@ -45,7 +45,7 @@ contract KlerosCore is KlerosCoreBase {
address _wNative
) external reinitializer(1) {
__KlerosCoreBase_initialize(
_governor,
_owner,
_guardian,
_pinakion,
_jurorProsecutionModule,
Expand All @@ -68,8 +68,8 @@ contract KlerosCore is KlerosCoreBase {
// ************************************* //

/// @dev Access Control to perform implementation upgrades (UUPS Proxiable)
/// Only the governor can perform upgrades (`onlyByGovernor`)
function _authorizeUpgrade(address) internal view override onlyByGovernor {
/// Only the owner can perform upgrades (`onlyByOwner`)
function _authorizeUpgrade(address) internal view override onlyByOwner {
// NOP
}
}
Loading
Loading