Why Real World Asset (RWA) on Rootstock For Bitcoin enthusiasts, Real World Assets is a goldmine of opportunity. And here is where Rootstock (as a scaling solution for Bitcoin) steps in. Rootstock offers a platform that not only integrates with Ethereum and the Bitcoin network (as Layer 2), it also enhances Bitcoin by enabling smart contracts, a feature #Bitcoin lacks natively. This integration allows for the tokenization of real estate on a blockchain that is secured by Bitcoin hash power, providing an unprecedented layer of security and trust for investors. The concept of tokenizing real estate is not just about owning a piece of property digitally; it is about fractional ownership, liquidity, and global accessibility to markets that were once exclusive and cumbersome. Guide to Build and Deploy RWA Tokenized Real Estate on Rootstock Prerequisites and Tools Here are what you should be familiar with/and get hands on: 1. Understand: Tokenization Real estate shares/fractionalization 2. Install Node.js and nmp: To interact with the blockchain and run Solidity development tools. sudo apt-get install -y nodejs sudo apt-get install -y npm 3. Install Truffle npm install -g truffle 4. Rootstock Node (rskj): To interact with the Rootstock network, we need an RSK node. And we can run a local Rootstock node or connect to a public node (Mainnet or Testnet). Follow instructions on how to set up an RSK node here. 5. Web3.js 6. Configure Web3 and Rootstock: Use Web3.js to interact with Rootstock smart contracts. Install it using: npm install web3 Connect to the Rootstock network (testnet for testing, mainnet for production) by creating a Web3 provider: const Web3 = require('web3'); const web3 = new Web3('https://public-node.testnet.rsk.co'); // Testnet URL 7. Metamask wallet a. Adding Rootstock Testnet to Metamask and get tRBTC faucet: - Open the MetaMask Chrome extension - In the network options, choose custom RPC - Enter "RSK Testnet" as the Network Name - Enter https://public-node.testnet.rsk.co as the RPC URL - Enter "RBTC" as SymbolPut and Save - Copy the account address - Get the Faucet (tRBTC) from: https://faucet.testnet.rsk.co/ 8. OpenZeppelin: For standard contract templates (ERC-20, ERC-721, ERC-1400). 9. Rootstock Docs: Comprehensive documentation for connecting to Rootstock. Setting up Smart Contract Development Since we are tokenizing real estate, it is advisable to follow ERC-1400 standard for security tokens, to ensures compliance and legal ownership rules. a. ERC-1400 (Security Token Standard) Here is a smart contract for real estate tokens using ERC-20, which can adapt to ERC-1400 for security tokens: // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract RealEstateToken is ERC20 { address public owner; string public propertyDetails; // Store property metadata constructor(uint256 initialSupply, string memory _propertyDetails) ERC20("RealEstateToken", "RET") { owner = msg.sender; propertyDetails = _propertyDetails; _mint(msg.sender, initialSupply); } // Custom logic for ownership transfers and compliance can be added here } b. Compile and Deploy Smart Contracts Once the smart contract is written, compile and deploy it using Truffle. truffle compile truffle migrate --network rskTestnet Make sure to configure truffle-config.js to connect to Rootstock Testnet or Mainnet by providing the correct RPC URL and network settings. Integrating Frontend Next now is to build a frontend for the DApp where users can interact with the tokenized real estate platform, view properties, and purchase or trade tokens. a. Create a Framework (React.js) npx create-react-app real-estate-dapp cd real-estate-dapp b. Install Dependencies: npm install web3 npm install @mui/material # Material-UI for styling Project Structure real-estate-dapp/ ├── public/ └── src/ ├── components/ │ ├── PropertyList.js │ ├── PropertyDetails.js │ └── BuyToken.js ├── App.js ├── index.js └── web3.js Set Up Web3.js Connection In src/web3.js, set up a Web3 instance connected to Rootstock: import Web3 from 'web3'; let web3; if (window.ethereum) { web3 = new Web3(window.ethereum); try { window.ethereum.enable(); } catch (error) { console.log("User denied account access."); } } else if (window.web3) { web3 = new Web3(window.web3.currentProvider); } else { alert("Please install MetaMask to interact with this platform."); } export default web3; Creating Smart Contract Interaction in App.js In App.js, connect to the deployed smart contract. Use the contract’s ABI and address: import React, { useEffect, useState } from 'react'; import web3 from './web3'; import PropertyList from './components/PropertyList'; import BuyToken from './components/BuyToken'; // Replace these with your smart contract's ABI and deployed address const contractABI = [ /* ABI goes here */ ]; const contractAddress = "0xYourContractAddress"; const contract = new web3.eth.Contract(contractABI, contractAddress); function App() { const [properties, setProperties] = useState([]); const [account, setAccount] = useState(''); useEffect(() => { // Get the user's account const loadAccount = async () => { const accounts = await web3.eth.getAccounts(); setAccount(accounts[0]); }; // Load the properties from the contract (pseudo-function, implement in contract) const loadProperties = async () => { const propCount = await contract.methods.propertyCount().call(); const propArray = []; for (let i = 0; i < propCount; i++) { const property = await contract.methods.properties(i).call(); propArray.push(property); } setProperties(propArray); }; loadAccount(); loadProperties(); }, []); return ( <div> <h1>Real Estate Tokenized Platform</h1> <PropertyList properties={properties} /> <BuyToken contract={contract} account={account} /> </div> ); } export default App; Display Properties (PropertyList.js) In PropertyList.js, display a list of properties that are retrieved from the smart contract. import React from 'react'; import React from 'react'; function PropertyList({ properties }) { return ( <div> <h2>Available Properties</h2> <ul> {properties.map((property, index) => ( <li key={index}> <h3>{property.name}</h3> <p>{property.description}</p> <p>Price per Token: {web3.utils.fromWei(property.price, 'ether')} R-BTC</p> </li> ))} </ul> </div> ); } export default PropertyList; Create Buy Token Component (BuyToken.js) BuyToken.js component lets users buy tokens for a specific property. import React, { useState } from 'react'; function BuyToken({ contract, account }) { const [propertyId, setPropertyId] = useState(''); const [amount, setAmount] = useState(''); const buyTokens = async () => { try { const pricePerToken = await contract.methods.getPricePerToken(propertyId).call(); const totalCost = web3.utils.toWei((pricePerToken * amount).toString(), 'ether'); await contract.methods.buyTokens(propertyId, amount).send({ from: account, value: totalCost, }); alert('Tokens purchased successfully!'); } catch (error) { console.error("Error purchasing tokens:", error); } }; return ( <div> <h2>Buy Tokens</h2> <input type="text" placeholder="Property ID" value={propertyId} onChange={(e) => setPropertyId(e.target.value)} /> <input type="number" placeholder="Number of Tokens" value={amount} onChange={(e) => setAmount(e.target.value)} /> <button onClick={buyTokens}>Buy Tokens</button> </div> ); } export default BuyToken; You can also consider using database (MongoDB) to store additional property details and display metadata like images or descriptions. Deploy on Rootstock Mainnet Once you are satisfied with the testing, next is to deploy the DApp on Rootstock Mainnet. Update your truffle-config.js or hardhat.config.js to point to the Mainnet RPC: networks: { rskMainnet: { provider: () => new HDWalletProvider(mnemonic, 'https://public-node.rsk.co'), network_id: 30, // Rootstock Mainnet ID gasPrice: 60000000 } } Then, deploy: truffle migrate --network rskMainnet In Conclusion These steps set a valid guide to create a decentralized real estate tokenization platform on Rootstock. Why Real World Asset (RWA) on Rootstock For Bitcoin enthusiasts, Real World Assets is a goldmine of opportunity. And here is where Rootstock (as a scaling solution for Bitcoin) steps in. For Bitcoin enthusiasts, Real World Assets is a goldmine of opportunity. And here is where Rootstock (as a scaling solution for Bitcoin) steps in. Rootstock offers a platform that not only integrates with Ethereum and the Bitcoin network (as Layer 2), it also enhances Bitcoin by enabling smart contracts, a feature #Bitcoin lacks natively. This integration allows for the tokenization of real estate on a blockchain that is secured by Bitcoin hash power, providing an unprecedented layer of security and trust for investors. The concept of tokenizing real estate is not just about owning a piece of property digitally; it is about fractional ownership, liquidity, and global accessibility to markets that were once exclusive and cumbersome. Guide to Build and Deploy RWA Tokenized Real Estate on Rootstock Prerequisites and Tools Prerequisites and Tools Here are what you should be familiar with/and get hands on: Here are what you should be familiar with/and get hands on: 1. Understand: Tokenization Real estate shares/fractionalization Tokenization Real estate shares/fractionalization 2. Install Node.js and nmp: To interact with the blockchain and run Solidity development tools. sudo apt-get install -y nodejs sudo apt-get install -y npm sudo apt-get install -y nodejs sudo apt-get install -y npm 3. Install Truffle npm install -g truffle npm install -g truffle 4. Rootstock Node (rskj): To interact with the Rootstock network, we need an RSK node. And we can run a local Rootstock node or connect to a public node (Mainnet or Testnet). Follow instructions on how to set up an RSK node here. Follow instructions on how to set up an RSK node here. 5. Web3.js 6. Configure Web3 and Rootstock: Use Web3.js to interact with Rootstock smart contracts. Install it using: Install it using: npm install web3 npm install web3 Connect to the Rootstock network (testnet for testing, mainnet for production) by creating a Web3 provider: const Web3 = require('web3'); const web3 = new Web3('https://public-node.testnet.rsk.co'); // Testnet URL const Web3 = require('web3'); const web3 = new Web3('https://public-node.testnet.rsk.co'); // Testnet URL 7. Metamask wallet a. Adding Rootstock Testnet to Metamask and get tRBTC faucet: a. Adding Rootstock Testnet to Metamask and get tRBTC faucet: a. Adding Rootstock Testnet to Metamask and get tRBTC faucet: - Open the MetaMask Chrome extension - In the network options, choose custom RPC - Enter "RSK Testnet" as the Network Name - Enter https://public-node.testnet.rsk.co as the RPC URL - Enter "RBTC" as SymbolPut and Save - Copy the account address - Get the Faucet (tRBTC) from: https://faucet.testnet.rsk.co/ 8. OpenZeppelin: For standard contract templates (ERC-20, ERC-721, ERC-1400). 9. Rootstock Docs: Comprehensive documentation for connecting to Rootstock. Setting up Smart Contract Development Setting up Smart Contract Development Since we are tokenizing real estate, it is advisable to follow ERC-1400 standard for security tokens, to ensures compliance and legal ownership rules. a. ERC-1400 (Security Token Standard) a. ERC-1400 (Security Token Standard) a. ERC-1400 (Security Token Standard) Here is a smart contract for real estate tokens using ERC-20, which can adapt to ERC-1400 for security tokens: // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract RealEstateToken is ERC20 { address public owner; string public propertyDetails; // Store property metadata constructor(uint256 initialSupply, string memory _propertyDetails) ERC20("RealEstateToken", "RET") { owner = msg.sender; propertyDetails = _propertyDetails; _mint(msg.sender, initialSupply); } // Custom logic for ownership transfers and compliance can be added here } // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract RealEstateToken is ERC20 { address public owner; string public propertyDetails; // Store property metadata constructor(uint256 initialSupply, string memory _propertyDetails) ERC20("RealEstateToken", "RET") { owner = msg.sender; propertyDetails = _propertyDetails; _mint(msg.sender, initialSupply); } // Custom logic for ownership transfers and compliance can be added here } b. Compile and Deploy Smart Contracts Compile and Deploy Smart Contracts Compile and Deploy Smart Contracts Once the smart contract is written, compile and deploy it using Truffle. truffle compile truffle migrate --network rskTestnet truffle compile truffle migrate --network rskTestnet Make sure to configure truffle-config.js to connect to Rootstock Testnet or Mainnet by providing the correct RPC URL and network settings. Integrating Frontend Integrating Frontend Next now is to build a frontend for the DApp where users can interact with the tokenized real estate platform, view properties, and purchase or trade tokens. a. Create a Framework (React.js) a. Create a Framework (React.js) a. Create a Framework (React.js) npx create-react-app real-estate-dapp cd real-estate-dapp npx create-react-app real-estate-dapp cd real-estate-dapp b. Install Dependencies: b. Install Dependencies: b. Install Dependencies: npm install web3 npm install @mui/material # Material-UI for styling npm install web3 npm install @mui/material # Material-UI for styling Project Structure Project Structure real-estate-dapp/ ├── public/ └── src/ ├── components/ │ ├── PropertyList.js │ ├── PropertyDetails.js │ └── BuyToken.js ├── App.js ├── index.js └── web3.js real-estate-dapp/ ├── public/ └── src/ ├── components/ │ ├── PropertyList.js │ ├── PropertyDetails.js │ └── BuyToken.js ├── App.js ├── index.js └── web3.js Set Up Web3.js Connection Set Up Web3.js Connection In src/web3.js, set up a Web3 instance connected to Rootstock: import Web3 from 'web3'; let web3; if (window.ethereum) { web3 = new Web3(window.ethereum); try { window.ethereum.enable(); } catch (error) { console.log("User denied account access."); } } else if (window.web3) { web3 = new Web3(window.web3.currentProvider); } else { alert("Please install MetaMask to interact with this platform."); } export default web3; import Web3 from 'web3'; let web3; if (window.ethereum) { web3 = new Web3(window.ethereum); try { window.ethereum.enable(); } catch (error) { console.log("User denied account access."); } } else if (window.web3) { web3 = new Web3(window.web3.currentProvider); } else { alert("Please install MetaMask to interact with this platform."); } export default web3; Creating Smart Contract Interaction in App.js Creating Smart Contract Interaction in App.js In App.js, connect to the deployed smart contract. Use the contract’s ABI and address: import React, { useEffect, useState } from 'react'; import web3 from './web3'; import PropertyList from './components/PropertyList'; import BuyToken from './components/BuyToken'; // Replace these with your smart contract's ABI and deployed address const contractABI = [ /* ABI goes here */ ]; const contractAddress = "0xYourContractAddress"; const contract = new web3.eth.Contract(contractABI, contractAddress); function App() { const [properties, setProperties] = useState([]); const [account, setAccount] = useState(''); useEffect(() => { // Get the user's account const loadAccount = async () => { const accounts = await web3.eth.getAccounts(); setAccount(accounts[0]); }; // Load the properties from the contract (pseudo-function, implement in contract) const loadProperties = async () => { const propCount = await contract.methods.propertyCount().call(); const propArray = []; for (let i = 0; i < propCount; i++) { const property = await contract.methods.properties(i).call(); propArray.push(property); } setProperties(propArray); }; loadAccount(); loadProperties(); }, []); return ( <div> <h1>Real Estate Tokenized Platform</h1> <PropertyList properties={properties} /> <BuyToken contract={contract} account={account} /> </div> ); } export default App; import React, { useEffect, useState } from 'react'; import web3 from './web3'; import PropertyList from './components/PropertyList'; import BuyToken from './components/BuyToken'; // Replace these with your smart contract's ABI and deployed address const contractABI = [ /* ABI goes here */ ]; const contractAddress = "0xYourContractAddress"; const contract = new web3.eth.Contract(contractABI, contractAddress); function App() { const [properties, setProperties] = useState([]); const [account, setAccount] = useState(''); useEffect(() => { // Get the user's account const loadAccount = async () => { const accounts = await web3.eth.getAccounts(); setAccount(accounts[0]); }; // Load the properties from the contract (pseudo-function, implement in contract) const loadProperties = async () => { const propCount = await contract.methods.propertyCount().call(); const propArray = []; for (let i = 0; i < propCount; i++) { const property = await contract.methods.properties(i).call(); propArray.push(property); } setProperties(propArray); }; loadAccount(); loadProperties(); }, []); return ( <div> <h1>Real Estate Tokenized Platform</h1> <PropertyList properties={properties} /> <BuyToken contract={contract} account={account} /> </div> ); } export default App; Display Properties (PropertyList.js) Display Properties (PropertyList.js) In PropertyList.js, display a list of properties that are retrieved from the smart contract. import React from 'react'; import React from 'react'; function PropertyList({ properties }) { return ( <div> <h2>Available Properties</h2> <ul> {properties.map((property, index) => ( <li key={index}> <h3>{property.name}</h3> <p>{property.description}</p> <p>Price per Token: {web3.utils.fromWei(property.price, 'ether')} R-BTC</p> </li> ))} </ul> </div> ); } export default PropertyList; import React from 'react'; function PropertyList({ properties }) { return ( <div> <h2>Available Properties</h2> <ul> {properties.map((property, index) => ( <li key={index}> <h3>{property.name}</h3> <p>{property.description}</p> <p>Price per Token: {web3.utils.fromWei(property.price, 'ether')} R-BTC</p> </li> ))} </ul> </div> ); } export default PropertyList; Create Buy Token Component (BuyToken.js) Create Buy Token Component (BuyToken.js) BuyToken.js component lets users buy tokens for a specific property. import React, { useState } from 'react'; function BuyToken({ contract, account }) { const [propertyId, setPropertyId] = useState(''); const [amount, setAmount] = useState(''); const buyTokens = async () => { try { const pricePerToken = await contract.methods.getPricePerToken(propertyId).call(); const totalCost = web3.utils.toWei((pricePerToken * amount).toString(), 'ether'); await contract.methods.buyTokens(propertyId, amount).send({ from: account, value: totalCost, }); alert('Tokens purchased successfully!'); } catch (error) { console.error("Error purchasing tokens:", error); } }; return ( <div> <h2>Buy Tokens</h2> <input type="text" placeholder="Property ID" value={propertyId} onChange={(e) => setPropertyId(e.target.value)} /> <input type="number" placeholder="Number of Tokens" value={amount} onChange={(e) => setAmount(e.target.value)} /> <button onClick={buyTokens}>Buy Tokens</button> </div> ); } export default BuyToken; import React, { useState } from 'react'; function BuyToken({ contract, account }) { const [propertyId, setPropertyId] = useState(''); const [amount, setAmount] = useState(''); const buyTokens = async () => { try { const pricePerToken = await contract.methods.getPricePerToken(propertyId).call(); const totalCost = web3.utils.toWei((pricePerToken * amount).toString(), 'ether'); await contract.methods.buyTokens(propertyId, amount).send({ from: account, value: totalCost, }); alert('Tokens purchased successfully!'); } catch (error) { console.error("Error purchasing tokens:", error); } }; return ( <div> <h2>Buy Tokens</h2> <input type="text" placeholder="Property ID" value={propertyId} onChange={(e) => setPropertyId(e.target.value)} /> <input type="number" placeholder="Number of Tokens" value={amount} onChange={(e) => setAmount(e.target.value)} /> <button onClick={buyTokens}>Buy Tokens</button> </div> ); } export default BuyToken; You can also consider using database (MongoDB) to store additional property details and display metadata like images or descriptions. You can also consider using database (MongoDB) to store additional property details and display metadata like images or descriptions. Deploy on Rootstock Mainnet Deploy on Rootstock Mainnet Once you are satisfied with the testing, next is to deploy the DApp on Rootstock Mainnet. Update your truffle-config.js or hardhat.config.js to point to the Mainnet RPC: networks: { rskMainnet: { provider: () => new HDWalletProvider(mnemonic, 'https://public-node.rsk.co'), network_id: 30, // Rootstock Mainnet ID gasPrice: 60000000 } } networks: { rskMainnet: { provider: () => new HDWalletProvider(mnemonic, 'https://public-node.rsk.co'), network_id: 30, // Rootstock Mainnet ID gasPrice: 60000000 } } Then, deploy: truffle migrate --network rskMainnet truffle migrate --network rskMainnet In Conclusion In Conclusion These steps set a valid guide to create a decentralized real estate tokenization platform on Rootstock.