Unchecked deposit amount
Description
The receive_deposit_batch function calls parse_deposit_payload to parse deposit payloads. While received_asset_amount represents the total sum of all depositor amounts, the parse_deposit_payload function lacks validation to ensure this sum matches the actual total deposit amount received.
fun parse_deposit_payload(received_asset_metadata: Object<Metadata>, received_asset_amount: u64, message: vector<u8>): DepositPayload acquires DepositManagerController {
// [...]
let asset_mantissa_diff = *smart_table::borrow(&controller.asset_decimals_mantissa_table, received_asset_metadata);
// [...]
let depositor_indices = vector::range_with_step(65, vector::length(&message), 32);
let depositor_map = simple_map::new();
vector::for_each(depositor_indices, |index| {
assert!(index + 32 <= vector::length(&message), ERR_DEPOSIT_MANAGER_MALFORMED_PAYLOAD);
let depositor_address = vector::slice(&message, index, index + 20);
let depositor_amount = from_bcs::to_u128(vector::slice(&message, index + 20, index + 32));
assert!(depositor_amount <= MAX_U64, ERR_DEPOSIT_MANAGER_DEPOSIT_AMOUNT_OVERFLOW);
let depositor_amount_adjusted = ((depositor_amount / (math64::pow(10, asset_mantissa_diff) as u128)) as u64);
let amount_vector = vector[depositor_amount_adjusted];
simple_map::add(&mut depositor_map, depositor_address, amount_vector);
});
// [...]Impact
The lack of validation between the received total amount and the sum of individual deposits could potentially allow inconsistent deposit states. While this does not directly lead to fund loss, it may cause accounting discrepancies that need to be reconciled manually.
Recommendations
Since there is logic that adjusts deposit amounts based on asset decimals, the received_asset_amount may not exactly match the total sum of deposits. We recommend adding a validation check to ensure the sum of all depositor amounts approximately matches the received_asset_amount.
Remediation
This issue has been acknowledged by Echelon, and a fix was implemented in commit d1afe83e↗.