26/05/2025
Part-3
Here's a sample smart contract in Solidity for a blockchain-based land registry system with:
โ
Multiple owners with share percentages
โ
Immutable land metadata (e.g., GPS, direction)
โ
Transfer of ownership shares
๐ Assumptions:
Land is tokenized as an NFT (ERC721-style).
Percentages are tracked via mappings.
Mutation (transfer of shares) requires only the owner's approval.
Simplified for demonstration โ not production-grade.
๐งฑ LandRegistry.sol
solidity
Copy
Edit
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract LandRegistry {
struct Owner {
uint256 share; // In percentage (e.g., 20 means 20%)
bool exists;
}
struct LandMetadata {
string plotId;
string village;
string district;
string direction; // e.g., "East"
string gpsCoordinates; // GeoJSON or simple lat-long
uint256 totalArea; // e.g., in square yards
}
struct LandParcel {
LandMetadata metadata;
address[] ownerAddresses;
mapping(address => Owner) owners;
}
mapping(string => LandParcel) public lands; // plotId => LandParcel
event LandRegistered(string plotId, string village, uint256 area);
event OwnershipTransferred(string plotId, address from, address to, uint256 share);
// Modifier to check only valid land
modifier landExists(string memory plotId) {
require(bytes(lands[plotId].metadata.plotId).length > 0, "Land not registered");
_;
}
// Register new land with metadata and owners
function registerLand(
string memory plotId,
string memory village,
string memory district,
string memory direction,
string memory gpsCoordinates,
uint256 totalArea,
address[] memory initialOwners,
uint256[] memory initialShares
) public {
require(bytes(lands[plotId].metadata.plotId).length == 0, "Land already registered");
require(initialOwners.length == initialShares.length, "Mismatched owner/share data");
uint256 totalShare = 0;
LandParcel storage land = lands[plotId];
land.metadata = LandMetadata(plotId, village, district, direction, gpsCoordinates, totalArea);
land.ownerAddresses = initialOwners;
for (uint256 i = 0; i < initialOwners.length; i++) {
land.owners[initialOwners[i]] = Owner(initialShares[i], true);
totalShare += initialShares[i];
}
require(totalShare == 100, "Total share must equal 100");
emit LandRegistered(plotId, village, totalArea);
}
// Get owner share for a plot
function getOwnerShare(string memory plotId, address owner) public view landExists(plotId) returns (uint256) {
Owner storage o = lands[plotId].owners[owner];
return o.exists ? o.share : 0;
}
// Transfer a percentage share to another person
function transferShare(string memory plotId, address to, uint256 share) public landExists(plotId) {
LandParcel storage land = lands[plotId];
Owner storage sender = land.owners[msg.sender];
require(sender.exists && sender.share >= share, "Insufficient share or not an owner");
sender.share -= share;
if (!land.owners[to].exists) {
land.ownerAddresses.push(to);
land.owners[to] = Owner(share, true);
} else {
land.owners[to].share += share;
}
emit OwnershipTransferred(plotId, msg.sender, to, share);
}
// Get all owners and their shares
function getOwners(string memory plotId) public view landExists(plotId) returns (address[] memory, uint256[] memory) {
LandParcel storage land = lands[plotId];
address[] memory addresses = land.ownerAddresses;
uint256[] memory shares = new uint256[](addresses.length);
for (uint256 i = 0; i < addresses.length; i++) {
shares[i] = land.owners[addresses[i]].share;
}
return (addresses, shares);
}
}
๐งช Sample Use Case
Register Land
solidity
Copy
Edit
registerLand(
"PLOT123",
"Jewar",
"Gautam Buddh Nagar",
"East",
"28.0982,77.5213",
300,
[0xRajesh, 0xSunita, 0xPankaj],
[60, 20, 20]
)
Transfer 10% from Rajesh to Amit
solidity
Copy
Edit
transferShare("PLOT123", 0xAmit, 10);
Get All Owners
solidity
Copy
Edit
getOwners("PLOT123");
โ
Key Features:
Share percentage-based ownership
Metadata with land direction and GPS
Transparent, traceable mutations
Future-ready for Aadhaar integration, zoning rules, e-stamping