- Overview
- Architecture & Workflow
- Key Features
- Technology Stack
- Project Structure
- Smart Contract Architecture
- Local Development
- Deployment Guide
- Troubleshooting
- Resources
- Contributing
- Flare Ambassador Program
The Flare Real Estate Tokenization dApp demonstrates how to tokenize real-world assets (RWAs) using blockchain technology. It showcases the integration of Flare's Time Series Oracle (FTSOv2) with modern DeFi protocols to create a marketplace for fractional real estate ownership.
This project serves as a comprehensive tutorial for developers interested in:
- Building decentralized marketplaces for real-world assets
- Implementing fractional ownership through NFTs and ERC-20 tokens
- Leveraging Flare's FTSOv2 for reliable price feeds
- Creating secure whitelist mechanisms with Merkle trees
- Building responsive Web3 interfaces with modern React patterns
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ FTSO ORACLES │ │ SMART CONTRACTS │ │ FRONTEND APP │
│ │ │ │ │ │
│ ETH/USD Price ├────►│ Property Factory├────►│ User Interface │
│ Data Feed │ │ Property Tokens │ │ & Marketplace │
└─────────────────┘ └─────────┬───────┘ └───────┬─────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ AI GENERATION │ │ IPFS STORAGE │
│ │ │ │
│ Mistral AI │ │ Property │
│ Freepik API │ │ Metadata │
└─────────┬───────┘ └───────┬─────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ NEXT.JS API │ │ MERKLE PROOFS │
│ /generate- │ │ Whitelist │
│ property │ │ Verification │
└─────────────────┘ └─────────────────┘
User Flow:
- Connect wallet to Flare Coston2 testnet
- Verify whitelist eligibility through Merkle proof validation
- Input property details (surface, location) for AI content generation
- AI automatically generates professional descriptions and property images
- Create property listings with AI-generated metadata stored on IPFS
- Mint property NFTs with associated ERC-20 tokens for fractional ownership
- Trade property tokens with real-time price feeds from FTSOv2
- Property NFTs: Unique tokens representing real estate properties
- Fractional Ownership: ERC-20 tokens for divisible property shares
- Metadata Storage: Decentralized property information via IPFS/Pinata
- Automated Valuation: Integration with FTSOv2 for price discovery
- Merkle Tree Whitelist: Gas-efficient whitelist verification
- Owner Verification: Cryptographic proof of property ownership
- Role-based Permissions: Factory owner controls and property-specific access
- RainbowKit Wallet Connection: Seamless wallet integration
- Wagmi Hooks: Type-safe contract interactions
- Real-time Updates: Live blockchain data synchronization
- Responsive Design: Optimized for desktop and mobile devices
- Solidity 0.8.28: Smart contract development
- OpenZeppelin 5.3.0: Secure contract standards
- Hardhat 2.26.0: Development environment and testing
- Flare Periphery Contracts 0.1.34: FTSOv2 integration
- MerkleTreeJS 0.5.2: Whitelist proof generation
- Next.js 15.4.1: React framework with App Router
- React 19.1.0: Modern UI library
- Tailwind CSS 4.x: Utility-first styling
- RainbowKit 2.2.8: Wallet connection interface
- Wagmi 2.15.7: React hooks for Ethereum
- Viem 2.32.0: TypeScript Ethereum library
- Mistral AI: Advanced property description generation
- Freepik API: AI-powered property image generation
- Custom Prompt Engineering: Optimized real estate content creation
- Automated Metadata: Smart property attributes and valuations
- IPFS/Pinata 2.4.9: Decentralized storage and gateway
- Ethers.js 6.4.0: Ethereum interactions
- Keccak256 1.0.6: Cryptographic hashing
- TanStack Query 5.83.0: Data fetching and caching
flare-real-estate-tokenization/
├── backend/ # Smart contracts & blockchain logic
│ ├── contracts/ # Solidity smart contracts
│ │ ├── PropertyTokenFactory.sol # Main factory contract
│ │ ├── PropertyToken.sol # Individual property tokens
│ │ ├── FtsoV2Consumer.sol # Oracle price consumer
│ │ └── mocks/ # Testing contracts
│ ├── test/ # Comprehensive test suite
│ │ ├── RWA.test.js # Main functionality tests
│ │ └── FtsoV2Consumer.test.js
│ ├── ignition/ # Hardhat Ignition deployment
│ ├── hardhat.config.js # Hardhat configuration
│ └── package.json # Backend dependencies
│
├── frontend/ # Web application
│ ├── src/
│ │ ├── app/ # Next.js App Router pages
│ │ │ ├── page.js # Main application interface
│ │ │ └── layout.js # Root layout with providers
│ │ ├── components/ # React components
│ │ │ ├── PropertyCreator.js # Property creation form
│ │ │ ├── PriceDisplay.js # Real-time price display
│ │ │ └── ui/ # Reusable UI components
│ │ ├── hooks/ # Custom React hooks
│ │ ├── lib/ # Utility libraries
│ │ └── artifacts/ # Compiled contract ABIs
│ └── package.json # Frontend dependencies
│
├── .env.example # Environment variables template
└── README.md # This documentation
The main factory contract that orchestrates property tokenization:
contract PropertyTokenFactory is Ownable, FtsoV2Consumer {
bytes32 public merkleRootOwners;
function createProperty(
string memory tokenURI,
uint256 surfaceM2,
bytes32[] calldata ownerProof
) external returns (uint256 nftId) {
require(isWhitelisted(msg.sender, ownerProof), "Not whitelisted");
require(surfaceM2 >= MIN_SURFACE_M2 && surfaceM2 <= MAX_SURFACE_M2, "Invalid surface");
uint256 ethPrice = getETHPrice();
uint256 totalTokens = (surfaceM2 * TOKEN_PRICE_USD * 1e18) / ethPrice;
PropertyToken newProperty = new PropertyToken(
string.concat("Property #", nftId.toString()),
"PROP",
totalTokens,
msg.sender
);
_mint(msg.sender, nftId);
_setTokenURI(nftId, tokenURI);
emit PropertyCreated(nftId, msg.sender, address(newProperty), surfaceM2, totalTokens);
}
}
Oracle integration for real-time price feeds with auto-initialization:
function getETHPrice() public returns (uint256) {
if (currentPrice.price == 0 || block.timestamp >= currentPrice.timestamp + 3600) {
_recordPrice();
}
require(currentPrice.price > 0, "Factory__OracleError");
return currentPrice.price;
}
The platform integrates advanced AI capabilities to automatically generate professional property content, streamlining the tokenization process:
The /api/generate-property
endpoint orchestrates a complete AI workflow:
// 1. Property Analysis & Description Generation
const description = await generateDescription(surface, location);
// 2. AI-Generated Property Visualization
const imageBlob = await generateImage(surface, location);
// 3. Decentralized Storage
const imageFile = new File([imageBlob], `property-${Date.now()}.png`);
const imageUpload = await pinata.upload.file(imageFile);
// 4. Complete Metadata Package
const metadata = {
name: `Property ${surface}m² - ${location}`,
description,
image: `ipfs://${imageUpload.IpfsHash}`,
attributes: [
{ trait_type: "Surface", value: `${surface} m²` },
{ trait_type: "Location", value: location },
{
trait_type: "Estimated Rooms",
value: Math.floor(surface / 25),
},
{ trait_type: "Annual Yield", value: "20%" },
],
};
Advanced Property Description Generation:
- Model:
mistral-small-latest
for optimal quality - Prompt Engineering: Specialized real estate analysis prompts
- Context-Aware: Surface-based property type estimation
- Investment Focus: Emphasizes tokenization and yield potential
const prompt = `Generate a professional real estate description for:
- Surface: ${surface}m²
- Location: ${location}
- Type: ${
surface < 50
? "Modern Studio"
: surface < 100
? "Spacious Apartment"
: "Luxury Villa"
}
- Estimated Rooms: ${Math.floor(surface / 25)}
- Annual Yield: 20%
Format: Professional, engaging paragraph (250-300 words)
Focus: Investment potential, location benefits, tokenized ownership`;
Professional Property Visualization:
- Model: FLUX.1-dev for photorealistic results
- Dynamic Prompts: Surface and location-adaptive descriptions
- Quality Optimization: 8K resolution, architectural photography style
- Variety: Random seed generation for unique visualizations
const imagePrompt = `Modern real estate property photography,
${
surface < 50
? "cozy studio apartment"
: surface < 100
? "spacious apartment with open floor plan"
: "luxury villa with garden"
},
located in ${location}, bright natural lighting, high-end finishes,
minimalist design, wide angle lens, photorealistic,
award winning architecture photography, 8k resolution.`;
- Automated Content Creation: Eliminates manual description writing
- Professional Quality: AI-generated content matches industry standards
- Scalability: Handle hundreds of property listings efficiently
- Consistency: Uniform quality across all property descriptions
- Localization Ready: Easily adaptable for different markets
- Cost Efficiency: Reduces content creation overhead
- Node.js 18+ and npm/yarn
- MetaMask wallet with Coston2 testnet configured
- Pinata Account for IPFS storage (optional)
-
Install dependencies:
cd backend npm install
-
Configure environment (.env):
COSTON2_PRIVATE_KEY=your_private_key_without_0x_prefix FLARESCAN_API_KEY=your_flarescan_api_key
-
Compile and test:
npx hardhat compile npx hardhat test
-
Deploy to Coston2:
npx hardhat ignition deploy ./ignition/modules/PropertyTokenFactory.module.js --network coston2 --verify
-
Install dependencies:
cd frontend npm install
-
Configure environment (.env.local):
# Deployed contract addresses NEXT_PUBLIC_FACTORY_ADDRESS=0x... # IPFS/Pinata configuration NEXT_PUBLIC_PINATA_JWT=your_pinata_jwt_token NEXT_PUBLIC_PINATA_GATEWAY=gateway.pinata.cloud # AI Content Generation NEXT_PUBLIC_MISTRAL_API_KEY=your_mistral_api_key NEXT_PUBLIC_FREEPIK_API_KEY=your_freepik_api_key
-
Start development server:
npm run dev
-
Configure MetaMask for Coston2:
- Network Name: Flare Coston2 Testnet
- RPC URL: https://coston2-api.flare.network/ext/C/rpc
- Chain ID: 114
- Symbol: C2FLR
- Get test tokens: Coston2 Faucet
# Deploy to Coston2 testnet
npx hardhat ignition deploy ./ignition/modules/PropertyTokenFactory.module.js --network coston2 --verify
# For mainnet deployment
npx hardhat ignition deploy ./ignition/modules/PropertyTokenFactory.module.js --network flare --verify
Vercel (Recommended):
cd frontend
npm run build
vercel --prod
Configure environment variables in Vercel dashboard with your contract addresses and API keys.
"Factory__OracleError()" when calling getETHPrice()
- Solution: The FTSOv2 price needs initialization. Call
refreshPrice()
manually or the contract auto-initializes on first call.
"Not whitelisted" error during property creation
- Solution: Verify Merkle proof generation:
const leaves = whitelist.map((addr) => keccak256(addr)); const tree = new MerkleTree(leaves, keccak256, { sortPairs: true }); const proof = tree.getHexProof(keccak256(userAddress));
Wallet connection issues
- Solution: Ensure Coston2 network is properly configured in MetaMask with correct RPC URL and Chain ID.
Contract interaction failures
- Solution: Verify contract addresses and ensure artifact files are up-to-date after deployment.
"AI content generation fails" during property creation
-
Solution: Check API keys configuration:
# Verify environment variables echo $NEXT_PUBLIC_MISTRAL_API_KEY echo $NEXT_PUBLIC_FREEPIK_API_KEY # Test API endpoints curl -H "Authorization: Bearer $MISTRAL_API_KEY" https://api.mistral.ai/v1/models curl -H "x-freepik-api-key: $FREEPIK_API_KEY" https://api.freepik.com/v1/ai/text-to-image
"IPFS upload failures" for generated images
-
Solution: Verify Pinata configuration:
const pinata = new PinataSDK({ pinataJwt: process.env.NEXT_PUBLIC_PINATA_JWT, pinataGateway: process.env.NEXT_PUBLIC_PINATA_GATEWAY, }); // Test authentication const testAuth = await pinata.testAuthentication(); console.log("Pinata Auth:", testAuth);
"Property generation timeout" errors
- Solution: Increase timeout in Next.js config and implement retry logic for failed AI requests.
- Flare Network: https://dev.flare.network/
- FTSOv2 Integration: https://dev.flare.network/tech/ftso/
- Coston2 Faucet: https://faucet.flare.network/coston2
- Block Explorer: https://coston2.testnet.flarescan.com/
- Hardhat Documentation: https://hardhat.org/docs
- Wagmi Documentation: https://wagmi.sh/
- RainbowKit Documentation: https://www.rainbowkit.com/docs
- Mistral AI API: https://docs.mistral.ai/
- Freepik API Documentation: https://www.freepik.com/api/doc
- Pinata IPFS Documentation: https://docs.pinata.cloud/
Contributions are welcome! Areas for improvement:
- Core Features: Add advanced property types, multi-currency support, automated rent distribution
- Smart Contracts: Gas optimization, security enhancements, upgrade patterns
- Frontend: Analytics dashboard, mobile app, advanced filtering
- AI Enhancement: Multi-language support, property valuation models, image style variations
- Developer Experience: Improved documentation, comprehensive testing, CI/CD pipelines
- Fork the repository and create a feature branch
- Follow coding standards as defined in the project
- Write comprehensive tests for new functionality
- Update documentation to reflect changes
- Submit a pull request with detailed description
This project is proudly developed as part of the Flare Ambassador Program, which encourages developers to build innovative applications on the Flare Network ecosystem.
- Apply to become a Flare Ambassador: Flare Ambassador Program
- Developer Community: Flare Developer Portal
- Discord: https://discord.gg/flarenetwork
© 2025 Flare Real Estate Tokenization dApp
Built for the Flare Ambassador Program
Created by Antoine Delamare | Blockchain & Cie