A Developer Guide to Ethereum smart contract creation with Remix IDE

Posted By : Krishna

May 13, 2022

Brief Into of Blockchain Smart Contract Through Remix IDE.

What is Smart Contract:

"Smart contract" is simply a program that runs on the Ethereum blockchain. It is a collection of code (its functions) and data (its state) located at a specific address on the Ethereum blockchain. 
 A smart contract is a type of Ethereum account. This means they have a balance and can send transactions over the network. However, they are not controlled by the user, but deployed on the network and run on a schedule. The user account can then interact with the smart contract by sending transactions that perform a function defined on the smart contract. Smart contracts can define rules, just like a regular contract, and execute them automatically through code. Smart contracts cannot be deleted by default and interactions with them are immutable.

 
 Let's familiar with Remix IDE:
 
Remix IDE is an open-source desktop and web application. It promotes rapid development cycles and has a rich set of plugins with an intuitive GUI. Remix is "‹"‹used throughout the contract development journey and serves as a playground to learn and teach Ethereum. The Remix IDE is part of the Remix project, which is a platform for development tools that use the plugin architecture. It includes subprojects like Remix Plugin Engine, Remix Libs, and of course RemixIDE.  Remix IDE is a powerful open-source tool that helps you write Solidity contracts directly from the browser.  It is written in JavaScript and supports both uses in the browser, but runs locally and in the desktop version.  Remix IDE has modules for testing, debugging, and deploying smart contracts, and more.
 

Let's get acquainted with the basic features of the IDE. In the sidebar you have 3 tabs,  now: 

  • File Explorer is where we will write our smart contract and its test file. It is already pre-populated with some files. Don't hesitate to browse them! 
  • Solidity compiler. This is where we will compile our smart contract when it is ready.  Deploy and execute transactions, as you have guessed, where we will send our smart contract to the Blockchain.

Create your first smart contract:

  1.  Open Remix IDE
  2. Click on Sure and then Done.
  3. Under default_workshop, click on create a new file.
  4. Rename it as Resort.sol.

Contract Code:

  • You need to provide the solidity version in the smart contract:
pragma solidity ^0.5.16;
  • Now create the main contract named Resort:
contract Resort{
    ...
}
  • Now inside the Resort contract {...} follow the steps below. Create variables where the smart contract will store the payable address (42-character hex string with prefix: "0x") of the owner and tenant.
 address payable tenant;
 address payable owner;
  • Create public variables where the smart contract will store integer values. For this, there is a data type called uint (256-bit unsigned integer)
    uint public no_of_rooms = 0;
    uint public no_of_agreement = 0;
    uint public no_of_rent = 0;   
 
  • Now let's create a structure to store the details of each room in the hotel like the room number, room name, room address,  total agreements, monthly rent, one-time deposit, the time of signing the final agreement, the vacancy, and the address of the owner. and the current address of the tenant.
    struct Room{
        uint roomid;
        uint agreementid;
        string roomname;
        string roomaddress;
        uint rent_per_month;
        uint securityDeposit;
        uint timestamp;
        bool vacant;
        address payable owner;
        address payable currentTenant;
      }
  • map the previous structure with a uint (named: roomid).
        mapping(uint => Room) public Room_by_No;
  • As above, create a struct for each lease and map it to a uint (named: Agreementid). This will store details like: room number, agreement number, room name, room address, monthly rent, one-time deposit, lock time, time of signing the agreement, the address of the owner, and the address of the tenant.
    struct RoomAgreement{
        uint roomid;
        uint agreementid;
        string Roomname;
        string RoomAddresss;
        uint rent_per_month;
        uint securityDeposit;
        uint lockInPeriod;
        uint timestamp;
        address payable tenantAddress;
        address payable ownerAddress;
    }
    mapping(uint => RoomAgreement) public RoomAgreement_by_No;

    
  • Now create a structure for each rent payment and map it with a uint. This will store details like: rent number, room number, contract number, room name, room address, monthly rent, rental payment time, owner's address property, and address of the tenant.
    struct Rent{
        uint rentno;
        uint roomid;
        uint agreementid;
        string Roomname;
        string RoomAddresss;
        uint rent_per_month;
        uint timestamp;
        address payable tenantAddress;
        address payable ownerAddress;
    }
   mapping(uint => Rent) public Rent_by_No;
  • Creating modifiers will help you check for certain things before running a function. 

 This requires (...); which means if the given condition is not met, the function will not run and the given string will appear as an error code. 

  •  The following will check if the sender of the message is the owner.
   modifier onlyOwner(uint _index) {
        require(msg.sender == Room_by_No[_index].owner, "Only owner can access this");
        _;
    }
  • The following will check if the message sender is anyone except the owner.
    modifier notOwner(uint _index) {
        require(msg.sender != Room_by_No[_index].owner, "Only Tenant can access this");
        _;
        }
  • The following will check if the room is available or not.
    modifier OnlyWhileVacant(uint _index){
        require(Room_by_No[_index].vacant == true, "Room is currently Occupied.");
        _;
    }
  • The following will check if the tenant has enough Ether in their wallet to pay the rent.
    modifier enoughRent(uint _index) {
        require(msg.value >= uint(Room_by_No[_index].rent_per_month), "Not enough Ether in your wallet");
        _;
    }
  • The following will check if the tenant has enough Ether in their wallet to pay the one-time security deposit and pay one month's rent in advance.
    modifier enoughAgreementfee(uint _index) {
        require(msg.value >= uint(uint(Room_by_No[_index].rent_per_month) + uint(Room_by_No[_index].securityDeposit)), "Not enough Ether in your wallet");
        _;
    }
  • The following will check if the tenant's address is the same as the one who signed the previous tenancy agreement.
    modifier sameTenant(uint _index) {
        require(msg.sender == Room_by_No[_index].currentTenant, "No previous agreement found with you & owner");
        _;
    }
  • The following section checks to see if there is still time for the deal to close.
    modifier AgreementTimesLeft(uint _index) {
        uint _AgreementNo = Room_by_No[_index].agreementid;
        uint time = RoomAgreement_by_No[_AgreementNo].timestamp + RoomAgreement_by_No[_AgreementNo].lockInPeriod;
        require(now < time, "Agreement already Ended");
        _;
    }
  • The following will check if 365 days have passed since the last agreement was created.
    modifier AgreementTimesUp(uint _index) {
        uint _AgreementNo = Room_by_No[_index].agreementid;
        uint time = RoomAgreement_by_No[_AgreementNo].timestamp + RoomAgreement_by_No[_AgreementNo].lockInPeriod;
        require(now > time, "Time is left for contract to end");
        _;
    }
  • The following will check if 30 days have passed since the last rental payment.
    modifier RentTimesUp(uint _index) {
        uint time = Room_by_No[_index].timestamp + 30 days;
        require(now >= time, "Time left to pay Rent");
        _;
    }

 

  • Now let's create some functions that will be used to add rooms.
    function addRoom(string memory _roomname, string memory _roomaddress, uint _rentcost, uint  _securitydeposit) public {
        require(msg.sender != address(0));
        no_of_rooms ++;
        bool _vacancy = true;
        Room_by_No[no_of_rooms] = Room(no_of_rooms,0,_roomname,_roomaddress, _rentcost,_securitydeposit,0,_vacancy, msg.sender, address(0)); 
    }
  • Now let's create a function to sign a rental contract between owner and tenant. 

 Before creating the signingOfAgreement function, remember the following: 

  1.   The function will only run if the user is a Tenant, which means that the user's address and the owner's address do not match. 
  2. The function will only run if the user has enough ether ('stable ether') in their Ethereum wallet. (Enough ether means = one-time deposit + first month's rent) 

 Use these modifiers here, for: 

  1.  The signingOfAgreement function will only run if said room is empty and the tenant has enough ether in their wallet.  
     function signAgreement(uint _index) public payable notOwner(_index) enoughAgreementfee(_index) OnlyWhileVacant(_index) {
        require(msg.sender != address(0));
        address payable _owner = Room_by_No[_index].owner;
        uint totalfee = Room_by_No[_index].rent_per_month + Room_by_No[_index].securityDeposit;
        _owner.transfer(totalfee);
        no_of_agreement++;
        Room_by_No[_index].currentTenant = msg.sender;
        Room_by_No[_index].vacant = false;
        Room_by_No[_index].timestamp = block.timestamp;
        Room_by_No[_index].agreementid = no_of_agreement;
        RoomAgreement_by_No[no_of_agreement]=RoomAgreement(_index,no_of_agreement,Room_by_No[_index].roomname,Room_by_No[_index].roomaddress,Room_by_No[_index].rent_per_month,Room_by_No[_index].securityDeposit,365 days,block.timestamp,msg.sender,_owner);
        no_of_rent++;
        Rent_by_No[no_of_rent] = Rent(no_of_rent,_index,no_of_agreement,Room_by_No[_index].roomname,Room_by_No[_index].roomaddress,Room_by_No[_index].rent_per_month,now,msg.sender,_landlord);
    }
  • Now create a function that the tenant will use to pay the owner's monthly rent. 

Before creating the payRent function, remember the following: 

  1. The function will run only if the user's address and the previous tenant's address are the same, which means the user cannot pay the rent only if he signed the agreement with the owner the last time in 365 days. 
  2. This function will only run if the tenant has paid their previous rent more than a month ago. 
  3. The function will only run if the user has enough ether ('stable ether') in their Ethereum wallet. (enough ether = enough  rent).
       function payRent(uint _index) public payable sameTenant(_index) RentTimesUp(_index) enoughRent(_index){
        require(msg.sender != address(0));
        address payable _owner = Room_by_No[_index].owner;
        uint _rent = Room_by_No[_index].rent_per_month;
        _owner.transfer(_rent);
        Room_by_No[_index].currentTenant = msg.sender;
        Room_by_No[_index].vacant = false;
        no_of_rent++;
        Rent_by_No[no_of_rent] = Rent(no_of_rent,_index,Room_by_No[_index].agreementid,Room_by_No[_index].roomname,Room_by_No[_index].roomaddress,_rent,now,msg.sender,Room_by_No[_index].landlord);
    }
  • Let's create a function that the owner will use to mark the transaction as complete. 

 Before creating agreementCompleted function, remember the following: 

  1. The function will only run if the user address and owner address are the same. 
  2. The function will only be performed if the tenant signed this agreement more than a year ago.
 function agreementCompleted(uint _index) public payable onlyOwner(_index) AgreementTimesUp(_index){
    require(msg.sender != address(0));
    require(Room_by_No[_index].vacant == false, "Room is currently Occupied.");
    Room_by_No[_index].vacant = true;
    address payable _Tenant = Room_by_No[_index].currentTenant;
    uint _securitydeposit = Room_by_No[_index].securityDeposit;
    _Tenant.transfer(_securitydeposit);
}
  • Let's create aagreementCompleted a function that the owner will use to mark the transaction as complete. 

 Before creating a function, remember the following: 

  1.  The function will only run if the user address and owner address are the same. 
  2.  The function will only be performed if the tenant signed this agreement more than a year ago.
 function agreementTerminated(uint _index) public onlyOwner(_index) AgreementTimesLeft(_index){
        require(msg.sender != address(0));
        Room_by_No[_index].vacant = true;
    }

Compile the Smart Contract:

Now click on  Solidity Compile option on the left sidebar. 

  1.  Select compiler version 0.5.16+ 
  2. Then click  Compile Resort.sol 

 
Deploy the Smart Contract:

  1. Click on the Deploy & Run Transactions option in the left sidebar.
  2. Select Environment > JavaScript VM (London)
  3. Now click on Deploy

Benefits of smart contracts:
 
 Now you may be wondering, "what is the benefit of smart contracts when there are many centralized methods?" 
 Let me explain some advantages of smart contracts over centralized systems: 
 Here, data cannot be altered or tampered with. Therefore, it is almost impossible for malicious actors to manipulate the data. 
 It is completely decentralized. 
 Unlike any centralized payment wallet, you don't have to pay a percentage of commission to the middleman to complete the transaction.

Leave a

Comment

Name is required

Invalid Name

Comment is required

Recaptcha is required.

blog-detail

November 23, 2024 at 01:16 am

Your comment is awaiting moderation.

By using this site, you allow our use of cookies. For more information on the cookies we use and how to delete or block them, please read our cookie notice.

Chat with Us
Telegram Button
Youtube Button

Contact Us

Oodles | Blockchain Development Company

Name is required

Please enter a valid Name

Please enter a valid Phone Number

Please remove URL from text