Smart Contracts

A Smart Contract is a program that runs in the EVM (Ethereum Virtual Machine). Functions within a Smart Contract deal with/process the data from a transaction that calls it. Smart Contracts have an address, and can send/transfer funds.

Solidity was a great starting point, since I'm already well-versed with Javascript. Here is an example of what a Smart Contract looks like in Solidity:

pragma solidity 0.8.26;
// SPDX-License-Identifier: GPL-3.0

// Our first contract is a faucet!
contract Faucet {

    // Give out ether to anyone who asks
    function withdraw(uint256 _withdrawAmount, address payable _to) public {

        // Limit withdrawal amount
        require(_withdrawAmount <= 1000000000000);

        // Send the amount to the address that requested it
        _to.transfer(_withdrawAmount);
    }

    // Function to receive Ether. msg.data must be empty
    receive() external payable {}

    // Fallback function is called when msg.data is not empty
    fallback() external payable {}
}

this code is from Ethereumbook

Dissecting:

State Variables & Integers

uint (is also uint256) means unsigned integer. It is used for values that should never be negative such as: balance, counters, etc.

uint8 means a maximum of 255 (0-255, 256 or 11111111)

Another new data type I learned was address, which is used for Ethereum wallet or smart contract addresses.

There may be cases of overflow or underflow when dealing with values in Smart Contracts, which is dangerous especially since you're dealing with funds. For versions below Solidity 0.8.0, you must import SafeMath

Data Locations
Storage Stores data permanently in the blockchain. Data in the storage must be mutable, thus this is where state variables (variables outside of a function) are stored. Reminds me of Hardrive
Memory Stores data needed only during function execution, temporary. Used for: Local Variables, arrays inside a function or arguments...Reminds me of RAM
CallData Read-only, immutable and temporary location where function arguments are stored. Kind of like memory but for array parameters, calldata is more approriate since it uses less gas compared to memory. It can only be used for function declaration parameters and not function logic

Examples from Alchemy

Use Case A (Storage):

contract ColorStorage {
    mapping(address => string) private favoriteColors;
    
    function setFavoriteColor(string calldata color) public {
        favoriteColors[msg.sender] = color;
    }
    
    function getFavoriteColor(address userAddress) public view returns (string memory) {
        return favoriteColors[userAddress];
    }
}

The favoriteColors is a state variable and is thus placed in Storage..it also noticeable that it can be mutated

Use Case B (Memory):

function sumArray(uint[] memory arr) public pure returns (uint) {
	uint sum = 0
	for(uint i = 0; i < arr.length; i++) {
		sum += array[i]; 
		//or if you want to use SafeMath
		// sum = sum.add(array[i])
	}
	
	return sum;
}
Function Modifiers: Public vs. Private vs. Internal vs. External
Types of functions
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.5.0;
/// @title A contract for demonstrating pure functions
/// @notice For now, this contract defining pure function to calculate product and sum of two numbers    
contract Test {

   function getResult(
   ) public pure returns(
     uint product, uint sum){
      uint num1 = 2; 
      uint num2 = 4;
      product = num1 * num2;
      sum = num1 + num2; 
   }
}
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.5.0;
/// @title A contract for demonstrating view functions
/// @author Jitendra Gangwar
/// @notice For now, this contract defining view function to calculate product and sum of two numbers    
contract Test {
    // Declaring state variables                              
    uint num1 = 2; 
    uint num2 = 4;

   function getResult(
   ) public view returns(
     uint product, uint sum){
      product = num1 * num2;
      sum = num1 + num2; 
   }
}
Why do I need to know all this?

Every Ethereum transaction requires payment of a fee, which is collected by the network to validate the transaction. This fee is called gas. You pay for the gas with ether.

Code Optimization is very important to reduce gas costs. There are many ways to do this. For instance:

More tips here

Some more useful built-in functions
Storing Data

Unlike regular code where you store data in a Database, Solidity usually stores them in Mappings. (looks like HashMaps)

mapping(address => uint256) public balances;

What the mapping above those is it stores the a value and pairs it with an address, which in this case, is the owner.

Sample code:

pragma solidity ^0.8.0;  
  
contract SimpleBank {  
// Define a mapping to store balances  
mapping(address => uint) public balances;  
  
// Function to deposit ether into the contract  
function deposit() public payable {  
balances[msg.sender] += msg.value;  
}  
  
// Function to withdraw ether from the contract  
function withdraw(uint amount) public {  
require(balances[msg.sender] >= amount, "Insufficient balance");  
balances[msg.sender] -= amount;  
payable(msg.sender).transfer(amount);  
}  
  
// Function to check the balance of the caller  
function getBalance() public view returns (uint) {  
return balances[msg.sender];  
}  
}

Resources

Resources