Docs / Smart Contracts
Smart Contracts
All contracts are deployed and verified on Arbitrum Sepolia (chainId 421614). Source in contracts/. ABIs in artifacts/. Frontend ABIs in app/lib/contracts.ts.
// Architecture
Wallet
β
ββ @iexec-nox/handle β { handle, handleProof } β Intel TDX TEE
β
ββ usdt.approve(PropertyToken, amount)
ββ PropertyToken.purchaseTokens(handle, proof, amount)
β Nox.fromExternal(handle, proof) β euint256 (encrypted balance)
β Nox.allowThis + Nox.allow(amount, wallet)
β
ββ PropertyRegistry.registerHolder(propertyId, wallet)
β β
β ββ RentDistributor.distributeRent() β USDT per holder (equal share)
β β
β ββ TierNFT.mint() β Gold/Platinum require isHolder() gate
β
ββ SecondaryMarket
β β grantOperator β createListing(tokenContract, id, amount, price)
β β usdt.approve(SecondaryMarket) β executeBuy(listingId)
β β confidentialTransferFrom (encrypted) via ERC-7984
β β
β ββ CESTToken.stake() β getTier() β fee discount (0.5% β 0%)
β
ββ ConfidentialGovernance
β β registry.isHolder() β onlyHolder gate
β ββ createProposal / castVote / finalizeProposal
β
ββ TierNFT (Soulbound)
β CESTToken.getTier() β badge tier eligibility
β CEST burned β treasury (fee-discount reserve)
β recordPoints(wallet, handle, proof) β euint256 encrypted points
ββ airdropMultiplierBps / feeDiscountiExec Nox Integration β All Contracts
iApp Live Test Evidence
Verified on iExecThe iExec Nox iApp was live-tested on April 30, 2026 against the Arbitrum Sepolia PropertyToken contracts. All 5 latest tasks completed successfully β 100% success rate on the latest test run. All deals used the same Intel TDX enclave, confirming the full TEE encryption pipeline is operational end-to-end.
Latest Tasks
5 / 5
100% β latest run
Total Deals
8+
all at 0.1 RLC
Deal Price
0.1 RLC
Test Date
30 Apr 2026
iApp (TEE Enclave)
0xB11bC7288eE239F6536829E410d22Eb514C5E282 βjancok075/iexec:0.0.1-tdx-1f1d5e8f915a
Tag: tee,tdx β Intel TDX hardware enclave
Latest Requested Tasks β April 30, 2026
0x7c10bcβ¦de3a1COMPLETED04/30/2026 01:33 PM0xca537dβ¦1fcc3COMPLETED04/30/2026 01:26 PM0xee7f34β¦80365COMPLETED04/30/2026 01:25 PM0x423c62β¦8a4d9COMPLETED04/30/2026 11:26 AM0x6091cfβ¦5df0dCOMPLETED04/30/2026 09:42 AMShowing page 1 of 3 β all 5 latest tasks COMPLETED. Full history at iExec Explorer β
Latest Requested Deals β iApp 0xb11bc7β¦5e282
0xe8990cβ¦76b951h ago100%0.1 RLC0x3d6a21β¦2d00b1h ago100%0.1 RLC0xaa4fd6β¦3c3b71h ago100%0.1 RLC0x8e424dβ¦9119c3h ago100%0.1 RLC0x31da2eβ¦173585h ago100%0.1 RLCShowing page 1 of 3 β all latest deals at 100% success. Workerpool: 0x2956f0β¦3123f Β· No dataset.
IPFS Document Registry
10 / 10 PinnedAll legal documents are pinned to IPFS via Pinata and accessible via ipfs.io and gateway.pinata.cloud gateways. CIDs are immutable β content is guaranteed identical across all gateways.
SPV Structure Document
QmPzTpiTzYcQNJ12eGRjvYtXVj6vHtcHK2UtJZpfD3wtAJSPV Structure Document
QmUe6PK91ZHbPGtwE6tqyp1K2AX2NYboLvzBy9usd99oxqPropertyToken.sol
One instance per property, deployed via CREATE2 from PropertyRegistry. The core confidential token β balances stored as euint256, encrypted by Intel TDX TEE. No observer can read holdings.
Inherits
Key Functions
purchaseTokens(bytes32 handle, bytes handleProof, uint256 clearAmount)publicPay USDT, receive encrypted tokens. handle + handleProof generated by @iexec-nox/handle SDK.
grantOperator(address operator, uint256 expiry)holderDelegate transfer rights to SecondaryMarket for listings. Expiry in unix timestamp.
pricePerToken() β uint256viewToken price in USDT 6 decimals. All 5 deployed = 1_000_000 ($1.00).
propertyId() β uint256viewID assigned by PropertyRegistry (1β5 for current properties).
Notes
- Β·Transfers never revert on insufficient balance (ERC-7984 spec β prevents balance inference via gas)
- Β·Events do not emit token amounts β privacy by design
- Β·Salt for CREATE2 = bytes32(propertyId) β deterministic addresses
PropertyRegistry.sol
Central registry and CREATE2 factory. Admin lists properties, which deploys a new PropertyToken. Tracks all holders per property for RentDistributor. Currently 5 active properties.
Inherits
Key Functions
listProperty(string name, string location, string ipfsDocHash, uint256 totalSupply, uint256 pricePerToken, uint256 monthlyRent) β (uint256 propertyId, address tokenContract)onlyOwnerDeploys PropertyToken via CREATE2, registers property. pricePerToken in USDT 6 decimals.
registerHolder(uint256 propertyId, address holder)approvedCalled by PropertyToken on purchase and by approved markets. Prevents duplicate entries.
setApprovedMarket(address market, bool approved)onlyOwnerWhitelist SecondaryMarket to register buyers as holders post-trade.
getPropertyHolders(uint256 propertyId) β address[]viewReturns all registered holder addresses. Used by RentDistributor.
properties(uint256) β PropertyviewReturns full property struct: id, name, location, supply, price, rent, status, tokenContract.
propertyCount() β uint256viewTotal properties listed. Currently 5.
Notes
- Β·owner() = 0x834De729cb9dF77451DBc6bf7FD05F475B011Ac7 (treasury/deployer)
- Β·paused() = false (all contracts operational)
SecondaryMarket.sol
Fixed-price P2P listing marketplace for property token trading. Sellers post a listing at a fixed price; buyers execute against it. Token amounts moved via confidentialTransferFrom (encrypted). CEST stakers get fee discounts.
Inherits
Key Functions
createListing(address tokenContract, uint256 propertyId, uint256 tokenAmount, uint256 pricePerToken) β uint256 listingIdpublicRequires grantOperator first. pricePerToken in USDT 6 decimals (e.g. $1.025 = 1_025_000). Returns listingId.
executeBuy(uint256 listingId)publicBuyer must approve USDT first. Triggers confidentialTransferFrom (encrypted). Deducts 0.5% fee (reduced by CEST tier).
cancelListing(uint256 listingId)sellerSeller can cancel an active listing at any time.
listings(uint256) β ListingviewReturns: listingId, seller, tokenContract, propertyId, tokenAmount, pricePerToken, listedAt, active.
Notes
- Β·Fee: 0.5% base, reduced by CEST staking tier (0% for PLATINUM)
- Β·Seller must call propertyToken.grantOperator(secondaryMarket, expiry) before listing
- Β·Buyer must call usdt.approve(secondaryMarket, totalCost) before executeBuy
RentDistributor.sol
Receives monthly USDT from the property operator and distributes 90% to all registered holders. Platform takes 5%, maintenance reserve 5%. Equal-share model (not pro-rata) because ERC-7984 balances cannot be read on-chain.
Inherits
Key Functions
depositRent(uint256 propertyId, uint256 amount)onlyOwnerDeposit USDT rent for a property. Accumulates in pendingRent[propertyId].
distributeRent(uint256 propertyId)onlyOwnerDistribute accumulated pendingRent β splits: 5% platform + 5% maintenance + 90% equally to all holders.
getDistributionHistory(uint256 propertyId) β RentDistribution[]viewReturns past distributions for a property.
getPendingRent(uint256 propertyId) β uint256viewReturns accumulated undistributed rent for a property.
Notes
- Β·Equal share per holder β not pro-rata by token balance
- Β·Pro-rata distribution planned for Phase 2 using iExec Nox compute over encrypted balances
- Β·All distribution totals are on-chain auditable; per-investor amounts are private
CESTToken.sol
Utility and future-governance token. 1 Billion total supply. Staking unlocks: (1) SecondaryMarket fee discounts (0.5% β 0% at PLATINUM), (2) TierNFT badge eligibility (determines mint tier). Now includes iExec Nox integration: after staking, holders can call encryptMyStake() to store their staked amount as an encrypted euint256 handle via Nox.fromExternal() β adding a confidential layer on top of the on-chain stake record. Price: $0.04 β $40M market cap.
Inherits
Key Functions
stake(uint256 amount, uint256 lockDays)publicTime-lock CEST for tier benefits. Min 30 days, max 365 days. Adds to existing staked amount. Tier automatically recalculates.
unstake(uint256 amount)holderWithdraw a specific staked CEST amount after lock period expires. Tier recalculates automatically.
encryptMyStake(externalEuint256 handle, bytes handleProof)holderiExec Nox: store your staked amount as encrypted euint256. Call after stake(). Uses Nox.fromExternal(handle, handleProof) β same TEE-verified pattern as PropertyToken. Only you can decrypt your stake amount off-chain via Nox JS SDK.
encryptedStake(address holder) β euint256viewReturns the Nox-encrypted stake handle. Only readable (decryptable) by the holder via Nox.allow().
getTier(address account) β StakingTierviewReturns NONE/BRONZE/SILVER/GOLD/PLATINUM based on staked balance. Read by TierNFT.getTier() for badge eligibility.
getFeeDiscount(address account) β uint256viewReturns discount in BPS (0β10000). PLATINUM = 10000 (100% free). Used by SecondaryMarket.executeBuy().
Notes
- Β·ERC20Votes = delegation only (future DAO) β ConfidentialGovernance uses PropertyToken holder status, not CEST
- Β·TierNFT reads CESTToken.getTier() to determine which badge tier a wallet qualifies for
- Β·Faucet drips 2,400 CEST (~$96) per address per 24h on testnet
- Β·Total supply: 1,000,000,000 Β· Airdrop pool: 250,000,000 (25%)
ConfidentialGovernance.sol
Property-level governance gated by PropertyToken (ERC-7984) holder status β NOT by CEST token. Each verified holder gets exactly 1 vote regardless of their encrypted token balance, preventing whale dominance while preserving full privacy. Holder status checked via registry.isHolder().
Inherits
Key Functions
createProposal(uint256 propertyId, ProposalType proposalType, string description) β uint256 proposalIdonlyHolderCreate a governance proposal for a property. ProposalType: RentAdjustment | Maintenance | PropertyStatus | Other.
castVote(uint256 proposalId, VoteOption option)holder1 address = 1 vote. VoteOption: For | Against | Abstain. Balance-blind β no whale advantage visible on-chain.
finalizeProposal(uint256 proposalId)publicFinalize a proposal after voting deadline. Checks quorum and majority. Any address can call.
getProposal(uint256 proposalId) β ProposalviewReturns full proposal struct including vote counts and execution status.
getProposalsByProperty(uint256 propertyId) β Proposal[]viewReturns all proposals for a property.
Notes
- Β·Access control: registry.isHolder(propertyId, msg.sender) β no balance exposed
- Β·1 address = 1 vote (balance-blind for privacy)
- Β·Proposals: rent adjustments, maintenance, property status changes
TierNFT.sol
Soulbound (non-transferable) ERC-721 tier badge. Minted by staking CEST via CESTToken.stake() and paying a CEST burn cost to the treasury (fee-discount reserve pool). Four tiers: Bronze / Silver / Gold / Platinum. Gold and Platinum additionally require the caller to hold a Nox ERC-7984 PropertyToken β proved via PropertyRegistry.isHolder(). On-chain testnet interaction points are stored as encrypted euint256 using Nox.fromExternal() + Nox.add() β the same TEE-verified pattern as PropertyToken.purchaseTokens(). No observer can read your point balance.
Inherits
Key Functions
mint()publicMint your tier badge. Requires: (1) CESTToken.stake(amount, days) to reach a tier, (2) CEST.approve(TierNFT, mintCost). CEST cost is sent to treasury. Gold/Platinum also require PropertyRegistry.isHolder() (Nox gate).
upgrade()holderUpgrade existing badge to a higher tier by paying only the cost delta. Example: BronzeβGold = 8,000β500 = 7,500 CEST. Requires CESTToken.getTier() to have increased.
recordPoints(address holder, externalEuint256 handle, bytes handleProof)onlyOwnerRecord encrypted testnet interaction points. Uses Nox.fromExternal(handle, handleProof) β same pattern as PropertyToken. Points are accumulated as euint256: never readable on-chain. Only holder can decrypt via Nox JS SDK.
getTier(address holder) β TierviewReturns live eligible tier based on CESTToken.getTier() (staked amount). None/Bronze/Silver/Gold/Platinum.
airdropMultiplierBps(address holder) β uint16viewReturns airdrop multiplier in BPS (100=1Γ, 110=1.1Γ, 125=1.25Γ, 150=1.5Γ, 200=2Γ) based on minted badge tier.
feeDiscount(address holder) β uint8viewReturns fee discount percentage (0/5/10/15/20) based on minted badge tier.
encryptedPoints(address holder) β euint256viewReturns the Nox-encrypted points handle. Requires Nox.allow() access β only holder can decrypt off-chain.
hasBadge(address holder) β boolviewReturns true if the wallet has minted a badge.
badgeTier(address holder) β TierviewReturns the tier of the minted badge (may differ from live getTier if balance dropped).
Notes
- Β·Soulbound: _update() reverts on wallet-to-wallet transfer (ERC-721 override)
- Β·Mint costs burned to treasury: Bronze 500 Β· Silver 2K Β· Gold 8K Β· Platinum 25K CEST
- Β·upgrade() costs delta only: e.g. SilverβPlatinum = 25,000β2,000 = 23,000 CEST
- Β·Point amounts omitted from PointsRecorded event β confidentiality by design
- Β·Gold/Platinum require PropertyRegistry.isHolder() β must have purchased via Nox TEE first