Problem
The deployed contract emits a unified close/liquidation event:
event TakerClosed(uint256 posId, SwapResult sr, int256 funding, uint256 utilFees, uint256 liqFee, bool isLiquidation);
(See the binding fix that added liqFee/isLiquidation — the deployed TakerClosed differs from the v0.2.1 source; related: #58.)
But decode_log drops those two fields (src/feeds/events.rs):
} else if topic0 == Perp::TakerClosed::SIGNATURE_HASH {
let d = decode_raw::<Perp::TakerClosed>(log)?;
Some(MarketEvent::TakerClosed {
pos_id: d.posId,
swap: swap_info(&d.sr)?,
funding: i256_usdc(d.funding)?,
util_fees: u256_usdc(d.utilFees)?,
// d.liqFee and d.isLiquidation are dropped
})
}
And the MarketEvent::TakerClosed variant has no liquidation fields.
Impact
Because liquidation is folded into TakerClosed(isLiquidation=true) on the deployed contract (rather than a separate TakerLiquidated), a consumer cannot distinguish a liquidation from a voluntary close via the event stream, nor see the liquidation fee. Position eviction doesn't care (both → remove the position), but risk/strategy/PnL logic does (e.g. Legion would want to know it got liquidated rather than chose to close).
Proposal
Add is_liquidation: bool and liq_fee: f64 to MarketEvent::TakerClosed (and check MakerClosed for the same isLiquidation/liqFee shape — verify its deployed signature per #58), and populate them in decode_log:
Some(MarketEvent::TakerClosed {
pos_id: d.posId,
swap: swap_info(&d.sr)?,
funding: i256_usdc(d.funding)?,
util_fees: u256_usdc(d.utilFees)?,
liq_fee: u256_usdc(d.liqFee)?,
is_liquidation: d.isLiquidation,
})
This pairs naturally with #58 (verifying the sibling close/liquidation bindings against the deployment). Surfaced by the Legion migration's market_data review.
Problem
The deployed contract emits a unified close/liquidation event:
(See the binding fix that added
liqFee/isLiquidation— the deployedTakerCloseddiffers from the v0.2.1 source; related: #58.)But
decode_logdrops those two fields (src/feeds/events.rs):And the
MarketEvent::TakerClosedvariant has no liquidation fields.Impact
Because liquidation is folded into
TakerClosed(isLiquidation=true)on the deployed contract (rather than a separateTakerLiquidated), a consumer cannot distinguish a liquidation from a voluntary close via the event stream, nor see the liquidation fee. Position eviction doesn't care (both → remove the position), but risk/strategy/PnL logic does (e.g. Legion would want to know it got liquidated rather than chose to close).Proposal
Add
is_liquidation: boolandliq_fee: f64toMarketEvent::TakerClosed(and checkMakerClosedfor the sameisLiquidation/liqFeeshape — verify its deployed signature per #58), and populate them indecode_log:This pairs naturally with #58 (verifying the sibling close/liquidation bindings against the deployment). Surfaced by the Legion migration's
market_datareview.