Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ Soroban contract for revenue-share offerings and blacklist management.
| 18 | `InvalidPeriodId` | period_id is 0 where a positive value is required (#35). |
| 25 | `ReportingWindowClosed` | Current ledger timestamp is outside the configured reporting window; `report_revenue` rejected. |
| 26 | `ClaimWindowClosed` | Current ledger timestamp is outside the configured claiming window; `claim` rejected. |
| 47 | `MissingReportForOverride` | `report_revenue` rejected when `override_existing=true` is requested for a period that has no existing persisted report. Emits `rev_omiss`. |

Auth failures (e.g. wrong signer) are signaled by host/panic, not `RevoraError`. Use `try_register_offering`, `try_report_revenue`, and similar `try_*` client methods to receive contract errors as `Result`.

Expand All @@ -87,6 +88,7 @@ Auth failures (e.g. wrong signer) are signaled by host/panic, not `RevoraError`.
| `rev_init` | `(issuer, token), (amount, period_id, blacklist_vec)` | First persisted report for a period. |
| `rev_ovrd` | `(issuer, token), (new_amount, period_id, old_amount, blacklist_vec)` | Accepted correction of an existing persisted period (`override_existing=true`). |
| `rev_rej` | `(issuer, token), (attempted_amount, period_id, existing_amount, blacklist_vec)` | Duplicate report attempt for an existing period when `override_existing=false`; no state change. |
| `rev_omiss` | (`issuer, token`), (`attempted_amount, period_id`) | Rejected override attempt when `override_existing=true` is used for a period with no prior report. |
| `rev_rep` | `(issuer, token), (amount, period_id, blacklist_vec)` | Receipt for an accepted persisted report call (initial or override). Use `rev_init` plus `rev_ovrd` to reconstruct audit totals. |
| `bl_add` | `(token, caller), investor` | After `blacklist_add`. |
| `bl_rem` | `(token, caller), investor` | After `blacklist_remove`. |
Expand Down
25 changes: 25 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ const EVENT_REVENUE_REPORT_INITIAL_ASSET: Symbol = symbol_short!("rev_inia");
const EVENT_REVENUE_REPORT_OVERRIDE: Symbol = symbol_short!("rev_ovrd");
const EVENT_REVENUE_REPORT_OVERRIDE_ASSET: Symbol = symbol_short!("rev_ovra");
const EVENT_REVENUE_REPORT_REJECTED: Symbol = symbol_short!("rev_rej");
const EVENT_REVENUE_REPORT_MISSING_OVERRIDE: Symbol = symbol_short!("rev_omiss");
const EVENT_REVENUE_REPORT_REJECTED_ASSET: Symbol = symbol_short!("rev_reja");
pub const EVENT_SCHEMA_VERSION_V2: u32 = 2;

Expand Down Expand Up @@ -282,6 +283,7 @@ const EVENT_TYPE_OFFER: Symbol = symbol_short!("offer");
const EVENT_TYPE_REV_INIT: Symbol = symbol_short!("rv_init");
const EVENT_TYPE_REV_OVR: Symbol = symbol_short!("rv_ovr");
const EVENT_TYPE_REV_REJ: Symbol = symbol_short!("rv_rej");
const EVENT_TYPE_REV_OMISS: Symbol = symbol_short!("rv_omiss");
const EVENT_TYPE_REV_REP: Symbol = symbol_short!("rv_rep");
const EVENT_TYPE_CLAIM: Symbol = symbol_short!("claim");
const EVENT_REPORT_WINDOW_SET: Symbol = symbol_short!("rep_win");
Expand Down Expand Up @@ -2672,6 +2674,29 @@ impl RevoraRevenueShare {
}
None => {
if override_existing {
env.events().publish(
(
EVENT_REVENUE_REPORT_MISSING_OVERRIDE,
issuer.clone(),
namespace.clone(),
token.clone(),
),
(amount, period_id),
);
env.events().publish(
(
EVENT_INDEXED_V2,
EventIndexTopicV2 {
version: 2,
event_type: EVENT_TYPE_REV_OMISS,
issuer: issuer.clone(),
namespace: namespace.clone(),
token: token.clone(),
period_id,
},
),
(amount, period_id, payout_asset.clone()),
);
return Err(RevoraError::MissingReportForOverride);
}
// preserve existing initial-report behavior when override_existing=false
Expand Down
38 changes: 38 additions & 0 deletions src/test_duplicates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,41 @@ fn test_duplicate_report_revenue_rev_rej_event_payload() {
}
assert!(found_asset, "rev_reja event with correct payload must be emitted");
}

#[test]
fn test_override_missing_report_emits_rev_omiss_and_returns_missing_override() {
let (env, client, issuer, token, payout_asset) = setup_offering();
let namespace = symbol_short!("ns");
let attempted_amount: i128 = 123;
let period_id: u64 = 1;

let before = env.events().all().len();
let result = client.try_report_revenue(
&issuer,
&namespace,
&token,
&payout_asset,
&attempted_amount,
&period_id,
&true,
);

assert_eq!(result, Err(Ok(RevoraError::MissingReportForOverride)));

let mut found_rev_omiss = false;
for i in before..env.events().all().len() {
let (_, topics, data) = env.events().all().get(i).unwrap();
let topics_vec: soroban_sdk::Vec<Val> = topics.clone().into_val(&env);
let topic_sym: Symbol = topics_vec.get(0).unwrap().into_val(&env);
if topic_sym == symbol_short!("rev_omiss") {
let data_vec: soroban_sdk::Vec<Val> = data.clone().into_val(&env);
let amount: i128 = data_vec.get(0).unwrap().into_val(&env);
let pid: u64 = data_vec.get(1).unwrap().into_val(&env);
assert_eq!(amount, attempted_amount);
assert_eq!(pid, period_id);
found_rev_omiss = true;
break;
}
}
assert!(found_rev_omiss, "rev_omiss event with correct payload must be emitted");
}
Loading