스마트컨트랙트 송금 - seumateukeonteulaegteu song-geum

솔리디티

이더리움 송금 스마트컨트랙트 코드(이더잔액: 주소.balance, msg.value:송금액,msg.sender:보내는자)

청어와물메기 2022. 2. 26. 01:52

주소.balance    주소의 현재 갖고 있는 이더의 잔액

( msg.value       송금액을 의미한다 달라! )

msg.sender      스마트컨트랙을 사용하는 주체, 보내는 자

스마트컨트랙트 송금 - seumateukeonteulaegteu song-geum
주고 받는거 해봄

이더보내는 스마트컨트랙트 코드  (출처: https://github.com/D-One0914/BreakingSolidityBasic/blob/main/lec33.sol

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.5.0 < 0.9.0;

//주소.balance
//주소의 현재 갖고 있는 이더의 잔액을 의미함.  //  msg.value는 송금액을 의미한다 달라!

// msg.sender
// msg.sender는 스마트컨트랙을 사용하는 주체라고 볼 수 있다 
// 앞으로 설명할 call 과 delegate call에서 주요 내용이니 관심잇게 봐라

contract MobileBanking{
    event SendInfo(address _msgSender, uint256 _currentValue);
    event MyCurrentValue(address _msgSender,uint256 _value);
    event CurrentValueOfSomeone(address _msgSender, address _to, uint256 _value);


   //이더를 보낼라면 
   //을 넣을 줄 알았지만!!! 보내는 주소, 받을 사람 주소만 있음 되는구나.. 이더를 받아야되기때문에 payable써준다 //함수전체도 이더보는거라 payable써줌
    function sendEther(address payable _to) public payable {
        require (msg.sender.balance >= msg.value , "your balance is not enough");
        //트랜스퍼 함수를 통해 이더 송금
        _to.transfer(msg.value);
        //보낸 나의 주소, 내 잔고
         emit SendInfo(msg.sender, (msg.sender).balance);
    }
    //그냥 현재 잔고확인 함수인듯?
    function checkValueNow() public{
        emit MyCurrentValue(msg.sender, (msg.sender).balance);
    }
    //어떤 계정의 잔고 확인하고 싶을때, 확인하고 싶은 주소 넣기
    function checkUserValue(address _to) public{
       emit CurrentValueOfSomeone(msg.sender, _to, _to.balance);
    }

}

이더송금하기 

sendEther함수 사용

1. 코드를 컴파일한다

스마트컨트랙트 송금 - seumateukeonteulaegteu song-geum

또는 우클릭해서 원하는 코드 컴파일.

스마트컨트랙트 송금 - seumateukeonteulaegteu song-geum

2. ACCOUNT 에서 현재 내 계정주소 확인하고  Deploy 배포한다.

스마트컨트랙트 송금 - seumateukeonteulaegteu song-geum
1로 표시한거 &gt;&nbsp; 계정주소 넣을 부분 2로 표시한거 &gt; 이더금액 넣는 부분 3로 표시한거 &gt;&nbsp; Deploy 배포 4로 표시한거 &gt; 함수사용하는 부분 5로 표시한거 &gt;&nbsp; 내역&nbsp; &nbsp; &nbsp; &nbsp;(숫자 이거 순서 아님주의!!!)

3. 함수 실행

Deploy했으면

Deployed Contracts 가 생성될거다.

함수에 값넣어서 이더송금할 수 있다.

sendEther는 송금받을 주소를 넣는 곳이다.

Account에서 보낼 주소를 골라서 복사해서 sendEther에 넣는다.

그리고 Account에서 다시 내 계정주소로 와있는지 확인한 다음에

보낼 이더 값을 Value에 넣는다. Ether로 되어있는지 확인한다.

그리고 sendEther를 눌러 송금함수를 실행한다. 

잘보내졌으면 저렇게 내역이 뜬다.

ACCOUNT 눌러서 남은 잔고와 받은 잔고를 맨위에 사진처럼 확인할 수 있다. 

현재계정 잔고확인하기

checkValueNow함수 사용

스마트컨트랙트 송금 - seumateukeonteulaegteu song-geum
스마트컨트랙트 송금 - seumateukeonteulaegteu song-geum

특정계정의 잔고 확인하기 

checkUserValue함수

에 _to 확인할 계정주소 넣고

원래 보낼 주소로 되어있는지 ACCOUNT확인하고

함수 실행하면

_msgSender 주체

_to 확인한 계정

_value 잔고

스마트컨트랙트 송금 - seumateukeonteulaegteu song-geum

이더리움 스마트 컨트랙으로 입금받기가 어려운 이유

Photo by JESHOOTS.COM on Unsplash

이더리움의 차별점은 스마트 컨트랙을 이용하여 블록체인 위에서 다양한 어플리케이션을 만들 수 있다는 점이다. 하지만 스마트 컨트랙 때문에 오히려 간단한 일이 복잡해지기도 한다. 일례로, 이더리움에서 특정한 주소에 얼마의 ETH가 입금되었는지 알아내는 일은 무척 어려운 일이다. 스마트 컨트랙이 실제로 어떤 일을 하는지 실행을 시켜보지 않고 알아낼 방법이 없기 때문이다.

블록체인 내부와 외부를 연동해야 하는 이유

스마트 컨트랙은 블록체인에 저장된 데이터만을 읽고 쓴다. 블록체인의 데이터만을 사용해서도 유용한 어플리케이션을 만들 수 있다. 다중 서명 지갑과 ERC-20, ERC-721 토큰과 같은 스마트 컨트랙은 블록 체인에 저장된 데이터만을 읽고 쓰지만 유용한 어플리케이션이다. 하지만 대부분의 어플리케이션은 체인 외부와 연결되어야 한다.

대표적으로 거래소가 그 예시이다. 거래소는 ETH를 받아서 현금으로 바꾸거나 현금으로 ETH를 살 수 있다. 체인에서 입금받은 내용을 확인한 뒤 은행의 계좌로 돈을 보내주거나, 반대로 계좌로 받은 돈을 확인한 뒤 ETH를 송금해준다.

스마트 컨트랙으로 할 수 있는 일임에도 체인 외부에서 하는 게 더 나을 수도 있다. 스마트 컨트랙의 비용이 비싸기 때문이다. 스마트 컨트랙 호출은 네트워크의 모든 노드가 계산한다. 2019년 6월 현재 약 8,000개 노드가 이더리움 네트워크에 참여한다. 즉 한 번 스마트 컨트랙을 호출하면 8,000번 실행된다는 뜻이다. 그래서 이런 작업은 비용을 절감하기 위해 체인 외부에서 실행한다.

하지만 체인 내부와 외부를 연결하는 일은 생각보다 쉽지 않다.

이더리움에서 특정한 계좌에 들어온 ETH를 읽는 방법

간혹, ETH를 입금할 때 스마트 컨트랙 지갑의 이용을 금지하는 거래소들이 있다. 대부분 거래소는 유저마다 고유한 이더리움 주소를 만들어주며, 유저가 해당 주소로 ETH를 입금하면 이를 확인한다. 계좌에 들어있는 ETH를 확인하는 건 간단한데 왜 스마트 컨트랙 입금을 거절하는 걸까?

특정 계좌에 돈이 입금되는 트랜잭션은 두 종류가 있다. 하나는 다른 Account에 ETH를 보내는 트랜잭션이고, 다른 하나는 스마트 컨트랙을 호출하는 트랜잭션이다. ETH를 보내는 트랜잭션은 트랜잭션에 적혀있는 From, To, Value를 읽어서 누가 얼마를 보내는지 쉽게 알 수 있다. 이것이 보통 우리가 생각하는 쉬운 잔액 확인 방법이다. 반면 스마트 컨트랙을 호출하는 트랜잭션은 어떤 계좌에 얼마의 돈을 넣었는지 알 방법이 없다. 트랜잭션 정보에 적혀있지 않으며, 이더리움 SDK에도 해당 정보를 가져오는 API가 존재하지 않기 때문이다.

세 가지의 방법으로 이 문제를 해결할 수 있다.

가장 쉬운 방법은 유저에게 직접 입금만 해달라고 부탁하고, 스마트 컨트랙을 통한 입금은 일절 받지 않는 것이다. 초창기 거래소가 이렇게 운영했으며, 지금도 직접 입금한 금액만 처리해주는 거래소가 꽤 남아있다.

(Huobi 거래소는 스마트 컨트랙 입금을 받지 않는다.)

다른 방법으로는 블록마다 계좌 잔고를 확인하는 방법이 있다. 이전 블록에서 계산한 잔고와 현재 블록에서 계산한 잔고의 차이로 얼마의 ETH가 입금되었는지 확인하는 것이다. 하지만 해당 금액이 어떤 트랜잭션을 통해서 들어왔는지 알 수 없으므로 거래의 추적이 어려워 문제가 생겼을 시 원인파악이 힘들다. 블록마다 관리하는 모든 계좌의 잔고를 확인해야 하므로, 시간이 오래 걸리는 단점도 있다.

또 다른 방법은 Go Ethereum(link)과 Parity(link) 구현체가 제공하는 trace API를 사용하는 방법이다. 각 구현체는 자신만의 방법으로 블록에 포함된 트랜잭션이 세부적으로 어떤 일을 했는지 추적하는 API를 제공한다. trace API를 사용하면, 각 트랜잭션이 어떤 스테이트를 수정했는지 EVM 인스트럭션 단위로 모든 걸 알 수 있다. 이러한 방법으로 스마트 컨트랙이 어떤 계좌에 얼마를 입금했는지도 추적할 수 있다. API 사용이 복잡하며 반드시 풀 노드를 운영해야 한다는 게 단점이다. 또한 공식 API가 아니므로 구현에 따라 API가 바뀔 수 있다.

결론

이상으로 이더리움에서 스마트 컨트랙을 이용했을 때 특정한 계좌에 얼마가 입금되었는지를 확인하는 세 가지 방법을 알아보았다. 내 계좌에 누가 얼마를 언제 넣었는지 정보는 가장 기본적인 방법이지만 쉽고 완벽한 정답은 없다. 각 어플리케이션에서 요구사항에 맞는 방법을 선택하면 된다.