Skip to content

Commit 2f3a8d8

Browse files
authored
Merge branch 'dev' into feat/kleros-app
2 parents ee802df + 71ac556 commit 2f3a8d8

File tree

8 files changed

+175
-24
lines changed

8 files changed

+175
-24
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
{
2+
"address": "0x39D123fc4cFD24EA5bB76195f9ecFE1f0DF35b0B",
3+
"abi": [
4+
{
5+
"inputs": [
6+
{
7+
"internalType": "uint256",
8+
"name": "block",
9+
"type": "uint256"
10+
}
11+
],
12+
"name": "randomNumbers",
13+
"outputs": [
14+
{
15+
"internalType": "uint256",
16+
"name": "number",
17+
"type": "uint256"
18+
}
19+
],
20+
"stateMutability": "view",
21+
"type": "function"
22+
},
23+
{
24+
"inputs": [
25+
{
26+
"internalType": "uint256",
27+
"name": "_block",
28+
"type": "uint256"
29+
}
30+
],
31+
"name": "receiveRandomness",
32+
"outputs": [
33+
{
34+
"internalType": "uint256",
35+
"name": "randomNumber",
36+
"type": "uint256"
37+
}
38+
],
39+
"stateMutability": "nonpayable",
40+
"type": "function"
41+
},
42+
{
43+
"inputs": [
44+
{
45+
"internalType": "uint256",
46+
"name": "_block",
47+
"type": "uint256"
48+
}
49+
],
50+
"name": "requestRandomness",
51+
"outputs": [],
52+
"stateMutability": "nonpayable",
53+
"type": "function"
54+
}
55+
],
56+
"transactionHash": "0x6ef5328c567093fa94fc10f1b23dd73f62b533aaa2ceaaa676ae2e2a15adc83b",
57+
"receipt": {
58+
"to": null,
59+
"from": "0xf1C7c037891525E360C59f708739Ac09A7670c59",
60+
"contractAddress": "0x39D123fc4cFD24EA5bB76195f9ecFE1f0DF35b0B",
61+
"transactionIndex": 3,
62+
"gasUsed": "224305",
63+
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
64+
"blockHash": "0xf88fbe2248f81d28c062b7380dcc474fb084e579a3766bc6ce77f5649187078b",
65+
"transactionHash": "0x6ef5328c567093fa94fc10f1b23dd73f62b533aaa2ceaaa676ae2e2a15adc83b",
66+
"logs": [],
67+
"blockNumber": 278824880,
68+
"cumulativeGasUsed": "584927",
69+
"status": 1,
70+
"byzantium": true
71+
},
72+
"args": [],
73+
"numDeployments": 1,
74+
"solcInputHash": "a5602534c00c2f67ca4b6a1cab8c717e",
75+
"metadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"block\",\"type\":\"uint256\"}],\"name\":\"randomNumbers\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"receiveRandomness\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"randomNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"requestRandomness\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Cl\\u00e9ment Lesaege - <[email protected]>\",\"details\":\"Random Number Generator returning the blockhash with a fallback behaviour. In case no one called it within the 256 blocks, it returns the previous blockhash. This contract must be used when returning 0 is a worse failure mode than returning another blockhash. Allows saving the random number for use in the future. It allows the contract to still access the blockhash even after 256 blocks.\",\"kind\":\"dev\",\"methods\":{\"receiveRandomness(uint256)\":{\"details\":\"Return the random number. If it has not been saved and is still computable compute it.\",\"params\":{\"_block\":\"Block the random number is linked to.\"},\"returns\":{\"randomNumber\":\"The random number or 0 if it is not ready or has not been requested.\"}},\"requestRandomness(uint256)\":{\"details\":\"Request a random number.\",\"params\":{\"_block\":\"Block the random number is linked to.\"}}},\"title\":\"Random Number Generator using blockhash with fallback.\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/rng/BlockhashRNG.sol\":\"BlockHashRNG\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[]},\"sources\":{\"src/rng/BlockhashRNG.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\nimport \\\"./RNG.sol\\\";\\n\\n/// @title Random Number Generator using blockhash with fallback.\\n/// @author Cl\\u00e9ment Lesaege - <[email protected]>\\n/// @dev\\n/// Random Number Generator returning the blockhash with a fallback behaviour.\\n/// In case no one called it within the 256 blocks, it returns the previous blockhash.\\n/// This contract must be used when returning 0 is a worse failure mode than returning another blockhash.\\n/// Allows saving the random number for use in the future. It allows the contract to still access the blockhash even after 256 blocks.\\ncontract BlockHashRNG is RNG {\\n mapping(uint256 block => uint256 number) public randomNumbers; // randomNumbers[block] is the random number for this block, 0 otherwise.\\n\\n /// @dev Request a random number.\\n /// @param _block Block the random number is linked to.\\n function requestRandomness(uint256 _block) external override {\\n // nop\\n }\\n\\n /// @dev Return the random number. If it has not been saved and is still computable compute it.\\n /// @param _block Block the random number is linked to.\\n /// @return randomNumber The random number or 0 if it is not ready or has not been requested.\\n function receiveRandomness(uint256 _block) external override returns (uint256 randomNumber) {\\n randomNumber = randomNumbers[_block];\\n if (randomNumber != 0) {\\n return randomNumber;\\n }\\n\\n if (_block < block.number) {\\n // The random number is not already set and can be.\\n if (blockhash(_block) != 0x0) {\\n // Normal case.\\n randomNumber = uint256(blockhash(_block));\\n } else {\\n // The contract was not called in time. Fallback to returning previous blockhash.\\n randomNumber = uint256(blockhash(block.number - 1));\\n }\\n }\\n randomNumbers[_block] = randomNumber;\\n }\\n}\\n\",\"keccak256\":\"0xb2ae9b40700c5915c1cbe57dde68486b669cfea1fdfec18d5b42ffbde44031de\",\"license\":\"MIT\"},\"src/rng/RNG.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.24;\\n\\ninterface RNG {\\n /// @dev Request a random number.\\n /// @param _block Block linked to the request.\\n function requestRandomness(uint256 _block) external;\\n\\n /// @dev Receive the random number.\\n /// @param _block Block the random number is linked to.\\n /// @return randomNumber Random Number. If the number is not ready or has not been required 0 instead.\\n function receiveRandomness(uint256 _block) external returns (uint256 randomNumber);\\n}\\n\",\"keccak256\":\"0xf92e0cf768afefc5cc6ef786c263b67dd00c021aa5753213dbbc33014adb68c5\",\"license\":\"MIT\"}},\"version\":1}",
76+
"bytecode": "0x608060405234801561001057600080fd5b50610169806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806313cf9054146100465780635257cd901461006b5780637363ae1f1461008b575b600080fd5b6100596100543660046100f3565b61009e565b60405190815260200160405180910390f35b6100596100793660046100f3565b60006020819052908152604090205481565b61009c6100993660046100f3565b50565b005b60008181526020819052604090205480156100b857919050565b438210156100de578140156100cf575080406100de565b6100da60014361010c565b4090505b60009182526020829052604090912081905590565b60006020828403121561010557600080fd5b5035919050565b8181038181111561012d57634e487b7160e01b600052601160045260246000fd5b9291505056fea26469706673582212208af4d57cc9727b11cb8cd9b8e8dca8477db4c383e58db8f1fbccf103ef66318d64736f6c63430008180033",
77+
"deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c806313cf9054146100465780635257cd901461006b5780637363ae1f1461008b575b600080fd5b6100596100543660046100f3565b61009e565b60405190815260200160405180910390f35b6100596100793660046100f3565b60006020819052908152604090205481565b61009c6100993660046100f3565b50565b005b60008181526020819052604090205480156100b857919050565b438210156100de578140156100cf575080406100de565b6100da60014361010c565b4090505b60009182526020829052604090912081905590565b60006020828403121561010557600080fd5b5035919050565b8181038181111561012d57634e487b7160e01b600052601160045260246000fd5b9291505056fea26469706673582212208af4d57cc9727b11cb8cd9b8e8dca8477db4c383e58db8f1fbccf103ef66318d64736f6c63430008180033",
78+
"devdoc": {
79+
"author": "Clément Lesaege - <[email protected]>",
80+
"details": "Random Number Generator returning the blockhash with a fallback behaviour. In case no one called it within the 256 blocks, it returns the previous blockhash. This contract must be used when returning 0 is a worse failure mode than returning another blockhash. Allows saving the random number for use in the future. It allows the contract to still access the blockhash even after 256 blocks.",
81+
"kind": "dev",
82+
"methods": {
83+
"receiveRandomness(uint256)": {
84+
"details": "Return the random number. If it has not been saved and is still computable compute it.",
85+
"params": {
86+
"_block": "Block the random number is linked to."
87+
},
88+
"returns": {
89+
"randomNumber": "The random number or 0 if it is not ready or has not been requested."
90+
}
91+
},
92+
"requestRandomness(uint256)": {
93+
"details": "Request a random number.",
94+
"params": {
95+
"_block": "Block the random number is linked to."
96+
}
97+
}
98+
},
99+
"title": "Random Number Generator using blockhash with fallback.",
100+
"version": 1
101+
},
102+
"userdoc": {
103+
"kind": "user",
104+
"methods": {},
105+
"version": 1
106+
},
107+
"storageLayout": {
108+
"storage": [
109+
{
110+
"astId": 34790,
111+
"contract": "src/rng/BlockhashRNG.sol:BlockHashRNG",
112+
"label": "randomNumbers",
113+
"offset": 0,
114+
"slot": "0",
115+
"type": "t_mapping(t_uint256,t_uint256)"
116+
}
117+
],
118+
"types": {
119+
"t_mapping(t_uint256,t_uint256)": {
120+
"encoding": "mapping",
121+
"key": "t_uint256",
122+
"label": "mapping(uint256 => uint256)",
123+
"numberOfBytes": "32",
124+
"value": "t_uint256"
125+
},
126+
"t_uint256": {
127+
"encoding": "inplace",
128+
"label": "uint256",
129+
"numberOfBytes": "32"
130+
}
131+
}
132+
}
133+
}

web/src/components/ClaimPnkButton.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ const ClaimPnkButton: React.FC = () => {
5151
const { request } = await simulatePnkFaucet(wagmiConfig, {
5252
functionName: "request",
5353
});
54-
if (walletClient) {
54+
if (walletClient && publicClient) {
5555
wrapWithToast(async () => await walletClient.writeContract(request), publicClient)
5656
.finally(() => {
5757
setIsSending(false);

web/src/components/Popup/index.tsx

+8-4
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,14 @@ const Popup: React.FC<PopupProps & IPopup> = ({
236236
break;
237237
}
238238

239+
const closePopup = () => {
240+
setIsOpen(false);
241+
resetValue();
242+
};
243+
239244
return (
240-
<Overlay>
241-
<Container ref={containerRef}>
245+
<Overlay onClick={closePopup}>
246+
<Container ref={containerRef} onClick={(e) => e.stopPropagation()}>
242247
{popupType === PopupType.SWAP_SUCCESS && (
243248
<SVGContainer>
244249
<CloseIcon onClick={() => setIsOpen(false)} />
@@ -259,8 +264,7 @@ const Popup: React.FC<PopupProps & IPopup> = ({
259264
variant="secondary"
260265
text={popupType === PopupType.DISPUTE_CREATED ? "Check the case" : "Close"}
261266
onClick={() => {
262-
setIsOpen(false);
263-
resetValue();
267+
closePopup();
264268
if (popupType === PopupType.DISPUTE_CREATED) {
265269
const { disputeId } = props as IDisputeCreated;
266270
navigate(`/cases/${disputeId}`);

web/src/pages/Cases/CaseDetails/Appeal/Classic/Fund.tsx

+1-3
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,7 @@ const Fund: React.FC<IFund> = ({ amount, setAmount, setIsOpen }) => {
137137
if (fundAppeal && fundAppealConfig && publicClient) {
138138
setIsSending(true);
139139
wrapWithToast(async () => await fundAppeal(fundAppealConfig.request), publicClient)
140-
.then((res) => {
141-
res.status && setIsOpen(true);
142-
})
140+
.then((res) => setIsOpen(res.status))
143141
.finally(() => {
144142
setIsSending(false);
145143
});

web/src/pages/Cases/CaseDetails/Evidence/SubmitEvidenceModal.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ const SubmitEvidenceModal: React.FC<{
8989
}, [publicClient, wagmiConfig, walletClient, close, evidenceGroup, file, message, setIsSending, uploadFile]);
9090

9191
return (
92-
<StyledModal {...{ isOpen }}>
92+
<StyledModal {...{ isOpen }} shouldCloseOnEsc shouldCloseOnOverlayClick onRequestClose={close}>
9393
<h1>Submit New Evidence</h1>
9494
<StyledTextArea value={message} onChange={(e) => setMessage(e.target.value)} placeholder="Your Arguments" />
9595
<StyledFileUploader callback={(file: File) => setFile(file)} />

web/src/pages/Courts/CourtDetails/StakePanel/InputDisplay.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ const InputDisplay: React.FC<IInputDisplay> = ({
104104
},
105105
args: [address ?? "0x", BigInt(id ?? "0")],
106106
});
107-
const parsedStake = formatPNK(jurorBalance?.[2] || 0n, 0, true);
107+
const parsedStake = formatPNK(jurorBalance?.[2] ?? 0n, 0, true);
108108
const isStaking = useMemo(() => action === ActionType.stake, [action]);
109109

110110
useEffect(() => {
@@ -153,6 +153,7 @@ const InputDisplay: React.FC<IInputDisplay> = ({
153153
isSending,
154154
setIsSending,
155155
setIsPopupOpen,
156+
setErrorMsg,
156157
}}
157158
/>
158159
</EnsureChainContainer>

web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx

+18-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useCallback, useMemo } from "react";
1+
import React, { useCallback, useEffect, useMemo } from "react";
22

33
import { useParams } from "react-router-dom";
44
import { useAccount, usePublicClient } from "wagmi";
@@ -36,17 +36,14 @@ const Container = styled.div`
3636
flex-direction: column;
3737
`;
3838

39-
const ErrorLabel = styled.label`
40-
color: ${({ theme }) => theme.error};
41-
`;
42-
4339
interface IActionButton {
4440
isSending: boolean;
4541
parsedAmount: bigint;
4642
action: ActionType;
4743
setIsSending: (arg0: boolean) => void;
4844
setAmount: (arg0: string) => void;
4945
setIsPopupOpen: (arg0: boolean) => void;
46+
setErrorMsg: (msg: string) => void;
5047
}
5148

5249
const StakeWithdrawButton: React.FC<IActionButton> = ({
@@ -55,6 +52,7 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({
5552
isSending,
5653
setIsSending,
5754
setIsPopupOpen,
55+
setErrorMsg,
5856
}) => {
5957
const { id } = useParams();
6058
const { address } = useAccount();
@@ -104,9 +102,11 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({
104102
},
105103
args: [klerosCoreAddress[DEFAULT_CHAIN], BigInt(targetStake ?? 0) - BigInt(allowance ?? 0)],
106104
});
105+
107106
const { writeContractAsync: increaseAllowance } = useWritePnkIncreaseAllowance();
107+
108108
const handleAllowance = useCallback(() => {
109-
if (increaseAllowanceConfig) {
109+
if (increaseAllowanceConfig && publicClient) {
110110
setIsSending(true);
111111
wrapWithToast(async () => await increaseAllowance(increaseAllowanceConfig.request), publicClient).finally(() => {
112112
setIsSending(false);
@@ -116,16 +116,18 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({
116116

117117
const { data: setStakeConfig, error: setStakeError } = useSimulateKlerosCoreSetStake({
118118
query: {
119-
enabled: !isUndefined(targetStake) && !isUndefined(id) && !isAllowance && parsedAmount !== 0n,
119+
enabled:
120+
!isUndefined(targetStake) && !isUndefined(id) && !isAllowance && parsedAmount !== 0n && targetStake >= 0n,
120121
},
121122
args: [BigInt(id ?? 0), targetStake],
122123
});
123124
const { writeContractAsync: setStake } = useWriteKlerosCoreSetStake();
125+
124126
const handleStake = useCallback(() => {
125-
if (setStakeConfig) {
127+
if (setStakeConfig && publicClient) {
126128
setIsSending(true);
127129
wrapWithToast(async () => await setStake(setStakeConfig.request), publicClient)
128-
.then((res) => res.status && setIsPopupOpen(true))
130+
.then((res) => setIsPopupOpen(res.status))
129131
.finally(() => {
130132
setIsSending(false);
131133
});
@@ -135,7 +137,7 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({
135137
const buttonProps = {
136138
[ActionType.allowance]: {
137139
text: "Allow PNK",
138-
checkDisabled: () => !balance || targetStake! > balance,
140+
checkDisabled: () => !balance || targetStake > balance,
139141
onClick: handleAllowance,
140142
},
141143
[ActionType.stake]: {
@@ -150,6 +152,12 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({
150152
},
151153
};
152154

155+
useEffect(() => {
156+
if (setStakeError) {
157+
setErrorMsg(setStakeError?.shortMessage ?? setStakeError.message);
158+
}
159+
}, [setStakeError]);
160+
153161
const { text, checkDisabled, onClick } = buttonProps[isAllowance ? ActionType.allowance : action];
154162
return (
155163
<EnsureChain>
@@ -168,7 +176,6 @@ const StakeWithdrawButton: React.FC<IActionButton> = ({
168176
}
169177
onClick={onClick}
170178
/>
171-
{setStakeError && <ErrorLabel> {setStakeError.message}</ErrorLabel>}
172179
</Container>
173180
</EnsureChain>
174181
);

web/src/pages/Resolver/NavigationButtons/SubmitDisputeButton.tsx

+11-3
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ const SubmitDisputeButton: React.FC = () => {
4343
}, [userBalance, disputeData]);
4444

4545
// TODO: decide which dispute kit to use
46-
const { data: submitCaseConfig } = useSimulateDisputeResolverCreateDisputeForTemplate({
46+
const { data: submitCaseConfig, error } = useSimulateDisputeResolverCreateDisputeForTemplate({
4747
query: {
4848
enabled: !insufficientBalance && isTemplateValid(disputeTemplate),
4949
},
@@ -63,6 +63,14 @@ const SubmitDisputeButton: React.FC = () => {
6363
[isSubmittingCase, insufficientBalance, isBalanceLoading, disputeTemplate]
6464
);
6565

66+
const errorMsg = useMemo(() => {
67+
if (insufficientBalance) return "Insufficient balance";
68+
else if (error) {
69+
return error?.shortMessage ?? error.message;
70+
}
71+
return null;
72+
}, [error, insufficientBalance]);
73+
6674
return (
6775
<>
6876
{" "}
@@ -91,9 +99,9 @@ const SubmitDisputeButton: React.FC = () => {
9199
}
92100
}}
93101
/>
94-
{insufficientBalance && (
102+
{errorMsg && (
95103
<ErrorButtonMessage>
96-
<ClosedCircleIcon /> Insufficient balance
104+
<ClosedCircleIcon /> {errorMsg}
97105
</ErrorButtonMessage>
98106
)}
99107
</div>

0 commit comments

Comments
 (0)