Ethernaut Challenge: Level 18 Magic Number. (Solution)
Magic Number
Task: Create a solver contract that response to “whatIsTheMeaningOfLife()” with the right number (42). Easy right??
However, there’s some constraint in this challenge. The contract code should be very small, about 10 opcode at most.
Investigation
First I recommend you to read more about opcode and bytecode here https://www.ethervm.io/
We first create a simple solution first, and here’s the code.
Here’s the debug to trace the executeion step used to call whatIsTheMeaningOfLife() in the first solution contract.
vm trace step: 53
execution step: 53
So we changed the contract to use assembly.
After we changed to use assembly, we could reduce half execution step.
vm trace step: 29
execution step: 29
We then spectate the opcode used in second solution and found this one in remix debug.
// FROM REMIX DEBUGGER
076 PUSH1 2a |
078 PUSH1 00 |- MSTORE(0x00, 0x2a)
080 MSTORE |
081 PUSH1 20 |
083 PUSH1 00 |- RETURN(0x00,0x20)
085 RETURN |
These are the one we needed!!!
// BYTECODE - OPCODE : From ethervm.io
0x60 PUSH1
0x52 MSTORE
0xF3 RETURN
Convert opcode above into bytecode
0x602a - 2 (PUSH1 2a)
0x6000 - 2 (PUSH1 00)
0x52 - 1 (MSTORE)
0x6020 - 2 (PUSH1 0x20)
0x6000 - 2 (PUSH1 0x00)
0xF3 - 1 (RETURN)
======== 10 bytes => 0x0a
32 - 10 bytes = 22 bytes => 0x16
========
0x602a60005260206000f3 with 22 bytes prepadding
So we final the solution by creating the contract that store the solution
We can test our contract after deploy be running command in remix-console
web3.eth.call({
to: 'YOUR_SOLVER_CONTRACT_ADDRESS',
data: '0x650500c1' // abi encoded for "whatIsTheMeaningOfLife()"
})
and this is the result you’d get
0x000000000000000000000000000000000000000000000000000000000000002a
All Done! Thanks for reading :)