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 = ControllerIntegra 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 immutable3. 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 participantScenario 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 tokensScenario 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 NFTsIntegra'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 contractsReal 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 defaultsNone 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 dutiesComplex 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 transactionThe 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 governanceScenario 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 transfers2. Share Sale:
// Transfer company shares
sharesToken.transfer(buyer, shareAmount);
// = Fractional ownership transfers3. Role Delegation:
// Transfer guarantor position
multiPartyTokenizerV1.safeTransferFrom(oldGuarantor, newGuarantor, guarantorTokenId);
// = Guarantor obligation transfers4. 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
| Role | Controls | Rights | Example |
|---|---|---|---|
| Record Owner | Configuration, resolvers, executor | Administrative control | Law firm, title company, platform |
| Executor | Operations on behalf of owner | Automation authority | Backend service, escrow contract, workflow engine |
| Token Holder | Their tokens, economic benefits | Economic interests, roles | Buyer, seller, shareholder, tenant |
| Record Creator | Initial registration | Usually record owner initially | Person/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:
- Record Owner = Administrator/Registrar (not necessarily beneficiary)
- Token Holders = Economic stakeholders and role participants
- Executor = Automation agent (delegated authority)
- Tokens = Roles and interests (not just assets)
- Focus = Bind blockchain functionality to traditional contracts
- 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
- Reserve-Claim Pattern --- Token issuance for non-wallet users
- Record-Token Binding --- How records and tokens connect
- Privacy-First Architecture --- Privacy considerations