CoinFabrik/scout-substrate huggingface dataset:
Audit finding: Casting overflow
Project: ReefChain
Auditor: Halborn
Location: modules/evm-bridge/src/lib.rs:183,186,191
Impact: 3
Likelihood: 2
Vulnerability class (Scout): Arithmetic
Status: SOLVED

3.3 (HAL-03) CASTING OVERFLOW - LOW
Description:
When converting or casting between types, an “overflow”/wrapping may occur and result in logic bugs leading to thread panic. The decode_string utility method defined in modules/evm-bridge/src/lib.rs does not validate if the values of the offset and length variables can be cast to the usize type. Although the method is not exported and available externally, the method is vulnerable still and the risk could increase in the future if the method is used before it’s patched.

Code Location:
Listing 5: modules/evm-bridge/src/lib.rs (Lines 183,186,191)
182 let offset = U256::from_big_endian(&output[0..32]);
183 let length = U256::from_big_endian(&output[offset.as_usize()..offset.as_usize() + 32]);
184 ensure!(
// output is 32-byte aligned. ensure total_length >= offset + string length + string data length.
186 output.len() >= offset.as_usize() + 32 + length.as_usize(),
187 Error::<T>::InvalidReturnValue
188 );
189 let mut data = Vec::new();
191 data.extend_from_slice(&output[offset.as_usize() + 32..offset.as_usize() + 32 + length.as_usize()]);

Risk Level:
Likelihood - 2
Impact - 3

Recommendations:
Check the value against maximum type value before casting.

Listing 6:
1 if (x <= usize::MAX) {
2 // logic ...
3 }

Remediation:
SOLVED: Reef fixed the issue in commit 313439bb7940afa0f0d5060fbcbbe26d5a3e5298.

Summary: Casting overflow vulnerability due to unchecked type conversion in decode_string method.
Audit finding: Slash amount validation missing
Project: ReefChain
Auditor: Halborn
Location: modules/currencies/src/lib.rs:396
Impact: 2
Likelihood: 2
Vulnerability class (Scout): Error Handling and Validation
Status: SOLVED

3.4 (HAL-04) SLASH AMOUNT VALIDATION MISSING - LOW
Description:
The slash_reserved method defined in modules/currencies/src/lib.rs does not validate if the value of the user-supplied value parameter exceeds the actual balance of the account owned by the address that is to have its ERC20 tokens slashed.

Code Location:
Listing 7: modules/currencies/src/lib.rs (Lines 396)
394 fn slash_reserved(currency_id: Self::CurrencyId, who: &T::AccountId, value: Self::Balance) -> Self::Balance {
395 match currency_id {
396 CurrencyId::ERC20(_) => value,
397 CurrencyId::Token(TokenSymbol::REEF) => T::NativeCurrency::slash_reserved(who, value),
398 _ => T::MultiCurrency::slash_reserved(currency_id, who, value),
399 }
400 }

Risk Level:
Likelihood - 2
Impact - 2

Recommendations:
The slashed amount should always be lesser or equal to the account balance that is to be slashed.

Remediation:
SOLVED: Reef fixed the issue in commit bd43bec58890be763b32bfdfd18ba85a8c0ef9e5.

Summary: Missing validation in slash_reserved method allows slashing beyond account balance.
Audit finding: Vector capacity validation missing
Project: ReefChain
Auditor: Halborn
Location: modules/evm-accounts/src/lib.rs:313
Impact: 2
Likelihood: 1
Vulnerability class (Scout): Error Handling and Validation
Status: SOLVED

3.6 (HAL-06) VECTOR CAPACITY VALIDATION MISSING - INFORMATIONAL
Description:
The to_ascii_hex utility function defined in modules/evm-accounts/src/lib.rs when creating a new Vec<u8> from the user-supplied data slice with a Vec::with_capacity method does not validate if the capacity of the new vector exceeds the maximum allowed capacity.

Code Location:
Listing 10: modules/currencies/src/lib.rs (Lines 313)
312 pub fn to_ascii_hex(data: &[u8]) -> Vec<u8> {
313 let mut r = Vec::with_capacity(data.len() * 2);
314 let mut push_nibble = |n| r.push(if n < 10 { b'0' + n } else { b'a' - 10 + n });
315 for &b in data.iter() {
316 push_nibble(b / 16);
317 push_nibble(b % 16);
318 }
319 r
320 }

Risk Level:
Likelihood - 1
Impact - 2

Recommendations:
Validate if the new capacity (data.len() * 2) does not exceed isize::MAX bytes.

Remediation:
SOLVED: Reef fixed the issue in commit 6b826f7ca16d1a30f3fa55f0606d0b94b69b2b3a.

Summary: Missing validation in to_ascii_hex function allows vector capacity to exceed maximum limit.
Audit finding: Static fee charged despite dynamic storage accesses
Project: MantaNetwork
Auditor: Veridise
Location: parachain-staking/lib.rs
Impact: Medium
Vulnerability class (audit): Bad Extrinsic Weight
Vulnerability class (Scout): Weight Management
Status: Acknowledged

4.1.1 V-MANC-VUL-001: Static fee charged despite dynamic storage accesses

Severity: Medium
Type: Bad Extrinsic Weight
Commit: 45ba60e1d
Status: Acknowledged

File(s): parachain-staking/lib.rs
Location(s): go_online, go_offline, candidate_bond_more

Blockchain computations must have appropriate fees to prevent network congestion. For substrate extrinsics, these fees are set by computing an associated weight for the operation where the weight is intended to capture the maximum computational cost. As reads from and writes to storage are expensive, these weights should consider the number of these operations that are performed. The following extrinsics, however, have a fixed weight despite requiring a dynamic number of reads or writes due to insert or remove operations being performed on CandidatePool.

- go_online
- go_offline
- candidate_bond_more
- execute_candidate_bond_less
- delegate
- execute_leave_delegators
- delegator_bond_more
- execute_delegation_request
- schedule_leave_delegators
- schedule_delegator_bond_less
- cancel_leave_delegators

Also note that similar functions in the same pallet, such as schedule_leave_candidates charge the users dynamic fees. An example can be seen in Snippet 4.1.

Impact: As the size of the CandidatePool grows, the cost of insert and remove will increase linearly since vector inserts in Rust are linear in the size of the vector. This allows malicious actors to add many candidates to the pool for a fixed monetary cost despite an increasing computational cost. If the size of the pool becomes too large, this could effectively create a DoS.

Recommendation: Similar to schedule_leave_candidates, calculate the weights dynamically rather than charging a fixed cost.

Developer Response: The developers have acknowledged the issue and are determining how to address it.

Snippet 4.1: go_offline calls remove on the CandidatePool but charges users a fixed weight in WeightInfo::go_offline

#[pallet::call_index(12)]
#[pallet::weight(<T as Config>::WeightInfo::go_offline())]
/// Temporarily leave the set of collator candidates without unbonding
pub fn go_offline(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
   let collator = ensure_signed(origin)?;
   let mut state = <CandidateInfo<T>>::get(&collator).ok_or(Error::<T>::CandidateDNE)?;
   ensure!(state.is_active(), Error::<T>::AlreadyOffline);
   state.go_offline();
   let mut candidates = <CandidatePool<T>>::get();
   if candidates.remove(&Bond::from_owner(collator.clone())) {
      <CandidatePool<T>>::put(candidates);
   }
   <CandidateInfo<T>>::insert(&collator, state);
   Self::deposit_event(Event::CandidateWentOffline { candidate: collator });
   Ok(().into())
}

Summary: Fixed fees are charged for dynamic storage operations, potentially leading to DoS as CandidatePool size grows.
Audit finding: MantaPay weights calculated with a small database
Project: MantaNetwork
Auditor: Veridise
Location: pallets/manta-pay/src/lib.rs
Impact: Medium
Vulnerability class (audit): Bad Extrinsic Weight
Vulnerability class (Scout): Weight Management
Status: Acknowledged

4.1.3 V-MANC-VUL-003: MantaPay weights calculated with a small database

Severity: Medium
Type: Bad Extrinsic Weight
Commit: 45ba60e1d
Status: Acknowledged

File(s): pallets/manta-pay/src/lib.rs
Location(s): to_private, to_public, private_transfer

Transactions to_public, to_private, and private_transfer take as input nullifiers and membership proofs and generate UTXOs. These UTXOs are then added to a Merkle tree on the ledger.

MantaPay shards this Merkle tree into 256 buckets where each bucket has its own Merkle tree. Instead of storing the entire tree at each bucket, the Ledger just stores the last path added to the tree. When adding a UTXO, the Ledger first computes its corresponding bucket, then computes the new path pointing to that UTXO, and finally adds that path to the bucket.

Computing the new path should take time proportional to log(n) where n is the size of the Merkle Tree. The current benchmarking scheme only covers cases where the previous path is small, i.e., at most size 1. However, if the number of transactions gets large, on the order of hundreds of millions or billions, then the size of the path can get to 24-28 (taking shards into account). If the tree grows to this size, this means each execution of the extrinsic will perform 24-28 hashes, multiplied by the number of UTXOs to be added.

The benchmarking scheme should take into account the size of the tree to ensure that the existing weights are sufficient to offset the computation of the new Merkle tree path.

Impact: Setting the weight too low can allow users to perform a large number of transactions with little cost, potentially allowing malicious users to launch a DoS attack.

Recommendation: There are several ways to address this. One strategy is to take an additional parameter corresponding to the logarithm of the Merkle Tree's size on the ledger. The weight charged can be proportional to this value. In the implementation, this value (technically 2^value) can be compared against the actual size, and the transaction will only proceed if it is larger than or equal to the actual size.

Another strategy is to benchmark the pallets by taking into account the tree's size. If MantaPay is expected not to exceed more than a billion transactions, then the pallet could be benchmarked assuming the current path length is around 24-28.

Developer Response: The developers acknowledged that the weights should be recalculated with a more saturated database.

Summary: Inadequate benchmarking of weights for MantaPay's Merkle tree could lead to DoS attacks as the tree grows.
Audit finding: Missing updates in update_asset_metadata
Project: MantaNetwork
Auditor: Veridise
Location: pallets/asset-manager/src/lib.rs
Impact: Medium
Vulnerability class (audit): Logic Error
Vulnerability class (Scout): Business Logic
Status: Acknowledged

4.1.5 V-MANC-VUL-005: Missing updates in update_asset_metadata

Severity: Medium
Type: Logic Error
Commit: 45ba60e1d
Status: Acknowledged

File(s): pallets/asset-manager/src/lib.rs
Location(s): update_asset_metadata

Manta Chain has an asset-manager pallet responsible for registering and minting assets. Each asset has a unique id and is associated with various metadata like a name, symbol, decimal places, etc. One important metadata is called min_balance. To store an account with some quantity of assets on the ledger, it must have more than min_balance quantity. This metadata is also used when validating transfers.

In particular, many asset transfers take an “existential parameter” as input, called KeepAlive, which decides what to do if the transfer would take the account’s balance (with respect to the asset) below min_balance. If KeepAlive is set, the transfer will fail if the amount goes below the min_balance. If it is not set, other configurations come into play, and the account may be removed and the remaining balance burned.

The asset-manager pallet exposes an extrinsic called update_asset_metadata, which takes as input the new metadata for that asset and updates the ledger to associate the asset with that metadata. While the implementation took a new min_balance as input, it did not update the ledger to associate the asset with this metadata.

Additionally, this API also took as input a new value for the metadata is_sufficient, but similarly did not update the ledger to associate the asset with this metadata.

Impact: While it is rare for the min_balance to be changed, it is sometimes necessary if it was originally set too high, for example. The current API made it appear that min_balance could be changed, so users might think the min_balance was changed when, in fact, it wasn’t.

Recommendation: The main issue with this extrinsic is its interface makes it appear as though the metadata min_balance and is_sufficient could be changed when it actually didn’t. Either the API should be changed to only take the metadata that should be changed, or it should appropriately update min_balance and is_sufficient.

Developer Response: The developers acknowledged this issue and are discussing two possible fixes. The first is to update both parameters in the asset pallet, and the second is to change the interface to prevent updating the min_balance or is_sufficient parameters.

Summary: update_asset_metadata does not apply updates to min_balance and is_sufficient metadata as expected.
Audit finding: No slashing mechanism for collators
Project: MantaNetwork
Auditor: Veridise
Location: parachain-staking
Impact: Medium
Vulnerability class (audit): Consensus
Vulnerability class (Scout): Business Logic
Status: Acknowledged

4.1.6 V-MANC-VUL-006: No slashing mechanism for collators

Severity: Medium
Type: Consensus
Commit: 45ba60e1d
Status: Acknowledged

File(s): parachain-staking
Location(s): N/A

Proof of Stake blockchains often have a slashing mechanism to detect poorly performing stakers and punish them. Typically, a significant portion of the staker’s stake is taken by the chain as punishment for poor performance.

Currently, Manta Chain does not have any slashing mechanism. Instead, it uses a combination of social pressure and manual slashing to incentivize good behavior. Specifically, when the owners detect a poorly performing collator, they contact the collator over Discord and warn them of the poor performance. If their performance does not improve, the owners manually slash the collator’s funds.

While this approach may work when the blockchain is small, it will be challenging to enforce as the chain grows. Therefore, we recommend that Manta Chain implement a slashing mechanism.

Impact: Manta Chain’s current method of using social pressure will only work with a small set of trusted collators. However, as the chain expands, this mechanism is unlikely to sufficiently incentivize collators to perform well.

Recommendation: We recommend that Manta Chain establish a slashing mechanism to implement if/when the current process becomes inadequate.

Developer Response: The developers acknowledged the lack of a slashing mechanism and plan to include one in the future if/when the current process stops working.

Summary: No automated slashing mechanism exists to penalize poorly performing collators, relying on social pressure and manual intervention.
Audit finding: Collators given full rewards regardless of quality
Project: MantaNetwork
Auditor: Veridise
Location: pallets/parachain-staking/src/lib.rs
Impact: Medium
Vulnerability class (audit): Consensus
Vulnerability class (Scout): Business Logic
Status: Open

4.1.7 V-MANC-VUL-007: Collators given full rewards regardless of quality

Severity: Medium
Type: Consensus
Commit: 45ba60e1d
Status: Open

File(s): pallets/parachain-staking/src/lib.rs
Location(s): pay_one_collator_reward

Manta Chain rewards collators by first allocating a fixed number of points (20) for every block they author and then giving the collator a fixed percentage of those allocated points as rewards. However, there is no check on the quality of the blocks authored by the collator: an empty block will result in just as many rewards as a full block.

Currently, Manta relies on the owners to monitor the blocks on-chain and manually punish collators who perform poorly. However, as the chain grows, this misbehavior may not be easy to detect.

One relatively simple way to address this issue is to adjust the reward system to incentivize high quality blocks.

Impact: Collators can effectively steal funds from Manta by authoring low-quality blocks (i.e., empty or partial blocks) and reaping full rewards.

Recommendation: We recommend the developers adjust the rewards system to either reward the collators for high-quality blocks or punish them for authoring poor ones.

Developer Response: TBD

Summary: Collators receive full rewards regardless of block quality, allowing low-quality blocks to earn the same as high-quality ones.
Audit finding: Missing validation in pull_ledger_diff
Project: MantaNetwork
Auditor: Veridise
Location: pallets/manta-pay/src/lib.rs:593
Impact: Low
Vulnerability class (audit): Data Validation
Vulnerability class (Scout): Error Handling and Validation
Status: Acknowledged

4.1.8 V-MANC-VUL-008: Missing validation in pull_ledger_diff

Severity: Low
Type: Data Validation
Commit: 45ba60e1d
Status: Acknowledged

File(s): pallets/manta-pay/src/lib.rs
Location(s): Line 593

pull_ledger_diff takes as input a Checkpoint, which is a struct with two fields: receiver_index and sender_index. It pulls sender and receiver data from the ledger, starting at sender_index (resp. receiver_index) up to at most sender_index + PULL_MAX_SENDER_UPDATE_SIZE (resp. receiver_index + PULL_MAX_RECEIVER_UPDATE_SIZE). However, there is no check to ensure that this sum cannot overflow for both the sender and receiver index in pull_senders, pull_receivers, pull_senders_for_shard, and pull_receivers_for_shard.

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

Recommendation: We recommend adding bounds checks for safety and to return an Error.

Developer Response: The developers are aware and agree that it would be better to check and return an error.

Summary: Missing bounds checks in pull_ledger_diff could lead to overflow, potentially crashing the node.
Audit finding: increase_count_of_associated_assets can overflow
Project: MantaNetwork
Auditor: Veridise
Location: pallets/asset-manager/src/lib.rs:590
Impact: Low
Vulnerability class (audit): Logic Error
Vulnerability class (Scout): Arithmetic
Status: Acknowledged

4.1.9 V-MANC-VUL-009: increase_count_of_associated_assets can overflow

Severity: Low
Type: Logic Error
Commit: 45ba60e1d
Status: Acknowledged

File(s): pallets/asset-manager/src/lib.rs
Location(s): Line 590

The asset_manager pallet maintains a mapping of paraids to a count of assets associated with that paraid. Each paraid can be associated with at most u32::MAX assets. When registering an asset or moving its location, the pallet calls increase_count_of_associated_assets, which takes as input a paraid and increments the number of assets associated with that paraid. However, this function does not check whether increasing the number of assets will result in an overflow.

Impact: If the runtime is compiled using --debug, this can crash the node. However, if built under --release, the asset count will go to zero.

Recommendation: Make this function check if the addition will result in an overflow, i.e., check if the current count is u32::MAX and return an error.

Developer Response: Acknowledged

Summary: increase_count_of_associated_assets lacks overflow check, risking node crash or reset to zero in certain cases.
Audit finding: Account checks are incorrect
Project: MantaNetwork
Auditor: Veridise
Location: pallets/manta-pay/src/lib.rs
Impact: Low
Vulnerability class (audit): Logic Error
Vulnerability class (Scout): Business Logic
Status: Acknowledged

4.1.10 V-MANC-VUL-010: Account checks are incorrect.

Severity: Low
Type: Logic Error
Commit: 45ba60e1d
Status: Acknowledged

File(s): pallets/manta-pay/src/lib.rs
Location(s): check_sink_accounts, check_source_accounts

When validating a transaction, the source and sink accounts are checked by check_sink_accounts and check_source_accounts. These functions iterate over pairs (account, value) and check that value can be safely deposited (withdrawn) from account. The logic is correct only if every account appears in at most one pair. While this is fine for the current APIs, if the APIs change to allow multiple sink or multiple source accounts, then this code needs to be refactored or the uniqueness needs to be enforced elsewhere.

Impact: Currently there is no impact since the current APIs only allow one account for the source and sink accounts.

Recommendation: To be safe, we recommend adding an additional check in the validation step to ensure the accounts are distinct for both sources and sinks.

Developer Response: The developers acknowledged the issue and plan to add a check during validation to ensure that the accounts are distinct.

Summary: Account checks in transaction validation assume unique accounts, which may lead to issues if APIs change to allow multiple accounts.
Audit finding: Unstaked user may be selected as collator
Project: MantaNetwork
Auditor: Veridise
Location: parachain-staking/lib.rs
Impact: Low
Vulnerability class (audit): Logic Error
Vulnerability class (Scout): Business Logic
Status: Acknowledged

4.1.11 V-MANC-VUL-011: Unstaked user may be selected as collator

Severity: Low
Type: Logic Error
Commit: 45ba60e1d
Status: Acknowledged

File(s): parachain-staking/lib.rs
Location(s): select_top_candidates

Parachains use collators to combine transactions into blocks that are then checked by Validators on the relay chain. Notably, this allows collators to remain relatively untrusted as validators ensure blocks are created correctly. On Manta’s chain, collators are selected from a group of staked users who receive rewards for creating blocks. Requiring that collators be staked provides additional security guarantees as, if a collator misbehaves (e.g., submits no blocks for validation, submits multiple conflicting blocks), governance can step in and slash the user’s staked funds. As such, unstaked collators have less incentive to maintain parachain stability and should be avoided.

However, in the collator selection process, if no sufficiently staked collator can be found, collators from the previous round will be selected. As there is no validation on the current state of the previous collators’ stake, this could select unstaked validators who lack the incentive to ensure network stability.

Here is a simple test case demonstrating this:

#[test]
fn test_failed_candidate_selection() {
  ExtBuilder::default()
    .with_balances(vec![(10, 10)])
    .with_candidates(vec![(10, 10)])
    .build()
    .execute_with(|| {
      roll_to(2);
      assert_ok!(ParachainStaking::schedule_leave_candidates(Origin::signed(10), 6u32));
      roll_to(5);
      let candidate: Vec<u64> = ParachainStaking::selected_candidates();
      assert_ne!(candidate[0], 10u64);
    });
}

Impact: Collators will not be incentivized to ensure network stability. Another set of partially staked or “trusted” collators could provide better stability.

Recommendation: Consider maintaining a set of “trusted” collators to fall back on if no staked collators can be found.

Developer Response: Acknowledged.

Summary: Unstaked users may be selected as collators if no sufficiently staked collators are available, reducing network stability.