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
49 changes: 46 additions & 3 deletions sources/ltc1.move
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ public struct LTC1Package<phantom T> has key {

// ==================== Initialization ====================

/// Module initializer.
/// Automatically called when the package is published. Sets up the
/// IOTA Display standard for `LTC1Token` objects.

#[allow(lint(share_owned))]
fun init(otw: LTC1, ctx: &mut iota::tx_context::TxContext) {
// 1. Claim Publisher
Expand Down Expand Up @@ -142,6 +146,28 @@ fun init(otw: LTC1, ctx: &mut iota::tx_context::TxContext) {

// ==================== Public Functions ====================

/// Creates a new LTC1 Package (NPL Fractionalization Contract)
///
/// This is the entry point for Originators to tokenize an NPL package.
///
/// # Arguments
/// * `registry` - The NPLEX Registry shared object, used to verify authorization.
/// * `name` - The display name of the NPL Package.
/// * `notarization` - The IOTA SDK Notarization object bounding the off-chain documents to this contract.
/// * `total_supply` - The total number of token shares to emit (must be >= `MIN_SUPPLY`).
/// * `token_price` - The price of a single token share in NANOS (1,000,000,000 = 1 IOTA).
/// * `nominal_value` - The gross book value (GBV) of the underlying NPL package.
/// * `investor_split_bps` - The percentage of future revenue destined to investors (in Basis Points).
/// * `metadata_uri` - A link (e.g., IPFS) to the prospectus or public metadata.
/// * `owner_identity` - The Decentralized Identifier (DID) of the Originator/Servicer.
/// * `token` - The sender's `DelegationToken` proving their `ROLE_INSTITUTION` authority.
/// * `clock` - The IOTA system clock for timestamping.
///
/// # Aborts
/// * `E_INVALID_SPLIT` - if `investor_split_bps` > `MAX_INVESTOR_BPS`.
/// * `E_SUPPLY_TOO_LOW` - if `total_supply` < `MIN_SUPPLY`.
/// * Reverts if the `DelegationToken` does not authorize the caller as an Institution.

public entry fun create_contract<T>(
registry: &mut NPLEXRegistry,
name: String,
Expand Down Expand Up @@ -230,9 +256,26 @@ public entry fun create_contract<T>(
);
}

/// Buy tokens from the package
/// User specifies how many "shares" they want to buy (`amount`)
/// and provides the Payment in IOTA.
/// Purchase tokens (fractional shares) from the package
///
/// Investors use this function to finance the NPL package by acquiring `LTC1Token` shares.
///
/// # Arguments
/// * `registry` - The NPLEX Registry to verify the investor's identity.
/// * `package` - The `LTC1Package` offering the tokens.
/// * `payment` - An IOTA `Coin` used to pay for the tokens. Change is refunded.
/// * `amount` - The number of tokens requested.
/// * `token` - The sender's `DelegationToken` proving their `ROLE_INVESTOR` authority.
///
/// # Logic
/// Implements "Dividend-stripping protection" by pre-calculating the `initial_claimed`
/// revenue. This ensures the new investor cannot claim past revenue that was generated
/// before they bought the token. The past revenue is credited to the Originator.
///
/// # Aborts
/// * `E_SALES_CLOSED` - if the package sales are not active.
/// * `E_INSUFFICIENT_SUPPLY` - if the requested `amount` exceeds the `max_sellable_supply`.
/// * `E_INSUFFICIENT_PAYMENT` - if the `payment` coin value is lower than the required cost.
public entry fun buy_token<T>(
registry: &NPLEXRegistry,
package: &mut LTC1Package<T>,
Expand Down
43 changes: 38 additions & 5 deletions sources/registry.move
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,25 @@ fun init(otw: REGISTRY, ctx: &mut TxContext) {
// ==================== Admin Functions ====================

/// Register a new approved notarization in the registry
/// These are the documents which are used only for create_contract
/// Notarizations for other approvals are managed in other tables not in approved_notarizations
/// A note on this: The fact that we pass notarization_id and document_hash instead of the notarization object is because
/// the locked notarization object cannot be traded. The user has to create it and have it audited then pass it to the create_contract function.
///
/// These are the documents which are used only for `create_contract`.
/// Notarizations for other approvals are managed in other tables, not in `approved_notarizations`.
///
/// **Note:** We pass `notarization_id` and `document_hash` instead of the `Notarization` object
/// because the locked Notarization object cannot be traded. The user must create it via SDK,
/// have it audited off-chain, and then pass it to the `create_contract` function.
///
/// # Arguments
/// * `registry` - The NPLEX Registry shared object.
/// * `_admin_cap` - The NPLEX Administrator Capability (authorization).
/// * `notarization_id` - The `ID` of the Notarization object created via SDK.
/// * `document_hash` - The `u256` SHA256/Keccak hash of the off-chain PDF asset document.
/// * `authorized_creator` - The address allowed to consume this hash to create an LTC1.
/// * `clock` - The system clock for auditing timestamp.
/// * `ctx` - Transaction context.
///
/// # Aborts
/// * `E_NOTARIZATION_ALREADY_USED` - If the `notarization_id` is already registered.
public entry fun register_notarization(
registry: &mut NPLEXRegistry,
_admin_cap: &NPLEXAdminCap,
Expand Down Expand Up @@ -458,7 +473,25 @@ public entry fun revoke_identity(

// ==================== Validation Functions ====================

/// Claim a notarization to start usage flow
/// Claim a notarization to start the package creation flow
///
/// Consumes an approved notarization and returns a "Hot Potato" `NotarizationClaim`
/// that must be immediately bound to a new contract via `bind_executor`.
///
/// # Arguments
/// * `registry` - The NPLEX Registry shared object.
/// * `notarization_id` - The ID of the notarization being claimed.
/// * `document_hash` - The hash of the document, must match the registered one.
/// * `ctx` - Transaction context.
///
/// # Returns
/// * `NotarizationClaim` - A Hot Potato struct containing the hash and ID.
///
/// # Aborts
/// * `E_NOTARIZATION_NOT_APPROVED` - If not found or `document_hash` mismatches.
/// * `E_NOTARIZATION_REVOKED` - If it was revoked by NPLEX Admin.
/// * `E_NOTARIZATION_ALREADY_USED` - If it was already bound to a contract.
/// * `E_UNAUTHORIZED_CREATOR` - If the caller is not the `authorized_creator`.
public fun claim_notarization(
registry: &mut NPLEXRegistry,
notarization_id: ID,
Expand Down
Loading