This is a Cardano project which enables Homeowners, Contractors, and Inspectors to easily manage major home remodel projects.
This project utilizes Cardano Smart Contracts to simplify the process of scheduled payments for major milestones in a project. The high-level workflow is below:
- Once the Homeowner and Contractor have signed a contract, the Contractor will pull a permit with an Inspector (usually a county or other municipality)
- Once the permit is issued, the Inspector creates a unique NFT Policy (using mintPermitFromScript.sh)
- The Homeowner can then deposit funds into the contract
- The Contractor will be able to retrieve funds from the contract as milestones are met and published to the unique NFT Policy
- If the project is
ClosedIncomplete
, the Homeowner will be able to retrieve their remaining funds
To create the NFT project for the milestones:
- Clone this repository
- Open
nix-shell
- Run
cabal build
- In Inspector.Deploy.hs:
- Update the
inspector
field with the PubKeyHash of the wallet serving as the Inspector - Update the
utxo
field with the utxo that will used to create the InspectorNFT policy
- Update the
- Run
main
in Inspector.Deploy.hs to createMint.plutus
- Run mintPermitFromScript.sh and follow the prompts to create the Inspector NFT
- Additional scripts are provided for the other Inspector NFTs
- mintRoughFromScript.sh - NFT to indicate
"RoughPassed"
- mintDrywallFromScript.sh - NFT to indicate
"DrywallPassed"
- mintFinalFromScript.sh - NFT to indicate
"FinalPassed"
- mintClosedFromScript.sh - NFT to indicate
"ClosedIncomplete"
- In this scenario, the Homeowner can withdraw any funds not owed to the Contractor
- mintRoughFromScript.sh - NFT to indicate
- Note that for the steps outlined in the scripts provided below, a corresponding Inspector NFT will need to be minted and selected at each step or the Milestones validation will fail
- In Milestones.DeployNFT.hs:
- Update the
contractor
field with the PubKeyHash of the wallet serving as the Contractor - Update the
TokenName
field with a meaningful name for this Milestone project, this will be the AuthNFT's TokenName - Update the
utxo
field with the utxo that will used to create the unique AuthNFT policy
- Update the
- Run
main
in Milestones.DeployNFT.hs to createMint.plutus
- Run mintMilestonesAuthNFT.sh and follow the prompts to create the Milestones AuthNFT
- The AuthNFT will be sent to the Contractor's address that you provided
- You will send this AuthNFT to the Validator's ScriptAddress using the 0-initializeContract.sh script later in this process
- In Milestones.DeployOnChain.hs:
- Update the
contractor
field with the PubKeyHash of the wallet serving as the Contractor - Update the
homeowner
field with the PubKeyHash of the wallet serving as the Homeowner - Update the
totalCost
field with the total cost of the project (in Lovelace) - Update the individual payment fields, note that the sum of these 4 must add up to the
totalCost
- Update the
deposit
field with the amount for the first Homeowner payment - Update the
secondPayment
field with the amount for the second Homeowner payment - Update the
thirdPayment
field with the amount for the third Homeowner payment - Update the
finalPayment
field with the amount for the fourth Homeowner payment
- Update the
- Update the
inspectionPolicyId
field with the Inspector NFT's policyID - Update the
projectPolicyId
field with the Milestones AuthNFT policyID
- Update the
- Run
main
in Milestones.DeployOnChain.hs to createMilestones.plutus
- Run 0-initializeContract.sh and follow the prompts to transfer the AuthNFT from the Contractor's wallet to the Validator's ScriptAddress
- This will transfer the AuthNFT to the Milestones ScriptAddress and set the initial
lastBalance
datum value to 2ADA (2000000 Lovelace) to account for the 2ADA MinUTXO that came with the AuthNFT - This will also create milestonesScript.addr which will be automatically referenced by all future shell scripts below
You can create your own off-chain transactions, but a sequence of transactions has been created to help demonstrate the flow of the application
- Following the sequence below will demonstrate the flow of a normal project, including deliberate failing transactions that show the Validator logic preventing malicious behavior
- Several scripts have been created, prefixed
<index>-<step-name>.sh
such as 1-contractorStartProject.sh - These work with the corresponding datum files in
src/Milestones/Deploy/<index>-<step-name>
that were created with their corresponding Deploy files insrc/Milestones/DeployAdditional_<index>_<step-name>.hs
- You can re-run these Deploy files to create your own custom Datum files if you choose, but since they only rely on the
Milestones.plutus
andmilestonesScript.addr
that were created with your custom inputs above, you can use them as-is with no changes - For this walkthrough, you can ignore these Deploy and Datum files, they will be hardcoded for ease of use in the walkthrough scripts
- You can re-run these Deploy files to create your own custom Datum files if you choose, but since they only rely on the
- To use the application, simply run the scripts in order starting with 1-contractorStartProject.sh followed by 2-homeownerFirstDeposit.sh and so on
- The shell scripts will indicate what is happening at each step and what values need to be provided
- The Homeowner can deposit funds at any step of the project, except for if the Inspector NFT is
"FinalPassed"
or"ClosedIncomplete"
since both indicate the project is over- If the Inspector mints the
"ClosedIncomplete"
NFT, the Homeowner will be able to remove any remaining owed funds
- If the Inspector mints the
- Note that for each step where a contractor is withdrawing funds, the corresponding Inspector NFT needs to be minted and referenced. See the Inspector NFT scripts above to mint these as needed
- Additionally, since each Contractor withdrawal depends on a corresponding Inspector NFT, you can easily test the expected failure case by trying to (for example) run 5-contractorWithdrawDrywall.sh before the Inspector's mintDrywallFromScript.sh (or by simply selecting the wrong InspectorNFT in any of the Contractor scripts). This will result in the Milestones validator rejecting the withdrawal, since the Inspector has not passed this phase of the project. This can be checked for every Contractor step as desired
- Step 5 in this flow is set to fail deliberately. After confirming this failure, you can continue with 6-contractorWithdrawRough.sh
- When you reach step 8 in the provided workflow, you can choose to either have the Contractor get their final payment with 8a-contractorWithdrawFinal.sh, or if you mint a
"ClosedIncomplete"
NFT from the Inspector using mintClosedFromScript.sh, you can have the Homeowner retrieve their balance of funds using 8b-homeownerWithdrawProjectFail.sh