From 66c5e8f4265b383871e80e04deae124c826fcf3a Mon Sep 17 00:00:00 2001 From: thasmi21 Date: Fri, 1 Aug 2025 13:00:32 +0100 Subject: [PATCH 1/3] feat(arbitration): implement SafeSend library for secure ETH transfers --- .../deploy/00-home-chain-arbitration-neo.ts | 3 ++- .../deploy/00-home-chain-arbitration-ruler.ts | 1 + .../00-home-chain-arbitration-university.ts | 3 ++- contracts/deploy/00-home-chain-arbitration.ts | 9 +++---- contracts/src/arbitration/KlerosCore.sol | 7 ++++-- contracts/src/arbitration/KlerosCoreBase.sol | 13 ++++++---- contracts/src/arbitration/KlerosCoreNeo.sol | 7 ++++-- contracts/src/arbitration/KlerosGovernor.sol | 15 ++++++++---- .../arbitration/devtools/KlerosCoreRuler.sol | 10 ++++++-- .../dispute-kits/DisputeKitClassic.sol | 5 ++-- .../dispute-kits/DisputeKitClassicBase.sol | 15 +++++++++--- .../dispute-kits/DisputeKitGated.sol | 5 ++-- .../dispute-kits/DisputeKitGatedShutter.sol | 5 ++-- .../dispute-kits/DisputeKitShutter.sol | 5 ++-- .../dispute-kits/DisputeKitSybilResistant.sol | 10 ++++++-- .../university/KlerosCoreUniversity.sol | 14 +++++++---- contracts/src/libraries/SafeSend.sol | 24 +++++++++++++++++++ 17 files changed, 114 insertions(+), 37 deletions(-) create mode 100644 contracts/src/libraries/SafeSend.sol diff --git a/contracts/deploy/00-home-chain-arbitration-neo.ts b/contracts/deploy/00-home-chain-arbitration-neo.ts index c4530604e..1020da715 100644 --- a/contracts/deploy/00-home-chain-arbitration-neo.ts +++ b/contracts/deploy/00-home-chain-arbitration-neo.ts @@ -32,7 +32,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) const disputeKit = await deployUpgradable(deployments, "DisputeKitClassicNeo", { from: deployer, contract: "DisputeKitClassic", - args: [deployer, ZeroAddress], + args: [deployer, ZeroAddress, weth.target], log: true, }); @@ -81,6 +81,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) ethers.toBeHex(5), // Extra data for sortition module will return the default value of K sortitionModule.address, nft.target, + weth.target, ], log: true, }); // nonce+2 (implementation), nonce+3 (proxy) diff --git a/contracts/deploy/00-home-chain-arbitration-ruler.ts b/contracts/deploy/00-home-chain-arbitration-ruler.ts index d49431c46..585bb552e 100644 --- a/contracts/deploy/00-home-chain-arbitration-ruler.ts +++ b/contracts/deploy/00-home-chain-arbitration-ruler.ts @@ -32,6 +32,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) deployer, // governor pnk.target, [minStake, alpha, feeForJuror, jurorsForCourtJump], + weth.target, ], log: true, }); diff --git a/contracts/deploy/00-home-chain-arbitration-university.ts b/contracts/deploy/00-home-chain-arbitration-university.ts index 218e498b9..37c7f7531 100644 --- a/contracts/deploy/00-home-chain-arbitration-university.ts +++ b/contracts/deploy/00-home-chain-arbitration-university.ts @@ -27,7 +27,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) const disputeKit = await deployUpgradable(deployments, "DisputeKitClassicUniversity", { from: deployer, contract: "DisputeKitClassic", - args: [deployer, ZeroAddress], + args: [deployer, ZeroAddress, weth.target], log: true, }); @@ -59,6 +59,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) [minStake, alpha, feeForJuror, jurorsForCourtJump], [0, 0, 0, 10], // evidencePeriod, commitPeriod, votePeriod, appealPeriod sortitionModule.address, + weth.target, ], log: true, }); // nonce+2 (implementation), nonce+3 (proxy) diff --git a/contracts/deploy/00-home-chain-arbitration.ts b/contracts/deploy/00-home-chain-arbitration.ts index f66e14cdf..c22a1b960 100644 --- a/contracts/deploy/00-home-chain-arbitration.ts +++ b/contracts/deploy/00-home-chain-arbitration.ts @@ -37,7 +37,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) const disputeKit = await deployUpgradable(deployments, "DisputeKitClassic", { from: deployer, - args: [deployer, ZeroAddress], + args: [deployer, ZeroAddress, weth.target], log: true, }); @@ -74,6 +74,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) [0, 0, 0, 10], // evidencePeriod, commitPeriod, votePeriod, appealPeriod ethers.toBeHex(5), // Extra data for sortition module will return the default value of K sortitionModule.address, + weth.target, ], log: true, }); // nonce+2 (implementation), nonce+3 (proxy) @@ -105,7 +106,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) // Extra dispute kits const disputeKitShutter = await deployUpgradable(deployments, "DisputeKitShutter", { from: deployer, - args: [deployer, core.target], + args: [deployer, core.target, weth.target], log: true, }); await core.addNewDisputeKit(disputeKitShutter.address); @@ -113,7 +114,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) const disputeKitGated = await deployUpgradable(deployments, "DisputeKitGated", { from: deployer, - args: [deployer, core.target], + args: [deployer, core.target, weth.target], log: true, }); await core.addNewDisputeKit(disputeKitGated.address); @@ -121,7 +122,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) const disputeKitGatedShutter = await deployUpgradable(deployments, "DisputeKitGatedShutter", { from: deployer, - args: [deployer, core.target], + args: [deployer, core.target, weth.target], log: true, }); await core.addNewDisputeKit(disputeKitGatedShutter.address); diff --git a/contracts/src/arbitration/KlerosCore.sol b/contracts/src/arbitration/KlerosCore.sol index b63093413..94c71aadd 100644 --- a/contracts/src/arbitration/KlerosCore.sol +++ b/contracts/src/arbitration/KlerosCore.sol @@ -30,6 +30,7 @@ contract KlerosCore is KlerosCoreBase { /// @param _timesPerPeriod The `timesPerPeriod` property value of the general court. /// @param _sortitionExtraData The extra data for sortition module. /// @param _sortitionModuleAddress The sortition module responsible for sortition of the jurors. + /// @param _wNative The address for WETH tranfers. function initialize( address _governor, address _guardian, @@ -40,7 +41,8 @@ contract KlerosCore is KlerosCoreBase { uint256[4] memory _courtParameters, uint256[4] memory _timesPerPeriod, bytes memory _sortitionExtraData, - ISortitionModule _sortitionModuleAddress + ISortitionModule _sortitionModuleAddress, + address _wNative ) external reinitializer(1) { __KlerosCoreBase_initialize( _governor, @@ -52,7 +54,8 @@ contract KlerosCore is KlerosCoreBase { _courtParameters, _timesPerPeriod, _sortitionExtraData, - _sortitionModuleAddress + _sortitionModuleAddress, + _wNative ); } diff --git a/contracts/src/arbitration/KlerosCoreBase.sol b/contracts/src/arbitration/KlerosCoreBase.sol index 7da1b429a..306a3ec16 100644 --- a/contracts/src/arbitration/KlerosCoreBase.sol +++ b/contracts/src/arbitration/KlerosCoreBase.sol @@ -8,6 +8,7 @@ import {ISortitionModule} from "./interfaces/ISortitionModule.sol"; import {Initializable} from "../proxy/Initializable.sol"; import {UUPSProxiable} from "../proxy/UUPSProxiable.sol"; import {SafeERC20, IERC20} from "../libraries/SafeERC20.sol"; +import {SafeSend} from "../libraries/SafeSend.sol"; import "../libraries/Constants.sol"; /// @title KlerosCoreBase @@ -15,6 +16,7 @@ import "../libraries/Constants.sol"; /// Note that this contract trusts the PNK token, the dispute kit and the sortition module contracts. abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable { using SafeERC20 for IERC20; + using SafeSend for address payable; // ************************************* // // * Enums / Structs * // @@ -99,6 +101,7 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable Dispute[] public disputes; // The disputes. mapping(IERC20 => CurrencyRate) public currencyRates; // The price of each token in ETH. bool public paused; // Whether asset withdrawals are paused. + address public wNative; // The address for WETH tranfers. // ************************************* // // * Events * // @@ -199,13 +202,15 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable uint256[4] memory _courtParameters, uint256[4] memory _timesPerPeriod, bytes memory _sortitionExtraData, - ISortitionModule _sortitionModuleAddress + ISortitionModule _sortitionModuleAddress, + address _wNative ) internal onlyInitializing { governor = _governor; guardian = _guardian; pinakion = _pinakion; jurorProsecutionModule = _jurorProsecutionModule; sortitionModule = _sortitionModuleAddress; + wNative = _wNative; // NULL_DISPUTE_KIT: an empty element at index 0 to indicate when a dispute kit is not supported. disputeKits.push(); @@ -802,7 +807,7 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable // No one was coherent, send the rewards to the governor. if (round.feeToken == NATIVE_CURRENCY) { // The dispute fees were paid in ETH - payable(governor).send(round.totalFeesForJurors); + payable(governor).safeSend(round.totalFeesForJurors, wNative); } else { // The dispute fees were paid in ERC20 round.feeToken.safeTransfer(governor, round.totalFeesForJurors); @@ -854,7 +859,7 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable pinakion.safeTransfer(account, pnkReward); if (round.feeToken == NATIVE_CURRENCY) { // The dispute fees were paid in ETH - payable(account).send(feeReward); + payable(account).safeSend(feeReward, wNative); } else { // The dispute fees were paid in ERC20 round.feeToken.safeTransfer(account, feeReward); @@ -880,7 +885,7 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable if (leftoverFeeReward != 0) { if (round.feeToken == NATIVE_CURRENCY) { // The dispute fees were paid in ETH - payable(governor).send(leftoverFeeReward); + payable(governor).safeSend(leftoverFeeReward, wNative); } else { // The dispute fees were paid in ERC20 round.feeToken.safeTransfer(governor, leftoverFeeReward); diff --git a/contracts/src/arbitration/KlerosCoreNeo.sol b/contracts/src/arbitration/KlerosCoreNeo.sol index 4355bcdd1..1ca6334c4 100644 --- a/contracts/src/arbitration/KlerosCoreNeo.sol +++ b/contracts/src/arbitration/KlerosCoreNeo.sol @@ -39,6 +39,7 @@ contract KlerosCoreNeo is KlerosCoreBase { /// @param _sortitionExtraData The extra data for sortition module. /// @param _sortitionModuleAddress The sortition module responsible for sortition of the jurors. /// @param _jurorNft NFT contract to vet the jurors. + /// @param _wNative The address for WETH tranfers. function initialize( address _governor, address _guardian, @@ -50,7 +51,8 @@ contract KlerosCoreNeo is KlerosCoreBase { uint256[4] memory _timesPerPeriod, bytes memory _sortitionExtraData, ISortitionModule _sortitionModuleAddress, - IERC721 _jurorNft + IERC721 _jurorNft, + address _wNative ) external reinitializer(2) { __KlerosCoreBase_initialize( _governor, @@ -62,7 +64,8 @@ contract KlerosCoreNeo is KlerosCoreBase { _courtParameters, _timesPerPeriod, _sortitionExtraData, - _sortitionModuleAddress + _sortitionModuleAddress, + _wNative ); jurorNft = _jurorNft; } diff --git a/contracts/src/arbitration/KlerosGovernor.sol b/contracts/src/arbitration/KlerosGovernor.sol index 9d0d8a712..36791bf1d 100644 --- a/contracts/src/arbitration/KlerosGovernor.sol +++ b/contracts/src/arbitration/KlerosGovernor.sol @@ -3,10 +3,12 @@ pragma solidity ^0.8.24; import {IArbitrableV2, IArbitratorV2} from "./interfaces/IArbitrableV2.sol"; +import {SafeSend} from "../libraries/SafeSend.sol"; import "./interfaces/IDisputeTemplateRegistry.sol"; /// @title KlerosGovernor for V2. Note that appeal functionality and evidence submission will be handled by the court. contract KlerosGovernor is IArbitrableV2 { + using SafeSend for address payable; // ************************************* // // * Enums / Structs * // // ************************************* // @@ -60,6 +62,8 @@ contract KlerosGovernor is IArbitrableV2 { Submission[] public submissions; // Stores all created transaction lists. submissions[_listID]. Session[] public sessions; // Stores all submitting sessions. sessions[_session]. + address public wNative; // The address for WETH tranfers. + // ************************************* // // * Function Modifiers * // // ************************************* // @@ -111,6 +115,7 @@ contract KlerosGovernor is IArbitrableV2 { /// @param _submissionTimeout Time in seconds allocated for submitting transaction list. /// @param _executionTimeout Time in seconds after approval that allows to execute transactions of the approved list. /// @param _withdrawTimeout Time in seconds after submission that allows to withdraw submitted list. + /// @param _wNative The address of the WETH used by SafeSend for fallback transfers. constructor( IArbitratorV2 _arbitrator, bytes memory _arbitratorExtraData, @@ -119,10 +124,12 @@ contract KlerosGovernor is IArbitrableV2 { uint256 _submissionBaseDeposit, uint256 _submissionTimeout, uint256 _executionTimeout, - uint256 _withdrawTimeout + uint256 _withdrawTimeout, + address _wNative ) { arbitrator = _arbitrator; arbitratorExtraData = _arbitratorExtraData; + wNative = _wNative; lastApprovalTime = block.timestamp; submissionBaseDeposit = _submissionBaseDeposit; @@ -237,7 +244,7 @@ contract KlerosGovernor is IArbitrableV2 { emit ListSubmitted(submissions.length - 1, msg.sender, sessions.length - 1, _description); uint256 remainder = msg.value - submission.deposit; - if (remainder > 0) payable(msg.sender).send(remainder); + if (remainder > 0) payable(msg.sender).safeSend(remainder, wNative); reservedETH += submission.deposit; } @@ -277,7 +284,7 @@ contract KlerosGovernor is IArbitrableV2 { submission.approvalTime = block.timestamp; uint256 sumDeposit = session.sumDeposit; session.sumDeposit = 0; - submission.submitter.send(sumDeposit); + submission.submitter.safeSend(sumDeposit, wNative); lastApprovalTime = block.timestamp; session.status = Status.Resolved; sessions.push(); @@ -311,7 +318,7 @@ contract KlerosGovernor is IArbitrableV2 { Submission storage submission = submissions[session.submittedLists[_ruling - 1]]; submission.approved = true; submission.approvalTime = block.timestamp; - submission.submitter.send(session.sumDeposit); + submission.submitter.safeSend(session.sumDeposit, wNative); } // If the ruling is "0" the reserved funds of this session become expendable. reservedETH -= session.sumDeposit; diff --git a/contracts/src/arbitration/devtools/KlerosCoreRuler.sol b/contracts/src/arbitration/devtools/KlerosCoreRuler.sol index 2382970cf..61aa8d3de 100644 --- a/contracts/src/arbitration/devtools/KlerosCoreRuler.sol +++ b/contracts/src/arbitration/devtools/KlerosCoreRuler.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.24; import {IArbitrableV2, IArbitratorV2} from "../interfaces/IArbitratorV2.sol"; import {SafeERC20, IERC20} from "../../libraries/SafeERC20.sol"; +import {SafeSend} from "../../libraries/SafeSend.sol"; import {UUPSProxiable} from "../../proxy/UUPSProxiable.sol"; import {Initializable} from "../../proxy/Initializable.sol"; import "../../libraries/Constants.sol"; @@ -12,6 +13,7 @@ import "../../libraries/Constants.sol"; /// Core arbitrator contract for development and testing purposes. contract KlerosCoreRuler is IArbitratorV2, UUPSProxiable, Initializable { using SafeERC20 for IERC20; + using SafeSend for address payable; string public constant override version = "0.8.0"; @@ -93,6 +95,7 @@ contract KlerosCoreRuler is IArbitratorV2, UUPSProxiable, Initializable { mapping(IArbitrableV2 arbitrable => address ruler) public rulers; // The ruler of each arbitrable contract. mapping(IArbitrableV2 arbitrable => RulerSettings) public settings; // The settings of each arbitrable contract. mapping(uint256 disputeID => RulingResult) public rulingResults; // The ruling results of each dispute. + address public wNative; // The address for WETH tranfers. // ************************************* // // * Events * // @@ -175,13 +178,16 @@ contract KlerosCoreRuler is IArbitratorV2, UUPSProxiable, Initializable { /// @param _governor The governor's address. /// @param _pinakion The address of the token contract. /// @param _courtParameters Numeric parameters of General court (minStake, alpha, feeForJuror and jurorsForCourtJump respectively). + /// @param _wNative The address of the WETH used by SafeSend for fallback transfers. function initialize( address _governor, IERC20 _pinakion, - uint256[4] memory _courtParameters + uint256[4] memory _courtParameters, + address _wNative ) external reinitializer(1) { governor = _governor; pinakion = _pinakion; + wNative = _wNative; // FORKING_COURT // TODO: Fill the properties for the Forking court, emit CourtCreated. @@ -525,7 +531,7 @@ contract KlerosCoreRuler is IArbitratorV2, UUPSProxiable, Initializable { round.sumFeeRewardPaid += feeReward; if (round.feeToken == NATIVE_CURRENCY) { // The dispute fees were paid in ETH - payable(account).send(feeReward); + payable(account).safeSend(feeReward, wNative); } else { // The dispute fees were paid in ERC20 round.feeToken.safeTransfer(account, feeReward); diff --git a/contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol b/contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol index 5132b34ea..4935d730f 100644 --- a/contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol +++ b/contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol @@ -25,8 +25,9 @@ contract DisputeKitClassic is DisputeKitClassicBase { /// @dev Initializer. /// @param _governor The governor's address. /// @param _core The KlerosCore arbitrator. - function initialize(address _governor, KlerosCore _core) external reinitializer(1) { - __DisputeKitClassicBase_initialize(_governor, _core); + /// @param _wNative The address for WETH tranfers. + function initialize(address _governor, KlerosCore _core, address _wNative) external reinitializer(1) { + __DisputeKitClassicBase_initialize(_governor, _core, _wNative); } function initialize7() external reinitializer(7) { diff --git a/contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol b/contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol index 5c2485a8c..e53981f39 100644 --- a/contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol +++ b/contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol @@ -5,6 +5,7 @@ pragma solidity ^0.8.24; import {KlerosCore, KlerosCoreBase, IDisputeKit, ISortitionModule} from "../KlerosCore.sol"; import {Initializable} from "../../proxy/Initializable.sol"; import {UUPSProxiable} from "../../proxy/UUPSProxiable.sol"; +import {SafeSend} from "../../libraries/SafeSend.sol"; /// @title DisputeKitClassicBase /// Abstract Dispute kit classic implementation of the Kleros v1 features including: @@ -13,6 +14,7 @@ import {UUPSProxiable} from "../../proxy/UUPSProxiable.sol"; /// - an incentive system: equal split between coherent votes, /// - an appeal system: fund 2 choices only, vote on any choice. abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxiable { + using SafeSend for address payable; // ************************************* // // * Structs * // // ************************************* // @@ -64,6 +66,7 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi mapping(uint256 localDisputeID => mapping(uint256 localRoundID => mapping(address drawnAddress => bool))) public alreadyDrawn; // True if the address has already been drawn, false by default. To be added to the Round struct when fully redeploying rather than upgrading. mapping(uint256 coreDisputeID => bool) public coreDisputeIDToActive; // True if this dispute kit is active for this core dispute ID. + address public wNative; // The address for WETH tranfers. // ************************************* // // * Events * // @@ -142,9 +145,15 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi /// @dev Initializer. /// @param _governor The governor's address. /// @param _core The KlerosCore arbitrator. - function __DisputeKitClassicBase_initialize(address _governor, KlerosCore _core) internal onlyInitializing { + /// @param _wNative The address for WETH tranfers. + function __DisputeKitClassicBase_initialize( + address _governor, + KlerosCore _core, + address _wNative + ) internal onlyInitializing { governor = _governor; core = _core; + wNative = _wNative; } // ************************ // @@ -409,7 +418,7 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi core.appeal{value: appealCost}(_coreDisputeID, dispute.numberOfChoices, dispute.extraData); } - if (msg.value > contribution) payable(msg.sender).send(msg.value - contribution); + if (msg.value > contribution) payable(msg.sender).safeSend(msg.value - contribution, wNative); } /// @dev Allows those contributors who attempted to fund an appeal round to withdraw any reimbursable fees or rewards after the dispute gets resolved. @@ -454,7 +463,7 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi round.contributions[_beneficiary][_choice] = 0; if (amount != 0) { - _beneficiary.send(amount); // Deliberate use of send to prevent reverting fallback. It's the user's responsibility to accept ETH. + _beneficiary.safeSend(amount, wNative); // Deliberate use of send to prevent reverting fallback. It's the user's responsibility to accept ETH. emit Withdrawal(_coreDisputeID, _coreRoundID, _choice, _beneficiary, amount); } } diff --git a/contracts/src/arbitration/dispute-kits/DisputeKitGated.sol b/contracts/src/arbitration/dispute-kits/DisputeKitGated.sol index 007a039b9..d69eaa807 100644 --- a/contracts/src/arbitration/dispute-kits/DisputeKitGated.sol +++ b/contracts/src/arbitration/dispute-kits/DisputeKitGated.sol @@ -41,8 +41,9 @@ contract DisputeKitGated is DisputeKitClassicBase { /// @dev Initializer. /// @param _governor The governor's address. /// @param _core The KlerosCore arbitrator. - function initialize(address _governor, KlerosCore _core) external reinitializer(1) { - __DisputeKitClassicBase_initialize(_governor, _core); + /// @param _wNative The address for WETH tranfers. + function initialize(address _governor, KlerosCore _core, address _wNative) external reinitializer(1) { + __DisputeKitClassicBase_initialize(_governor, _core, _wNative); } function initialize7() external reinitializer(7) { diff --git a/contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol b/contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol index 2d1ea355d..ebd77c2e7 100644 --- a/contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol +++ b/contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol @@ -60,8 +60,9 @@ contract DisputeKitGatedShutter is DisputeKitClassicBase { /// @dev Initializer. /// @param _governor The governor's address. /// @param _core The KlerosCore arbitrator. - function initialize(address _governor, KlerosCore _core) external reinitializer(1) { - __DisputeKitClassicBase_initialize(_governor, _core); + /// @param _wNative The address for WETH tranfers. + function initialize(address _governor, KlerosCore _core, address _wNative) external reinitializer(1) { + __DisputeKitClassicBase_initialize(_governor, _core, _wNative); } function initialize7() external reinitializer(7) { diff --git a/contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol b/contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol index 1c332aac7..86dba9b02 100644 --- a/contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol +++ b/contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol @@ -44,8 +44,9 @@ contract DisputeKitShutter is DisputeKitClassicBase { /// @dev Initializer. /// @param _governor The governor's address. /// @param _core The KlerosCore arbitrator. - function initialize(address _governor, KlerosCore _core) external reinitializer(1) { - __DisputeKitClassicBase_initialize(_governor, _core); + /// @param _wNative The address for WETH tranfers. + function initialize(address _governor, KlerosCore _core, address _wNative) external reinitializer(1) { + __DisputeKitClassicBase_initialize(_governor, _core, _wNative); } function initialize8() external reinitializer(8) { diff --git a/contracts/src/arbitration/dispute-kits/DisputeKitSybilResistant.sol b/contracts/src/arbitration/dispute-kits/DisputeKitSybilResistant.sol index 7bde0feb6..d95407c7b 100644 --- a/contracts/src/arbitration/dispute-kits/DisputeKitSybilResistant.sol +++ b/contracts/src/arbitration/dispute-kits/DisputeKitSybilResistant.sol @@ -39,8 +39,14 @@ contract DisputeKitSybilResistant is DisputeKitClassicBase { /// @param _governor The governor's address. /// @param _core The KlerosCore arbitrator. /// @param _poh The Proof of Humanity registry. - function initialize(address _governor, KlerosCore _core, IProofOfHumanity _poh) external reinitializer(1) { - __DisputeKitClassicBase_initialize(_governor, _core); + /// @param _wNative The address for WETH tranfers. + function initialize( + address _governor, + KlerosCore _core, + IProofOfHumanity _poh, + address _wNative + ) external reinitializer(1) { + __DisputeKitClassicBase_initialize(_governor, _core, _wNative); poh = _poh; singleDrawPerJuror = true; } diff --git a/contracts/src/arbitration/university/KlerosCoreUniversity.sol b/contracts/src/arbitration/university/KlerosCoreUniversity.sol index 35fd5262c..d0252df59 100644 --- a/contracts/src/arbitration/university/KlerosCoreUniversity.sol +++ b/contracts/src/arbitration/university/KlerosCoreUniversity.sol @@ -6,6 +6,7 @@ import {IArbitrableV2, IArbitratorV2} from "../interfaces/IArbitratorV2.sol"; import {IDisputeKit} from "../interfaces/IDisputeKit.sol"; import {ISortitionModuleUniversity} from "./ISortitionModuleUniversity.sol"; import {SafeERC20, IERC20} from "../../libraries/SafeERC20.sol"; +import {SafeSend} from "../../libraries/SafeSend.sol"; import "../../libraries/Constants.sol"; import {UUPSProxiable} from "../../proxy/UUPSProxiable.sol"; import {Initializable} from "../../proxy/Initializable.sol"; @@ -14,6 +15,7 @@ import {Initializable} from "../../proxy/Initializable.sol"; /// Core arbitrator contract for educational purposes. contract KlerosCoreUniversity is IArbitratorV2, UUPSProxiable, Initializable { using SafeERC20 for IERC20; + using SafeSend for address payable; string public constant override version = "0.8.0"; @@ -99,6 +101,7 @@ contract KlerosCoreUniversity is IArbitratorV2, UUPSProxiable, Initializable { IDisputeKit[] public disputeKits; // Array of dispute kits. Dispute[] public disputes; // The disputes. mapping(IERC20 => CurrencyRate) public currencyRates; // The price of each token in ETH. + address public wNative; // The address for WETH tranfers. // ************************************* // // * Events * // @@ -197,6 +200,7 @@ contract KlerosCoreUniversity is IArbitratorV2, UUPSProxiable, Initializable { /// @param _courtParameters Numeric parameters of General court (minStake, alpha, feeForJuror and jurorsForCourtJump respectively). /// @param _timesPerPeriod The `timesPerPeriod` property value of the general court. /// @param _sortitionModuleAddress The sortition module responsible for sortition of the jurors. + /// @param _wNative The address of the WETH used by SafeSend for fallback transfers. function initialize( address _governor, address _instructor, @@ -206,13 +210,15 @@ contract KlerosCoreUniversity is IArbitratorV2, UUPSProxiable, Initializable { bool _hiddenVotes, uint256[4] memory _courtParameters, uint256[4] memory _timesPerPeriod, - ISortitionModuleUniversity _sortitionModuleAddress + ISortitionModuleUniversity _sortitionModuleAddress, + address _wNative ) external reinitializer(1) { governor = _governor; instructor = _instructor; pinakion = _pinakion; jurorProsecutionModule = _jurorProsecutionModule; sortitionModule = _sortitionModuleAddress; + wNative = _wNative; // NULL_DISPUTE_KIT: an empty element at index 0 to indicate when a dispute kit is not supported. disputeKits.push(); @@ -793,7 +799,7 @@ contract KlerosCoreUniversity is IArbitratorV2, UUPSProxiable, Initializable { // No one was coherent, send the rewards to the governor. if (round.feeToken == NATIVE_CURRENCY) { // The dispute fees were paid in ETH - payable(governor).send(round.totalFeesForJurors); + payable(governor).safeSend(round.totalFeesForJurors, wNative); } else { // The dispute fees were paid in ERC20 round.feeToken.safeTransfer(governor, round.totalFeesForJurors); @@ -845,7 +851,7 @@ contract KlerosCoreUniversity is IArbitratorV2, UUPSProxiable, Initializable { pinakion.safeTransfer(account, pnkReward); if (round.feeToken == NATIVE_CURRENCY) { // The dispute fees were paid in ETH - payable(account).send(feeReward); + payable(account).safeSend(feeReward, wNative); } else { // The dispute fees were paid in ERC20 round.feeToken.safeTransfer(account, feeReward); @@ -871,7 +877,7 @@ contract KlerosCoreUniversity is IArbitratorV2, UUPSProxiable, Initializable { if (leftoverFeeReward != 0) { if (round.feeToken == NATIVE_CURRENCY) { // The dispute fees were paid in ETH - payable(governor).send(leftoverFeeReward); + payable(governor).safeSend(leftoverFeeReward, wNative); } else { // The dispute fees were paid in ERC20 round.feeToken.safeTransfer(governor, leftoverFeeReward); diff --git a/contracts/src/libraries/SafeSend.sol b/contracts/src/libraries/SafeSend.sol new file mode 100644 index 000000000..2476d23e7 --- /dev/null +++ b/contracts/src/libraries/SafeSend.sol @@ -0,0 +1,24 @@ +/** + * @authors: [@andreimvp] + * @reviewers: [@divyangchauhan, @wadader, @fcanela, @unknownunknown1] + * @auditors: [] + * @bounties: [] + * SPDX-License-Identifier: MIT + */ + +pragma solidity 0.8.24; + +interface WethLike { + function deposit() external payable; + + function transfer(address dst, uint256 wad) external; +} + +library SafeSend { + function safeSend(address payable _to, uint256 _value, address _wethLike) internal { + if (_to.send(_value)) return; + + WethLike(_wethLike).deposit{value: _value}(); + WethLike(_wethLike).transfer(_to, _value); + } +} From 1644927adc1816f5f86debfc633bbae56cc332a6 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Fri, 1 Aug 2025 11:45:50 +0100 Subject: [PATCH 2/3] test: fixed missing constructor param wNative --- contracts/test/foundry/KlerosCore.t.sol | 36 ++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/contracts/test/foundry/KlerosCore.t.sol b/contracts/test/foundry/KlerosCore.t.sol index e1f452da4..c214b42f8 100644 --- a/contracts/test/foundry/KlerosCore.t.sol +++ b/contracts/test/foundry/KlerosCore.t.sol @@ -28,6 +28,7 @@ contract KlerosCoreTest is Test { BlockHashRNG rng; PNK pinakion; TestERC20 feeToken; + TestERC20 wNative; ArbitrableExample arbitrable; DisputeTemplateRegistry registry; address governor; @@ -65,6 +66,7 @@ contract KlerosCoreTest is Test { rng = new BlockHashRNG(); pinakion = new PNK(); feeToken = new TestERC20("Test", "TST"); + wNative = new TestERC20("wrapped ETH", "wETH"); governor = msg.sender; guardian = vm.addr(1); @@ -96,7 +98,12 @@ contract KlerosCoreTest is Test { UUPSProxy proxyCore = new UUPSProxy(address(coreLogic), ""); - bytes memory initDataDk = abi.encodeWithSignature("initialize(address,address)", governor, address(proxyCore)); + bytes memory initDataDk = abi.encodeWithSignature( + "initialize(address,address,address)", + governor, + address(proxyCore), + address(wNative) + ); UUPSProxy proxyDk = new UUPSProxy(address(dkLogic), initDataDk); disputeKit = DisputeKitClassic(address(proxyDk)); @@ -125,7 +132,8 @@ contract KlerosCoreTest is Test { [minStake, alpha, feeForJuror, jurorsForCourtJump], timesPerPeriod, sortitionExtraData, - sortitionModule + sortitionModule, + address(wNative) ); vm.prank(staker1); pinakion.approve(address(core), 1 ether); @@ -277,7 +285,12 @@ contract KlerosCoreTest is Test { UUPSProxy proxyCore = new UUPSProxy(address(coreLogic), ""); - bytes memory initDataDk = abi.encodeWithSignature("initialize(address,address)", governor, address(proxyCore)); + bytes memory initDataDk = abi.encodeWithSignature( + "initialize(address,address,address)", + governor, + address(proxyCore), + address(wNative) + ); UUPSProxy proxyDk = new UUPSProxy(address(dkLogic), initDataDk); disputeKit = DisputeKitClassic(address(proxyDk)); @@ -325,7 +338,8 @@ contract KlerosCoreTest is Test { [minStake, alpha, feeForJuror, jurorsForCourtJump], timesPerPeriod, sortitionExtraData, - sortitionModule + sortitionModule, + address(wNative) ); } @@ -2075,7 +2089,12 @@ contract KlerosCoreTest is Test { uint256 disputeID = 0; DisputeKitClassic dkLogic = new DisputeKitClassic(); // Create a new DK and court to check the switch - bytes memory initDataDk = abi.encodeWithSignature("initialize(address,address)", governor, address(core)); + bytes memory initDataDk = abi.encodeWithSignature( + "initialize(address,address,address)", + governor, + address(core), + address(wNative) + ); UUPSProxy proxyDk = new UUPSProxy(address(dkLogic), initDataDk); DisputeKitClassic newDisputeKit = DisputeKitClassic(address(proxyDk)); @@ -2856,7 +2875,12 @@ contract KlerosCoreTest is Test { function test_castVote_differentDK() public { DisputeKitClassic dkLogic = new DisputeKitClassic(); // Create a new DK to check castVote. - bytes memory initDataDk = abi.encodeWithSignature("initialize(address,address)", governor, address(core)); + bytes memory initDataDk = abi.encodeWithSignature( + "initialize(address,address,address)", + governor, + address(core), + address(wNative) + ); UUPSProxy proxyDk = new UUPSProxy(address(dkLogic), initDataDk); DisputeKitClassic newDisputeKit = DisputeKitClassic(address(proxyDk)); From c5a894a99d41e9991cee77134137ab2339bb7754 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Fri, 1 Aug 2025 12:27:39 +0100 Subject: [PATCH 3/3] fix: removed SafeSend from ruler and university, natspec tweaks, SafeSend solidity version --- .../deploy/00-home-chain-arbitration-ruler.ts | 1 - .../deploy/00-home-chain-arbitration-university.ts | 1 - contracts/src/arbitration/KlerosCore.sol | 2 +- contracts/src/arbitration/KlerosCoreBase.sol | 2 +- contracts/src/arbitration/KlerosCoreNeo.sol | 2 +- contracts/src/arbitration/KlerosGovernor.sol | 6 +++--- .../src/arbitration/devtools/KlerosCoreRuler.sol | 10 ++-------- .../arbitration/dispute-kits/DisputeKitClassic.sol | 2 +- .../dispute-kits/DisputeKitClassicBase.sol | 7 ++++--- .../arbitration/dispute-kits/DisputeKitGated.sol | 2 +- .../dispute-kits/DisputeKitGatedShutter.sol | 2 +- .../arbitration/dispute-kits/DisputeKitShutter.sol | 2 +- .../dispute-kits/DisputeKitSybilResistant.sol | 2 +- .../university/KlerosCoreUniversity.sol | 14 ++++---------- contracts/src/libraries/SafeSend.sol | 2 +- 15 files changed, 22 insertions(+), 35 deletions(-) diff --git a/contracts/deploy/00-home-chain-arbitration-ruler.ts b/contracts/deploy/00-home-chain-arbitration-ruler.ts index 585bb552e..d49431c46 100644 --- a/contracts/deploy/00-home-chain-arbitration-ruler.ts +++ b/contracts/deploy/00-home-chain-arbitration-ruler.ts @@ -32,7 +32,6 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) deployer, // governor pnk.target, [minStake, alpha, feeForJuror, jurorsForCourtJump], - weth.target, ], log: true, }); diff --git a/contracts/deploy/00-home-chain-arbitration-university.ts b/contracts/deploy/00-home-chain-arbitration-university.ts index 37c7f7531..81267ca91 100644 --- a/contracts/deploy/00-home-chain-arbitration-university.ts +++ b/contracts/deploy/00-home-chain-arbitration-university.ts @@ -59,7 +59,6 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) [minStake, alpha, feeForJuror, jurorsForCourtJump], [0, 0, 0, 10], // evidencePeriod, commitPeriod, votePeriod, appealPeriod sortitionModule.address, - weth.target, ], log: true, }); // nonce+2 (implementation), nonce+3 (proxy) diff --git a/contracts/src/arbitration/KlerosCore.sol b/contracts/src/arbitration/KlerosCore.sol index 94c71aadd..15f0f47d8 100644 --- a/contracts/src/arbitration/KlerosCore.sol +++ b/contracts/src/arbitration/KlerosCore.sol @@ -30,7 +30,7 @@ contract KlerosCore is KlerosCoreBase { /// @param _timesPerPeriod The `timesPerPeriod` property value of the general court. /// @param _sortitionExtraData The extra data for sortition module. /// @param _sortitionModuleAddress The sortition module responsible for sortition of the jurors. - /// @param _wNative The address for WETH tranfers. + /// @param _wNative The wrapped native token address, typically wETH. function initialize( address _governor, address _guardian, diff --git a/contracts/src/arbitration/KlerosCoreBase.sol b/contracts/src/arbitration/KlerosCoreBase.sol index 306a3ec16..562f7eba1 100644 --- a/contracts/src/arbitration/KlerosCoreBase.sol +++ b/contracts/src/arbitration/KlerosCoreBase.sol @@ -101,7 +101,7 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable Dispute[] public disputes; // The disputes. mapping(IERC20 => CurrencyRate) public currencyRates; // The price of each token in ETH. bool public paused; // Whether asset withdrawals are paused. - address public wNative; // The address for WETH tranfers. + address public wNative; // The wrapped native token for safeSend(). // ************************************* // // * Events * // diff --git a/contracts/src/arbitration/KlerosCoreNeo.sol b/contracts/src/arbitration/KlerosCoreNeo.sol index 1ca6334c4..4f748a765 100644 --- a/contracts/src/arbitration/KlerosCoreNeo.sol +++ b/contracts/src/arbitration/KlerosCoreNeo.sol @@ -39,7 +39,7 @@ contract KlerosCoreNeo is KlerosCoreBase { /// @param _sortitionExtraData The extra data for sortition module. /// @param _sortitionModuleAddress The sortition module responsible for sortition of the jurors. /// @param _jurorNft NFT contract to vet the jurors. - /// @param _wNative The address for WETH tranfers. + /// @param _wNative The wrapped native token address, typically wETH. function initialize( address _governor, address _guardian, diff --git a/contracts/src/arbitration/KlerosGovernor.sol b/contracts/src/arbitration/KlerosGovernor.sol index 36791bf1d..7e9415a7b 100644 --- a/contracts/src/arbitration/KlerosGovernor.sol +++ b/contracts/src/arbitration/KlerosGovernor.sol @@ -9,6 +9,7 @@ import "./interfaces/IDisputeTemplateRegistry.sol"; /// @title KlerosGovernor for V2. Note that appeal functionality and evidence submission will be handled by the court. contract KlerosGovernor is IArbitrableV2 { using SafeSend for address payable; + // ************************************* // // * Enums / Structs * // // ************************************* // @@ -48,6 +49,7 @@ contract KlerosGovernor is IArbitrableV2 { IArbitratorV2 public arbitrator; // Arbitrator contract. bytes public arbitratorExtraData; // Extra data for arbitrator. + address public wNative; // The wrapped native token for safeSend(). IDisputeTemplateRegistry public templateRegistry; // The dispute template registry. uint256 public templateId; // The current dispute template identifier. @@ -62,8 +64,6 @@ contract KlerosGovernor is IArbitrableV2 { Submission[] public submissions; // Stores all created transaction lists. submissions[_listID]. Session[] public sessions; // Stores all submitting sessions. sessions[_session]. - address public wNative; // The address for WETH tranfers. - // ************************************* // // * Function Modifiers * // // ************************************* // @@ -115,7 +115,7 @@ contract KlerosGovernor is IArbitrableV2 { /// @param _submissionTimeout Time in seconds allocated for submitting transaction list. /// @param _executionTimeout Time in seconds after approval that allows to execute transactions of the approved list. /// @param _withdrawTimeout Time in seconds after submission that allows to withdraw submitted list. - /// @param _wNative The address of the WETH used by SafeSend for fallback transfers. + /// @param _wNative The wrapped native token address, typically wETH. constructor( IArbitratorV2 _arbitrator, bytes memory _arbitratorExtraData, diff --git a/contracts/src/arbitration/devtools/KlerosCoreRuler.sol b/contracts/src/arbitration/devtools/KlerosCoreRuler.sol index 61aa8d3de..2382970cf 100644 --- a/contracts/src/arbitration/devtools/KlerosCoreRuler.sol +++ b/contracts/src/arbitration/devtools/KlerosCoreRuler.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.24; import {IArbitrableV2, IArbitratorV2} from "../interfaces/IArbitratorV2.sol"; import {SafeERC20, IERC20} from "../../libraries/SafeERC20.sol"; -import {SafeSend} from "../../libraries/SafeSend.sol"; import {UUPSProxiable} from "../../proxy/UUPSProxiable.sol"; import {Initializable} from "../../proxy/Initializable.sol"; import "../../libraries/Constants.sol"; @@ -13,7 +12,6 @@ import "../../libraries/Constants.sol"; /// Core arbitrator contract for development and testing purposes. contract KlerosCoreRuler is IArbitratorV2, UUPSProxiable, Initializable { using SafeERC20 for IERC20; - using SafeSend for address payable; string public constant override version = "0.8.0"; @@ -95,7 +93,6 @@ contract KlerosCoreRuler is IArbitratorV2, UUPSProxiable, Initializable { mapping(IArbitrableV2 arbitrable => address ruler) public rulers; // The ruler of each arbitrable contract. mapping(IArbitrableV2 arbitrable => RulerSettings) public settings; // The settings of each arbitrable contract. mapping(uint256 disputeID => RulingResult) public rulingResults; // The ruling results of each dispute. - address public wNative; // The address for WETH tranfers. // ************************************* // // * Events * // @@ -178,16 +175,13 @@ contract KlerosCoreRuler is IArbitratorV2, UUPSProxiable, Initializable { /// @param _governor The governor's address. /// @param _pinakion The address of the token contract. /// @param _courtParameters Numeric parameters of General court (minStake, alpha, feeForJuror and jurorsForCourtJump respectively). - /// @param _wNative The address of the WETH used by SafeSend for fallback transfers. function initialize( address _governor, IERC20 _pinakion, - uint256[4] memory _courtParameters, - address _wNative + uint256[4] memory _courtParameters ) external reinitializer(1) { governor = _governor; pinakion = _pinakion; - wNative = _wNative; // FORKING_COURT // TODO: Fill the properties for the Forking court, emit CourtCreated. @@ -531,7 +525,7 @@ contract KlerosCoreRuler is IArbitratorV2, UUPSProxiable, Initializable { round.sumFeeRewardPaid += feeReward; if (round.feeToken == NATIVE_CURRENCY) { // The dispute fees were paid in ETH - payable(account).safeSend(feeReward, wNative); + payable(account).send(feeReward); } else { // The dispute fees were paid in ERC20 round.feeToken.safeTransfer(account, feeReward); diff --git a/contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol b/contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol index 4935d730f..041c274c7 100644 --- a/contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol +++ b/contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol @@ -25,7 +25,7 @@ contract DisputeKitClassic is DisputeKitClassicBase { /// @dev Initializer. /// @param _governor The governor's address. /// @param _core The KlerosCore arbitrator. - /// @param _wNative The address for WETH tranfers. + /// @param _wNative The wrapped native token address, typically wETH. function initialize(address _governor, KlerosCore _core, address _wNative) external reinitializer(1) { __DisputeKitClassicBase_initialize(_governor, _core, _wNative); } diff --git a/contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol b/contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol index e53981f39..b8bd3ba51 100644 --- a/contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol +++ b/contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol @@ -15,6 +15,7 @@ import {SafeSend} from "../../libraries/SafeSend.sol"; /// - an appeal system: fund 2 choices only, vote on any choice. abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxiable { using SafeSend for address payable; + // ************************************* // // * Structs * // // ************************************* // @@ -66,7 +67,7 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi mapping(uint256 localDisputeID => mapping(uint256 localRoundID => mapping(address drawnAddress => bool))) public alreadyDrawn; // True if the address has already been drawn, false by default. To be added to the Round struct when fully redeploying rather than upgrading. mapping(uint256 coreDisputeID => bool) public coreDisputeIDToActive; // True if this dispute kit is active for this core dispute ID. - address public wNative; // The address for WETH tranfers. + address public wNative; // The wrapped native token for safeSend(). // ************************************* // // * Events * // @@ -145,7 +146,7 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi /// @dev Initializer. /// @param _governor The governor's address. /// @param _core The KlerosCore arbitrator. - /// @param _wNative The address for WETH tranfers. + /// @param _wNative The wrapped native token address, typically wETH. function __DisputeKitClassicBase_initialize( address _governor, KlerosCore _core, @@ -463,7 +464,7 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi round.contributions[_beneficiary][_choice] = 0; if (amount != 0) { - _beneficiary.safeSend(amount, wNative); // Deliberate use of send to prevent reverting fallback. It's the user's responsibility to accept ETH. + _beneficiary.safeSend(amount, wNative); emit Withdrawal(_coreDisputeID, _coreRoundID, _choice, _beneficiary, amount); } } diff --git a/contracts/src/arbitration/dispute-kits/DisputeKitGated.sol b/contracts/src/arbitration/dispute-kits/DisputeKitGated.sol index d69eaa807..82e377497 100644 --- a/contracts/src/arbitration/dispute-kits/DisputeKitGated.sol +++ b/contracts/src/arbitration/dispute-kits/DisputeKitGated.sol @@ -41,7 +41,7 @@ contract DisputeKitGated is DisputeKitClassicBase { /// @dev Initializer. /// @param _governor The governor's address. /// @param _core The KlerosCore arbitrator. - /// @param _wNative The address for WETH tranfers. + /// @param _wNative The wrapped native token address, typically wETH. function initialize(address _governor, KlerosCore _core, address _wNative) external reinitializer(1) { __DisputeKitClassicBase_initialize(_governor, _core, _wNative); } diff --git a/contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol b/contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol index ebd77c2e7..e67be35bf 100644 --- a/contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol +++ b/contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol @@ -60,7 +60,7 @@ contract DisputeKitGatedShutter is DisputeKitClassicBase { /// @dev Initializer. /// @param _governor The governor's address. /// @param _core The KlerosCore arbitrator. - /// @param _wNative The address for WETH tranfers. + /// @param _wNative The wrapped native token address, typically wETH. function initialize(address _governor, KlerosCore _core, address _wNative) external reinitializer(1) { __DisputeKitClassicBase_initialize(_governor, _core, _wNative); } diff --git a/contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol b/contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol index 86dba9b02..768b149be 100644 --- a/contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol +++ b/contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol @@ -44,7 +44,7 @@ contract DisputeKitShutter is DisputeKitClassicBase { /// @dev Initializer. /// @param _governor The governor's address. /// @param _core The KlerosCore arbitrator. - /// @param _wNative The address for WETH tranfers. + /// @param _wNative The wrapped native token address, typically wETH. function initialize(address _governor, KlerosCore _core, address _wNative) external reinitializer(1) { __DisputeKitClassicBase_initialize(_governor, _core, _wNative); } diff --git a/contracts/src/arbitration/dispute-kits/DisputeKitSybilResistant.sol b/contracts/src/arbitration/dispute-kits/DisputeKitSybilResistant.sol index d95407c7b..5b0605f18 100644 --- a/contracts/src/arbitration/dispute-kits/DisputeKitSybilResistant.sol +++ b/contracts/src/arbitration/dispute-kits/DisputeKitSybilResistant.sol @@ -39,7 +39,7 @@ contract DisputeKitSybilResistant is DisputeKitClassicBase { /// @param _governor The governor's address. /// @param _core The KlerosCore arbitrator. /// @param _poh The Proof of Humanity registry. - /// @param _wNative The address for WETH tranfers. + /// @param _wNative The wrapped native token address, typically wETH. function initialize( address _governor, KlerosCore _core, diff --git a/contracts/src/arbitration/university/KlerosCoreUniversity.sol b/contracts/src/arbitration/university/KlerosCoreUniversity.sol index d0252df59..35fd5262c 100644 --- a/contracts/src/arbitration/university/KlerosCoreUniversity.sol +++ b/contracts/src/arbitration/university/KlerosCoreUniversity.sol @@ -6,7 +6,6 @@ import {IArbitrableV2, IArbitratorV2} from "../interfaces/IArbitratorV2.sol"; import {IDisputeKit} from "../interfaces/IDisputeKit.sol"; import {ISortitionModuleUniversity} from "./ISortitionModuleUniversity.sol"; import {SafeERC20, IERC20} from "../../libraries/SafeERC20.sol"; -import {SafeSend} from "../../libraries/SafeSend.sol"; import "../../libraries/Constants.sol"; import {UUPSProxiable} from "../../proxy/UUPSProxiable.sol"; import {Initializable} from "../../proxy/Initializable.sol"; @@ -15,7 +14,6 @@ import {Initializable} from "../../proxy/Initializable.sol"; /// Core arbitrator contract for educational purposes. contract KlerosCoreUniversity is IArbitratorV2, UUPSProxiable, Initializable { using SafeERC20 for IERC20; - using SafeSend for address payable; string public constant override version = "0.8.0"; @@ -101,7 +99,6 @@ contract KlerosCoreUniversity is IArbitratorV2, UUPSProxiable, Initializable { IDisputeKit[] public disputeKits; // Array of dispute kits. Dispute[] public disputes; // The disputes. mapping(IERC20 => CurrencyRate) public currencyRates; // The price of each token in ETH. - address public wNative; // The address for WETH tranfers. // ************************************* // // * Events * // @@ -200,7 +197,6 @@ contract KlerosCoreUniversity is IArbitratorV2, UUPSProxiable, Initializable { /// @param _courtParameters Numeric parameters of General court (minStake, alpha, feeForJuror and jurorsForCourtJump respectively). /// @param _timesPerPeriod The `timesPerPeriod` property value of the general court. /// @param _sortitionModuleAddress The sortition module responsible for sortition of the jurors. - /// @param _wNative The address of the WETH used by SafeSend for fallback transfers. function initialize( address _governor, address _instructor, @@ -210,15 +206,13 @@ contract KlerosCoreUniversity is IArbitratorV2, UUPSProxiable, Initializable { bool _hiddenVotes, uint256[4] memory _courtParameters, uint256[4] memory _timesPerPeriod, - ISortitionModuleUniversity _sortitionModuleAddress, - address _wNative + ISortitionModuleUniversity _sortitionModuleAddress ) external reinitializer(1) { governor = _governor; instructor = _instructor; pinakion = _pinakion; jurorProsecutionModule = _jurorProsecutionModule; sortitionModule = _sortitionModuleAddress; - wNative = _wNative; // NULL_DISPUTE_KIT: an empty element at index 0 to indicate when a dispute kit is not supported. disputeKits.push(); @@ -799,7 +793,7 @@ contract KlerosCoreUniversity is IArbitratorV2, UUPSProxiable, Initializable { // No one was coherent, send the rewards to the governor. if (round.feeToken == NATIVE_CURRENCY) { // The dispute fees were paid in ETH - payable(governor).safeSend(round.totalFeesForJurors, wNative); + payable(governor).send(round.totalFeesForJurors); } else { // The dispute fees were paid in ERC20 round.feeToken.safeTransfer(governor, round.totalFeesForJurors); @@ -851,7 +845,7 @@ contract KlerosCoreUniversity is IArbitratorV2, UUPSProxiable, Initializable { pinakion.safeTransfer(account, pnkReward); if (round.feeToken == NATIVE_CURRENCY) { // The dispute fees were paid in ETH - payable(account).safeSend(feeReward, wNative); + payable(account).send(feeReward); } else { // The dispute fees were paid in ERC20 round.feeToken.safeTransfer(account, feeReward); @@ -877,7 +871,7 @@ contract KlerosCoreUniversity is IArbitratorV2, UUPSProxiable, Initializable { if (leftoverFeeReward != 0) { if (round.feeToken == NATIVE_CURRENCY) { // The dispute fees were paid in ETH - payable(governor).safeSend(leftoverFeeReward, wNative); + payable(governor).send(leftoverFeeReward); } else { // The dispute fees were paid in ERC20 round.feeToken.safeTransfer(governor, leftoverFeeReward); diff --git a/contracts/src/libraries/SafeSend.sol b/contracts/src/libraries/SafeSend.sol index 2476d23e7..fcd02d815 100644 --- a/contracts/src/libraries/SafeSend.sol +++ b/contracts/src/libraries/SafeSend.sol @@ -6,7 +6,7 @@ * SPDX-License-Identifier: MIT */ -pragma solidity 0.8.24; +pragma solidity ^0.8.24; interface WethLike { function deposit() external payable;