Exploring Missed Vulnerabilities: CodeHawks Sparkn Audit Contest

Zuhaib Mohammed
4 min readSep 19


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 in deployProxyAndDistributeBySignature 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