2

As I understand I should make transfer function payable but it says "Overriding function changes state mutability from "payable" to "nonpayable".

wladknd
  • 21
  • 3

1 Answers1

3

Solidity currently (v0.8) doesn't allow overriding non-payable methods (e.g. the OpenZeppelin transfer() function) to payable. So this approach won't work:

pragma solidity ^0.8;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MyToken is ERC20 {
    constructor() ERC20("MyToken", "MyT") {
    }

    // cannot override non-payable function to payable
    function transfer(address to, uint256 amount) override public payable returns (bool) {
    }
}

The ERC-20 standard doesn't say anything about the transfer() function being payable - it doesn't explicitly allow nor disallow it.


There are two ways to define a payable transfer() function in your case:

  1. Create a local fork of the OpenZeppelin ERC20.sol contract, as well as its dependencies, and change the declaration of their transfer() function to payable. Then you can override it in a child contract and implement a custom fee.

  2. Implement the ERC20 standard from scratch in your contract without using OpenZeppelin. Then you'll be able define a custom transfer() function with the payable modifier.

Petr Hejda
  • 40,554
  • 8
  • 72
  • 100