Ethernaut Solutions: Challenge 18 Magic Number

Zvinodashe Mupambirei
2 min readJun 10, 2022

Challenge 18 on Ethernaut requires us to create a contract Solver that always returns the value 42 using minimal opcodes (10 or less in this case).

Bytecode that is deployed is in two parts Initialization Code + Runtime Code. It is the job of the initialization code to return the runtime code and we want our Runtime Code to be 10 or less bytes. The code is simple it just returns 42.

For Runtime Code/Contract Code we need to return a uint256 value 42 from memory having stored such a value onto memory. The two key parts of runtime code is store in memory(MSTORE OPCODE 52) and return from memory (RETURN OPCODE f3). MSTORE needs position in memory and value from the stack, so we need PUSH1 OPCODE 60 to add onto the stack.

// Runtime Code OPCODES
60 2a // Push value 42 (0x2a) onto stack
60 00 // Push value 0x00 index 0 position memory onto stack
52 // mstore(from memory location 0x00, value) store value 0x2a
60 20 // Push 0x20 size of uint256 - 32 bytes
60 00 // Push value 0x00 memory position to return value from
f3 // return(from memory location position 0x00, size 32bytes)
// Contract Code Bytecode Output
602a60005260206000f3 // 10 bytes

For the Initialization Code/ Creation Code we need to copy the 10 bytes Runtime Code to memory making use of (CODECOPY OPCODE 39) which takes destination of the runtime code, location of runtime code in relation to entire code, and size of runtime code (10 bytes = 0xa) and and return them

60 0a   // Push value 0xa size 10 bytes of runtime code onto stack
60 0c // posRel location bytes from where runtime code starts
60 00 // Push value 0x00 location of the code in memory position
39 // codecopy(location memory position 0x00, posRel, size)
60 a0 // Push 0xa size of runtime code - 10 bytes
60 00 // Push value 0x00 memory location
f3 // return(memory location 0x00, size 10 bytes 0xa)
// posRel location = 0x0c = 12 bytes(count above bytes) size of the initialization code from where the contract code starts for codecopy// Creation Code Bytecode Output
600a600c600039600a6000f3
// Combined Bytecode
0x600a600c600039600a6000f3602a60005260206000f3

Contract Creation involves sending …”data” == contract bytecode(initialization+runtime) to the blockchain via a transaction that does not have a “to” address.

const bytecode = "0x600a600c600039600a6000f3602a60005260206000f3"
const tx = await web3.eth.sendTransaction({
from: player,
data: bytecode
})
const solverAddress = tx.contractAddress// Call instance with our Solver Address
await contract.setSolver(solverAddress);

To connect with me on LinkedIn Click Here

To connect with me on Twitter Click Here

--

--