Category: security
Problem
dabdub_contracts/contracts/fee_calculator/src/lib.rs's calculate_fee(env: Env, merchant: Address, amount: i128) -> (i128, i128, u32) has no caller parameter and calls no require_auth() anywhere. It directly mutates persistent per-merchant rolling-30-day volume state via update_and_get_volume (line 151-171), which determines which fee tier (select_fee_bps) the merchant gets on every subsequent call. src/test.rs calls client.calculate_fee(&merchant, &amount) directly with no authorizing party in every test, consistent with there being no auth to bypass.
Impact
Any address can call calculate_fee for any merchant with an arbitrary amount, with no funds actually moving and no relationship to a real payment. Repeated calls artificially inflate a targeted merchant's tracked volume_usdc, permanently pushing them into a lower fee-bps tier ahead of real usage — a direct fee-tier manipulation/gaming vector, and also a griefing vector (an attacker can pollute a competitor's volume window with a flood of amount=1 calls). Since this contract appears intended to be invoked only by trusted settlement flow (e.g. payment_escrow/settlement_ledger), the absence of a caller restriction is a real access-control gap on state that directly affects merchant economics.
Suggested fix
Add a caller: Address parameter with caller.require_auth(), and restrict calculate_fee to a configured, admin-settable caller (e.g. the settlement/escrow contract's address), similar to the admin-gating pattern used in merchant_registry::update_fee_tier.
Category: security
Problem
dabdub_contracts/contracts/fee_calculator/src/lib.rs'scalculate_fee(env: Env, merchant: Address, amount: i128) -> (i128, i128, u32)has nocallerparameter and calls norequire_auth()anywhere. It directly mutates persistent per-merchant rolling-30-day volume state viaupdate_and_get_volume(line 151-171), which determines which fee tier (select_fee_bps) the merchant gets on every subsequent call.src/test.rscallsclient.calculate_fee(&merchant, &amount)directly with no authorizing party in every test, consistent with there being no auth to bypass.Impact
Any address can call
calculate_feefor any merchant with an arbitraryamount, with no funds actually moving and no relationship to a real payment. Repeated calls artificially inflate a targeted merchant's trackedvolume_usdc, permanently pushing them into a lower fee-bps tier ahead of real usage — a direct fee-tier manipulation/gaming vector, and also a griefing vector (an attacker can pollute a competitor's volume window with a flood ofamount=1calls). Since this contract appears intended to be invoked only by trusted settlement flow (e.g. payment_escrow/settlement_ledger), the absence of a caller restriction is a real access-control gap on state that directly affects merchant economics.Suggested fix
Add a
caller: Addressparameter withcaller.require_auth(), and restrictcalculate_feeto a configured, admin-settable caller (e.g. the settlement/escrow contract's address), similar to the admin-gating pattern used inmerchant_registry::update_fee_tier.