 안녕하세요. 개발자 모도리입니다. Ethernaut 문제 풀이 시리즈를 계속 진행해 보려고 합니다. 이번에는 Level 3 문제를 풀어보겠습니다. 지난 게시물은 아래를 확인해 주세요. * [Ethernaut 소개](https://steemit.com/kr-dev/@modolee/ethereum-ethernaut) * [Ethernaut 풀이 - 0.Hello Ethenaut](https://steemit.com/kr-dev/@modolee/ethereum-ethernaut-0-hello-ethenaut) * [Ethernaut 풀이 - 1.Fallback](https://steemit.com/kr-dev/@modolee/ethereum-ethernaut-1-fallback) * [Ethernaut 풀이 - 2.Fallout](https://steemit.com/kr-dev/@modolee/ethereum-ethernaut-2-fallout) --- # 3. Coin Flip ## 임무 확인  * 동전 뒤집기 게임이라고 하네요. 앞면이 나올 지 뒷면이 나올지 예측을 하는 게임입니다. * 임무 완수 조건은 10번 연속 예측에 성공하는 것입니다. * 초능력을 써서 하라고 합니다...ㅠㅠ * 난이도는 총 6단계 중 3단계에 해당합니다. ## Solidity 코드 분석 * 초능력은 모르겠고, 일단 코드를 보겠습니다. *  * **버전 및 상태변수 정의** *  * Solidity 0.4.18 버전을 기준으로 작성되었습니다. * CoinFlip 컨트랙트가 정의되어 있습니다. * 3개의 상태 변수가 있습니다. * consecutiveWins : 연속해서 승리한 횟수를 저장하는 변수입니다. public입니다. * lastHash : 마지막 실행할 때 사용되었던, hash 값 입니다. * FACTOR : hash 값과 함께 사용하여 랜덤한 값을 만들어 낼 때 사용하는 값입니다. * **생성자** *  * 컨트랙트를 생성하면서 연속해서 승리한 횟수를 0으로 초기화합니다. * **동전 뒤집기 게임 함수** *  * 입력 예측 값(_guess)으로 앞면/뒷면(true/false) 값을 받고, 실제 랜덤하게 생성한 앞면/뒷면 결과와 비교해서 같으면 true, 다르면 false 값을 반환하는 함수입니다. * blockValue는 solidity 내장 함수인 block.blockhash 함수를 이용해서 한 개 전 블록(block.number - 1)의 blockhash 값을 가져옵니다. * [block.blockhash(uint blockNumber) returns (bytes32)]((https://solidity.readthedocs.io/en/v0.4.24/units-and-global-variables.html?highlight=block.blockhash#block-and-transaction-properties)) : 블록번호를 넣었을 때 해당 블록의 hash 값을 반환하는 함수입니다. 0.4.22 버전에서 deprecated 되었고, blockhash로 대체 되었습니다. * [block.number (uint)](https://solidity.readthedocs.io/en/v0.4.24/units-and-global-variables.html?highlight=block.number#block-and-transaction-properties) : 현재 블록번호를 담고 있는 변수입니다. * blockVale의 값과 lastHash의 값이 같은 경우 (이전 게임에서 사용되었던 것과 같은 랜덤 시드를 사용할 경우) revert 시킵니다. * [revert()](https://solidity.readthedocs.io/en/v0.4.24/units-and-global-variables.html?highlight=revert#error-handling) : 실행을 중단 시키고, 상태는 실행 전으로 돌립니다. * lastHash에 새로 생성 된 blockValue를 저장합니다. * coinFlip에는 아까 구한 blockValue를 FACTOR로 나눈 값을 저장합니다. * 그리고 그 값이 1이면 side 변수에 true를 저장하고 그렇지 않으면 false를 저장합니다. * side와 _guess가 같으면 consecutiveWins에 1을 더하고 true를 반환하고, 그렇지 않으면 다시 처음부터 카운팅하도록 consecutiveWins를 0으로 만들고 false를 반환합니다. ## 새로운 인스턴스 생성 * **Get new instance** 버튼을 눌러서 임무를 시작합니다. ## Remix 이용하기 * 소스코드를 붙여 넣습니다. *  * 콘솔에서 Instance address를 확인합니다. *  * 해당 주소를 복사해서 Remix의 Load contract from Address 창에 붙여 넣고 At Address 버튼을 눌러주면 해당 컨트랙트를 불러옵니다. *  ## 예측을 해 보겠습니다! * 계속 true만 넣었더니 5번 만에 처음으로 맞췄습니다!!! ㅠㅠ *  * 오! 6번째에도 맞췄습니다. 우주의 기운이 모여진 것 같습니다. 이대로 10번까지 가즈아~~ *  * 아........... 틀렸어요. *  * 당연히 이렇게 풀라고 낸 문제가 아니겠죠? ## 문제 풀이 * 초능력을 발휘할 수 있는 컨트랙틀 작성합니다. *  * 어디서 많이 본 코드 같죠?? 맞습니다. CoinFlip 코드를 복사해서 붙여넣고, 조금만 수정했습니다. * 다른 부분은 크게 2가지 입니다. * 생성자에서 target 변수에 배포 된 CoinFlip 컨트랙트 주소를 받아 올 수 있게 합니다. * side를 예측해서 _guess와 비교하는 것이 아니라. 그냥 예측한 그 side 값을 CoinFlip의 flip 함수를 호출하는데 사용합니다. * 이렇게 하면 정말 초능력이 발휘되어 10번 연속 결과를 맞출 수 있을까요? * PsychicAbility 컨트랙트를 배포할 때 아까 확인했던 instance address를 넣어서 배포합니다. *  * 이제 시작해 보겠습니다! flip을 실행해 주세요! *  * 1번!  * 2번!  * 중간 중간 숫자가 안 올라가는 경우가 있는데, 이 경우에 트랜잭션 내역을 살펴보면 Out of gas 에러나 나 있는 것을 확인할 수 있습니다. *  * 동일 블록에서 랜덤 값을 뽑지 않게 하려고 작성한 코드 때문에 이런 에러가 발생합니다. 그냥 무시하시고 계속~ 하시면 됩니다. *  * 5번!  * 7번!  * 9번!  * 10번!  * 이게 어떻게 가능할까요? * PsychicAbility 컨트랙트의 flip 함수에서 CoinFlip 컨트랙트의 flip 함수를 부르게 되는데, 이 트랜잭션은 동일 블록에 담기게 됩니다. 그러면 blockhash를 이용해서 난수를 생성하는데, PsychicAbility에서 미리 해당 값을 구한 후 CoinFlip의 flip 함수를 호출한다면 매번 동일한 값이 나오게 될 것입니다. ## 답안 제출 * 콘솔에서도 확인해 보겠습니다. *  * Submit instance 버튼을 누릅니다. *  * 임무를 완수했습니다. *  ## 말하고자 하는 취약점 * 블록체인 상에서의 난수 생성의 어려움 * 단순히 블록체인 상에서 얻을 수 있는 blockhash, timestamp 등을 이용해 난수 생성 시드로 사용하게 된다면, 위와 같이 예측이 가능합니다. * 그래서 난수 생성을 위해서는 외부의 오라클을 이용해서 생성한다던지, 조금 복잡한 방법으로 난수를 생성해서 사용해야 안전합니다. * 자세한 내용은 아래 글들을 참고해 주세요. * [그럼 이더리움에서는 어떻게 난수를 안전하게 만들어낼 수 있을까?](https://github.com/bear2u/til/blob/master/blockchain/zombies/zombie4.md#%EA%B7%B8%EB%9F%BC-%EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80%EC%97%90%EC%84%9C%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%82%9C%EC%88%98%EB%A5%BC-%EC%95%88%EC%A0%84%ED%95%98%EA%B2%8C-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%82%BC-%EC%88%98-%EC%9E%88%EC%9D%84%EA%B9%8C--) * [Predicting Random Numbers in Ethereum Smart Contracts](https://blog.positive.com/predicting-random-numbers-in-ethereum-smart-contracts-e5358c6b8620) * [How can I securely generate a random number in my smart contract?](https://ethereum.stackexchange.com/questions/191/how-can-i-securely-generate-a-random-number-in-my-smart-contract) 오늘은 이것으로 마치겠습니다. 감사합니다.
author | modolee |
---|---|
permlink | ethereum-ethernaut-3-coin-flip |
category | kr-dev |
json_metadata | {"tags":["kr-dev","kr","ethereum","solidity","ethernaut"],"image":["https://steemitimages.com/DQmWQDjyP5d1RNW3mkCWUkDQ6yh3uDJFUZErPpaKBwKi4gM/iron_modolee.png","https://cdn.steemitimages.com/DQmSbMrjJynM9pm8R6R7iTRD1dmbxz2eXfMqTsfQHY7DLAk/00_mission.png","https://cdn.steemitimages.com/DQmT7VGkgTJ9UnAVEWCb1S4s9cjxiS9E5jxQ1D6vvdM8v66/01_source.png","https://cdn.steemitimages.com/DQmRyjf86KtdpS2bVUDNU13r9z5SRf62WJ641UwusAzA1DU/02_source_01.png","https://cdn.steemitimages.com/DQmX4q3GDCHSNmD7HbJjChFngQPVA7kTcTQmCXoR5WzyWVD/03_source_02.png","https://cdn.steemitimages.com/DQmQFFAZVfgHt31XY7WWaGe9k12bqMFgjFRHpZYeCLg95vj/04_source_03.png","https://cdn.steemitimages.com/DQmPSe8jkKHsaUtp6ice6Lds4CfXJ88MGXJZfdcidn2GSSF/05_remix_source.png","https://cdn.steemitimages.com/DQmcyfZtioYUAmtP7TpxrfQz8WCcmeVfjqFsvCQifXqHmsq/06_instance_address.png","https://cdn.steemitimages.com/DQmUXvY9bvgrn8phsg6ebzozzkMSbkVxwBU3MZJHYMSAub1/07_deploy.png","https://cdn.steemitimages.com/DQmPCECsPAzRauCDuf6taoBc2h5oFY3RYyrC4ZCrZkkuF7f/08_flip_1.png","https://cdn.steemitimages.com/DQmdWf3XY8Pd3r8iY8Dqu3B86RZNQzo7uMBZ58UJmDmv38P/09_flip_2.png","https://cdn.steemitimages.com/DQmNfctVvYMPZ7ywa9S2NWKPLXeLjqdsZRh9DYc9RygRND6/10_flip_0.png","https://cdn.steemitimages.com/DQmbN2BEmYv7ZaqoGyQWyVNHU1GKYCX6cQS7WpKRYWLDB1q/11_psychic_ability.png","https://cdn.steemitimages.com/DQmQV1yiZJD7MamXFT5hVRZX4MjzrgGgBzR13RDBzLPErTZ/12_psychic_ability_deploy.png","https://cdn.steemitimages.com/DQmd8j1kTU37wGzSeJQTPUMLfpzgXR8HhrMGsedRJxSbDEp/12_new_flip.png","https://cdn.steemitimages.com/DQmTfJCg7BgGRJXkBP6aVJEYiigY2Xb5mRVVbN6a4C4mHRK/13_consecutive_win_1.png","https://cdn.steemitimages.com/DQmQDkwAgKAVZy9tzqinsE45EszmmrVEtv4wuX1T2VxNcGD/14_consecutive_win_2.png","https://cdn.steemitimages.com/DQmPmehD3Bj6VJ2J9Mjc6xxRSCpuh6fj8wdLMWrq6KjWMVD/18_oog.png","https://cdn.steemitimages.com/DQmPCzjq4tjVogBW2dKJDHCkm3aQBtuM9uoSdGxxw6rknTu/18_oog_source.png","https://cdn.steemitimages.com/DQmbqGk249xUycvfXzJ8wyp9MBE76wA8pe7m8KpGtycFrfp/15_consecutive_win_5.png","https://cdn.steemitimages.com/DQmbKE9xe8eLioeL1Bayt33QzUs9ANLQRWbhr9ZGmTpP7mz/16_consecutive_win_7.png","https://cdn.steemitimages.com/DQmZYy6ng8rwqaw8G9nBqotTah7TJuMBX3xdSxagmpSFJsS/17_consecutive_win_9.png","https://cdn.steemitimages.com/DQmQGTdcLYJ6AB8efn9juWRPBe5PJ4a6US621yqasjrS38L/19_consecutive_win_10.png","https://cdn.steemitimages.com/DQmSakKphLpziYVxkapchS25zYWPLsr62Strjp3ejaydvry/20_console_10.png","https://steemitimages.com/0x0/https://cdn.steemitimages.com/DQme3DtJ5HWZD8KAeDQ3hpWwoWJi5XGK7KQAvSzzhGDrZrQ/16_submit_instance.png","https://cdn.steemitimages.com/DQmQNG38ExkdjBDFsL1imaqnjgWEdURjzzkCYSgbcQze5mW/21_complete.png"],"links":["https://steemit.com/kr-dev/@modolee/ethereum-ethernaut","https://steemit.com/kr-dev/@modolee/ethereum-ethernaut-0-hello-ethenaut","https://steemit.com/kr-dev/@modolee/ethereum-ethernaut-1-fallback","https://steemit.com/kr-dev/@modolee/ethereum-ethernaut-2-fallout","(https://solidity.readthedocs.io/en/v0.4.24/units-and-global-variables.html?highlight=block.blockhash#block-and-transaction-properties)","https://solidity.readthedocs.io/en/v0.4.24/units-and-global-variables.html?highlight=block.number#block-and-transaction-properties","https://solidity.readthedocs.io/en/v0.4.24/units-and-global-variables.html?highlight=revert#error-handling","https://github.com/bear2u/til/blob/master/blockchain/zombies/zombie4.md#%EA%B7%B8%EB%9F%BC-%EC%9D%B4%EB%8D%94%EB%A6%AC%EC%9B%80%EC%97%90%EC%84%9C%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%82%9C%EC%88%98%EB%A5%BC-%EC%95%88%EC%A0%84%ED%95%98%EA%B2%8C-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%82%BC-%EC%88%98-%EC%9E%88%EC%9D%84%EA%B9%8C--","https://blog.positive.com/predicting-random-numbers-in-ethereum-smart-contracts-e5358c6b8620","https://ethereum.stackexchange.com/questions/191/how-can-i-securely-generate-a-random-number-in-my-smart-contract"],"app":"steemit/0.1","format":"markdown"} |
created | 2018-06-24 14:34:09 |
last_update | 2018-06-24 14:34:09 |
depth | 0 |
children | 0 |
last_payout | 2018-07-01 14:34:09 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.178 HBD |
curator_payout_value | 0.055 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 7,615 |
author_reputation | 285,192,678,959 |
root_title | "[Ethereum] Ethernaut 풀이 - 3.Coin Flip" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 62,054,170 |
net_rshares | 116,603,419,949 |
author_curate_reward | "" |
voter | weight | wgt% | rshares | pct | time |
---|---|---|---|---|---|
hr1 | 0 | 52,798,597,293 | 0.02% | ||
interestree | 0 | 108,439,985 | 100% | ||
brainstormot | 0 | 33,831,674,026 | 100% | ||
mishana | 0 | 13,915,007,941 | 60% | ||
creamer7 | 0 | 12,412,246,262 | 100% | ||
minebuu | 0 | 610,701,273 | 100% | ||
dmgpol09 | 0 | 2,926,753,169 | 8% |