Skip to content

Conversation

@yan-man
Copy link

@yan-man yan-man commented Aug 29, 2025

  • update horizon docs re: Price Oracle Safeguards

@github-actions
Copy link

Download Logs

Copy link

@certora-run certora-run bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verification Results

  • Group ID: 4eacd9cd-8ee6-48f5-aa5c-da154166580a
Job Result VERIFIED Link
VariableDebtToken.conf 15 Link
UserConfiguration.conf 13 Link
stableRemoved.conf 2 Link
RwaAToken.conf 13 Link
ReserveConfiguration.conf 19 Link
NEW-pool-simple-properties.conf --rule_sanity none --rule cannotBorrowZeroAmount 1 Link
NEW-pool-simple-properties.conf --rule_sanity none --rule cannotBorrowOnReserveDisabledForBorrowing 1 Link
NEW-pool-simple-properties.conf --rule_sanity none --rule cannotBorrowOnInactiveReserve 1 Link
NEW-pool-simple-properties.conf --rule_sanity none --rule cannotBorrowOnFrozenReserve 1 Link
NEW-pool-simple-properties.conf --rule cannotWithdrawZeroAmount 1 Link
NEW-pool-simple-properties.conf --rule cannotWithdrawFromInactiveReserve 1 Link
NEW-pool-simple-properties.conf --rule cannotDepositZeroAmount 1 Link
NEW-pool-simple-properties.conf --rule cannotDepositInInactiveReserve 1 Link
NEW-pool-simple-properties.conf --rule cannotDepositInFrozenReserve 1 Link
NEW-pool-no-summarizations.conf 3 Link
EModeConfiguration.conf 5 Link
AToken.conf 13 Link

Copy link

@certora-run certora-run bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verification Results

  • Group ID: 0bd42b0b-92bf-4361-82b0-55ed91656ae9
Job Result VERIFIED Link
VariableDebtToken.conf 15 Link
UserConfiguration.conf 13 Link
stableRemoved.conf 2 Link
RwaAToken.conf 13 Link
ReserveConfiguration.conf 19 Link
NEW-pool-simple-properties.conf --rule_sanity none --rule cannotBorrowZeroAmount 1 Link
NEW-pool-simple-properties.conf --rule_sanity none --rule cannotBorrowOnReserveDisabledForBorrowing 1 Link
NEW-pool-simple-properties.conf --rule_sanity none --rule cannotBorrowOnInactiveReserve 1 Link
NEW-pool-simple-properties.conf --rule_sanity none --rule cannotBorrowOnFrozenReserve 1 Link
NEW-pool-simple-properties.conf --rule cannotWithdrawZeroAmount 1 Link
NEW-pool-simple-properties.conf --rule cannotWithdrawFromInactiveReserve 1 Link
NEW-pool-simple-properties.conf --rule cannotDepositZeroAmount 1 Link
NEW-pool-simple-properties.conf --rule cannotDepositInInactiveReserve 1 Link
NEW-pool-simple-properties.conf --rule cannotDepositInFrozenReserve 1 Link
NEW-pool-no-summarizations.conf 3 Link
EModeConfiguration.conf 5 Link
AToken.conf 13 Link

Copy link

@certora-run certora-run bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verification Results

  • Group ID: 08f8e798-8642-4ab5-b04a-2dc95fd64b02
Job Result VERIFIED Link
verifyStataToken.conf --rule totalClaimableRewards_stable 2 Link
verifyStataToken.conf --rule totalAssets_stable 2 Link
verifyStataToken.conf --rule solvency_total_asset_geq_total_supply 2 Link
verifyStataToken.conf --rule solvency_positive_total_supply_only_if_positive_asset 2 Link
verifyStataToken.conf --rule singleAssetAccruedRewards 2 Link
verifyStataToken.conf --rule rewardsTotalDeclinesOnlyByClaim 2 Link
verifyStataToken.conf --rule rewardsConsistencyWhenSufficientRewardsExist 2 Link
verifyStataToken.conf --rule rewardsConsistencyWhenInsufficientRewards 2 Link
verifyStataToken.conf --rule getClaimableRewards_stable 2 Link
verifyStataToken.conf --rule getClaimableRewards_stable_after_refreshRewardTokens 2 Link
verifyStataToken.conf --rule getClaimableRewards_stable_after_deposit 2 Link
verifyStataToken.conf --rule getClaimableRewardsBefore_leq_claimed_claimRewardsOnBehalf 2 Link
verifyERC4626Extended.conf --rule redeemSum 2 Link
verifyERC4626Extended.conf --rule redeemATokensSum 2 Link
verifyERC4626DepositSummarization.conf --rule depositCheckIndexGRayAssert1 depositATokensCheckIndexGRayAssert1 depositWithPermitCheckIndexGRayAssert1 depositCheckIndexERayAssert1 depositATokensCheckIndexERayAssert1 depositWithPermitCheckIndexERayAssert1 7 Link
verifyERC4626.conf --rule maxMintMustntRevert maxDepositMustntRevert maxRedeemMustntRevert maxWithdrawMustntRevert totalAssetsMustntRevert 6 Link
verifyDoubleClaim.conf --rule prevent_duplicate_reward_claiming_single_reward_sufficient 2 Link
verifyDoubleClaim.conf --rule prevent_duplicate_reward_claiming_single_reward_insufficient 2 Link
verifyAToken.conf --rule aTokenBalanceIsFixed_for_collectAndUpdateRewards aTokenBalanceIsFixed_for_claimRewards aTokenBalanceIsFixed_for_claimRewardsOnBehalf 4 Link
verifyAToken.conf --rule aTokenBalanceIsFixed_for_claimSingleRewardOnBehalf aTokenBalanceIsFixed_for_claimRewardsToSelf 3 Link
tWithPermitCheckIndexGRayAssert2 depositCheckIndexERayAssert2 depositATokensCheckIndexERayAssert2 depositWithPermitCheckIndexERayAssert2 mintCheckIndexGRayUpperBound mintCheckIndexGRayLowerBound mintCheckIndexEqualsRay 10 Link
ToAssetsCheck convertToSharesCheck toAssetsDoesNotRevert sharesConversionRoundedDown toSharesDoesNotRevert previewDepositAmountCheck maxRedeemCompliance maxWithdrawConversionCompliance previewMintIndependentOfAllowance 23 Link
ingRange previewRedeemRoundingRange amountConversionPreserved sharesConversionPreserved accountsJoiningSplittingIsLimited convertSumOfAssetsPreserved previewDepositSameAsDeposit previewMintSameAsMint maxDepositConstant 10 Link


Unlike crypto-native assets priced by decentralized exchange markets, RWAs rely on a Net Asset Value (NAV) reported directly by the asset issuer. This introduces a critical risk vector: the potential for delayed, inaccurate, or malicious price reporting. A simple operational error or a malicious act could lead to an incorrect NAV being published on-chain, which could trigger faulty liquidations across the market. While an emergency multisig can reactively freeze the reserve, this process introduces operational delays, creating a window where whitelisted liquidators could exploit a faulty price and cause irreparable harm to borrowers.

Horizon implements a robust, automated safeguard directly at the Oracle level to mitigate this risk. In partnership with Chainlink and LlamaRisk, pre-defined upper and lower price bounds are configured for each RWA price feed at the Decentralized Oracle Network (DON) level. When an issuer reports a new NAV, the Chainlink DON validates it against these bounds before publishing it on-chain. If the reported NAV is within the bounds, the update is accepted. If it is outside the bounds, the DON rejects the update, and the oracle continues to report the last known valid price. This proactive mechanism prevents a faulty price from ever reaching the Horizon protocol, eliminating the risk of erroneous liquidations. Furthermore, any breach of these price bounds is paired with a time-sensitive reaction from Horizon's emergency multisig to prevent new loan originations and additional exposure until the root cause analysis is performed.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Horizon implements a robust, automated safeguard directly at the Oracle level to mitigate this risk. In partnership with Chainlink and LlamaRisk, pre-defined upper and lower price bounds are configured for each RWA price feed at the Decentralized Oracle Network (DON) level. When an issuer reports a new NAV, the Chainlink DON validates it against these bounds before publishing it on-chain. If the reported NAV is within the bounds, the update is accepted. If it is outside the bounds, the DON rejects the update, and the oracle continues to report the last known valid price. This proactive mechanism prevents a faulty price from ever reaching the Horizon protocol, eliminating the risk of erroneous liquidations. Furthermore, any breach of these price bounds is paired with a time-sensitive reaction from Horizon's emergency multisig to prevent new loan originations and additional exposure until the root cause analysis is performed.
Horizon implements a robust, automated safeguard directly at the Oracle level to mitigate this risk. In partnership with Chainlink and LlamaRisk, pre-defined upper and lower price bounds are configured for each RWA price feed at the Decentralized Oracle Network (DON) level. When an issuer reports a new NAV, the Chainlink DON validates it against these bounds before publishing it on-chain. If the reported NAV is within the bounds, the update is accepted. If it is outside the bounds, the DON rejects the update, and the oracle continues to report the last known valid price. This proactive mechanism prevents a faulty price from ever reaching the Horizon protocol, eliminating the risk of erroneous liquidations. Furthermore, any breach of these price bounds is paired with a time-sensitive reaction from Horizon's emergency stewards to prevent new debt originations and additional exposure until the root cause analysis is performed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

@certora-run certora-run bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verification Results

  • Group ID: 29979174-3926-4901-88c3-8d7b36eec55a
Job Result VERIFIED Link
VariableDebtToken.conf 15 Link
UserConfiguration.conf 13 Link
stableRemoved.conf 2 Link
RwaAToken.conf 13 Link
ReserveConfiguration.conf 19 Link
NEW-pool-simple-properties.conf --rule_sanity none --rule cannotBorrowZeroAmount 1 Link
NEW-pool-simple-properties.conf --rule_sanity none --rule cannotBorrowOnReserveDisabledForBorrowing 1 Link
NEW-pool-simple-properties.conf --rule_sanity none --rule cannotBorrowOnInactiveReserve 1 Link
NEW-pool-simple-properties.conf --rule_sanity none --rule cannotBorrowOnFrozenReserve 1 Link
NEW-pool-simple-properties.conf --rule cannotWithdrawZeroAmount 1 Link
NEW-pool-simple-properties.conf --rule cannotWithdrawFromInactiveReserve 1 Link
NEW-pool-simple-properties.conf --rule cannotDepositZeroAmount 1 Link
NEW-pool-simple-properties.conf --rule cannotDepositInInactiveReserve 1 Link
NEW-pool-simple-properties.conf --rule cannotDepositInFrozenReserve 1 Link
NEW-pool-no-summarizations.conf 3 Link
EModeConfiguration.conf 5 Link
AToken.conf 13 Link

Copy link

@certora-run certora-run bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verification Results

  • Group ID: 53f6b887-530c-46c6-b9cb-0057f6895000
Job Result VERIFIED Link
verifyStataToken.conf --rule totalClaimableRewards_stable 2 Link
verifyStataToken.conf --rule totalAssets_stable 2 Link
verifyStataToken.conf --rule solvency_total_asset_geq_total_supply 2 Link
verifyStataToken.conf --rule solvency_positive_total_supply_only_if_positive_asset 2 Link
verifyStataToken.conf --rule singleAssetAccruedRewards 2 Link
verifyStataToken.conf --rule rewardsTotalDeclinesOnlyByClaim 0 Link
verifyStataToken.conf --rule rewardsConsistencyWhenSufficientRewardsExist 2 Link
verifyStataToken.conf --rule rewardsConsistencyWhenInsufficientRewards 2 Link
verifyStataToken.conf --rule getClaimableRewards_stable 2 Link
verifyStataToken.conf --rule getClaimableRewards_stable_after_refreshRewardTokens 2 Link
verifyStataToken.conf --rule getClaimableRewards_stable_after_deposit 2 Link
verifyStataToken.conf --rule getClaimableRewardsBefore_leq_claimed_claimRewardsOnBehalf 2 Link
verifyERC4626Extended.conf --rule redeemSum 2 Link
verifyERC4626Extended.conf --rule redeemATokensSum 2 Link
verifyERC4626DepositSummarization.conf --rule depositCheckIndexGRayAssert1 depositATokensCheckIndexGRayAssert1 depositWithPermitCheckIndexGRayAssert1 depositCheckIndexERayAssert1 depositATokensCheckIndexERayAssert1 depositWithPermitCheckIndexERayAssert1 7 Link
verifyERC4626.conf --rule maxMintMustntRevert maxDepositMustntRevert maxRedeemMustntRevert maxWithdrawMustntRevert totalAssetsMustntRevert 6 Link
verifyDoubleClaim.conf --rule prevent_duplicate_reward_claiming_single_reward_sufficient 2 Link
verifyDoubleClaim.conf --rule prevent_duplicate_reward_claiming_single_reward_insufficient 2 Link
verifyAToken.conf --rule aTokenBalanceIsFixed_for_collectAndUpdateRewards aTokenBalanceIsFixed_for_claimRewards aTokenBalanceIsFixed_for_claimRewardsOnBehalf 4 Link
verifyAToken.conf --rule aTokenBalanceIsFixed_for_claimSingleRewardOnBehalf aTokenBalanceIsFixed_for_claimRewardsToSelf 3 Link
tWithPermitCheckIndexGRayAssert2 depositCheckIndexERayAssert2 depositATokensCheckIndexERayAssert2 depositWithPermitCheckIndexERayAssert2 mintCheckIndexGRayUpperBound mintCheckIndexGRayLowerBound mintCheckIndexEqualsRay 10 Link
ToAssetsCheck convertToSharesCheck toAssetsDoesNotRevert sharesConversionRoundedDown toSharesDoesNotRevert previewDepositAmountCheck maxRedeemCompliance maxWithdrawConversionCompliance previewMintIndependentOfAllowance 23 Link
ingRange previewRedeemRoundingRange amountConversionPreserved sharesConversionPreserved accountsJoiningSplittingIsLimited convertSumOfAssetsPreserved previewDepositSameAsDeposit previewMintSameAsMint maxDepositConstant 10 Link

@yan-man yan-man requested a review from avniculae September 23, 2025 22:26
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.

3 participants