This repository uses the recommended structure for a Soroban project:
.
├── contracts
│ └── hello_world
│ ├── src
│ │ ├── lib.rs
│ │ └── test.rs
│ └── Cargo.toml
├── Cargo.toml
└── README.md
- New Soroban contracts can be put in
contracts, each in their own directory. There is already ahello_worldcontract in there to get you started. - If you initialized this project with any other example contracts via
--with-example, those contracts will be in thecontractsdirectory as well. - Contracts should have their own
Cargo.tomlfiles that rely on the top-levelCargo.tomlworkspace for their dependencies. - Frontend libraries can be added to the top-level directory as well. If you initialized this project with a frontend template via
--frontend-templateyou will have those files already included.
- Network: Stellar Testnet
- Contract ID: CAEGD57WVTVQSYWYB23AISBW334QO7WNA5XQ56S45GH6BP3D2AVHKUG4
LeaseFlow manages the full lifecycle of a property lease on-chain — from creation through rent streaming to deposit settlement and lease closure. The landlord initialises the lease with terms and a deposit requirement; the tenant activates it by funding the deposit; rent streams continuously to the landlord while the lease is active; and when the lease ends the protocol calculates the final settlement, releases the remaining deposit to the tenant, and closes the record. This design keeps funds non-custodial and settlement logic transparent at every step.
sequenceDiagram
autonumber
participant L as Landlord
participant T as Tenant
participant P as LeaseFlow Protocol
participant S as Payment Stream
L->>P: create_lease(landlord, tenant, rent_amount, deposit_amount, start_date, end_date, property_uri)
P-->>L: LeaseCreated (status: Pending, lease record stored)
T->>P: activate_lease(lease_id) + deposit funds
P-->>T: LeaseActivated (status: Active, deposit_amount locked)
P->>S: start_stream(lease_id, rent_amount, recipient: landlord)
S-->>P: StreamActive (streaming rent each ledger tick)
loop Every ledger / payment interval
S->>L: stream rent payment (rent_amount per period)
end
T->>P: stop_stream(lease_id)
P->>S: halt_stream(lease_id)
S-->>P: StreamSettled (final_amount calculated)
P-->>T: release_deposit(lease_id) - remaining deposit refunded
T->>P: return_asset(lease_id)
P-->>L: AssetReturned (landlord notified)
P-->>T: LeaseClosed (status: Closed, lease record finalised)
-
Landlord calls
create_lease— Passes tenant address,rent_amount,deposit_amount,start_date,end_date, and aproperty_uri(e.g. an IPFS link to the property listing). The protocol stores the lease record with statusPending. -
Protocol emits
LeaseCreated— The lease is registered in contract instance storage under theleasekey. No funds move yet. -
Tenant calls
activate_leaseand funds the deposit — The tenant transfersdeposit_amountto the contract. The protocol validates the amount and flips the lease status toActive. -
Protocol emits
LeaseActivated— Deposit is locked in the contract. The lease is now live and the payment stream can begin. -
Protocol starts the payment stream — Internally triggers
start_streamwith the agreedrent_amountrate and the landlord as recipient. The stream is tied to the lease record. -
Stream flows each ledger tick — Rent is continuously streamed from the locked funds to the landlord's address at the agreed rate for the duration of the lease.
-
Tenant signals end of lease via
stop_stream— Tenant calls the protocol to halt the stream, indicating they are ready to return the asset and close out. -
Protocol halts the stream and settles — Calls
halt_streaminternally; the stream calculates thefinal_amountpaid and reports back. Any unstreamed rent is reconciled. -
Protocol releases remaining deposit to tenant — After settlement,
release_depositreturns the unused portion ofdeposit_amountto the tenant's address. -
Tenant calls
return_asset— Signals that the physical or digital asset has been returned to the landlord. The protocol records this on-chain. -
Protocol closes the lease — Emits
AssetReturnedto the landlord andLeaseClosedto the tenant. The lease status is set toClosedand the record is finalised in storage.
-
Tenant never returns the asset — If
return_assetis not called before theend_date+ grace period, the protocol can slash all or part of thedeposit_amountas a penalty and mark the leaseDefaulted. Seetest_deposit_release_disputedfor the disputed-return flow. -
Stream runs out of funds before lease ends — If the tenant's deposited funds are exhausted before
end_date, the stream halts automatically. The protocol records the shortfall; the landlord can claim the remaining deposit as partial compensation. Seetest_deposit_release_partial_refundfor this scenario. -
Landlord disputes the return condition — If the landlord rejects the asset return (e.g. damage claim), the lease enters a
Disputedstate. The deposit is held in escrow until the dispute is resolved — either by on-chain arbitration logic or a manual settlement call. Seetest_deposit_release_disputedfor the disputed-return snapshot.