Decentralization

Solidity로 복권 스마트 컨트랙트 구현하기

이영훈닷컴 2025. 3. 15. 19:22
728x90

오늘은 Solidity를 사용하여 간단한 복권(Lottery) 스마트 컨트랙트를 작성해 보았다. 이 컨트랙트는 참가자들이 일정 금액 이상의 Ether를 입금하면 자동으로 복권에 등록되고, 이후 관리자가 무작위로 승자를 선정하여 상금을 지급하는 기능을 수행한다.

코드 분석

pragma solidity >=0.4.22 <0.6.0;

contract Lottery {
    address public manager; // 관리자 주소
    address[] public players; // 참가자 목록

    // 계약을 배포할 때 실행되는 생성자 함수
    constructor() public {
        manager = msg.sender; // 계약을 배포한 계정을 관리자(manager)로 설정
    }

    // 복권 참가 함수
    function enter() public payable {
        require(msg.value > .01 ether); // 최소 0.01 ETH 이상을 보내야 참가 가능
        players.push(msg.sender); // 참가자의 주소를 배열에 추가
    }

    // 무작위 숫자를 생성하는 함수 (보안적으로 안전하지 않음)
    function random() private view returns (uint) {
        return uint(keccak256(abi.encodePacked(block.difficulty, now, players)));
    }

    // 승자를 결정하고 상금을 지급하는 함수
    function pickWinner() public restricted {
        uint index = random() % players.length; // 무작위로 인덱스 선택
        address winner = players[index]; // 승자 주소
        address(uint160(winner)).transfer(address(this).balance); // 계약 잔액을 승자에게 전송
        players = new address[](0); // 참가자 목록 초기화
    }

    // 현재 참가자 목록을 반환하는 함수
    function getPlayers() public view returns (address[] memory) { 
        return players;
    }

    // 관리자만 실행할 수 있도록 제한하는 수정자(modifier)
    modifier restricted() {
        require(msg.sender == manager); // 호출자가 관리자여야 함
        _;
    }
}

핵심 기능

  1. 복권 참가 (enter): 사용자는 0.01 ETH 이상을 입금해야 복권에 참가할 수 있다.
  2. 무작위 승자 선정 (pickWinner): 관리자가 pickWinner를 실행하면 random() 함수를 통해 무작위 승자를 선택하고 잔액을 전송한다.
  3. 관리자 권한 (restricted): 특정 기능(예: 승자 선정)은 관리자만 실행할 수 있도록 제한한다.

개선할 점

  • random() 함수는 블록 난이도 및 현재 시간을 이용한 해시 기반의 난수를 생성하는데, 이는 보안적으로 취약하다. 실제 배포 시에는 Chainlink VRF와 같은 안전한 난수 생성 방법을 사용하는 것이 좋다.

마무리

이번 학습을 통해 Solidity에서 간단한 복권 스마트 컨트랙트를 구현하는 방법을 배웠다. 다음에는 좀 더 보안이 강화된 난수 생성 방법을 적용해 보고 싶다.

728x90