Solidity – Transferring Only Available for Objects of Type “address payable”, Not “address”

openzeppelin-contractsremixsolidity

I am reading the book Mastering Blockchain Programming With Solidity by Jitendra Chittoda published by Packt Publishing. On page 129 it has a sample contract to deploy using the Remix IDE and MetaMask. DeploymentExample.sol

I have modified this code to move past a few errors but now I am stuck:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol";

/**
 * @title Contract Deployment Example
 */
contract DeploymentExample is Ownable {
    using SafeMath for uint;

    mapping(address  => uint) public balances;
    uint public totalDeposited;

    event Deposited(address indexed who, uint amount);
    event Withdrawn(address indexed who, uint amount);

    /**
     * @dev The fallback function to receive ether.
     */
    receive() external payable {
        depositEther();
    }

    /**
     * @dev Deposits Ether to the contract
     */
    function depositEther() public payable {
        require(msg.value > 0);
        balances[msg.sender] = balances[msg.sender].add(msg.value);
        totalDeposited = totalDeposited.add(msg.value);
        emit Deposited(msg.sender, msg.value);
    }

    /**
     * @dev Withdraw the deposit ether balance.
     * @param _amount Amount to withdraw.
     */
    function withdraw(uint _amount) public  {
        require(balances[msg.sender] >= _amount);
        balances[msg.sender] = balances[msg.sender].sub(_amount);
        totalDeposited = totalDeposited.sub(_amount);
        msg.sender.transfer(_amount);
        emit Withdrawn(msg.sender, _amount);
    }

    /**
     * @dev Destroy the contract and send all ether balance to owner.
     */
    function kill() public onlyOwner {
        //Convert from `address` to `address payable`
        address payable payableOwner = address(uint160(owner()));
        selfdestruct(payableOwner);
    }
}

On line 45 the code msg.sender.transfer(_amount); is giving me the error TypeError: "send" and "transfer" are only available for objects of type "address payable", not "address".

Part of the problem seems to be that I had to change the compiler version to use the imported OpenZeppelin contracts.

Best Answer

msg.sender is no longer a payable address anymore starting from Solidity 0.8.x. You can explicitly convert it to payable by using payable(msg.sender). That should resolve the error.

Related Topic