#46942 [SC-Low] set perpetual asset balance link there is no cycle checks
Submitted on Jun 6th 2025 at 14:37:44 UTC by @gln for IOP | Paradex
Report ID: #46942
Report Type: Smart Contract
Report severity: Low
Target: https://github.com/tradeparadex/audit-competition-may-2025/tree/main/paraclear
Impacts:
Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol)
Description
Brief/Intro
By calling set_perpetual_asset_balance_link function admin could create cycles in Paraclear_perpetual_asset_balance list. As a result, any function which loads account state from storage will revert.
Vulnerability Details
Let's look at how contract handles account loading from storage, code from paraclear.cairo:
fn _load_account_no_asset_data(
self: @ContractState, account: ContractAddress,
) -> AccountState {
// load fees and referral
let fee_rates = self.account._get_account_fee_rate(account);
let referral = self.account.get_account_referral(account);
// load perpetual markets (both futures and options)
let (perp_names, perp_balances) = self.perpetual_future._get_account_markets(account);
// load token markets
let (mut token_names, mut token_balances) = self.token._get_account_markets(account);
...
}
fn _load_account_v2(self: @ContractState, account: ContractAddress) -> AccountState {
let mut account_state = self._load_account_no_asset_data(account);
if account_state.perpetual_names.is_empty() && account_state.token_names.is_empty() {
return account_state;
}
account_state
.asset_data = self
._load_asset_data(account_state.perpetual_names, account_state.token_names);
account_state
}
Now look at the function _get_account_markets from future.cairo:
If we manage to create cycle here, this function will always revert due to out of gas error
The only function which is capable of createing such loop is set_perpetual_asset_balance_link() :
There is no cycle check, such that prev_market could equal to market.
Malicious or compromised admin could create cycle by calling this function.
As a result any contract functions which load account data from storage will fail with out of gas error.
Impact Details
After creating cycle in Paraclear_perpetual_asset_balance list, Paradex contract becomes unusable.
Proof of Concept
Proof of Concept
How to reproduce:
Add test to paraclear/tests/test_paraclear.cairo.
See gist link - https://gist.github.com/gln7/871b2e0d4cdc04a69718923ca332c7a9
Run the test:
Was this helpful?