A decentralized application (dApp) for tokenizing real estate assets in Indonesia, built on Mantle Sepolia Testnet. This platform enables fractional ownership of property through ERC-20 compliant security tokens with built-in KYC compliance.
- Frontend: https://idproperty.vercel.app/
| Contract | Address | Status |
|---|---|---|
| KYCRegistry | 0xeaea25d2021e069aa6858b133e727b63ea5bce92 |
β Verified |
| IndonesiaPropertyToken | 0x96437740de3af7f644557f6c3371b86525d595e7 |
β Verified |
- Property Tokenization: View tokenized property details including location, valuation, and legal documents
- KYC Compliance: Integrated KYC verification system with multiple levels (Basic, Verified, Accredited)
- Token Transfers: Transfer tokens between verified investors with real-time balance updates
- Portfolio Management: Track your token holdings and ownership percentage
- Admin Dashboard: Manage KYC registrations, freeze accounts, and perform force transfers
- Multi-wallet Support: Connect via MetaMask, Rainbow, Coinbase Wallet, and more
- 97 comprehensive smart contract tests
- Custom errors for gas optimization
- Pausable for emergency stops
- Two-step admin transfer
- Access control with admin functions
- Freeze/unfreeze accounts for AML compliance
- Investment limits enforcement (min/max)
idproperty/
βββ contract/ # Smart contracts (Foundry)
β βββ src/
β β βββ KYCRegistry.sol # KYC verification (2.5 KB)
β β βββ IndonesiaPropertyToken.sol # ERC-20 token (6.0 KB)
β βββ test/
β β βββ KYCRegistry.t.sol # 38 tests
β β βββ IndonesiaPropertyToken.t.sol # 59 tests
β βββ script/
β β βββ Deploy.s.sol # Deployment script
β βββ foundry.toml
βββ frontend/ # React frontend
β βββ src/
β β βββ components/ # UI components
β β βββ config/ # Contract ABIs & config
β β βββ hooks/ # Web3 hooks
β β βββ pages/ # App pages
β β βββ lib/ # Utilities
β βββ package.json
βββ .env.example # Environment template
βββ README.md # This file
- Foundry
- Node.js 18+
- MetaMask or compatible Web3 wallet
# Clone repository
git clone https://github.com/azharpratama/idproperty
cd idproperty
# Install contract dependencies
cd contract && forge install
# Install frontend dependencies
cd ../frontend && npm installcd contract
forge buildcd contract
# Run all tests
forge test
# Run with gas report
forge test --gas-report
# Run with verbosity
forge test -vvvExpected: All 97 tests passing β
cd contract
# 1. Configure ../.env with your PRIVATE_KEY
# 2. Deploy to Mantle Sepolia
forge script script/Deploy.s.sol \
--rpc-url https://rpc.sepolia.mantle.xyz \
--broadcast \
--verify \
-vvvv# Check contract balance
cast call <CONTRACT_ADDRESS> "totalSupply()" --rpc-url https://rpc.sepolia.mantle.xyz
# Get token name
cast call <CONTRACT_ADDRESS> "name()" --rpc-url https://rpc.sepolia.mantle.xyzcd frontend
npm install
npm run devVisit http://localhost:5173
cd frontend
npm run build| Page | Path | Description |
|---|---|---|
| Home | / |
Platform overview and key statistics |
| Property | /property |
Detailed property information |
| Portfolio | /portfolio |
User's token holdings |
| Transfer | /transfer |
Send tokens to other investors |
| KYC Status | /kyc |
View KYC verification status |
| Admin | /admin |
Admin functions (owner only) |
| Function | Description | Access |
|---|---|---|
registerInvestor(address, level, countryCode, validDays) |
Register KYC verified investor | Admin |
updateInvestor(address, newLevel) |
Update KYC level | Admin |
revokeInvestor(address) |
Revoke KYC (blacklist) | Admin |
isVerified(address) |
Check if investor is verified | Public |
meetsLevel(address, level) |
Check minimum KYC level | Public |
| Function | Description | Access |
|---|---|---|
transfer(to, value) |
Transfer tokens (KYC required) | Public |
freezeAccount(account, reason) |
Freeze account (AML) | Admin |
unfreezeAccount(account) |
Unfreeze account | Admin |
forceTransfer(from, to, value) |
Force transfer (legal) | Admin |
getOwnershipPercent(owner) |
Get ownership % (basis points) | Public |
canTransfer(from, to, value) |
Check if transfer allowed | Public |
| Level | Code | Requirements |
|---|---|---|
| NONE | 0 | Not verified |
| BASIC | 1 | KTP only |
| VERIFIED | 2 | KTP + NPWP |
| ACCREDITED | 3 | KTP + NPWP + Asset Proof |
- Solidity 0.8.30
- Foundry (Forge, Cast, Anvil)
- React 19, TypeScript, Vite 6
- Tailwind CSS 4
- Wagmi 2, Viem 2, RainbowKit 2
- TanStack React Query 5
PRIVATE_KEY=your_private_key
ETHERSCAN_API_KEY=your_mantlescan_api_keyVITE_CONTRACT_ADDRESS=0x96437740de3af7f644557f6c3371b86525d595e7
VITE_KYC_REGISTRY_ADDRESS=0xeaea25d2021e069aa6858b133e727b63ea5bce92- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Azhar Aditya Pratama
- GitHub: @azharpratama
Built for HackQuest Indonesia: Co-Learning Camp 6 - Mantle
This project is licensed under the MIT License - see the LICENSE file for details.
Copyright (c) 2025 Azhar Aditya Pratama