CoinFabrik/scout-substrate huggingface dataset:
Audit finding: Missing validation in pull_ledger_diff
Project: MantaNetwork
Auditor: Veridise
Location: pallets/manta-sbt/src/lib.rs
Impact: Warning
Vulnerability class (audit): Data Validation
Vulnerability class (Scout): Error Handling and Validation
Status: Acknowledged

4.1.3 V-MSBT-VUL-003: Missing validation in pull_ledger_diff

Severity: Warning
Type: Data Validation
Commit: ceb9e46
Status: Acknowledged
File(s): pallets/manta-sbt/src/lib.rs
Location(s): pull_ledger_diff

pull_ledger_diff takes as input a Checkpoint which is a struct of two fields receiver_index and sender_index and pulls receiver data from the ledger starting at receiver_index up till at most receiver_index + PULL_MAX_RECEIVER_UPDATE_SIZE. However, there is no check that this sum cannot overflow for both the sender and receiver index in pull_receivers and pull_receivers_for_shard.

Impact: If the code is compiled without the --release flag then a malicious user could crash the node by passing in bad values. If it is built with --release then the call will be reported as successful and no senders or receivers will be returned. However, if a benign end user is calling the API with incorrect indexes it might be better to return an error informing them that the index is invalid.

Recommendation: We recommend adding bounds checks to be safe and to return an Error.

Developer Response: The developers acknowledged the issue and will fix this prior to release.

Summary: Missing bounds check in pull_ledger_diff could allow overflow and node crash.
Audit finding: Off-by-one error in to_private
Project: MantaNetwork
Auditor: Veridise
Location: pallets/manta-sbt/src/lib.rs
Impact: Warning
Vulnerability class (audit): Logic Error
Vulnerability class (Scout): Arithmetic
Status: Acknowledged

4.1.4 V-MSBT-VUL-004: Off-by-one error in to_private

Severity: Warning
Type: Logic Error
Commit: ceb9e46
Status: Acknowledged
File(s): pallets/manta-sbt/src/lib.rs
Location(s): to_private

The manta-sbt pallet has a user-callable extrinsic, to_private, which allows users to mint reserved SBT tokens. To facilitate minting tokens, the pallet maintains a mapping from users to an interval [l, u] where l ≤ u and l and u refer to minimum and maximum asset ids that can be minted by the user. The function does two things. First, it mints an asset with id l and then updates the interval to [l + 1, u]. If l + 1 > u, it removes the user from the map since this indicates they don’t have any more user ids to reserve.

There is an edge case where l = u = 2^128 - 1 where this function’s behavior is incorrect. In this case, the extrinsic will revert because l + 1 would result in an overflow as it is of type u128. However, this prevents the user from minting a token reserved for them.

Currently this should not be a problem because it is unlikely that all 2^128 ids will get reserved anytime soon.

Impact: A user may not be able to mint an SBT token reserved for them.

Recommendation: We recommend adding an edge case for when l = 2^128-1. In that case, the token should be minted and user removed from the map.

Developer Response: Not to be resolved. What the auditors point out is correct that the last id will not get minted; however, the resolution is unnecessary as once we hit this edge case the entire zkSBT protocol is unable to function. Furthermore, this value is extremely large and unlikely to ever be reached.

Summary: Off-by-one error in to_private may prevent users from minting reserved tokens.
Audit finding: Unnecessary Storage Variable
Project: MantaNetwork
Auditor: Veridise
Location: pallets/manta-sbt/src/lib.rs:382
Impact: Warning
Vulnerability class (audit): Gas Optimization
Vulnerability class (Scout): Code Quality
Status: Fixed

4.1.5 V-MSBT-VUL-005: Unnecessary Storage Variable

Severity: Warning
Type: Gas Optimization
Commit: ceb9e46
Status: Fixed
File(s): pallets/manta-sbt/src/lib.rs
Location(s): 382

The storage variable UtxoAccumulatorOutputs keeps track of all Merkle roots generated by manta-sbt; however, this variable is unnecessary. It seems to be taken from the manta-pay pallet which uses it to keep track of previous Merkle roots so that when users provide membership proofs for asset transfers, the ledger can check that the root provided was a legitimate one.

However, the tokens in manta-sbt are non-transferable so there isn’t any logic which should use it. In particular, the only two places which use this storage variable are in the functions has_matching_utxo_accumulator_output and register_all. The former will never be invoked in manta-sbt because the asset is non-transferable. The latter just adds a newly created Merkle root to UtxoAccumulatorOutputs.

Since this storage variable keeps track of every root generated, it is a non-trivial amount of storage to keep on-chain. Moreover, every minting transaction, namely to_private and mint_sbt_eth, will incur an extra cost of writing to storage, which is unnecessary.

Impact: Unnecessarily high transaction fees for every mint transaction and bloated storage.

Recommendation: We recommend removing this storage variable.

Developer Response: This has been fixed in the following commit.

Summary: Unnecessary storage variable increases transaction fees and storage usage.
Audit finding: Missing validation when setting mint info
Project: MantaNetwork
Auditor: Veridise
Location: pallets/manta-sbt/src/lib.rs
Impact: Info
Vulnerability class (audit): Data Validation
Vulnerability class (Scout): Error Handling and Validation
Status: Acknowledged

4.1.6 V-MSBT-VUL-006: Missing validation when setting mint info

Severity: Info
Type: Data Validation
Commit: ceb9e46
Status: Acknowledged
File(s): pallets/manta-sbt/src/lib.rs
Location(s): new_mint_info, update_mint_info

When setting metadata for a mint type, the functions new_mint_info and update_mint_info set the start_time and end_time associated with the mint type. The functions validate the start and end times by making sure start_time < end_time. However, they don’t check whether those make sense with respect to the current time. In particular, it seems like you would want now < end_time.

Impact: Setting end_time < now means that nobody can mint for that mint type until it gets changed again.

Recommendation: We recommend adding the additional validation which shouldn’t be too expensive.

Developer Response: This is intended behavior for now. The only way to pause a mint is to set end_time < now. This however could be improved by using an Option<> and remove the need for this invariant. This is low priority, but we could fix it in the future.

Summary: Missing validation allows minting periods to be set in the past, blocking minting.
Audit finding: Missing benchmarking for the lockdrop precompile dispatch
Project: Astar
Auditor: Security Research Labs
Location: precompiles/dispatch-lockdrop/src/lib.rs:88-90
Impact: Info
Vulnerability class (Scout): Weight Management
Status: Closed [4] [Online].Available: https://github.com/AstarNetwork/dappstaking-v3-audit/issues/7#issuecomment-2034174383.

3.2.1 Missing benchmarking for the lockdrop precompile dispatch
Attack scenario
Location
Tracking
Attack impact
Severity
Status
Static ref_time used for weight calculation leading to underestimation
of the weights can enable an attacker to perform denial of service
precompiles/dispatch-lockdrop
[2]
An attacker may spam and conduct denial of service attacks cheaply in
comparison to the actual weight_to_gas price
Info
Closed [4]
The precompile dispatch-lockdrop has un-benchmarked weight_to_gas estimation with
ref_time configured to 1_000_000_000 [5].
// Record a fixed amount of weight to ensure there is no free execution
handle.record_cost(Runtime::GasWeightMapping::weight_to_gas(
    Weight::from_parts(1_000_000_000u64, 0),
))?;
This estimation doesn’t reflect the actual runtime environment and can aid an attacker to spam
the chain.
We suggest to appropriately benchmark the precompile dispatch to reflect the accurate
weight_to_gas estimation for ref_time and POV_size.
The issue was acknowledged by the Astar team and remediation is currently in progress
through collaboration with the Frontier team [6]

Summary: Underestimated weight_to_gas estimation due to missing benchmarking allows attackers to perform denial of service attacks.
Audit finding: Unbounded call length limit in lockdrop dispatch call
Project: Astar
Auditor: Security Research Labs
Location: precompiles/dispatch-lockdrop/src/lib.rs:74,104
Impact: Low
Vulnerability class (Scout): Denial of Service (DoS) and Spamming
Status: Closed [7] [Online].Available: https://github.com/AstarNetwork/Astar/pull/1208.

3.2.2 Unbounded call length limit in lockdrop dispatch call
Attack scenario
Location
Tracking
Attack impact
Severity
Status
An attacker may create multiple nested calls bloating the call_length
before call decoding
precompiles/dispatch-lockdrop
[3]
Unbounded call length can aid an attacker to cause heap overflow when
call data is moved to the vector
Low
Closed [7]
The precompile dispatch call uses the UnboundedBytes [8] type without any call_length being
set for the call object parameter. During runtime-call decoding, a stack overflow is prevented
through usage of DecodeLimit [9] however, a heap overflow might occur even before decoding
if an unbounded call with large call_length is moved into the u8 vector.
An attacker can use this to create multiple nested calls bloating the call_length and cause heap
overflow even before call decoding.
We recommend using BoundedBytes<call_length> instead of UnboundedBytes. A best practice
implementation from Moonbeam may be adopted for setting CallLengthLimit similar to
GetProposalLimit [10] and implementing additional guard condition for call_length validity
similar to proposal_length [11] before decoding the call for additional safety.

Summary: Unbounded call length in dispatch call allows attackers to cause heap overflow and perform denial of service attacks.
Audit finding: Weight calculation
Project: Astar
Auditor: Zellic
Impact: Low
Likelihood: Low
Vulnerability class (audit): Coding Mistakes
Vulnerability class (Scout): Weight Management
Status: The Astar team acknowledged this issue and stated that the gas weight currently being charged for one read is equivalent to a read of length 80 bytes. They also pointed out that the MetadataName and MetadataSymbol are bounded by the AssetsStringLimit config variable, which is set to 50 bytes. Therefore, charging for one read is fine in this instance.

All the assets pallet functions exposed by the chain extension are weighted with a constant amount. The weight of some operations is charged using the same quantity that the assets pallet benchmarks have computed. However, other operations only charge the weight of one runtime database read operation — T::DbWeight::get().reads(1_u64).
Two functions, MetadataSymbol and MetadataName, operate on a variable amount of data, but they also only account for one runtime database read operation.

Summary: Constant weight for functions, ignores variable data in MetadataSymbol & MetadataName.
Audit finding: Static calculation of weights for the claim_reward extrinsic enables DoS attack vector
Project: Bifrost
Auditor: Oak Security
Location: pallets/lend-market/src/lib.rs:782-800
Impact: Major
Vulnerability class (Scout): Weight Management
Status: Resolved

1. Static calculation of weights for the claim_reward extrinsic enables DoS attack vector
Severity: Major
The claim_reward function, defined in pallets/lend-market/src/lib.rs:782-800, iterates over all the existing markets to collect rewards from each of them. However, since the number of registered markets is not bounded, the execution could exceed the computation limit if too many markets are registered. Since the calculation of the extrinsic weights does not take into account the cardinality of the markets, the fee charged to the origin will be uncorrelated with the actual computational resource usage. This leads to a situation where the execution of multiple claims within the claim_reward extrinsic will cost the same as a single claim done with the claim_reward_for_market extrinsic. Consequently, attackers could leverage this behavior to overload chain nodes by executing claim_reward on multiple markets paying a smaller fee, potentially allowing a denial-of-service attack.

Summary: Static weight calculation in claim_reward allows potential DoS due to unbounded market iterations.
Audit finding: Price feeder centralization risks
Project: Bifrost
Auditor: Oak Security
Location: pallets/prices/src/lib.rs:120-143
Impact: Minor
Vulnerability class (Scout): Error Handling and Validation
Status: Acknowledged

2. Price feeder centralization risks
Severity: Minor
In the prices pallet, the FeederOrigin can set arbitrary emergency prices by executing the set_price and reset_price extrinsics defined in pallets/prices/src/lib.rs:120-143. However, prices are not validated before being stored and every value is accepted.
As a consequence, this could lead to the following scenarios:
1. Privilege abuse: An attacker may get access to the private key of the FeederOrigin. He can then use the account to manipulate prices, for example by setting the price for all assets to a small value, which would allow the attacker to liquidate all users at their loss.
2. Input error: Since the provided Price is not validated, incorrect values could be provided as input and stored in the contract. Even a Price equal to zero is allowed.
We classify this issue as minor since only a privileged account can perform the aforementioned operations.
Recommendation
We recommend performing validation on the provided prices. For instance, there could be a maximum allowed delta per time unit, such that a price of zero would not be accepted.
While this does not fully resolve the centralization issue, privilege abuse would be more involved and require multiple transactions over a longer time span. This would allow operators and users to react.
Status: Acknowledged
The client states that they use multi-signature accounts for privileged roles to reduce centralization risks.

Summary: Price feeder allows unvalidated emergency prices, risking privilege abuse and input errors.
Audit finding: Multiple foreign_asset_id can be mapped to the same asset_id
Project: Bifrost
Auditor: Oak Security
Location: pallets/prices/src/lib.rs:149-157
Impact: Minor
Vulnerability class (Scout): Error Handling and Validation
Status: Resolved

3. Multiple foreign_asset_id can be mapped to the same asset_id
Severity: Minor
In pallets/prices/src/lib.rs:149-157, the set_foreign_asset extrinsic permits the UpdateOrigin origin to establish a mapping within the pallet, associating a foreign_asset_id with an asset_id. However, it lacks a verification mechanism to ensure that the given asset_id is not already linked to a different foreign_asset_id. As a result, an asset_id can be associated with multiple foreign assets which would lead to market misconfigurations. We classify this issue with minor severity since only a privileged account can perform the aforementioned operation.
Recommendation
We recommend introducing a verification mechanism checking that the asset_id is not already linked to a different foreign_asset_id.
Status: Resolved
The client removed set_foreign_asset and get_special_asset_price from the codebase.

Summary: Lack of verification allows multiple foreign_asset_id to map to the same asset_id, risking market misconfigurations.
Audit finding: Missing check that foreign_asset_id is specifically of the ForeignAsset type
Project: Bifrost
Auditor: Oak Security
Location: pallets/prices/src/lib.rs:149-157
Impact: Minor
Vulnerability class (Scout): Error Handling and Validation
Status: Resolved

4. Missing check that foreign_asset_id is specifically of the ForeignAsset type
Severity: Minor
In pallets/prices/src/lib.rs:149-157, the set_foreign_asset extrinsic enables the UpdateOrigin origin to establish a mapping within the pallet that associates a foreign_asset_id with an asset_id. However, it does not verify that the provided foreign_asset_id is specifically of the ForeignAsset type; it is only identified as a CurrencyId. As a result, the UpdateOrigin can map any asset type, not just foreign assets. We classify this issue with minor severity since only a privileged account can perform the aforementioned operation.
Recommendation
We recommend verifying that the provided foreign_asset_id is specifically of the ForeignAsset type.
Status: Resolved
The client removed set_foreign_asset and get_special_asset_price from the codebase.

Summary: Missing validation allows mapping of non-ForeignAsset types, risking misconfigurations.
Audit finding: Default mantissa precision can lead to an incorrect price
Project: Bifrost
Auditor: Oak Security
Location: pallets/prices/src/lib.rs:179-186
Impact: Minor
Vulnerability class (Scout): Error Handling and Validation
Status: Acknowledged

5. Default mantissa precision can lead to an incorrect price
Severity: Minor
In pallets/prices/src/lib.rs:179-186, the get_asset_mantissa function is designed to calculate the mantissa for a given asset by attempting to retrieve the asset's decimal precision from multiple sources. However, if it fails to find any decimal information for the specified asset_id, it automatically assumes a default precision of 12 decimals. As a result, this approach poses a risk, as the function plays a crucial role in asset valuation, and an incorrect mantissa calculation would lead to the determination of an erroneous price.
Recommendation
We recommend returning an error if the decimal precision for a particular asset cannot be retrieved.
Status: Acknowledged
The client states that a misconfiguration of the decimal precision is unlikely since it is set during the asset registration in the bifrost-asset-registry pallet.

Summary: Default mantissa precision assumption can lead to incorrect asset price calculation.
Audit finding: Missing validation for the lend_token_id
Project: Bifrost
Auditor: Oak Security
Location: pallets/lend-market/src/lib.rs:656-680
Impact: Minor
Vulnerability class (Scout): Error Handling and Validation
Status: Resolved

6. Missing validation for the lend_token_id
Severity: Minor
In pallets/lend-market/src/lib.rs:656-680, the force_update_market function enables the UpdateOrigin to assign a new lend_token_id to a specified market. However, it fails to verify whether the lend_token_id is not already a market, a validation that is performed in the ensure_lend_token method in line 1843. As a consequence, this oversight could lead to inconsistencies in market configuration since the lend token is not designed to be used in a market. We classify this issue with minor severity since only a privileged account can perform the aforementioned operation.
Recommendation
We recommend verifying whether the lend_token_id is not already utilized in a market.
Status: Resolved

Summary: Missing validation for lend_token_id may lead to market configuration inconsistencies.
Audit finding: The force_update_market extrinsic could break existing markets
Project: Bifrost
Auditor: Oak Security
Location: pallets/lend-market/src/lib.rs:659
Impact: Minor
Vulnerability class (Scout): Business Logic
Status: Resolved

7. The force_update_market extrinsic could break existing markets
Severity: Minor
In pallets/lend-market/src/lib.rs:659, the force_update_market function permits the UpdateOrigin to forcibly replace an existing market with another, without ensuring the coherence of the provided data. This poses a risk since UpdateOrigin is allowed to modify markets with any data, including malicious ones that could break invariants. As a consequence, the current approach could result in the acceptance of markets with a collateral_factor or liquidation_threshold outside of the [0,1] range, which could break market operations and potentially cause a loss of funds. We classify this issue as minor since only a privileged account can perform the aforementioned operation.
Recommendation
We recommend removing the force_update_market extrinsic and utilizing the update_market one to handle market updates.
Status: Resolved

Summary: force_update_market extrinsic allows data inconsistencies that could break market operations.
Audit finding: Static calculation of weights for the update_liquidation_fee_collateral extrinsic
Project: Bifrost
Auditor: Oak Security
Location: pallets/lend-market/src/interest.rs:1123-1130
Impact: Minor
Vulnerability class (Scout): Weight Management
Status: Resolved

8. Static calculation of weights for the update_liquidation_fee_collateral extrinsic
Severity: Minor
In pallets/lend-market/src/interest.rs:1123-1130, the update_liquidation_fee_collateral extrinsic takes a collaterals vector as a parameter. However, the calculation of the extrinsic weights does not take into account the length of the collaterals vector. As a result, the update_liquidation_fee_collateral extrinsic will charge the same fee for vectors of different sizes leading to an uncorrelated relation between fees and computational resource usage. We classify this issue as minor since only a privileged account can perform the aforementioned operation.
Recommendation
We recommend dynamically calculating the weight of the update_liquidation_fee_collateral extrinsic based on the collaterals vector's cardinality.
Status: Resolved

Summary: Static weight calculation for update_liquidation_fee_collateral ignores vector length, causing uncorrelated fee charges.
Audit finding: Missing validation of liquidate_incentive_reserved_factor during market update
Project: Bifrost
Auditor: Oak Security
Location: pallets/lend-market/src/lib.rs:381,610,1757
Impact: Minor
Vulnerability class (Scout): Error Handling and Validation
Status: Resolved

9. Missing validation of liquidate_incentive_reserved_factor during market update
Severity: Minor
In pallets/lend-market/src/lib.rs:381 the add_market function checks the correct allowed ranges for the provided market parameters, including liquidate_incentive_reserved_factor. This value is forced to be in the (0,1) range. However, in the update_market function in pallets/lend-market/src/lib.rs:610, this validation is not performed. As a consequence, when updating the market, it is possible to set the liquidate_incentive_reserved_factor value outside the (0,1) range, which will have implications in the form of incorrect calculations of incentives when liquidating positions within the liquidated_transfer function in pallets/lend-market/src/lib.rs:1757. We classify this as minor since only a privileged account can perform the aforementioned operation.
Recommendation
We recommend validating the liquidate_incentive_reserved_factor in the update_market function.
Status: Resolved

Summary: Missing validation in update_market allows liquidate_incentive_reserved_factor outside valid range.
Audit finding: Incorrect interest is calculated if requested before market initialization
Project: Bifrost
Auditor: Oak Security
Location: pallets/lend-market/src/interest.rs:58,75
Impact: Minor
Vulnerability class (Scout): Business Logic
Status: Resolved

10. Incorrect interest is calculated if requested before market initialization
Severity: Minor
In pallets/lend-market/src/interest.rs:58, the get_market_status function calculates and returns information about the queried market. However, in case the market has not been used yet, the last_accrued_interest_time variable, when retrieved in line 75 from the LastAccruedInterestTime on-chain storage, would default to zero. Consequently, when get_market_status is called without the market being previously initialized, the interest accrual period is inaccurately computed from January 1, 1970, despite the asset not being used yet leading to a wrong calculation.
Recommendation
We recommend handling the case of last_accrued_interest_time equal to zero in the get_market_status function.
Status: Resolved

Summary: Incorrect interest calculation occurs if requested before market initialization.