ENG-484: add custodial NAV report timestamps#529
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
28cbd4e to
11ba5c0
Compare
|
|
||
| env.as_contract(&contract_id, || { | ||
| store_reported_assets(&env, &asset, 50); | ||
| store_report_nonce(&env, &asset, 7); |
| asset.clone(), | ||
| 9, | ||
| 11, | ||
| 2, |
There was a problem hiding this comment.
Warning
CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.
Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@contract/vault/soroban/custodial-adapter/src/lib.rs`:
- Around line 1332-1356: Update
failed_explicit_report_does_not_change_reported_at to first submit a successful
report with the initial nonce, then advance the ledger timestamp and replay that
same nonce with otherwise valid input. Assert the replay returns the expected
nonce-validation error and reported_at remains at the original timestamp,
ensuring replay rejection is checked after expected_current validation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: abb78618-4589-4776-9736-aa0342331aeb
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (8)
.github/workflows/test.ymlcontract/vault/soroban/AGENTS.mdcontract/vault/soroban/README.mdcontract/vault/soroban/custodial-adapter/Cargo.tomlcontract/vault/soroban/custodial-adapter/src/lib.rscontract/vault/soroban/custodial-adapter/tests/artifact_reported_at.rscontract/vault/soroban/justfilecontract/vault/soroban/scripts/check_custodial_adapter_release_abi.py
| fn failed_explicit_report_does_not_change_reported_at() { | ||
| let env = Env::default(); | ||
| env.mock_all_auths(); | ||
| let (contract_id, _admin, vault, _custodian, asset) = setup_adapter(&env); | ||
|
|
||
| env.ledger().set_timestamp(100); | ||
| set_reported_assets_for(&env, &contract_id, vault.clone(), asset.clone(), 10); | ||
|
|
||
| env.ledger().set_timestamp(200); | ||
| env.as_contract(&contract_id, || { | ||
| assert_eq!( | ||
| CustodialAdapterContract::set_reported_assets( | ||
| env.clone(), | ||
| vault, | ||
| asset.clone(), | ||
| 9, | ||
| 11, | ||
| 2, | ||
| ), | ||
| Err(AdapterError::InvalidInput) | ||
| ); | ||
| }); | ||
|
|
||
| assert_eq!(reported_at(&env, &contract_id, &asset), Some(100)); | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Cover the replay-specific timestamp invariant.
This test fails on expected_current before nonce validation. Add a literal replay after advancing the ledger timestamp and assert reported_at remains unchanged.
Suggested test
+ #[test]
+ fn replayed_report_does_not_change_reported_at() {
+ let env = Env::default();
+ env.mock_all_auths();
+ let (contract_id, _admin, vault, _custodian, asset) = setup_adapter(&env);
+
+ env.ledger().set_timestamp(100);
+ set_reported_assets_for(&env, &contract_id, vault.clone(), asset.clone(), 0);
+
+ env.ledger().set_timestamp(200);
+ env.as_contract(&contract_id, || {
+ assert_eq!(
+ CustodialAdapterContract::set_reported_assets(
+ env.clone(), vault, asset.clone(), 0, 0, 1,
+ ),
+ Err(AdapterError::InvalidInput)
+ );
+ });
+ assert_eq!(reported_at(&env, &contract_id, &asset), Some(100));
+ }As per coding guidelines, “Write comprehensive unit tests for new non-trivial logic.”
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| fn failed_explicit_report_does_not_change_reported_at() { | |
| let env = Env::default(); | |
| env.mock_all_auths(); | |
| let (contract_id, _admin, vault, _custodian, asset) = setup_adapter(&env); | |
| env.ledger().set_timestamp(100); | |
| set_reported_assets_for(&env, &contract_id, vault.clone(), asset.clone(), 10); | |
| env.ledger().set_timestamp(200); | |
| env.as_contract(&contract_id, || { | |
| assert_eq!( | |
| CustodialAdapterContract::set_reported_assets( | |
| env.clone(), | |
| vault, | |
| asset.clone(), | |
| 9, | |
| 11, | |
| 2, | |
| ), | |
| Err(AdapterError::InvalidInput) | |
| ); | |
| }); | |
| assert_eq!(reported_at(&env, &contract_id, &asset), Some(100)); | |
| } | |
| fn failed_explicit_report_does_not_change_reported_at() { | |
| let env = Env::default(); | |
| env.mock_all_auths(); | |
| let (contract_id, _admin, vault, _custodian, asset) = setup_adapter(&env); | |
| env.ledger().set_timestamp(100); | |
| set_reported_assets_for(&env, &contract_id, vault.clone(), asset.clone(), 10); | |
| env.ledger().set_timestamp(200); | |
| env.as_contract(&contract_id, || { | |
| assert_eq!( | |
| CustodialAdapterContract::set_reported_assets( | |
| env.clone(), | |
| vault, | |
| asset.clone(), | |
| 9, | |
| 11, | |
| 2, | |
| ), | |
| Err(AdapterError::InvalidInput) | |
| ); | |
| }); | |
| assert_eq!(reported_at(&env, &contract_id, &asset), Some(100)); | |
| } | |
| #[test] | |
| fn replayed_report_does_not_change_reported_at() { | |
| let env = Env::default(); | |
| env.mock_all_auths(); | |
| let (contract_id, _admin, vault, _custodian, asset) = setup_adapter(&env); | |
| env.ledger().set_timestamp(100); | |
| set_reported_assets_for(&env, &contract_id, vault.clone(), asset.clone(), 0); | |
| env.ledger().set_timestamp(200); | |
| env.as_contract(&contract_id, || { | |
| assert_eq!( | |
| CustodialAdapterContract::set_reported_assets( | |
| env.clone(), vault, asset.clone(), 0, 0, 1, | |
| ), | |
| Err(AdapterError::InvalidInput) | |
| ); | |
| }); | |
| assert_eq!(reported_at(&env, &contract_id, &asset), Some(100)); | |
| } |
🧰 Tools
🪛 GitHub Check: CodeQL
[failure] 1349-1349: Hard-coded cryptographic value
This hard-coded value is used as a nonce.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@contract/vault/soroban/custodial-adapter/src/lib.rs` around lines 1332 -
1356, Update failed_explicit_report_does_not_change_reported_at to first submit
a successful report with the initial nonce, then advance the ledger timestamp
and replay that same nonce with otherwise valid input. Assert the replay returns
the expected nonce-validation error and reported_at remains at the original
timestamp, ensuring replay rejection is checked after expected_current
validation.
Source: Coding guidelines
Summary
reported_at(asset) -> Result<Option<u64>, AdapterError>to the custodial adapter.set_reported_assetscall.templar-soroban-custodial-adapterto1.1.0and update its lockfile entry.Why
Custodial NAV reports exposed their value and nonce but not when the last explicit off-chain report
was accepted. Curators and monitors therefore could not measure report freshness independently of
normal custody lifecycle activity.
Compatibility
Noneuntil the next successful explicit report.Stack
This is PR 1 of 3 and targets
dev.Validation
cargo test -q -p templar-soroban-custodial-adapter— 42 passed.just -f contract/vault/soroban/justfile verify-custodial-adapter-release-abireported_at(address) -> Result<Option<u64>, AdapterError>interface;None.cargo fmt --all -- --checkgit diff --check11981bytes, hash03c1c749613d67d5ed460bc4fbb12eedb1a043068665a295fbefb774588a796b.Issue
ENG-484
This change is