0
const { ethers } = require("hardhat")
const { time } = require("@nomicfoundation/hardhat-network-helpers");

describe("Escrow", function () {
 let Escrow;
 let escrow;
 let PropertyToken;
 let propertyToken;
 let owner;
 let inspector;
 let seller;
 let buyer;
 let tenant;

 const TOKEN_ID = 1;
 const PRICE_FOR_RENT = ethers.utils.parseEther("0.1");
 const PRICE_FOR_BUY = ethers.utils.parseEther("1");
 const ESCROW_AMOUNT = ethers.utils.parseEther("0.5");

 beforeEach(async function () {
   [owner, inspector, seller, buyer, tenant] = await ethers.getSigners();

   // Deploy PropertyToken with the initial owner
   PropertyToken = await ethers.getContractFactory("PropertyToken");
   propertyToken = await PropertyToken.deploy(owner.address);
   await propertyToken.deployed();

   // Mint a token to the seller
   await propertyToken.connect(owner).safeMint(seller.address, "Token URI");

   // Deploy Escrow with the correct arguments
   Escrow = await ethers.getContractFactory("Escrow");
   escrow = await Escrow.deploy(propertyToken.address, inspector.address);
   await escrow.deployed();

   // Approve the escrow contract to transfer the NFT
   await propertyToken.connect(seller).approve(escrow.address, TOKEN_ID);
 });

 describe("Deployment", function () {
   it("Should set the right PTK address", async function () {
     expect(await escrow.PTKaddress()).to.equal(propertyToken.address);
   });

   it("Should set the right inspector", async function () {
     expect(await escrow.inspector()).to.equal(inspector.address);
   });
 });

 describe("Listing Property", function () {
   it("Should list a property", async function () {
     await escrow.connect(seller).listProperty(TOKEN_ID, PRICE_FOR_RENT, PRICE_FOR_BUY, ESCROW_AMOUNT);
     expect(await escrow.getSeller(TOKEN_ID)).to.equal(seller.address);
   });

   it("Should not allow listing with zero prices", async function () {
     await expect(escrow.connect(seller).listProperty(TOKEN_ID, 0, PRICE_FOR_BUY, ESCROW_AMOUNT)).to.be.revertedWith("Enter a Amount greater than 0");
     await expect(escrow.connect(seller).listProperty(TOKEN_ID, PRICE_FOR_RENT, 0, ESCROW_AMOUNT)).to.be.revertedWith("Enter a Amount greater than 0");
   });
 });

 describe("Depositing Earnest", function () {
   beforeEach(async function () {
     await escrow.connect(seller).listProperty(TOKEN_ID, PRICE_FOR_RENT, PRICE_FOR_BUY, ESCROW_AMOUNT);
   });

   it("Should allow depositing earnest for buying", async function () {
     await expect(escrow.connect(buyer).depositEarnest(TOKEN_ID, false, { value: ESCROW_AMOUNT })).to.not.be.reverted;
   });

   it("Should allow depositing earnest for renting", async function () {
     await expect(escrow.connect(tenant).depositEarnest(TOKEN_ID, true, { value: PRICE_FOR_RENT })).to.not.be.reverted;
   });

   it("Should not allow depositing if property is not listed", async function () {
     await expect(escrow.connect(buyer).depositEarnest(TOKEN_ID + 1, false, { value: ESCROW_AMOUNT })).to.be.revertedWith("Property is already sold");
   });
 });

 describe("Executing Buy", function () {
   beforeEach(async function () {
     await escrow.connect(seller).listProperty(TOKEN_ID, PRICE_FOR_RENT, PRICE_FOR_BUY, ESCROW_AMOUNT);
     await escrow.connect(buyer).depositEarnest(TOKEN_ID, false, { value: ESCROW_AMOUNT });
     await escrow.connect(inspector).approveInspection(TOKEN_ID);
     await propertyToken.connect(seller).transferFrom(seller.address, escrow.address, TOKEN_ID);
     await buyer.sendTransaction({
       to: escrow.address,
       value: PRICE_FOR_BUY
     });
   });

   it("Should execute buying", async function () {
     await expect(escrow.connect(buyer).executeBuying(TOKEN_ID))
       .to.emit(escrow, "PurchaisedPropertySuccess")
       .withArgs(TOKEN_ID, buyer.address, seller.address);
   });

   it("Should not allow buying without inspection", async function () {
     await escrow.connect(seller).listProperty(TOKEN_ID + 1, PRICE_FOR_RENT, PRICE_FOR_BUY, ESCROW_AMOUNT);
     await escrow.connect(buyer).depositEarnest(TOKEN_ID + 1, false, { value: ESCROW_AMOUNT });
     await expect(escrow.connect(buyer).executeBuying(TOKEN_ID + 1)).to.be.revertedWith("Inspection Isn't passed");
   });
 });

 describe("Executing Rent", function () {
   beforeEach(async function () {
     await escrow.connect(seller).listProperty(TOKEN_ID, PRICE_FOR_RENT, PRICE_FOR_BUY, ESCROW_AMOUNT);
     await escrow.connect(tenant).depositEarnest(TOKEN_ID, true, { value: PRICE_FOR_RENT });
     await escrow.connect(inspector).approveInspection(TOKEN_ID);
     await propertyToken.connect(seller).transferFrom(seller.address, escrow.address, TOKEN_ID);
   });

   it("Should execute renting", async function () {
     await expect(escrow.connect(tenant).executeRent(TOKEN_ID, 7))
       .to.emit(escrow, "RentedPropertySuccess")
       .withArgs(TOKEN_ID, tenant.address, seller.address, 2); // 2 is rentForweek
   });

   it("Should not allow renting without earnest", async function () {
     await escrow.connect(seller).listProperty(TOKEN_ID + 1, PRICE_FOR_RENT, PRICE_FOR_BUY, ESCROW_AMOUNT);
     await escrow.connect(inspector).approveInspection(TOKEN_ID + 1);
     await expect(escrow.connect(tenant).executeRent(TOKEN_ID + 1, 7)).to.be.revertedWith("Have to deposit Earnest first");
   });
 });

 describe("Chainlink Automation", function () {
   beforeEach(async function () {
     await escrow.connect(seller).listProperty(TOKEN_ID, PRICE_FOR_RENT, PRICE_FOR_BUY, ESCROW_AMOUNT);
     await escrow.connect(tenant).depositEarnest(TOKEN_ID, true, { value: PRICE_FOR_RENT });
     await escrow.connect(inspector).approveInspection(TOKEN_ID);
     await propertyToken.connect(seller).transferFrom(seller.address, escrow.address, TOKEN_ID);
     await escrow.connect(tenant).executeRent(TOKEN_ID, 7);
   });

   it("Should check upkeep", async function () {
     await time.increase(8 * 24 * 60 * 60); // Increase time by 8 days
     const [upkeepNeeded, performData] = await escrow.checkUpkeep("0x");
     expect(upkeepNeeded).to.be.true;
   });

   it("Should perform upkeep", async function () {
     await time.increase(8 * 24 * 60 * 60); // Increase time by 8 days
     const [, performData] = await escrow.checkUpkeep("0x");
     await expect(escrow.performUpkeep(performData)).to.emit(escrow, "returnRentedProperty");
   });

   it("Should not need upkeep before rental period ends", async function () {
     const [upkeepNeeded] = await escrow.checkUpkeep("0x");
     expect(upkeepNeeded).to.be.false;
   });
 });
});
``` is my test file for contract ```//SPDX-License-Identifier:MIT
pragma solidity ^0.8.20;

import {PropertyToken} from "./ERC-721/PropertyToken.sol";
import {AutomationCompatibleInterface} from "@chainlink/contracts/src/v0.8/automation/AutomationCompatible.sol";
contract Escrow is AutomationCompatibleInterface{

   address public PTKaddress;
   address public inspector;
   PropertyToken public PTKcontract;

   uint rentFordays=1;
   uint rentForweek=2;
   uint rentFormonths=3;

   event returnRentedProperty(
       uint indexed nftId , 
       address indexed tenant,
       uint rentPaid
   );
   event PurchaisedPropertySuccess(
       uint indexed nftId , 
       address indexed buyer,
       address indexed seller
   );
   event RentedPropertySuccess(
       uint indexed nftId , 
       address indexed tenant,
       address indexed owner,
       uint rent
   );
   
   constructor(address _PTKaddress, address _inspector)
   {
       PTKaddress=_PTKaddress;
       inspector=_inspector;
       PTKcontract = PropertyToken(_PTKaddress);

   }

   modifier onlyInspector(){
       require(msg.sender==inspector,"Only inspector can call this function");
       _;
   }

   mapping(uint=>bool)isListed;
   mapping(uint=>address)tenant;
   mapping(uint=>uint)returnTime;
   mapping(address=>mapping(uint=>uint))rentDuration;
   mapping(uint=>address)sellers;
   mapping(uint=>uint)escrowAmount;
   mapping(uint=>uint)priceForRent;
   mapping(uint=>uint)priceForBuy;
   mapping(uint=>bool)isInspectionPassed;
   mapping(uint=> mapping(address=>bool))approval;

   uint[] public activeTokensOnRent;

   function listProperty(uint nftId,uint _priceForRent,uint _priceForBuy,uint _escrowAmt) public
   {
       require(_priceForRent>0,"Enter a Amount greater than 0");
       require(_priceForBuy>0,"Enter a Amount greater than 0");
       require(_escrowAmt>0,"Enter a Amount greater than 0");

       isListed[nftId] = true;
       sellers[nftId]=msg.sender;
       priceForRent[nftId] = _priceForRent;
       priceForBuy[nftId] = _priceForBuy;
       escrowAmount[nftId] = _escrowAmt;

   }

   function getTotalSupply() public view returns(uint){
       return PTKcontract.totalSupply();
   }

   function getSeller(uint nftId) public view  returns(address)
   {
       return sellers[nftId];
   }

   function approveInspection(uint nftId) public onlyInspector{
       isInspectionPassed[nftId]=true;
   }

   function getInspectionStatus(uint nftId) public view returns(bool){
       return isInspectionPassed[nftId];
   }

   function depositEarnest(uint nftId,bool rent) public payable
   {
       require(isListed[nftId],"Property is already sold");
       require(tenant[nftId]==address(0),"Property is on Rent");
       if(!rent)
           require(msg.value>=escrowAmount[nftId],"Amount should be greater than/equal to  escrow amount");
       else
       {
          require(msg.value>=priceForRent[nftId],"Amount should be greater than/equal to  escrow amount"); 
          tenant[nftId]=msg.sender;
       }
   }

   function approveSale(uint nftId) public {
       require(approval[nftId][msg.sender]==false,"ALready Approved");
       approval[nftId][msg.sender]=true;

   }

   function executeBuying(uint nftId) public {
       uint supply =  getTotalSupply();
       require(nftId<=supply,"Property doesn't exists");
       require(isInspectionPassed[nftId]==true,"Inspection Isn't passed");
       require(address(this).balance>=priceForBuy[nftId],"Insufficient balance");

       address seller = sellers[nftId];
       uint amount = escrowAmount[nftId];
       

       isListed[nftId]=false;
       (bool success,)=payable(seller).call{value:amount}("Amount transfered");
       PTKcontract.transferFrom(address(this),msg.sender,nftId);
       require(success,"Transfer to seller failed");
       emit PurchaisedPropertySuccess(nftId,msg.sender,seller);

   }

   function executeRent(uint nftId,uint duration) public {
       uint supply =  getTotalSupply();
       require(nftId<=supply,"Property doesn't exists");
       require(tenant[nftId]==msg.sender,"Have to deposit Earnest first");
       require(isInspectionPassed[nftId]==true,"Inspection Isn't passed");
       require(address(this).balance>=priceForRent[nftId],"Insufficient balance");

       address owner = sellers[nftId];
       uint amount = priceForRent[nftId];
       uint rent;

       if(duration<7)
           rent=rentFordays;
       else if(duration>=7 && duration<30)
           rent=rentForweek;
       else
           rent=rentFormonths;

       tenant[nftId]=msg.sender;
       returnTime[nftId]=block.timestamp+duration;
       rentDuration[msg.sender][nftId] = duration;
       (bool success,)=payable(owner).call{value:amount}("Amount transfered");
       PTKcontract.transferFrom(address(this),msg.sender,nftId);
       activeTokensOnRent.push(nftId);
       require(success,"Transfer to owner failed");
       emit RentedPropertySuccess(nftId,msg.sender,owner,rent);
   }

   function getTenant(uint nftId) public view returns(address){
       return tenant[nftId];
   }

   function returnRentedproperty(uint nftId) internal{
       require(tenant[nftId]!=address(0),"Property is not on rent");
       uint rent;
       address owner = sellers[nftId];
       address currentTenant = getTenant(nftId);
       uint duration = rentDuration[currentTenant][nftId];
       if(duration<7)
           rent=rentFordays;
       else if(duration>=7 && duration<30)
           rent=rentForweek;
       else
           rent=rentFormonths;

       
       uint amountToReturn = priceForRent[nftId]-rent;
       PTKcontract.transferFrom(currentTenant ,owner,nftId);
       (bool success,)=payable(currentTenant ).call{value:amountToReturn}("amount transferred to tenant");
       tenant[nftId]=address(0);
       returnTime[nftId] = 0;
       for(uint i=0;i<activeTokensOnRent.length;i++)
       {
           if(activeTokensOnRent[i]==nftId)
           {
               activeTokensOnRent[i] = activeTokensOnRent[activeTokensOnRent.length-1];
               activeTokensOnRent.pop();
               break;
           }
       }
       require(success,"Transfer to owner failed");
       emit returnRentedProperty(nftId,currentTenant,rent);
   }




   function checkUpkeep(bytes calldata checkdata) external view override returns (bool upkeepNeeded, bytes memory performData) {
       uint[] memory tokensToreturn = new uint[](activeTokensOnRent.length);
       uint count = 0;
       for(uint i=0;i<activeTokensOnRent.length;i++)
       {
           uint nftID = activeTokensOnRent[i];
           if(tenant[nftID]!=address(0) && block.timestamp>=returnTime[nftID])
           {
               tokensToreturn[count] = nftID;
               count++;
           }
           
       }

       uint [] memory propertyToReturn = new uint[](count);
       for(uint i=0;i<count;i++) propertyToReturn[i]=tokensToreturn[i];

       upkeepNeeded = count>0;
       performData=abi.encode(propertyToReturn);


   }


   function performUpkeep(bytes calldata performData) external override {
       (uint[] memory propertyToReturn) = abi.decode(performData,(uint[]));

       for(uint i=0;i<propertyToReturn.length;i++) returnRentedproperty(propertyToReturn[i]);

   }






}```  getting error while testing TypeError: Cannot read properties of undefined (reading 'parseEther'). Give me solution and also any further modification needed or not.                           Thank you in advance

2 Answers 2

2

ethers.utils.parseEther() is deprecated in newer versions (i.e., v6) of the Ethers library.

You need to use ethers.parseEther() instead for compatibility with the latest version.

1

Try

 const PRICE_FOR_RENT = ethers.parseEther("0.1");

https://stackoverflow.com/questions/77007626/const-amount-ethers-utils-parseether1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.