Writing Solidity Functions

Back

Loading concept...

πŸ—οΈ Writing Solidity Functions

Your Blueprint for Building Smart Contracts


The Big Picture: Functions are Like Doors

Imagine a smart contract as a magical vending machine. 🎰

  • The machine has different buttons (functions) you can press
  • Some buttons anyone can press (public)
  • Some buttons only the owner has a key for (private)
  • Some buttons need you to put in coins first (payable)
  • And some buttons just show you information without changing anything (view)

That’s exactly how Solidity functions work!


🎯 What is a Solidity Function?

A function is a set of instructions that does something when you call it.

function sayHello() public pure
    returns (string memory) {
    return "Hello, World!";
}

Think of it like a recipe:

  • Name: sayHello (what we call it)
  • Who can use it: public (everyone!)
  • What it gives back: a message

πŸ” Function Visibility: Who Can Press the Button?

There are 4 types of visibility – like 4 different locks on doors:

graph TD A["Function Visibility"] --> B["🌍 public"] A --> C["πŸ”’ private"] A --> D["🏠 internal"] A --> E["🌐 external"] B --> B1["Anyone can call"] C --> C1["Only this contract"] D --> D1["This + child contracts"] E --> E1["Only from outside"]

The 4 Locks Explained:

Visibility Who Can Use It? Real-Life Example
public Everyone Front door of a shop
private Only this contract Your secret diary
internal This + inherited contracts Family recipe
external Only outsiders Drive-thru window

Quick Examples:

// Anyone can call this
function getBalance() public view
    returns (uint) {
    return balance;
}

// Only this contract can use
function _secretCalc() private pure
    returns (uint) {
    return 42;
}

// This contract + children
function _familySecret() internal view
    returns (uint) {
    return treasureLocation;
}

// Only call from outside
function deposit() external payable {
    balance += msg.value;
}

🏁 Constructors: The Birth Certificate

A constructor runs once – the moment your contract is born.

It’s like setting up a new phone:

  • Choose your name
  • Set your password
  • Pick your settings
contract MyToken {
    string public name;
    address public owner;

    // Runs ONCE when deployed
    constructor(string memory _name) {
        name = _name;
        owner = msg.sender;
    }
}

Key Points:

  • βœ… No function keyword needed
  • βœ… Can take parameters
  • βœ… Sets up initial state
  • ❌ Cannot be called again ever

πŸ›‘οΈ Function Modifiers: The Security Guards

Modifiers are checkpoints before your function runs.

Think of a nightclub bouncer:

  • β€œAre you on the list?” βœ“
  • β€œAre you old enough?” βœ“
  • β€œOK, you can enter!” πŸŽ‰
// The bouncer definition
modifier onlyOwner() {
    require(
        msg.sender == owner,
        "Not the owner!"
    );
    _; // Continue to function
}

// Using the bouncer
function withdraw() public onlyOwner {
    // Only owner gets here!
    payable(owner).transfer(balance);
}

The Magic _; Symbol

The underscore _; means: β€œNow run the actual function”

graph LR A["Call Function"] --> B["Check Modifier"] B --> C{Pass Check?} C -->|Yes| D["Run Function Code"] C -->|No| E["Revert with Error"]

Stacking Multiple Modifiers:

modifier notPaused() {
    require(!paused, "Contract paused");
    _;
}

// Both guards must pass!
function transfer()
    public
    onlyOwner
    notPaused
{
    // Safe to run
}

πŸ‘€ Read-Only Functions: Just Looking, Not Touching

Two types of functions that promise not to change anything:

view Functions – Reading State

uint public balance = 100;

// Can READ state variables
function getBalance() public view
    returns (uint) {
    return balance;
}

pure Functions – No State Access

// Cannot read OR write state
function add(uint a, uint b)
    public pure
    returns (uint) {
    return a + b;
}

The Difference:

Type Can Read State? Can Modify State? Gas Cost
view βœ… Yes ❌ No Free*
pure ❌ No ❌ No Free*

*Free when called externally, not from a transaction


πŸ’° Payable Functions: Show Me The Money!

Payable functions can receive ETH (Ether).

Without payable, the function rejects any money sent to it.

contract Donation {
    // Can receive ETH
    function donate() public payable {
        // msg.value = amount sent
        emit Received(msg.sender, msg.value);
    }

    // Cannot receive ETH
    function normalFunc() public {
        // Reverts if ETH sent!
    }
}

Real Example – Crowdfunding:

contract Crowdfund {
    uint public goal = 10 ether;
    uint public raised;

    function contribute() public payable {
        require(msg.value > 0, "Send ETH!");
        raised += msg.value;
    }

    function goalReached() public view
        returns (bool) {
        return raised >= goal;
    }
}

🚨 Fallback and Receive: The Safety Nets

What happens when someone sends ETH with no function call?

Or calls a function that doesn’t exist?

receive() – Plain ETH Transfers

// Triggered when ETH sent with no data
receive() external payable {
    emit Received(msg.sender, msg.value);
}

fallback() – Everything Else

// Triggered when:
// 1. Function doesn't exist
// 2. ETH sent without receive()
fallback() external payable {
    emit FallbackCalled(msg.data);
}

The Decision Flow:

graph TD A["ETH Sent to Contract"] --> B{msg.data empty?} B -->|Yes| C{receive exists?} B -->|No| D{Function exists?} C -->|Yes| E["Call receive"] C -->|No| F["Call fallback"] D -->|Yes| G["Call that function"] D -->|No| F F --> H{fallback payable?} H -->|Yes| I["Accept ETH"] H -->|No| J["Revert!"]

Complete Example:

contract Wallet {
    event Deposit(address, uint);
    event Fallback(bytes);

    // Plain ETH transfers
    receive() external payable {
        emit Deposit(msg.sender, msg.value);
    }

    // Unknown calls or ETH with data
    fallback() external payable {
        emit Fallback(msg.data);
    }
}

πŸŽ“ Putting It All Together

Here’s a complete contract using everything we learned:

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

contract VendingMachine {
    address public owner;
    uint public itemPrice = 0.01 ether;
    uint public stock = 100;

    // CONSTRUCTOR - runs once
    constructor() {
        owner = msg.sender;
    }

    // MODIFIER - security check
    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    // PAYABLE - accepts ETH
    function buyItem() public payable {
        require(msg.value >= itemPrice);
        require(stock > 0);
        stock--;
    }

    // VIEW - read only
    function getStock() public view
        returns (uint) {
        return stock;
    }

    // PURE - no state access
    function calculate(uint qty)
        public pure returns (uint) {
        return qty * 0.01 ether;
    }

    // PRIVATE - internal only
    function _resetStock() private {
        stock = 100;
    }

    // EXTERNAL + MODIFIER
    function withdraw() external onlyOwner {
        payable(owner).transfer(
            address(this).balance
        );
    }

    // RECEIVE - plain ETH
    receive() external payable {}

    // FALLBACK - unknown calls
    fallback() external payable {}
}

πŸš€ Quick Reference

Concept Purpose Keyword
Visibility Who can call public private internal external
Constructor Initial setup constructor()
Modifier Add checks modifier name() { _; }
Read-only No changes view or pure
Accept ETH Receive money payable
Safety net Handle unknown receive() fallback()

πŸ’‘ Remember This!

🎰 Functions = Buttons on your smart contract vending machine

  • public = Everyone’s button
  • private = Secret button
  • payable = Coin slot button
  • view/pure = Display screen (just shows info)
  • receive/fallback = β€œInsert coins here” slot

You now understand Solidity functions! πŸŽ‰

Each function type has its purpose. Mix them together to build powerful, secure smart contracts.

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.