Sample PERC20 contract

There is a sample PERC20 (Private ERC20) contract with disabled logs and signature check in the balanceOf function

Contract developers should avoid adding sensitive information to logs, such as transfer amounts, sender and recipient, etc. But you still can use them for some debugging or contract-wide events, for example, contract initialization.

Also, you should be careful with public view functions that can also leak some sensitive information, for example, user balance. In the example, we're using a msg.sender check to verify if the caller is the wallet owner. If this function was called from EOA (Externally Owned Account), EVM will try to recover msg.sender from provided signature within eth_call.

Code of that contract you can see below (full example you can find here: https://github.com/SigmaGmbH/swisstronik-tutorials/blob/main/PERC20_interaction/contracts/PERC20Sample.sol)

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

import "./PERC20.sol";

/**
 * @dev Sample implementation of the {PERC20} contract.
 */
contract PERC20Sample is PERC20 {
    constructor() PERC20("Sample PERC20", "pSWTR") {}

    /// @dev Wraps SWTR to PSWTR.
    receive() external payable {
        _mint(_msgSender(), msg.value);
    }

    /**
     * @dev Regular `balanceOf` function marked as internal, so we override it to extend visibility  
     */ 
    function balanceOf(address account) public view override returns (uint256) {
        // This function should be called by EOA using signed `eth_call` to make EVM able to
        // extract original sender of this request. In case of regular (non-signed) `eth_call`
        // msg.sender will be empty address (0x0000000000000000000000000000000000000000).
        require(msg.sender == account, "PERC20Sample: msg.sender != account");

        // If msg.sender is correct we return the balance
        return _balances[account];
    }

    /**
     * @dev Regular `allowance` function marked as internal, so we override it to extend visibility  
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        // This function should be called by EOA using signed `eth_call` to make EVM able to
        // extract original sender of this request. In case of regular (non-signed) `eth_call`
        // msg.sender will be empty address (0x0000000000000000000000000000000000000000)
        require(msg.sender == spender, "PERC20Sample: msg.sender != account");
        
        // If msg.sender is correct we return the allowance
        return _allowances[owner][spender];
    }
}

Last updated