Lottery DApp 개발 - Lottery contract 개발[4]

Distribute 함수설계 & isMath함수 구현 및 테스트

Distribute 함수설계

Bet함수 사용 후 큐에 저장된 베팅 정보를 해결하는 Distribute함수를 설계 해보자

function distribute() public {
        // head 부터 tail 까지 도는 loop
        uint256 cur;
        BetInfo memory b;
        
        for(cur = _head; cur < _tail; cur++){
            b = _bets[cur];
	
	//현재 블록과 결과확인 블록의 hash 같을 경우 = win
	//현재 블록과 결과확인 블록의 hash  글자만 같을 경우 = draw
	//현재 블록과 결과확인 블록의 hash 다를 경우 = fail
    }

이 때, 베팅한 hash와 +3 블럭의 hash가 같은지 비교해주는 함수를 따로 작성해준다.

isMatch함수를 구현해 보면

/**
    * @dev 베팅글자와 정답을 확인
    * @param challenges 베팅 글자
    * @param answer 블럭해쉬
    * @return 정답결과
    */
    function isMatch(byte challenges, bytes32 answer) public pure returns(BettingResult){
        //challenges 0xab, answer 0xab....... 32bytes
        byte c1 = challenges;
        byte c2 = challenges;
        byte a1 = answer[0];
        byte a2 = answer[0];

        c1 = c1 >> 4;
        c1 = c1 << 4;
        a1 = a1 >> 4;
        a1 = a1 << 4;

        c2 = c2 << 4;
        c2 = c2 >> 4;
        a2 = a2 << 4;
        a2 = a2 >> 4;

        if(a1 == c1 && a2 == c2)
            return BettingResult.win;
        if(a1 == c1 || a2 == c2)
            return BettingResult.draw;
        return BettingResult.fail;
    }

shift를 이용해서 값을 한 비트씩 비교해준다.
0xab » 4 = 0x0a / 0x0a « 4 = 0xa0

isMatch 함수의 리턴 값은 BettingResult 로 해주었으니 변수를 선언해 준다.

enum BettingResult {fail, win, draw}

fail부터 0, win은 1, draw는 2로 인식하게 된다. 잘 기억해 두자 test할 때 비교값으로 넣어준다

또 필요한 함수가 뭐가 있을까 생각해보자
현재 블록의 상태를 구해서 에러가 나는 상황인지 체크해주는 함수가 필요하다.

  1. 현재 가리키고 있는 블록이 내가 베팅한 블록보다 뒤에 있어야 답 체크가 가능하다.
  2. 블록의 최대치는 256이므로 256을 넘으면 에러처리
    이걸 생각하고 if문을 생각해 보면
    function getBlockStatus(uint256 answerBlockNumber) internal view returns(BlockStatus) {
         if(block.number > answerBlockNumber && block.number < BLOCK_LIMIT + answerBlockNumber){
             return BlockStatus.Checkable;
         }
         if(block.number <= answerBlockNumber){
             return BlockStatus.NotRevealed;
         }
         if(block.number >= answerBlockNumber + BLOCK_LIMIT){
             return BlockStatus.BlockLimitPassed;
         }
         return BlockStatus.BlockLimitPassed;
     }
    


    여기서 return값이 BlockStatus이므로 변수로 선언해준다.

    enum BlockStatus {Checkable, NotRevealed, BlockLimitPassed}

checkable은 매핑이 완료 되 답 비교가 가능한 것을 나타내고 notrevealed는 현재 블럭이 베팅을 건 블럭보다 앞에 있으면 매핑이 안되 답을 확인할 수 없는 것을 나타내고, BlockLimitPassed는 limit를 넘겼을 때 답을 구할 수 없는 것을 나타내는 것이다.
지금까지 작성한 함수를 이용해 distribute함수를 작성해보자!

function distribute() public {
        // head 부터 tail 까지 도는 loop
        uint256 cur;
        BetInfo memory b;
        BlockStatus currentBlockStatus;
        for(cur = _head; cur < _tail; cur++){
            b = _bets[cur];
            currentBlockStatus = getBlockStatus(b.answerBlockNumber);

            if(currentBlockStatus == BlockStatus.Checkable){
                //win bettor gets pot

                //fail bettor's momey goes pot

                //하나만 맞췄을 경우 refund bettor's money
            }
            if(currentBlockStatus == BlockStatus.NotRevealed){
                break;
            }
            if(currentBlockStatus == BlockStatus.BlockLimitPassed){
                
            }
            popBet(cur);
        }
    }

sMath함수 구현 및 테스트

lotery.test.js 파일에

describe.only('isMatch', function (){
        let blockHash ='0xab66ec4675534645e7f83e0c9d369356db51a012a0746e2f0e82df38a345b38b'
	
        it('should be BettingResult.win when two characters match', async () =>{
            let matchingResult = await lotery.isMatch('0xab', blockHash);

            assert.equal(matchingResult, 1);
        })
        it('should be BettingResult.draw when two characters match', async () =>{
            let matchingResult = await lotery.isMatch('0xac', blockHash);

            assert.equal(matchingResult, 2);
        })
        it('should be BettingResult.fail when two characters match', async () =>{
            let matchingResult = await lotery.isMatch('0xcd', blockHash);

            assert.equal(matchingResult, 0);
        })
    });

이 때 Blockhash값은 web3.eth.getBlock(0) 해서 아무값이나 넣어주었다.
처음에 이곳에서 오류가 낫었다 이유는 BettingResult를 선언해 줄 때 win, fail, draw 순으로 선언 해 주고는 강의 그대로 따라해서 넣었더니 당연이 일치하지 않으므로 에러가 났었다. 그래서 고쳐 준 후 isMatch 함수 return 부분을 다시 입력해주고 truffle test test/lotery.test.js를 실행하니

2020

맨 위로 이동 ↑