OpenZeppelin Address Library – Cannot Use sendValue Method Properly

libraryopenzeppelinsolidity

I was trying to use Openzeppelin Address library sendValue(), and it kept showing error Member "sendValue" not found or not visible after argument-dependent lookup in address.solidity(9582) while isContract() worked.

Could anyone help?

My contract:

// I'm a comment!
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;
import "@openzeppelin/contracts/utils/Address.sol";


contract Example {
    using Address for address;

    struct Voucher {
        address buyer;
    }

    function Test(Voucher calldata voucher) public payable {

        address buyer = payable(voucher.buyer);
        buyer.isContract(); // This works
        buyer.sendValue(2); // This doesn't work

    }
}

Openzeppelin Address library:

    function isContract(address account) internal view returns (bool) {
        return account.code.length > 0;
    }

    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

Best Answer

This is really interesting.

Notice how the sendValue first parameter is of type address payable while the isContract first parameter is only of type address. There is a difference.

You just need to use the library not only on the address but for the address payable type, like this:

using Address for address payable;

And then declare the buyer value as payable as well, like:

address payable buyer = payable(voucher.buyer);

The whole thing would look like this:

// I'm a comment!
// SPDX-License-Identifier: MIT

pragma solidity 0.8.17;
import "@openzeppelin/contracts/utils/Address.sol";


contract Example {
    using Address for address payable;

    struct Voucher {
        address buyer;
    }

    function Test(Voucher calldata voucher) public payable {

        address payable buyer = payable(voucher.buyer);
        buyer.isContract(); // This works
        buyer.sendValue(2); // Now it works work too

    }
}