Skip to content

Commit 4695fcc

Browse files
Merge pull request #1066 from abdoolyaro/docs/957-960-ink-message-doc-comments
docs: add doc comments to all ink! messages in sanctions, version-reg…
2 parents 075198b + ace7656 commit 4695fcc

4 files changed

Lines changed: 308 additions & 0 deletions

File tree

contracts/fractional/src/lib.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,16 +348,41 @@ pub mod fractional {
348348
}
349349

350350
impl Fractional {
351+
/// Records the last-known price per share for `token_id`.
352+
///
353+
/// Not payable. Open to any caller -- this message performs no
354+
/// access-control or ownership check, and unconditionally
355+
/// overwrites any previously stored price. Never fails; there is no
356+
/// `Result` return. The stored value feeds `redeem_shares`'s payout
357+
/// calculation and is used as the fallback price in
358+
/// `aggregate_portfolio` when a caller does not supply its own
359+
/// price for a token.
351360
#[ink(message)]
352361
pub fn set_last_price(&mut self, token_id: u64, price_per_share: u128) {
353362
self.last_prices.insert(token_id, &price_per_share);
354363
}
355364

365+
/// Returns the last-known price per share for `token_id`, as most
366+
/// recently set by `set_last_price`.
367+
///
368+
/// Open to any caller. Returns `None` if no price has ever been set
369+
/// for `token_id`.
356370
#[ink(message)]
357371
pub fn get_last_price(&self, token_id: u64) -> Option<u128> {
358372
self.last_prices.get(token_id)
359373
}
360374

375+
/// Computes the total value of a caller-supplied list of holdings, a
376+
/// read-only convenience calculation that does not touch this
377+
/// contract's own balance records.
378+
///
379+
/// Open to any caller. For each `PortfolioItem`, uses
380+
/// `item.price_per_share` if it is nonzero, otherwise falls back to
381+
/// this contract's stored `last_prices` for `item.token_id` (`0` if
382+
/// none is stored). Returns the summed `total_value` along with a
383+
/// per-item `(token_id, shares, price_used)` breakdown in
384+
/// `positions`, in the same order as the input `items`. All
385+
/// arithmetic saturates rather than overflowing. Never fails.
361386
#[ink(message)]
362387
pub fn aggregate_portfolio(&self, items: Vec<PortfolioItem>) -> PortfolioAggregation {
363388
let mut total: u128 = 0;
@@ -378,6 +403,15 @@ pub mod fractional {
378403
}
379404
}
380405

406+
/// Summarizes caller-supplied dividend and proceeds records into
407+
/// total dividends, total proceeds, and a transaction count.
408+
///
409+
/// Open to any caller. This is a pure calculation over the `dividends`
410+
/// and `proceeds` arguments; it does not read or write any of this
411+
/// contract's own storage, so it reflects only what the caller
412+
/// passes in, not this contract's actual transaction history.
413+
/// `transactions` is the combined length of both input lists. All
414+
/// arithmetic saturates rather than overflowing. Never fails.
381415
#[ink(message)]
382416
pub fn summarize_tax(
383417
&self,

contracts/prediction-market/src/lib.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,13 +243,37 @@ pub mod propchain_prediction_market {
243243
}
244244
}
245245

246+
/// Sets the oracle account address for this contract. Admin-only.
247+
///
248+
/// Not payable. Note: this address is currently informational only
249+
/// for the manual-resolution markets (`create_market` /
250+
/// `resolve_market`), which are resolved directly by the admin, not
251+
/// by checking this value. It is used as the required caller for
252+
/// `submit_oracle_data` on oracle-driven markets.
253+
///
254+
/// # Errors
255+
/// - `Error::Unauthorized` if the caller is not the contract admin.
246256
#[ink(message)]
247257
pub fn set_oracle(&mut self, oracle: AccountId) -> Result<(), Error> {
248258
self.ensure_admin()?;
249259
self.oracle_address = Some(oracle);
250260
Ok(())
251261
}
252262

263+
/// Creates a new manual-resolution prediction market for a property
264+
/// metric and returns its `market_id`. Admin-only.
265+
///
266+
/// Not payable. The market starts `Active` with zero stakes on both
267+
/// sides. Once `resolution_time` (a block timestamp) has passed, the
268+
/// admin resolves the market with `resolve_market`, comparing the
269+
/// submitted value against `target_value`. Emits `MarketCreated`.
270+
///
271+
/// This is the manual-resolution counterpart to
272+
/// `create_oracle_market`; the two market kinds are tracked in
273+
/// separate id spaces and are not interchangeable in other messages.
274+
///
275+
/// # Errors
276+
/// - `Error::Unauthorized` if the caller is not the contract admin.
253277
#[ink(message)]
254278
pub fn create_market(
255279
&mut self,
@@ -286,6 +310,23 @@ pub mod propchain_prediction_market {
286310
Ok(market_id)
287311
}
288312

313+
/// Stakes the transferred value on `direction` (Long or Short) for a
314+
/// manual-resolution market. Payable; the transferred value is the
315+
/// stake amount.
316+
///
317+
/// Open to any caller. Repeated calls for the same `market_id` by the
318+
/// same caller add to their existing stake, provided the direction
319+
/// matches; this contract does not support hedging both directions
320+
/// on the same market from one account. Emits `PredictionStaked`.
321+
///
322+
/// # Errors
323+
/// - `Error::InvalidAmount` if no value was transferred, or if the
324+
/// caller already holds a stake on this market in the opposite
325+
/// direction.
326+
/// - `Error::MarketNotFound` if `market_id` does not exist.
327+
/// - `Error::MarketNotActive` if the market is not `Active`, or if
328+
/// its `resolution_time` has already passed (staking closes at
329+
/// resolution time, before `resolve_market` is even called).
289330
#[ink(message, payable)]
290331
pub fn stake_prediction(
291332
&mut self,
@@ -343,6 +384,29 @@ pub mod propchain_prediction_market {
343384
Ok(())
344385
}
345386

387+
/// Resolves a manual-resolution market by admin-submitted
388+
/// `resolved_value`, deciding the winning direction. Admin-only.
389+
///
390+
/// Not payable. `Long` wins if `resolved_value >= target_value`,
391+
/// otherwise `Short` wins. Can only be called once per market, and
392+
/// only after `resolution_time` has passed. Emits `MarketResolved`.
393+
///
394+
/// # Screening / trust note
395+
/// This value is currently supplied directly by the admin account,
396+
/// not verified against `oracle_address` or any external data feed.
397+
/// Oracle-driven settlement for this market type is tracked
398+
/// separately; today's guarantee is only that the admin attests to
399+
/// `resolved_value`. Oracle-driven markets created via
400+
/// `create_oracle_market` are resolved differently, via
401+
/// `submit_oracle_data`.
402+
///
403+
/// # Errors
404+
/// - `Error::Unauthorized` if the caller is not the contract admin.
405+
/// - `Error::MarketNotFound` if `market_id` does not exist.
406+
/// - `Error::MarketAlreadyResolved` if the market is not `Active`
407+
/// (already resolved or cancelled).
408+
/// - `Error::MarketNotReadyForResolution` if `resolution_time` has
409+
/// not yet passed.
346410
#[ink(message)]
347411
pub fn resolve_market(
348412
&mut self,
@@ -380,6 +444,31 @@ pub mod propchain_prediction_market {
380444
Ok(())
381445
}
382446

447+
/// Claims the caller's payout from a resolved manual-resolution
448+
/// market, transferring it to the caller. Not payable.
449+
///
450+
/// Open to any caller who holds a stake on `market_id`. A winning
451+
/// stake's payout is
452+
/// `stake + stake * losing_pool / winning_pool`, minus a protocol
453+
/// fee of `fee_bips` (in basis points, set at construction). A
454+
/// losing stake cannot claim and instead records unsuccessful-
455+
/// prediction reputation for the caller (see `get_user_reputation`);
456+
/// a winning claim records successful-prediction reputation. Each
457+
/// stake can be claimed at most once. Guarded against reentrancy.
458+
/// Emits `RewardClaimed` on success.
459+
///
460+
/// # Errors
461+
/// - `Error::MarketNotFound` if `market_id` does not exist.
462+
/// - `Error::MarketNotActive` if the market has not been resolved
463+
/// yet.
464+
/// - `Error::StakeNotFound` if the caller has no stake on this
465+
/// market.
466+
/// - `Error::RewardAlreadyClaimed` if the caller already claimed
467+
/// this stake.
468+
/// - `Error::LoserCannotClaim` if the caller's stake was on the
469+
/// losing direction.
470+
/// - `Error::TransferFailed` if the payout transfer fails.
471+
/// - `Error::ReentrantCall` if called reentrantly.
383472
#[ink(message)]
384473
pub fn claim_reward(&mut self, market_id: u64) -> Result<(), Error> {
385474
non_reentrant!(self, {
@@ -438,6 +527,15 @@ pub mod propchain_prediction_market {
438527
})
439528
}
440529

530+
/// Returns `user`'s prediction reputation: total predictions made,
531+
/// how many resolved in the user's favor, and an accuracy score out
532+
/// of 10000 (e.g. `7500` = 75%).
533+
///
534+
/// Open to any caller. Reputation is only updated by
535+
/// `claim_reward` (manual-resolution markets), not by
536+
/// `claim_winnings` (oracle markets). A user who has never claimed a
537+
/// manual-resolution reward gets a zeroed-out `UserReputation`
538+
/// rather than an error.
441539
#[ink(message)]
442540
pub fn get_user_reputation(&self, user: AccountId) -> UserReputation {
443541
self.reputations.get(&user).unwrap_or(UserReputation {
@@ -447,11 +545,28 @@ pub mod propchain_prediction_market {
447545
})
448546
}
449547

548+
/// Returns the manual-resolution market info for `market_id`, if it
549+
/// exists.
550+
///
551+
/// Open to any caller. Returns `None` if `market_id` was never
552+
/// created via `create_market`. For oracle-driven markets, use
553+
/// `get_oracle_market` instead -- the two id spaces are separate.
450554
#[ink(message)]
451555
pub fn get_market(&self, market_id: u64) -> Option<PredictionMarketInfo> {
452556
self.markets.get(&market_id)
453557
}
454558

559+
/// Records a backtest-accuracy attestation for a market and emits
560+
/// `BacktestValidated`. Admin-only. Not payable.
561+
///
562+
/// This message does not verify `historical_accuracy` or
563+
/// `model_version` against anything (no proof check, no stored
564+
/// mapping) -- it only accepts the admin's submitted values and
565+
/// emits the event for off-chain consumption. It does not affect
566+
/// market resolution, staking, or payouts.
567+
///
568+
/// # Errors
569+
/// - `Error::Unauthorized` if the caller is not the contract admin.
455570
#[ink(message)]
456571
pub fn submit_backtest_data(
457572
&mut self,

contracts/sanctions/lib.rs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,13 +260,28 @@ pub mod sanctions_screening {
260260
Ok(())
261261
}
262262

263+
/// Returns the sanctioned-entity record for `entity_id`, if one exists.
264+
///
265+
/// Open to any caller. Returns `None` if `entity_id` has never been
266+
/// registered. The returned record may have `active == false` if the
267+
/// entity was later removed via `remove_sanctioned_entity`; callers that
268+
/// care about current sanction status should check `active` themselves.
263269
#[ink(message)]
264270
pub fn get_sanctioned_entity(&self, entity_id: u64) -> Option<SanctionedEntity> {
265271
self.sanctioned_entities.get(entity_id)
266272
}
267273

268274
// ── Admin: Manage sanctioned properties ─────────────────────────────
269275

276+
/// Adds a property to the sanctions list, keyed by caller-supplied
277+
/// `property_id`. Admin-only.
278+
///
279+
/// Unlike `add_sanctioned_entity`, `property_id` is not auto-assigned;
280+
/// calling this again with the same `property_id` overwrites the
281+
/// existing record. Emits `PropertySanctioned`.
282+
///
283+
/// # Errors
284+
/// - `Error::NotAuthorized` if the caller is not the contract admin.
270285
#[ink(message)]
271286
pub fn add_sanctioned_property(
272287
&mut self,
@@ -294,6 +309,16 @@ pub mod sanctions_screening {
294309
Ok(())
295310
}
296311

312+
/// Deactivates a sanctioned property. Admin-only.
313+
///
314+
/// Sets the property's `active` flag to `false`. The record is kept
315+
/// (not deleted) so it remains queryable via `get_sanctioned_property`.
316+
/// Emits `PropertyCleared`.
317+
///
318+
/// # Errors
319+
/// - `Error::NotAuthorized` if the caller is not the contract admin.
320+
/// - `Error::PropertyNotFound` if no property is registered under
321+
/// `property_id`.
297322
#[ink(message)]
298323
pub fn clear_sanctioned_property(&mut self, property_id: u64) -> Result<()> {
299324
self.ensure_admin()?;
@@ -310,13 +335,49 @@ pub mod sanctions_screening {
310335
Ok(())
311336
}
312337

338+
/// Returns the sanctioned-property record for `property_id`, if one
339+
/// exists.
340+
///
341+
/// Open to any caller. Returns `None` if `property_id` was never listed.
342+
/// The returned record may have `active == false` if it was later
343+
/// cleared via `clear_sanctioned_property`; callers that care about
344+
/// current sanction status should check `active` themselves.
313345
#[ink(message)]
314346
pub fn get_sanctioned_property(&self, property_id: u64) -> Option<SanctionedProperty> {
315347
self.sanctioned_properties.get(property_id)
316348
}
317349

318350
// ── Screening ───────────────────────────────────────────────────────
319351

352+
/// Screens a property (and, optionally, an associated entity) against
353+
/// the sanctions lists, and records the outcome. Admin-only.
354+
///
355+
/// Checks are evaluated in order and the first match wins:
356+
/// 1. If `property_id` is itself an active sanctioned property, the
357+
/// screening fails (`passed = false`) with that property's
358+
/// `sanction_level`, regardless of `entity_id`.
359+
/// 2. Otherwise, if `entity_id` is `Some` and refers to an active
360+
/// sanctioned entity whose `jurisdiction_code` matches the one
361+
/// passed in, the screening fails with that entity's
362+
/// `sanction_level`.
363+
/// 3. Otherwise the screening passes with `SanctionLevel::None`. This
364+
/// includes the case where `jurisdiction_code` does not match any
365+
/// known jurisdiction: an unrecognized jurisdiction is not itself
366+
/// grounds for failure.
367+
///
368+
/// Every call stores a new `ScreeningResult` (auto-incrementing
369+
/// `screening_id`), appends it to the property's screening history
370+
/// (see `get_property_screenings`), and emits `ScreeningsPerformed`.
371+
///
372+
/// # Screening guarantee
373+
/// This lookup runs in time proportional to whether `property_id` and
374+
/// `entity_id` are present in storage (a `Mapping::get` per check), not
375+
/// in constant time.
376+
///
377+
/// # Errors
378+
/// - `Error::NotAuthorized` if the caller is not the contract admin.
379+
/// - `Error::ThresholdExceeded` if the internal screening-id counter
380+
/// has been exhausted (`u64::MAX` screenings recorded).
320381
#[ink(message)]
321382
pub fn screen_property(
322383
&mut self,
@@ -421,11 +482,23 @@ pub mod sanctions_screening {
421482
self.property_screenings.insert(property_id, &existing);
422483
}
423484

485+
/// Returns a single screening result by its `screening_id`, if one
486+
/// exists.
487+
///
488+
/// Open to any caller. Returns `None` if `screening_id` was never
489+
/// recorded (every `screen_property` call produces exactly one).
424490
#[ink(message)]
425491
pub fn get_screening_result(&self, screening_id: u64) -> Option<ScreeningResult> {
426492
self.screening_results.get(screening_id)
427493
}
428494

495+
/// Returns the full screening history for a property, in the order
496+
/// the screenings were performed.
497+
///
498+
/// Open to any caller. Returns an empty `Vec` if `property_id` has
499+
/// never been screened. Any screening id recorded against the property
500+
/// that can no longer be resolved to a stored result is silently
501+
/// skipped rather than causing an error.
429502
#[ink(message)]
430503
pub fn get_property_screenings(&self, property_id: u64) -> Vec<ScreeningResult> {
431504
match self.property_screenings.get(property_id) {
@@ -442,16 +515,40 @@ pub mod sanctions_screening {
442515
}
443516
}
444517

518+
/// Returns whether `property_id` has ever been screened, i.e. whether
519+
/// `screen_property` has been called for it at least once.
520+
///
521+
/// Open to any caller. This does not indicate pass/fail status, only
522+
/// that a screening history exists; use `get_property_screenings` or
523+
/// `get_screening_result` to inspect outcomes.
445524
#[ink(message)]
446525
pub fn is_property_screened(&self, property_id: u64) -> bool {
447526
self.property_screenings.get(property_id).is_some()
448527
}
449528

529+
/// Returns the account currently authorized to call the admin-only
530+
/// messages on this contract (`add_sanctioned_entity`,
531+
/// `remove_sanctioned_entity`, `add_sanctioned_property`,
532+
/// `clear_sanctioned_property`, `screen_property`,
533+
/// `set_screening_threshold`, and `set_max_sanctioned_entities`).
534+
///
535+
/// Open to any caller. There is no message to transfer admin rights;
536+
/// the admin is fixed to the account that called the constructor.
450537
#[ink(message)]
451538
pub fn admin(&self) -> AccountId {
452539
self.admin
453540
}
454541

542+
/// Updates the screening-threshold configuration value (in days).
543+
/// Admin-only.
544+
///
545+
/// Note: this value is stored and returned by `screening_threshold`,
546+
/// but is not currently read anywhere else in this contract, including
547+
/// `screen_property` -- there is no re-screening cadence or expiry
548+
/// enforced from it today. Emits `SanctionThresholdUpdated`.
549+
///
550+
/// # Errors
551+
/// - `Error::NotAuthorized` if the caller is not the contract admin.
455552
#[ink(message)]
456553
pub fn set_screening_threshold(&mut self, days: u32) -> Result<()> {
457554
self.ensure_admin()?;
@@ -463,6 +560,11 @@ pub mod sanctions_screening {
463560
Ok(())
464561
}
465562

563+
/// Returns the current screening-threshold configuration value (in
564+
/// days), as last set by `set_screening_threshold` or the default of
565+
/// 90 set in the constructor.
566+
///
567+
/// Open to any caller.
466568
#[ink(message)]
467569
pub fn screening_threshold(&self) -> u32 {
468570
self.screening_threshold_days

0 commit comments

Comments
 (0)