그리고 그 값이 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 등을 이용해 난수 생성 시드로 사용하게 된다면, 위와 같이 예측이 가능합니다.
그래서 난수 생성을 위해서는 외부의 오라클을 이용해서 생성한다던지, 조금 복잡한 방법으로 난수를 생성해서 사용해야 안전합니다.