create account

[Ethereum] Ethernaut 풀이 - 3.Coin Flip by modolee

View this thread on: hive.blogpeakd.comecency.com
· @modolee ·
$0.23
[Ethereum] Ethernaut 풀이 - 3.Coin Flip
![modolee_logo](https://steemitimages.com/DQmWQDjyP5d1RNW3mkCWUkDQ6yh3uDJFUZErPpaKBwKi4gM/iron_modolee.png)
안녕하세요. 개발자 모도리입니다.
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

## 임무 확인
![00_mission.png](https://cdn.steemitimages.com/DQmSbMrjJynM9pm8R6R7iTRD1dmbxz2eXfMqTsfQHY7DLAk/00_mission.png)
* 동전 뒤집기 게임이라고 하네요. 앞면이 나올 지 뒷면이 나올지 예측을 하는 게임입니다.
* 임무 완수 조건은 10번 연속 예측에 성공하는 것입니다.
* 초능력을 써서 하라고 합니다...ㅠㅠ
* 난이도는 총 6단계 중 3단계에 해당합니다.

## Solidity 코드 분석
* 초능력은 모르겠고, 일단 코드를 보겠습니다.
* ![01_source.png](https://cdn.steemitimages.com/DQmT7VGkgTJ9UnAVEWCb1S4s9cjxiS9E5jxQ1D6vvdM8v66/01_source.png)
* **버전 및 상태변수 정의**
* ![02_source_01.png](https://cdn.steemitimages.com/DQmRyjf86KtdpS2bVUDNU13r9z5SRf62WJ641UwusAzA1DU/02_source_01.png)
* Solidity 0.4.18 버전을 기준으로 작성되었습니다.
* CoinFlip 컨트랙트가 정의되어 있습니다.
* 3개의 상태 변수가 있습니다.
  * consecutiveWins : 연속해서 승리한 횟수를 저장하는 변수입니다. public입니다.
  * lastHash : 마지막 실행할 때 사용되었던, hash 값 입니다.
  * FACTOR : hash 값과 함께 사용하여 랜덤한 값을 만들어 낼 때 사용하는 값입니다. 
* **생성자**
* ![03_source_02.png](https://cdn.steemitimages.com/DQmX4q3GDCHSNmD7HbJjChFngQPVA7kTcTQmCXoR5WzyWVD/03_source_02.png)
* 컨트랙트를 생성하면서 연속해서 승리한 횟수를 0으로 초기화합니다.
* **동전 뒤집기 게임 함수**
* ![04_source_03.png](https://cdn.steemitimages.com/DQmQFFAZVfgHt31XY7WWaGe9k12bqMFgjFRHpZYeCLg95vj/04_source_03.png)
* 입력 예측 값(_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 이용하기
* 소스코드를 붙여 넣습니다.
* ![05_remix_source.png](https://cdn.steemitimages.com/DQmPSe8jkKHsaUtp6ice6Lds4CfXJ88MGXJZfdcidn2GSSF/05_remix_source.png)
* 콘솔에서 Instance address를 확인합니다.
* ![06_instance_address.png](https://cdn.steemitimages.com/DQmcyfZtioYUAmtP7TpxrfQz8WCcmeVfjqFsvCQifXqHmsq/06_instance_address.png)
* 해당 주소를 복사해서 Remix의 Load contract from Address 창에 붙여 넣고 At Address 버튼을 눌러주면 해당 컨트랙트를 불러옵니다.
* ![07_deploy.png](https://cdn.steemitimages.com/DQmUXvY9bvgrn8phsg6ebzozzkMSbkVxwBU3MZJHYMSAub1/07_deploy.png)

## 예측을 해 보겠습니다!
* 계속 true만 넣었더니 5번 만에 처음으로 맞췄습니다!!! ㅠㅠ
* ![08_flip_1.png](https://cdn.steemitimages.com/DQmPCECsPAzRauCDuf6taoBc2h5oFY3RYyrC4ZCrZkkuF7f/08_flip_1.png)
* 오! 6번째에도 맞췄습니다. 우주의 기운이 모여진 것 같습니다. 이대로 10번까지 가즈아~~
* ![09_flip_2.png](https://cdn.steemitimages.com/DQmdWf3XY8Pd3r8iY8Dqu3B86RZNQzo7uMBZ58UJmDmv38P/09_flip_2.png)
* 아........... 틀렸어요.
* ![10_flip_0.png](https://cdn.steemitimages.com/DQmNfctVvYMPZ7ywa9S2NWKPLXeLjqdsZRh9DYc9RygRND6/10_flip_0.png)
* 당연히 이렇게 풀라고 낸 문제가 아니겠죠?

## 문제 풀이
* 초능력을 발휘할 수 있는 컨트랙틀 작성합니다.
* ![11_psychic_ability.png](https://cdn.steemitimages.com/DQmbN2BEmYv7ZaqoGyQWyVNHU1GKYCX6cQS7WpKRYWLDB1q/11_psychic_ability.png)
* 어디서 많이 본 코드 같죠?? 맞습니다. CoinFlip 코드를 복사해서 붙여넣고, 조금만 수정했습니다.
* 다른 부분은 크게 2가지 입니다.
  * 생성자에서 target 변수에 배포 된 CoinFlip 컨트랙트 주소를 받아 올 수 있게 합니다. 
  * side를 예측해서 _guess와 비교하는 것이 아니라. 그냥 예측한 그 side 값을 CoinFlip의 flip 함수를 호출하는데 사용합니다.
* 이렇게 하면 정말 초능력이 발휘되어 10번 연속 결과를 맞출 수 있을까요?
* PsychicAbility 컨트랙트를 배포할 때 아까 확인했던 instance address를 넣어서 배포합니다.
* ![12_psychic_ability_deploy.png](https://cdn.steemitimages.com/DQmQV1yiZJD7MamXFT5hVRZX4MjzrgGgBzR13RDBzLPErTZ/12_psychic_ability_deploy.png)
* 이제 시작해 보겠습니다! flip을 실행해 주세요!
* ![12_new_flip.png](https://cdn.steemitimages.com/DQmd8j1kTU37wGzSeJQTPUMLfpzgXR8HhrMGsedRJxSbDEp/12_new_flip.png)
* 1번! ![13_consecutive_win_1.png](https://cdn.steemitimages.com/DQmTfJCg7BgGRJXkBP6aVJEYiigY2Xb5mRVVbN6a4C4mHRK/13_consecutive_win_1.png)
* 2번! ![14_consecutive_win_2.png](https://cdn.steemitimages.com/DQmQDkwAgKAVZy9tzqinsE45EszmmrVEtv4wuX1T2VxNcGD/14_consecutive_win_2.png)
* 중간 중간 숫자가 안 올라가는 경우가 있는데, 이 경우에 트랜잭션 내역을 살펴보면 Out of gas 에러나 나 있는 것을 확인할 수 있습니다.
* ![18_oog.png](https://cdn.steemitimages.com/DQmPmehD3Bj6VJ2J9Mjc6xxRSCpuh6fj8wdLMWrq6KjWMVD/18_oog.png)
* 동일 블록에서 랜덤 값을 뽑지 않게 하려고 작성한 코드 때문에 이런 에러가 발생합니다. 그냥 무시하시고 계속~ 하시면 됩니다.
* ![18_oog_source.png](https://cdn.steemitimages.com/DQmPCzjq4tjVogBW2dKJDHCkm3aQBtuM9uoSdGxxw6rknTu/18_oog_source.png)
* 5번! ![15_consecutive_win_5.png](https://cdn.steemitimages.com/DQmbqGk249xUycvfXzJ8wyp9MBE76wA8pe7m8KpGtycFrfp/15_consecutive_win_5.png)
* 7번! ![16_consecutive_win_7.png](https://cdn.steemitimages.com/DQmbKE9xe8eLioeL1Bayt33QzUs9ANLQRWbhr9ZGmTpP7mz/16_consecutive_win_7.png)
* 9번! ![17_consecutive_win_9.png](https://cdn.steemitimages.com/DQmZYy6ng8rwqaw8G9nBqotTah7TJuMBX3xdSxagmpSFJsS/17_consecutive_win_9.png)
* 10번! ![19_consecutive_win_10.png](https://cdn.steemitimages.com/DQmQGTdcLYJ6AB8efn9juWRPBe5PJ4a6US621yqasjrS38L/19_consecutive_win_10.png)
* 이게 어떻게 가능할까요?
* PsychicAbility 컨트랙트의 flip 함수에서 CoinFlip 컨트랙트의 flip 함수를 부르게 되는데, 이 트랜잭션은 동일 블록에 담기게 됩니다. 그러면 blockhash를 이용해서 난수를 생성하는데, PsychicAbility에서 미리 해당 값을 구한 후 CoinFlip의 flip 함수를 호출한다면 매번 동일한 값이 나오게 될 것입니다.

## 답안 제출
* 콘솔에서도 확인해 보겠습니다.
* ![20_console_10.png](https://cdn.steemitimages.com/DQmSakKphLpziYVxkapchS25zYWPLsr62Strjp3ejaydvry/20_console_10.png)
* Submit instance 버튼을 누릅니다.
* ![submit_button](https://steemitimages.com/0x0/https://cdn.steemitimages.com/DQme3DtJ5HWZD8KAeDQ3hpWwoWJi5XGK7KQAvSzzhGDrZrQ/16_submit_instance.png)
* 임무를 완수했습니다.
* ![21_complete.png](https://cdn.steemitimages.com/DQmQNG38ExkdjBDFsL1imaqnjgWEdURjzzkCYSgbcQze5mW/21_complete.png)

## 말하고자 하는 취약점
* 블록체인 상에서의 난수 생성의 어려움
  * 단순히 블록체인 상에서 얻을 수 있는 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)

오늘은 이것으로 마치겠습니다. 감사합니다.
👍  , , , , , ,
properties (23)
authormodolee
permlinkethereum-ethernaut-3-coin-flip
categorykr-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"}
created2018-06-24 14:34:09
last_update2018-06-24 14:34:09
depth0
children0
last_payout2018-07-01 14:34:09
cashout_time1969-12-31 23:59:59
total_payout_value0.178 HBD
curator_payout_value0.055 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length7,615
author_reputation285,192,678,959
root_title"[Ethereum] Ethernaut 풀이 - 3.Coin Flip"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id62,054,170
net_rshares116,603,419,949
author_curate_reward""
vote details (7)