EVM Opcode execution for calling external contracts - The PUZZLE
About:-
There is a puzzle ByteCode given and the target is, it should work with normal stop execution not a revert. The puzzle is given in IMAGE : The Puzzle ByteCode and sequence of Opcode is given in IMAGE : The Puzzle Opcode
Understanding The Puzzle :-
Block 1: Copy the whole calldata input in memory
The CALLDATACOPY is like a "KIND OF" MLOAD that take the data to be stored in the memory directly from the calldata location. Those instructions are saying: take all the data from calldata and copy it to the memory starting from the memory position 0.
Block 2: Create a new contract, its code will be the equal to the calldata data
These opcodes are just saying: create a new contract transferring 0 wei with the transaction. The code to deploy the new contract will be the one in memory that goes from offset 0 to CALLDATASIZE bytes.
So connecting Block 1 and Block 2 the result is this: use the calldata data in input to use it as the code to deploy a new contract.
Block 3: Prepare and make the CALL
All the opcodes before CALL are just preparing all the inputs needed to execute the call. After the preparation, we will execute this CALL(gas=ALL_THE_GAS_AVAILABLE, address=ADDRESS_FROM_CREATE, value: 0, argsOffset=0, argsSize=0, retOffset=0, retSize=0)
Basically, we are just calling the deployed contract with all the gas still available without any calldata arguments and without reading anything from the returned value.
After the execution of CALL the stack will have only one value. 0 if it has reverted, 1 otherwise.
Block 4: Final execution
Before the PUSH1 00 the stack has only the execution result of the CALL.
Recommended by LinkedIn
All these op codes are saying: if the CALL has reverted, jump to 1B otherwise keep going with the flow and execute REVERT (something that we don't want!).
The solution of the challenge is to not execute the REVERT opcode in position 1A is to deploy a contract that, when called, will revert. Reverting CALL will push to the stack the value 0 that will make the EQ push to the stack a 1.
By doing so, the JUMPI opcode will jump to the 1B position!
The Solutions -
The question is, which is the CALLDATA to pass to the transaction to make this?
We can make the deployed contract to just revert as soon as possible by having just the REVERT opcode.
The calldata that we need to pass will be as follows :-
// store in memory the REVERT opcode as the only "code" of the contract
PUSH1 FD
PUSH1 00
MSTORE8
// make the constructor return the stored runtime code
PUSH1 01
PUSH1 00
RETURN
Translated in bytecode, our calldata and solution to the puzzle will be 0x60FD60005360016000F3
Note: I was not able to solve it initially after after understanding the opcode in details and spending lots of time was able to solve it.
HAPPY CODING !!