Smart Rental Agreement

What it does:
A smart contract that digitizes rental agreements, automatically handling rent payments, security deposits, late fees, and lease conditions without intermediaries.

Why it matters:
Traditional rental agreements rely on trust, paperwork, and manual enforcement. This contract ensures rent is paid on time, deposits are handled fairly, and all rules are enforced transparently on-chain.

How it works:

  • Landlord and tenant agree on rent terms.

  • Tenant deposits a security deposit and periodic rent.

  • Rent is paid automatically per rental period.

  • Late payments trigger penalties.

  • Deposit is released or partially withheld at lease end.

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

/**
 * @title SmartRentalAgreement
 * @author Nam
 * @notice On-chain rental agreement with automated rent and deposit handling
 */
contract SmartRentalAgreement {

    // -------------------- STATE VARIABLES --------------------

    address public landlord;
    address public tenant;

    uint256 public rentAmount;        // Rent per period
    uint256 public rentInterval;      // Rental interval (e.g. 30 days)
    uint256 public securityDeposit;
    uint256 public lateFee;           // Flat late fee
    uint256 public leaseEnd;

    uint256 public lastRentPaid;
    bool public active;

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

    event LeaseStarted();
    event RentPaid(uint256 amount);
    event LateFeePaid(uint256 amount);
    event LeaseEnded(uint256 depositReturned);

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

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

    modifier onlyLandlord() {
        require(msg.sender == landlord, "Not landlord");
        _;
    }

    modifier leaseActive() {
        require(active, "Lease inactive");
        _;
    }

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

    constructor(
        address _tenant,
        uint256 _rentAmount,
        uint256 _rentInterval,
        uint256 _securityDeposit,
        uint256 _lateFee,
        uint256 _leaseDuration
    ) {
        require(_tenant != address(0), "Invalid tenant");
        require(_rentAmount > 0, "Invalid rent");
        require(_rentInterval > 0, "Invalid interval");

        landlord = msg.sender;
        tenant = _tenant;
        rentAmount = _rentAmount;
        rentInterval = _rentInterval;
        securityDeposit = _securityDeposit;
        lateFee = _lateFee;
        leaseEnd = block.timestamp + _leaseDuration;
    }

    // -------------------- LEASE START --------------------

    /**
     * @notice Tenant starts lease by paying deposit
     */
    function startLease() external payable onlyTenant {
        require(!active, "Already active");
        require(
            msg.value == securityDeposit,
            "Incorrect deposit"
        );

        active = true;
        lastRentPaid = block.timestamp;

        emit LeaseStarted();
    }

    // -------------------- RENT PAYMENT --------------------

    /**
     * @notice Pay periodic rent
     */
    function payRent() external payable onlyTenant leaseActive {
        require(
            block.timestamp  dueDate) {
            totalDue += lateFee;
            emit LateFeePaid(lateFee);
        }

        require(msg.value == totalDue, "Incorrect payment");

        lastRentPaid = block.timestamp;
        payable(landlord).transfer(msg.value);

        emit RentPaid(msg.value);
    }

    // -------------------- LEASE END --------------------

    /**
     * @notice End lease and release deposit
     */
    function endLease(uint256 damageCost)
        external
        onlyLandlord
        leaseActive
    {
        require(block.timestamp >= leaseEnd, "Lease ongoing");
        require(damageCost  0) {
            payable(tenant).transfer(refund);
        }

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

        emit LeaseEnded(refund);
    }

    // -------------------- VIEW FUNCTIONS --------------------

    function nextRentDue() external view returns (uint256) {
        return lastRentPaid + rentInterval;
    }
}