Audit · firm’s term: audit report
QuillAudits reviewed Memeswap on 25 Jun 2024: 19 findings, 0 critical; 17 marked fixed, 2 open.
Report hosted on quillaudits.com.
Trustblock does not review code.
Statuses are the security firm’s own, from its report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 0 | 0 | 2 |
| Medium | 1 | 0 | 2 |
| Low | 1 | 0 | 13 |
The MemeswapVault contract manages staking, enqueuing, renting, and claiming processes for the Memeswap protocol. Users can stake their Ether, join the queue, and claim rewards through various functions within the contract.A significant problem occurs with the trigger modifier, which attempts to dequeue items and send Ether to the queued user. If the recipient is a malicious contract that reverts the transaction through its receive or fallback function, the entire operation fails. This creates a Denial of Service (DoS) condition, halting the protocol and causing funds to be stuck.
A critical Denial of Service (DoS) vulnerability in the MemeswapVault contract. The vulnerability is related to the enqueue and dequeue logic, specifically how the dequeuePossible function interacts with the enqueue process, potentially leading to a state where the contract becomes unusable due to arithmetic underflow or overflow.The MemeswapVault contract allows users to enqueue ether and stake it. The staking process involves renting liquidity to newly deployed tokens. However, the logic in the dequeuePossible function can be manipulated to create a situation where the dequeue function can never be called successfully, leading to a critical DoS scenario.
The createPair() function is using && instead of ||, this will allow an actor to create a pair with just one whitelisted token. Instead both the tokens should be checked for being whitelisted to make sure that pairs are only created with whitelisted tokens.
In the ` MemeswapCollector::liquidate` function, the parameters amountAMin and amountBMin for removing liquidity are set to zero. This configuration allows for up to 100% slippage during liquidity removal, potentially resulting in significant losses or unexpected behavior.Impact Setting these parameters to zero means the contract does not enforce any minimum amount for the tokens received from liquidity removal. This could result in all of the liquidity being removed at unfavorable rates, potentially leading to a significant loss of funds or exploitation.
The initialize() function can be called multiple times by the owner and he can eventually change the vault once it is assigned. This possesses a centralization risk in the contract that could be abused by the owner. There is no condition in the initialize() function that would check if the contract has already been initialized.
DOMAIN_SEPARATOR variable should be declared as immutable as it is not getting changed once getting initialized in the constructor.
Certain functions in the Memeswap contracts perform state changes without emitting corresponding events. This reduces transparency and makes it harder to track these changes off-chain. The following functions should emit events:Functions to Update: • MemeswapTokenFactory.setMaxTax(uint256) (src/MemeswapTokenFactory.sol#100-102) • MemeswapVault.setParams(uint256,uint256,uint256,uint256) (src/MemeswapVault.sol#146-160) • MemeswapVault.setChadBar(uint256) (src/MemeswapVault.sol#332-336) • MemeswapVault.setValhallaFee(uint256) (src/MemeswapVault.sol#355-361)
The variable naming conventions and conditions in the lock() function should be consistent with the function name. Instead of using `unlocked`, use `locked` as that would make more sense with the function name.
There is no error handling on the _burn() function for the scenario when the `from` address has less balance than the `value`. This would break the flow of the execution.
The error handling in transferFrom() function is not done properly, it should also verify that allowance in `allowance[from][msg.sender]` is greater than the `value` else it should throw an error.
There is a lack of NatSpec documentations in all the contracts in the protocol which makes it less unreadable for the team as well as for future users of the protocol .
The array _params.taxes is passed to the `deploy()` function line 120, this `deploy()` expects this array to have at least 4 elements but the users can pass the array of any length. This length should be verified to prevent the execution state from breaking.
There are vulnerabilities related to missing caps and checks in the contract system, which can lead to overflow issues and unregulated fee structures. Key variables such as chadBar and valhallaFee lack proper limits, increasing the risk of exploitative behavior and unintended consequences. 1. Overflow Risk with Large chadBar Values: The MemeSwapVault::chadBar value, if set to an excessively large number, can cause the chad function to always return false due to overflow in the condition reserve > amount * chadBar. 2. Unintended Behavior with Zero chadBar: Setting MemeSwapVault::chadBar to zero causes the chad function to always return true, as reserve > amount * chadBar simplifies to reserve > 0. 3. Uncapped valhallaFee: The MemeSwapVault::valhallaFee can be set to values as high as 99%, leading to a disproportionate amount of remaining LP tokens being sent to the fee collector. This is problematic as it can be exploited to direct excessive amounts to the fee collector. 4. Max Tax Capping: The MemeswapTokenFactory::setMaxTax function sets the MemeswapTokenFactory::maxTax value without constraints, which could lead to excessively high tax rates being applied.
Certain variables in the Memeswap contracts should be marked as immutable or constant to improve gas efficiency and security. Immutable variables are set at deployment and cannot be changed, while constant variables are fixed and used directly in the contract's bytecode.
The check `if (msg.value == 0)` on line 112 is redundant as there is already a check `if (msg.value < _params.buyAmount)` on the very next line. Therefore the check on line 112 is just a waste of gas.
The condition `if (!initialized)` in `setLiquidator()`, `setTreasury()` and `withdrawToken()` functions are unoptimized and a waste of gas. The reason is there is no need to verify the initialization everytime `liquidator` or `treasury` is changed or tokens are withdrawn as the `initialized` variable is checked whenever the `collect()` or `liquidate()` function is called. Therefore the collector cannot be used until it’s initialized.
The length of the `urls` should be verified before they can be stored in the storage of the contract. Because according to the logic in the contract, the url array should have a maximum length of 10. This length is verified when updating the `urls` but it is not getting verified in the constructor.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (20)
350 projects reviewed · 459 reports · latest Apr 2025
See QuillAudits’s auditsSomething wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.
Tell us