Solidity contract for Real Estate tokenization
This project defines a fungible security token in Solidity that represents a real-world asset (like real estate) generating a monthly rental income. Because there may be over 1 million token holders, this project focuses on implementing an income distribution method that is both efficient (low gas cost) and trustless (no need to trust the contract owner).
In the first solution, we use a pull-based dividend system using the "magnified dividend per share" technique. When rental income is received, the contract updates a global dividend variable. Each token holder can then withdraw their accumulated dividend based on their balance, without requiring a loop over all holders in a single transaction. This approach reduces gas costs and avoids scalability issues.
A pull-based dividend system is a mechanism where the contract owner distributes dividends to token holders. The token holders can then withdraw their dividends by calling a function on the contract.
- The contract owner distributes dividends to token holders by calling the
distributeDividends
function every month (or period). - The token holders can then withdraw their dividends by calling a function on the contract.
- If the contract owner doesn't distribute the dividends, the token holders can't withdraw their dividends.
- If the token holders don't withdraw their dividends, the dividends remain in the contract.
- The gas cost is paid by the contract owner when calling the
distributeDividends
function, and the gas cost is paid by each token holder when withdrawing their dividends.
- There is no need to iterate over all token holders in a single transaction.
- The contract owner can't cheat the token holders because the token holders can always withdraw their dividends.
- The contract can handle a large number of token holders because the gas cost is low.
- Requires monthly updates of the dividend variable.
- The contract owner needs to call the distributeDividends function on the contract every month to distribute the dividends.
The second solution uses a Merkle tree to distribute dividends. An off-chain process computes a Merkle tree that maps each token holder’s address to their dividend amount, and only the Merkle root is stored on-chain. Token holders claim their dividend by providing a valid Merkle proof. This approach is also efficient since it avoids iterating through all holders on-chain, although it requires off-chain computation and monthly updates of the Merkle root.
A Merkle tree is a data structure where each non-leaf node is the hash of its two child nodes. The leaves represent individual data items, such as each token holder's dividend allocation. By combining the hashes in pairs repeatedly, you end up with a single hash at the top called the Merkle root. This structure allows anyone to verify that a particular piece of data is part of the tree by using only a small subset of the entire tree, making it very efficient.
- An off-chain process first calculates the dividend for each token holder and creates a Merkle tree from these values.
- Each leaf in the tree is generated by hashing a token holder’s address with their corresponding dividend amount.
- The process then pairs these hashes and continues hashing up the tree until a single Merkle root is produced.
- This Merkle root is stored on-chain.
- When a token holder wants to claim their dividend, they must provide a Merkle proof—a list of hashes that, when combined with their own, recreates the Merkle root.
- The contract verifies this proof to ensure that the claim is valid without needing to process every holder's data on-chain.
- Only a single Merkle root is stored on-chain, drastically reducing storage needs and gas costs.
- The method scales well even with millions of token holders since it avoids iterating over every account on-chain.
- The structure of the Merkle tree ensures data integrity, as any tampering with the data would change the Merkle root.
- The Merkle tree must be computed off-chain and updated periodically, which introduces reliance on an external process.
- Token holders need additional tools or interfaces to generate and submit their Merkle proofs when claiming dividends.
In this solution, the contract uses a push-based dividend mechanism to automatically distribute rental income to token holders. When rental income is deposited into the contract, the owner can trigger a process that pushes dividends directly to each token holder's address in batches.
A push-based dividend system is one where the contract actively sends dividend payments to token holders rather than waiting for them to claim their dividends. The contract owner (or an automated process) triggers the distribution, which calculates each holder’s dividend share and directly transfers funds to their accounts.
- When rental income is received, it is added to a dividend pool within the contract.
- The owner then calls a function that processes token holders in batches.
- For each holder in the specified batch, the contract calculates the dividend based on the holder’s balance relative to the total token supply and transfers the appropriate amount.
- Dividends are sent directly to token holders without requiring them to manually withdraw funds.
- Token holders receive their dividends automatically, enhancing the overall user experience.
- Once the dividend pool is funded, token holders can receive their income without extra steps.
- Distributing dividends to a large number of holders requires splitting the process into batches, which can introduce delays.
- The owner bears the gas cost for each batch transaction, and handling many accounts might lead to high cumulative gas fees.
- Maintaining an accurate list of token holders and ensuring that all batches are processed correctly adds design complexity.