Omniscia Tokemak Network Audit

VoteTracker Manual Review Findings

VoteTracker Manual Review Findings

VTR-01M: Inexistent Validation of Duplicates

Description:

The setVoteMultipliers function does not properly sanitize the input array against duplicates which can significantly impact the logic of the contract.

Example:

contracts/vote/VoteTracker.sol
332function setVoteMultiplers(VoteTokenMultipler[] memory multipliers) public override onlyOwner {
333 uint256 votingTokenLength = votingTokens.length;
334 if (votingTokenLength > 0) {
335 for (uint256 i = votingTokenLength; i > 0; i--) {
336 votingTokens.pop();
337 }
338 }
339
340 for (uint256 i = 0; i < multipliers.length; i++) {
341 voteMultipliers[multipliers[i].token] = multipliers[i].multiplier;
342 votingTokens.push(multipliers[i].token);
343 }
344
345 emit VoteMultipliersSet(multipliers);
346}

Recommendation:

We advise proper sanitization to be imposed in the linked for loop by ensuring that the votingTokens array does not contain the entry for example by using the voteMultipliers value and zeroing it during the first deletion iteration.

Alleviation:

Duplicates are now properly prevented by ensuring that the vote multiplier of a particular token is zero.

VTR-02M: Potential Vote Race Condition

Description:

By being able to arbitrarily change the currentSigningChainId and currentDomainSeparator, it is possible for a compromised owner to sabotage proxy vote submissions.

Example:

contracts/vote/VoteTracker.sol
120/// @notice Vote for the assets and reactors you wish to see liquidity deployed for
121/// @param userVotePayload Users vote percent breakdown
122/// @param signature Account signature
123function vote(UserVotePayload memory userVotePayload, Signature memory signature)
124 external
125 override
126 whenNotPaused
127{
128 uint256 domainChain = _getChainID();
129
130 require(domainChain == userVotePayload.chainId, "INVALID_PAYLOAD_CHAIN");
131
132 // Rate limiting when using our proxy apis
133 // Users can only submit every X blocks
134 if (proxySubmitters[msg.sender]) {
135 require(
136 lastUserProxyVoteBlock[userVotePayload.account].add(settings.voteEveryBlockLimit) <
137 block.number,
138 "TOO_FREQUENT_VOTING"
139 );
140 lastUserProxyVoteBlock[userVotePayload.account] = block.number;
141 domainChain = currentSigningChainId;
142 }
143
144 // Validate the signer is the account the votes are on behalf of
145 address signatureSigner = _hash(domainChain, userVotePayload, signature.signatureType)
146 .recover(signature.v, signature.r, signature.s);
147 require(signatureSigner == userVotePayload.account, "MISMATCH_SIGNER");
148
149 _vote(userVotePayload);
150}

Recommendation:

We advise this trait of the system to be adjustable via a more decentralized or blockchain aware way as it will cause all pending proxy transactions to fail beyond the adjustment.

Alleviation:

The setSigningChainId function has been omitted from the codebase rendering this exhibit null.