diff --git a/contracts/README.md b/contracts/README.md index 2b09dc629..36b23216f 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -19,6 +19,7 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments - [EvidenceModule: proxy](https://arbiscan.io/address/0x48e052B4A6dC4F30e90930F1CeaAFd83b3981EB3), [implementation](https://arbiscan.io/address/0xE22500Fa27f696d06702367246bd17Bd2C8a4c5d) - [KlerosCoreNeo: proxy](https://arbiscan.io/address/0x991d2df165670b9cac3B022f4B68D65b664222ea), [implementation](https://arbiscan.io/address/0x17c39AB53A7072b167A74a85D47b30385c98ae89) - [KlerosCoreRulerNeo: proxy](https://arbiscan.io/address/0xc0169e0B19aE02ac4fADD689260CF038726DFE13), [implementation](https://arbiscan.io/address/0x85093b5EDa4F2e2E2fEDae34Da91239D6a08e324) +- [KlerosCoreSnapshotProxy](https://arbiscan.io/address/0xEF719a5B3352F607e6C4E17b7e0cDAd8322fEC95) - [KlerosV2NeoEarlyUser](https://arbiscan.io/address/0xfE34a72c55e512601E7d491A9c5b36373cE34d63) - [Pinakion](https://arbiscan.io/address/0x330bD769382cFc6d50175903434CCC8D206DCAE5) - [PolicyRegistry: proxy](https://arbiscan.io/address/0x553dcbF6aB3aE06a1064b5200Df1B5A9fB403d3c), [implementation](https://arbiscan.io/address/0x15E5964C7751dF8563eA4bC000301582C79BC454) @@ -39,6 +40,7 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments - [DisputeTemplateRegistry: proxy](https://sepolia.arbiscan.io/address/0xe763d31Cb096B4bc7294012B78FC7F148324ebcb), [implementation](https://sepolia.arbiscan.io/address/0x7283c07CC5224B20f431B1fa0E6d6db3cA02de34) - [EvidenceModule: proxy](https://sepolia.arbiscan.io/address/0xA88A9a25cE7f1d8b3941dA3b322Ba91D009E1397), [implementation](https://sepolia.arbiscan.io/address/0x63CF56e1c99E65E4a9eCDCC805F4735E016F2dc8) - [KlerosCore: proxy](https://sepolia.arbiscan.io/address/0xE8442307d36e9bf6aB27F1A009F95CE8E11C3479), [implementation](https://sepolia.arbiscan.io/address/0x0766e4B8c4a3aAC9371a5A9D6119E8125Adcfd55) +- [KlerosCoreSnapshotProxy](https://sepolia.arbiscan.io/address/0xd74e61A4dB9C6c3F2C97b62a319aE194f616858C) - [PNKFaucet](https://sepolia.arbiscan.io/address/0x9f6ffc13B685A68ae359fCA128dfE776458Df464) - [PinakionV2](https://sepolia.arbiscan.io/address/0x34B944D42cAcfC8266955D07A80181D2054aa225) - [PolicyRegistry: proxy](https://sepolia.arbiscan.io/address/0x2668c46A14af8997417138B064ca1bEB70769585), [implementation](https://sepolia.arbiscan.io/address/0xB958113f96950C7806d584eFBed964288d46a0B8) @@ -87,6 +89,7 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments - [KlerosCore: proxy](https://sepolia.arbiscan.io/address/0xA54e7A16d7460e38a8F324eF46782FB520d58CE8), [implementation](https://sepolia.arbiscan.io/address/0x91a373BBdE0532F86410682F362e2Cf685e95085) - [KlerosCoreNeo: proxy](https://sepolia.arbiscan.io/address/0x26bf077037550e437605F07e25EfcAd510715C3A), [implementation](https://sepolia.arbiscan.io/address/0x3bE96b7eAF6A3640DBa1f7CE58776D5b790B74CB) - [KlerosCoreRuler: proxy](https://sepolia.arbiscan.io/address/0x7ffcd32A0521645E6fCFd071A68F0e26957775a5), [implementation](https://sepolia.arbiscan.io/address/0x97e30A3A940856A3913437912C746f1aF6ccC76c) +- [KlerosCoreSnapshotProxy](https://sepolia.arbiscan.io/address/0x9300D415af6e747ADe3C6cbA09a3b3CD5fb0c091) - [KlerosCoreUniversity: proxy](https://sepolia.arbiscan.io/address/0x5AB37F38778Bc175852fA353056591D91c744ce6), [implementation](https://sepolia.arbiscan.io/address/0xF74DaBfC5F5dbdBD07636637204d9C35326D2906) - [KlerosV2NeoEarlyUser](https://sepolia.arbiscan.io/address/0x0d60Ff8bbCF49Bc5352328E7E28e141834d7750F) - [PNKFaucet](https://sepolia.arbiscan.io/address/0x7EFE468003Ad6A858b5350CDE0A67bBED58739dD) diff --git a/contracts/deploy/00-home-chain-arbitration-neo.ts b/contracts/deploy/00-home-chain-arbitration-neo.ts index 3aa5ceac9..c4530604e 100644 --- a/contracts/deploy/00-home-chain-arbitration-neo.ts +++ b/contracts/deploy/00-home-chain-arbitration-neo.ts @@ -122,6 +122,12 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) console.log(`core.changeArbitrableWhitelist(${resolver.address}, true)`); await core.changeArbitrableWhitelist(resolver.address, true); + + await deploy("KlerosCoreSnapshotProxy", { + from: deployer, + args: [deployer, core.target], + log: true, + }); }; deployArbitration.tags = ["ArbitrationNeo"]; diff --git a/contracts/deploy/00-home-chain-arbitration.ts b/contracts/deploy/00-home-chain-arbitration.ts index 559453910..e61805f31 100644 --- a/contracts/deploy/00-home-chain-arbitration.ts +++ b/contracts/deploy/00-home-chain-arbitration.ts @@ -10,6 +10,7 @@ import { ChainlinkRNG, DisputeKitClassic, KlerosCore } from "../typechain-types" const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { const { ethers, deployments, getNamedAccounts, getChainId } = hre; + const { deploy } = deployments; const { ZeroAddress } = hre.ethers; const RNG_LOOKAHEAD = 20; @@ -94,6 +95,12 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) } catch (e) { console.error("failed to change currency rates:", e); } + + await deploy("KlerosCoreSnapshotProxy", { + from: deployer, + args: [deployer, core.target], + log: true, + }); }; deployArbitration.tags = ["Arbitration"]; diff --git a/contracts/deployments/arbitrum/KlerosCoreSnapshotProxy.json b/contracts/deployments/arbitrum/KlerosCoreSnapshotProxy.json new file mode 100644 index 000000000..69426d3f2 --- /dev/null +++ b/contracts/deployments/arbitrum/KlerosCoreSnapshotProxy.json @@ -0,0 +1,228 @@ +{ + "address": "0xEF719a5B3352F607e6C4E17b7e0cDAd8322fEC95", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + }, + { + "internalType": "contract IKlerosCore", + "name": "_core", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "totalStaked", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IKlerosCore", + "name": "_core", + "type": "address" + } + ], + "name": "changeCore", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + } + ], + "name": "changeGovernor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "core", + "outputs": [ + { + "internalType": "contract IKlerosCore", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x9519002826064774768f0756c58d55c3f908265e0437de0cb6794f193df7bab4", + "receipt": { + "to": null, + "from": "0xf1C7c037891525E360C59f708739Ac09A7670c59", + "contractAddress": "0xEF719a5B3352F607e6C4E17b7e0cDAd8322fEC95", + "transactionIndex": 2, + "gasUsed": "381513", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x377819384e975cdff6f1207252d20ff63dae97c6e6f5e30a0ef4c0690e05362e", + "transactionHash": "0x9519002826064774768f0756c58d55c3f908265e0437de0cb6794f193df7bab4", + "logs": [], + "blockNumber": 303002159, + "cumulativeGasUsed": "1057838", + "status": 1, + "byzantium": true + }, + "args": [ + "0xf1C7c037891525E360C59f708739Ac09A7670c59", + "0x991d2df165670b9cac3B022f4B68D65b664222ea" + ], + "numDeployments": 1, + "solcInputHash": "ede3f7f4426109631936df3b8acee8f2", + "metadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"},{\"internalType\":\"contract IKlerosCore\",\"name\":\"_core\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IKlerosCore\",\"name\":\"_core\",\"type\":\"address\"}],\"name\":\"changeCore\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"changeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"core\",\"outputs\":[{\"internalType\":\"contract IKlerosCore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"balanceOf(address)\":{\"details\":\"Returns the amount of PNK staked in KlerosV2 for a particular address. Note: Proxy doesn't need to differentiate between courts so we pass 0 as courtID.\",\"params\":{\"_account\":\"The address to query.\"},\"returns\":{\"totalStaked\":\"Total amount staked in V2 by the address.\"}},\"changeCore(address)\":{\"details\":\"Changes the `core` storage variable.\",\"params\":{\"_core\":\"The new value for the `core` storage variable.\"}},\"changeGovernor(address)\":{\"details\":\"Changes the `governor` storage variable.\",\"params\":{\"_governor\":\"The new value for the `governor` storage variable.\"}},\"constructor\":{\"details\":\"Constructor\",\"params\":{\"_core\":\"KlerosCore to read the balance from.\",\"_governor\":\"The governor of the contract.\"}}},\"title\":\"KlerosCoreSnapshotProxy Proxy contract for V2 that exposes staked PNK with balanceOf() function for Snapshot voting.\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/arbitration/view/KlerosCoreSnapshotProxy.sol\":\"KlerosCoreSnapshotProxy\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"src/arbitration/interfaces/ISortitionModule.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.24;\\n\\nimport \\\"../../libraries/Constants.sol\\\";\\n\\ninterface ISortitionModule {\\n enum Phase {\\n staking, // Stake sum trees can be updated. Pass after `minStakingTime` passes and there is at least one dispute without jurors.\\n generating, // Waiting for a random number. Pass as soon as it is ready.\\n drawing // Jurors can be drawn. Pass after all disputes have jurors or `maxDrawingTime` passes.\\n }\\n\\n event NewPhase(Phase _phase);\\n\\n function createTree(bytes32 _key, bytes memory _extraData) external;\\n\\n function setStake(\\n address _account,\\n uint96 _courtID,\\n uint256 _newStake,\\n bool _alreadyTransferred\\n ) external returns (uint256 pnkDeposit, uint256 pnkWithdrawal, StakingResult stakingResult);\\n\\n function setJurorInactive(address _account) external;\\n\\n function lockStake(address _account, uint256 _relativeAmount) external;\\n\\n function unlockStake(address _account, uint256 _relativeAmount) external;\\n\\n function penalizeStake(address _account, uint256 _relativeAmount) external;\\n\\n function notifyRandomNumber(uint256 _drawnNumber) external;\\n\\n function draw(bytes32 _court, uint256 _coreDisputeID, uint256 _nonce) external view returns (address);\\n\\n function getJurorBalance(\\n address _juror,\\n uint96 _courtID\\n ) external view returns (uint256 totalStaked, uint256 totalLocked, uint256 stakedInCourt, uint256 nbCourts);\\n\\n function getJurorCourtIDs(address _juror) external view returns (uint96[] memory);\\n\\n function isJurorStaked(address _juror) external view returns (bool);\\n\\n function createDisputeHook(uint256 _disputeID, uint256 _roundID) external;\\n\\n function postDrawHook(uint256 _disputeID, uint256 _roundID) external;\\n}\\n\",\"keccak256\":\"0x18a4ff126bb51e7b5b0e3fbff7cf0dbbcfff7195ad79307e69cdbc9226e63502\",\"license\":\"MIT\"},\"src/arbitration/view/KlerosCoreSnapshotProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@unknownunknown1]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.24;\\n\\nimport {ISortitionModule} from \\\"../interfaces/ISortitionModule.sol\\\";\\n\\ninterface IKlerosCore {\\n function sortitionModule() external view returns (ISortitionModule);\\n}\\n\\n/// @title KlerosCoreSnapshotProxy\\n/// Proxy contract for V2 that exposes staked PNK with balanceOf() function for Snapshot voting.\\ncontract KlerosCoreSnapshotProxy {\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n IKlerosCore public core;\\n address public governor;\\n string public constant name = \\\"Staked Pinakion\\\";\\n string public constant symbol = \\\"stPNK\\\";\\n uint8 public constant decimals = 18;\\n\\n // ************************************* //\\n // * Modifiers * //\\n // ************************************* //\\n\\n modifier onlyByGovernor() {\\n require(governor == msg.sender, \\\"Access not allowed: Governor only.\\\");\\n _;\\n }\\n\\n // ************************************* //\\n // * Constructor * //\\n // ************************************* //\\n\\n /// @dev Constructor\\n /// @param _governor The governor of the contract.\\n /// @param _core KlerosCore to read the balance from.\\n constructor(address _governor, IKlerosCore _core) {\\n governor = _governor;\\n core = _core;\\n }\\n\\n // ************************************* //\\n // * Governance * //\\n // ************************************* //\\n\\n /// @dev Changes the `governor` storage variable.\\n /// @param _governor The new value for the `governor` storage variable.\\n function changeGovernor(address _governor) external onlyByGovernor {\\n governor = _governor;\\n }\\n\\n /// @dev Changes the `core` storage variable.\\n /// @param _core The new value for the `core` storage variable.\\n function changeCore(IKlerosCore _core) external onlyByGovernor {\\n core = _core;\\n }\\n\\n // ************************************* //\\n // * Public Views * //\\n // ************************************* //\\n\\n /// @dev Returns the amount of PNK staked in KlerosV2 for a particular address.\\n /// Note: Proxy doesn't need to differentiate between courts so we pass 0 as courtID.\\n /// @param _account The address to query.\\n /// @return totalStaked Total amount staked in V2 by the address.\\n function balanceOf(address _account) external view returns (uint256 totalStaked) {\\n (totalStaked, , , ) = core.sortitionModule().getJurorBalance(_account, 0);\\n }\\n}\\n\",\"keccak256\":\"0xf9516838d21bc8b4d8776d8d8b0b17d46ebb3d0940c055c09944f7f35adfd99d\",\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// Courts\\nuint96 constant FORKING_COURT = 0; // Index of the forking court.\\nuint96 constant GENERAL_COURT = 1; // Index of the default (general) court.\\n\\n// Dispute Kits\\nuint256 constant NULL_DISPUTE_KIT = 0; // Null pattern to indicate a top-level DK which has no parent. DEPRECATED, as its main purpose was to accommodate forest structure which is not used now.\\nuint256 constant DISPUTE_KIT_CLASSIC = 1; // Index of the default DK. 0 index is skipped.\\n\\n// Sortition Module\\nuint256 constant MAX_STAKE_PATHS = 4; // The maximum number of stake paths a juror can have.\\nuint256 constant DEFAULT_K = 6; // Default number of children per node.\\n\\n// Defaults\\nuint256 constant DEFAULT_NB_OF_JURORS = 3; // The default number of jurors in a dispute.\\nIERC20 constant NATIVE_CURRENCY = IERC20(address(0)); // The native currency, such as ETH on Arbitrum, Optimism and Ethereum L1.\\n\\nenum OnError {\\n Revert,\\n Return\\n}\\n\\nenum StakingResult {\\n Successful,\\n StakingTransferFailed,\\n UnstakingTransferFailed,\\n CannotStakeInMoreCourts,\\n CannotStakeInThisCourt,\\n CannotStakeLessThanMinStake,\\n CannotStakeMoreThanMaxStakePerJuror,\\n CannotStakeMoreThanMaxTotalStaked,\\n CannotStakeZeroWhenNoStake\\n}\\n\",\"keccak256\":\"0x5bbda7c304b3681b90feae33be694d04dc129edd60e1d07cb593b895fdc9cd4e\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5060405161053338038061053383398101604081905261002f91610078565b600180546001600160a01b039384166001600160a01b031991821617909155600080549290931691161790556100b2565b6001600160a01b038116811461007557600080fd5b50565b6000806040838503121561008b57600080fd5b825161009681610060565b60208401519092506100a781610060565b809150509250929050565b610472806100c16000396000f3fe608060405234801561001057600080fd5b50600436106100785760003560e01c806306fdde031461007d5780630c340a24146100c1578063313ce567146100ec57806370a08231146101065780638e4264601461012757806395d89b411461013c578063e4c0aaf414610160578063f2f4eb2614610173575b600080fd5b6100ab6040518060400160405280600f81526020016e29ba30b5b2b2102834b730b5b4b7b760891b81525081565b6040516100b8919061031c565b60405180910390f35b6001546100d4906001600160a01b031681565b6040516001600160a01b0390911681526020016100b8565b6100f4601281565b60405160ff90911681526020016100b8565b610119610114366004610383565b610186565b6040519081526020016100b8565b61013a610135366004610383565b61027b565b005b6100ab604051806040016040528060058152602001647374504e4b60d81b81525081565b61013a61016e366004610383565b6102d0565b6000546100d4906001600160a01b031681565b60008060009054906101000a90046001600160a01b03166001600160a01b0316632e1daf2f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fe91906103a7565b604051631a383be960e31b81526001600160a01b03848116600483015260006024830152919091169063d1c1df4890604401608060405180830381865afa15801561024d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027191906103c4565b5091949350505050565b6001546001600160a01b031633146102ae5760405162461bcd60e51b81526004016102a5906103fa565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031633146102fa5760405162461bcd60e51b81526004016102a5906103fa565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60006020808352835180602085015260005b8181101561034a5785810183015185820160400152820161032e565b506000604082860101526040601f19601f8301168501019250505092915050565b6001600160a01b038116811461038057600080fd5b50565b60006020828403121561039557600080fd5b81356103a08161036b565b9392505050565b6000602082840312156103b957600080fd5b81516103a08161036b565b600080600080608085870312156103da57600080fd5b505082516020840151604085015160609095015191969095509092509050565b60208082526022908201527f416363657373206e6f7420616c6c6f7765643a20476f7665726e6f72206f6e6c6040820152613c9760f11b60608201526080019056fea2646970667358221220ae7b8da51562210a09a90e77fc37c7a9669fa0ff5f919ec51b43ac365aace78464736f6c63430008180033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100785760003560e01c806306fdde031461007d5780630c340a24146100c1578063313ce567146100ec57806370a08231146101065780638e4264601461012757806395d89b411461013c578063e4c0aaf414610160578063f2f4eb2614610173575b600080fd5b6100ab6040518060400160405280600f81526020016e29ba30b5b2b2102834b730b5b4b7b760891b81525081565b6040516100b8919061031c565b60405180910390f35b6001546100d4906001600160a01b031681565b6040516001600160a01b0390911681526020016100b8565b6100f4601281565b60405160ff90911681526020016100b8565b610119610114366004610383565b610186565b6040519081526020016100b8565b61013a610135366004610383565b61027b565b005b6100ab604051806040016040528060058152602001647374504e4b60d81b81525081565b61013a61016e366004610383565b6102d0565b6000546100d4906001600160a01b031681565b60008060009054906101000a90046001600160a01b03166001600160a01b0316632e1daf2f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fe91906103a7565b604051631a383be960e31b81526001600160a01b03848116600483015260006024830152919091169063d1c1df4890604401608060405180830381865afa15801561024d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027191906103c4565b5091949350505050565b6001546001600160a01b031633146102ae5760405162461bcd60e51b81526004016102a5906103fa565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031633146102fa5760405162461bcd60e51b81526004016102a5906103fa565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60006020808352835180602085015260005b8181101561034a5785810183015185820160400152820161032e565b506000604082860101526040601f19601f8301168501019250505092915050565b6001600160a01b038116811461038057600080fd5b50565b60006020828403121561039557600080fd5b81356103a08161036b565b9392505050565b6000602082840312156103b957600080fd5b81516103a08161036b565b600080600080608085870312156103da57600080fd5b505082516020840151604085015160609095015191969095509092509050565b60208082526022908201527f416363657373206e6f7420616c6c6f7765643a20476f7665726e6f72206f6e6c6040820152613c9760f11b60608201526080019056fea2646970667358221220ae7b8da51562210a09a90e77fc37c7a9669fa0ff5f919ec51b43ac365aace78464736f6c63430008180033", + "devdoc": { + "kind": "dev", + "methods": { + "balanceOf(address)": { + "details": "Returns the amount of PNK staked in KlerosV2 for a particular address. Note: Proxy doesn't need to differentiate between courts so we pass 0 as courtID.", + "params": { + "_account": "The address to query." + }, + "returns": { + "totalStaked": "Total amount staked in V2 by the address." + } + }, + "changeCore(address)": { + "details": "Changes the `core` storage variable.", + "params": { + "_core": "The new value for the `core` storage variable." + } + }, + "changeGovernor(address)": { + "details": "Changes the `governor` storage variable.", + "params": { + "_governor": "The new value for the `governor` storage variable." + } + }, + "constructor": { + "details": "Constructor", + "params": { + "_core": "KlerosCore to read the balance from.", + "_governor": "The governor of the contract." + } + } + }, + "title": "KlerosCoreSnapshotProxy Proxy contract for V2 that exposes staked PNK with balanceOf() function for Snapshot voting.", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 216, + "contract": "src/arbitration/view/KlerosCoreSnapshotProxy.sol:KlerosCoreSnapshotProxy", + "label": "core", + "offset": 0, + "slot": "0", + "type": "t_contract(IKlerosCore)212" + }, + { + "astId": 218, + "contract": "src/arbitration/view/KlerosCoreSnapshotProxy.sol:KlerosCoreSnapshotProxy", + "label": "governor", + "offset": 0, + "slot": "1", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_contract(IKlerosCore)212": { + "encoding": "inplace", + "label": "contract IKlerosCore", + "numberOfBytes": "20" + } + } + } +} diff --git a/contracts/deployments/arbitrumSepolia/KlerosCoreSnapshotProxy.json b/contracts/deployments/arbitrumSepolia/KlerosCoreSnapshotProxy.json new file mode 100644 index 000000000..d24c1bea4 --- /dev/null +++ b/contracts/deployments/arbitrumSepolia/KlerosCoreSnapshotProxy.json @@ -0,0 +1,228 @@ +{ + "address": "0xd74e61A4dB9C6c3F2C97b62a319aE194f616858C", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + }, + { + "internalType": "contract IKlerosCore", + "name": "_core", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "totalStaked", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IKlerosCore", + "name": "_core", + "type": "address" + } + ], + "name": "changeCore", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + } + ], + "name": "changeGovernor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "core", + "outputs": [ + { + "internalType": "contract IKlerosCore", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x951a0309da4f71c199c36e0004ba7a67e1c68f4135942ee062040b6bf4edcf2f", + "receipt": { + "to": null, + "from": "0xf1C7c037891525E360C59f708739Ac09A7670c59", + "contractAddress": "0xd74e61A4dB9C6c3F2C97b62a319aE194f616858C", + "transactionIndex": 1, + "gasUsed": "363319", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xa62b5ceb98b8de3cd5d3f142c7384221d1d823adb28dcc8c9ae7945f22542274", + "transactionHash": "0x951a0309da4f71c199c36e0004ba7a67e1c68f4135942ee062040b6bf4edcf2f", + "logs": [], + "blockNumber": 121346526, + "cumulativeGasUsed": "363319", + "status": 1, + "byzantium": true + }, + "args": [ + "0xf1C7c037891525E360C59f708739Ac09A7670c59", + "0xE8442307d36e9bf6aB27F1A009F95CE8E11C3479" + ], + "numDeployments": 1, + "solcInputHash": "ede3f7f4426109631936df3b8acee8f2", + "metadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"},{\"internalType\":\"contract IKlerosCore\",\"name\":\"_core\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IKlerosCore\",\"name\":\"_core\",\"type\":\"address\"}],\"name\":\"changeCore\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"changeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"core\",\"outputs\":[{\"internalType\":\"contract IKlerosCore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"balanceOf(address)\":{\"details\":\"Returns the amount of PNK staked in KlerosV2 for a particular address. Note: Proxy doesn't need to differentiate between courts so we pass 0 as courtID.\",\"params\":{\"_account\":\"The address to query.\"},\"returns\":{\"totalStaked\":\"Total amount staked in V2 by the address.\"}},\"changeCore(address)\":{\"details\":\"Changes the `core` storage variable.\",\"params\":{\"_core\":\"The new value for the `core` storage variable.\"}},\"changeGovernor(address)\":{\"details\":\"Changes the `governor` storage variable.\",\"params\":{\"_governor\":\"The new value for the `governor` storage variable.\"}},\"constructor\":{\"details\":\"Constructor\",\"params\":{\"_core\":\"KlerosCore to read the balance from.\",\"_governor\":\"The governor of the contract.\"}}},\"title\":\"KlerosCoreSnapshotProxy Proxy contract for V2 that exposes staked PNK with balanceOf() function for Snapshot voting.\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/arbitration/view/KlerosCoreSnapshotProxy.sol\":\"KlerosCoreSnapshotProxy\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"src/arbitration/interfaces/ISortitionModule.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.24;\\n\\nimport \\\"../../libraries/Constants.sol\\\";\\n\\ninterface ISortitionModule {\\n enum Phase {\\n staking, // Stake sum trees can be updated. Pass after `minStakingTime` passes and there is at least one dispute without jurors.\\n generating, // Waiting for a random number. Pass as soon as it is ready.\\n drawing // Jurors can be drawn. Pass after all disputes have jurors or `maxDrawingTime` passes.\\n }\\n\\n event NewPhase(Phase _phase);\\n\\n function createTree(bytes32 _key, bytes memory _extraData) external;\\n\\n function setStake(\\n address _account,\\n uint96 _courtID,\\n uint256 _newStake,\\n bool _alreadyTransferred\\n ) external returns (uint256 pnkDeposit, uint256 pnkWithdrawal, StakingResult stakingResult);\\n\\n function setJurorInactive(address _account) external;\\n\\n function lockStake(address _account, uint256 _relativeAmount) external;\\n\\n function unlockStake(address _account, uint256 _relativeAmount) external;\\n\\n function penalizeStake(address _account, uint256 _relativeAmount) external;\\n\\n function notifyRandomNumber(uint256 _drawnNumber) external;\\n\\n function draw(bytes32 _court, uint256 _coreDisputeID, uint256 _nonce) external view returns (address);\\n\\n function getJurorBalance(\\n address _juror,\\n uint96 _courtID\\n ) external view returns (uint256 totalStaked, uint256 totalLocked, uint256 stakedInCourt, uint256 nbCourts);\\n\\n function getJurorCourtIDs(address _juror) external view returns (uint96[] memory);\\n\\n function isJurorStaked(address _juror) external view returns (bool);\\n\\n function createDisputeHook(uint256 _disputeID, uint256 _roundID) external;\\n\\n function postDrawHook(uint256 _disputeID, uint256 _roundID) external;\\n}\\n\",\"keccak256\":\"0x18a4ff126bb51e7b5b0e3fbff7cf0dbbcfff7195ad79307e69cdbc9226e63502\",\"license\":\"MIT\"},\"src/arbitration/view/KlerosCoreSnapshotProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@unknownunknown1]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.24;\\n\\nimport {ISortitionModule} from \\\"../interfaces/ISortitionModule.sol\\\";\\n\\ninterface IKlerosCore {\\n function sortitionModule() external view returns (ISortitionModule);\\n}\\n\\n/// @title KlerosCoreSnapshotProxy\\n/// Proxy contract for V2 that exposes staked PNK with balanceOf() function for Snapshot voting.\\ncontract KlerosCoreSnapshotProxy {\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n IKlerosCore public core;\\n address public governor;\\n string public constant name = \\\"Staked Pinakion\\\";\\n string public constant symbol = \\\"stPNK\\\";\\n uint8 public constant decimals = 18;\\n\\n // ************************************* //\\n // * Modifiers * //\\n // ************************************* //\\n\\n modifier onlyByGovernor() {\\n require(governor == msg.sender, \\\"Access not allowed: Governor only.\\\");\\n _;\\n }\\n\\n // ************************************* //\\n // * Constructor * //\\n // ************************************* //\\n\\n /// @dev Constructor\\n /// @param _governor The governor of the contract.\\n /// @param _core KlerosCore to read the balance from.\\n constructor(address _governor, IKlerosCore _core) {\\n governor = _governor;\\n core = _core;\\n }\\n\\n // ************************************* //\\n // * Governance * //\\n // ************************************* //\\n\\n /// @dev Changes the `governor` storage variable.\\n /// @param _governor The new value for the `governor` storage variable.\\n function changeGovernor(address _governor) external onlyByGovernor {\\n governor = _governor;\\n }\\n\\n /// @dev Changes the `core` storage variable.\\n /// @param _core The new value for the `core` storage variable.\\n function changeCore(IKlerosCore _core) external onlyByGovernor {\\n core = _core;\\n }\\n\\n // ************************************* //\\n // * Public Views * //\\n // ************************************* //\\n\\n /// @dev Returns the amount of PNK staked in KlerosV2 for a particular address.\\n /// Note: Proxy doesn't need to differentiate between courts so we pass 0 as courtID.\\n /// @param _account The address to query.\\n /// @return totalStaked Total amount staked in V2 by the address.\\n function balanceOf(address _account) external view returns (uint256 totalStaked) {\\n (totalStaked, , , ) = core.sortitionModule().getJurorBalance(_account, 0);\\n }\\n}\\n\",\"keccak256\":\"0xf9516838d21bc8b4d8776d8d8b0b17d46ebb3d0940c055c09944f7f35adfd99d\",\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// Courts\\nuint96 constant FORKING_COURT = 0; // Index of the forking court.\\nuint96 constant GENERAL_COURT = 1; // Index of the default (general) court.\\n\\n// Dispute Kits\\nuint256 constant NULL_DISPUTE_KIT = 0; // Null pattern to indicate a top-level DK which has no parent. DEPRECATED, as its main purpose was to accommodate forest structure which is not used now.\\nuint256 constant DISPUTE_KIT_CLASSIC = 1; // Index of the default DK. 0 index is skipped.\\n\\n// Sortition Module\\nuint256 constant MAX_STAKE_PATHS = 4; // The maximum number of stake paths a juror can have.\\nuint256 constant DEFAULT_K = 6; // Default number of children per node.\\n\\n// Defaults\\nuint256 constant DEFAULT_NB_OF_JURORS = 3; // The default number of jurors in a dispute.\\nIERC20 constant NATIVE_CURRENCY = IERC20(address(0)); // The native currency, such as ETH on Arbitrum, Optimism and Ethereum L1.\\n\\nenum OnError {\\n Revert,\\n Return\\n}\\n\\nenum StakingResult {\\n Successful,\\n StakingTransferFailed,\\n UnstakingTransferFailed,\\n CannotStakeInMoreCourts,\\n CannotStakeInThisCourt,\\n CannotStakeLessThanMinStake,\\n CannotStakeMoreThanMaxStakePerJuror,\\n CannotStakeMoreThanMaxTotalStaked,\\n CannotStakeZeroWhenNoStake\\n}\\n\",\"keccak256\":\"0x5bbda7c304b3681b90feae33be694d04dc129edd60e1d07cb593b895fdc9cd4e\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5060405161053338038061053383398101604081905261002f91610078565b600180546001600160a01b039384166001600160a01b031991821617909155600080549290931691161790556100b2565b6001600160a01b038116811461007557600080fd5b50565b6000806040838503121561008b57600080fd5b825161009681610060565b60208401519092506100a781610060565b809150509250929050565b610472806100c16000396000f3fe608060405234801561001057600080fd5b50600436106100785760003560e01c806306fdde031461007d5780630c340a24146100c1578063313ce567146100ec57806370a08231146101065780638e4264601461012757806395d89b411461013c578063e4c0aaf414610160578063f2f4eb2614610173575b600080fd5b6100ab6040518060400160405280600f81526020016e29ba30b5b2b2102834b730b5b4b7b760891b81525081565b6040516100b8919061031c565b60405180910390f35b6001546100d4906001600160a01b031681565b6040516001600160a01b0390911681526020016100b8565b6100f4601281565b60405160ff90911681526020016100b8565b610119610114366004610383565b610186565b6040519081526020016100b8565b61013a610135366004610383565b61027b565b005b6100ab604051806040016040528060058152602001647374504e4b60d81b81525081565b61013a61016e366004610383565b6102d0565b6000546100d4906001600160a01b031681565b60008060009054906101000a90046001600160a01b03166001600160a01b0316632e1daf2f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fe91906103a7565b604051631a383be960e31b81526001600160a01b03848116600483015260006024830152919091169063d1c1df4890604401608060405180830381865afa15801561024d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027191906103c4565b5091949350505050565b6001546001600160a01b031633146102ae5760405162461bcd60e51b81526004016102a5906103fa565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031633146102fa5760405162461bcd60e51b81526004016102a5906103fa565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60006020808352835180602085015260005b8181101561034a5785810183015185820160400152820161032e565b506000604082860101526040601f19601f8301168501019250505092915050565b6001600160a01b038116811461038057600080fd5b50565b60006020828403121561039557600080fd5b81356103a08161036b565b9392505050565b6000602082840312156103b957600080fd5b81516103a08161036b565b600080600080608085870312156103da57600080fd5b505082516020840151604085015160609095015191969095509092509050565b60208082526022908201527f416363657373206e6f7420616c6c6f7765643a20476f7665726e6f72206f6e6c6040820152613c9760f11b60608201526080019056fea2646970667358221220ae7b8da51562210a09a90e77fc37c7a9669fa0ff5f919ec51b43ac365aace78464736f6c63430008180033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100785760003560e01c806306fdde031461007d5780630c340a24146100c1578063313ce567146100ec57806370a08231146101065780638e4264601461012757806395d89b411461013c578063e4c0aaf414610160578063f2f4eb2614610173575b600080fd5b6100ab6040518060400160405280600f81526020016e29ba30b5b2b2102834b730b5b4b7b760891b81525081565b6040516100b8919061031c565b60405180910390f35b6001546100d4906001600160a01b031681565b6040516001600160a01b0390911681526020016100b8565b6100f4601281565b60405160ff90911681526020016100b8565b610119610114366004610383565b610186565b6040519081526020016100b8565b61013a610135366004610383565b61027b565b005b6100ab604051806040016040528060058152602001647374504e4b60d81b81525081565b61013a61016e366004610383565b6102d0565b6000546100d4906001600160a01b031681565b60008060009054906101000a90046001600160a01b03166001600160a01b0316632e1daf2f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fe91906103a7565b604051631a383be960e31b81526001600160a01b03848116600483015260006024830152919091169063d1c1df4890604401608060405180830381865afa15801561024d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027191906103c4565b5091949350505050565b6001546001600160a01b031633146102ae5760405162461bcd60e51b81526004016102a5906103fa565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031633146102fa5760405162461bcd60e51b81526004016102a5906103fa565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60006020808352835180602085015260005b8181101561034a5785810183015185820160400152820161032e565b506000604082860101526040601f19601f8301168501019250505092915050565b6001600160a01b038116811461038057600080fd5b50565b60006020828403121561039557600080fd5b81356103a08161036b565b9392505050565b6000602082840312156103b957600080fd5b81516103a08161036b565b600080600080608085870312156103da57600080fd5b505082516020840151604085015160609095015191969095509092509050565b60208082526022908201527f416363657373206e6f7420616c6c6f7765643a20476f7665726e6f72206f6e6c6040820152613c9760f11b60608201526080019056fea2646970667358221220ae7b8da51562210a09a90e77fc37c7a9669fa0ff5f919ec51b43ac365aace78464736f6c63430008180033", + "devdoc": { + "kind": "dev", + "methods": { + "balanceOf(address)": { + "details": "Returns the amount of PNK staked in KlerosV2 for a particular address. Note: Proxy doesn't need to differentiate between courts so we pass 0 as courtID.", + "params": { + "_account": "The address to query." + }, + "returns": { + "totalStaked": "Total amount staked in V2 by the address." + } + }, + "changeCore(address)": { + "details": "Changes the `core` storage variable.", + "params": { + "_core": "The new value for the `core` storage variable." + } + }, + "changeGovernor(address)": { + "details": "Changes the `governor` storage variable.", + "params": { + "_governor": "The new value for the `governor` storage variable." + } + }, + "constructor": { + "details": "Constructor", + "params": { + "_core": "KlerosCore to read the balance from.", + "_governor": "The governor of the contract." + } + } + }, + "title": "KlerosCoreSnapshotProxy Proxy contract for V2 that exposes staked PNK with balanceOf() function for Snapshot voting.", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 216, + "contract": "src/arbitration/view/KlerosCoreSnapshotProxy.sol:KlerosCoreSnapshotProxy", + "label": "core", + "offset": 0, + "slot": "0", + "type": "t_contract(IKlerosCore)212" + }, + { + "astId": 218, + "contract": "src/arbitration/view/KlerosCoreSnapshotProxy.sol:KlerosCoreSnapshotProxy", + "label": "governor", + "offset": 0, + "slot": "1", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_contract(IKlerosCore)212": { + "encoding": "inplace", + "label": "contract IKlerosCore", + "numberOfBytes": "20" + } + } + } +} diff --git a/contracts/deployments/arbitrumSepoliaDevnet/KlerosCoreSnapshotProxy.json b/contracts/deployments/arbitrumSepoliaDevnet/KlerosCoreSnapshotProxy.json new file mode 100644 index 000000000..f02b3234c --- /dev/null +++ b/contracts/deployments/arbitrumSepoliaDevnet/KlerosCoreSnapshotProxy.json @@ -0,0 +1,228 @@ +{ + "address": "0x9300D415af6e747ADe3C6cbA09a3b3CD5fb0c091", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + }, + { + "internalType": "contract IKlerosCore", + "name": "_core", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "totalStaked", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IKlerosCore", + "name": "_core", + "type": "address" + } + ], + "name": "changeCore", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + } + ], + "name": "changeGovernor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "core", + "outputs": [ + { + "internalType": "contract IKlerosCore", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x021bfe3731521c0619fa56f401c3873dad4e4b330d34f727bb401226b8120edf", + "receipt": { + "to": null, + "from": "0xf1C7c037891525E360C59f708739Ac09A7670c59", + "contractAddress": "0x9300D415af6e747ADe3C6cbA09a3b3CD5fb0c091", + "transactionIndex": 1, + "gasUsed": "363333", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc565952e226bb538ebd218e89b7923eb2517fb3ffcf5202fb1e1ccacbc1c30e5", + "transactionHash": "0x021bfe3731521c0619fa56f401c3873dad4e4b330d34f727bb401226b8120edf", + "logs": [], + "blockNumber": 121346480, + "cumulativeGasUsed": "363333", + "status": 1, + "byzantium": true + }, + "args": [ + "0xf1C7c037891525E360C59f708739Ac09A7670c59", + "0xA54e7A16d7460e38a8F324eF46782FB520d58CE8" + ], + "numDeployments": 1, + "solcInputHash": "ede3f7f4426109631936df3b8acee8f2", + "metadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"},{\"internalType\":\"contract IKlerosCore\",\"name\":\"_core\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IKlerosCore\",\"name\":\"_core\",\"type\":\"address\"}],\"name\":\"changeCore\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"changeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"core\",\"outputs\":[{\"internalType\":\"contract IKlerosCore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"balanceOf(address)\":{\"details\":\"Returns the amount of PNK staked in KlerosV2 for a particular address. Note: Proxy doesn't need to differentiate between courts so we pass 0 as courtID.\",\"params\":{\"_account\":\"The address to query.\"},\"returns\":{\"totalStaked\":\"Total amount staked in V2 by the address.\"}},\"changeCore(address)\":{\"details\":\"Changes the `core` storage variable.\",\"params\":{\"_core\":\"The new value for the `core` storage variable.\"}},\"changeGovernor(address)\":{\"details\":\"Changes the `governor` storage variable.\",\"params\":{\"_governor\":\"The new value for the `governor` storage variable.\"}},\"constructor\":{\"details\":\"Constructor\",\"params\":{\"_core\":\"KlerosCore to read the balance from.\",\"_governor\":\"The governor of the contract.\"}}},\"title\":\"KlerosCoreSnapshotProxy Proxy contract for V2 that exposes staked PNK with balanceOf() function for Snapshot voting.\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/arbitration/view/KlerosCoreSnapshotProxy.sol\":\"KlerosCoreSnapshotProxy\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"src/arbitration/interfaces/ISortitionModule.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.24;\\n\\nimport \\\"../../libraries/Constants.sol\\\";\\n\\ninterface ISortitionModule {\\n enum Phase {\\n staking, // Stake sum trees can be updated. Pass after `minStakingTime` passes and there is at least one dispute without jurors.\\n generating, // Waiting for a random number. Pass as soon as it is ready.\\n drawing // Jurors can be drawn. Pass after all disputes have jurors or `maxDrawingTime` passes.\\n }\\n\\n event NewPhase(Phase _phase);\\n\\n function createTree(bytes32 _key, bytes memory _extraData) external;\\n\\n function setStake(\\n address _account,\\n uint96 _courtID,\\n uint256 _newStake,\\n bool _alreadyTransferred\\n ) external returns (uint256 pnkDeposit, uint256 pnkWithdrawal, StakingResult stakingResult);\\n\\n function setJurorInactive(address _account) external;\\n\\n function lockStake(address _account, uint256 _relativeAmount) external;\\n\\n function unlockStake(address _account, uint256 _relativeAmount) external;\\n\\n function penalizeStake(address _account, uint256 _relativeAmount) external;\\n\\n function notifyRandomNumber(uint256 _drawnNumber) external;\\n\\n function draw(bytes32 _court, uint256 _coreDisputeID, uint256 _nonce) external view returns (address);\\n\\n function getJurorBalance(\\n address _juror,\\n uint96 _courtID\\n ) external view returns (uint256 totalStaked, uint256 totalLocked, uint256 stakedInCourt, uint256 nbCourts);\\n\\n function getJurorCourtIDs(address _juror) external view returns (uint96[] memory);\\n\\n function isJurorStaked(address _juror) external view returns (bool);\\n\\n function createDisputeHook(uint256 _disputeID, uint256 _roundID) external;\\n\\n function postDrawHook(uint256 _disputeID, uint256 _roundID) external;\\n}\\n\",\"keccak256\":\"0x18a4ff126bb51e7b5b0e3fbff7cf0dbbcfff7195ad79307e69cdbc9226e63502\",\"license\":\"MIT\"},\"src/arbitration/view/KlerosCoreSnapshotProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@unknownunknown1]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n/// @custom:deployments: []\\n\\npragma solidity 0.8.24;\\n\\nimport {ISortitionModule} from \\\"../interfaces/ISortitionModule.sol\\\";\\n\\ninterface IKlerosCore {\\n function sortitionModule() external view returns (ISortitionModule);\\n}\\n\\n/// @title KlerosCoreSnapshotProxy\\n/// Proxy contract for V2 that exposes staked PNK with balanceOf() function for Snapshot voting.\\ncontract KlerosCoreSnapshotProxy {\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n IKlerosCore public core;\\n address public governor;\\n string public constant name = \\\"Staked Pinakion\\\";\\n string public constant symbol = \\\"stPNK\\\";\\n uint8 public constant decimals = 18;\\n\\n // ************************************* //\\n // * Modifiers * //\\n // ************************************* //\\n\\n modifier onlyByGovernor() {\\n require(governor == msg.sender, \\\"Access not allowed: Governor only.\\\");\\n _;\\n }\\n\\n // ************************************* //\\n // * Constructor * //\\n // ************************************* //\\n\\n /// @dev Constructor\\n /// @param _governor The governor of the contract.\\n /// @param _core KlerosCore to read the balance from.\\n constructor(address _governor, IKlerosCore _core) {\\n governor = _governor;\\n core = _core;\\n }\\n\\n // ************************************* //\\n // * Governance * //\\n // ************************************* //\\n\\n /// @dev Changes the `governor` storage variable.\\n /// @param _governor The new value for the `governor` storage variable.\\n function changeGovernor(address _governor) external onlyByGovernor {\\n governor = _governor;\\n }\\n\\n /// @dev Changes the `core` storage variable.\\n /// @param _core The new value for the `core` storage variable.\\n function changeCore(IKlerosCore _core) external onlyByGovernor {\\n core = _core;\\n }\\n\\n // ************************************* //\\n // * Public Views * //\\n // ************************************* //\\n\\n /// @dev Returns the amount of PNK staked in KlerosV2 for a particular address.\\n /// Note: Proxy doesn't need to differentiate between courts so we pass 0 as courtID.\\n /// @param _account The address to query.\\n /// @return totalStaked Total amount staked in V2 by the address.\\n function balanceOf(address _account) external view returns (uint256 totalStaked) {\\n (totalStaked, , , ) = core.sortitionModule().getJurorBalance(_account, 0);\\n }\\n}\\n\",\"keccak256\":\"0xf9516838d21bc8b4d8776d8d8b0b17d46ebb3d0940c055c09944f7f35adfd99d\",\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n// Courts\\nuint96 constant FORKING_COURT = 0; // Index of the forking court.\\nuint96 constant GENERAL_COURT = 1; // Index of the default (general) court.\\n\\n// Dispute Kits\\nuint256 constant NULL_DISPUTE_KIT = 0; // Null pattern to indicate a top-level DK which has no parent. DEPRECATED, as its main purpose was to accommodate forest structure which is not used now.\\nuint256 constant DISPUTE_KIT_CLASSIC = 1; // Index of the default DK. 0 index is skipped.\\n\\n// Sortition Module\\nuint256 constant MAX_STAKE_PATHS = 4; // The maximum number of stake paths a juror can have.\\nuint256 constant DEFAULT_K = 6; // Default number of children per node.\\n\\n// Defaults\\nuint256 constant DEFAULT_NB_OF_JURORS = 3; // The default number of jurors in a dispute.\\nIERC20 constant NATIVE_CURRENCY = IERC20(address(0)); // The native currency, such as ETH on Arbitrum, Optimism and Ethereum L1.\\n\\nenum OnError {\\n Revert,\\n Return\\n}\\n\\nenum StakingResult {\\n Successful,\\n StakingTransferFailed,\\n UnstakingTransferFailed,\\n CannotStakeInMoreCourts,\\n CannotStakeInThisCourt,\\n CannotStakeLessThanMinStake,\\n CannotStakeMoreThanMaxStakePerJuror,\\n CannotStakeMoreThanMaxTotalStaked,\\n CannotStakeZeroWhenNoStake\\n}\\n\",\"keccak256\":\"0x5bbda7c304b3681b90feae33be694d04dc129edd60e1d07cb593b895fdc9cd4e\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5060405161053338038061053383398101604081905261002f91610078565b600180546001600160a01b039384166001600160a01b031991821617909155600080549290931691161790556100b2565b6001600160a01b038116811461007557600080fd5b50565b6000806040838503121561008b57600080fd5b825161009681610060565b60208401519092506100a781610060565b809150509250929050565b610472806100c16000396000f3fe608060405234801561001057600080fd5b50600436106100785760003560e01c806306fdde031461007d5780630c340a24146100c1578063313ce567146100ec57806370a08231146101065780638e4264601461012757806395d89b411461013c578063e4c0aaf414610160578063f2f4eb2614610173575b600080fd5b6100ab6040518060400160405280600f81526020016e29ba30b5b2b2102834b730b5b4b7b760891b81525081565b6040516100b8919061031c565b60405180910390f35b6001546100d4906001600160a01b031681565b6040516001600160a01b0390911681526020016100b8565b6100f4601281565b60405160ff90911681526020016100b8565b610119610114366004610383565b610186565b6040519081526020016100b8565b61013a610135366004610383565b61027b565b005b6100ab604051806040016040528060058152602001647374504e4b60d81b81525081565b61013a61016e366004610383565b6102d0565b6000546100d4906001600160a01b031681565b60008060009054906101000a90046001600160a01b03166001600160a01b0316632e1daf2f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fe91906103a7565b604051631a383be960e31b81526001600160a01b03848116600483015260006024830152919091169063d1c1df4890604401608060405180830381865afa15801561024d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027191906103c4565b5091949350505050565b6001546001600160a01b031633146102ae5760405162461bcd60e51b81526004016102a5906103fa565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031633146102fa5760405162461bcd60e51b81526004016102a5906103fa565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60006020808352835180602085015260005b8181101561034a5785810183015185820160400152820161032e565b506000604082860101526040601f19601f8301168501019250505092915050565b6001600160a01b038116811461038057600080fd5b50565b60006020828403121561039557600080fd5b81356103a08161036b565b9392505050565b6000602082840312156103b957600080fd5b81516103a08161036b565b600080600080608085870312156103da57600080fd5b505082516020840151604085015160609095015191969095509092509050565b60208082526022908201527f416363657373206e6f7420616c6c6f7765643a20476f7665726e6f72206f6e6c6040820152613c9760f11b60608201526080019056fea2646970667358221220ae7b8da51562210a09a90e77fc37c7a9669fa0ff5f919ec51b43ac365aace78464736f6c63430008180033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100785760003560e01c806306fdde031461007d5780630c340a24146100c1578063313ce567146100ec57806370a08231146101065780638e4264601461012757806395d89b411461013c578063e4c0aaf414610160578063f2f4eb2614610173575b600080fd5b6100ab6040518060400160405280600f81526020016e29ba30b5b2b2102834b730b5b4b7b760891b81525081565b6040516100b8919061031c565b60405180910390f35b6001546100d4906001600160a01b031681565b6040516001600160a01b0390911681526020016100b8565b6100f4601281565b60405160ff90911681526020016100b8565b610119610114366004610383565b610186565b6040519081526020016100b8565b61013a610135366004610383565b61027b565b005b6100ab604051806040016040528060058152602001647374504e4b60d81b81525081565b61013a61016e366004610383565b6102d0565b6000546100d4906001600160a01b031681565b60008060009054906101000a90046001600160a01b03166001600160a01b0316632e1daf2f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fe91906103a7565b604051631a383be960e31b81526001600160a01b03848116600483015260006024830152919091169063d1c1df4890604401608060405180830381865afa15801561024d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027191906103c4565b5091949350505050565b6001546001600160a01b031633146102ae5760405162461bcd60e51b81526004016102a5906103fa565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031633146102fa5760405162461bcd60e51b81526004016102a5906103fa565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60006020808352835180602085015260005b8181101561034a5785810183015185820160400152820161032e565b506000604082860101526040601f19601f8301168501019250505092915050565b6001600160a01b038116811461038057600080fd5b50565b60006020828403121561039557600080fd5b81356103a08161036b565b9392505050565b6000602082840312156103b957600080fd5b81516103a08161036b565b600080600080608085870312156103da57600080fd5b505082516020840151604085015160609095015191969095509092509050565b60208082526022908201527f416363657373206e6f7420616c6c6f7765643a20476f7665726e6f72206f6e6c6040820152613c9760f11b60608201526080019056fea2646970667358221220ae7b8da51562210a09a90e77fc37c7a9669fa0ff5f919ec51b43ac365aace78464736f6c63430008180033", + "devdoc": { + "kind": "dev", + "methods": { + "balanceOf(address)": { + "details": "Returns the amount of PNK staked in KlerosV2 for a particular address. Note: Proxy doesn't need to differentiate between courts so we pass 0 as courtID.", + "params": { + "_account": "The address to query." + }, + "returns": { + "totalStaked": "Total amount staked in V2 by the address." + } + }, + "changeCore(address)": { + "details": "Changes the `core` storage variable.", + "params": { + "_core": "The new value for the `core` storage variable." + } + }, + "changeGovernor(address)": { + "details": "Changes the `governor` storage variable.", + "params": { + "_governor": "The new value for the `governor` storage variable." + } + }, + "constructor": { + "details": "Constructor", + "params": { + "_core": "KlerosCore to read the balance from.", + "_governor": "The governor of the contract." + } + } + }, + "title": "KlerosCoreSnapshotProxy Proxy contract for V2 that exposes staked PNK with balanceOf() function for Snapshot voting.", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 216, + "contract": "src/arbitration/view/KlerosCoreSnapshotProxy.sol:KlerosCoreSnapshotProxy", + "label": "core", + "offset": 0, + "slot": "0", + "type": "t_contract(IKlerosCore)212" + }, + { + "astId": 218, + "contract": "src/arbitration/view/KlerosCoreSnapshotProxy.sol:KlerosCoreSnapshotProxy", + "label": "governor", + "offset": 0, + "slot": "1", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_contract(IKlerosCore)212": { + "encoding": "inplace", + "label": "contract IKlerosCore", + "numberOfBytes": "20" + } + } + } +} diff --git a/contracts/src/arbitration/view/KlerosCoreSnapshotProxy.sol b/contracts/src/arbitration/view/KlerosCoreSnapshotProxy.sol new file mode 100644 index 000000000..3e4493551 --- /dev/null +++ b/contracts/src/arbitration/view/KlerosCoreSnapshotProxy.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT + +/// @custom:authors: [@unknownunknown1] +/// @custom:reviewers: [] +/// @custom:auditors: [] +/// @custom:bounties: [] +/// @custom:deployments: [] + +pragma solidity 0.8.24; + +import {ISortitionModule} from "../interfaces/ISortitionModule.sol"; + +interface IKlerosCore { + function sortitionModule() external view returns (ISortitionModule); +} + +/// @title KlerosCoreSnapshotProxy +/// Proxy contract for V2 that exposes staked PNK with balanceOf() function for Snapshot voting. +contract KlerosCoreSnapshotProxy { + // ************************************* // + // * State Modifiers * // + // ************************************* // + + IKlerosCore public core; + address public governor; + string public constant name = "Staked Pinakion"; + string public constant symbol = "stPNK"; + uint8 public constant decimals = 18; + + // ************************************* // + // * Modifiers * // + // ************************************* // + + modifier onlyByGovernor() { + require(governor == msg.sender, "Access not allowed: Governor only."); + _; + } + + // ************************************* // + // * Constructor * // + // ************************************* // + + /// @dev Constructor + /// @param _governor The governor of the contract. + /// @param _core KlerosCore to read the balance from. + constructor(address _governor, IKlerosCore _core) { + governor = _governor; + core = _core; + } + + // ************************************* // + // * Governance * // + // ************************************* // + + /// @dev Changes the `governor` storage variable. + /// @param _governor The new value for the `governor` storage variable. + function changeGovernor(address _governor) external onlyByGovernor { + governor = _governor; + } + + /// @dev Changes the `core` storage variable. + /// @param _core The new value for the `core` storage variable. + function changeCore(IKlerosCore _core) external onlyByGovernor { + core = _core; + } + + // ************************************* // + // * Public Views * // + // ************************************* // + + /// @dev Returns the amount of PNK staked in KlerosV2 for a particular address. + /// Note: Proxy doesn't need to differentiate between courts so we pass 0 as courtID. + /// @param _account The address to query. + /// @return totalStaked Total amount staked in V2 by the address. + function balanceOf(address _account) external view returns (uint256 totalStaked) { + (totalStaked, , , ) = core.sortitionModule().getJurorBalance(_account, 0); + } +} diff --git a/contracts/test/foundry/KlerosCore.t.sol b/contracts/test/foundry/KlerosCore.t.sol index 56e33c9c5..66d2f22cd 100644 --- a/contracts/test/foundry/KlerosCore.t.sol +++ b/contracts/test/foundry/KlerosCore.t.sol @@ -3,9 +3,10 @@ pragma solidity 0.8.24; import {Test} from "forge-std/Test.sol"; import {console} from "forge-std/console.sol"; // Import the console for logging -import {KlerosCoreMock, KlerosCoreBase, IArbitratorV2} from "../../src/test/KlerosCoreMock.sol"; +import {KlerosCoreMock, KlerosCoreBase} from "../../src/test/KlerosCoreMock.sol"; +import {IArbitratorV2} from "../../src/arbitration/KlerosCoreBase.sol"; import {IDisputeKit} from "../../src/arbitration/interfaces/IDisputeKit.sol"; -import {DisputeKitClassic} from "../../src/arbitration/dispute-kits/DisputeKitClassic.sol"; +import {DisputeKitClassic, DisputeKitClassicBase} from "../../src/arbitration/dispute-kits/DisputeKitClassic.sol"; import {DisputeKitSybilResistant} from "../../src/arbitration/dispute-kits/DisputeKitSybilResistant.sol"; import {ISortitionModule} from "../../src/arbitration/interfaces/ISortitionModule.sol"; import {SortitionModuleMock, SortitionModuleBase} from "../../src/test/SortitionModuleMock.sol"; @@ -16,6 +17,7 @@ import {TestERC20} from "../../src/token/TestERC20.sol"; import {ArbitrableExample, IArbitrableV2} from "../../src/arbitration/arbitrables/ArbitrableExample.sol"; import {DisputeTemplateRegistry} from "../../src/arbitration/DisputeTemplateRegistry.sol"; import "../../src/libraries/Constants.sol"; +import {IKlerosCore, KlerosCoreSnapshotProxy} from "../../src/snapshot-proxy/KlerosCoreSnapshotProxy.sol"; contract KlerosCoreTest is Test { event Initialized(uint64 version); @@ -1278,6 +1280,33 @@ contract KlerosCoreTest is Test { core.setStakeBySortitionModule(staker1, GENERAL_COURT, 1000, false); } + function test_setStake_snapshotProxyCheck() public { + vm.prank(staker1); + core.setStake(GENERAL_COURT, 12346); + + KlerosCoreSnapshotProxy snapshotProxy = new KlerosCoreSnapshotProxy(governor, IKlerosCore(address(core))); + assertEq(snapshotProxy.name(), "Staked Pinakion", "Wrong name of the proxy token"); + assertEq(snapshotProxy.symbol(), "stPNK", "Wrong symbol of the proxy token"); + assertEq(snapshotProxy.decimals(), 18, "Wrong decimals of the proxy token"); + assertEq(snapshotProxy.governor(), msg.sender, "Wrong governor"); + assertEq(address(snapshotProxy.core()), address(core), "Wrong core in snapshot proxy"); + assertEq(snapshotProxy.balanceOf(staker1), 12346, "Wrong stPNK balance"); + + vm.prank(other); + vm.expectRevert(bytes("Access not allowed: Governor only.")); + snapshotProxy.changeCore(IKlerosCore(other)); + vm.prank(governor); + snapshotProxy.changeCore(IKlerosCore(other)); + assertEq(address(snapshotProxy.core()), other, "Wrong core in snapshot proxy after change"); + + vm.prank(other); + vm.expectRevert(bytes("Access not allowed: Governor only.")); + snapshotProxy.changeGovernor(other); + vm.prank(governor); + snapshotProxy.changeGovernor(other); + assertEq(snapshotProxy.governor(), other, "Wrong governor after change"); + } + // *************************************** // // * Disputes * // // *************************************** // @@ -1326,7 +1355,7 @@ contract KlerosCoreTest is Test { uint256 nbChoices = 2; vm.prank(disputer); vm.expectEmit(true, true, true, true); - emit DisputeKitClassic.DisputeCreation(disputeID, nbChoices, newExtraData); + emit DisputeKitClassicBase.DisputeCreation(disputeID, nbChoices, newExtraData); vm.expectEmit(true, true, true, true); emit IArbitratorV2.DisputeCreation(disputeID, arbitrable); arbitrable.createDispute{value: 0.04 ether}("Action"); @@ -1592,7 +1621,7 @@ contract KlerosCoreTest is Test { vm.prank(staker1); vm.expectEmit(true, true, true, true); - emit DisputeKitClassic.CommitCast(disputeID, staker1, voteIDs, commit); + emit DisputeKitClassicBase.CommitCast(disputeID, staker1, voteIDs, commit); disputeKit.castCommit(disputeID, voteIDs, commit); (, , , uint256 totalCommited, uint256 nbVoters, uint256 choiceCount) = disputeKit.getRoundInfo(disputeID, 0, 0); @@ -1608,7 +1637,7 @@ contract KlerosCoreTest is Test { vm.prank(staker1); vm.expectEmit(true, true, true, true); - emit DisputeKitClassic.CommitCast(disputeID, staker1, voteIDs, commit); + emit DisputeKitClassicBase.CommitCast(disputeID, staker1, voteIDs, commit); disputeKit.castCommit(disputeID, voteIDs, commit); (, , , totalCommited, nbVoters, choiceCount) = disputeKit.getRoundInfo(disputeID, 0, 0); @@ -1913,7 +1942,7 @@ contract KlerosCoreTest is Test { vm.prank(crowdfunder1); vm.expectEmit(true, true, true, true); - emit DisputeKitClassic.Contribution(disputeID, 0, 1, crowdfunder1, 0.21 ether); + emit DisputeKitClassicBase.Contribution(disputeID, 0, 1, crowdfunder1, 0.21 ether); disputeKit.fundAppeal{value: 0.21 ether}(disputeID, 1); // Fund the losing choice. Total cost will be 0.63 (0.21 + 0.21 * (20000/10000)) assertEq(crowdfunder1.balance, 9.79 ether, "Wrong balance of the crowdfunder"); @@ -1922,9 +1951,9 @@ contract KlerosCoreTest is Test { vm.prank(crowdfunder1); vm.expectEmit(true, true, true, true); - emit DisputeKitClassic.Contribution(disputeID, 0, 1, crowdfunder1, 0.42 ether); + emit DisputeKitClassicBase.Contribution(disputeID, 0, 1, crowdfunder1, 0.42 ether); vm.expectEmit(true, true, true, true); - emit DisputeKitClassic.ChoiceFunded(disputeID, 0, 1); + emit DisputeKitClassicBase.ChoiceFunded(disputeID, 0, 1); disputeKit.fundAppeal{value: 5 ether}(disputeID, 1); // Deliberately overpay to check reimburse assertEq(crowdfunder1.balance, 9.37 ether, "Wrong balance of the crowdfunder"); @@ -2117,7 +2146,7 @@ contract KlerosCoreTest is Test { vm.expectEmit(true, true, true, true); emit KlerosCoreBase.DisputeKitJump(disputeID, 1, newDkID, DISPUTE_KIT_CLASSIC); vm.expectEmit(true, true, true, true); - emit DisputeKitClassic.DisputeCreation(disputeID, 2, newExtraData); + emit DisputeKitClassicBase.DisputeCreation(disputeID, 2, newExtraData); vm.expectEmit(true, true, true, true); emit KlerosCoreBase.AppealDecision(disputeID, arbitrable); vm.expectEmit(true, true, true, true); @@ -2692,11 +2721,11 @@ contract KlerosCoreTest is Test { assertEq(address(disputeKit).balance, 1.04 ether, "Wrong balance of the DK"); vm.expectEmit(true, true, true, true); - emit DisputeKitClassic.Withdrawal(disputeID, 0, 1, crowdfunder1, 0.63 ether); + emit DisputeKitClassicBase.Withdrawal(disputeID, 0, 1, crowdfunder1, 0.63 ether); disputeKit.withdrawFeesAndRewards(disputeID, payable(crowdfunder1), 0, 1); vm.expectEmit(true, true, true, true); - emit DisputeKitClassic.Withdrawal(disputeID, 0, 2, crowdfunder2, 0.41 ether); + emit DisputeKitClassicBase.Withdrawal(disputeID, 0, 2, crowdfunder2, 0.41 ether); disputeKit.withdrawFeesAndRewards(disputeID, payable(crowdfunder2), 0, 2); assertEq(crowdfunder1.balance, 10 ether, "Wrong balance of the crowdfunder1");