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.
Prerequisites and Tools
Here are what you should be familiar with/and get hands on:
1. Understand:
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.