SummaryThis challenge reminds the weird workings of solidity in assembly. Here the challenge contract is supposed to call the setup contract but the challenge contract executes only one opcode at a time and further more. One of the interesting challenges that i have played.
Intro to challengeThis is evmvm contract. The contract is not as complex as it looks. The stack variable works exactly like a stack. The
enterTheMetametaverse function takes opcode and bytes32 argument which is used only when
necessary for example in a calldata operations.
To understand this better, let's say we want to add two values. we pass 0x01 as argument in the function. The function pops the top 2 values from the stack variable and adds it and pushes the result back into the stack. You may wonder there's nothing in the stack to pop and we don't have explicit
calling ability. We'll discuss about this in later part.
setup contract initializes the
evmvm contract in a immutable variable. So,
there is no way to change the address the only way is to make the
evmvm contract call the
setup contract to solve. To call another contract we can use
delegate call opcode.
This was my approach until i met this man and i realized that argsOffset is
location from memory though we are allowed to use one opcode at a time the memory gets reset. If the
argsOffset is 0 & argsLength is 0 we can call the fallback function because the function
signature of fallback is
But this executes in the context of the caller contract not the
evmvm contract. There is
something different when it comes to delegate call.
evmvm contract calls the fallback function using delegate call but msg.sender is still
evmvm contract interesting!. So, that's it?
Make a contract which has fallback calling the
evmvm contract's solve and push the values
into the stack and call the delegate call opcode. Yes, except one.
We push four 0's first then address and then gas. So, that stack top value is gas and it gets poped as first argument and so on. But that's not the case. Click me! So, we need to push in the reverse order. The contract should look something like this. We call the attack function which loads the
evmvm contract to know the
metametaverse contract address and calls the gas opcode and then caller opcode to delegate the
function call and followed by self balance which is 0 and finally delegate call opcode which in turn calls
fallback function and solved.
My way of pushing values into the stack when i thought of using call opcode was to first call
callvalue opcode four times to push 0 into the stack. Then I create a contract and fund the
contract with 36 wei and send the balance to
evmvm contract by destroying it. Then call
self balance opcode to push 36 into the stack and duplicate it. I use the duplicated value to
access the 2nd argument using calldataload opcode by doing that i can load the contract address and swap the
stack to bring back 36 again to the top of the stack so that i can repeat the part again and push the gas
value into the stack. Confusing! LOL