Skip to content

fix(contracts): prevent same-block borrow-to-liquidation edge case#223

Merged
Baskarayelu merged 3 commits intoCredenceOrg:mainfrom
solomonadzape95:disallow_same_block_and_borrow
Apr 1, 2026
Merged

fix(contracts): prevent same-block borrow-to-liquidation edge case#223
Baskarayelu merged 3 commits intoCredenceOrg:mainfrom
solomonadzape95:disallow_same_block_and_borrow

Conversation

@solomonadzape95
Copy link
Copy Markdown
Contributor

@solomonadzape95 solomonadzape95 commented Mar 30, 2026

fix(contracts): prevent same-ledger borrow-to-liquidation edge case

fixes #169

Summary

This change prevents a same-ledger (same block/sequence) sandwich-style edge where collateral can be increased and a subsequent slash (liquidation equivalent) is executed before the next ledger, enabling unfair penalties. The guard rejects slashing only when the last collateral increase happened in the current ledger, while allowing legitimate liquidations in later ledgers.

Design

  • Uses Soroban ledger ordering via e.ledger().sequence() as the “block height”.
  • On any successful collateral increase, records the current ledger sequence.
  • On slash entry points, checks the recorded sequence:
    • If it matches the current ledger sequence, the call panics (same-ledger restriction).
    • If unset (e.g., pre-upgrade storage), the slash is allowed.

This is intentionally narrow and does not impose a global throttle. It only guards slash/liquidation-like operations; withdrawals, early exits, renewals, attestations, claims, and governance remain unaffected.

Implementation

New guard module

  • Added contracts/credence_bond/src/same_ledger_liquidation_guard.rs
    • record_collateral_increase(e): stores e.ledger().sequence() in storage
    • require_slash_allowed_after_collateral_increase(e): panics with:
      • slash blocked: collateral increased in this ledger

Storage key

  • Added DataKey::LastCollateralIncreaseLedger in contracts/credence_bond/src/lib.rs

Where we record collateral increases

  • create_bond_with_rolling in contracts/credence_bond/src/lib.rs
  • top_up in contracts/credence_bond/src/lib.rs
  • increase_bond in contracts/credence_bond/src/lib.rs
  • create_batch_bonds in contracts/credence_bond/src/batch.rs (after creating the bonds)

Where we enforce the guard on slashing

  • contracts/credence_bond/src/slashing.rs: called inside slash_bond so it covers the slashing flow
  • contracts/credence_bond/src/lib.rs: called inside CredenceBond::slash_bond entrypoint as well

Tests

  • Added contracts/credence_bond/src/test_same_ledger_liquidation_guard.rs

    • Verifies slashing is rejected when it occurs in the same ledger immediately after:
      • increase_bond
      • top_up
      • create_bond_with_rolling
    • Verifies slashing succeeds after advancing the ledger sequence by 1.
  • Updated contracts/credence_bond/src/test_helpers.rs with a test utility to advance ledger sequence so existing slashing/integration tests can perform slashing in a subsequent ledger (ensuring no unintended regression of healthy flows).

Backwards compatibility / migration notes

  • The guard allows slashing when LastCollateralIncreaseLedger is unset, so existing positions prior to deployment should not get bricked until the account performs a new collateral increase.
  • Adding DataKey enum variants can have upgrade/migration implications depending on how the contract is deployed/upgraded. If this is a live contract, validate Soroban storage migration expectations or consider switching to a standalone Symbol key for the new storage slot.

Security Considerations

  • Scoped narrowly to slash/liquidation-like operations to avoid harming protocol throughput.
  • Prevents same-ledger collateral increase -> slash sequencing edge case by enforcing a minimum ledger distance of 1 (same ledger blocked, next ledger allowed).

Follow-up (optional)

  • Consider refactoring to ensure slashing entrypoints share a single implementation path (to further reduce the chance of missing the guard in future slash-related functions).

@drips-wave
Copy link
Copy Markdown

drips-wave bot commented Mar 30, 2026

@solomonadzape95 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Baskarayelu Baskarayelu merged commit 1b30062 into CredenceOrg:main Apr 1, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Disallow same-block borrow and liquidation on same account

2 participants