Rental Deposit Refund Contract

What it does:
Locks a tenant’s security deposit in a smart contract and automatically refunds it (fully or partially) after the rental period, based on agreed conditions.

Why it matters:
Eliminates deposit disputes by making refund rules transparent, enforceable, and trustless for both tenants and landlords.

How it works:

  • Tenant deposits security funds into the contract.

  • Rental period and refund conditions are predefined.

  • An inspection result (landlord / oracle / DAO) determines deductions.

  • Remaining funds are automatically refunded to the tenant.

      // SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * @title RentalDepositRefund
 * @author Nam
 * @notice Trustless escrow for rental security deposits
 */
contract RentalDepositRefund {

    // -------------------- ROLES --------------------

    address public landlord;
    address public tenant;
    address public inspector;

    // -------------------- STATE --------------------

    uint256 public depositAmount;
    uint256 public leaseEndTime;
    bool public deposited;
    bool public settled;

    // Damage cost determined after inspection
    uint256 public damageCost;

    // -------------------- EVENTS --------------------

    event DepositMade(address indexed tenant, uint256 amount);
    event InspectionCompleted(uint256 damageCost);
    event DepositSettled(uint256 refundedToTenant, uint256 paidToLandlord);

    // -------------------- MODIFIERS --------------------

    modifier onlyTenant() {
        require(msg.sender == tenant, "Not tenant");
        _;
    }

    modifier onlyInspector() {
        require(msg.sender == inspector, "Not inspector");
        _;
    }

    modifier notSettled() {
        require(!settled, "Already settled");
        _;
    }

    // -------------------- CONSTRUCTOR --------------------

    constructor(
        address _tenant,
        address _inspector,
        uint256 _leaseDuration
    ) {
        require(_tenant != address(0), "Invalid tenant");
        require(_inspector != address(0), "Invalid inspector");
        require(_leaseDuration > 0, "Invalid duration");

        landlord = msg.sender;
        tenant = _tenant;
        inspector = _inspector;
        leaseEndTime = block.timestamp + _leaseDuration;
    }

    // -------------------- DEPOSIT --------------------

    /**
     * @notice Tenant deposits security funds
     */
    function deposit() external payable onlyTenant {
        require(!deposited, "Already deposited");
        require(msg.value > 0, "Zero deposit");

        depositAmount = msg.value;
        deposited = true;

        emit DepositMade(msg.sender, msg.value);
    }

    // -------------------- INSPECTION --------------------

    /**
     * @notice Inspector submits damage cost after lease ends
     */
    function submitInspection(uint256 _damageCost)
        external
        onlyInspector
        notSettled
    {
        require(block.timestamp >= leaseEndTime, "Lease not ended");
        require(_damageCost = leaseEndTime, "Lease active");

        settled = true;

        uint256 landlordAmount = damageCost;
        uint256 tenantRefund = depositAmount - damageCost;

        if (landlordAmount > 0) {
            payable(landlord).transfer(landlordAmount);
        }

        if (tenantRefund > 0) {
            payable(tenant).transfer(tenantRefund);
        }

        emit DepositSettled(tenantRefund, landlordAmount);
    }
}