Exploring Missed Vulnerabilities: CodeHawks Sparkn Audit Contest
--
The Sparkn contest marked my first audit as a team with 33Audits and hexbyte. It was an amazing learning opportunity, and I recommend solo auditors to occasionally work in teams.
Now, let’s get to the findings: In total, there were 1 High, 3 Medium, and 12 Low-risk issues in the contest. I’ll explain each vulnerability and share the lessons I’ve learned to help prevent similar mistakes in the future.
The Findings
H-01. The same signature can be used in different
distribution
implementation causing that the caller who owns the signature, can distribute on unauthorized implementations
The Vulnerability: The caller who owns the signature, can distribute the prizes for a new distribution implementation using the same signature which was created for an old implementation.
Learning: When handling signatures, ensure to verify unique hash generation parameters and assess the potential for replay attacks.
M-01. The
digest
calculation indeployProxyAndDistributeBySignature
does not follow EIP-712 specification
The Vulnerability: The calculation of the digest
done in ProxyFactory.deployProxyAndDistributeBySignature()
does not follow the EIP-712 specification. It is missing the function's corresponding typeHash
, as well as the hashStruct
calculation of the data
signature parameter, which are both defined in the EIP.
Learning: This is a fundamental vulnerability !! Always verify whether the implementation adheres to the standard EIPS.
M-02. Blacklisted STADIUM_ADDRESS address cause fund stuck in the contract forever
The Vulnerability: This vulnerability concerns the immutability of STADIUM_ADDRESS
. If the token used for rewards blacklists this address, it can render the system incapable of making transfers, resulting in funds becoming trapped in the contract indefinitely.
Learning: We identified and reported this issue by considering the implications of a hardcoded address, particularly if it were to become compromised or blacklisted.
M-03. Malicious/Compromised organiser can reclaw all funds, stealing work from supporters
The Vulnerability: There is no input validation on the winners
array. A malicious or compromised organizer can, with little effort, simply pass an array of length one containing a wallet address that they control as the winners
parameter, and [10000]
as the percentages
parameter in order to receive 100% of the funds initially deposited to the contract
Learning: Double-check trusted users’ roles and actions to prevent potential rugpulls.
L-01. If a winner is blacklisted on any of the tokens they can’t receive their funds
The Vulnerability: Since transfers are done in a loop to all winners i.e all winners wouldn’t be able to get their tokens when the reward is distributed.
Learning: This is somewhat similar to M-02 but the trigger to identify such issues should be transfer of value via loops. Most of time they yield DoS related issues.
L-02. Owner can incorrectly pull funds from contests not yet expired
The Vulnerability: Owner can incorrectly pull funds from a closed contest which has not yet expired using distributeByOwner()
.
Learning: Similar to M-03, Double-check trusted users’ roles and actions to prevent potential rugpulls.
L-03. Lack of checking the existence of the Proxy contract
The Vulnerability: If the ProxyFactory::distributeByOwner()
is executed before the Proxy
contract has been deployed, the transaction will be executed successfully, but the stuck tokens will not be transferred to a rescue requestor.
Learning: When making a low-level call to an external contract, always check for its existance, be sure to check the return value as well.
L-04. Signature missing nonce & expiration deadline
The Vulnerability: The signature used in ProxyFactory::deployProxyAndDistributeBySignature()
is missing a nonce & expiration deadline.
Learning: Always look for signature replay attack vectors.
L-05. Precision loss/Rounding to Zero in
_distribute()
The Vulnerability: The vulnerability stems from the calculation of amount
within the distribution loop. The formula amount = totalAmount * percentages[i] / BASIS_POINTS
involves a division operation that could result in loss of precision(Rounding to Zero) when dealing with small totalAmount
values or low percentages[i]
.
Learning: We reported this issue, and it was also included in the final report. Whenever you encounter mathematical equations, be sure to check for precision loss-related problems. For further context, consider reading Dacian’s article at https://dacian.me/precision-loss-errors.
L-06. Potential DOS due to Gas Exhaustion Due to Large Array Iteration in
_distribute
Function
The Vulnerability: When dealing with very large arrays, this loop may consume excessive gas, which can result in transactions running out of gas and failing.
Learning: We’ve reported this issue. Always consider the possibility of running out of gas when working with loops.
L-12. Organizers are not incentivized to deploy and distribute to winners causing that winners may not to be rewarded for a long time and force the protocol owner to manage the distribution
The Vulnerability: The organizer can deploy and distribute to winners at any time without restriction about the contest expiration time EXPIRATION_TIME
causing that the winners to be unable to receive their rewards for a long time.
Learning: If an external party or EOA is dependent to perform an action, are they incentivised for it.
Sparkn Audit Report — https://www.codehawks.com/report/cllcnja1h0001lc08z7w0orxx
Thank For Reading.
Connect with me: https://linktr.ee/zuhaib44