---
# System prepended metadata

title: Payable Functions in Solidity

---

# Payable Functions in Solidity

Let's discuss the keyword `payable` in Solidity! 

Before we dive into the code, let's first ask: **what is the purpose of this keyword**? :thinking_face: 

The keyword `payable` allows someone to send ether to a contract and run code to account for this deposit. This code could potentially log an event, modify storage to record the deposit, or it could even revert the transaction if it chooses to do so.

When a developer explicitly marks a function as `payable` they are saying "I expect ether to be sent to this function". To understand why this important, imagine how bad it would be if someone sent ether to a contract and the developer did not write code to handle that event. In that case, it would be highly possible that the ether could be locked forever or never withdrawn by its intended recipient. :scream: 

## The Technicals

Ok, now it's time to dive into the technicals. First question: **How does someone send ether to a smart contract?**

Sending ether is a native function of the Ethereum Virtual Machine (EVM). This is different from any other transfer in the EVM which requires the developer to write custom logic inside a smart contract to handle the transfer (i.e. for NFTs or ERC20s). 

When someone sends ether to a smart contract, they do so through a `value` field on the transaction itself. Let's take a look at what a transaction looks like in JSON:

```json
{
    "to": "0x5baf84167cad405ce7b2e8458af73975f9489291",
    "value": "0xb1a2bc2ec50000", // 1 ether 
    "data": "0xd0e30db0" // deposit() 
    // ... other properties
}
```

:point_up: This transaction sends **1 ether** to the address `0x2a20380dca5bc24d052acfbf79ba23e988ad0050`. If this address is a smart contract, it will attempt to parse the calldata (`data`) to figure out which smart contract function this user is attempting to call (in this case it is [`deposit()`](https://www.4byte.directory/signatures/?bytes4_signature=d0e30db0)). If that function is a `payable` function, then it will run the logic. If it is not payable, the transaction will revert and funds will be returned minus the gas cost for the transaction.

So, **what might a payable function look like on the Solidity side**? 

```solidity
function deposit() payable external {
    // no need to write anything here!
}
```

:point_up: Notice, in this case, we didn't write any code in the `deposit` function body. Writing a payable function alone is enough to receive ether and you may not need to write any logic. For instance, if this was a smart contract that was controlled by a charity, perhaps users would just call `deposit` and the charity would eventually be able to withdraw these contributions to an address of their choosing. In that case it may be better to write a `receive` function:

```solidity
receive() external payable {
    // this built-in function doesn't require any calldata,
    // it will get called if the data field is empty and 
    // the value field is not empty.
    // this allows the smart contract to receive ether just like a 
    // regular user account controlled by a private key would.
}
```

So then we should ask ourselves, **why might we write logic in a payable function?**

If we had a smart contract where we needed to keep traack of who deposited which ether, we might keep track of that in storage:

```solidity 
mapping(address => uint) balances;

function deposit() payable external {
    // record the value sent 
    // to the address that sent it
    balances[msg.sender] += msg.value;
}
```

:point_up: The `msg.value` here corresponds with the `value` field encoded in the transaction we looked at much further up on this page! As a Solidity developer we can tap into message value to record deposits and map it up to some internal balance for the address making this transaction.

> :face_with_monocle: Wondering why this it is called `msg.value`? In the EVM, interactions with smart contracts are referred to as "message calls". This is true whether a user is calling a smart contract directly or if a smart contract is calling another smart contract.

Lastly, its worth mentioning, a `payable` smart contract function can revert:

```solidity
mapping(address => uint) balances;

function deposit() payable external {
    // deposit sizes are restricted to 1 ether
    require(msg.value == 1 ether);
    // an address cannot deposit twice
    require(balances[msg.sender] == 0);
    balances[msg.sender] += msg.value;
}
```

If either of the `require` statements are not `true`, the transaction would revert and the sender would receive their funds back. 

In summary, a **payable** function is a function that can receive ether. It provides the developer with the opportunity to respond to an ether deposit for record keeping or any additional necessary logic.