체인의정석

Solidity) 스마트컨트렉트에서 이더리움을 보내는 방법 본문

블록체인/Solidity

Solidity) 스마트컨트렉트에서 이더리움을 보내는 방법

체인의정석 2022. 8. 10. 15:28
728x90
반응형

스마트컨트렉트에서 이더리움을 보내는 방법은 총 3가지가 있다고한다.

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

 

Solidity by Example

 

solidity-by-example.org

  • transfer (2300 gas, throws error)
  • send (2300 gas, returns bool)
  • call (forward all gas or set gas, returns bool)

 

이렇게 3가지 인데, 원래 예전에는 call을 쓰면 재진입 공격이 가능하기 때문에 잘 쓰지 않는고 배웠었다. transfer나 send를 쓰라고 했는데

 

예전에 어느 시점의 메인넷 업데이트 이후 가스비가 변경되어 send나 transfer에 문제가 생기는 경우가 있었던 이야기를 전에 들은거 같다. 결국 나중에 업데이트 되면 고정 가스비는 위험하기 때문에 call을 쓰는것이 좋은거 같다.

 

또한 프록시 배포를 한 경우 이더리움 전송은 call을 통해서만 가능하니 call을 써야한다.

 

각 전송 방식에 대한 예시는 아래와 같은데 sent를 통해서 전송이 되었는지 여부를 체크하고 전송이 안되었을 경우 오류가 나오게 코딩해주어야 한다.

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");
    }
}

 

일단 이번에는 프록시 배포를 나중에 쓸 수도 있고 메인넷 업데이트에 영향을 안받고 사용하기 위해서 call을 쓰고 재진입 공격을 막는 형태로 사용하기로 결정했다. 여기에 대해서는 추후 오픈제플린의 재진입 방지 코드를 상속받아서 사용할 생각이다.

 

위의 예시를 보고 그대로 코드를 작성하려고 하는데

ParserError: Expected ';' but got '{'
    (bool sent, bytes memory data) = depositReceiver.call{value: msg.value}("");

이런 에러가 떴다.

 

찾아본 과 0.7.0 버전 밑에서의 문법이 달라서 난 에러였다.

 

https://stackoverflow.com/questions/66388642/solidity-parsererror-expected-but-got

 

Solidity ParserError: Expected ';' but got '{'

Using Version 0.6.0 pragma solidity ^0.6.0; contract Test { function sendValue(address payable recipient, uint256 amount) external { (bool success, ) = recipient.call{ value: amount }(...

stackoverflow.com

 

찾아보니 0.5.0 버전에서 이더리움을 보내는 식은달랐다.

address payable targetAddress = ....;

(bool sent, bytes memory data) = targetAddress.call.value(msg.value)("");

이런식으로 바꾸니까 컴파일이 잘 되었다.

728x90
반응형
Comments