[Solidity] payable, Sending Ether

jhcha·2023년 8월 1일
0

Solidity

목록 보기
8/17
post-thumbnail
post-custom-banner

Payable

url: https://solidity-by-example.org/payable/

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

contract Payable {
    // Payable address can receive Ether
    address payable public owner;

    // Payable constructor can receive Ether
    constructor() payable {
        owner = payable(msg.sender);
    }

    // Function to deposit Ether into this contract.
    // Call this function along with some Ether.
    // The balance of this contract will be automatically updated.
    function deposit() public payable {}

    // Call this function along with some Ether.
    // The function will throw an error since this function is not payable.
    function notPayable() public {}

    // Function to withdraw all Ether from this contract.
    function withdraw() public {
        // get the amount of Ether stored in this contract
        uint amount = address(this).balance;

        // send all Ether to owner
        // Owner can receive Ether since the address of owner is payable
        (bool success, ) = owner.call{value: amount}("");
        require(success, "Failed to send Ether");
    }

    // Function to transfer Ether from this contract to address from input
    function transfer(address payable _to, uint _amount) public {
        // Note that "to" is declared as payable
        (bool success, ) = _to.call{value: _amount}("");
        require(success, "Failed to send Ether");
    }
}

function과 address에 payable이 선언되어 있으면 이더를 수신할 수 있다.

contract Payable {
    // Payable address can receive Ether
    address payable public owner;

    // Payable constructor can receive Ether
    constructor() payable {
        owner = payable(msg.sender);
    }
}

Payable 컨트랙트를 배포하게 되면 생성자 함수에 payable 키워드를 통해 배포한 주소 (msg.sender)에 이더리움을 전송할 수 있다.

Sending Ether (transfer, send, call)

url: https://solidity-by-example.org/sending-ether

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

contract ReceiveEther {
    /*
    Which function is called, fallback() or receive()?

           send Ether
               |
         msg.data is empty?
              / \
            yes  no
            /     \
receive() exists?  fallback()
         /   \
        yes   no
        /      \
    receive()   fallback()
    */

    // Function to receive Ether. msg.data must be empty
    receive() external payable {}

    // Fallback function is called when msg.data is not empty
    fallback() external payable {}

    function getBalance() public view returns (uint) {
        return address(this).balance;
    }
}

contract SendEther {
    function sendViaTransfer(address payable _to) public payable {
        // This function is no longer recommended for sending Ether.
        _to.transfer(msg.value);
    }

    function sendViaSend(address payable _to) public payable {
        // Send returns a boolean value indicating success or failure.
        // This function is not recommended for sending Ether.
        bool sent = _to.send(msg.value);
        require(sent, "Failed to send Ether");
    }

    function sendViaCall(address payable _to) public payable {
        // Call returns a boolean value indicating success or failure.
        // This is the current recommended method to use.
        (bool sent, bytes memory data) = _to.call{value: msg.value}("");
        require(sent, "Failed to send Ether");
    }
}

이더는 transfer(2300 gas, throws error), send (2300 gas, returns bool), call (forward all gas or set gas, returns bool)를 통해 보낼 수 있다.
받는 방법은 아래 기능 중 하나 이상이 있어야 한다.

  • receive() external payable
  • fallback() external payable
    msg.data가 비어있다면 receive()가 호출되고 아닌 경우 fallback()가 호출된다.
    이더를 보내는 방법으로 재진입방지 (re-entracy guard)를 결합하여 call을 사용하는 것이 권장된다.
    address 객체의 members 참고자료: https://solidity-kr.readthedocs.io/ko/latest/types.html
post-custom-banner

0개의 댓글