1

I'm writing a contract & trying to implement a small fee for a feature when users trade NFTs & I'm getting errors everything I add a custom uint256 the transaction completely fails as such.

eth_estimateGas
  Contract call:       <UnrecognizedContract>
  From:                0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
  To:                  0xe6e340d132b5f46d1e472debcd681b2abc16e57e
  Value:               0 ETH

  Error: VM Exception while processing transaction: reverted with reason string 'Ether sent to address failed'
      at <UnrecognizedContract>.<unknown> (0xe6e340d132b5f46d1e472debcd681b2abc16e57e)
      at runMicrotasks (<anonymous>)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)
      at EthModule._estimateGasAction (/node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:429:7)
      at HardhatNetworkProvider._sendWithLogging (/node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:139:22)
      at HardhatNetworkProvider.request (/node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:116:18)
      at JsonRpcHandler._handleRequest (/node_modules/hardhat/src/internal/hardhat-network/jsonrpc/handler.ts:188:20)
      at JsonRpcHandler._handleSingleRequest (/node_modules/hardhat/src/internal/hardhat-network/jsonrpc/handler.ts:167:17)

Here is my function trying to send 250 wei for example to another address

function payFee(address payable _addr) external payable {
    // ...... other dapp function calls 
    (bool success,) = _addr.call{value: 250}("");
    require(success, "Ether sent to address failed");
    emit PaymentSent(success);
}

Yet when I call the same function with msg.value instead of a uint256 of 250 then the function passes. What am I doing wrong here? Is it even possible to impose a fee like this in solidity?

2
  • Did your contract have ETH balance? Your code worked perfectly at my end. Commented Nov 23, 2022 at 6:40
  • I was making a mistake on the remix end, I kept forgetting to add Value of 250wei when sending the transaction, part of me thought it would come out automatically
    – CoderMan
    Commented Nov 23, 2022 at 16:27

1 Answer 1

0

I think that you should call the address.transfer or address.send member instead of address.call; On my personal experience I only use address.call when I want to call a function within an external contract, read more info about this here

<address payable>.transfer(uint256 amount)
send given amount of Wei to Address, reverts on failure, forwards 2300 gas stipend, not adjustable

<address payable>.send(uint256 amount) returns (bool)
send given amount of Wei to Address, returns false on failure, forwards 2300 gas stipend, not adjustable

<address>.call(bytes memory) returns (bool, bytes memory)
issue low-level CALL with the given payload, returns success condition and return data, forwards all available gas, adjustable

If you want something cheaper on gas and utterly overkill in knowledge terms you could do this; more info in YUL here

function _transfer(address to, uint256 amount) internal {
    bool callStatus;
    assembly {
        callStatus := call(gas(), to, amount, 0, 0, 0, 0)
    }
    if (!callStatus) revert TransferFailed();
}
2
  • 1
    Thank you for the detailed response, I've only went with call() since the docs where stating that call() should be the standard choice over send() or transfer() but I tried send() with a uint256 & the function passed :)
    – CoderMan
    Commented Nov 23, 2022 at 16:15
  • yeah ahah In my Yul snippet I'm actually just using the call as you did in your example :3 all of them are valid and technically the same
    – Casareafer
    Commented Nov 24, 2022 at 4:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.