The Property Token Standard is a comprehensive implementation that maintains compatibility with both ERC-721 and ERC-1155 token standards while adding real estate-specific features and cross-chain support. This standard enables the tokenization of real estate properties with enhanced functionality for compliance, legal documentation, and interoperability across different blockchain networks.
- ERC-721 Compliance: Full compatibility with the Ethereum NFT standard
- ERC-1155 Support: Batch operations and multi-token management
- Backward Compatibility: Works with existing ERC-721 wallets and marketplaces
- Property Metadata Schema: Extended metadata for real estate properties
- Legal Document Attachment: Secure attachment of legal documents
- Ownership History Tracking: Complete transfer history
- Compliance Verification: Built-in compliance checking system
- Token Bridging: Standardized cross-chain token transfer
- Metadata Preservation: Consistent metadata across chains
- Ownership Verification: Cross-chain ownership validation
Located at: contracts/property-token/src/lib.rs
#[ink(storage)]
pub struct PropertyToken {
// ERC-721 standard mappings
token_owner: Mapping<TokenId, AccountId>,
owner_token_count: Mapping<AccountId, u32>,
token_approvals: Mapping<TokenId, AccountId>,
operator_approvals: Mapping<(AccountId, AccountId), bool>,
// ERC-1155 batch operation support
balances: Mapping<(AccountId, TokenId), u128>,
operators: Mapping<(AccountId, AccountId), bool>,
// Property-specific mappings
token_properties: Mapping<TokenId, PropertyInfo>,
property_tokens: Mapping<u64, TokenId>,
ownership_history: Mapping<TokenId, Vec<OwnershipTransfer>>,
compliance_flags: Mapping<TokenId, ComplianceInfo>,
legal_documents: Mapping<TokenId, Vec<DocumentInfo>>,
// Cross-chain bridge mappings
bridged_tokens: Mapping<(ChainId, TokenId), BridgedTokenInfo>,
bridge_operators: Vec<AccountId>,
// Standard counters
total_supply: u64,
token_counter: u64,
admin: AccountId,
}Returns the number of tokens owned by an account.
Returns the owner of a specific token.
Transfers a token from one account to another with proper authorization checks.
Approves an account to transfer a specific token.
Sets or unsets an operator for an owner.
Gets the approved account for a token.
Checks if an operator is approved for an owner.
Returns the balances of multiple tokens for multiple accounts.
safe_batch_transfer_from(from: AccountId, to: AccountId, ids: Vec<TokenId>, amounts: Vec<u128>, data: Vec<u8>) -> Result<(), Error>
Safely transfers multiple tokens in a single transaction.
Returns the URI for token metadata.
Registers a new property and mints a corresponding token.
Parameters:
metadata: Property metadata including location, size, legal description, etc.
Returns:
Ok(token_id): The ID of the newly created tokenErr(Error): Various error conditions
attach_legal_document(token_id: TokenId, document_hash: Hash, document_type: String) -> Result<(), Error>
Attaches a legal document to a property token.
Parameters:
token_id: The token to attach the document todocument_hash: IPFS hash or other identifier for the documentdocument_type: Type of document (e.g., "Deed", "Title", "Survey")
Verifies compliance for a property token.
Parameters:
token_id: The token to verifyverification_status: True if compliant, false otherwise
Retrieves the complete ownership history for a token.
bridge_to_chain(destination_chain: ChainId, token_id: TokenId, recipient: AccountId) -> Result<(), Error>
Initiates token bridging to another chain.
Parameters:
destination_chain: Target chain IDtoken_id: Token to bridgerecipient: Recipient address on destination chain
receive_bridged_token(source_chain: ChainId, original_token_id: TokenId, recipient: AccountId) -> Result<(), Error>
Receives a bridged token from another chain.
Parameters:
source_chain: Source chain IDoriginal_token_id: Original token ID on source chainrecipient: Recipient address on current chain
Adds a bridge operator (admin only).
Removes a bridge operator (admin only).
Extended metadata structure for real estate properties:
pub struct PropertyMetadata {
pub location: String,
pub size: u64,
pub legal_description: String,
pub valuation: u128,
pub documents_url: String,
}Complete property information:
pub struct PropertyInfo {
pub id: u64,
pub owner: AccountId,
pub metadata: PropertyMetadata,
pub registered_at: u64,
}Compliance verification information:
pub struct ComplianceInfo {
pub verified: bool,
pub verification_date: u64,
pub verifier: AccountId,
pub compliance_type: String,
}Legal document information:
pub struct DocumentInfo {
pub document_hash: Hash,
pub document_type: String,
pub upload_date: u64,
pub uploader: AccountId,
}#[ink(event)]
pub struct Transfer {
#[ink(topic)]
pub from: Option<AccountId>,
#[ink(topic)]
pub to: Option<AccountId>,
#[ink(topic)]
pub id: TokenId,
}
#[ink(event)]
pub struct Approval {
#[ink(topic)]
pub owner: AccountId,
#[ink(topic)]
pub spender: AccountId,
#[ink(topic)]
pub id: TokenId,
}
#[ink(event)]
pub struct ApprovalForAll {
#[ink(topic)]
pub owner: AccountId,
#[ink(topic)]
pub operator: AccountId,
pub approved: bool,
}#[ink(event)]
pub struct PropertyTokenMinted {
#[ink(topic)]
pub token_id: TokenId,
#[ink(topic)]
pub property_id: u64,
#[ink(topic)]
pub owner: AccountId,
}
#[ink(event)]
pub struct LegalDocumentAttached {
#[ink(topic)]
pub token_id: TokenId,
#[ink(topic)]
pub document_hash: Hash,
#[ink(topic)]
pub document_type: String,
}
#[ink(event)]
pub struct ComplianceVerified {
#[ink(topic)]
pub token_id: TokenId,
#[ink(topic)]
pub verified: bool,
#[ink(topic)]
pub verifier: AccountId,
}
#[ink(event)]
pub struct TokenBridged {
#[ink(topic)]
pub token_id: TokenId,
#[ink(topic)]
pub destination_chain: ChainId,
#[ink(topic)]
pub recipient: AccountId,
}#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
pub enum Error {
// Standard ERC errors
TokenNotFound,
Unauthorized,
// Property-specific errors
PropertyNotFound,
InvalidMetadata,
DocumentNotFound,
ComplianceFailed,
// Cross-chain bridge errors
BridgeNotSupported,
InvalidChain,
BridgeLocked,
}// Create a new property token contract
let mut contract = PropertyToken::new();
// Register a property with token
let metadata = PropertyMetadata {
location: String::from("123 Main St, City, Country"),
size: 2500, // square feet
legal_description: String::from("Residential property with 3 bedrooms"),
valuation: 750000,
documents_url: String::from("ipfs://Qm..."),
};
let token_id = contract.register_property_with_token(metadata)?;
// Attach legal documents
let deed_hash = Hash::from([1u8; 32]);
contract.attach_legal_document(token_id, deed_hash, String::from("Deed"))?;
// Verify compliance
contract.verify_compliance(token_id, true)?;
// Transfer ownership
contract.transfer_from(accounts.alice, accounts.bob, token_id)?;// Bridge token to another chain
contract.bridge_to_chain(2, token_id, recipient_on_chain_2)?;
// On destination chain, receive the bridged token
contract.receive_bridged_token(1, original_token_id, recipient)?;- Only token owners can transfer their tokens
- Only approved operators can act on behalf of owners
- Only admin or designated bridge operators can verify compliance
- Only bridge operators can receive bridged tokens
- Tokens must be verified as compliant before bridging
- Compliance status is tracked and auditable
- Verification requires proper authorization
- Tokens are locked during the bridging process
- Bridge operators are managed by admin
- Cross-chain transfers are tracked and verifiable
The implementation includes comprehensive unit tests covering:
- ERC-721 standard compliance
- ERC-1155 batch operations
- Property-specific functionality
- Cross-chain bridge operations
- Error condition handling
- Edge cases and security scenarios
Tests are located in tests/property_token_tests.rs.
- Rust toolchain with ink! support
- cargo-contract CLI tool
- Properly configured Substrate node
# Navigate to the property-token directory
cd contracts/property-token
# Build the contract
cargo contract build
# Run tests
cargo testThe contract can be deployed using standard ink! deployment tools or through the provided deployment scripts in the project.
- Advanced metadata schemas for different property types
- Integration with real estate oracles for automatic valuation updates
- Fractional ownership support
- Rental income distribution mechanisms
- Governance features for property communities
- Enhanced cross-chain bridge protocols
- Merkle tree-based ownership proofs
- Batch registration for multiple properties
- Optimized storage patterns for large-scale deployments
- Gas optimization for frequent operations
For detailed API documentation, please refer to the inline documentation in the source code and the generated documentation from cargo doc.
For questions, issues, or contributions:
- GitHub Issues: Repository Issues
- Discord: PropChain Community
- Email: dev@propchain.io
This documentation reflects version 1.0.0 of the Property Token Standard implementation.