vsupalov

Call a Payable Solidity Function Using Ethers

I found this quite hard to Google, and spent too much time finding it out. Here’s a quick writeup for anyone who’s just getting started with Solidity and ethers.js.

A word of caution: I’m a beginner as well! Things which worked for me may not work for you. The stuff below may be very flawed for reasons I don’t understand. For personal studying purposes only, no guarantees of any kind.

Calling a Payable Function

Here’s a snippet. Kudos to buildspace, most of this code originates in one of their courses. I have seen it wrapped in a try-catch block, to catch and print errors.

It also assumes, that you have connected a metamask wallet already. Otherwise the ethereum object wouldn’t be useful here.

const { ethereum } = window;
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner()
const connectedContract = new ethers.Contract(CONTRACT_ADDRESS, YOUR_ABI.abi, signer);

let tx = await connectedContract.YOUR_PAYABLE_FUNCTION(ALL, OTHER, PARAMETERS, {value: ethers.utils.parseEther(ETH_VALUE_AS_STRING)});

Above, you’ll have to be very cautious. Make sure you’re on a test net, and all values are correct.

  • CONTRACT_ADDRESS should probably be a string, starting with “0x”.
  • YOUR_ABI is an object you are importing, after copying the .json ABI file from your built smart contract somewhere where it can be imported.
  • YOUR_PAYABLE_FUNCTION is the name of the function you want to call.
  • The ALL, OTHER, PARAMETERS part depends on your function. If it’s a function which does not expect argument, you skip them.
  • And finally, ETH_VALUE_AS_STRING is something like "0.0000001" or whatever amount of ETH is supposed to go to your payable function.

If everything works correctly, your metamask should pop up and ask you for a confirmation, if you really want to call this payable function.

Calling a Payable Function During Testing

Assuming you’re using chai and hardhat for testing, and your setup looks like almost-all-tutorials-out-there.

First, you’ll need to have a selection of addresses. Using something like:

[owner, addr1, addr2] = await ethers.getSigners();

I’m not quite sure how this works yet, but this snippet is good enough to get two usable addresses, apart from the owner, for future tests. I’ve had success storing them in global variables for testing.

Now, assuming you’ve deployed your test contract from a Factory to the hardhat testnet using a .deploy() call. Here’s how to call a payable function:

// in the setup
YOUR_DEPLOYED_CONTRACT = await YOUR_DEPLOYED_CONTRACT_Factory.deploy()
// in the test
await YOUR_DEPLOYED_CONTRACT.connect(addr1).YOUR_PAYABLE_FUNCTION(ALL, OTHER, PARAMETERS, {value: ethers.utils.parseEther(ETH_VALUE_AS_STRING)})

You see, the function call is pretty similar as above, only that we’re connecting to the deployed contract by specifying an address.

In Conclusion

I hope this will help you to get over the hurdle of calling your first payable Solidity function from ethers.js. Have fun and stay safe!