Solidity - 스마트컨트랙트를 이용한 슬롯머신(확률게임) 만들기 1편

in #dunkpay7 years ago (edited)

Screen Shot 2018-06-06 at 10.33.13 PM.png

우선 결과화면은 다음과 같습니다.

Screen Shot 2018-06-06 at 10.34.30 PM.png

배팅버튼을 클릭하면 메타마스크가 실행되며 승리여부를 알려주게 됩니다.

이곳을 방문하시면 실제로 테스트가 가능합니다.

https://www.dunkpay.com/slot-test/

슬롯머신게임 의 스마트 컨트랙트 소스는 매우 간단합니다.

https://ropsten.etherscan.io/address/0x2f9a2b2977ae4557a8d7d545c48d4c0b67dc3ae7#code

pragma solidity ^0.4.8;

contract SlotMachine {
    
    mapping (address => uint) public playerList; 
    uint256 public contractBalance;
    
    function SlotMachine() public {
    }
    
    function () payable public {
        start();
    }
    
    function start() public payable {
        
        uint256 userBalance = msg.value;
        require(userBalance > 0);
        uint randomValue = random();
        playerList[msg.sender] = randomValue;
        contractBalance = address(this).balance;
            
        if(randomValue > 50)
        {    
            uint256 winBalance = userBalance * 2;
            if(contractBalance < winBalance){
                winBalance = contractBalance;
            }
            msg.sender.transfer(winBalance); 
            contractBalance = address(this).balance;        
        }
    }
    
    function random() view returns (uint8) {
        return uint8(uint256(keccak256(block.timestamp)) % 100) + 1; // 1 ~ 100 (Only for testing.)
    }
}

첫줄에 무명함수는 Fallback 즉, 이더리움이 입금될 때 실행되는 함수를 의미합니다.

payable은 이더리움을 받을 수 있는 함수를 의미합니다.

public 은 외부에서 실행할 수 있는 함수를 의미합니다.

public 변수 playerList, contractBalance는 외부에서 읽을 수 있는 변수를 의미합니다.

random() 함수는 현재시간을 100으로 나누는 함수를 의미합니다.

즉, 사용자가 이 컨트랙트로 ETH를 입금하게 되면 start() 함수가 호출됩니다.

이후, random() 함수가 호출되어 1~100 사이의 난수를 발생시킵니다.

그 값이 50보다 크면 컨트랙트에서 사용자에게 배팅한 금액이 2배가 출금이 됩니다.

클라이언트 구성은 더욱 간단합니다.

클라이언트에서는 단순히 컨트랙트에 입금을 실행합니다.

사용자가 입금을 하게되면 Hash값을 생성하게 됩니다.

이후에 클라이언트에서 컨트랙트를 읽어서 당첨 여부를 확인하여 표시하면 됩니다.

이 소스에 문제는 없을까요?

random() 함수는 보안상 큰 이슈를 가지고 있습니다.

스마트컨트랙트의 장점 또는 단점이 그대로 나타나는 부분입니다.

사용자는 random()함수의 원리를 그대로 볼 수 있습니다.

본 예제에서는 timestamp 값을 사용하지만 hash 값을 사용하던 sha값을 사용하던지 동일합니다.

특히 사용자가 블럭을 임의로 조작할 수 있는 마이너 라면 문제가 커집니다.

즉, 연습에서는 사용할 수 있는 Random() 이지만 상용에서는 절대로 사용해서는 안됩니다.

1편에서는 스마트컨트랙트의 동작원리를 이해하는 수준에서 글을 마치겠습니다.

2편에서는 random()함수를 상용 프로그램에서 쓰려면 어떻해야 하는지 얘기해 보겠습니다.

Reference:
https://github.com/josex2r/jQuery-SlotMachine
https://medium.com/@promentol/lottery-smart-contract-can-we-generate-random-numbers-in-solidity-4f586a152b27
https://ethereum.stackexchange.com/questions/41463/a-possible-method-for-safe-random-number-in-lotteries?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
https://ethereum.stackexchange.com/questions/191/how-can-i-securely-generate-a-random-number-in-my-smart-contract?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

Sort:  

궁금했던 사항인데~~ 감사합니다~~