The distributeByOwner()
function in ProxyFactory
is used to perform an emergency distribution e.g. when the contest organizer has failed to perform a distribution timeously. The contestId
parameter indicates the contest in question, and the proxy
parameter must point to the proxy contract that owns the contestId
reward token pool. There is no validation that proxy
is the correct proxy address for contestId
, therefore it is possible for a different contest's reward pool to be irreversibly distributed to the winners of contestId
if the wrong proxy
address is specified.
The distributeByOwner()
function in ProxyFactory
is used to perform an emergency distribution:
If owner
accidentally provides the proxy
address for a different contestId
in the call to distributeByOwner()
, the ProxyFactory._distribute()
call on line 217 will irreversibly send rewards for that other contest to the winners of contestId
(the list of winners is encoded in the data
parameter).
On the side of the proxy, in the default Distributor._distribute()
implementation there is no contest ID validation prior to distribution (indeed, the contest ID is not available at all). The token parameter is validated according to a whitelist, but the whitelist is very short and tokens chosen for rewards are very likely to overlap between contests e.g. JPYC or USDC is very likely to be used. Rewards are specified as percentages, so these will scale with the size of the contest reward pool and thus not prevent mistakes either.
Proof of Concept
Alice
organizes contestId A
with USDC rewards
Alicia
organizes contestId B
, with a close time that happens to be 7 days after contestId A
, also with USDC rewards
Contest A
ends, and 7 days later content B
ends
Alice
hasn't distributed rewards for contest A
yet, so owner
steps in and invokes distributeByOwner()
, specifying the winners of contest A
in the data
parameter, but accidentally specifies the proxy
for contest B
instead of contest A
Alicia's
contest B
rewards are incorrectly and irreversibly distributed to the winners of contest A
This is a medium risk issue because there is a permanent loss of funds at risk, but there are external conditions required (owner
error and overlapping contest periods).
Manual analysis.
The proxy
parameter is error prone and unnecessary. Replace proxy
with an implementation
address to match the pattern used everywhere else, and use getProxyAddress(bytes32 salt, address implementation)
to determine the correct value for proxy
.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.