Repository navigation
feat: add vote snapshot checkpointing, vault reentrancy guard, oracle failover, and standardized TTL configs (#793, #794, #795, #796) - #797
Merged
Jaydbrown merged 1 commit intoOct 18, 2026
Conversation
…uit-protocol#795, and conduit-protocol#796 - governor: add proposal vote tally snapshotting and balance checkpoints at snapshot ledger (Closes conduit-protocol#793) - token-vault: add transient reentrancy protection macro across all external token transfers (Closes conduit-protocol#794) - oracle: support fallback secondary oracle feed with automatic failover if primary feed fails (Closes conduit-protocol#795) - common: centralize MIN_TTL_LEDGERS, EXTEND_TTL_LEDGERS, and testnet/mainnet TTL config constants (Closes conduit-protocol#796)
|
@blurbeast 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! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
voting weights to the ledger sequence at which a proposal was created. In a token-weighted or account-delegated
governance model, evaluating voting power at vote time rather than at a fixed proposal snapshot ledger exposes
the protocol to vote-multiplication attacks: a single participant can cast a vote from one wallet, transfer their
governance tokens or weight to a secondary wallet after the proposal is already active, and vote a second time on
the exact same proposal to artificially inflate support or quorum.
contracts/governor/src/storage.rsand wired it intocontracts/governor/src/lib.rs:- Snapshot Ledger Anchoring: Extended
Proposalwithsnapshot_ledgerand addedDataKey::ProposalSnapshotLedger(u64)andDataKey::ProposalVoteSnapshot(u64)(VoteTallySnapshot). Whenproposeis invoked, the current ledger sequence (env.ledger().sequence()) and total governance supply areimmutably recorded for that proposal.
- Historical Balance Checkpoints: Added
BalanceCheckpoint { ledger, weight }stored inDataKey::VoteCheckpoints(Address)along withcheckpoint_balanceandget_prior_votes. Checkpoints record anaccount's voting weight at a specific ledger sequence.
- Snapshot-Time Weight Lookup & Double-Vote Prevention: During
cast_vote/cast_vote_with_rationale,the governor verifies that the voter has not already voted on the proposal via
DataKey::VoterReceipt(proposal_id, voter)(reverting withError::AlreadyVotedif so) and resolves the voter's weight strictly from checkpointsrecorded at or before
proposal.snapshot_ledger. Any tokens or weight acquired afterproposal.snapshot_ledgerresolve to zero weight for that proposal and are rejected with
Error::InsufficientVotingWeight.multi-token, and emergency migration entry points. While standard Stellar asset contracts do not re-enter caller
contracts, custom or arbitrary SEP-0041 token implementations can execute hooks during
transfercalls that re-invoke the vault before post-transfer balance assertions, accounting updates, or state cleanups are finalized.
contracts/token-vault/src/storage.rs, andcontracts/token-vault/src/errors.rs:- Transient Reentrancy Guard Macro: Defined
non_reentrant!(and aliasreentrancy_guard!) incontracts/token-vault/src/lib.rs, backed by Soroban temporary storage (DataKey::ReentrancyLock). Before anyexternal token invocation begins, the macro checks whether
DataKey::ReentrancyLockis set; if active, the callimmediately aborts with
Error::ReentrancyDetected. Otherwise, it sets the lock, executes the transfer block,and removes the lock from temporary storage upon completion.
- Comprehensive Transfer Coverage: Wrapped every external token transfer flow in
TokenVault(deposit,batch_deposit,withdraw_payoutscoveringwithdrawandwithdraw_batch,deposit_token,withdraw_token,and
execute_emergency_migration) withnon_reentrant!.on a single primary oracle provider. If the primary oracle node or contract becomes unresponsive, uninitialized,
or serves stale data beyond the configured
max_stalenesswindow, downstream stream settlements and fiat payoutconversions halt until manual administrative intervention occurs.
storage, along with admin-gated configuration entry points (
set_oracle_feeds,set_primary_oracle,set_fallback_oracle) and read accessors (primary_oracle,fallback_oracle).- Automatic Failover Resolution: Implemented
query_oracle_feedandresolve_oracle_with_failover,exposed via
get_price_with_fallbackand integrated intoget_twap_priceandlatest_price. The oracle queriesprimary_oraclefirst (supporting both local feeder submissions and external oracle contract cross-invocationsvia
try_invoke_contract) and validates freshness againstmax_staleness. If the primary feed is missing,unresponsive, or stale, execution seamlessly fails over to
fallback_oracle.ledger constants without distinguishing between Testnet and Mainnet ledger retention profiles, and some per-
contract
ttl.rsmodules still performed inlineextend_ttlcalls instead of delegating todrip-common.Inconsistent TTL thresholds risk premature state archival on Mainnet or unnecessary rent overhead on Testnet.
rs
(and re-exported them at the root ofdrip-common), preservingTTL_THRESHOLDandTTL_EXTEND_TOas aliases for backward compatibility. - **Testnet & Mainnet Profiles**: AddedTtlConfig,TESTNET_MIN_TTL_LEDGERS(17_280ledgers ≈ 1 day),TESTNET_EXTEND_TTL_LEDGERS(34_560ledgers ≈ 2 days),MAINNET_MIN_TTL_LEDGERS(100_000ledgers ≈ 5.8 days),MAINNET_EXTEND_TTL_LEDGERS(200_000ledgers ≈ 11.6 days), plusttl::testnetandttl::mainnetmodules and Cargo feature flags (testnet,mainnet). - **Unified Delegation**: Updatedcontracts/batch-processor/src/ttl.rsandcontracts/factory/src/ttl.rsto delegate directly todrip_common::ttl`.closes #793
closes #794
closes #795
closes #796