Skip to content

Commit 5a46536

Browse files
committed
fix: token whitelist for DisputeKitGated and DisputeKitGatedShutter
1 parent 6b7e365 commit 5a46536

File tree

4 files changed

+88
-8
lines changed

4 files changed

+88
-8
lines changed

contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi
204204
uint256 _numberOfChoices,
205205
bytes calldata _extraData,
206206
uint256 /*_nbVotes*/
207-
) external override onlyByCore {
207+
) public virtual override onlyByCore {
208208
uint256 localDisputeID;
209209
Dispute storage dispute;
210210
Active storage active = coreDisputeIDToActive[_coreDisputeID];

contracts/src/arbitration/dispute-kits/DisputeKitGated.sol

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ interface IBalanceHolderERC1155 {
2929
contract DisputeKitGated is DisputeKitClassicBase {
3030
string public constant override version = "2.0.0";
3131

32+
// ************************************* //
33+
// * Storage * //
34+
// ************************************* //
35+
36+
mapping(address token => bool supported) public supportedTokens; // Whether the token is supported or not.
37+
3238
// ************************************* //
3339
// * Constructor * //
3440
// ************************************* //
@@ -62,6 +68,34 @@ contract DisputeKitGated is DisputeKitClassicBase {
6268
// NOP
6369
}
6470

71+
/// @notice Changes the supported tokens.
72+
/// @param _tokens The tokens to support.
73+
/// @param _supported Whether the tokens are supported or not.
74+
function changeSupportedTokens(address[] memory _tokens, bool _supported) external onlyByOwner {
75+
for (uint256 i = 0; i < _tokens.length; i++) {
76+
supportedTokens[_tokens[i]] = _supported;
77+
}
78+
}
79+
80+
// ************************************* //
81+
// * State Modifiers * //
82+
// ************************************* //
83+
84+
/// @inheritdoc DisputeKitClassicBase
85+
function createDispute(
86+
uint256 _coreDisputeID,
87+
uint256 _coreRoundID,
88+
uint256 _numberOfChoices,
89+
bytes calldata _extraData,
90+
uint256 _nbVotes
91+
) public override {
92+
(address tokenGate, , ) = _extraDataToTokenInfo(_extraData);
93+
if (!supportedTokens[tokenGate]) revert TokenNotSupported(tokenGate);
94+
95+
// super.createDispute() ensures access control onlyByCore.
96+
super.createDispute(_coreDisputeID, _coreRoundID, _numberOfChoices, _extraData, _nbVotes);
97+
}
98+
6599
// ************************************* //
66100
// * Internal * //
67101
// ************************************* //
@@ -78,7 +112,7 @@ contract DisputeKitGated is DisputeKitClassicBase {
78112
/// @return tokenId The token ID for ERC-1155 tokens (ignored for ERC-20/ERC-721).
79113
function _extraDataToTokenInfo(
80114
bytes memory _extraData
81-
) public pure returns (address tokenGate, bool isERC1155, uint256 tokenId) {
115+
) internal pure returns (address tokenGate, bool isERC1155, uint256 tokenId) {
82116
// Need at least 160 bytes to safely read the parameters
83117
if (_extraData.length < 160) return (address(0), false, 0);
84118

@@ -116,4 +150,10 @@ contract DisputeKitGated is DisputeKitClassicBase {
116150
return IBalanceHolder(tokenGate).balanceOf(_juror) > 0;
117151
}
118152
}
153+
154+
// ************************************* //
155+
// * Errors * //
156+
// ************************************* //
157+
158+
error TokenNotSupported(address tokenGate);
119159
}

contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ contract DisputeKitGatedShutter is DisputeKitClassicBase {
3434
// * Storage * //
3535
// ************************************* //
3636

37+
mapping(address token => bool supported) public supportedTokens; // Whether the token is supported or not.
3738
mapping(uint256 localDisputeID => mapping(uint256 localRoundID => mapping(uint256 voteID => bytes32 recoveryCommitment)))
3839
public recoveryCommitments;
3940

@@ -96,10 +97,34 @@ contract DisputeKitGatedShutter is DisputeKitClassicBase {
9697
// NOP
9798
}
9899

100+
/// @notice Changes the supported tokens.
101+
/// @param _tokens The tokens to support.
102+
/// @param _supported Whether the tokens are supported or not.
103+
function changeSupportedTokens(address[] memory _tokens, bool _supported) external onlyByOwner {
104+
for (uint256 i = 0; i < _tokens.length; i++) {
105+
supportedTokens[_tokens[i]] = _supported;
106+
}
107+
}
108+
99109
// ************************************* //
100110
// * State Modifiers * //
101111
// ************************************* //
102112

113+
/// @inheritdoc DisputeKitClassicBase
114+
function createDispute(
115+
uint256 _coreDisputeID,
116+
uint256 _coreRoundID,
117+
uint256 _numberOfChoices,
118+
bytes calldata _extraData,
119+
uint256 _nbVotes
120+
) public override {
121+
(address tokenGate, , ) = _extraDataToTokenInfo(_extraData);
122+
if (!supportedTokens[tokenGate]) revert TokenNotSupported(tokenGate);
123+
124+
// super.createDispute() ensures access control onlyByCore.
125+
super.createDispute(_coreDisputeID, _coreRoundID, _numberOfChoices, _extraData, _nbVotes);
126+
}
127+
103128
/// @notice Sets the caller's commit for the specified votes.
104129
///
105130
/// @dev It can be called multiple times during the commit period, each call overrides the commits of the previous one.
@@ -209,7 +234,7 @@ contract DisputeKitGatedShutter is DisputeKitClassicBase {
209234
/// @return tokenGate The address of the token contract used for gating access.
210235
/// @return isERC1155 True if the token is an ERC-1155, false for ERC-20/ERC-721.
211236
/// @return tokenId The token ID for ERC-1155 tokens (ignored for ERC-20/ERC-721).
212-
function __extraDataToTokenInfo(
237+
function _extraDataToTokenInfo(
213238
bytes memory _extraData
214239
) internal pure returns (address tokenGate, bool isERC1155, uint256 tokenId) {
215240
// Need at least 160 bytes to safely read the parameters
@@ -237,7 +262,7 @@ contract DisputeKitGatedShutter is DisputeKitClassicBase {
237262
// Get the local dispute and extract token info from extraData
238263
uint256 localDisputeID = coreDisputeIDToLocal[_coreDisputeID];
239264
Dispute storage dispute = disputes[localDisputeID];
240-
(address tokenGate, bool isERC1155, uint256 tokenId) = __extraDataToTokenInfo(dispute.extraData);
265+
(address tokenGate, bool isERC1155, uint256 tokenId) = _extraDataToTokenInfo(dispute.extraData);
241266

242267
// If no token gate is specified, allow all jurors
243268
if (tokenGate == address(0)) return true;
@@ -254,5 +279,6 @@ contract DisputeKitGatedShutter is DisputeKitClassicBase {
254279
// * Errors * //
255280
// ************************************* //
256281

282+
error TokenNotSupported(address tokenGate);
257283
error EmptyRecoveryCommit();
258284
}

contracts/test/arbitration/dispute-kit-gated.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
KlerosCore,
66
SortitionModule,
77
IncrementalNG,
8-
DisputeKitGated,
8+
DisputeKitGatedMock,
99
TestERC20,
1010
TestERC721,
1111
TestERC1155,
@@ -14,6 +14,7 @@ import { expect } from "chai";
1414
import { Courts } from "../../deploy/utils";
1515
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
1616
import { deployERC1155, deployERC721 } from "../../deploy/utils/deployTokens";
17+
import { deployUpgradable } from "../../deploy/utils/deployUpgradable";
1718

1819
/* eslint-disable no-unused-vars */
1920
/* eslint-disable no-unused-expressions */ // https://github.com/standard/standard/issues/690#issuecomment-278533482
@@ -26,7 +27,7 @@ describe("DisputeKitGated", async () => {
2627
let deployer: string;
2728
let juror1: HardhatEthersSigner;
2829
let juror2: HardhatEthersSigner;
29-
let disputeKitGated: DisputeKitGated;
30+
let disputeKitGated: DisputeKitGatedMock;
3031
let pnk: PNK;
3132
let dai: TestERC20;
3233
let core: KlerosCore;
@@ -47,12 +48,25 @@ describe("DisputeKitGated", async () => {
4748
fallbackToGlobal: true,
4849
keepExistingDeployments: false,
4950
});
50-
disputeKitGated = await ethers.getContract<DisputeKitGated>("DisputeKitGated");
51+
5152
pnk = await ethers.getContract<PNK>("PNK");
5253
dai = await ethers.getContract<TestERC20>("DAI");
54+
const weth = await ethers.getContract<TestERC20>("WETH");
5355
core = await ethers.getContract<KlerosCore>("KlerosCore");
5456
sortitionModule = await ethers.getContract<SortitionModule>("SortitionModule");
5557

58+
const deploymentResult = await deployUpgradable(deployments, "DisputeKitGatedMock", {
59+
from: deployer,
60+
proxyAlias: "UUPSProxy",
61+
args: [deployer, core.target, weth.target, 1],
62+
log: true,
63+
});
64+
await core.addNewDisputeKit(deploymentResult.address);
65+
const disputeKitGatedID = (await core.getDisputeKitsLength()) - 1n;
66+
await core.enableDisputeKits(Courts.GENERAL, [disputeKitGatedID], true); // enable disputeKitGated on the General Court
67+
68+
disputeKitGated = await ethers.getContract<DisputeKitGatedMock>("DisputeKitGatedMock");
69+
5670
// Make the tests more deterministic with this dummy RNG
5771
await deployments.deploy("IncrementalNG", {
5872
from: deployer,
@@ -123,7 +137,7 @@ describe("DisputeKitGated", async () => {
123137
const extraData = encodeExtraData(courtId, minJurors, disputeKitId, tokenGate, isERC1155, tokenId);
124138
// console.log("extraData", extraData);
125139

126-
const tokenInfo = await disputeKitGated._extraDataToTokenInfo(extraData);
140+
const tokenInfo = await disputeKitGated.extraDataToTokenInfo(extraData);
127141
expect(tokenInfo[0]).to.equal(tokenGate);
128142
expect(tokenInfo[1]).to.equal(isERC1155);
129143
expect(tokenInfo[2]).to.equal(tokenId);

0 commit comments

Comments
 (0)