jackofcrypto

Posted on Jan 09, 2022Read on Mirror.xyz

Interacting with Smart Contracts

Learn about decision making, managing ETH, the require function, tracking trades, and enforcing terms of a smart contract.

By the end of this post, readers will be able to:

  • Define the payable function's role in smart contracts.
  • Develop the syntax in Solidity to withdraw and deposit ether.
  • Use conditional statements in Solidity in order to obtain the desired results in your smart contract.
  • Demonstrate how the require function works in Solidity smart contracts.
  • Develop a smart contract using the require function to enforce smart contract terms.

In the previous lesson, we defined the basic structure of a smart contract, and wrote a function as well as variables for storing data. In this lesson, we’ll create functions that add functionality to a smart contract.

Deposit/Withdraw ETH

In order for our functions to receive ether, they must be attached to a modifier called payable. payable is a reserved keyword in Solidity. Usually, there is a no name function that accepts ether that is to be sent to a contract. This is called a fallback function, which we’ll dive into a bit later.

function () payable {}

An exception is when you have more than one payable function that is used to perform different tasks, such as registering a deposit to your contract:

function deposit() payable {
  deposits[msg.sender] += msg.value;
}; 

Each time you deploy a smart contract, a public Ethereum address is assigned to it.

  • A smart contract can store and send ETH like a cryptocurrency wallet with its Ethereum account address.
  • It’s up to developers to create functions that manage this address.

In the contract below, anyone can add ETH via the contract address or the deposit function. Anyone can also send any amount of ETH to any address that we specify to the withdraw function, as long as we have enough in our balance.

pragma solidity ^0.5.0;

contract CustomerSavings {

function withdraw(uint amount, address payable recipient) public {
  return recipient.transfer(amount);
}

function deposit() public payable {}

function() external payable {}
}

The function at the end without a name is known as a fallback function. If we don't add the fallback function, and ETH gets sent to our contract address, the ETH will be returned. This forces other users to send ETH via the deposit function.

A fallback function is used in two scenarios:

  • (1) if the function identifier doesn't match any other function in the contract, or
  • (2) if the sending function doesn't supply any data, so we have to add the external keyword so that other contracts or transactions can call this contract. We also add the payable keyword so that the contract can collect any amount of ETH that gets sent to it via the contract address.

Conditional Statements

Below, you will gain practical experience with using conditional statements in Solidity. We’ll use basic logical operators and a control flow—an order of statements and functions—to build a smart contract that tracks trades in the Ethereum blockchain.

The code snippet below showcases using if/else statements and stacked conditionals:

pragma solidity ^0.5.0;

contract TradeController {
    uint previousPrice;
    string tradeType;

    function makeTrade(uint currentPrice, bool buyAnyway) public {
        if (currentPrice < previousPrice || buyAnyway) {
            tradeType = "Buy";
            previousPrice = currentPrice;
        }
        else if (currentPrice > previousPrice) {
                tradeType = "Sell";
                previousPrice = currentPrice;
        }
        else {
            tradeType = "Hold";
        }
    }
}

Require Function

An alternative to conditionals in Solidity is the require function. Use cases for the require function include:

  • Verifying that a recipient is someone you know after completing a withdrawal transaction.
  • Verifying that the sender smart contract has enough ETH to cover the requested amount.

The require function checks a condition just like an if statement does. But if the condition is false, it will return the unused gas and any ETH and roll back the entire transaction. Consider it a hard stopping point: you require a specific condition to be true to continue.

pragma solidity ^0.5.0;

contract BankAccount {
    address payable accountOwner = 0xc3879B456DAA348a16B6524CBC558d2CC984722c;

    function withdraw(uint amount, address payable recipient) public {
        require(recipient == accountOwner, "You don’t own this account!");
        return recipient.transfer(amount);
    }

    function deposit() public payable {}

    function() external payable {}
}

In the preceding code, we use the require function to check if the recipient is the account owner. If the conditional statement is false, the recipient isn’t the account owner. So, the code raises (returns) an exception that throws (displays) a message reading "You don't own this account!"

Until next time, here’s a twitter thread summary of this post:

https://twitter.com/jackofcrypto/status/1480208333034246147?s=20