DEV Community

bin2chen
bin2chen

Posted on

Ethernaut系列-Level 18(MagicNum)

LEVEL 18 (MagicNum):

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

contract MagicNum {

  address public solver;

  constructor() public {}

  function setSolver(address _solver) public {
    solver = _solver;
  }

  /*
    ____________/\\\_______/\\\\\\\\\_____        
     __________/\\\\\_____/\\\///////\\\___       
      ________/\\\/\\\____\///______\//\\\__      
       ______/\\\/\/\\\______________/\\\/___     
        ____/\\\/__\/\\\___________/\\\//_____    
         __/\\\\\\\\\\\\\\\\_____/\\\//________   
          _\///////////\\\//____/\\\/___________  
           ___________\/\\\_____/\\\\\\\\\\\\\\\_ 
            ___________\///_____\///////////////__
  */
}
Enter fullscreen mode Exit fullscreen mode

通关要求

写个合约,设置为solver
合约要求:
1.调用合约的whatIsTheMeaningOfLife()方法返回一个代表生命意思的答案(科幻梗数字42)
2.合约的字节码要足够小,extcodesize <=10

要点

1.了解yul编码(或以太坊的opcodes)
https://docs.soliditylang.org/en/v0.8.14/yul.html

解题思路

由于需要考虑到合约的大小,所以不能用solidity来编写
可以使用yul来编写,参考官方文档的例子
https://docs.soliditylang.org/en/v0.8.14/yul.html
新建18MagicNum.yul

object "magic42" {
    code {
        //部署
        datacopy(0, dataoffset("runtime"), datasize("runtime"))
        return(0, datasize("runtime"))
    }
    object "runtime" {
        code {
            mstore(0, 0x2a)  //设置mem[0..32]=0x2a
            return(0, 0x20)  //返回mem[0..32]
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

然后用命令编译:
solc --strict-assembly --optimize contracts/18MagicNum.yul
得到

Binary representation:
600a80600c6000396000f3fe602a60005260206000f3
Enter fullscreen mode Exit fullscreen mode

如果使用在线的remix,也可以在线用yul编译,再复制Bytecode->object
如图:
Image description

这串是合约部署bytecode,实际部署完会更小
线上过关可以在chrome控制台执行

bytecode = '600a80600c6000396000f3fe602a60005260206000f3'
txn = await web3.eth.sendTransaction({from: player, data: bytecode})
await contract.setSolver(txn.contractAddress)
Enter fullscreen mode Exit fullscreen mode

hardhat里
contracts/18MagicNumRun.sol

  function check(address _runAddress,uint codeszie) external payable {
    require(ILevel(_runAddress).whatIsTheMeaningOfLife() == 42, "not equal 42");

    uint256 size;
    assembly {
      size := extcodesize(_runAddress)
    }

    require(size <= codeszie,"bigger codeszie ");
  } 
Enter fullscreen mode Exit fullscreen mode

test/18MagicNum.js

describe("18MagicNumb", function () {
  let player, levelOwner, levelContract, runContract;
  it("setup", async function () {
    [player, levelOwner] = await ethers.getSigners();
    const interface = ["function whatIsTheMeaningOfLife() returns (uint)"];
    //使用:得到这个solc --strict-assembly --optimize contracts/18MagicNumber.yul
    //也可以使用remix在线编译,再复制Bytecode
    const bytecode = "600a80600c6000396000f3fe602a60005260206000f3";
    const Contract = new ethers.ContractFactory(
      interface,
      bytecode,
      levelOwner
    );
    levelContract = await Contract.deploy();
    await levelContract.deployed();

    runContract = await tools.deployContract("MagicNumRun", player);
  });

  it("attacks", async function () {});

  it("check", async function () {
    //检查通过条件
    await runContract.check(levelContract.address, 10);
  });
});
Enter fullscreen mode Exit fullscreen mode

Top comments (0)