I'm practicing How to Build a Staking Dapp example in Alchemy. In Staker.sol, there's a withdraw function which hasn't a payable keyword. But it does work. Isn't it necessary to use 'payable' when transferring eth?

function withdraw() public withdrawlDeadlineReached(true) claimDeadlineReached(false) notCompleted {
    require(balances[msg.sender] > 0 , "You have no balance to withdraw!");
    uint256 individualBalance = balances[msg.sender];
    uint256 indBalanceReward = individualBalance + ((block.timestamp - depositTimestamps[msg.sender]) * rewardRatePerBlock);
    balances[msg.sender] = 0;

    (bool sent, bytes memory data) = msg.sender.call{value: indBalanceReward}("");
    require(sent, "RIP, withdrawl failed :( ");

3 Answers 3


You need the payable modifier when a function you write intends to receive ether (e.g. deposit(), receive(), fallback()...etc). Your withdraw function is not intended to receive ether, so no payable modifier is necessary. And no, it isn't necessary to use payable when transferring ether.

See: payable() function In solidity


you should convert msg.sender to address payable:

take a look at the doc

The global variables tx.origin and msg.sender have the type address instead of address payable. One can convert them into address payable by using an explicit conversion, i.e., payable(tx.origin) or payable(msg.sender).

(bool sent, bytes memory data) = payable(msg.sender).call{value: indBalanceReward}("");

To further clear your understanding of this a similar question like this was asked here. It explain the difference between the two.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.