Question: I saw a Solidity smart contract where some variables were declared with the type `address` and some were declared with the type `address payable`. What are the differences between the two?

* Do they store the same data?
* How do you convert a value from one address type to the other type?

Answer: 
Data storage and representation in the EVM
------------------------------------------

The `address` and `address payable` types both store a 160-bit Ethereum address. The concept of payable and non-payable addresses only exists in the Solidity type system at compile-time. The difference between payable and non-payable addresses is gone in the compiled contract code.

---

Built-in methods
----------------

You can use `.transfer(..)` and `.send(..)` on `address payable`, but not on `address`.

You can use a low-level `.call{value: ..}(..)` on both `address` and `address payable`, even if you attach value.

---

Casting from `address payable` to `address`
-------------------------------------------

`address payable` can be implicitly or explicitly cast to `address`:

```
address payable addr1 = payable(msg.sender);
address addr2 = addr1; // This is correct
address addr3 = address(addr1); // This is correct

```

---

Casting from `address` to `address payable`
-------------------------------------------

`address` can only be explicitly cast to `address payable`:

```
address addr1 = msg.sender;
address payable addr2 = addr1; // Incorrect
address payable addr3 = payable(addr1); // Correct since Solidity >= 0.6.0
address payable addr4 = address(uint160(addr1)); // Incorrect since Solidity >= 0.8.0

```

---

Casting `address[]` or `address payable[]`
------------------------------------------

Although a single `address payable` can be cast to `address`, arrays of one address type cannot be cast to arrays of another address type:

```
function testCast(address payable[] memory _addresses) returns (address[] memory)
{
    return _addresses; // Type error!
}

```

---

Rationale
---------

Types in programming languages exist for two reasons:

* To provide special type-specific semantics (e.g. `+` on numbers is addition, but `+` on strings might be concatenation)
* To limit the amount of incorrect programs that are accepted by the compiler

The splitting of addresses into `address` and `address payable` serves the latter purpose. It forces the smart contract programmer to think about whether an address should ever receive ether from the smart contract. If it should never receive Ether, the `address` type can be used. Compilation will fail with a type error if the programmer makes a mistake and tries to transfer Ether to that address.

---

Built-in address constants
--------------------------

`msg.sender` is an `address`

`tx.origin` is an `address`

`block.coinbase` is an `address payable`
I was confused about the payable address but after a lot of searching, I find the best use case of a payable address.
when you are working with a solidity smart contract then you use the payable function which receives ethers and stores it in your contract, not your personal address.
so if you want to directly send ethers from the contract to your address then you must need to make your address payable.

Example:

```
address payable contractDeployer;

function recieveEth()public payable{

require(msg.value>0, "amount should be greater then Zero");

// now you directly transfer msg.value to "contractDeployer" account by using builtin function "transfer"

payable(contractDeployer).transfer(msg.value);

}

```

I hope this answer will be useful for you guys.

Thanks