Crypto Zombie로 Solidity 처음부터 공부하기 [Lesson 4]

Sungmin Oh·2021년 3월 16일
0

payable 제어자

이더리움에서는 돈(이더), 데이터, 컨트랙트 코드가 모두 이더리움 위에 존재하기 때문에 함수를 실행함과 동시에 컨트랙트에 돈을 지불하도록 하는 것이 가능하다. payable 제어자가 붙은 함수는 이더를 받을 수 있다. 이를 응용해 함수를 실행하기 위해서는 일정 금액을 지불해야 하도록 만들 수도 있다.

contract OnlineStore {
    function buySomething() external payable {
        require(msg.value == 0.001 ether);
        transferThing(msg.sender);
    }
}

위의 코드에서 buySomthing 함수를 호출한 사람이 컨트랙트에 0.01 이더를 송금하지 않으면 transferThing 함수는 실행되지 않는다.
여기서 msg.value는 컨트랙트로 이더가 얼마나 보내졌는지 확인할 수 있는 변수이다.

출금

컨트랙트에 이더를 전송하고 나면 해당 컨트랙트의 이더리움 계좌에 이더가 저장되고 거기에 갇히게 된다. 컨트랙트에서 이더를 인출하는 함수를 만들어서 이더를 나의 계좌로 옮길 수 있다. 이더를 전송하라는 함수는 다음과 같다.

주소.transfer(금액);

transfer 함수가 포함된 함수는 보안성이 중요하므로 onlyOwner 제어자를 포함하는 것이 안전하다.

난수 (Random Numbers)

현재 나의 수준에서 안전하게 완전한 난수를 생성하기는 불가능하다. (더 높은 수준에서 가능한지는 잘 모르겠다.) 다만, 안전하지는 않지만 난수를 생성할 수 있는 방법은 있다. 바로 keccak256 함수를 이용하는 것이다.

uint randNonce = 0;
uint random = uint(keccak256(now, msg.sender, randNonce)) % 100;
randNonce++;
uint random2 = uint(keccak256(now, msg.sender, randNonce)) % 100;

위 예시에서는 시간에 따라 값이 계속 변화는 타임스탬프 값 now, 함수를 호출한 사람에 따라 바뀌는 값 msg.sender, 그리고 매번 다른 랜덤한 값 nonce(논스)를 해시 함수에 넣어서 무작위성을 확보했다. 뒤에 % 100 연산을 했기 때문에 0에서 99 사이의 랜덤한 값을 얻을 수 있게 된다.

이 방법이 완벽하게 안전한 방법이 아닌 이유는 무엇일까? 이더리움에서 컨트랙트의 함수를 실행하면 트랜잭션으로서 네트워크의 노드 하나 혹은 여러 노드에 실행을 알리게 된다. 그 후 네트워크의 노드들은 여러 개의 트랜잭션을 모으고 '작업 증명'이라고 불리는 복잡한 수학 문제를 풀기 위한 시도를 한다. 작업 증명을 성공한 노드는 해당 트랜잭션 모음과 작업 증명을 하나의 블록으로 묶어서 네트워크에 배포하게 된다. 이렇게 한 노드가 작업 증명에 성공하게 되면 다른 노드들은 작업 증명을 풀려는 시도를 멈추고 배포된 블록이 유효한지 검증하게 된다. 만약 유효하다면, 해당 블록을 받아들이고 다음 블록을 풀기 시작하게 된다.

이 원리가 우리의 난수 발생 장치가 안전하지 않은 원인이 된다. 난수 발생기를 이용해 1/2 확률로 2배의 이더를 얻을 수 있는 함수를 만들었다고 가정하자. 악의적인 사용자가 이 함수를 실행하고 있다면, 그 트랜잭션을 자신에게만 알리고 남에게 공유하지 않을 수 있다. 따라서 이 사용자가 1/2 확률로 돈을 잃게 된다면 해당 트랜잭션을 공유하지 않을 수 있다. 그러나 이 사용자가 1/2 확률로 2배의 이더를 얻는 것에 성공하고, 그 다음 블록의 작업증명을 자신이 가장 먼저 풀 때까지 이 과정을 반복하면 (컴퓨팅 자원이 많이 들겠지만) 계속해서 이득을 얻을 수 있다.

블록체인의 코드는 모든 사용자가 열람할 수 있으므로 안전한 난수를 만들어내는 것은 어려운 문제라고 한다.

(내가 이해해서 정리한 내용이 맞는 내용인지 잘 모르겠다. 다만, 이 주제가 내게 상당히 흥미롭게 느껴졌기 때문에 추후에 더 공부해서 추가해보도록 하겠다.)

이 내용은 정보를 공유하기 위함이 아닌 저의 개인적인 공부 기록을 남기기 위함입니다. 따라서 틀린 정보가 있을 수 있으니 유의해서 봐주시면 감사하겠습니다.

profile
ambitious person

0개의 댓글