LogoLogo
Phron AIopenPhronDocs
  • Build with Phron AI
  • Quick Start
    • Rust toolchain
    • Install
    • Developer CLI Tools
  • Learn
    • Why Substrate
    • Ethereum Compatible
    • Governance on PhronAI
  • Use
    • Wallets
    • Explorer
    • Bridge
    • Staking
      • Menu Overview
      • How to Start Staking with the Phron Dashboard
      • How to Change Nominations
      • How to Stop Staking
      • Staking Rewards
    • Validate
    • Dashboard
  • Build with PhronAI
    • SDKs and Tools
      • Ethereum
        • Contracts
        • Libraries
          • Ethers.js
          • Ethers.rs
          • Web3.js
          • Web3.py
        • Dev Environments
          • OpenZeppelin
            • Overview
            • Contract Wizard
            • Defender
          • Ape
          • Brownie
          • Foundry
          • Hardhat
          • Remix
          • Scaffold-PHR
          • Tenderly
          • thirdweb
          • Waffle & Mars
        • Contract Verification
          • PhronScan
        • RPC APIs
          • Standard Ethereum
          • Non-standard Ethereum: Tracing
      • Substrate
        • Libraries
          • Polkadot.js
          • Py substrate interface
        • Dev Environments
          • Chopsticks by Acala
    • Smart Contracts Development
      • Solidity Contracts
        • Phron API
          • Project Overview
          • Prerequisites
          • Steps to Set Up
          • Contract Architecture
          • Contract Functions
          • Testing
          • Deployment
          • Security Considerations
          • Using Foundry Start to End with Phron
          • How to Build a DApp: Complete DApp Architecture
        • Phron Toolkit
          • Libraries
            • Ethers.js
            • Ethers.rs
            • viem
            • Web3.js
            • Web3.py
          • Dev Environments
            • OpenZeppelin
              • Overview
              • Contract Wizard
              • Defender
            • Ape
            • Brownie
            • Foundry
            • Hardhat
            • Remix
            • Scaffold-PHR
            • Tenderly
            • thirdweb
            • Waffle & Mars
          • Verify Contracts
            • PhronScan
          • JSON-RPC APIs
            • Standard Ethereum
            • Non-standard Ethereum: Tracing
      • Rust Contracts
        • Phron smart contracts basics
          • Setting up a Testnet account
          • Installing required tools
          • Creating your first contract
          • Deploying your contract to Phron Testnet
          • Extending your contract
        • Cross contract calls
          • Using references
          • Using dynamic calls
Powered by GitBook
On this page
Export as PDF
  1. Build with PhronAI
  2. Smart Contracts Development
  3. Solidity Contracts
  4. Phron API

Contract Architecture

Contract Interfaces

Interfaces in Solidity are used to define the structure of external functions without providing their internal logic. They are essential for creating interoperable contracts that follow a standard design, ensuring that different contracts can interact with one another seamlessly.

interface IMyContract {
    function transfer(address recipient, uint256 amount) external returns (bool);
    function balanceOf(address account) external view returns (uint256);
}
  • transfer(address recipient, uint256 amount): Defines a function to transfer tokens to a specified recipient. It returns a boolean (true/false) to indicate whether the transfer was successful.

  • balanceOf(address account): Defines a function that returns the current balance of an account. It's a read-only function (view) that doesn't modify the state.

Interfaces allow for modularity and upgradeability by ensuring that any contract implementing this interface will have these two key functions, without enforcing their specific implementation details.

Modifiers

Modifiers are used to alter the behavior of functions. They allow you to add prerequisites or checks before the function’s execution proceeds. This helps streamline code by avoiding repetition of common checks and improving contract security.

modifier onlyOwner() {
    require(msg.sender == owner, "Caller is not the owner");
    _;
}
  • onlyOwner: This modifier restricts function access to only the contract's owner. The require statement checks that the caller (msg.sender) is the owner. If the condition fails, it reverts the transaction with an error message. The _ in the modifier represents where the function body will be inserted when the modifier is applied. This is a common pattern for restricting administrative functions, ensuring only the owner can perform sensitive operations.

Events

Events are a logging mechanism in Solidity that allow contracts to emit information during execution. Off-chain services, like blockchain explorers and front-end applications, can listen to these events and react to them. They are a fundamental part of communication between the blockchain and external systems.

event Transfer(address indexed from, address indexed to, uint256 value);
  • Transfer: This event logs token transfers between accounts. It includes three key pieces of information:

    • from: The address of the sender.

    • to: The address of the recipient.

    • value: The number of tokens transferred.

The indexed keyword allows these fields to be easily filtered in external event logs. Emitting events is gas-efficient and provides a way to track contract activity without modifying the blockchain state.

Storage Variables

Storage variables are used to hold the persistent state of the contract. These variables are stored directly on the blockchain and are essential for managing the contract’s data.

address public owner;
mapping(address => uint256) private balances;
  • owner: This variable stores the address of the contract owner, typically set during the contract’s deployment. Marked as public, it automatically generates a getter function, allowing anyone to view the owner’s address.

  • balances: This is a mapping (a key-value data structure) that associates each account (address) with its token balance (uint256). Marked as private, this ensures that the balance data can only be accessed through functions explicitly defined in the contract, maintaining data security.

Example of How Everything Works Together

Here's an example of how interfaces, modifiers, events, and storage variables come together in a complete smart contract:

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

interface IMyContract {
    function transfer(address recipient, uint256 amount) external returns (bool);
    function balanceOf(address account) external view returns (uint256);
}

contract MyToken is IMyContract {
    address public owner;
    mapping(address => uint256) private balances;

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

    modifier onlyOwner() {
        require(msg.sender == owner, "Caller is not the owner");
        _;
    }

    constructor() {
        owner = msg.sender;
        balances[owner] = 1000000; // Initial token supply to owner
    }

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

    function balanceOf(address account) external view override returns (uint256) {
        return balances[account];
    }

    function mint(uint256 amount) external onlyOwner {
        balances[owner] += amount;
        emit Transfer(address(0), owner, amount); 
        // Emitting a mint event as a "transfer" from the zero address
    }
}
  • IMyContract interface ensures that the contract implements the required functions (transfer and balanceOf).

  • onlyOwner modifier restricts certain actions (like minting new tokens) to the contract’s owner.

  • Transfer event provides a way to track token transfers, ensuring transparency.

  • balances storage variable keeps track of how many tokens each account holds.

PreviousSteps to Set UpNextContract Functions