Skip to content

Commit 7e79c70

Browse files
authored
Merge pull request #363 from sherlock-protocol/feat/create-contest-new-pricing
feat: new pricing structure in contest creation
2 parents 43278a9 + 2889437 commit 7e79c70

File tree

3 files changed

+77
-70
lines changed

3 files changed

+77
-70
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { useQuery } from "react-query"
2+
import { contests as contestsAPI } from "../axios"
3+
4+
type GetAdminContestVariablesResponse = {
5+
length: number
6+
full_payment: number
7+
contest_rewards: number
8+
judging_prize_pool: number
9+
lead_judge_fixed_pay: number
10+
admin_fee: number
11+
}
12+
13+
type ContestVariables = {
14+
length: number
15+
fullPayment: number
16+
auditContestRewards: number
17+
judgingPrizePool: number
18+
leadJudgeFixedPay: number
19+
adminFee: number
20+
}
21+
22+
export const adminContestVariablesQueryKey = (nSLOC: number) => ["contest-variables", nSLOC]
23+
export const useAdminContestVariables = (nSLOC: number) =>
24+
useQuery<ContestVariables, Error>(adminContestVariablesQueryKey(nSLOC), async () => {
25+
const { data } = await contestsAPI.get<GetAdminContestVariablesResponse>(`/admin/contest/variables?nsloc=${nSLOC}`)
26+
27+
return {
28+
length: data.length,
29+
fullPayment: data.full_payment,
30+
auditContestRewards: data.contest_rewards,
31+
judgingPrizePool: data.judging_prize_pool,
32+
leadJudgeFixedPay: data.lead_judge_fixed_pay,
33+
adminFee: data.admin_fee,
34+
}
35+
})

src/hooks/api/admin/useAdminCreateContest.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@ type AdminCreateContestParams = {
2020
nSLOC: string
2121
startDate: DateTime
2222
endDate: DateTime
23-
auditPrizePool: number
23+
auditRewards: number
2424
judgingPrizePool: number
25-
leadSeniorAuditorFixedPay: number
2625
leadJudgeFixedPay: number
2726
fullPayment: number
2827
}
@@ -47,9 +46,8 @@ export const useAdminCreateContest = () => {
4746
lines_of_code: params.contest.nSLOC,
4847
starts_at: params.contest.startDate.toSeconds(),
4948
ends_at: params.contest.endDate.toSeconds(),
50-
prize_pool: params.contest.auditPrizePool,
49+
audit_rewards: params.contest.auditRewards,
5150
judging_prize_pool: params.contest.judgingPrizePool,
52-
lead_senior_auditor_fixed_pay: params.contest.leadSeniorAuditorFixedPay,
5351
lead_judge_fixed_pay: params.contest.leadJudgeFixedPay,
5452
full_payment: params.contest.fullPayment,
5553
})

src/pages/admin/AdminContestsList/CreateContestModal.tsx

Lines changed: 40 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { commify } from "../../../utils/units"
1717
import { Field } from "../../Claim/Field"
1818
import { ErrorModal } from "../../../pages/ContestDetails/ErrorModal"
1919
import { useAdminTwitterAccount } from "../../../hooks/api/admin/useTwitterAccount"
20+
import { useAdminContestVariables } from "../../../hooks/api/admin/useAdminContestVariables"
2021

2122
type Props = ModalProps & {}
2223

@@ -43,18 +44,14 @@ export const CreateContestModal: React.FC<Props> = ({ onClose }) => {
4344
const [contestTitle, setContestTitle] = useState("")
4445
const [contestShortDescription, setShortDescription] = useState("")
4546
const [contestNSLOC, setContestNSLOC] = useState("")
47+
const [debouncedContestNSLOC] = useDebounce(contestNSLOC, 300)
4648
const [contestStartDate, setContestStartDate] = useState("")
4749
const [contestAuditLength, setContestAuditLength] = useState("")
48-
const [contestAuditPrizePool, setContestAuditPrizePool] = useState<BigNumber | undefined>(BigNumber.from(0))
49-
const [contestLeadSeniorWatsonFixedPay, setContestLeadSeniorWatsonFixedPay] = useState<BigNumber | undefined>(
50-
BigNumber.from(0)
51-
)
50+
const [contestAuditRewards, setContestAuditRewards] = useState<BigNumber | undefined>(BigNumber.from(0))
5251
const [contestJudgingPrizePool, setContestJudgingPrizePool] = useState<BigNumber | undefined>(BigNumber.from(0))
5352
const [contestLeadJudgeFixedPay, setContestLeadJudgeFixedPay] = useState<BigNumber | undefined>(BigNumber.from(0))
5453
const [contestTotalCost, setContestTotalCost] = useState<BigNumber | undefined>(BigNumber.from(0))
55-
const [initialLeadSeniorWatsonFixedPay, setInitialLeadSeniorWatsonFixedPay] = useState<BigNumber | undefined>(
56-
BigNumber.from(0)
57-
)
54+
const [initialAuditContestRewards, setInitialAuditContestRewards] = useState<BigNumber | undefined>(BigNumber.from(0))
5855
const [initialJudgingPrizePool, setInitialJudgingPrizePool] = useState<BigNumber | undefined>(BigNumber.from(0))
5956
const [initialLeadJudgeFixedPay, setInitialLeadJudgeFixedPay] = useState<BigNumber | undefined>(BigNumber.from(0))
6057
const [initialTotalCost, setInitialTotalCost] = useState<BigNumber | undefined>(BigNumber.from(0))
@@ -66,6 +63,27 @@ export const CreateContestModal: React.FC<Props> = ({ onClose }) => {
6663

6764
const displayProtocolInfo = !!protocol || protocolNotFound || protocolLoading
6865

66+
const { data: contestVariables, isSuccess: contestVariablesSuccess } = useAdminContestVariables(
67+
parseInt(debouncedContestNSLOC)
68+
)
69+
70+
useEffect(() => {
71+
if (contestVariablesSuccess) {
72+
setContestAuditLength(`${contestVariables.length}`)
73+
74+
setInitialAuditContestRewards(ethers.utils.parseUnits(`${contestVariables.auditContestRewards}`, 6))
75+
setInitialJudgingPrizePool(ethers.utils.parseUnits(`${contestVariables.judgingPrizePool}`, 6))
76+
setInitialLeadJudgeFixedPay(ethers.utils.parseUnits(`${contestVariables.leadJudgeFixedPay}`, 6))
77+
setInitialTotalCost(ethers.utils.parseUnits(`${contestVariables.fullPayment}`, 6))
78+
} else {
79+
setContestAuditLength("")
80+
setInitialAuditContestRewards(BigNumber.from(0))
81+
setInitialJudgingPrizePool(BigNumber.from(0))
82+
setInitialLeadJudgeFixedPay(BigNumber.from(0))
83+
setInitialTotalCost(BigNumber.from(0))
84+
}
85+
}, [contestVariablesSuccess, setContestAuditLength, contestVariables])
86+
6987
useEffect(() => {
7088
if (isSuccess) onClose?.()
7189
}, [isSuccess, onClose])
@@ -105,46 +123,14 @@ export const CreateContestModal: React.FC<Props> = ({ onClose }) => {
105123
setStartDateError(undefined)
106124
}, [contestStartDate, contestAuditLength])
107125

108-
useEffect(() => {
109-
if (!contestAuditPrizePool) return
110-
111-
const fixedPay = contestAuditPrizePool.div(10).mul(4)
112-
const judgingPool = contestAuditPrizePool.div(100).mul(5)
113-
114-
setInitialLeadSeniorWatsonFixedPay(fixedPay)
115-
setInitialJudgingPrizePool(judgingPool)
116-
setInitialLeadJudgeFixedPay(judgingPool)
117-
}, [contestAuditPrizePool, setInitialLeadSeniorWatsonFixedPay, setInitialJudgingPrizePool, setInitialTotalCost])
118-
119-
useEffect(() => {
120-
if (!contestJudgingPrizePool) return
121-
setInitialLeadJudgeFixedPay(contestJudgingPrizePool)
122-
}, [contestJudgingPrizePool])
123-
124-
useEffect(() => {
125-
const total = contestAuditPrizePool
126-
?.add(contestLeadSeniorWatsonFixedPay ?? 0)
127-
.add(contestJudgingPrizePool ?? 0)
128-
.add(contestLeadJudgeFixedPay ?? 0)
129-
.add(contestAuditPrizePool.div(100).mul(5))
130-
setInitialTotalCost(total)
131-
}, [contestAuditPrizePool, contestLeadSeniorWatsonFixedPay, contestJudgingPrizePool, contestLeadJudgeFixedPay])
132-
133126
const sherlockFee = useMemo(() => {
134127
const fee = contestTotalCost
135-
?.sub(contestAuditPrizePool ?? 0)
136-
.sub(contestLeadSeniorWatsonFixedPay ?? 0)
128+
?.sub(contestAuditRewards ?? 0)
137129
.sub(contestJudgingPrizePool ?? 0)
138130
.sub(contestLeadJudgeFixedPay ?? 0)
139131

140132
return commify(parseInt(ethers.utils.formatUnits(fee ?? 0, 6)))
141-
}, [
142-
contestAuditPrizePool,
143-
contestLeadSeniorWatsonFixedPay,
144-
contestJudgingPrizePool,
145-
contestTotalCost,
146-
contestLeadJudgeFixedPay,
147-
])
133+
}, [contestTotalCost, contestAuditRewards, contestJudgingPrizePool, contestLeadJudgeFixedPay])
148134

149135
const canCreateContest = useMemo(() => {
150136
if (protocolName === "") return false
@@ -163,15 +149,13 @@ export const CreateContestModal: React.FC<Props> = ({ onClose }) => {
163149
if (!startDate.isValid) return false
164150
if (startDate < DateTime.now()) return false
165151

166-
if (contestAuditPrizePool?.eq(BigNumber.from(0))) return false
167-
if (contestLeadSeniorWatsonFixedPay?.eq(BigNumber.from(0))) return false
152+
if (contestAuditRewards?.eq(BigNumber.from(0))) return false
168153
if (contestTotalCost?.eq(BigNumber.from(0))) return false
169154

170155
return true
171156
}, [
172157
contestAuditLength,
173-
contestAuditPrizePool,
174-
contestLeadSeniorWatsonFixedPay,
158+
contestAuditRewards,
175159
contestShortDescription.length,
176160
contestStartDate,
177161
contestTitle,
@@ -227,18 +211,16 @@ export const CreateContestModal: React.FC<Props> = ({ onClose }) => {
227211
nSLOC: contestNSLOC,
228212
startDate,
229213
endDate,
230-
auditPrizePool: parseInt(ethers.utils.formatUnits(contestAuditPrizePool ?? 0, 6)),
214+
auditRewards: parseInt(ethers.utils.formatUnits(contestAuditRewards ?? 0, 6)),
231215
judgingPrizePool: parseInt(ethers.utils.formatUnits(contestJudgingPrizePool ?? 0, 6)),
232-
leadSeniorAuditorFixedPay: parseInt(ethers.utils.formatUnits(contestLeadSeniorWatsonFixedPay ?? 0, 6)),
233216
leadJudgeFixedPay: parseInt(ethers.utils.formatUnits(contestLeadJudgeFixedPay ?? 0, 6)),
234217
fullPayment: parseInt(ethers.utils.formatUnits(contestTotalCost ?? 0, 6)),
235218
},
236219
})
237220
}, [
238221
contestAuditLength,
239-
contestAuditPrizePool,
222+
contestAuditRewards,
240223
contestJudgingPrizePool,
241-
contestLeadSeniorWatsonFixedPay,
242224
contestLeadJudgeFixedPay,
243225
contestNSLOC,
244226
contestShortDescription,
@@ -262,16 +244,14 @@ export const CreateContestModal: React.FC<Props> = ({ onClose }) => {
262244
contestNSLOC !== "" ||
263245
contestStartDate !== "" ||
264246
contestAuditLength !== "" ||
265-
contestAuditPrizePool?.gt(BigNumber.from(0)) ||
266-
contestLeadSeniorWatsonFixedPay?.gt(BigNumber.from(0)) ||
247+
contestAuditRewards?.gt(BigNumber.from(0)) ||
267248
contestJudgingPrizePool?.gt(BigNumber.from(0)) ||
268249
contestLeadJudgeFixedPay?.gt(BigNumber.from(0)) ||
269250
contestTotalCost?.gt(BigNumber.from(0)),
270251
[
271252
contestAuditLength,
272-
contestAuditPrizePool,
253+
contestAuditRewards,
273254
contestJudgingPrizePool,
274-
contestLeadSeniorWatsonFixedPay,
275255
contestLeadJudgeFixedPay,
276256
contestNSLOC,
277257
contestShortDescription,
@@ -400,6 +380,9 @@ export const CreateContestModal: React.FC<Props> = ({ onClose }) => {
400380
<Field label="Short Description" error={!!shortDescriptionError} errorMessage={shortDescriptionError ?? ""}>
401381
<Input value={contestShortDescription} onChange={handleUpdateShortDescription} />
402382
</Field>
383+
<Field label="Start Date" error={!!startDateError} errorMessage={startDateError ?? ""}>
384+
<Input value={contestStartDate} onChange={setContestStartDate} />
385+
</Field>
403386
<Field
404387
label="nSLOC"
405388
detail={
@@ -410,31 +393,22 @@ export const CreateContestModal: React.FC<Props> = ({ onClose }) => {
410393
>
411394
<Input value={contestNSLOC} onChange={setContestNSLOC} />
412395
</Field>
413-
<Field label="Start Date" error={!!startDateError} errorMessage={startDateError ?? ""}>
414-
<Input value={contestStartDate} onChange={setContestStartDate} />
415-
</Field>
416396
<Field label="Audit Length">
417397
<Input type="number" value={contestAuditLength} onChange={setContestAuditLength} />
418398
</Field>
419-
<Field label="Audit Contest Prize Pool">
420-
<TokenInput token="USDC" onChange={setContestAuditPrizePool} />
421-
</Field>
422-
<Field label="Lead Senior Watson Fixed Pay">
423-
<TokenInput
424-
token="USDC"
425-
initialValue={initialLeadSeniorWatsonFixedPay}
426-
onChange={setContestLeadSeniorWatsonFixedPay}
427-
/>
399+
<Field label="Audit Contest Rewards" sublabel="Contest Pool + Lead fixed pay">
400+
<TokenInput token="USDC" initialValue={initialAuditContestRewards} onChange={setContestAuditRewards} />
428401
</Field>
429402
<Field label="Judging Contest Prize Pool">
430403
<TokenInput token="USDC" initialValue={initialJudgingPrizePool} onChange={setContestJudgingPrizePool} />
431404
</Field>
432405
<Field label="Lead Judge Fixed Pay">
433406
<TokenInput token="USDC" initialValue={initialLeadJudgeFixedPay} onChange={setContestLeadJudgeFixedPay} />
434407
</Field>
435-
<Field label="Total Cost" detail={`Sherlock fee will be ${sherlockFee} USDC`}>
408+
<Field label="Total Cost">
436409
<TokenInput token="USDC" initialValue={initialTotalCost} onChange={setContestTotalCost} />
437410
</Field>
411+
<Text size="small">{`Admin Fee: ${sherlockFee} USDC`}</Text>
438412
</Column>
439413
<hr />
440414
<Button disabled={!canCreateContest} onClick={handleCreateContest}>

0 commit comments

Comments
 (0)