# **Ramen Finance Audit Report Summary** ![LogoHorz-Light](https://hackmd.io/_uploads/HJRxusJFyg.png) **Date:** December 26, 2024 **Conducted by:** **Bogo Cvetkov (b0g0)**, Independent Security Researcher # **Table of Contents** [**1\. About b0g0** ](#_9jo5jkwu1wod) [**2\. About Ramen Finance** ](#_e2wmaviueewy) [**3\. Risk Classification** ](#_udoixqsdjw65) [3.1. Impact ](#_v8n12sy5kgqm) [3.2. Likelihood ](#_aovjsuf7syk) [3.3. Handling severity levels ](#_6znccm3pyoct) [**4\. Executive Summary** ](#_54atpm4daz33) [**5\. Disclaimer** ](#_djmm5vlq3g7m) [**6\. Findings** ](#_xkjr58nqyjcs) [**6.1. High Severity** ](#_pb7a748gs5gk) [6.1.1. Anyone can settle an auction externally and permanently DOS the settlement inside AxisManager and project conclusion ](#_tpuieir57xrc) [6.1.2. Anyone can abort an auction and DOS AxisManager settlement ](#_1mohk2xtqui8) [6.1.3. Anyone can steal the proceeds and refunds of any project, that are sent back to the AxisManager after settlement ](#_kanji2vk1psx) [6.1.4. The proceeds and refunds paid back after auction settlement are not accounted properly and would DOS project settlement/conclusion ](#_8cgs09b1b0xr) [6.1.5. During project refund wBera proceeds from auction and private sale payments are not handled and remain stuck in the contract ](#_x0rg96s1zkn1) [6.1.6. Conclusion could get DOSed in case of too many bids ](#_lsmov1ts5s3m) [6.1.7. Native presale payments are incorrectly transferred as wrapped assets, which might DOS project conclusion ](#_esdsvs5mjbcd) [6.1.9. Bidders can steal wBera reserves during bid submission and use it for their bids ](#_h1w2w5h681c8) [**6.2. Medium Severity** ](#_l4p4ppkpst0e) [6.2.1. Malicious tokens can be used as base tokens in deployed projects and potentially affect the Ramen protocol as well ](#_vftfpzaowmx) [6.2.2. Project could be created with invalid configuration ](#_cegxmw1ou3dq) [6.2.3. No actual deadline enforced when adding liquidity ](#_7iqxd7vbn0uo) [**6.3. Low Severity**](#_etv7auuz4z7j) [6.3.1. Potential signature replayability on another chain ](#_5tt9qtbekhpl) [6.3.2. Fee-on-transfer/rebasing tokens not supported ](#_at3j08eqttn1) [6.3.3. There might be unclaimable leftover amounts during private sale ](#_kkjsnxsnn8en) [6.3.4. Private sale buyers could get charged more than they have to ](#_jdovmnm1p7ux) [6.3.5. Restrict the DexManager to be called only by actually deployed project ](#_xdhlysubmf53) [6.3.6. BidId is not returned upon bid creation and makes it hard for bidders to query it ](#_z8sovbjott6f) [6.3.7. Conclude and bid periods overlap ](#_dqi9hsbgspa1) [6.4. Informational ](#_egm8h3rvzem1) [6.4.1. Insufficient validation ](#_qhmteq5amnrq) [6.4.2. Gas optimizations ](#_qyt242jfm0lw) [6.4.3. Emit events on important state changes ](#_b18iqlilm4j0) [6.4.4. Dex/AxisManager could be fetched from launchpad instead of being managed by separate variables in LaunchPadProjectPDS ](#_xo6w26j72ec8) ## # About b0g0 **Bogo Cvetkov (b0g0)** is a smart contract security researcher with a proven track record of consistently uncovering vulnerabilities in a wide spectrum of DeFi protocols. Constantly pushing the limits of his expertise, he strives to be a superior security partner to any protocol & client he dedicates himself to! # About Ramen Finance Ramen Finance is a Berachain-native token launchpad protocol powering liquidity bootstrapping and price discovery for new assets. # Risk Classification ![](data:image/png;base64,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IBVCCCGEEEIIkRdkkAohhBBCCCGEyAsySIUQQgghhBBC5AUZpEIIIYQQQggh8kKVMMJ+LjieeeaZ4JBDDgmOOOIImyKEWNn4/fffjSw46KCDgtVWW82mClE8zJgxI5g7d26w99572xQhRD558sknTX1cc801bYoQlY/x48cHF110UdCrVy+bUrgUtEH6xBNPBKeddlpwwAEH2BQhxMrGggULgilTpgStWrUKGjRoYFOFKB7ee++9YM6cOWrrhCgQxo4dG7Rt2zZYY401bIoQlQ/Kcc+ePYPzzjvPphQuBW2QooS2a9cu+Ouvv2yKEGJlg5Gjhg0bBjNnzgyaNWtmU4UoHvr16xcMHz7cjJQKIfJPrVq1gmnTpgVNmjSxKUJUPlq0aBF07tw56N69u00pXDSHVAghhBBCCCFEXpBBKoQQQgghhBAiL8ggFUIIIYQQQgiRF2SQCiGEEEIIIYTICzJIhRBCCCGEEELkBRmkQgghhBBCCCHyggxSIYQQQgghhBB5QQapEEIIIYQQQoi8IINUCCGEEEIIIURekEEqhBBCCCGEECIvyCAVQgghhBBCCJEXZJAKIYQQQgghhMgLMkiFEEIIIYQQQuQFGaRCCCGEEEIIIfKCDFIhhBBCCCGEEHlBBmkWxo0bF5x00knBwoULbUoqn332WXDttdcGv//+u01Zfvz666/Bo48+Gjz99NM2pYQwDIPevXsHN910U/DPP//Y1BL+/fff4NVXXw1GjRplUyon3Mebb74ZDB482KYUJryPBx98MOjWrVva97G0cN7PP/88uPrqq22KKC8///xzcP/99wedO3cO9txzz+Coo44KBg0aFMyZM8fuEQQLFiwIJk6caL+Vj+eee87IjMWLF9uU3KGsXHbZZcHNN99synq+WLJkiZEVzz77rE0RKxNfffVVcMghhwRffPGFTakY/v7772D06NHBjBkzbIoQIt+gV1Dnr7jiCptSAnmXX3650XOpv0IsV6ICV7C89tprYbVq1ey3spk3b1542223hQ0bNgy5Nbett9564TXXXBNGxozds2x+++23cI011jDHn3XWWWGkIJr0Z555JjzmmGPCdddd1+Rtttlm4aJFi0xeRTN37tywf//+YaQ4J+/lzjvvtLklRI18WKVKFZPPM3MMHz48POCAA8I111zT5F1yySU2p3Jx++23h4cddljyPnr16mVzlo233nor7Nu3b1ijRo3k82Vr1apVGBm94e+//273DMNffvnFpG2//fYp+9aqVSu8+OKLU5779OnTTR7vJDIubOrS88knn4QnnniiKcect379+jZn5SAyFs19z5w506aUn/Hjx4fbbbdduMoqq4TbbLONqUdPPfVU+MQTT4RXXXVVuOGGG4aNGjUK99lnn3CDDTYI77nnHntk7kSNelizZk1zrWeeeaZNzZ1HHnnEHFu1atVw3LhxNnXFgAyLFI9w//33N9fAhiwVK4ZLL700bN68uf1WNvPnzw/vv//+sFmzZsn3xbb66quHV155Zfjxxx/bPcPwn3/+MeX/1FNPTdmX7dBDDw1HjRpl9nH71qtXz+Rx7j/++MOkLy20m5SrHXbYIaxevbo576RJk2yuEIUL+sasWbPst+x89NFH4b333hu2bt06Wbco7++9957dIzfQ2dzxbJtuumk4cODAcPbs2XaPimPy5Mlh586dk/V9rbXWsjklPPvss6Y9Iv/555+3qaIysdVWW4U33nij/VbYFJVB6vjss8/COnXqJCv1q6++anNy588//zTGBsdjtDiD1DFs2DCTtzwNUsdPP/1kjBB+L51BSgOPok1+XACiUGBgkVdZDVKgg4CKxX1UlEHqGDlypDkv26qrrmrefSZ415tvvnly/4ceesjmlPDpp5+aPAzSdPlLA+WvW7du5rwySHPnr7/+MsYhygEG/ZgxY5LKtw/1BCPUvdcBAwbYnNz57rvvwnXWWcccTydFeaGzi2OReX4Hx4qEsu86t2SQrjjKa5A6lixZEq622mrJcvvKK6/YnNIgQy644ILkvnvvvXepdo260aJFC5Pfpk0bU38qAuQm5ZrzyiAVlYHyGKQO2ip0CFfH9t13X5tTNn///Xe41157JY+lc6m8Bm158WVCOoN0ypQpyY6kfLVJYtmoTAZpUbrsNmrUKIiUT/M5Ut6DZs2amc/lIaqExj10xIgRwUUXXRRESprNSdCkSRP7afkTCcZgo402st9K07ZtW+NeN3ny5KBly5Y2NUEkHIMGDRrYb5WXGjVqBE2bNrXfKhb/mbVr1868+0ysscYaKe9im222sZ9K2HTTTU3Zwb36v//9r01dNih/kWCx30QuRI1t0KVLl2DgwIGmDvE+DjrooKBq1dJij3qCG+8TTzxhvuPaW17q1atn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DvVnzpw5adtW5PsXX3yxQtpVIYQQhUFRGaQvvPBC0LBhw2DVVVcNqlSpktyqV68erL/++sG5555r9ywbjJ9NNtkkaNKkSXDjjTfa1ISR+vjjjwdt27YNatasGbRr1y5YsmSJza1YaLTffPPN4NRTTw2qVasWrLfeesFjjz1mc0t47733gsaNG5t7nzVrlk0NjLEyaNAgcw+1a9cObr75ZptTufjmm2+Cu+66K9h8882DWrVqpbyPpQVF6KSTTipVXtZZZ51yK0JDhw5NKW9rrLFGsNFGGwUffvih3aPi4FnwTjfddFPzLG6//XabU0LXrl2Dpk2bBrvvvrvpNFnZuOeee8x7pd7774X3TPrzzz9v9wxMJ02jRo2COnXqpOzLRlnYa6+9gj/++MPsi7G4yy67mHJ42WWXmbRlARnzzjvvBCeccIIpM8io7777zuYKkZmXX37ZyBjkul9m33rrLbtHblDe/ONXWWUVUw4vuOCCtJ2bywLt2aRJk4IjjzzStJ0bbLCB6Sj1oYN3iy22MPJt2LBhNlWIwua6664L6tevb+qPX59q1KgRbLjhhsGTTz5p9xRCZKKoDNK9997b9LqOHz/eKKOOhx56yIwe3nLLLTalbH777bfkKMj06dOTjXPdunWDjh07Bv/5z3/M9+UJ97DjjjsG/fr1M4IuEx988EFyZIX7dKy77rrBMcccY79VXhDoRx99dIWO+PE8H3jgAVNenn32WZsamBFoOjZyBWPl1ltvtd+CYK211jKjk19//XXQokULm1px8Cw6depkzp+JadOmmf9ffvllsHjxYvN5ZYIOHN7ryJEjjVIAVatWNXKB9P3228+kwdprr228C1DMUZAdBx98sBmpefHFF41SASjPzkPB7/hZWri2Vq1aBTvvvHPw559/2lQhymaPPfYwMoAOldVXX92mBsHll1+e0aMnHY8++qj9lIA2kjbk+uuvT9adioL2jA7c5s2bZ7xG6iedvoB3khCVgZ49e5o2xO8gptPlo48+Mp3Ihx12mE0VQmSiKF12W7dunVQuGfmg8S4vjFjcdtttRmG84YYbSjXO+++/v/20/GFkdNttt7XfSnPccccF7du3D84+++xgt912s6kJMKAZLavsMBKw66672m8Vy9Zbb20/JUatzjnnnJyVOozXt99+234LTLljFG55QkPH6GcmUDIZZaAj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EEKIvCCDVAghhBBCCCFEXpBBKoQQQgghhBAiL8ggFUIIIYQQQgiRF2SQCiGEEEIIIYTICzJIs/D2228HN954Y7B48WKbksrcuXODxx9/PPjzzz9tyvJjyZIlwcSJE4PXX3/dppQQhmHw4IMPBk888UTw77//2tQSSJsxY0bw6quv2pTKCfcxa9asYPz48TZFiOJj3rx5wdixY+23Ev7666/g3nvvDZ5++mmbIoQQQghR+Skqg/Tjjz8OTj/99GCdddYJqlSpktzq1KkTnHTSScZ4zBWMzD333DM477zzgssvv9wYffDmm28GPXv2DBo3bhw0bNgw6NWrl1EUlwfz588P7rvvvuCwww4LVl999WCPPfYI3nnnHZtbwosvvhh07tw5OOKII4J3333XpgbBK6+8EnTp0iWoX79+sNVWWwXjxo2zOZWLp556KjjzzDPNfTRr1szc77LC+xw8eHBw8MEHp5QVthYtWgTnn39+8PPPP9u9RWUCY+7cc88NmjZtmnyna665ZkrdyAXKWfXq1ZPnoL5TDpEBFQ2dX3379g0233zzYP311w/69+9vc0qgHpx66qnBkUceGXz55Zc2VayMfPLJJ6atW2ONNZLlk61u3brBKaecEjz33HN2TyHE8ub5558PjjvuuKBGjRop9RFZTlv0/vvv2z2FEBmJFPOC5bXXXgurVatmv+XOBx98EEYNNRak2SJhYXNy5/fffw8jJdYcHxml4b///mtzEtx9990mb7PNNgsXLVpkU5cP33//fRgpGub37rzzTptaQqR8hFWrVjX5kbJsUxP89ttvYWRgmbxLLrnEplY+fv311zBS1s199OrVy6YuO7zXCy+80JyXbYMNNgj//vtvmysKgTlz5ph3M3PmTJuSG5HRFq699trJd3vyySfbnNzYeeedk8eyTZs2zeYsP0466STzW23atLEpJTz66KMmb9VVVw0/++wzmyqKgUsvvTRs3ry5/ZY7H3/8sWkjXRl94403bI4QYllA/5s1a5b9lhuPP/54si7WqlXL6G5C5JOtttoqvPHGG+23wqYoXXa32GKLoEGDBubzuuuuG2y77bbmc3mgp+vZZ58NIkUh6Nevn+nt8mnVqpX9tPxhhJcR2Uzsv//+wS233BI8/PDDwXbbbWdTE9SsWTPYaKON7LfKCyPELVu2tN8qDt7rQQcdZL8FwX77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) ### ## Impact - **High** \- leads to a significant loss of assets in the protocol or significantly harms a group of users - **Medium** \- leads to a moderate loss of assets in the protocol or some disruption of the protocol’s functionality - **Low** \- funds are not at risk ## Likelihood - **High** \- almost certain to happen, easy to perform, or highly incentivized - **Medium** \- only conditionally possible, but still relatively likely - **Low** \- requires specific state or little-to-no incentive ## Handling severity levels - **Critical** \- Must fix as soon as possible (if already deployed) - **High** \- Must fix (before deployment if not already deployed) - **Medium** \- Should fix - **Low** \- Could fix - **Governance** \- Could fix # Executive Summary For the duration of 8 days **b0g0** has invested his expertise as a security researcher to analyze the smart contracts of **Ramen Finance** protocol and assess the state of its security. For that time a total of 24 issues have been detected, out of which **9** have been assigned a severity level of **High** and **3** a severity level of **Medium**. # Disclaimer Smart contracts are an experimental technology with many known and unknown risks. A smart contract security review can never verify the complete absence of vulnerabilities. This effort is limited by time, resources, and expertise. My evaluation of the codebase aims to uncover as many vulnerabilities as possible, given the above limitations! Subsequent security reviews, bug bounty programs and on-chain monitoring are strongly recommended! Bogo assumes no responsibility for any misbehavior, bugs or exploits affecting the audited code or any part of the deployment phase. **Overview** | Project | Ramen Finance | | --- | --- | | URL | <https://ramen.finance/> | | Platform | Berachain | | Language | Solidity | | Repo | <https://github.com/ramenfinance/ramen-finance/tree/master/contracts-ramenfinance/contracts> | | Commit Hash | 9ea1ab25ea82db306da2e9b0e193f1845e3e19fa | | Mitigation | 02e49a24b5ec04bacb5c1be3fb861a2459aa3183 | | Dates | 18 December - 26 December 2024 | **Scope** | Contract | Address | | --- | --- | | Launchpad.sol | \- | | LaunchpadProjectPDS.sol | \- | | AxisManager.sol | \- | | ProjectFactoryPDS.sol | \- | | DexManager.sol | \- | **Issue Statistic** | **Severity** | **Count** | | --- | --- | | High | 9 | | Medium | 3 | | Low/Informational | 12 | | **Total** | **24** | # Findings ## **High Severity** ### Anyone can settle an auction externally and permanently DOS the settlement inside AxisManager and project conclusion **Context**: **AxisManager.sol, LaunchpadProjectPDS.sol** **Description** : The **AxisManager** defines a **settle()** function that is meant to be called by projects when they get concluded. The code assumes that the **auctionHouse.settle()** function inside Axis protocol can be called only by the auction creator ( **AxisManager** ) which is not correct. And this is the source of an issue. It would be a good idea to **restrict AxisManger calls only to project launchpads** and not allow arbitrary calls from anyone. **Recommendation:** It would be a good approach here to take advantage of [the callBack mechanism provided by Axis:](https://axis.finance/developer/guides/overview#callbacks) These are a set of callbacks invoked at a target contract defined by the creator during auction creation. Those callbacks are called by Axis during different flows - abortion, cancellation, settlement etc. They allow the auction creator to react to them in certain ways. In this particular case you can use the **onSettle()** callback invoked once an auction is settled, it would call a Ramen contract (probably **AxisManager)** which would execute the respective logic from **AxisManger.settle().** This way the protocol would be able to handle the settlement safely regardless if it was done through the AxisManager or externally. It is very important to thoroughly test out the flow after the architectural changes to make sure everything works as expected and also go through the docs in detail to make sure you have a good understanding of Axis so that you would develop the code with the appropriate assumptions **Resolution:** **Fixed -** The team has switched to the callback mechanism of handling the auctions ### Anyone can abort an auction and DOS AxisManager settlement **Context**: AxisManager.sol **Description**: [According to AxisDocs](https://axis.finance/developer/guides/batch/abort): “ _After a batch auction concludes, there is a dedicated settlement period in which the auction seller is exclusively able to settle the auction lot. Subsequent to this, anyone may abort the auction_ ” Meaning that after the dedicated settlement period, anyone can abort an auction, which would change the **lotId** status to **LotStatus.Settled** and any subsequent calls to **auctionHouse.settle()** would revert and as result project conclusion would be **DOSed**. **Recommendation:** Similar to a previous issue it is recommended here to leverage [the callBack mechanism provided by Axis:](https://axis.finance/developer/guides/overview#callbacks) Upon abort [Axis invokes the **onCancel** callback](https://github.com/Axis-Fi/axis-core/blob/master/src/BatchAuctionHouse.sol#L511-L522) **-** use it in AxisManager to handle the relevant state transitions and also the refunded baseTokens that are sent back to the seller. It is very important to thoroughly test out the flow after the architectural changes to make sure everything works as expected and also go through the docs in detail to make sure you have a good understanding of Axis so that you would develop the code with the appropriate assumptions **Resolution:** **Fixed -** The team has switched to the callback mechanism of handling the auctions ### Anyone can steal the proceeds and refunds of any project, that are sent back to the AxisManager after settlement **Context**: AxisManager.sol **Description**: The **AxisManager.settle()** incorrectly assumes it can only get called by a project, while in fact it can get called by anyone. All project auctions are created through **AxisManager**, which makes it the owner for the auctions(lotId) of all projects. And since there is no validation in **settle(),** anyone can call it providing the **lotId** for any project and stealing the funds **Recommendation:** Create a mapping that stores the **project** to which a **lotId** belongs and validate inside **settle()** that the caller can only be the project for the respective lotId. And a general advice would be to validate all the calls inside **AxisManager** \- this way you would encapsulate the system to be used internally by trusted contracts and reduce the attack surface that is introduced by arbitrary callers **Resolution:** **Fixed -** A mapping was implemented that restricts each lotId to its respective project ### The proceeds and refunds paid back after auction settlement are not accounted properly and would DOS project settlement/conclusion **Context**: AxisManager.sol **Description**: Problem is that the calculation is not based on the actual balances received in the contract, but rather it assumes that those balances have been sent, which is not correct. For example Axis deducts a fee from **totalIn_** ( the amount of paid quote tokens) before sending it to the seller. This can be verified by [taking a look at the implementation of the function in their contracts](https://github.com/Axis-Fi/axis-core/blob/a2443d27cb3e1c51098747693e20547537f831b5/src/BatchAuctionHouse.sol#L399-L411). But since **totalIn_** is used by **AxisManager**, it would either be spent from the proceeds of another project or it will just DOS if there are not enough balances. **Recommendation:** Since settlement is permissionless in Axis and anyone can call it, using a before/after pattern with balaceOf() is not an option. You can again use the callback mechanism to handle the assets once they are sent to the protocol. [Upon settlement Axis calls the **onSettle()** callback and provides to it the exact amount](https://github.com/Axis-Fi/axis-core/blob/a2443d27cb3e1c51098747693e20547537f831b5/src/BatchAuctionHouse.sol#L448-L458) of quote & base tokens that have been sent to the seller (AxisManager). Use those values when sending out the assets to the appropriate project **Resolution:** **Fixed -** The parameters provided by Axis in the callback are used ### During project refund wBera proceeds from auction and private sale payments are not handled and remain stuck in the contract **Context**: LaunchpadProjectPDS.sol **Description**: The **concludeProject()** function is used to settle the axis auction and then transfer out all the payment and deposited base tokens from the contract. The problem here is that even if the project should be refunded, the axis auction is still successfully concluded - meaning that the **wBera** paid and the not-sold **baseTokens** during the auction are transferred back to the **seller** (which is the **LaunchpadProjectPDS** contract**).** All **baseTokens** are transferred out. However not all assets in the contract are handled in case of refund and without any mechanism to take them out, they remain stuck. **Recommendation:** Make sure to properly handle all assets and also warn the users that the baseTokens they paid for might get revoked and the responsibility for refunds lies in the protocol/project owner. **Resolution:** **Fixed** ### Conclusion could get DOSed in case of too many bids **Context**: LaunchpadProjectPDS.sol **Description**: The **concludeProject()** function settles the auction through the AxisManage. It always takes the total number of bids and provides them to be resolved in the **settle()** function. Currently the project launchpad does not support incremental settlement and always tries to settle all bids at once, which will revert if the bids to process are too much. **Recommendation:** Similar to previous issues the recommendation here would be to use the callback mechanism of Axis, so that wherever the settlement is done ( either through Ramen or directly from Axis) the protocol would only have to handle the settlement result ( **onSettle()** callback) - e.g **conclusion** should **not depend** on calling **settle()** **directly.** When you implement the callbacks make sure to consider the case described above **Resolution:** **Fixed** ### Native presale payments are incorrectly transferred as wrapped assets, which might DOS project conclusion **Context**: LaunchpadProjectPDS.sol **Description**: The **collectFee()** function deducts a fee from **presaleSold** assets, which is paid as native Bera tokens**.** However they are transferred out as wrapped assets, although they never got wrapped. As a result those fees would either get deducted from the proceeds from the auction, or if the wBera balances are insufficient it would revert. **Recommendation:** Wrap **presaleQuoteFee** to **wBera** before sending it out. **Resolution:** **Fixed** ### Improper fee & runway calculation might DOS project conclusion **Context**: LaunchPadProjectPDS **Description**: In **concludeProject()** the **fee** and **operationRunway** % are calculated based on the amount of tokens sold during the Axis auction. The problem is that there is no guarantee that those **baseTokens** are available in the contract - since they have been sent to Axis, while the rest that are sent to the project might have been sold at private sale. Since actual balances are never checked, this creates a scenario where the calculated fees and amounts for liquidity are invalid and lead to DOS. **Recommendation:** Always make sure to check the actual balances in the contract and if lower than the calculated amounts, cap them down. This also applies to the calculated **baseFee** executed in **\_collectFee() -** make sure that balances are present, before sending them out. It is a general advice for all token transfers that are done Also make sure to properly test out scenarios with different fees in order to capture potential edge cases **Resolution:** **Fixed** ### Bidders can steal wBera reserves during bid submission and use it for their bids **Context**: LaunchpadProjectPDS **Description**: The bid submission function is used to submit bids to buy baseTokens with quote tokens (**wBera**). The bidders send **native Bera**, which gets wrapped and transferred to the Axis manager to create the bid. Problem here is that **msg.value** is not properly validated before transferring wBera from the project to AxisManager. This strips the protocol from its **wBera** reserves or potentially in case of a follow-up contract upgrade it could allow theft of deposits. **Recommendation:** Add a check that makes sure that **msg.value == bp.amount** **Resolution:** **Fixed** ## **Medium Severity** ### Malicious tokens can be used as base tokens in deployed projects and potentially affect the Ramen protocol as well **Context**: **Launchpad.sol** **Description** : The Launchpad acts as a factory contract that deploys project contracts, which have the goal of distributing the project specific tokens (e.g baseTokens) through various mechanisms (airdrops, pre-sales and auctions). As such the contract is expected to be as general as possible, allowing every project to deploy its own token. This means that there is no token whitelisting and anyone can provide any contract that adheres (superficially) to the ERC20 interface. This seems like an inherent risk to the system, that should be isolated only to the deployed project contracts - e.g a malicious baseToken should only affect/compromise the project it is deployed for. Additionally it should be considered that a lot of the Ramen contracts are upgradeable, meaning their logic can change, so it is imperative to **NEVER assume baseTokens would work as intended** (as a standard ERC20). **Recommendation** The most straightforward approach would be to implement token whitelisting. However given that the idea of the Launchpad is to deploy any token - such safeguard might be impossible. In that case it is recommended to explicitly warn the users (mainly buyers of project tokens) that the project might use malicious tokens and manipulate any stage (airdrops, pre-sales, bids) so that they are well aware of the risks. Also be very cautious when you write/upgrade logic that involves such arbitrary tokens, especially when it can affect the protocol itself. As developers **NEVER** assume such tokens would behave properly - it is a good way not to shoot yourself in the foot and write safer code Make sure that the ramen treasury can’t get DOSed in any way by malicious tokens being sent. The recommendation applies to any arbitrary address that the creator can provide to the project config. **Resolution:** **Acknowledged -** Team Comments: _“Warn Administrator to not accept any upgradable token / suspicious token”_ ### Project could be created with invalid configuration **Context**: Launchpad.sol **Description**: The Launchpad is the contract that is used by authorized callers to deploy new PDS & FPS projects. In order to be deployed each project includes a set of parameters that the caller must provide as structs ( **ProjectFPS** / **ProjectPDS ).** The fields of those structs are very important since they get used throughout the whole deployment flow and finally get passed to the initializer of the created project contract. It is very important that all of the fields in the parameter struct get validated to make sure that projects will not be initialized with invalid or malicious state. The launchpad contract already validates the provided input parameters, but the problem is that not all important fields get checked and hence some invalid configurations could be created. **Recommendation**: Consider validating all of the fields of the provided project launch configuration structs **Resolution:** **Fixed -** Team Comments: _“There will be no limit on the bid price”_ ### No actual deadline enforced when adding liquidity **Context**: DexManager.sol **Description**: Inside the **\_addLiquidity()** function the uniswap router is being called to provide liquidity to the freshly created pool. Currently the deadline is calculated on chain - as result **block.timestamp** will always be the timestamp of when the transaction gets executed, meaning the deadline will always be valid since 10 minutes are counted starting when the transaction is executed. **Recommendation:** Deadline should be calculated by the off-chain nodes and provided as a parameter to the **addLiquidity()** function. Never calculate it in the contract itself. **Resolution:** **Acknowledged -** Team Comments: _“Hard to implement on PDS: couldn't pass trusted data from offchain to project on settle. Since we're implementing a launchpad project we actually don't want to enforce the deadline and only want to bypass the deadline check”_ ## **Low Severity** ### Potential signature replayability on another chain **Context**: Launchpad.sol **Description**: Currently the launchpad uses signatures to validate that a caller can deploy an FPS or PDS project. The only parameters included in the signature are sender & project. This might be problematic in case the team decides to deploy the contracts on another EVM chain using the same signer. Additionally the signature lacks a deadline, meaning it never expires and so the sender can use it at any time in the future. It is considered a best practice to always issue signatures that are specific in order to prevent any potential replayability scenarios. The most important fields to include in a signature are: - chainId - contractId - deadline Additionally consider if the signature should be provided for a particular type of project ( FPS/PDS) and if so, then add that to the signature as well **Recommendation:** Consider exploring the [**EIP712** signatures by OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol) ,which is the safer way of using signatures - it includes chainId & contractId when signing messages along with a few other security mechanisms. You should add the deadline parameter It would require a bit more code changes, but OZ already took care of lots of the details. If you decide to stick with the current approach consider including deadline, chainId and contract in the signature to make sure it is used exactly as it is supposed to. **Resolution:** **Acknowledged -** _The team will consider this in case they deploy to another chain in the future_ ### Fee-on-transfer/rebasing tokens not supported **Context**: General **Description**: The Protocol is not supposed to work with non-standard tokens, such as tokens that withhold fee upon transfer or dynamically change their balances(LIDO stETH). Launching projects with such tokens will either fail or deploy them with invalid state **Recommendation:** Make sure to add comments in the code and the protocol docs to warn the users that suck tokens are not supported **Resolution:** **Acknowledged** ### There might be unclaimable leftover amounts during private sale **Context**: LaunchpadProjectPDS.sol **Description**: The **privateSale()** function checks that the amount that the caller provides cannot be bought for 0 price. Each buyer is pre-approved by a presale commit hash and has a maximum amount ( presaleCap) of tokens he/she can buy during pre-sale. Currently there exists the scenario that he might provide such an amount, so that the leftover between ( **\_presaleCap** \- **received\[msg.sender\].presale)** might not be enough to satisfy the condition in the above check and hence it won’t get sold. Such amounts would be small, hence the low severity, but this would apply for all projects and all buyers in private sale so it makes sense to fix this. **Recommendation:** Add a check at the end that verifies that after the purchase the leftover amount will not be too small to get sold. **Resolution:** **Fixed** ### Private sale buyers could get charged more than they have to **Context**: LaunchpadProjectPDS.sol **Description**: The **privateSale()** function allows more than the required native tokens to be sent for the purchase. Meaning that if the user has to pay 10 native tokens, but sends 11 he won’t get the 1 extra token back. Considering that the price is hardcoded and no oracle is used here, cost prediction is very straightforward so it would be better to revert in case **msg.value** is more than it has to **Recommendation:** Consider changing the above check to use **msg.value ==**, instead of **\>=** You can also add a convenience function **getCost()** that can calculate the exact price for the buyer before **privateSale()** is called **Resolution:** **Acknowledged -** _Team Comment: “Since there are some precision loss, there are cases when buyer must provide higher amount, this is intended”_ ### Restrict the DexManager to be called only by actually deployed project **Context**: DexManager.sol **Description**: The **addLiquidity()** function of the **DexManager** is used to create a Uniswap pool for a project and provide tokens to it as liquidity. The function expects that the caller is a Launchpad project since it wraps **msg.sender** in **ILaunchpadProject()** interface. It’s recommended here to also check that msg.sender is an **actually deployed** project by the **Launchpad**. This would reduce the attack surface, since it will not allow arbitrary contracts that mimic **ILaunchpadProject to** call it directly. **Recommendation:** You can add **projectId** as input to the function and validate it. Alternatively you can create a reverse mapping in the LAUNCHPAD (address => projectId) and query it. **Resolution:** **Acknowledged** ### BidId is not returned upon bid creation and makes it hard for bidders to query it **Context**: AxisManager.sol **Description**: The **submitBid()** function is used to participate in an Axis auction. The bid is created by calling **auctionHouse.bid()** which returns the id of the newly created bid after execution. This id is later provided to the **claimBids()** function to withdraw the bids to their creators The issue here is that the returned id is never captured into a variable and returned by the **submitBid()** function. The function is called by **LaunchpadProjectPDS.** This makes it difficult to track which id belongs to which bidder and hence can hinder the claiming process **Recommendation:** Consider returning the **bidId** from **submitBid()** and also emit an event for it, so that the bidders can store/query it after the function call and use it to claim the bids later or get info about them. You can also store that in a mapping. **Resolution:** **Acknowledged** ### Conclude and bid periods overlap **Context**: LaunchpadProjectPDS.sol **Description**: **concludeProject()** start period is defined like this: ```solidity require( block.timestamp >= _auctionEnded(project.launchTime), 'concludeProject: project is still open' ); ``` **Recommendation**: Consider updating it like this: ```solidity block.timestamp > _auctionEnded(project.launchTime) ``` Replace **\>=** with **\>**, this ensures that the project cannot be concluded while bids are still possible- e.g **inBidPhase.** **Resolution:** **Fixed** ## **Informational** ### Insufficient validation **Context**: General **Description**: Validation should be more strict in multiple places throughout the contracts. Proper validation reduces the chance of accidental mistakes: - **LaunchPad.sol:** - Inside the **initialize()** function validate that: - The provided addresses are not **address(0)** - Define reasonable boundaries for the periods - the **period** state variable defines the different time periods used by the projects and is set by the admin role. - Inside **setPenaltyThreshold** define a max limit of 1e6 (100%) - Inside **setDexManager()/setAxisManager()/setProjectFactoryFPS()/ setProjectFactoryPDS()/setTimelockFactory()/** validate that the newly provided address is not **address(0)** - Inside **setRamenTreasury()** validate that the newly provided treasury address is not **address(0)** - **ProjectFactoryPDS.sol:** - Inside the **constructor()** validate that the provided addresses are not **address(0).** - Inside **setService()** check that the provided parameter is not **address(0)** - Inside **create()** validate that owner is not **address(0)** - **DexManager.sol:** - In the constructor make sure that **\_wBERA** is not **address(0)** - **AxisManager.sol:** - In the constructor check that the _**owner** and **\_auctionHouse** are not **address(0),** also make sure that **duration** is above 0 since Axis requires it - Inside **setMinFillPercent** set an upper limit of **100e2**, since this is the max allowed by Axis or else it would revert. - Inside **submitBid()** check that **bidder** is not **address(0)** - **LaunchpadProjectPDS.sol:** - Inside the **initializer()** check that the provided **service & \_wBERA** parameters are not **address(0)** - Inside **setAxisManager() / setDexManager()** check that parameters are not **address(0)** - Inside **setProjectFee()** add the same checks implemented in **Launchpad.\_isValidDetails() -** to make sure the ratios are respected. **Recommendation**: Consider implementing the above recommendations **Resolution:** **Partially resolved-** the team has implemented the bigger part of the proposed validations - in the most important functions. ### Gas optimizations **Context**: General **Description**: **Recommendation**: All issues related to gas are collected here to keep the report focused and easy to read: - **LaunchPad.sol:** - Inside **\_checkAllowance()** if **baseSupply** is 0 you can skip the **saleSupply** calculation and just assign it to zero like this: - uint256 saleSupply = isAirdropOnly ? 0 : baseSupply \* 2 - (baseSupply \* operationRunway) / FEES_DECIMALS; - **DexManager.sol:** - The **wBERA** variables could be defined as immutable - The internal **\_pow()** function is not used, consider removing it to reduce contract size - **LaunchpadProjectPDS.sol:** - Inside **reserveAirdrop()** check and return early in the beginning if **airdropRoot** is 0 in order to prevent unnecessary operations . - Inside **reserveAirdrop()** move the following check at the top in order to save some gas: - require(!isReserved\[\_tokenOwner\], reserveAirdrop: already reserved the airdrop'); **Resolution:** **Fixed** ### Emit events on important state changes **Context**: General **Description**: The following state changing functions do not emit events: **Launchpad.sol:** - **setPeriod()** - **setRamenTreasury()** - **setPenaltyThreshold()** - **setDexManager()** - **setAxisManager()** - **setProjectFactoryFPS()** - **setProjectFactoryPDS()** - **setTimelockFactory()** - **setSignerAddress()** **ProjectFactoryPDS.sol:** - **setImplementation()** - **setService()** **AxisManager.sol:** - **setAuctionDuration()** - **setMinFillPercent()** - **setMinBidScaler()** **LaunchPadProjectPDS.sol:** - **reserveAirdrop()** - **privateSale()** - **setRoot()** - **setProjectFee()** - **setSlippage** - **setVester()** It is considered a best practice to emit events that mark changes in the state of the smart contract. It provides transparency to anyone observing how the contract is configured and also allows querying by offchain listeners when that is necessary. **Recommendation**: Consider emitting relevant events in the above functions **Resolution:** **Partially resolved -** the team has added events to the most important functions ### Dex/AxisManager could be fetched from launchpad instead of being managed by separate variables in LaunchPadProjectPDS **Context**: LaunchpadProjectPDS.sol **Description**: The **Launchpad** has the dex/axisManager variables defined, which are also used by **LaunchPadProjectPDS** upon initialization. Currently there are separate setter functions for those variables both in Launchpad & LaunchPadProjectPDS. Consider if it makes sense to remove setters in LaunchPadProjectPDS to streamline the update and syncing process. **Recommendation:** Since it is expected that those be synchronized across the contracts, consider if it makes sense to only have setter function inside the **Launchpad**, so that **LaunchPadProjectPDS** only queries it and when they get updated, the change will be reflected immediately in all projects, instead of having to go through each one separately. Also any configuration discrepancies could be prevented this way. **Resolution:** **Acknowledged**