#46888 [SC-High] account_transfer_partial: lack of input validation when working with signed integers
Description
Brief/Intro
Vulnerability Details
fn account_transfer_partial(
ref self: ContractState,
account: ContractAddress,
receiver: ContractAddress,
account_share: felt252,
amount_collateral: felt252,
) -> felt252 {
// Validate account share is between 0 and 1
assert!(
account_share.try_into().unwrap() > 0_i128
&& account_share.try_into().unwrap() <= ONE,
"AccountTransfer: account_share must be within [1,100000000]",
);
// detect transfer restriction
self
.token
._detect_account_transfer_restriction(account, receiver, account_share.into());
// Load account state and verify account is healthy
let account_state = self._load_account_v2(account);
let excess_balance = account_state.excess_balance(MARGIN_CHECK_MAINTENANCE);
assert!(excess_balance >= 0_i128, "AccountTransfer: account must be healthy");
// Get account value and settlement token info
let account_value = account_state.account_value();
// Standard transfer mode, % of both collateral and positions
if amount_collateral == 0 {
// Transfer each perpetual position
self._transfer_positions_internal(account_state, receiver, account_share, 0);
// Transfer proportional collateral
let token_transfer_share = mul_128(
account_value, account_share.try_into().unwrap(),
);
let token_transfer = div_128(
token_transfer_share, account_state.asset_data.settlement_token_price,
);
self
.token
.transfer_internal(
account, receiver, self.getSettlementTokenAsset(), token_transfer.into(), 1,
);
// Fast transfer mode, collateral only
} else {
1) self
.token
.transfer_internal(
account, receiver, self.getSettlementTokenAsset(), amount_collateral, 1,
);
}
...
}Impact Details
Proof of Concept
Proof of Concept
Previous#46867 [SC-Insight] The `is_liquidation` field in `transfer_internal` is not properly differentiated.Next#46892 [SC-High] small deposits could prevent users from withdrawing their funds
Was this helpful?