0

I have the following smart contract function that is supposed to be called from a web app, using ethers and Metamask, running on Hardhat localhost blockchain. Its purpose is to send the specified amount to the specified wallet.

function sendRewardToGameWinner(address payable _to, uint256 amount) external payable {
    _to.send(amount);
}

I call this function using ethers in a Javascript React file like this:

export async function sendRewardToGameWinner(chainId, to, wonAmount) {
    const provider = new ethers.providers.Web3Provider(window.ethereum);
    const signer = provider.getSigner();
    const contract = new ethers.Contract(contractAddresses[chainId][0], abi, signer);

    try {
        const amount = ethers.utils.parseEther(ethAmount);
        const transactionResponse = await contract.sendRewardToGameWinner(to, amount, {value: amount});

        await listenForTransactionMine(transactionResponse, provider);
    } 
    catch (error) {
        console.log(error);
    }
}

In Metamask, the transaction appears as if it's going from the wallet to the contract, instead of my intended way, which is from the contract to the wallet.

enter image description here

After I confirm the transaction, it appears as -5 in the history, instead of +5, as I would expect. Also, the wallet balance doesn't change at all (in the following photo it was initially 10000 and it became 9996.9999 after initially sending ETH to the contract).

enter image description here

In short:

Initial balance: 10000

Send 3 ETH to contract => balance = 9996.9999 (OK)

Send 5 ETH FROM contract to wallet => balance = 9996.9999 (NOT OK), expected balance = 10001.9999/10002

Why is that? What am I doing wrong?

2 Answers 2

0

What you are exactly doing is making the function payable and sending the contract an ETH amount. You got to always remember, if you want the contract to receive ether, the function needs to be payable. If you need a wallet to receive ether, your wallet address needs to be payable. Here, you have both of these payable. Although it won't affect the working of the function, then you got to change your front-end code.

const transactionResponse = await contract.sendRewardToGameWinner(to, amount, {value: amount})

Adding anything in value means you are sending ETH to the contract. Just remove this, and you are good to go. Just make sure your contract has enough balance to transfer.

const transactionResponse = await contract.sendRewardToGameWinner(to, amount) 
2
  • Thank you for your answer! Actually, this is what I've began with, I had the function call exactly like you pointed out the second time. The reason why I also have {value: amount} in the call is because I had a problem with how you referenced and the ETH amount wasn't showing up in the transaction confirmation screen. Please see my question here: ethereum.stackexchange.com/questions/143866/… Feb 11, 2023 at 11:27
  • It will not show up. The metamask shows up ETH amount only in case of an external call, or direct call in which you want to send ETH to a contract. Here, the contract sending ETH to an address is an internal call, and thus cannot be shown in metamask. It can be shown in etherscan though. Feb 11, 2023 at 13:31
0

by providing the value field in :

const transactionResponse = await contract.sendRewardToGameWinner(to, amount, {value: amount})

you are actually filling the msg.value field with actual eth, and triggering an automatic send transaction from hardhat, as you previously provided all your signing informations. If you want to avoid that behavior, you should specify the amount as an additional parameter without filling the "value" field.

1
  • Thank you for your answer! Actually, this is what I've began with, I had the function call exactly like you pointed out the second time. The reason why I also have {value: amount} in the call is because I had a problem with how you referenced and the ETH amount wasn't showing up in the transaction confirmation screen. Please see my question here: ethereum.stackexchange.com/questions/143866/… Feb 11, 2023 at 11:28

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.