Skip to main content

Record vs Token Ownership

Understanding Integra's dual-ownership model that separates record control from economic interests in Real World Contracts.

Overview

Integra implements a dual-ownership model that separates record control from economic interests. This distinction is fundamental to understanding how Real World Contracts work and differs significantly from traditional NFT platforms.

The Critical Distinction

Record Owner:

  • Controls record configuration and registration
  • Selects tokenizer, resolvers, executors
  • Not necessarily the economic beneficiary
  • Often a service provider (law firm, title company, platform)

Token Holder:

  • Holds economic interests or roles in the contract
  • Represents parties to the agreement (buyer, seller, tenant, guarantor, etc.)
  • May have rights to payments, transfers, or specific actions
  • The actual stakeholders in the real-world contract

Why This Matters

Traditional NFT platforms conflate these concepts:

NFT Owner = Creator = Economic Beneficiary = Controller

Integra separates them for real-world applicability:

Record Owner = Registrar/Administrator
Token Holders = Economic Stakeholders
Executor = Automation Agent (optional)

Record Ownership Explained

What Record Owners Control

1. Registration Configuration:

// Record owner chooses:
integraRecordV1.registerRecord(
    contentHash,
    referenceHash,
    tokenizer,         // Which tokenization model
    executor,          // Who can automate operations
    processHash,
    identityExtension,
    primaryResolverId, // Which services to attach
    additionalResolvers
);

2. Resolver Management:

// Add/remove services
integraRecordV1.setPrimaryResolver(integraHash, newResolverId);
integraRecordV1.addAdditionalResolver(integraHash, resolverId);
integraRecordV1.lockResolvers(integraHash);  // Make immutable

3. Executor Authorization:

// Delegate automation authority
integraRecordV1.authorizeRecordExecutor(integraHash, executorAddress);

4. Ownership Transfer:

// Transfer record control
integraRecordV1.transferRecordOwnership(
    integraHash,
    newOwner,
    "Transferring from law firm to client"
);

What Record Owners Do NOT Control

Record owners cannot:

  • Modify the content hash (immutable)
  • Change token holders (only tokens can transfer)
  • Access token economic benefits
  • Transfer tokens on behalf of holders
  • Revoke token ownership

Token Ownership Explained

What Token Holders Represent

Tokens represent economic interests and roles in the underlying contract, NOT just "ownership":

Economic Interests:

  • Property ownership (buyer gets deed NFT)
  • Fractional shares (shareholders get ERC-20 tokens)
  • Royalty rights (artists get royalty distribution tokens)
  • Rental rights (tenant gets time-based access token)

Roles and Rights:

  • Guarantor (holds guarantor token, obligated if default)
  • Observer (holds observer token, receives notifications)
  • Notice recipient (holds notice token, must be informed)
  • Voter (holds voting token, participates in decisions)
  • Beneficiary (holds beneficiary token, receives distributions)

Token Holders Control

1. Their Own Tokens:

// Standard ERC transfers (if transferable)
nft.transferFrom(currentHolder, newHolder, tokenId);
erc20.transfer(recipient, amount);

2. Economic Benefits:

// Claim royalties
royaltyTokenizerV1.claimRoyalties(tokenId);

// Receive rent payments
rentalTokenizerV1.collectRentPayment(tokenId);

3. Participatory Rights:

// Vote on matters
governanceTokenizerV1.vote(proposalId, tokenId, choice);

// Approve actions
multiSigTokenizerV1.approveAction(actionId, tokenId);

Real-World Ownership Scenarios

Scenario 1: Law Firm Creating Contract for Client

Record Owner: Law Firm Token Holders: Client + Counterparty

// Law firm (record owner) registers client's purchase agreement
bytes32 agreementHash = integraRecordV1.registerRecord(
    purchaseAgreementHash,
    ipfsCID,
    multiPartyTokenizerV1,   // Buyer + Seller tokens
    lawFirmExecutor,          // Law firm can automate
    processHash,
    bytes32(0),
    bytes32(0),
    []
);

// Record owner: Law firm (0xLAW...)
// Controls: Configuration, resolvers, executor

// Reserve tokens for actual parties
multiPartyTokenizerV1.reserveToken(
    agreementHash,
    1,  // Buyer token
    clientAddress,  // Client (not law firm)
    1,
    processHash
);

multiPartyTokenizerV1.reserveToken(
    agreementHash,
    2,  // Seller token
    counterpartyAddress,
    1,
    processHash
);

// Token holders: Client + Counterparty
// Get: Economic interests
// Law firm: Gets nothing (just service provider)

// Later: Transfer record ownership to client
integraRecordV1.transferRecordOwnership(
    agreementHash,
    clientAddress,
    "Transaction complete - transferring control to client"
);

Scenario 2: Title Company Facilitating Property Transfer

Record Owner: Title Company Token Holders: Buyer (gets property deed)

// Title company registers property deed
bytes32 deedHash = integraRecordV1.registerRecord(
    propertyDeedHash,
    ipfsCID,
    ownershipTokenizerV1,
    titleCompanyExecutor,  // Title company automates
    processHash,
    bytes32(0),
    bytes32(0),
    []
);

// Record owner: Title Company
// Controls: Registry configuration, can update resolvers

// Reserve deed NFT for buyer
ownershipTokenizerV1.reserveTokenAnonymous(
    deedHash,
    0,
    1,
    encrypt("Property Buyer"),
    processHash
);

// Token holder (after claim): Buyer
// Gets: Property ownership NFT, can sell/transfer property

// Title company gets: Nothing
// Role: Service provider, not economic participant

Scenario 3: Company Issuing Stock to Employees

Record Owner: Company (Finance) Token Holders: Employees (shareholders)

// Company registers share document
bytes32 sharesHash = integraRecordV1.registerRecord(
    stockCertificateHash,
    ipfsCID,
    sharesTokenizerV1,
    companyExecutor,  // Automated by company backend
    processHash,
    bytes32(0),
    bytes32(0),
    [auditResolverId]
);

// Record owner: Company
// Controls: Share issuance configuration, resolvers

// Issue shares to 100 employees
for (employee of employees) {
    await sharesTokenizerV1.reserveToken(
        sharesHash,
        0,
        employee.wallet,
        employee.shareAmount,
        processHash
    );
}

// Token holders: Employees
// Get: Company shares (ERC-20), dividends, voting rights

// Company retains record ownership
// Can: Add compliance resolvers, authorize new executor
// Cannot: Take back shares, transfer employee tokens

Scenario 4: Platform Facilitating Multi-Party Agreements

Record Owner: Platform Token Holders: Agreement parties

// Platform (like DocuSign, but on blockchain)
contract AgreementPlatform {
    function createAgreement(
        bytes32 contentHash,
        address[] parties,
        string[] roles
    ) external returns (bytes32 integraHash) {
        // Platform registers record
        integraHash = integraRecordV1.registerRecord(
            contentHash,
            ipfsCID,
            multiPartyTokenizerV1,
            platformExecutor,  // Platform automates workflow
            processHash,
            bytes32(0),
            bytes32(0),
            [notificationResolverId, auditResolverId]
        );

        // Record owner: Platform
        // Role: Facilitator, automation provider

        // Reserve tokens for all parties
        for (uint i = 0; i < parties.length; i++) {
            multiPartyTokenizerV1.reserveToken(
                integraHash,
                i + 1,
                parties[i],
                1,
                processHash
            );
        }

        // Token holders: Actual agreement parties
        // Get: Participation tokens

        // Platform gets: Service fees (off-chain)
        // Not: Economic interest in agreement
    }
}

Executor Pattern: Delegated Automation

What Executors Are

Executor = Automation Agent authorized by record owner to execute operations:

// Record owner authorizes executor
integraRecordV1.authorizeRecordExecutor(
    integraHash,
    executorContractAddress
);

Executor can:

  • Reserve tokens (on behalf of record owner)
  • Cancel reservations
  • Call tokenizer functions marked requireOwnerOrExecutor
  • Automate workflows programmatically

Executor cannot:

  • Change record configuration (resolvers, etc.)
  • Transfer record ownership
  • Claim tokens (only recipients can)
  • Access economic benefits

Real-World Executor Use Cases

Use Case 1: Company Backend Automation

// Company authorizes backend service as executor
integraRecordV1.authorizeRecordExecutor(
    employeeSharesRecord,
    companyBackendExecutor  // Smart contract controlled by backend
);

// Backend can now automate stock grants
contract CompanyBackendExecutor {
    function grantEmployeeShares(
        bytes32 sharesHash,
        address employee,
        uint256 amount
    ) external onlyBackendService {
        // Executor reserves shares (no manual transaction from owner)
        sharesTokenizerV1.reserveToken(
            sharesHash,
            0,
            employee,
            amount,
            processHash
        );

        // Create claim attestation
        // ...
    }
}

Use Case 2: Escrow Service Automation

// Real estate platform authorizes escrow executor
integraRecordV1.authorizeRecordExecutor(
    deedHash,
    escrowExecutor
);

contract EscrowExecutor {
    function releaseOnPayment(
        bytes32 integraHash,
        uint256 tokenId,
        address buyer
    ) external payable {
        require(msg.value >= purchasePrice, "Insufficient payment");

        // Executor reserves token on payment receipt
        ownershipTokenizerV1.reserveToken(
            integraHash,
            tokenId,
            buyer,
            1,
            processHash
        );

        // Forward payment to seller
        payable(recordOwner).transfer(msg.value);
    }
}

Use Case 3: Workflow Engine Integration

// Record owner authorizes Temporal/Camunda executor
integraRecordV1.authorizeRecordExecutor(
    recordHash,
    workflowEngineExecutor
);

// Workflow engine can automate multi-step processes
contract WorkflowExecutor {
    function executeWorkflowStep(
        bytes32 integraHash,
        string memory stepName,
        bytes memory stepData
    ) external onlyWorkflowEngine {
        if (keccak256(bytes(stepName)) == keccak256("reserve_tokens")) {
            // Automated token reservation
            (address[] memory recipients, uint256[] memory amounts) =
                abi.decode(stepData, (address[], uint256[]));

            for (uint i = 0; i < recipients.length; i++) {
                tokenizer.reserveToken(
                    integraHash,
                    i + 1,
                    recipients[i],
                    amounts[i],
                    processHash
                );
            }
        }
    }
}

Tokens Represent Roles, Not Just Assets

Traditional NFT Model

NFT = Asset ownership
  - One token = one asset
  - Transfer = sell asset
  - Ownership = economic value

Examples: CryptoPunks, Bored Apes, art NFTs

Integra's Model

Token = Role/Interest in multi-party contract
  - Multiple tokens per record (different roles)
  - Transfer = role assignment (not always economic)
  - Ownership = rights and obligations
  - Focus: Bind blockchain functionality to traditional contracts

Real Estate Rental

Record: Lease Agreement (integraHash: 0xLEASE...)
  - Record Owner: Property Management Company
       Controls: Registration, resolvers, automation

  - Token Holders (represent roles):
       Token #1 (Landlord): Property owner
            Rights: Receive rent, end lease
            Obligations: Maintain property

       Token #2 (Tenant): Renter
            Rights: Occupy property, renew lease
            Obligations: Pay rent, maintain condition

       Token #3 (Guarantor): Co-signer
            Rights: Notice of default
            Obligations: Pay if tenant defaults

None of these tokens are "traded" --- they represent contractual positions.

Business Partnership

Record: Partnership Agreement (integraHash: 0xPART...)
  - Record Owner: Incorporating attorney
       Controls: Initial setup, later transferred to partners

  - Token Holders (represent partners):
       Token #1 (Managing Partner - 40% shares)
       Token #2 (Partner A - 30% shares)
       Token #3 (Partner B - 30% shares)
            Rights: Profit distribution, voting, management
            Obligations: Capital contributions, fiduciary duties

Complex Transaction

Record: Commercial Property Sale (integraHash: 0xSALE...)
  - Record Owner: Title company
       Controls: Transaction workflow, resolvers

  - Token Holders (multiple roles):
       Token #1 (Buyer): Future property owner
       Token #2 (Seller): Current property owner
       Token #3 (Lender): Mortgage provider
       Token #4 (Title Insurance): Risk bearer
       Token #5 (Escrow Agent): Holds funds
            Each has specific rights/obligations in transaction

The token holders are parties to the transaction. The title company (record owner) is the facilitator.

Record Ownership Transfer

When and Why to Transfer Record Ownership

Scenario 1: Service Provider to Client

// Law firm creates contract for client
bytes32 contractHash = lawFirm.registerClientContract(
    contractHash,
    ipfsCID,
    tokenizer,
    lawFirmExecutor,
    ...
);

// Record owner: Law firm (initially)

// After transaction closes, transfer control to client
integraRecordV1.transferRecordOwnership(
    contractHash,
    clientAddress,
    "Transaction complete - client now controls record configuration"
);

// Record owner: Client (now)
// Client can: Change resolvers, authorize new executor, etc.

Scenario 2: Platform to DAO

// Platform registers DAO governance record
bytes32 daoHash = platform.registerDAORecord(...);

// Record owner: Platform (initially)

// Once DAO established, transfer control
integraRecordV1.transferRecordOwnership(
    daoHash,
    daoMultisigAddress,
    "DAO governance transition - community control"
);

// Record owner: DAO (now)
// DAO controls: Configuration changes via governance

Scenario 3: Individual to Corporation

// Founder registers company shares personally
bytes32 sharesHash = founder.registerShares(...);

// After incorporation, transfer to corporation
integraRecordV1.transferRecordOwnership(
    sharesHash,
    corporationAddress,
    "Post-incorporation - corporate entity control"
);

The Executor Pattern: Delegated Operations

Executors Enable Automation Without Ownership

Key concept: Executors can perform operations on behalf of record owner without being the owner.

Authorization:

// Record owner authorizes executor
integraRecordV1.authorizeRecordExecutor(
    integraHash,
    executorContractAddress
);

// Later: Revoke authorization
integraRecordV1.authorizeRecordExecutor(
    integraHash,
    address(0)  // Revoke by setting to zero address
);

Executor Capabilities

Executors have operational authority but not ownership:

modifier requireOwnerOrExecutor(bytes32 integraHash) {
    address owner = integraRecordV1.getRecordOwner(integraHash);
    address executor = integraRecordV1.getRecordExecutor(integraHash);

    require(
        msg.sender == owner || msg.sender == executor,
        "Not authorized"
    );
    _;
}

// Functions using this modifier:
function reserveToken(...) external requireOwnerOrExecutor(integraHash) {
    // Both owner and executor can reserve
}

function cancelReservation(...) external requireOwnerOrExecutor(integraHash) {
    // Both can cancel
}

Executors CANNOT:

// These require actual record ownership
function transferRecordOwnership(...) external {
    require(msg.sender == owner);  // Executor cannot do this
}

function setPrimaryResolver(...) external {
    require(msg.sender == owner);  // Executor cannot do this
}

Real-World Executor Examples

Example 1: Property Management Platform

// Platform manages 1000 rental properties
class PropertyManagementPlatform {
    async setupRentalAutomation(propertyOwner, property) {
        // Owner registers deed, authorizes platform executor
        const deedHash = await integraRecordV1.registerRecord(
            property.deedHash,
            property.ipfsCID,
            rentalTokenizerV1,
            platformExecutorAddress,  // Platform authorized
            processHash,
            bytes32(0),
            lifecycleResolverId,
            [paymentResolverId]
        );

        // Record owner: Property owner
        // Executor: Platform
        // Platform can now automate:
        //   - Reserve tokens for new tenants
        //   - Process rent payments
        //   - Handle lease renewals
        // Without requiring manual transactions from owner
    }

    // Automated tenant onboarding
    async onboardNewTenant(deedHash, tenantEmail) {
        // Platform executor reserves token
        const tx = await rentalTokenizerV1.reserveTokenAnonymous(
            deedHash,
            2,  // Tenant token
            1,
            encrypt("Tenant", tenantEmail),
            processHash
        );

        // Platform executor creates claim attestation
        // Sends email to tenant
        // Tenant claims when ready
    }
}

Example 2: Corporate Stock Management System

// Corporation authorizes HRIS system as executor
contract CorporateStockExecutor {
    // Authorized executor for company shares record

    function grantOptionsOnVesting() external onlyHRIS {
        // Automatically triggered by HRIS on vesting dates
        Employee[] memory vestedToday = getVestedEmployees(today);

        for (employee in vestedToday) {
            // Executor reserves shares
            sharesTokenizerV1.reserveToken(
                companySharesHash,
                0,
                employee.wallet,
                employee.vestedAmount,
                processHash
            );

            // Create claim attestation
            createAttestation(
                companySharesHash,
                tokenId,
                employee.wallet
            );

            // Employee can claim shares
        }
    }

    // Called by payroll system
    function processDividend(uint256 totalDividend) external onlyPayroll {
        // Executor can trigger but does not receive dividend
        sharesTokenizerV1.distributeDividend{value: totalDividend}();

        // Dividend goes to token holders (employees)
        // Not to record owner (corporation)
        // Not to executor (HRIS system)
    }
}

Token Transfers: When and Why

When Tokens Transfer

Integra tokens can transfer, but transfers represent role reassignment, not speculation:

1. Property Sale:

// Transfer property deed NFT
ownershipNFT.transferFrom(seller, buyer, deedTokenId);
// = Ownership of property transfers

2. Share Sale:

// Transfer company shares
sharesToken.transfer(buyer, shareAmount);
// = Fractional ownership transfers

3. Role Delegation:

// Transfer guarantor position
multiPartyTokenizerV1.safeTransferFrom(oldGuarantor, newGuarantor, guarantorTokenId);
// = Guarantor obligation transfers

4. Non-Transferable Roles:

// Some tokens represent non-transferable positions
soulboundTokenizerV1.claimToken(...);
// Cannot transfer (credential, not asset)

Transfer Restrictions

Many Integra tokens have transfer restrictions based on real-world contract requirements:

Compliance restrictions:

// Security tokens: Only to accredited investors
function _beforeTokenTransfer(from, to, tokenId) internal override {
    require(isAccredited(to), "Recipient not accredited");
}

Role restrictions:

// Guarantor must be approved
function _beforeTokenTransfer(from, to, tokenId) internal override {
    if (tokenData[tokenId].role == GUARANTOR) {
        require(isApprovedGuarantor(to), "Not approved guarantor");
    }
}

Time restrictions:

// Vesting period
function _beforeTokenTransfer(from, to, tokenId) internal override {
    require(
        block.timestamp >= vestingDate[tokenId],
        "Shares not vested"
    );
}

Complete Ownership Matrix

RoleControlsRightsExample
Record OwnerConfiguration, resolvers, executorAdministrative controlLaw firm, title company, platform
ExecutorOperations on behalf of ownerAutomation authorityBackend service, escrow contract, workflow engine
Token HolderTheir tokens, economic benefitsEconomic interests, rolesBuyer, seller, shareholder, tenant
Record CreatorInitial registrationUsually record owner initiallyPerson/entity registering record

Integration Example: Complete Flow

// Real estate platform with full ownership model
class RealEstatePlatform {
    // Platform acts as record owner for all listings
    async createListing(sellerData, propertyData) {
        // 1. Platform registers deed (as record owner)
        const integraHash = await integraRecordV1.registerRecord(
            propertyData.deedHash,
            propertyData.ipfsCID,
            ownershipTokenizerV1,
            this.platformExecutor,  // Platform executor for automation
            processHash,
            bytes32(0),
            lifecycleResolverId,
            [escrowResolverId]
        );

        // Record owner: Platform
        // Role: Facilitator, provides automation

        // 2. Reserve NFT for future buyer (anonymous)
        const tokenId = await ownershipTokenizerV1.reserveTokenAnonymous(
            integraHash,
            0,
            1,
            encrypt("Property Buyer TBD"),
            processHash
        );

        // 3. When buyer found, create claim attestation
        const buyerEmail = "buyer@example.com";
        const attestationUID = await this.createEmailAttestation(
            integraHash,
            tokenId,
            buyerEmail
        );

        // 4. Buyer creates wallet and claims (self-custody)
        // ... handled by buyer later

        // 5. After closing, transfer record ownership to buyer
        await integraRecordV1.transferRecordOwnership(
            integraHash,
            buyerWallet,
            "Sale complete - buyer now controls record configuration"
        );

        // Final state:
        // - Record owner: Buyer (controls config)
        // - Token owner: Buyer (owns property NFT)
        // - Executor: Platform (still authorized for convenience)
        // - Platform: No ownership, just service provider
    }
}

Summary

Integra's ownership model:

  1. Record Owner = Administrator/Registrar (not necessarily beneficiary)
  2. Token Holders = Economic stakeholders and role participants
  3. Executor = Automation agent (delegated authority)
  4. Tokens = Roles and interests (not just assets)
  5. Focus = Bind blockchain functionality to traditional contracts
  6. Philosophy = Enable automation and proof, not replace legal framework

This model enables:

  • Service providers to facilitate without owning
  • Automation without requiring constant owner transactions
  • Multiple parties with different roles in the same contract
  • Transfer of administrative control separate from economic transfer
  • Real-world contract complexity represented on-chain

Integra does not replace traditional contracts --- it enhances them with blockchain functionality.

Learn More