πŸ“š
Open Polkadot Bootcamp
  • πŸ“š About the Bootcamp
    • πŸ“– Additional Resources
    • πŸ‘ Ask For Support
  • πŸ“– Curriculum
  • πŸ“•Rust Programming Language
    • Basic Rust
      • Introduction to Rust
        • πŸ§‘β€πŸ’» Excercises
      • Common Programming Concepts
        • πŸ§‘β€πŸ’» Excercises
      • Program Life Cycle
        • πŸ§‘β€πŸ’» Excercises
      • Ownership & Borrow Checker
      • Common Data Structures
    • Advanced Rust
      • Generic types, Trait extension and Advanced types
      • Lifetime Notation
      • Smart pointers & Macros
      • Common design patterns in Rust
      • Package management & How to structure your Rust project
      • Overview of the Rust ecosystem
  • πŸ“˜Building a blockchain with Polkadot SDK
    • Polkadot
      • Additional Reads
        • Why do you want to build a blockchain on Polkadot?
        • Understanding the sharded network design of Polkadot
      • Development on Polkadot
    • Polkadot SDK
      • Substrate
        • Create a new blockchain
          • πŸ§‘β€πŸ’» Exercise: Clone the minimal template
          • Understanding the architecture
          • Break down the node architecture
          • Introducing to Pop CLI tool
        • Adding a custom logic to runtime
          • πŸ§‘β€πŸ’» Exercise: Rust State Machine
          • Components of a Pallet
          • Hooks
          • Weights & Benchmarking
          • Extensions
            • Signed Extensions
            • Transaction Extensions
        • Common runtime modules
          • πŸ“•Example: System Pallet
          • πŸ“•Example: Contracts Pallet
          • πŸ“•Example: Assets Pallet
          • πŸ“•Example: Utility Pallet
        • Runtime API and RPC
        • Runtime upgrade
        • Bump Polkadot SDK versions
      • Cumulus
        • Introduction to Cumulus
          • Parachain from scratch
          • πŸ§‘β€πŸ’» Exercise: Build a parachain from scratch
        • Running a local relaychain network
          • Register & reserve a parachain
          • Launch the network & run a collator node
          • Launch the network with Pop CLI
        • Agile Coretime
    • Polkadot Hub
  • πŸ“’Smart Contract Development
    • Introduction
      • Introduction to PolkaVM
      • Getting started with Solidity development
      • Solidity File Structure
      • Contract Structure
    • Basic Solidity
      • Value types
      • Reference Types
      • Mapping Types
      • Simple Storage
    • Advanced Solidity
      • Units
      • Global Variables
      • Expression and Control Structures
      • Advanced Storage
      • Contract Tests
      • Contracts
Powered by GitBook
On this page
  • More information about Contract in Solidity
  • constructor
  • State variable visibility
  • Function visibility
  • Getter function
  • Constants and immutable state variables
  • Pure function
  • Payable functions and addresses
  • Receive Ether and Fallback function
  • Oracle
  1. Smart Contract Development
  2. Advanced Solidity

Contracts

More information about Contract in Solidity

constructor

Constructor is a function that runs immediately when the smart contract is initialized

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

// Base contract X
contract X {
    string public name;

    constructor(string memory _name) {
        name = _name;
    }
}

State variable visibility

  • public - Public variables are similar to internal variables (allowing the current contract and inherited contracts to access) but will automatically create a getter function so that external contracts can also access it.

  • internal - The variable can only be accessed by the current contract and inherited contracts. This is also the default visibility for state variable.

  • private - The variable can only be accessed by the current contract.

Note: The internal and private variables only restrict access to other contracts. The value of the variable remains visible to everyone.

Function visibility

  • external - function that can only be called from outside.

  • public - function can both be called by another function in contract, and can also be called from outside.

  • internal - function can only be called by an existing contract or an inherited contract.

  • private - function can only be called by the current contract.

Getter function

function is used to call the public variable that the compiler automatically creates. Also used to refer to the concept of function used to query variables to view.

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;

contract C {
    uint public data = 42;
}

contract Caller {
    C c = new C();
    function f() public view returns (uint) {
        return c.data();
    }
}

Constants and immutable state variables

  • constant - variables whose values ​​are fixed immediately upon compilation (put into contract bytecode).

  • immutable - variables whose values ​​can be assigned during construct.

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.21;

uint constant X = 32**22 + 8;

contract C {
    string constant TEXT = "abc";
    bytes32 constant MY_HASH = keccak256("abc");
    uint immutable decimals = 18;
    uint immutable maxBalance;
    address immutable owner = msg.sender;

    constructor(uint decimals_, address ref) {
        if (decimals_ != 0)
            // Immutables are only immutable when deployed.
            // At construction time they can be assigned to any number of times.
            decimals = decimals_;

        // Assignments to immutables can even access the environment.
        maxBalance = ref.balance;
    }

    function isBalanceTooHigh(address other) public view returns (bool) {
        return other.balance > maxBalance;
    }
}

Pure function

function does not read or change the state of the blockchain. Or used as a calculation function.

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.9.0;

contract C {
    function f(uint a, uint b) public pure returns (uint) {
        return a * (b + 42);
    }
}

Payable functions and addresses

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

contract Payable {
    // Payable address can send Ether via transfer or send
    address payable public owner;

    // Payable constructor can receive Ether
    constructor() payable {
        owner = payable(msg.sender);
    }

    // Function to deposit Ether into this contract.
    // Call this function along with some Ether.
    // The balance of this contract will be automatically updated.
    function deposit() public payable {}

    // Call this function along with some Ether.
    // The function will throw an error since this function is not payable.
    function notPayable() public {}

    // Function to withdraw all Ether from this contract.
    function withdraw() public {
        // get the amount of Ether stored in this contract
        uint256 amount = address(this).balance;

        // send all Ether to owner
        (bool success,) = owner.call{value: amount}("");
        require(success, "Failed to send Ether");
    }

    // Function to transfer Ether from this contract to address from input
    function transfer(address payable _to, uint256 _amount) public {
        // Note that "to" is declared as payable
        (bool success,) = _to.call{value: _amount}("");
        require(success, "Failed to send Ether");
    }
}

Receive Ether and Fallback function

A contract can have at most one receive function, declared using receive() external payable { ... } (without the function keyword). This function must have no arguments, cannot return anything and must have external visibility as well as payable state mutability. It can be virtual, it can be override and it can have modifiers.

    Which function is called, fallback() or receive()?

           send Ether
               |
         msg.data is empty?
              / \
            yes  no
            /     \
receive() exists?  fallback()
         /   \
        yes   no
        /      \
    receive()   fallback()
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

contract Fallback {
    event Log(string func, uint256 gas);

    // Fallback function must be declared as external.
    fallback() external payable {
        // send / transfer (forwards 2300 gas to this fallback function)
        // call (forwards all of the gas)
        emit Log("fallback", gasleft());
    }

    // Receive is a variant of fallback that is triggered when msg.data is empty
    receive() external payable {
        emit Log("receive", gasleft());
    }

    // Helper function to check the balance of this contract
    function getBalance() public view returns (uint256) {
        return address(this).balance;
    }
}

contract SendToFallback {
    function transferToFallback(address payable _to) public payable {
        _to.transfer(msg.value);
    }

    function callFallback(address payable _to) public payable {
        (bool sent,) = _to.call{value: msg.value}("");
        require(sent, "Failed to send Ether");
    }
}

Oracle

Oracle for smart contracts is a bridge between blockchain and the outside world. It provides data to smart contracts from sources outside the blockchain, such as APIs, market data, weather data, etc.

Here are some examples of how to use oracle for smart contracts:

  • Providing price data for decentralized markets (DeFi): Oracle can provide price data for crypto assets, allowing traders to make trades on decentralized exchanges.

  • Activate insurance contracts: Oracle can provide data about insurance events, such as accidents or natural disasters, to trigger insurance payments.

  • Automate processes: Oracle can be used to automate processes, such as bill payment or supply chain management.

PreviousContract Tests

Last updated 5 months ago

List of Oracles on Klaytn:

πŸ“’
https://klaytn.foundation/ecosystem/?search=&cate=oracles-bridges&sort=abc