0% found this document useful (0 votes)
8 views35 pages

UNIT 3

This document provides an introduction to Solidity programming, outlining its key features, structure of contracts, and various programming constructs. It covers topics such as data types, control structures, error handling, and the layout of a Solidity source file, emphasizing the importance of well-structured contracts for security and maintainability. Additionally, it explains input and output parameters, data locations, and examples of functions and control statements in Solidity.

Uploaded by

vishnuprya2915
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views35 pages

UNIT 3

This document provides an introduction to Solidity programming, outlining its key features, structure of contracts, and various programming constructs. It covers topics such as data types, control structures, error handling, and the layout of a Solidity source file, emphasizing the importance of well-structured contracts for security and maintainability. Additionally, it explains input and output parameters, data locations, and examples of functions and control statements in Solidity.

Uploaded by

vishnuprya2915
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 35

UNIT III

Introduction to Solidity Programming, Layout of a Solidity Source File, Structure of a Contract,


Types, Units and Globally Available Variables, Input Parameters and Output Parameters,
Control Structures, Function Calls, Creating Contracts via new, Order of Evaluation of
Expressions, Assignment, Scoping and Declarations, Error handling: Assert, Require, Revert and
Exceptions.

INTRODUCTION TO SOLIDITY PROGRAMMING:

 What is Solidity?
o Solidity is a contract-oriented programming language used to write smart
contracts that run on the Ethereum Virtual Machine (EVM).
o It is statically typed, and contracts are deployed on the Ethereum blockchain to
enable decentralized applications (dApps).
o Supports inheritance, libraries, and complex user-defined types.

Key features include:

1. Statically Typed: Solidity requires variable types to be defined explicitly.


2. Influenced by JavaScript, Python, and C++: It borrows syntax and concepts from these
languages.
3. Smart Contract Oriented: Designed specifically for writing decentralized applications.
4. Ethereum Virtual Machine (EVM) Compatible: Compiles into bytecode that runs on the
EVM.
5. Supports Inheritance and Libraries: Contracts can inherit properties and functions from
other contracts.
6. Secure Execution: Implements security measures like modifiers and access control.
7. Event Logging: Contracts can emit events that can be captured by external applications.
8. Supports Cryptographic Functions: Hashing and signature verification are built-in.

Solidity enables trustless transactions by executing contract logic autonomously, making it


essential for decentralized finance (DeFi), NFTs, and dApps.

LAYOUT OF A SOLIDITY SOURCE FILE (OR) STRUCTURE OF A SOLIDITY


CONTRACT:

A. Introduction

 A Solidity contract is a self-executing program that runs on the Ethereum blockchain.


 Smart contracts contain state variables, functions, events, and modifiers to define their
behavior.
 Well-structured contracts improve readability, security, and maintainability.
B. Basic Structure of a Solidity Contract

A Solidity contract typically follows this order:

1. Pragma Directive

 Specifies the Solidity compiler version.


 Ensures compatibility with the intended version range.
 Example:

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

2. Import Statements

 Used to include external contracts, libraries, or interfaces.


 Improves modularity and code reuse.
 Example:

solidity
import "@openzeppelin/contracts/access/Ownable.sol";
import "./MyLibrary.sol";

3. Contract Declaration

 Defines the contract name and inheritance (if applicable).


 Example:

solidity
contract MyContract is Ownable {
// Contract content
}

4. State Variables

 Store contract data on the blockchain.


 Visibility can be public, private, internal, or external.
 Example:

solidity
uint256 public totalSupply;
address public owner;
mapping(address => uint256) public balances;

5. Events

 Used to log transactions and important contract activities.


 Help external applications track changes efficiently.
 Example:

solidity
event Transfer(address indexed from, address indexed to, uint256 value);

6. Modifiers

 Define reusable conditions for function execution.


 Commonly used for access control.
 Example:

solidity
modifier onlyOwner() {
require(msg.sender == owner, "Not the owner");
_;
}

7. Constructor

 Special function that runs once at contract deployment.


 Used for initializing contract state.
 Example:

solidity
constructor() {
owner = msg.sender;
}

8. Functions

Types of Functions:
1. Public & External Functions

 Used to interact with the contract from outside.


 public: Accessible both internally and externally.
 external: Only accessible externally.
 Example:

solidity
function transfer(address to, uint256 amount) public returns (bool) {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
balances[to] += amount;
emit Transfer(msg.sender, to, amount);
return true;
}

2. Internal & Private Functions

 internal: Can be accessed within the contract and derived contracts.


 private: Can only be accessed within the contract.
 Example:

solidity
function _mint(address account, uint256 amount) internal {
balances[account] += amount;
totalSupply += amount;
}

3. View & Pure Functions

 View functions: Only read the state, do not modify it.


 Pure functions: Do not read or modify the state.
 Example:

solidity
function getBalance(address account) public view returns (uint256) {
return balances[account];
}

9. Fallback & Receive Functions

 Special functions that handle Ether transactions.


Receive Function

 Accepts plain Ether transfers.


 Example:

solidity
receive() external payable {
// Handle Ether payments
}

Fallback Function

 Handles unknown function calls.


 Example:

solidity
fallback() external payable {
// Handles non-matching function calls
}

10. Structs & Enums

 Used for defining complex data structures.


 Example:

solidity
struct User {
address account;
uint256 balance;
}

enum Status { Active, Inactive }

11. Mappings

 Efficient key-value store for on-chain data.


 Example:

solidity
.
mapping(address => uint256) public balanceOf;
12. Error Handling

 require(): Used for validation checks (e.g., input conditions).


 assert(): Used for internal consistency checks.
 revert(): Explicitly aborts execution.
 Custom Errors: Saves gas over require().
 Example:

solidity

error Unauthorized();

function restrictedFunction() public {


if (msg.sender != owner) revert Unauthorized();
}

TYPES, UNITS, AND GLOBALLY AVAILABLE VARIABLES:

1. Introduction

 Solidity is a statically typed language, meaning each variable must be explicitly declared
with a type.
 It supports value types (primitives) and reference types (complex structures).
 Solidity provides units for time and Ether measurements.
 Solidity also has global variables that provide blockchain-related data.

2. Data Types in Solidity

A. Value Types (Primitive Data Types)

These store data directly in memory.

Type Description Example

bool Stores true or false bool isActive = true;

uint Unsigned integer (0 or positive) uint256 count = 10;

int Signed integer (positive & negative) int256 balance = -50;

address Stores Ethereum addresses address owner = msg.sender;

bytes Stores raw byte data bytes32 hash = 0x1234...;


Example of Value Types

solidity
bool isActive = true;
uint256 totalSupply = 1000;
int256 temperature = -20;
address owner = msg.sender;
bytes32 hash = keccak256(abi.encodePacked("Hello"));

B. Reference Types

These store pointers to data, which exist in storage or memory.

Type Description Example

string Stores dynamic text string name = "Alice";

bytes Stores raw byte sequences bytes data = "0xabcdef";

array Fixed/dynamic-size list uint[] numbers = [1,2,3];

mapping Key-value storage mapping(address => uint256) balances;

struct Custom data structure struct Person { string name; uint age; }

Example of Reference Types

solidity

string public greeting = "Hello, World!";


uint[] public numbers = [1, 2, 3];
mapping(address => uint256) public balances;

struct Person {
string name;
uint age;
}
Person public user = Person("Alice", 25);
3. Units in Solidity

A. Ether Units

Solidity provides built-in units for Ether and Wei conversion.

Unit Equivalent in Wei

wei 1

gwei 1e9 wei

ether 1e18 wei

Example of Ether Units

solidity
uint oneEther = 1 ether; // 1 ether = 10^18 wei
uint oneGwei = 1 gwei; // 1 gwei = 10^9 wei
uint oneWei = 1 wei; // Smallest Ether unit

B. Time Units

Solidity provides time units for easier calculations.

Unit Equivalent

seconds Base unit

minutes 60 seconds

hours 60 minutes

days 24 hours

weeks 7 days

Example of Time Units

solidity
uint oneMinute = 1 minutes; // 60 seconds
uint oneHour = 1 hours; // 3600 seconds
uint oneDay = 1 days; // 86400 seconds
uint oneWeek = 1 weeks; // 604800 seconds

4. Globally Available Variables

Solidity provides global variables that offer useful information about the blockchain
environment.

Variable Description Example

msg.sender Address of the function caller address caller = msg.sender;

msg.value Amount of Ether sent with a transaction uint sent = msg.value;

msg.data Data payload of the transaction bytes data = msg.data;

block.timestamp Current block timestamp (UNIX time) uint time = block.timestamp;

block.number Current block number uint blockNum = block.number;

tx.origin Original sender of the transaction address initiator = tx.origin;

gasleft() Remaining gas in the transaction uint gasRemaining = gasleft();

Example of Using Global Variables

solidity
contract GlobalVars {
function getInfo() public view returns (address, uint, uint) {
return (msg.sender, block.timestamp, block.number);
}
}

INPUT PARAMETERS AND OUTPUT PARAMETERS:

1. Introduction

In Solidity, functions serve as the primary mechanism for interaction within smart contracts.
Functions can take input parameters (to receive data) and produce output parameters (to return
results).
 Input parameters: Allow users to supply values when calling a function.
 Output parameters: Return computed results after function execution.

Understanding how parameters work is crucial for writing efficient, secure, and gas-optimized
smart contracts.

2. Input Parameters in Solidity

Definition

 Input parameters allow external or internal callers to pass values into a function.
 They are defined within the function’s parentheses.
 Solidity supports primitive data types (e.g., uint, bool, address) and complex data types
(e.g., structs, arrays, mappings).

Characteristics of Input Parameters

✅ Function parameters are immutable within a function (cannot be modified).


✅ Solidity allows passing multiple parameters to a function.
✅ Reference types (e.g., string, arrays, structs) require explicit data location (memory, storage, or
calldata).

Syntax for Input Parameters

solidity
function functionName(type param1, type param2) public returns (returnType) {
// Function logic
}

Example of Input Parameters in Solidity

solidity
contract Calculator {
function add(uint256 a, uint256 b) public pure returns (uint256) {
return a + b;
}
}

 The function add(uint256 a, uint256 b) receives two uint256 numbers as input and returns
their sum.
 The pure modifier indicates that the function does not modify blockchain state.
3. Output Parameters in Solidity

Definition

 Output parameters define the return values of a function.


 Solidity allows multiple return values, enhancing flexibility.

Characteristics of Output Parameters

✅ Functions may return one or more values.


✅ Output parameters are defined after the returns keyword.
✅ Complex types (string, structs, arrays) must have explicit data locations (memory).

Syntax for Output Parameters

solidity
function functionName(type param1, type param2) public returns (returnType) {
return value;
}

Example of Output Parameters

solidity
contract Greeter {
function greet() public pure returns (string memory) {
return "Hello, Solidity!";
}
}

 The function greet() returns a string stored in memory.

4. Returning Multiple Output Parameters

Definition

Solidity allows a function to return more than one value, making it more efficient for batch
processing of data.

Example: Multiple Return Values

solidity
contract UserInfo {
function getUserData() public pure returns (string memory, uint256) {
return ("Alice", 25);
}
}

 This function returns two values:


o A string representing a name.
o A uint256 representing an age.

Named Return Variables

Instead of explicitly using return, Solidity allows named return variables:

solidity
contract MathOperations {
function calculate(uint256 a, uint256 b) public pure returns (uint256 sum, uint256 product) {
sum = a + b;
product = a * b;
}
}

 The function automatically returns sum and product without explicitly using return.

Accessing Multiple Return Values

A calling function can destructure return values:

solidity
contract Test {
function getResults() public pure returns (uint256, uint256) {
return (5, 10);
}

function useResults() public pure returns (uint256 sum, uint256 product) {


(sum, product) = getResults();
}
}

 The useResults() function captures multiple return values from getResults().

5. Data Location for Input and Output Parameters


Why Data Location Matters?

 Solidity requires explicit memory management for reference types (string, arrays,
structs).
 The three data locations in Solidity are:

Data
Description Usage
Location

Temporary data storage (deleted after Used for function parameters and return
memory
execution). values.

storage Permanent storage on the blockchain. Used for contract state variables.

Used for external function calls to save


calldata Read-only, external function input.
gas.

Example: Using Data Locations for Parameters

solidity
contract DataStorage {
string public storedData;

// Uses `memory` for temporary storage


function updateData(string memory newData) public {
storedData = newData;
}

// Uses `calldata` for gas efficiency


function readData(string calldata inputData) external pure returns (string calldata) {
return inputData;
}
}

✅ memory is used for modifying temporary data.


✅ calldata is used for external immutable inputs to save gas.
CONTROL STRUCTURES IN SOLIDITY:

1. Introduction

Control structures are essential programming constructs that determine the flow of execution in
Solidity smart contracts. Solidity supports traditional control structures similar to other languages
like C++, Java, and Python. These include:

1. Conditional Statements (if, if-else, else-if)


2. Looping Constructs (for, while, do-while)

Understanding these structures is crucial for writing secure, efficient, and gas-optimized smart
contracts.

1. Conditional Statements

Conditional statements control the execution of code based on Boolean expressions. Solidity
provides:

 if statement
 if-else statement
 else-if ladder

1.1 if Statement

 Executes a block of code only if the condition is true.


 Syntax:

solidity
if (condition) {
// Code to execute if condition is true
}

 Example:

solidity
contract ConditionalExample {
function checkNumber(uint256 num) public pure returns (string memory) {
if (num > 0) {
return "Positive Number";
}
return "Zero or Negative";
}
}
1.2 if-else Statement

 Adds an alternative block that executes when the condition is false.


 Syntax:

solidity
if (condition) {
// Executes if condition is true
} else {
// Executes if condition is false
}

 Example:

solidity
contract CheckEvenOdd {
function isEven(uint256 num) public pure returns (string memory) {
if (num % 2 == 0) {
return "Even Number";
} else {
return "Odd Number";
}
}
}

1.3 else-if Ladder

 Evaluates multiple conditions in sequence.


 Syntax:

solidity
if (condition1) {
// Executes if condition1 is true
} else if (condition2) {
// Executes if condition2 is true
} else {
// Executes if none of the above conditions are true
}
 Example:

solidity
contract CheckGrade {
function getGrade(uint256 marks) public pure returns (string memory) {
if (marks >= 90) {
return "A+";
} else if (marks >= 80) {
return "A";
} else if (marks >= 70) {
return "B";
} else {
return "Fail";
}
}
}

2. Looping Constructs

Loops help in executing repetitive tasks without writing redundant code. Solidity supports:

1. for loop
2. while loop
3. do-while loop

2.1 for Loop

 Best suited for scenarios where the number of iterations is known.


 Syntax:

solidity
.
for (initialization; condition; increment/decrement) {
// Code to execute
}

 Example:

solidity
contract LoopExample {
function sumFirstN(uint256 n) public pure returns (uint256 sum) {
for (uint256 i = 1; i <= n; i++) {
sum += i;
}
}
}

✅ Gas Consideration: Avoid infinite loops, as they consume all gas and fail execution.

2.2 while Loop

 Used when the number of iterations is not known in advance.


 Syntax:

solidity
.
while (condition) {
// Code to execute
}

 Example:

solidity
contract WhileLoopExample {
function sumUsingWhile(uint256 n) public pure returns (uint256 sum) {
uint256 i = 1;
while (i <= n) {
sum += i;
i++;
}
}
}

✅ Gas Optimization: Ensure loops terminate within a limited number of iterations to prevent
excessive gas consumption.

2.3 do-while Loop

 Executes the block at least once before checking the condition.


 Syntax:

solidity
do {
// Code to execute
} while (condition);
 Example:

solidity
contract DoWhileExample {
function countDown(uint256 n) public pure returns (uint256 count) {
do {
count++;
n--;
} while (n > 0);
}
}

✅ Use Case: When execution must happen at least once, regardless of the condition.

3. Break Statement

� Definition:
 The break statement terminates the loop immediately and exits, regardless of whether the loop
condition is still true.
 Control is transferred to the first statement after the loop.

� Syntax:

solidity
CopyEdit
for (initialization; condition; increment/decrement) {
if (condition_to_break) {
break; // Exit the loop immediately
}
// Code to execute if condition_to_break is false
}

� Example:

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract BreakExample {
uint[] public data;

function stopAt(uint _n) public {


for (uint i = 0; i < 10; i++) {
if (i == _n) {
break; // Exit the loop if i equals _n
}
data.push(i); // Add i to the array if condition is not met
}
}
}

� Explanation:
 The loop iterates from 0 to 9.
 If i == _n, the break statement stops the loop.
 Any value of i before _n is added to the data array.
 For example, if _n = 5, the data array will be [0, 1, 2, 3, 4] and the loop stops.

4. Continue Statement

� Definition:
 The continue statement skips the current iteration and proceeds to the next iteration of the loop.
 The remaining code inside the loop for that iteration is skipped.

� Syntax:

solidity
for (initialization; condition; increment/decrement) {
if (condition_to_skip) {
continue; // Skip the current iteration and proceed to the next one
}
// Code to execute if condition_to_skip is false
}

� Example:

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ContinueExample {
uint[] public data;

function skipEvenNumbers(uint _n) public {


for (uint i = 0; i < _n; i++) {
if (i % 2 == 0) {
continue; // Skip even numbers
}
data.push(i); // Add only odd numbers to the array
}
}
}

� Explanation:
 The loop iterates from 0 to _n - 1.
 continue skips the current iteration if i is even (i % 2 == 0).
 Only odd numbers are pushed to the data array.
 For _n = 10, the data array will contain [1, 3, 5, 7, 9].

Feature break continue

Purpose Terminates the loop Skips the current iteration

Effect Exits the loop immediately Proceeds to the next iteration

Scope Stops executing all loop iterations Skips part of the loop for that iteration

Usage When you want to exit a loop early When you want to skip some iterations

FUNCTION CALLS AND CREATING CONTRACTS VIA NEW IN SOLIDITY:

1. Introduction

Solidity allows smart contracts to interact with each other through function calls and enables the
creation of new contracts using the new keyword. This is crucial for building modular, reusable,
and upgradeable smart contract architectures.

2. Function Calls in Solidity

Functions in Solidity can be internal, external, public, or private, and can be invoked differently
based on their visibility and caller type.

2.1 Types of Function Calls

Function Call Type Description

Internal Call Calls within the same contract or derived contracts.

External Call Calls to functions of another contract instance.

Low-Level Call Uses call(), delegatecall(), staticcall() (less secure).


2.2 Internal Function Calls

✅ Can only be called within the same contract or from derived contracts (via inheritance).
✅ Cheaper gas cost because they do not require external transactions.

Example:

solidity
contract Parent {
function internalFunction() internal pure returns (string memory) {
return "Internal Function Called!";
}
}

contract Child is Parent {


function callInternalFunction() public pure returns (string memory) {
return internalFunction(); // Calling inherited internal function
}
}

2.3 External Function Calls

✅ Used when calling functions from another contract.


✅ Uses an instance of the contract.
✅ Requires public or external visibility.

Example: Calling another contract's function

solidity
contract ContractA {
function getValue() public pure returns (string memory) {
return "Hello from ContractA";
}
}

contract ContractB {
function callContractA(address contractAAddress) public view returns (string memory) {
ContractA contractA = ContractA(contractAAddress);
return contractA.getValue();
}
}

 ContractB calls getValue() from ContractA using its deployed address.


2.4 Low-Level Calls (call, delegatecall, staticcall)

Solidity provides low-level function calls, but they should be used with caution due to security
risks.

Low-Level Call Use Case

call() Calls another contract’s function but with less type safety.

delegatecall() Executes another contract’s function in the caller’s context.

staticcall() Calls a function without modifying the state.

Example: Using call()

solidity
contract ExternalContract {
function externalFunction() public pure returns (string memory) {
return "Hello from External Contract!";
}
}

contract Caller {
function callExternalFunction(address externalContract) public returns (bool, bytes memory) {
(bool success, bytes memory data) =
externalContract.call(abi.encodeWithSignature("externalFunction()"));
return (success, data);
}
}

✅ Pros: Works even when function signatures are unknown.


✅✅ Cons: Less secure, prone to reentrancy attacks.

CREATING CONTRACTS VIA NEW

1.1 Introduction

In Solidity, contracts can dynamically create new instances of other contracts using the new
keyword. This is useful for factory patterns, where one contract deploys multiple instances of
another contract.
1.2 Syntax for Creating Contracts

solidity
ContractName contractInstance = new ContractName(constructorArguments);

1.3 Example: Creating a Contract Inside Another Contract

solidity
contract Child {
string public message;

constructor(string memory _message) {


message = _message;
}
}

contract Factory {
Child public deployedChild;

function createChildContract(string memory _message) public {


deployedChild = new Child(_message);
}
}

✅ The Factory contract dynamically creates a Child contract using new.

1.4 Factory Contracts (Deploying Multiple Contracts)

A factory contract can create multiple instances of a contract and manage them efficiently.

Example: Factory Contract for Multiple Deployments

solidity
.
contract Product {
string public name;

constructor(string memory _name) {


name = _name;
}
}
contract ProductFactory {
Product[] public products;

function createProduct(string memory _name) public {


Product newProduct = new Product(_name);
products.push(newProduct);
}

function getProduct(uint index) public view returns (address) {


return address(products[index]);
}
}

✅ The ProductFactory contract creates and tracks multiple Product contract instances.

ORDER OF EVALUATION OF EXPRESSIONS AND ASSIGNMENT IN SOLIDITY:

1. Introduction

In Solidity, expressions are evaluated based on operator precedence and associativity.


Understanding the order of evaluation helps prevent unexpected behaviors, especially in
mathematical computations, logical operations, and state changes.

2. Operator Precedence and Associativity

Solidity follows a hierarchical order when evaluating expressions. Operators with higher
precedence are evaluated first, followed by those with lower precedence.

2.1 Operator Precedence Table

Operator Description Associativity

() Parentheses (Grouping) Left to Right

!~ Logical NOT, Bitwise NOT Right to Left

** Exponentiation Right to Left

*/% Multiplication, Division, Modulo Left to Right

+- Addition, Subtraction Left to Right


Operator Description Associativity

<< >> Bitwise Shift Left, Right Left to Right

< <= > >= Comparison Operators Left to Right

== != Equality Operators Left to Right

& Bitwise AND Left to Right

^ Bitwise XOR Left to Right

` ` Bitwise OR

&& Logical AND Left to Right

` `

?: Ternary Operator Right to Left

= += -= *= /= %= Assignment Operators Right to Left

2.2 Example: Operator Precedence

Consider the following Solidity expression:

solidity
uint result = 10 + 5 * 2;

✅ Evaluation Order:

1. 5 * 2 is evaluated first (multiplication has higher precedence).


2. 10 + 10 is computed next.
3. Final result = 20.

✅ Fixing Order with Parentheses:

solidity
.
uint result = (10 + 5) * 2; // Evaluates to 30

✅ Parentheses force higher precedence, overriding the default evaluation order.


2.3 Associativity Rules

 Left to Right Associativity: Operators like +, -, *, / evaluate expressions from left to


right.
 Right to Left Associativity: Assignment (=, +=, -=) and exponentiation (**) evaluate
from right to left.

Example:

solidity
uint a = 2 ** 3 ** 2; // 2 ** (3 ** 2) = 2 ** 9 = 512

✅ Since ** has right-to-left associativity, 3 ** 2 is computed first, then 2 ** 9.

3. Order of Evaluation in Expressions

Solidity does not guarantee strict left-to-right execution of expressions involving function calls
or storage reads/writes.

3.1 Function Call Evaluation Order

solidity
.
contract Test {
function first() public pure returns (uint) {
return 1;
}

function second() public pure returns (uint) {


return 2;
}

function evaluate() public pure returns (uint) {


return first() + second(); // Execution order is NOT guaranteed
}
}

✅ The function first() or second() may execute in any order, leading to non-deterministic
behavior in certain cases.

3.2 Short-Circuit Evaluation in Logical Expressions

 Solidity short-circuits logical expressions:


o && (AND) stops execution if the first operand is false.
o || (OR) stops execution if the first operand is true.

Example:

solidity
contract ShortCircuit {
function check(uint x) public pure returns (string memory) {
if (x > 10 && expensiveFunction()) {
return "Condition met";
}
return "Condition not met";
}

function expensiveFunction() internal pure returns (bool) {


// Heavy computation (not executed if x <= 10)
return true;
}
}

✅ Optimization Benefit: If x <= 10, expensiveFunction() is never called, saving gas.

4. Assignment Operations in Solidity

Assignment operators store values into variables. Solidity supports:

 Simple assignment (=)


 Compound assignment (+=, -=, *=, /=, %=)

4.1 Simple Assignment (=)

Stores the right-hand value into the left-hand variable.

solidity
.
uint a = 10; // a is assigned the value 10

4.2 Compound Assignment (+=, -=, *=, /=)

Combines arithmetic operations with assignment.


Example:

solidity
uint a = 5;
a += 3; // Equivalent to a = a + 3; (a = 8)
a *= 2; // Equivalent to a = a * 2; (a = 16)

✅ Gas Optimization: Compound assignments use less gas than separate operations.

4.3 Assignment Evaluation Order

Assignment operators have right-to-left associativity, meaning they evaluate rightmost first.

Example:

solidity
uint a;
uint b;
uint c;
a = b = c = 10; // c is assigned first, then b, then a

✅ Final values: a = 10, b = 10, c = 10.

SCOPING AND DECLARATIONS IN SOLIDITY:

1. Introduction

Scoping and declarations in Solidity define how variables and functions are accessed within a
contract. Understanding scope is essential for security, gas efficiency, and avoiding unintended
state modifications.

2. Variable Scope in Solidity

Solidity has three main variable scopes:

1. State Variables (stored on-chain, persistent)


2. Local Variables (temporary, exist only during function execution)
3. Global Variables (provided by Ethereum, e.g., msg.sender)

2.1 State Variables


 Declared outside functions but inside a contract.
 Stored permanently in the blockchain (higher gas cost).
 Can have public, private, internal, or external visibility.

Example:

solidity
contract Example {
uint public stateVar = 100; // State variable (stored on-chain)
}

2.2 Local Variables

 Declared inside functions.


 Exist only during execution and are destroyed afterward.
 Cheaper because they are not stored on the blockchain.

Example:

solidity
contract Example {
function addNumbers() public pure returns (uint) {
uint localVar = 10; // Local variable (temporary)
return localVar + 5;
}
}

✅ Local variables are more gas-efficient than state variables.

2.3 Global Variables

 Built-in Ethereum variables that provide network information.


 Common examples:
o msg.sender → Address of the function caller.
o block.timestamp → Current block timestamp.
o tx.origin → Original sender of the transaction.

Example:

solidity
contract Example {
function getSender() public view returns (address) {
return msg.sender; // Returns the caller's address
}
}

3. Function and Variable Visibility

Solidity provides different visibility specifiers:

Visibility Who Can Access? Use Case

public Any contract or account For external calls & visibility

private Only the same contract Internal logic, not inherited

internal Same contract & derived contracts Useful for inheritance

external Only other contracts/accounts Optimized for external calls

3.1 Example: Visibility Modifiers

solidity
contract VisibilityExample {
uint public publicVar = 10; // Accessible everywhere
uint private privateVar = 20; // Only inside this contract
uint internal internalVar = 30; // Accessible in derived contracts

function getPrivateVar() private view returns (uint) {


return privateVar; // Can only be called inside this contract
}

function getInternalVar() internal view returns (uint) {


return internalVar; // Can be inherited
}

function getPublicVar() public view returns (uint) {


return publicVar; // Can be called from outside
}
}

✅ Best Practice:

 Use internal instead of public or private for functions that should be accessible in derived
contracts.
 Avoid public for sensitive data.

4. Block Scoping and Variable Shadowing

4.1 Block Scoping

 Solidity follows block-level scoping, meaning variables declared inside {} are not
accessible outside.

Example:

solidity
contract BlockScope {
function example() public pure returns (uint) {
if (true) {
uint x = 10; // x exists only inside this block
}
// return x; // ✅ Compilation error (x is out of scope)
return 0;
}
}

4.2 Variable Shadowing

 Shadowing occurs when a local variable has the same name as a state variable.
 Solidity allows shadowing inside functions but disallows it in derived contracts.

Example: Shadowing Inside a Function

solidity
contract ShadowingExample {
uint x = 50; // State variable

function shadowExample() public view returns (uint) {


uint x = 10; // Shadows the state variable
return x; // Returns 10 (local variable)
}

function getStateX() public view returns (uint) {


return x; // Returns 50 (state variable)
}
}
✅ Best Practice: Avoid shadowing to prevent confusion.

4.3 Shadowing in Inheritance (Disallowed in Solidity 0.8+)

 Solidity disallows state variable shadowing in derived contracts.

Example (Throws Error in Solidity 0.8+):

solidity
contract Parent {
uint public value = 100;
}

contract Child is Parent {


uint public value = 200; // ✅ Compilation Error (Shadowing Disallowed)
}

ERROR HANDLING IN SOLIDITY: ASSERT, REQUIRE, REVERT, AND


EXCEPTIONS:

1.1. Introduction

Error handling in Solidity is crucial for ensuring contract security, preventing invalid operations,
and saving gas costs. Solidity provides three primary mechanisms for error handling:

 assert() → Used for internal consistency checks.


 require() → Used for validating conditions before execution proceeds.
 revert() → Used for manual error handling and more complex conditions.

1.2. Exceptions in Solidity

Solidity uses a state-reverting exception mechanism, meaning:

 When an error occurs, the entire transaction is reverted.


 Gas used before the error is lost, except when using require() in an external call.
 State changes are not applied if an exception occurs.

1.3. require() – Input Validation and Conditions

✅ Best used for:

 Validating input parameters.


 Ensuring proper conditions before execution.
 Checking external contract calls.
Example: Using require() for Input Validation

solidity
contract RequireExample {
function setAge(uint _age) public pure returns (string memory) {
require(_age >= 18, "Age must be 18 or older");
return "You are eligible";
}
}

✅ If _age < 18, the transaction reverts with "Age must be 18 or older".

Example: Checking ETH Transfers

solidity
contract Payment {
function deposit() public payable {
require(msg.value > 0, "Deposit amount must be greater than zero");
}
}

✅ Ensures only positive ETH values are sent.

1.4. assert() – Internal Consistency Checks

✅ Best used for:

 Checking invariants (conditions that should never fail).


 Ensuring critical bugs are caught.
 Should NOT be used for user input validation.

✅ Gas Consideration:

 If assert() fails, it consumes all remaining gas (unlike require()).

Example: Using assert() for Invariants

solidity
contract AssertExample {
uint public totalSupply = 100;

function decrementSupply(uint _amount) public {


totalSupply -= _amount;
assert(totalSupply >= 0); // Ensures totalSupply never becomes negative
}
}

✅ If totalSupply ever becomes negative, the contract fails entirely.

✅ Do not use assert() for conditions that users can trigger!

1.5. revert() – Manual Error Handling

✅ Best used for:

 Handling complex conditions that require custom logic.


 Providing detailed error messages.
 Early exits from functions when conditions are not met.

Example: Using revert() for Manual Error Handling

solidity
contract RevertExample {
function withdraw(uint _amount, uint balance) public pure returns (string memory) {
if (_amount > balance) {
revert("Insufficient balance");
}
return "Withdrawal successful";
}
}

✅ revert() is useful for explicitly throwing errors based on conditions.

1.6. require() vs. assert() vs. revert() – Key Differences


Feature require() assert() revert()
Input validation Internal
& condition consistency Manual error
Purpose checks checks handling
Gas Yes (unused No (all gas Yes (unused gas
Refund gas refunded) consumed) refunded)
Checking user Checking Handling errors
input, external invariants and with detailed
Use Case calls internal logic messages
require(msg.val if (x < y)
Typical ue > 0, "Must assert(totalSup revert("Invalid
Example send ETH"); ply >= 0); condition");

You might also like