Magic Number
Contents
this challenge is about calling the setSolver function and we give it an address of a contract that responds to whatIsTheMeaningOfLife() with the number 42
Challenge Info
- Platform: Ethernaut
- Challenge: Magic Number
- Category: Blockchain
| |
the plot is that this contract should be 10 bytes at most, if we create the contract using the normal way it will be way larger than 10 bytes
when we do an external call to a smart contract, we provide the function signature of the function we want to execute in this call, now someone may misunderstand the process and think that the evm will first look at this function signature and then look at it in the contract code stored in the blockchain and start executing the specific code block, but instead what the evm does is that it starts executing the contract we are calling from the first ever line, and when using the solidity compiler this line will include a jump instruction that redirects the evm into the right code block for the right function, so whatever the function we are calling in the contract, the evm will always start from offset 0, so if we deploy a custom bytecode without using the compiler, when the MagicNum contract calls that specific function, the evm will start executing our bytecode
our goal will be to deploy a bytecode that has only one job: return 42 to the caller contract
in order to do that we should store 42 in the memory and then return it, this can be done through the mstore opcode followed by a return instruction, in detail it will be:
mstore(0, 42)— store 42 in memory at offset 0- but before that we pass the opcode arguments into the stack using
push1 2aandpush1 00 - after we store it, we push the values that
returnwill use: we return 32 bytes from memory starting from offset 0, sopush1 20followed bypush1 00
the run time bytecode:
push1 2a->602apush1 00->6000mstore->52push1 20->6020push1 00->6000return->f3
so 602a60005260206000f3
but we still need the constructor logic that gets executed when the contract gets deployed and returns the run time bytecode into memory to get stored into the blockchain:
push10 0x602a60005260206000f3push1 00mstorepush1 0apush1 16return
this will execute return(22, 32) and the reason we did that is because when the bytes memory was stored it gets left padded with zeros so in memory slot 0 we have 22 zeros followed by 602a60005260206000f3, and we want to return exactly the run time bytecode, so we start from offset 22
the final bytecode we deploy is 69602a60005260206000f3600052600a6016f3
now all left is deploying this bytecode using another smart contract:
| |
gg the challenge is solved