Серия Этернаут — уровень 18 (MagicNum)


УРОВЕНЬ 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;
  }

  /*
    ____________/\_______/\\\\_____        
     __________/\\_____/\///////\___       
      ________/\/\____///______//\__      
       ______/\//\______________/\/___     
        ____/\/__/\___________/\//_____    
         __/\\\\\\\\_____/\//________   
          _///////////\//____/\/___________  
           ___________/\_____/\\\\\\\_ 
            ___________///_____///////////////__
  */
}
Войдите в полноэкранный режим Выход из полноэкранного режима

Требования к прохождению

Напишите контракт и задайте его решателю
Требования к контракту.
1. вызовите метод whatIsTheMeaningOfLife() контракта, чтобы вернуть ответ, представляющий смысл жизни (sci-fi stalk номер 42)
2. байткод контракта должен быть достаточно маленьким, extcodesize <=10

Ключевые моменты

1. понимать кодировку юл (или опкоды для ethereum)
https://docs.soliditylang.org/en/v0.8.14/yul.html

Идеи решения проблем

Не может писать в солиде, так как ему необходимо учитывать размер контракта
Вы можете использовать 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]
        }
    }
}
Войдите в полноэкранный режим Выход из полноэкранного режима

Затем скомпилируйте с помощью команды
solc —strict-assembly —optimize contracts/18MagicNum.yul
чтобы получить

Binary representation:
600a80600c6000396000f3fe602a60005260206000f3
Войдите в полноэкранный режим Выход из полноэкранного режима

Если вы используете онлайн-ремикс, вы также можете скомпилировать его онлайн с помощью yul, затем скопировать Bytecode->object
Как показано на изображении.

Эта строка является байткодом развертывания контракта, фактическое развертывание будет меньше
Онлайн-пропуск можно выполнить в консоли chrome

bytecode = '600a80600c6000396000f3fe602a60005260206000f3'
txn = await web3.eth.sendTransaction({from: player, data: bytecode})
await contract.setSolver(txn.contractAddress)
Войдите в полноэкранный режим Выход из полноэкранного режима

В каске
контракты/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 ");
  } 
Войдите в полноэкранный режим Выход из полноэкранного режима

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);
  });
});
Войдите в полноэкранный режим Выход из полноэкранного режима

Оцените статью
Procodings.ru
Добавить комментарий